+static void
+sanity_check_menu_options (const char *filename, const xmlChar *node_name,
+ parameter *p)
+{
+ GList *opts;
+ int noptions = 0;
+ int nulls = 0;
+ char *prefix = 0;
+
+/* fprintf (stderr, "\n## %s\n", p->id);*/
+ for (opts = p->options; opts; opts = opts->next)
+ {
+ parameter *s = (parameter *) opts->data;
+ if (!s->arg_set) nulls++;
+ noptions++;
+
+ if (s->arg_set)
+ {
+ char *a = strdup ((char *) s->arg_set);
+ char *spc = strchr (a, ' ');
+ if (spc) *spc = 0;
+ if (prefix)
+ {
+ if (strcmp (a, prefix))
+ fprintf (stderr,
+ "%s: %s: both \"%s\" and \"%s\" used in <select id=\"%s\">\n",
+ blurb(), filename, prefix, a, p->id);
+ free (prefix);
+ }
+ prefix = a;
+ }
+
+/* fprintf (stderr, "\n %s\n", s->arg_set);*/
+ }
+
+ if (prefix) free (prefix);
+ prefix = 0;
+ if (nulls > 1)
+ fprintf (stderr,
+ "%s: %s: more than one menu with no arg-set in <select id=\"%s\">\n",
+ blurb(), filename, p->id);
+}
+
+
+/* "text" nodes show up for all the non-tag text in the file, including
+ all the newlines between tags. Warn if there is text there that
+ is not whitespace.
+ */
+static void
+sanity_check_text_node (const char *filename, const xmlNodePtr node)
+{
+ const char *body = (const char *) node->content;
+ if (node->type != XML_TEXT_NODE) abort();
+ while (isspace (*body)) body++;
+ if (*body)
+ fprintf (stderr, "%s: WARNING: %s: random text present: \"%s\"\n",
+ blurb(), filename, body);
+}
+
+
+/* Returns a list of strings, every switch mentioned in the parameters.
+ The strings must be freed.
+ */
+static GList *
+get_all_switches (const char *filename, GList *parms)
+{
+ GList *switches = 0;
+ GList *p;
+ for (p = parms; p; p = p->next)
+ {
+ parameter *pp = (parameter *) p->data;
+
+ if (pp->type == SELECT)
+ {
+ GList *list2 = get_all_switches (filename, pp->options);
+ switches = g_list_concat (switches, list2);
+ }
+ if (pp->arg && *pp->arg)
+ switches = g_list_append (switches, strdup ((char *) pp->arg));
+ if (pp->arg_set && *pp->arg_set)
+ switches = g_list_append (switches, strdup ((char *) pp->arg_set));
+ if (pp->arg_unset && *pp->arg_unset)
+ switches = g_list_append (switches, strdup ((char *) pp->arg_unset));
+ }
+ return switches;
+}
+
+
+/* Ensures that no switch is mentioned more than once.
+ */
+static void
+sanity_check_parameters (const char *filename, GList *parms)
+{
+ GList *list = get_all_switches (filename, parms);
+ GList *p;
+ for (p = list; p; p = p->next)
+ {
+ char *sw = (char *) p->data;
+ GList *p2;
+
+ if (*sw != '-' && *sw != '+')
+ fprintf (stderr, "%s: %s: switch does not begin with hyphen \"%s\"\n",
+ blurb(), filename, sw);
+
+ for (p2 = p->next; p2; p2 = p2->next)
+ {
+ const char *sw2 = (const char *) p2->data;
+ if (!strcmp (sw, sw2))
+ fprintf (stderr, "%s: %s: duplicate switch \"%s\"\n",
+ blurb(), filename, sw);
+ }
+
+ free (sw);
+ }
+ g_list_free (list);
+}
+