Do not use date ranges in copyright notices.
[bison.git] / src / scan-skel.l
blob65ff26c82b41d4bc7755d4f626b6136b01e9fd94
1 /* Scan Bison Skeletons.                                       -*- C -*-
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
4    Free Software Foundation, Inc.
6    This file is part of Bison, the GNU Compiler Compiler.
8    This program is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 %option nodefault noyywrap noinput nounput never-interactive debug
22 %option prefix="skel_" outfile="lex.yy.c"
25 /* Work around a bug in flex 2.5.31.  See Debian bug 333231
26    <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
27 #undef skel_wrap
28 #define skel_wrap() 1
30 #define FLEX_PREFIX(Id) skel_ ## Id
31 #include "flex-scanner.h"
33 #include <dirname.h>
34 #include <error.h>
35 #include <quotearg.h>
37 #include "complain.h"
38 #include "getargs.h"
39 #include "files.h"
40 #include "scan-skel.h"
42 #define YY_DECL static int skel_lex (void)
43 YY_DECL;
45 #define QPUTS(String) \
46    fputs (quotearg_style (c_quoting_style, String), yyout)
48 static void at_directive_perform (int at_directive_argc,
49                                   char *at_directive_argv[],
50                                   char **outnamep, int *out_linenop);
51 static void fail_for_at_directive_too_many_args (char const *at_directive_name);
52 static void fail_for_at_directive_too_few_args (char const *at_directive_name);
53 static void fail_for_invalid_at (char const *at);
56 %x SC_AT_DIRECTIVE_ARGS
57 %x SC_AT_DIRECTIVE_SKIP_WS
62   int out_lineno IF_LINT (= 0);
63   char *outname = NULL;
65   /* Currently, only the @warn, @complain, @fatal, @warn_at, @complain_at, and
66      @fatal_at directives take multiple arguments, and the last three already
67      can't take more than 7.  at_directive_argv[0] is the directive name.  */
68   #define AT_DIRECTIVE_ARGC_MAX 8
69   int at_directive_argc = 0;
70   char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX];
73 "@@" fputc ('@', yyout);
74 "@{" fputc ('[', yyout);
75 "@}" fputc (']', yyout);
76 "@`" /* Emtpy.  Used by b4_cat in ../data/bison.m4.  */
77 @\n  /* Likewise.  */
79 "@oline@"  fprintf (yyout, "%d", out_lineno + 1);
80 "@ofile@"  QPUTS (outname);
81 "@dir_prefix@" QPUTS (dir_prefix);
83 @[a-z_]+"(" {
84   yytext[yyleng-1] = '\0';
85   obstack_grow (&obstack_for_string, yytext, yyleng);
86   at_directive_argv[at_directive_argc++] =
87     obstack_finish (&obstack_for_string);
88   BEGIN SC_AT_DIRECTIVE_ARGS;
91   /* This pattern must not match more than the previous @ patterns. */
92 @[^@{}`(\n]* fail_for_invalid_at (yytext);
93 \n         out_lineno++; ECHO;
94 [^@\n]+    ECHO;
96 <INITIAL><<EOF>> {
97   if (outname)
98     {
99       free (outname);
100       xfclose (yyout);
101     }
102   return EOF;
105 <SC_AT_DIRECTIVE_ARGS>{
106   [^@]+ { STRING_GROW; }
108   "@@" { obstack_1grow (&obstack_for_string, '@'); }
109   "@{" { obstack_1grow (&obstack_for_string, '['); }
110   "@}" { obstack_1grow (&obstack_for_string, ']'); }
111   "@`" /* Empty.  Useful for starting an argument
112           that begins with whitespace. */
113   @\n  /* Empty.  */
115   @[,)] {
116     if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
117       fail_for_at_directive_too_many_args (at_directive_argv[0]);
119     obstack_1grow (&obstack_for_string, '\0');
120     at_directive_argv[at_directive_argc++] =
121       obstack_finish (&obstack_for_string);
123     /* Like M4, skip whitespace after a comma.  */
124     if (yytext[1] == ',')
125       BEGIN SC_AT_DIRECTIVE_SKIP_WS;
126     else
127       {
128         at_directive_perform (at_directive_argc, at_directive_argv,
129                               &outname, &out_lineno);
130         obstack_free (&obstack_for_string, at_directive_argv[0]);
131         at_directive_argc = 0;
132         BEGIN INITIAL;
133       }
134   }
136   @.? { fail_for_invalid_at (yytext); }
139 <SC_AT_DIRECTIVE_SKIP_WS>{
140   [ \t\r\n]
141   . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; }
144 <SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>{
145   <<EOF>> {
146     fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
147   }
152 /*------------------------.
153 | Scan a Bison skeleton.  |
154 `------------------------*/
156 void
157 scan_skel (FILE *in)
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 ();
170 void
171 skel_scanner_free (void)
173   obstack_free (&obstack_for_string, 0);
174   /* Reclaim Flex's buffers.  */
175   yylex_destroy ();
178 static void
179 at_directive_perform (int at_directive_argc,
180                       char *at_directive_argv[],
181                       char **outnamep, int *out_linenop)
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]);
288 static void
289 fail_for_at_directive_too_few_args (char const *at_directive_name)
291   fatal (_("too few arguments for %s directive in skeleton"),
292          at_directive_name);
295 static void
296 fail_for_at_directive_too_many_args (char const *at_directive_name)
298   fatal (_("too many arguments for %s directive in skeleton"),
299          at_directive_name);
302 static void
303 fail_for_invalid_at (char const *at)
305   fatal ("invalid @ in skeleton: %s", at);