(root)/
util-linux-2.39/
lib/
color-names.c
       1  /*
       2   * No copyright is claimed.  This code is in the public domain; do with
       3   * it what you wish.
       4   *
       5   * Written by Karel Zak <kzak@redhat.com>
       6   */
       7  #include "c.h"
       8  #include "color-names.h"
       9  
      10  #include <ctype.h>
      11  
      12  struct ul_color_name {
      13  	const char *name;
      14  	const char *seq;
      15  };
      16  
      17  /*
      18   * qsort/bsearch buddy
      19   */
      20  static int cmp_color_name(const void *a0, const void *b0)
      21  {
      22  	const struct ul_color_name
      23  		*a = (const struct ul_color_name *) a0,
      24  		*b = (const struct ul_color_name *) b0;
      25  	return strcmp(a->name, b->name);
      26  }
      27  
      28  /*
      29   * Maintains human readable color names
      30   */
      31  const char *color_sequence_from_colorname(const char *str)
      32  {
      33  	static const struct ul_color_name basic_schemes[] = {
      34  		{ "black",	UL_COLOR_BLACK           },
      35  		{ "blink",      UL_COLOR_BLINK           },
      36  		{ "blue",	UL_COLOR_BLUE            },
      37  		{ "bold",       UL_COLOR_BOLD		 },
      38  		{ "brown",	UL_COLOR_BROWN           },
      39  		{ "cyan",	UL_COLOR_CYAN            },
      40  		{ "darkgray",	UL_COLOR_DARK_GRAY       },
      41  		{ "gray",	UL_COLOR_GRAY            },
      42  		{ "green",	UL_COLOR_GREEN           },
      43  		{ "halfbright", UL_COLOR_HALFBRIGHT	 },
      44  		{ "lightblue",	UL_COLOR_BOLD_BLUE       },
      45  		{ "lightcyan",	UL_COLOR_BOLD_CYAN       },
      46  		{ "lightgray,",	UL_COLOR_GRAY            },
      47  		{ "lightgreen", UL_COLOR_BOLD_GREEN      },
      48  		{ "lightmagenta", UL_COLOR_BOLD_MAGENTA  },
      49  		{ "lightred",	UL_COLOR_BOLD_RED        },
      50  		{ "magenta",	UL_COLOR_MAGENTA         },
      51  		{ "red",	UL_COLOR_RED             },
      52  		{ "reset",      UL_COLOR_RESET,          },
      53  		{ "reverse",    UL_COLOR_REVERSE         },
      54  		{ "yellow",	UL_COLOR_BOLD_YELLOW     },
      55  		{ "white",      UL_COLOR_WHITE           }
      56  	};
      57  	struct ul_color_name key = { .name = str }, *res;
      58  
      59  	if (!str)
      60  		return NULL;
      61  
      62  	res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes),
      63  				sizeof(struct ul_color_name),
      64  				cmp_color_name);
      65  	return res ? res->seq : NULL;
      66  }
      67  
      68  
      69  int color_is_sequence(const char *color)
      70  {
      71  	if (color && *color == 0x1B) {
      72  		size_t len = strlen(color);
      73  
      74  		if (len >= 4 &&
      75  		    *(color + 1) == '[' &&
      76  		    isdigit(*(color + 2)) &&
      77  		    *(color + len - 1) == 'm')
      78  		return 1;
      79  	}
      80  
      81  	return 0;
      82  }
      83  
      84  /* canonicalize sequence */
      85  static int __color_canonicalize(const char *str, char **seq)
      86  {
      87  	char *in, *out;
      88  	int len;
      89  
      90  	if (!str)
      91  		return -EINVAL;
      92  
      93  	*seq = NULL;
      94  
      95  	/* convert color names like "red" to the real sequence */
      96  	if (*str != '\\' && isalpha(*str)) {
      97  		const char *s = color_sequence_from_colorname(str);
      98  		*seq = strdup(s ? s : str);
      99  
     100  		return *seq ? 0 : -ENOMEM;
     101  	}
     102  
     103  	/* convert xx;yy sequences to "\033[xx;yy" */
     104  	if ((len = asprintf(seq, "\033[%sm", str)) < 1)
     105  		return -ENOMEM;
     106  
     107  	for (in = *seq, out = *seq; in && *in; in++) {
     108  		if (*in != '\\') {
     109  			*out++ = *in;
     110  			continue;
     111  		}
     112  		switch(*(in + 1)) {
     113  		case 'a':
     114  			*out++ = '\a';	/* Bell */
     115  			break;
     116  		case 'b':
     117  			*out++ = '\b';	/* Backspace */
     118  			break;
     119  		case 'e':
     120  			*out++ = '\033';	/* Escape */
     121  			break;
     122  		case 'f':
     123  			*out++ = '\f';	/* Form Feed */
     124  			break;
     125  		case 'n':
     126  			*out++ = '\n';	/* Newline */
     127  			break;
     128  		case 'r':
     129  			*out++ = '\r';	/* Carriage Return */
     130  			break;
     131  		case 't':
     132  			*out++ = '\t';	/* Tab */
     133  			break;
     134  		case 'v':
     135  			*out++ = '\v';	/* Vertical Tab */
     136  			break;
     137  		case '\\':
     138  			*out++ = '\\';	/* Backslash */
     139  			break;
     140  		case '_':
     141  			*out++ = ' ';	/* Space */
     142  			break;
     143  		case '#':
     144  			*out++ = '#';	/* Hash mark */
     145  			break;
     146  		case '?':
     147  			*out++ = '?';	/* Question mark */
     148  			break;
     149  		default:
     150  			*out++ = *in;
     151  			*out++ = *(in + 1);
     152  			break;
     153  		}
     154  		in++;
     155  	}
     156  
     157  	if (out) {
     158  		assert ((out - *seq) <= len);
     159  		*out = '\0';
     160  	}
     161  
     162  	return 0;
     163  }
     164  
     165  char *color_get_sequence(const char *color)
     166  {
     167  	char *seq = NULL;
     168  	int rc = __color_canonicalize(color, &seq);
     169  
     170  	return rc ? NULL : seq;
     171  }