Color code output of nm and objdump
diff --git a/lib/ChangeLog b/lib/ChangeLog
index a6fec30..47e831e 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,10 @@
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am (libeu_a_SOURCES): Add color.c.
+	* system.h: Declare color_argp.  Define color_enum.  Declare
+	color_* variables.
+	* color.c: New file.
+
 2011-10-02  Ulrich Drepper  <drepper@gmail.com>
 
 	* system.h: Declare __cxa_demangle.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 50d55c5..4ea1436 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 1996-2010 Red Hat, Inc.
+## Copyright (C) 1996-2011 Red Hat, Inc.
 ## This file is part of Red Hat elfutils.
 ##
 ## Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -30,8 +30,9 @@
 
 noinst_LIBRARIES = libeu.a
 
-libeu_a_SOURCES = xstrndup.c xmalloc.c next_prime.c \
-		  crc32.c crc32_file.c md5.c sha1.c
+libeu_a_SOURCES = xstrdup.c xstrndup.c xmalloc.c next_prime.c \
+		  crc32.c crc32_file.c md5.c sha1.c \
+		  color.c
 
 noinst_HEADERS = fixedsizehash.h system.h dynamicsizehash.h list.h md5.h \
 		 sha1.h eu-config.h
diff --git a/lib/color.c b/lib/color.c
new file mode 100644
index 0000000..ff82448
--- /dev/null
+++ b/lib/color.c
@@ -0,0 +1,227 @@
+/* Handling of color output.
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2011.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <error.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Option values.  */
+#define OPT_COLOR 0x100100
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL,
+    N_("colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 },
+
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Parser data structure.  */
+const struct argp color_argp =
+  {
+    options, parse_opt, NULL, NULL, NULL, NULL, NULL
+  };
+
+/* Coloring mode.  */
+enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+char *color_address = "";
+char *color_bytes = "";
+char *color_mnemonic = "";
+char *color_operand = NULL;
+char *color_operand1 = "";
+char *color_operand2 = "";
+char *color_operand3 = "";
+char *color_label = "";
+char *color_undef = "";
+char *color_undef_tls = "";
+char *color_undef_weak = "";
+char *color_symbol = "";
+char *color_tls = "";
+char *color_weak = "";
+
+const char color_off[] = "\e[0m";
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case OPT_COLOR:
+      if (arg == NULL)
+	color_mode = color_always;
+      else
+	{
+	  static const struct
+	  {
+	    const char str[7];
+	    enum color_enum mode;
+	  } values[] =
+	      {
+		{ "always", color_always },
+		{ "yes", color_always },
+		{ "force", color_always },
+		{ "never", color_never },
+		{ "no", color_never },
+		{ "none", color_never },
+		{ "auto", color_auto },
+		{ "tty", color_auto },
+		{ "if-tty", color_auto }
+	      };
+	  const int nvalues = sizeof (values) / sizeof (values[0]);
+	  int i;
+	  for (i = 0; i < nvalues; ++i)
+	    if (strcmp (arg, values[i].str) == 0)
+	      {
+		color_mode = values[i].mode;
+		if (color_mode == color_auto)
+		  color_mode
+		    = isatty (STDOUT_FILENO) ? color_always : color_never;
+		break;
+	      }
+	  if (i == nvalues)
+	    {
+	      error (0, 0, dgettext ("elfutils", "\
+%s: invalid argument '%s' for '--color'\n\
+valid arguments are:\n\
+  - 'always', 'yes', 'force'\n\
+  - 'never', 'no', 'none'\n\
+  - 'auto', 'tty', 'if-tty'\n"),
+		     program_invocation_short_name, arg);
+	      argp_help (&color_argp, stderr, ARGP_HELP_SEE,
+			 program_invocation_short_name);
+	      exit (EXIT_FAILURE);
+	    }
+	}
+
+      if (color_mode == color_always)
+	{
+	  const char *env = getenv ("ELFUTILS_COLORS");
+	  if (env != NULL)
+	    {
+	      do
+		{
+		  const char *start = env;
+		  while (*env != '=' && *env != '\0')
+		    ++env;
+		  if (*env == '=' && env != start)
+		    {
+		      size_t name_len = env - start;
+		      const char *val = ++env;
+		      env = strchrnul (env, ':');
+		      if (val != env)
+			{
+			  static const struct
+			  {
+			    unsigned char len;
+			    const char name[sizeof (char *) - 1];
+			    char **varp;
+			  } known[] =
+			      {
+#define E(name, var) { sizeof (#name) - 1, #name,  &color_##var }
+				E (a, address),
+				E (b, bytes),
+				E (m, mnemonic),
+				E (o, operand),
+				E (o1, operand1),
+				E (o1, operand2),
+				E (o1, operand3),
+				E (l, label),
+				E (u, undef),
+				E (ut, undef_tls),
+				E (uw, undef_weak),
+				E (sy, symbol),
+				E (st, tls),
+				E (sw, weak),
+			      };
+			  const size_t nknown = (sizeof (known)
+						 / sizeof (known[0]));
+
+			  for (size_t i = 0; i < nknown; ++i)
+			    if (name_len == known[i].len
+				&& memcmp (start, known[i].name, name_len) == 0)
+			      {
+				if (asprintf (known[i].varp, "\e[%.*sm",
+					      (int) (env - val), val) < 0)
+				  error (EXIT_FAILURE, errno,
+					 gettext ("cannot allocate memory"));
+				break;
+			      }
+			}
+		      if (*env == ':')
+			++env;
+		    }
+		}
+	      while (*env != '\0');
+
+	      if (color_operand != NULL)
+		{
+		  if (color_operand1[0] == '\0')
+		    color_operand1 = color_operand;
+		  if (color_operand2[0] == '\0')
+		    color_operand2 = color_operand;
+		  if (color_operand3[0] == '\0')
+		    color_operand3 = color_operand;
+		}
+	    }
+#if 0
+	  else
+	    {
+	      // XXX Just for testing.
+	      color_address = xstrdup ("\e[38;5;166;1m");
+	      color_bytes = xstrdup ("\e[38;5;141m");
+	      color_mnemonic = xstrdup ("\e[38;5;202;1m");
+	      color_operand1 = xstrdup ("\e[38;5;220m");
+	      color_operand2 = xstrdup ("\e[38;5;48m");
+	      color_operand3 = xstrdup ("\e[38;5;112m");
+	      color_label = xstrdup ("\e[38;5;21m");
+	    }
+#endif
+	}
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
diff --git a/lib/system.h b/lib/system.h
index 8e32c3a..3f9f0af 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -49,6 +49,7 @@
 #ifndef LIB_SYSTEM_H
 #define LIB_SYSTEM_H	1
 
+#include <argp.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <endian.h>
@@ -107,4 +108,37 @@
 extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
 			     size_t *length, int *status);
 
+
+
+/* Color handling.  */
+
+/* Command line parser.  */
+extern const struct argp color_argp;
+
+/* Coloring mode.  */
+enum color_enum
+  {
+    color_never = 0,
+    color_always,
+    color_auto
+  } __attribute__ ((packed));
+extern enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+extern char *color_address;
+extern char *color_bytes;
+extern char *color_mnemonic;
+extern char *color_operand1;
+extern char *color_operand2;
+extern char *color_operand3;
+extern char *color_label;
+extern char *color_undef;
+extern char *color_undef_tls;
+extern char *color_undef_weak;
+extern char *color_symbol;
+extern char *color_tls;
+extern char *color_weak;
+
+extern const char color_off[];
+
 #endif /* system.h */