+
+/*------------------------.
+| Scan a Bison skeleton. |
+`------------------------*/
+
+void
+scan_skel (FILE *in)
+{
+ static bool initialized = false;
+ if (!initialized)
+ {
+ initialized = true;
+ obstack_init (&obstack_for_string);
+ }
+ skel_in = in;
+ skel__flex_debug = trace_flag & trace_skeleton;
+ skel_lex ();
+}
+
+void
+skel_scanner_free (void)
+{
+ obstack_free (&obstack_for_string, 0);
+ /* Reclaim Flex's buffers. */
+ yylex_destroy ();
+}
+
+static void
+at_directive_perform (int at_directive_argc,
+ char *at_directive_argv[],
+ char **outnamep, int *out_linenop)
+{
+ if (STREQ (at_directive_argv[0], "@basename"))
+ {
+ if (at_directive_argc > 2)
+ fail_for_at_directive_too_many_args (at_directive_argv[0]);
+ fputs (last_component (at_directive_argv[1]), yyout);
+ }
+ else if (STREQ (at_directive_argv[0], "@warn")
+ || STREQ (at_directive_argv[0], "@complain")
+ || STREQ (at_directive_argv[0], "@fatal"))
+ {
+ warnings complaint_flag;
+ switch (at_directive_argv[0][1])
+ {
+ case 'w': complaint_flag = Wother; break;
+ case 'c': complaint_flag = complaint; break;
+ case 'f': complaint_flag = fatal; break;
+ default: aver (false); break;
+ }
+ switch (at_directive_argc)
+ {
+ case 2:
+ complain (complaint_flag, "%s", _(at_directive_argv[1]));
+ break;
+ case 3:
+ complain (complaint_flag, _(at_directive_argv[1]),
+ at_directive_argv[2]);
+ break;
+ case 4:
+ complain (complaint_flag, _(at_directive_argv[1]),
+ at_directive_argv[2], at_directive_argv[3]);
+ break;
+ case 5:
+ complain (complaint_flag, _(at_directive_argv[1]),
+ at_directive_argv[2], at_directive_argv[3],
+ at_directive_argv[4]);
+ break;
+ case 6:
+ complain (complaint_flag, _(at_directive_argv[1]),
+ at_directive_argv[2], at_directive_argv[3],
+ at_directive_argv[4], at_directive_argv[5]);
+ break;
+ default:
+ fail_for_at_directive_too_many_args (at_directive_argv[0]);
+ break;
+ }
+ }
+ else if (STREQ (at_directive_argv[0], "@warn_at")
+ || STREQ (at_directive_argv[0], "@complain_at")
+ || STREQ (at_directive_argv[0], "@fatal_at"))
+ {
+ warnings complaint_flag;
+ location loc;
+ if (at_directive_argc < 4)
+ fail_for_at_directive_too_few_args (at_directive_argv[0]);
+ switch (at_directive_argv[0][1])
+ {
+ case 'w': complaint_flag = Wother; break;
+ case 'c': complaint_flag = complaint; break;
+ case 'f': complaint_flag = fatal; break;
+ default: aver (false); break;
+ }
+ boundary_set_from_string (&loc.start, at_directive_argv[1]);
+ boundary_set_from_string (&loc.end, at_directive_argv[2]);
+ switch (at_directive_argc)
+ {
+ case 4:
+ complain_at (loc, complaint_flag, "%s", _(at_directive_argv[3]));
+ break;
+ case 5:
+ complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+ at_directive_argv[4]);
+ break;
+ case 6:
+ complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+ at_directive_argv[4], at_directive_argv[5]);
+ break;
+ case 7:
+ complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+ at_directive_argv[4], at_directive_argv[5],
+ at_directive_argv[6]);
+ break;
+ case 8:
+ complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+ at_directive_argv[4], at_directive_argv[5],
+ at_directive_argv[6], at_directive_argv[7]);
+ break;
+ default:
+ fail_for_at_directive_too_many_args (at_directive_argv[0]);
+ break;
+ }
+ }
+ else if (STREQ (at_directive_argv[0], "@output"))
+ {
+ if (at_directive_argc > 2)
+ fail_for_at_directive_too_many_args (at_directive_argv[0]);
+ if (*outnamep)
+ {
+ free (*outnamep);
+ xfclose (yyout);
+ }
+ *outnamep = xstrdup (at_directive_argv[1]);
+ output_file_name_check (outnamep);
+ yyout = xfopen (*outnamep, "w");
+ *out_linenop = 1;
+ }
+ else
+ fail_for_invalid_at (at_directive_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);
+}