+ yylex_destroy ();
+}
+
+static inline warnings
+flag (const char *arg)
+{
+ switch (arg[1])
+ {
+ case 'w': return Wother;
+ case 'c': return complaint;
+ case 'f': return fatal;
+ default: aver (false); break;
+ }
+}
+
+static void
+at_directive_perform (int argc, char *argv[], char **outnamep, int *out_linenop)
+{
+ if (STREQ (argv[0], "@basename"))
+ {
+ if (argc > 2)
+ fail_for_at_directive_too_many_args (argv[0]);
+ fputs (last_component (argv[1]), yyout);
+ }
+ else if (STREQ (argv[0], "@warn")
+ || STREQ (argv[0], "@complain")
+ || STREQ (argv[0], "@fatal"))
+ {
+ warnings w = flag (argv[0]);
+ switch (argc)
+ {
+ case 2:
+ complain (w, "%s", _(argv[1]));
+ break;
+ case 3:
+ complain (w, _(argv[1]), argv[2]);
+ break;
+ case 4:
+ complain (w, _(argv[1]), argv[2], argv[3]);
+ break;
+ case 5:
+ complain (w, _(argv[1]), argv[2], argv[3], argv[4]);
+ break;
+ case 6:
+ complain (w, _(argv[1]), argv[2], argv[3], argv[4], argv[5]);
+ break;
+ default:
+ fail_for_at_directive_too_many_args (argv[0]);
+ break;
+ }
+ }
+ else if (STREQ (argv[0], "@warn_at")
+ || STREQ (argv[0], "@complain_at")
+ || STREQ (argv[0], "@fatal_at"))
+ {
+ warnings w = flag (argv[0]);
+ location loc;
+ if (argc < 4)
+ fail_for_at_directive_too_few_args (argv[0]);
+ boundary_set_from_string (&loc.start, argv[1]);
+ boundary_set_from_string (&loc.end, argv[2]);
+ switch (argc)
+ {
+ case 4:
+ complain_at (loc, w, "%s", _(argv[3]));
+ break;
+ case 5:
+ complain_at (loc, w, _(argv[3]), argv[4]);
+ break;
+ case 6:
+ complain_at (loc, w, _(argv[3]), argv[4], argv[5]);
+ break;
+ case 7:
+ complain_at (loc, w, _(argv[3]), argv[4], argv[5], argv[6]);
+ break;
+ case 8:
+ complain_at (loc, w, _(argv[3]), argv[4], argv[5], argv[6],
+ argv[7]);
+ break;
+ default:
+ fail_for_at_directive_too_many_args (argv[0]);
+ break;
+ }
+ }
+ else if (STREQ (argv[0], "@output"))
+ {
+ if (argc > 2)
+ fail_for_at_directive_too_many_args (argv[0]);
+ if (*outnamep)
+ {
+ free (*outnamep);
+ xfclose (yyout);
+ }
+ *outnamep = xstrdup (argv[1]);
+ output_file_name_check (outnamep);
+ yyout = xfopen (*outnamep, "w");
+ *out_linenop = 1;
+ }
+ else
+ fail_for_invalid_at (argv[0]);
+}
+
+static void
+fail_for_at_directive_too_few_args (char const *at_directive_name)
+{
+ complain (fatal, _("too few arguments for %s directive in skeleton"),
+ at_directive_name);
+}
+
+static void
+fail_for_at_directive_too_many_args (char const *at_directive_name)
+{
+ complain (fatal, _("too many arguments for %s directive in skeleton"),
+ at_directive_name);
+}
+
+static void
+fail_for_invalid_at (char const *at)
+{
+ complain (fatal, "invalid @ in skeleton: %s", at);