+#define PRINT_HELP_EXIT() \
+ print_help (); \
+ exit (EXIT_SUCCESS); \
+
+#define PRINT_VERSION_EXIT() \
+ print_version (); \
+ exit (EXIT_SUCCESS); \
+
+extern char *optarg;
+
+static void
+process_opts (int argc, char **argv)
+{
+ int opt;
+ while ((opt = getopt_long (argc, argv, "hV", long_opts, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 0: /* long opts */
+ switch (opt_type)
+ {
+ case OPT_ATTR:
+ process_opt_attr (optarg);
+ break;
+ case OPT_CLEAN:
+ clean = true;
+ break;
+ case OPT_CLEAN_ALL:
+ clean_all = true;
+ break;
+ case OPT_EXCLUDE_RANDOM: {
+ bool valid = false;
+ unsigned int i;
+ exclude = xstrdup (optarg);
+ STACK_VAR (exclude);
+ for (i = 1; i < tables[GENERIC].count - 1; i++) /* skip color none and default */
+ {
+ const struct color *entry = &tables[GENERIC].entries[i];
+ if (streq (exclude, entry->name))
+ {
+ valid = true;
+ break;
+ }
+ }
+ if (!valid)
+ vfprintf_fail (formats[FMT_GENERIC], "--exclude-random switch must be provided a plain color");
+ break;
+ }
+ case OPT_HELP:
+ PRINT_HELP_EXIT ();
+ case OPT_VERSION:
+ PRINT_VERSION_EXIT ();
+ default: /* never reached */
+ ABORT_TRACE ();
+ }
+ break;
+ case 'h':
+ PRINT_HELP_EXIT ();
+ case 'V':
+ PRINT_VERSION_EXIT ();
+ case '?':
+ print_hint ();
+ exit (EXIT_FAILURE);
+ default: /* never reached */
+ ABORT_TRACE ();
+ }
+ }
+}
+
+static void
+process_opt_attr (const char *p)
+{
+ /* If attributes are added to this "list", also increase MAX_ATTRIBUTE_CHARS! */
+ const struct attr attrs[] = {
+ { "bold", 1, ATTR_BOLD },
+ { "underscore", 4, ATTR_UNDERSCORE },
+ { "blink", 5, ATTR_BLINK },
+ { "reverse", 7, ATTR_REVERSE },
+ { "concealed", 8, ATTR_CONCEALED },
+ };
+ unsigned int attr_types = 0;
+
+ while (*p)
+ {
+ const char *s;
+ if (!isalnum (*p))
+ vfprintf_fail (formats[FMT_GENERIC], "--attr switch must be provided a string");
+ s = p;
+ while (isalnum (*p))
+ p++;
+ if (*p != '\0' && *p != ',')
+ vfprintf_fail (formats[FMT_GENERIC], "--attr switch must have strings separated by ,");
+ else
+ {
+ bool valid_attr = false;
+ unsigned int i;
+ for (i = 0; i < sizeof (attrs) / sizeof (struct attr); i++)
+ {
+ const size_t name_len = strlen (attrs[i].name);
+ if ((size_t)(p - s) == name_len && strneq (s, attrs[i].name, name_len))
+ {
+ write_attr (&attrs[i], &attr_types);
+ valid_attr = true;
+ break;
+ }
+ }
+ if (!valid_attr)
+ vfprintf_fail (formats[FMT_GENERIC], "--attr switch must be provided valid attribute names");
+ }
+ if (*p)
+ p++;
+ }
+}
+
+static void
+write_attr (const struct attr *attr_i, unsigned int *attr_types)
+{
+ const unsigned int val = attr_i->val;
+ const enum attr_type attr_type = attr_i->type;
+ const char *attr_name = attr_i->name;
+
+ if (*attr_types & attr_type)
+ vfprintf_fail ("--attr switch has attribute '%s' twice or more", attr_name);
+ snprintf (attr + strlen (attr), 3, "%u;", val);
+ *attr_types |= attr_type;
+}
+
+static void
+print_hint (void)
+{
+ fprintf (stderr, "Type `%s --help' for help screen.\n", program_name);
+}
+