Blame lib/color.c

Packit 032894
/* Handling of color output.
Packit 032894
   Copyright (C) 2011 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2011.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <argp.h>
Packit 032894
#include <libintl.h>
Packit 032894
#include <stdlib.h>
Packit 032894
#include <string.h>
Packit 032894
#include <unistd.h>
Packit 032894
#include "system.h"
Packit 032894
#include "libeu.h"
Packit 032894
#include "color.h"
Packit 032894
Packit 032894
/* Prototype for option handler.  */
Packit 032894
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit 032894
Packit 032894
/* Option values.  */
Packit 032894
#define OPT_COLOR 0x100100
Packit 032894
Packit 032894
/* Definitions of arguments for argp functions.  */
Packit 032894
static const struct argp_option options[] =
Packit 032894
{
Packit 032894
  { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL,
Packit 032894
    N_("colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 },
Packit 032894
Packit 032894
  { NULL, 0, NULL, 0, NULL, 0 }
Packit 032894
};
Packit 032894
Packit 032894
/* Parser data structure.  */
Packit 032894
const struct argp color_argp =
Packit 032894
  {
Packit 032894
    options, parse_opt, NULL, NULL, NULL, NULL, NULL
Packit 032894
  };
Packit 032894
Packit 032894
/* Coloring mode.  */
Packit 032894
enum color_enum color_mode;
Packit 032894
Packit 032894
/* Colors to use for the various components.  */
Packit 032894
char *color_address = "";
Packit 032894
char *color_bytes = "";
Packit 032894
char *color_mnemonic = "";
Packit 032894
char *color_operand = NULL;
Packit 032894
char *color_operand1 = "";
Packit 032894
char *color_operand2 = "";
Packit 032894
char *color_operand3 = "";
Packit 032894
char *color_operand4 = "";
Packit 032894
char *color_operand5 = "";
Packit 032894
char *color_label = "";
Packit 032894
char *color_undef = "";
Packit 032894
char *color_undef_tls = "";
Packit 032894
char *color_undef_weak = "";
Packit 032894
char *color_symbol = "";
Packit 032894
char *color_tls = "";
Packit 032894
char *color_weak = "";
Packit 032894
Packit 032894
const char color_off[] = "\e[0m";
Packit 032894
Packit 032894
Packit 032894
/* Handle program arguments.  */
Packit 032894
static error_t
Packit 032894
parse_opt (int key, char *arg,
Packit 032894
	   struct argp_state *state __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  switch (key)
Packit 032894
    {
Packit 032894
    case OPT_COLOR:
Packit 032894
      if (arg == NULL)
Packit 032894
	color_mode = color_always;
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  static const struct
Packit 032894
	  {
Packit 032894
	    const char str[7];
Packit 032894
	    enum color_enum mode;
Packit 032894
	  } values[] =
Packit 032894
	      {
Packit 032894
		{ "always", color_always },
Packit 032894
		{ "yes", color_always },
Packit 032894
		{ "force", color_always },
Packit 032894
		{ "never", color_never },
Packit 032894
		{ "no", color_never },
Packit 032894
		{ "none", color_never },
Packit 032894
		{ "auto", color_auto },
Packit 032894
		{ "tty", color_auto },
Packit 032894
		{ "if-tty", color_auto }
Packit 032894
	      };
Packit 032894
	  const int nvalues = sizeof (values) / sizeof (values[0]);
Packit 032894
	  int i;
Packit 032894
	  for (i = 0; i < nvalues; ++i)
Packit 032894
	    if (strcmp (arg, values[i].str) == 0)
Packit 032894
	      {
Packit 032894
		color_mode = values[i].mode;
Packit 032894
		if (color_mode == color_auto)
Packit 032894
		  color_mode
Packit 032894
		    = isatty (STDOUT_FILENO) ? color_always : color_never;
Packit 032894
		break;
Packit 032894
	      }
Packit 032894
	  if (i == nvalues)
Packit 032894
	    {
Packit 032894
	      error (0, 0, dgettext ("elfutils", "\
Packit 032894
%s: invalid argument '%s' for '--color'\n\
Packit 032894
valid arguments are:\n\
Packit 032894
  - 'always', 'yes', 'force'\n\
Packit 032894
  - 'never', 'no', 'none'\n\
Packit 032894
  - 'auto', 'tty', 'if-tty'\n"),
Packit 032894
		     program_invocation_short_name, arg);
Packit 032894
	      argp_help (&color_argp, stderr, ARGP_HELP_SEE,
Packit 032894
			 (char *) program_invocation_short_name);
Packit 032894
	      exit (EXIT_FAILURE);
Packit 032894
	    }
Packit 032894
	}
Packit 032894
Packit 032894
      if (color_mode == color_always)
Packit 032894
	{
Packit 032894
	  const char *env = getenv ("ELFUTILS_COLORS");
Packit 032894
	  if (env != NULL)
Packit 032894
	    {
Packit 032894
	      do
Packit 032894
		{
Packit 032894
		  const char *start = env;
Packit 032894
		  while (*env != '=' && *env != '\0')
Packit 032894
		    ++env;
Packit 032894
		  if (*env == '=' && env != start)
Packit 032894
		    {
Packit 032894
		      size_t name_len = env - start;
Packit 032894
		      const char *val = ++env;
Packit 032894
		      env = strchrnul (env, ':');
Packit 032894
		      if (val != env)
Packit 032894
			{
Packit 032894
			  static const struct
Packit 032894
			  {
Packit 032894
			    unsigned char len;
Packit 032894
			    const char name[sizeof (char *) - 1];
Packit 032894
			    char **varp;
Packit 032894
			  } known[] =
Packit 032894
			      {
Packit 032894
#define E(name, var) { sizeof (#name) - 1, #name,  &color_##var }
Packit 032894
				E (a, address),
Packit 032894
				E (b, bytes),
Packit 032894
				E (m, mnemonic),
Packit 032894
				E (o, operand),
Packit 032894
				E (o1, operand1),
Packit 032894
				E (o2, operand2),
Packit 032894
				E (o3, operand3),
Packit 032894
				E (o4, operand4),
Packit 032894
				E (o5, operand5),
Packit 032894
				E (l, label),
Packit 032894
				E (u, undef),
Packit 032894
				E (ut, undef_tls),
Packit 032894
				E (uw, undef_weak),
Packit 032894
				E (sy, symbol),
Packit 032894
				E (st, tls),
Packit 032894
				E (sw, weak),
Packit 032894
			      };
Packit 032894
			  const size_t nknown = (sizeof (known)
Packit 032894
						 / sizeof (known[0]));
Packit 032894
Packit 032894
			  for (size_t i = 0; i < nknown; ++i)
Packit 032894
			    if (name_len == known[i].len
Packit 032894
				&& memcmp (start, known[i].name, name_len) == 0)
Packit 032894
			      {
Packit 032894
				if (asprintf (known[i].varp, "\e[%.*sm",
Packit 032894
					      (int) (env - val), val) < 0)
Packit 032894
				  error (EXIT_FAILURE, errno,
Packit 032894
					 gettext ("cannot allocate memory"));
Packit 032894
				break;
Packit 032894
			      }
Packit 032894
			}
Packit 032894
		      if (*env == ':')
Packit 032894
			++env;
Packit 032894
		    }
Packit 032894
		}
Packit 032894
	      while (*env != '\0');
Packit 032894
Packit 032894
	      if (color_operand != NULL)
Packit 032894
		{
Packit 032894
		  if (color_operand1[0] == '\0')
Packit 032894
		    color_operand1 = color_operand;
Packit 032894
		  if (color_operand2[0] == '\0')
Packit 032894
		    color_operand2 = color_operand;
Packit 032894
		  if (color_operand3[0] == '\0')
Packit 032894
		    color_operand3 = color_operand;
Packit 032894
		  if (color_operand4[0] == '\0')
Packit 032894
		    color_operand4 = color_operand;
Packit 032894
		  if (color_operand5[0] == '\0')
Packit 032894
		    color_operand5 = color_operand;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
#if 0
Packit 032894
	  else
Packit 032894
	    {
Packit 032894
	      // XXX Just for testing.
Packit 032894
	      color_address = xstrdup ("\e[38;5;166;1m");
Packit 032894
	      color_bytes = xstrdup ("\e[38;5;141m");
Packit 032894
	      color_mnemonic = xstrdup ("\e[38;5;202;1m");
Packit 032894
	      color_operand1 = xstrdup ("\e[38;5;220m");
Packit 032894
	      color_operand2 = xstrdup ("\e[38;5;48m");
Packit 032894
	      color_operand = xstrdup ("\e[38;5;112m");
Packit 032894
	      color_label = xstrdup ("\e[38;5;21m");
Packit 032894
	    }
Packit 032894
#endif
Packit 032894
	}
Packit 032894
      break;
Packit 032894
Packit 032894
    default:
Packit 032894
      return ARGP_ERR_UNKNOWN;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}