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