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) 42YY_DECL; 43 44#define QPUTS(String) \ 45 fputs (quotearg_style (c_quoting_style, String), yyout) 46 47static void at_directive_perform (int at_directive_argc, 48 char *at_directive_argv[], 49 char **outnamep, int *out_linenop); 50static void fail_for_at_directive_too_many_args (char const *at_directive_name); 51static void fail_for_at_directive_too_few_args (char const *at_directive_name); 52static 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 156void 157scan_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 170void 171skel_scanner_free (void) 172{ 173 obstack_free (&obstack_for_string, 0); 174 /* Reclaim Flex's buffers. */ 175 yylex_destroy (); 176} 177 178static void 179at_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 288static void 289fail_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 295static void 296fail_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 302static void 303fail_for_invalid_at (char const *at) 304{ 305 fatal ("invalid @ in skeleton: %s", at); 306} 307