1 /* Bison Grammar Scanner -*- C -*-
3 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 %option debug nodefault nounput noyywrap never-interactive
24 %option prefix="gram_" outfile="lex.yy.c"
30 #include <get-errno.h>
41 #define YY_USER_INIT \
44 scanner_cursor.file = current_file; \
45 scanner_cursor.line = 1; \
46 scanner_cursor.column = 1; \
47 code_start = scanner_cursor; \
51 /* Location of scanner cursor. */
52 boundary scanner_cursor;
54 static void adjust_location (location *, char const *, size_t);
55 #define YY_USER_ACTION adjust_location (loc, yytext, yyleng);
57 static size_t no_cr_read (FILE *, char *, size_t);
58 #define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
61 /* OBSTACK_FOR_STRING -- Used to store all the characters that we need to
62 keep (to construct ID, STRINGS etc.). Use the following macros to
65 Use STRING_GROW to append what has just been matched, and
66 STRING_FINISH to end the string (it puts the ending 0).
67 STRING_FINISH also stores this string in LAST_STRING, which can be
68 used, and which is used by STRING_FREE to free the last string. */
70 static struct obstack obstack_for_string;
72 /* A string representing the most recently saved token. */
73 static char *last_string;
77 obstack_grow (&obstack_for_string, yytext, yyleng)
79 #define STRING_FINISH \
81 obstack_1grow (&obstack_for_string, '\0'); \
82 last_string = obstack_finish (&obstack_for_string); \
86 obstack_free (&obstack_for_string, last_string)
89 scanner_last_string_free (void)
94 /* Within well-formed rules, RULE_LENGTH is the number of values in
95 the current rule so far, which says where to find `$0' with respect
96 to the top of the stack. It is not the same as the rule->length in
97 the case of mid rule actions.
99 Outside of well-formed rules, RULE_LENGTH has an undefined value. */
100 static int rule_length;
102 static void handle_dollar (int token_type, char *cp, location loc);
103 static void handle_at (int token_type, char *cp, location loc);
104 static void handle_syncline (char *args);
105 static unsigned long int scan_integer (char const *p, int base, location loc);
106 static int convert_ucn_to_byte (char const *hex_text);
107 static void unexpected_eof (boundary, char const *);
108 static void unexpected_newline (boundary, char const *);
111 %x SC_COMMENT SC_LINE_COMMENT SC_YACC_COMMENT
112 %x SC_STRING SC_CHARACTER
113 %x SC_AFTER_IDENTIFIER
114 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
115 %x SC_PRE_CODE SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
117 letter [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
118 id {letter}({letter}|[0-9])*
119 directive %{letter}({letter}|[0-9]|-)*
122 /* POSIX says that a tag must be both an id and a C union member, but
123 historically almost any character is allowed in a tag. We disallow
124 NUL and newline, as this simplifies our implementation. */
127 /* Zero or more instances of backslash-newline. Following GCC, allow
128 white space between the backslash and the newline. */
129 splice (\\[ \f\t\v]*\n)*
133 /* Nesting level of the current code in braces. */
134 int braces_level IF_LINT (= 0);
136 /* Parent context state, when applicable. */
137 int context_state IF_LINT (= 0);
139 /* Token type to return, when applicable. */
140 int token_type IF_LINT (= 0);
142 /* Location of most recent identifier, when applicable. */
143 location id_loc IF_LINT (= empty_location);
145 /* Where containing code started, when applicable. Its initial
146 value is relevant only when yylex is invoked in the SC_EPILOGUE
148 boundary code_start = scanner_cursor;
150 /* Where containing comment or string or character literal started,
152 boundary token_start IF_LINT (= scanner_cursor);
156 /*-----------------------.
157 | Scanning white space. |
158 `-----------------------*/
160 <INITIAL,SC_AFTER_IDENTIFIER,SC_PRE_CODE>
162 /* Comments and white space. */
163 "," warn_at (*loc, _("stray `,' treated as white space"));
167 token_start = loc->start;
168 context_state = YY_START;
169 BEGIN SC_YACC_COMMENT;
172 /* #line directives are not documented, and may be withdrawn or
173 modified in future versions of Bison. */
174 ^"#line "{int}" \"".*"\"\n" {
175 handle_syncline (yytext + sizeof "#line " - 1);
180 /*----------------------------.
181 | Scanning Bison directives. |
182 `----------------------------*/
185 "%binary" return PERCENT_NONASSOC;
186 "%debug" return PERCENT_DEBUG;
187 "%default"[-_]"prec" return PERCENT_DEFAULT_PREC;
188 "%define" return PERCENT_DEFINE;
189 "%defines" return PERCENT_DEFINES;
190 "%destructor" token_type = PERCENT_DESTRUCTOR; BEGIN SC_PRE_CODE;
191 "%dprec" return PERCENT_DPREC;
192 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
193 "%expect" return PERCENT_EXPECT;
194 "%expect"[-_]"rr" return PERCENT_EXPECT_RR;
195 "%file-prefix" return PERCENT_FILE_PREFIX;
196 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
197 "%initial-action" token_type = PERCENT_INITIAL_ACTION; BEGIN SC_PRE_CODE;
198 "%glr-parser" return PERCENT_GLR_PARSER;
199 "%left" return PERCENT_LEFT;
200 "%lex-param" token_type = PERCENT_LEX_PARAM; BEGIN SC_PRE_CODE;
201 "%locations" return PERCENT_LOCATIONS;
202 "%merge" return PERCENT_MERGE;
203 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
204 "%no"[-_]"default"[-_]"prec" return PERCENT_NO_DEFAULT_PREC;
205 "%no"[-_]"lines" return PERCENT_NO_LINES;
206 "%nonassoc" return PERCENT_NONASSOC;
207 "%nondeterministic-parser" return PERCENT_NONDETERMINISTIC_PARSER;
208 "%nterm" return PERCENT_NTERM;
209 "%output" return PERCENT_OUTPUT;
210 "%parse-param" token_type = PERCENT_PARSE_PARAM; BEGIN SC_PRE_CODE;
211 "%prec" rule_length--; return PERCENT_PREC;
212 "%printer" token_type = PERCENT_PRINTER; BEGIN SC_PRE_CODE;
213 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
214 "%right" return PERCENT_RIGHT;
215 "%skeleton" return PERCENT_SKELETON;
216 "%start" return PERCENT_START;
217 "%term" return PERCENT_TOKEN;
218 "%token" return PERCENT_TOKEN;
219 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
220 "%type" return PERCENT_TYPE;
221 "%union" token_type = PERCENT_UNION; BEGIN SC_PRE_CODE;
222 "%verbose" return PERCENT_VERBOSE;
223 "%yacc" return PERCENT_YACC;
226 complain_at (*loc, _("invalid directive: %s"), quote (yytext));
230 "|" rule_length = 0; return PIPE;
231 ";" return SEMICOLON;
234 val->symbol = symbol_get (yytext, *loc);
237 BEGIN SC_AFTER_IDENTIFIER;
241 val->integer = scan_integer (yytext, 10, *loc);
244 0[xX][0-9abcdefABCDEF]+ {
245 val->integer = scan_integer (yytext, 16, *loc);
249 /* Characters. We don't check there is only one. */
250 "'" STRING_GROW; token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
253 "\"" token_start = loc->start; BEGIN SC_ESCAPED_STRING;
256 "%{" code_start = loc->start; BEGIN SC_PROLOGUE;
258 /* Code in between braces. */
261 token_type = BRACED_CODE;
263 code_start = loc->start;
264 BEGIN SC_BRACED_CODE;
269 obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2);
271 val->uniqstr = uniqstr_new (last_string);
277 static int percent_percent_count;
278 if (++percent_percent_count == 2)
280 return PERCENT_PERCENT;
284 complain_at (*loc, _("invalid character: %s"), quote (yytext));
288 loc->start = loc->end = scanner_cursor;
294 /*-----------------------------------------------------------------.
295 | Scanning after an identifier, checking whether a colon is next. |
296 `-----------------------------------------------------------------*/
298 <SC_AFTER_IDENTIFIER>
307 scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0);
321 /*---------------------------------------------------------------.
322 | Scanning a Yacc comment. The initial `/ *' is already eaten. |
323 `---------------------------------------------------------------*/
327 "*/" BEGIN context_state;
329 <<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
333 /*------------------------------------------------------------.
334 | Scanning a C comment. The initial `/ *' is already eaten. |
335 `------------------------------------------------------------*/
339 "*"{splice}"/" STRING_GROW; BEGIN context_state;
340 <<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
344 /*--------------------------------------------------------------.
345 | Scanning a line comment. The initial `//' is already eaten. |
346 `--------------------------------------------------------------*/
350 "\n" STRING_GROW; BEGIN context_state;
351 {splice} STRING_GROW;
352 <<EOF>> BEGIN context_state;
356 /*------------------------------------------------.
357 | Scanning a Bison string, including its escapes. |
358 | The initial quote is already eaten. |
359 `------------------------------------------------*/
365 loc->start = token_start;
366 val->chars = last_string;
371 \n unexpected_newline (token_start, "\""); BEGIN INITIAL;
372 <<EOF>> unexpected_eof (token_start, "\""); BEGIN INITIAL;
375 /*----------------------------------------------------------.
376 | Scanning a Bison character literal, decoding its escapes. |
377 | The initial quote is already eaten. |
378 `----------------------------------------------------------*/
380 <SC_ESCAPED_CHARACTER>
383 unsigned char last_string_1;
386 loc->start = token_start;
387 val->symbol = symbol_get (quotearg_style (escape_quoting_style,
390 symbol_class_set (val->symbol, token_sym, *loc);
391 last_string_1 = last_string[1];
392 symbol_user_token_number_set (val->symbol, last_string_1, *loc);
398 \n unexpected_newline (token_start, "'"); BEGIN INITIAL;
399 <<EOF>> unexpected_eof (token_start, "'"); BEGIN INITIAL;
402 <SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING>
404 \0 complain_at (*loc, _("invalid null character"));
408 /*----------------------------.
409 | Decode escaped characters. |
410 `----------------------------*/
412 <SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
415 unsigned long int c = strtoul (yytext + 1, 0, 8);
417 complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
419 complain_at (*loc, _("invalid null character: %s"), quote (yytext));
421 obstack_1grow (&obstack_for_string, c);
424 \\x[0-9abcdefABCDEF]+ {
427 c = strtoul (yytext + 2, 0, 16);
428 if (UCHAR_MAX < c || get_errno ())
429 complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
431 complain_at (*loc, _("invalid null character: %s"), quote (yytext));
433 obstack_1grow (&obstack_for_string, c);
436 \\a obstack_1grow (&obstack_for_string, '\a');
437 \\b obstack_1grow (&obstack_for_string, '\b');
438 \\f obstack_1grow (&obstack_for_string, '\f');
439 \\n obstack_1grow (&obstack_for_string, '\n');
440 \\r obstack_1grow (&obstack_for_string, '\r');
441 \\t obstack_1grow (&obstack_for_string, '\t');
442 \\v obstack_1grow (&obstack_for_string, '\v');
444 /* \\[\"\'?\\] would be shorter, but it confuses xgettext. */
445 \\("\""|"'"|"?"|"\\") obstack_1grow (&obstack_for_string, yytext[1]);
447 \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
448 int c = convert_ucn_to_byte (yytext);
450 complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
452 complain_at (*loc, _("invalid null character: %s"), quote (yytext));
454 obstack_1grow (&obstack_for_string, c);
457 complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext));
462 /*--------------------------------------------.
463 | Scanning user-code characters and strings. |
464 `--------------------------------------------*/
466 <SC_CHARACTER,SC_STRING>
468 {splice}|\\{splice}[^\n$@\[\]] STRING_GROW;
473 "'" STRING_GROW; BEGIN context_state;
474 \n unexpected_newline (token_start, "'"); BEGIN context_state;
475 <<EOF>> unexpected_eof (token_start, "'"); BEGIN context_state;
480 "\"" STRING_GROW; BEGIN context_state;
481 \n unexpected_newline (token_start, "\""); BEGIN context_state;
482 <<EOF>> unexpected_eof (token_start, "\""); BEGIN context_state;
486 /*---------------------------------------------------.
487 | Strings, comments etc. can be found in user code. |
488 `---------------------------------------------------*/
490 <SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
494 context_state = YY_START;
495 token_start = loc->start;
500 context_state = YY_START;
501 token_start = loc->start;
506 context_state = YY_START;
507 token_start = loc->start;
512 context_state = YY_START;
513 BEGIN SC_LINE_COMMENT;
518 /*---------------------------------------------------------------.
519 | Scanning after %union etc., possibly followed by white space. |
520 | For %union only, allow arbitrary C code to appear before the |
521 | following brace, as an extension to POSIX. |
522 `---------------------------------------------------------------*/
527 bool valid = yytext[0] == '{' || token_type == PERCENT_UNION;
528 scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0);
534 code_start = loc->start;
535 BEGIN SC_BRACED_CODE;
539 complain_at (*loc, _("missing `{' in `%s'"),
540 token_name (token_type));
541 obstack_sgrow (&obstack_for_string, "{}");
543 val->chars = last_string;
549 <<EOF>> unexpected_eof (scanner_cursor, "{}"); BEGIN INITIAL;
553 /*---------------------------------------------------------------.
554 | Scanning some code in braces (%union and actions). The initial |
555 | "{" is already eaten. |
556 `---------------------------------------------------------------*/
560 "{"|"<"{splice}"%" STRING_GROW; braces_level++;
561 "%"{splice}">" STRING_GROW; braces_level--;
563 bool outer_brace = --braces_level < 0;
565 /* As an undocumented Bison extension, append `;' before the last
566 brace in braced code, so that the user code can omit trailing
567 `;'. But do not append `;' if emulating Yacc, since Yacc does
570 FIXME: Bison should warn if a semicolon seems to be necessary
571 here, and should omit the semicolon if it seems unnecessary
572 (e.g., after ';', '{', or '}', each followed by comments or
573 white space). Such a warning shouldn't depend on --yacc; it
574 should depend on a new --pedantic option, which would cause
575 Bison to warn if it detects an extension to POSIX. --pedantic
576 should also diagnose other Bison extensions like %yacc.
577 Perhaps there should also be a GCC-style --pedantic-errors
578 option, so that such warnings are diagnosed as errors. */
579 if (outer_brace && token_type == BRACED_CODE && ! yacc_flag)
580 obstack_1grow (&obstack_for_string, ';');
582 obstack_1grow (&obstack_for_string, '}');
588 loc->start = code_start;
589 val->chars = last_string;
595 /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
597 "<"{splice}"<" STRING_GROW;
599 "$"("<"{tag}">")?(-?[0-9]+|"$") handle_dollar (token_type, yytext, *loc);
600 "@"(-?[0-9]+|"$") handle_at (token_type, yytext, *loc);
602 <<EOF>> unexpected_eof (code_start, "}"); BEGIN INITIAL;
606 /*--------------------------------------------------------------.
607 | Scanning some prologue: from "%{" (already scanned) to "%}". |
608 `--------------------------------------------------------------*/
614 loc->start = code_start;
615 val->chars = last_string;
620 <<EOF>> unexpected_eof (code_start, "%}"); BEGIN INITIAL;
624 /*---------------------------------------------------------------.
625 | Scanning the epilogue (everything after the second "%%", which |
626 | has already been eaten). |
627 `---------------------------------------------------------------*/
633 loc->start = code_start;
634 val->chars = last_string;
641 /*-----------------------------------------.
642 | Escape M4 quoting characters in C code. |
643 `-----------------------------------------*/
645 <SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
647 \$ obstack_sgrow (&obstack_for_string, "$][");
648 \@ obstack_sgrow (&obstack_for_string, "@@");
649 \[ obstack_sgrow (&obstack_for_string, "@{");
650 \] obstack_sgrow (&obstack_for_string, "@}");
654 /*-----------------------------------------------------.
655 | By default, grow the string obstack with the input. |
656 `-----------------------------------------------------*/
658 <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
659 <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
663 /* Keeps track of the maximum number of semantic values to the left of
664 a handle (those referenced by $0, $-1, etc.) are required by the
665 semantic actions of this grammar. */
666 int max_left_semantic_context = 0;
668 /* Set *LOC and adjust scanner cursor to account for token TOKEN of
672 adjust_location (location *loc, char const *token, size_t size)
674 int line = scanner_cursor.line;
675 int column = scanner_cursor.column;
676 char const *p0 = token;
677 char const *p = token;
678 char const *lim = token + size;
680 loc->start = scanner_cursor;
682 for (p = token; p < lim; p++)
692 column += mbsnwidth (p0, p - p0, 0);
693 column += 8 - ((column - 1) & 7);
698 scanner_cursor.line = line;
699 scanner_cursor.column = column + mbsnwidth (p0, p - p0, 0);
701 loc->end = scanner_cursor;
705 /* Read bytes from FP into buffer BUF of size SIZE. Return the
706 number of bytes read. Remove '\r' from input, treating \r\n
707 and isolated \r as \n. */
710 no_cr_read (FILE *fp, char *buf, size_t size)
712 size_t bytes_read = fread (buf, 1, size, fp);
715 char *w = memchr (buf, '\r', bytes_read);
719 char const *lim = buf + bytes_read;
723 /* Found an '\r'. Treat it like '\n', but ignore any
724 '\n' that immediately follows. */
729 if (ch != '\n' && ungetc (ch, fp) != ch)
735 /* Copy until the next '\r'. */
741 while ((*w++ = *r++) != '\r');
752 /*------------------------------------------------------------------.
753 | TEXT is pointing to a wannabee semantic value (i.e., a `$'). |
755 | Possible inputs: $[<TYPENAME>]($|integer) |
757 | Output to OBSTACK_FOR_STRING a reference to this semantic value. |
758 `------------------------------------------------------------------*/
761 handle_action_dollar (char *text, location loc)
763 const char *type_name = NULL;
769 /* Get the type name if explicit. */
782 type_name = symbol_list_n_type_name_get (current_rule, loc, 0);
783 if (!type_name && typed)
784 complain_at (loc, _("$$ of `%s' has no declared type"),
785 current_rule->sym->tag);
788 obstack_fgrow1 (&obstack_for_string,
789 "]b4_lhs_value([%s])[", type_name);
795 num = strtol (cp, 0, 10);
797 if (INT_MIN <= num && num <= rule_length && ! get_errno ())
800 if (1-n > max_left_semantic_context)
801 max_left_semantic_context = 1-n;
802 if (!type_name && n > 0)
803 type_name = symbol_list_n_type_name_get (current_rule, loc, n);
804 if (!type_name && typed)
805 complain_at (loc, _("$%d of `%s' has no declared type"),
806 n, current_rule->sym->tag);
809 obstack_fgrow3 (&obstack_for_string,
810 "]b4_rhs_value(%d, %d, [%s])[",
811 rule_length, n, type_name);
814 complain_at (loc, _("integer out of range: %s"), quote (text));
821 /*----------------------------------------------------------------.
822 | Map `$?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
823 | (are we in an action?). |
824 `----------------------------------------------------------------*/
827 handle_dollar (int token_type, char *text, location loc)
832 if (handle_action_dollar (text, loc))
836 case PERCENT_DESTRUCTOR:
837 case PERCENT_INITIAL_ACTION:
838 case PERCENT_PRINTER:
841 obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
850 complain_at (loc, _("invalid value: %s"), quote (text));
854 /*------------------------------------------------------.
855 | TEXT is a location token (i.e., a `@...'). Output to |
856 | OBSTACK_FOR_STRING a reference to this location. |
857 `------------------------------------------------------*/
860 handle_action_at (char *text, location loc)
863 locations_flag = true;
869 obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
874 num = strtol (cp, 0, 10);
876 if (INT_MIN <= num && num <= rule_length && ! get_errno ())
879 obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
883 complain_at (loc, _("integer out of range: %s"), quote (text));
890 /*----------------------------------------------------------------.
891 | Map `@?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
892 | (are we in an action?). |
893 `----------------------------------------------------------------*/
896 handle_at (int token_type, char *text, location loc)
901 handle_action_at (text, loc);
904 case PERCENT_INITIAL_ACTION:
905 case PERCENT_DESTRUCTOR:
906 case PERCENT_PRINTER:
909 obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
918 complain_at (loc, _("invalid value: %s"), quote (text));
922 /*------------------------------------------------------.
923 | Scan NUMBER for a base-BASE integer at location LOC. |
924 `------------------------------------------------------*/
926 static unsigned long int
927 scan_integer (char const *number, int base, location loc)
929 unsigned long int num;
931 num = strtoul (number, 0, base);
932 if (INT_MAX < num || get_errno ())
934 complain_at (loc, _("integer out of range: %s"), quote (number));
941 /*------------------------------------------------------------------.
942 | Convert universal character name UCN to a single-byte character, |
943 | and return that character. Return -1 if UCN does not correspond |
944 | to a single-byte character. |
945 `------------------------------------------------------------------*/
948 convert_ucn_to_byte (char const *ucn)
950 unsigned long int code = strtoul (ucn + 2, 0, 16);
952 /* FIXME: Currently we assume Unicode-compatible unibyte characters
953 on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
954 non-ASCII hosts we support only the portable C character set.
955 These limitations should be removed once we add support for
956 multibyte characters. */
958 if (UCHAR_MAX < code)
961 #if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
963 /* A non-ASCII host. Use CODE to index into a table of the C
964 basic execution character set, which is guaranteed to exist on
965 all Standard C platforms. This table also includes '$', '@',
966 and '`', which are not in the basic execution character set but
967 which are unibyte characters on all the platforms that we know
969 static signed char const table[] =
971 '\0', -1, -1, -1, -1, -1, -1, '\a',
972 '\b', '\t', '\n', '\v', '\f', '\r', -1, -1,
973 -1, -1, -1, -1, -1, -1, -1, -1,
974 -1, -1, -1, -1, -1, -1, -1, -1,
975 ' ', '!', '"', '#', '$', '%', '&', '\'',
976 '(', ')', '*', '+', ',', '-', '.', '/',
977 '0', '1', '2', '3', '4', '5', '6', '7',
978 '8', '9', ':', ';', '<', '=', '>', '?',
979 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
980 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
981 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
982 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
983 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
984 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
985 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
986 'x', 'y', 'z', '{', '|', '}', '~'
989 code = code < sizeof table ? table[code] : -1;
997 /*----------------------------------------------------------------.
998 | Handle `#line INT "FILE"'. ARGS has already skipped `#line '. |
999 `----------------------------------------------------------------*/
1002 handle_syncline (char *args)
1004 int lineno = strtol (args, &args, 10);
1005 const char *file = NULL;
1006 file = strchr (args, '"') + 1;
1007 *strchr (file, '"') = 0;
1008 scanner_cursor.file = current_file = uniqstr_new (file);
1009 scanner_cursor.line = lineno;
1010 scanner_cursor.column = 1;
1014 /*----------------------------------------------------------------.
1015 | For a token or comment starting at START, report message MSGID, |
1016 | which should say that an end marker was found before |
1017 | the expected TOKEN_END. |
1018 `----------------------------------------------------------------*/
1021 unexpected_end (boundary start, char const *msgid, char const *token_end)
1025 loc.end = scanner_cursor;
1026 complain_at (loc, _(msgid), token_end);
1030 /*------------------------------------------------------------------------.
1031 | Report an unexpected EOF in a token or comment starting at START. |
1032 | An end of file was encountered and the expected TOKEN_END was missing. |
1033 `------------------------------------------------------------------------*/
1036 unexpected_eof (boundary start, char const *token_end)
1038 unexpected_end (start, N_("missing `%s' at end of file"), token_end);
1042 /*----------------------------------------.
1043 | Likewise, but for unexpected newlines. |
1044 `----------------------------------------*/
1047 unexpected_newline (boundary start, char const *token_end)
1049 unexpected_end (start, N_("missing `%s' at end of line"), token_end);
1053 /*-------------------------.
1054 | Initialize the scanner. |
1055 `-------------------------*/
1058 scanner_initialize (void)
1060 obstack_init (&obstack_for_string);
1064 /*-----------------------------------------------.
1065 | Free all the memory allocated to the scanner. |
1066 `-----------------------------------------------*/
1071 obstack_free (&obstack_for_string, 0);
1072 /* Reclaim Flex's buffers. */
1073 yy_delete_buffer (YY_CURRENT_BUFFER);