+ unsigned int index;
+ char *color, *p, *str;
+
+ str = xstrdup (color_string);
+ STACK_VAR (str);
+
+ for (index = 0, color = str; *color; index++, color = p)
+ {
+ char *ch, *sep;
+
+ p = NULL;
+ if ((sep = strchr (color, COLOR_SEP_CHAR)))
+ {
+ *sep = '\0';
+ p = sep + 1;
+ }
+ else
+ p = color + strlen (color);
+ assert (p != NULL);
+
+ for (ch = color; *ch; ch++)
+ if (!isalpha (*ch))
+ vfprintf_fail (formats[FMT_COLOR], tables[index].desc, color, "cannot be made of non-alphabetic characters");
+
+ for (ch = color + 1; *ch; ch++)
+ if (!islower (*ch))
+ vfprintf_fail (formats[FMT_COLOR], tables[index].desc, color, "cannot be in mixed lower/upper case");
+
+ if (streq (color, "None"))
+ vfprintf_fail (formats[FMT_COLOR], tables[index].desc, color, "cannot be bold");
+
+ if (isupper (*color))
+ {
+ switch (index)
+ {
+ case FOREGROUND:
+ snprintf (attr + strlen (attr), 3, "1;");
+ break;
+ case BACKGROUND:
+ vfprintf_fail (formats[FMT_COLOR], tables[BACKGROUND].desc, color, "cannot be bold");
+ default: /* never reached */
+ ABORT_TRACE ();
+ }
+ }
+
+ color_names[index] = xcalloc (1, sizeof (struct color_name));
+ STACK_VAR (color_names[index]);
+
+ color_names[index]->orig = xstrdup (color);
+ STACK_VAR (color_names[index]->orig);
+
+ for (ch = color; *ch; ch++)
+ *ch = tolower (*ch);
+
+ color_names[index]->name = xstrdup (color);
+ STACK_VAR (color_names[index]->name);
+ }
+
+ RELEASE_VAR (str);
+}
+
+static void
+read_print_stream (const char *attr, const struct color **colors, const char *file, FILE *stream)
+{
+ char buf[BUF_SIZE + 1];