]> git.saurik.com Git - bison.git/blobdiff - src/scan-skel.l
Use ASCII for Sebastien Fricker's name.
[bison.git] / src / scan-skel.l
index 4bba4ac4063d42b9d869d53d51f68f83a561e13d..f3fa1a61cdff54c7bb29486585dcd795c1a52aa6 100644 (file)
@@ -1,6 +1,6 @@
 /* Scan Bison Skeletons.                                       -*- C -*-
 
 /* Scan Bison Skeletons.                                       -*- C -*-
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
    Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -29,7 +29,6 @@
 #undef skel_wrap
 #define skel_wrap() 1
 
 #undef skel_wrap
 #define skel_wrap() 1
 
-#define FLEX_NO_OBSTACK
 #define FLEX_PREFIX(Id) skel_ ## Id
 #include "flex-scanner.h"
 
 #define FLEX_PREFIX(Id) skel_ ## Id
 #include "flex-scanner.h"
 
 #include "files.h"
 #include "scan-skel.h"
 
 #include "files.h"
 #include "scan-skel.h"
 
-int skel_lex (void);
+#define YY_DECL static int skel_lex (void)
+YY_DECL;
 
 #define QPUTS(String) \
    fputs (quotearg_style (c_quoting_style, String), yyout)
 
 
 #define QPUTS(String) \
    fputs (quotearg_style (c_quoting_style, String), yyout)
 
-static char *decode_at_digraphs (char *in);
+static void at_directive_perform (int at_directive_argc,
+                                  char *at_directive_argv[],
+                                  char **outnamep, int *out_linenop);
+static void fail_for_at_directive_too_many_args (char const *at_directive_name);
+static void fail_for_at_directive_too_few_args (char const *at_directive_name);
+static void fail_for_invalid_at (char const *at);
 %}
 %}
+
+%x SC_AT_DIRECTIVE_ARGS
+%x SC_AT_DIRECTIVE_SKIP_WS
+
 %%
 
 %{
 %%
 
 %{
-  int lineno IF_LINT (= 0);
+  int out_lineno IF_LINT (= 0);
   char *outname = NULL;
   char *outname = NULL;
-%}
 
 
-"@output ".*\n {
-  char *file_name = yytext + sizeof "@output " - 1;
-  yytext[yyleng - 1] = '\0';
-  if (outname)
-    {
-      free (outname);
-      xfclose (yyout);
-    }
-  outname = decode_at_digraphs (file_name);
-  output_file_name_check (outname);
-  yyout = xfopen (outname, "w");
-  lineno = 1;
-}
+  /* Currently, only the @warn, @complain, @fatal, @warn_at, @complain_at, and
+     @fatal_at directives take multiple arguments, and the last three already
+     can't take more than 7.  at_directive_argv[0] is the directive name.  */
+  #define AT_DIRECTIVE_ARGC_MAX 8
+  int at_directive_argc = 0;
+  char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX];
+%}
 
 "@@"      fputc ('@', yyout);
 "@{"      fputc ('[', yyout);
 "@}"      fputc (']', yyout);
 
 
 "@@"      fputc ('@', yyout);
 "@{"      fputc ('[', yyout);
 "@}"      fputc (']', yyout);
 
-"@oline@"  fprintf (yyout, "%d", lineno + 1);
+"@oline@"  fprintf (yyout, "%d", out_lineno + 1);
 "@ofile@"  QPUTS (outname);
 "@dir_prefix@" QPUTS (dir_prefix);
 
 "@ofile@"  QPUTS (outname);
 "@dir_prefix@" QPUTS (dir_prefix);
 
-"@basename(".*"@)" {
-  char *file_name = yytext + sizeof "@basename " - 1;
-  yytext[yyleng - 2] = '\0';
-  file_name = decode_at_digraphs (file_name);
-  fputs (last_component (file_name), yyout);
-  free (file_name);
+@[a-z_]+"(" {
+  yytext[yyleng-1] = '\0';
+  obstack_grow (&obstack_for_string, yytext, yyleng);
+  at_directive_argv[at_directive_argc++] =
+    obstack_finish (&obstack_for_string);
+  BEGIN SC_AT_DIRECTIVE_ARGS;
 }
 
   /* This pattern must not match more than the previous @ patterns. */
 }
 
   /* This pattern must not match more than the previous @ patterns. */
-@[^{}@\n]* fatal ("invalid @ in skeleton: %s", yytext);
-\n        lineno++; ECHO;
+@[^@{}(\n]* fail_for_invalid_at (yytext);
+\n        out_lineno++; ECHO;
 [^@\n]+           ECHO;
 
 [^@\n]+           ECHO;
 
-<<EOF>> {
+<INITIAL><<EOF>> {
   if (outname)
     {
       free (outname);
   if (outname)
     {
       free (outname);
@@ -99,6 +101,51 @@ static char *decode_at_digraphs (char *in);
     }
   return EOF;
 }
     }
   return EOF;
 }
+
+<SC_AT_DIRECTIVE_ARGS>{
+  [^@]+ { STRING_GROW; }
+
+  "@@" { obstack_1grow (&obstack_for_string, '@'); }
+  "@{" { obstack_1grow (&obstack_for_string, '['); }
+  "@}" { obstack_1grow (&obstack_for_string, ']'); }
+  "@`" /* Emtpy.  Useful for starting an argument
+          that begins with whitespace. */
+
+  @[,)] {
+    if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
+      fail_for_at_directive_too_many_args (at_directive_argv[0]);
+
+    obstack_1grow (&obstack_for_string, '\0');
+    at_directive_argv[at_directive_argc++] =
+      obstack_finish (&obstack_for_string);
+
+    /* Like M4, skip whitespace after a comma.  */
+    if (yytext[1] == ',')
+      BEGIN SC_AT_DIRECTIVE_SKIP_WS;
+    else
+      {
+        at_directive_perform (at_directive_argc, at_directive_argv,
+                              &outname, &out_lineno);
+        obstack_free (&obstack_for_string, at_directive_argv[0]);
+        at_directive_argc = 0;
+        BEGIN INITIAL;
+      }
+  }
+
+  @.? { fail_for_invalid_at (yytext); }
+}
+
+<SC_AT_DIRECTIVE_SKIP_WS>{
+  [ \t\r\n]
+  . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; }
+}
+
+<SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>{
+  <<EOF>> {
+    fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
+  }
+}
+
 %%
 
 /*------------------------.
 %%
 
 /*------------------------.
@@ -108,37 +155,151 @@ static char *decode_at_digraphs (char *in);
 void
 scan_skel (FILE *in)
 {
 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 ();
   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 ();
 }
 
   /* Reclaim Flex's buffers.  */
   yylex_destroy ();
 }
 
-static char *
-decode_at_digraphs (char *in)
+static
+void at_directive_perform (int at_directive_argc,
+                           char *at_directive_argv[],
+                           char **outnamep, int *out_linenop)
 {
 {
-  char *out_start = xnmalloc (strlen (in)+1, sizeof *out_start);
-  char *out;
-  for (out = out_start; *in != '\0'; ++in, ++out)
+  if (0 == strcmp (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 (0 == strcmp (at_directive_argv[0], "@warn")
+           || 0 == strcmp (at_directive_argv[0], "@complain")
+           || 0 == strcmp (at_directive_argv[0], "@fatal"))
     {
     {
-      if (*in == '@')
+      void (*func)(char const *, ...);
+      switch (at_directive_argv[0][1])
         {
         {
-          switch (*++in)
-            {
-              case '@': *out = '@'; break;
-              case '{': *out = '['; break;
-              case '}': *out = ']'; break;
-              default:
-                if (*in != '\0')
-                  in[1] = '\0';
-                fatal ("invalid @ in skeleton: %s", in-1);
-                break;
-            }
+          case 'w': func = warn; break;
+          case 'c': func = complain; break;
+          case 'f': func = fatal; break;
+          default: aver (false); break;
+        }
+      switch (at_directive_argc)
+        {
+          case 2:
+            func (_(at_directive_argv[1]));
+            break;
+          case 3:
+            func (_(at_directive_argv[1]), at_directive_argv[2]);
+            break;
+          case 4:
+            func (_(at_directive_argv[1]), at_directive_argv[2],
+                  at_directive_argv[3]);
+            break;
+          case 5:
+            func (_(at_directive_argv[1]), at_directive_argv[2],
+                  at_directive_argv[3], at_directive_argv[4]);
+            break;
+          case 6:
+            func (_(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
-        *out = *in;
     }
     }
-  *out = '\0';
-  return out_start;
+  else if (0 == strcmp (at_directive_argv[0], "@warn_at")
+           || 0 == strcmp (at_directive_argv[0], "@complain_at")
+           || 0 == strcmp (at_directive_argv[0], "@fatal_at"))
+    {
+      void (*func)(location, char const *, ...);
+      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': func = warn_at; break;
+          case 'c': func = complain_at; break;
+          case 'f': func = fatal_at; 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:
+            func (loc, _(at_directive_argv[3]));
+            break;
+          case 5:
+            func (loc, _(at_directive_argv[3]), at_directive_argv[4]);
+            break;
+          case 6:
+            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
+                  at_directive_argv[5]);
+            break;
+          case 7:
+            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
+                  at_directive_argv[5], at_directive_argv[6]);
+            break;
+          case 8:
+            func (loc, _(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 (0 == strcmp (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)
+{
+  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)
+{
+  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);
 }
 }