+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)
+ {
+ char *attr_invalid = xmalloc ((p - s) + 1);
+ STACK_VAR (attr_invalid);
+ strncpy (attr_invalid, s, p - s);
+ attr_invalid[p - s] = '\0';
+ vfprintf_fail ("--attr switch attribute '%s' is not valid", attr_invalid);
+ RELEASE_VAR (attr_invalid); /* never reached */
+ }
+ }
+ 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;
+}
+