Home | History | Annotate | Download | only in src
      1 /* Scan Bison Skeletons.                                       -*- C -*-
      2 
      3    Copyright (C) 2001-2007, 2009-2012 Free Software Foundation, Inc.
      4 
      5    This file is part of Bison, the GNU Compiler Compiler.
      6 
      7    This program is free software: you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation, either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 %option nodefault noyywrap noinput nounput never-interactive debug
     21 %option prefix="skel_" outfile="lex.yy.c"
     22 
     23 %{
     24 /* Work around a bug in flex 2.5.31.  See Debian bug 333231
     25    <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
     26 #undef skel_wrap
     27 #define skel_wrap() 1
     28 
     29 #define FLEX_PREFIX(Id) skel_ ## Id
     30 #include "flex-scanner.h"
     31 
     32 #include <dirname.h>
     33 #include <error.h>
     34 #include <quotearg.h>
     35 
     36 #include "complain.h"
     37 #include "getargs.h"
     38 #include "files.h"
     39 #include "scan-skel.h"
     40 
     41 #define YY_DECL static int skel_lex (void)
     42 YY_DECL;
     43 
     44 #define QPUTS(String) \
     45    fputs (quotearg_style (c_quoting_style, String), yyout)
     46 
     47 static void at_directive_perform (int at_directive_argc,
     48                                   char *at_directive_argv[],
     49                                   char **outnamep, int *out_linenop);
     50 static void fail_for_at_directive_too_many_args (char const *at_directive_name);
     51 static void fail_for_at_directive_too_few_args (char const *at_directive_name);
     52 static void fail_for_invalid_at (char const *at);
     53 %}
     54 
     55 %x SC_AT_DIRECTIVE_ARGS
     56 %x SC_AT_DIRECTIVE_SKIP_WS
     57 
     58 %%
     59 
     60 %{
     61   int out_lineno PACIFY_CC (= 0);
     62   char *outname = NULL;
     63 
     64   /* Currently, only the @warn, @complain, @fatal, @warn_at, @complain_at, and
     65      @fatal_at directives take multiple arguments, and the last three already
     66      can't take more than 7.  at_directive_argv[0] is the directive name.  */
     67   #define AT_DIRECTIVE_ARGC_MAX 8
     68   int at_directive_argc = 0;
     69   char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX];
     70 %}
     71 
     72 "@@" fputc ('@', yyout);
     73 "@{" fputc ('[', yyout);
     74 "@}" fputc (']', yyout);
     75 "@`" continue;  /* Used by b4_cat in ../data/bison.m4.  */
     76 @\n  continue;
     77 
     78 "@oline@"  fprintf (yyout, "%d", out_lineno + 1);
     79 "@ofile@"  QPUTS (outname);
     80 
     81 @[a-z_]+"(" {
     82   yytext[yyleng-1] = '\0';
     83   obstack_grow (&obstack_for_string, yytext, yyleng);
     84   at_directive_argv[at_directive_argc++] =
     85     obstack_finish (&obstack_for_string);
     86   BEGIN SC_AT_DIRECTIVE_ARGS;
     87 }
     88 
     89   /* This pattern must not match more than the previous @ patterns. */
     90 @[^@{}`(\n]*  fail_for_invalid_at (yytext);
     91 \n            out_lineno++; ECHO;
     92 [^@\n]+       ECHO;
     93 
     94 <INITIAL><<EOF>> {
     95   if (outname)
     96     {
     97       free (outname);
     98       xfclose (yyout);
     99     }
    100   return EOF;
    101 }
    102 
    103 <SC_AT_DIRECTIVE_ARGS>
    104 {
    105   [^@]+  STRING_GROW;
    106 
    107   "@@"   obstack_1grow (&obstack_for_string, '@');
    108   "@{"   obstack_1grow (&obstack_for_string, '[');
    109   "@}"   obstack_1grow (&obstack_for_string, ']');
    110   "@`"   continue; /* For starting an argument that begins with whitespace. */
    111   @\n    continue;
    112 
    113   @[,)] {
    114     if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
    115       fail_for_at_directive_too_many_args (at_directive_argv[0]);
    116 
    117     obstack_1grow (&obstack_for_string, '\0');
    118     at_directive_argv[at_directive_argc++] =
    119       obstack_finish (&obstack_for_string);
    120 
    121     /* Like M4, skip whitespace after a comma.  */
    122     if (yytext[1] == ',')
    123       BEGIN SC_AT_DIRECTIVE_SKIP_WS;
    124     else
    125       {
    126         at_directive_perform (at_directive_argc, at_directive_argv,
    127                               &outname, &out_lineno);
    128         obstack_free (&obstack_for_string, at_directive_argv[0]);
    129         at_directive_argc = 0;
    130         BEGIN INITIAL;
    131       }
    132   }
    133 
    134   @.?  fail_for_invalid_at (yytext);
    135 }
    136 
    137 <SC_AT_DIRECTIVE_SKIP_WS>
    138 {
    139   [ \t\r\n]    continue;
    140   .            { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; }
    141 }
    142 
    143 <SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>
    144 {
    145   <<EOF>> {
    146     fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
    147   }
    148 }
    149 
    150 %%
    151 
    152 /*------------------------.
    153 | Scan a Bison skeleton.  |
    154 `------------------------*/
    155 
    156 void
    157 scan_skel (FILE *in)
    158 {
    159   static bool initialized = false;
    160   if (!initialized)
    161     {
    162       initialized = true;
    163       obstack_init (&obstack_for_string);
    164     }
    165   skel_in = in;
    166   skel__flex_debug = trace_flag & trace_skeleton;
    167   skel_lex ();
    168 }
    169 
    170 void
    171 skel_scanner_free (void)
    172 {
    173   obstack_free (&obstack_for_string, 0);
    174   /* Reclaim Flex's buffers.  */
    175   yylex_destroy ();
    176 }
    177 
    178 static void
    179 at_directive_perform (int at_directive_argc,
    180                       char *at_directive_argv[],
    181                       char **outnamep, int *out_linenop)
    182 {
    183   if (0 == strcmp (at_directive_argv[0], "@basename"))
    184     {
    185       if (at_directive_argc > 2)
    186         fail_for_at_directive_too_many_args (at_directive_argv[0]);
    187       fputs (last_component (at_directive_argv[1]), yyout);
    188     }
    189   else if (0 == strcmp (at_directive_argv[0], "@warn")
    190            || 0 == strcmp (at_directive_argv[0], "@complain")
    191            || 0 == strcmp (at_directive_argv[0], "@fatal"))
    192     {
    193       void (*func)(char const *, ...);
    194       switch (at_directive_argv[0][1])
    195         {
    196           case 'w': func = warn; break;
    197           case 'c': func = complain; break;
    198           case 'f': func = fatal; break;
    199           default: aver (false); break;
    200         }
    201       switch (at_directive_argc)
    202         {
    203           case 2:
    204             func (_(at_directive_argv[1]));
    205             break;
    206           case 3:
    207             func (_(at_directive_argv[1]), at_directive_argv[2]);
    208             break;
    209           case 4:
    210             func (_(at_directive_argv[1]), at_directive_argv[2],
    211                   at_directive_argv[3]);
    212             break;
    213           case 5:
    214             func (_(at_directive_argv[1]), at_directive_argv[2],
    215                   at_directive_argv[3], at_directive_argv[4]);
    216             break;
    217           case 6:
    218             func (_(at_directive_argv[1]), at_directive_argv[2],
    219                   at_directive_argv[3], at_directive_argv[4],
    220                   at_directive_argv[5]);
    221             break;
    222           default:
    223             fail_for_at_directive_too_many_args (at_directive_argv[0]);
    224             break;
    225         }
    226     }
    227   else if (0 == strcmp (at_directive_argv[0], "@warn_at")
    228            || 0 == strcmp (at_directive_argv[0], "@complain_at")
    229            || 0 == strcmp (at_directive_argv[0], "@fatal_at"))
    230     {
    231       void (*func)(location, char const *, ...);
    232       location loc;
    233       if (at_directive_argc < 4)
    234         fail_for_at_directive_too_few_args (at_directive_argv[0]);
    235       switch (at_directive_argv[0][1])
    236         {
    237           case 'w': func = warn_at; break;
    238           case 'c': func = complain_at; break;
    239           case 'f': func = fatal_at; break;
    240           default: aver (false); break;
    241         }
    242       boundary_set_from_string (&loc.start, at_directive_argv[1]);
    243       boundary_set_from_string (&loc.end, at_directive_argv[2]);
    244       switch (at_directive_argc)
    245         {
    246           case 4:
    247             func (loc, _(at_directive_argv[3]));
    248             break;
    249           case 5:
    250             func (loc, _(at_directive_argv[3]), at_directive_argv[4]);
    251             break;
    252           case 6:
    253             func (loc, _(at_directive_argv[3]), at_directive_argv[4],
    254                   at_directive_argv[5]);
    255             break;
    256           case 7:
    257             func (loc, _(at_directive_argv[3]), at_directive_argv[4],
    258                   at_directive_argv[5], at_directive_argv[6]);
    259             break;
    260           case 8:
    261             func (loc, _(at_directive_argv[3]), at_directive_argv[4],
    262                   at_directive_argv[5], at_directive_argv[6],
    263                   at_directive_argv[7]);
    264             break;
    265           default:
    266             fail_for_at_directive_too_many_args (at_directive_argv[0]);
    267             break;
    268         }
    269     }
    270   else if (0 == strcmp (at_directive_argv[0], "@output"))
    271     {
    272       if (at_directive_argc > 2)
    273         fail_for_at_directive_too_many_args (at_directive_argv[0]);
    274       if (*outnamep)
    275         {
    276           free (*outnamep);
    277           xfclose (yyout);
    278         }
    279       *outnamep = xstrdup (at_directive_argv[1]);
    280       output_file_name_check (outnamep);
    281       yyout = xfopen (*outnamep, "w");
    282       *out_linenop = 1;
    283     }
    284   else
    285     fail_for_invalid_at (at_directive_argv[0]);
    286 }
    287 
    288 static void
    289 fail_for_at_directive_too_few_args (char const *at_directive_name)
    290 {
    291   fatal (_("too few arguments for %s directive in skeleton"),
    292          at_directive_name);
    293 }
    294 
    295 static void
    296 fail_for_at_directive_too_many_args (char const *at_directive_name)
    297 {
    298   fatal (_("too many arguments for %s directive in skeleton"),
    299          at_directive_name);
    300 }
    301 
    302 static void
    303 fail_for_invalid_at (char const *at)
    304 {
    305   fatal ("invalid @ in skeleton: %s", at);
    306 }
    307