24 |
|
|
25 |
%{ |
%{ |
26 |
#include "system.h" |
#include "system.h" |
27 |
#include "mbswidth.h" |
|
28 |
|
#include <mbswidth.h> |
29 |
|
#include <get-errno.h> |
30 |
|
#include <quote.h> |
31 |
|
|
32 |
#include "complain.h" |
#include "complain.h" |
33 |
#include "files.h" |
#include "files.h" |
|
#include "quote.h" |
|
|
#include "struniq.h" |
|
34 |
#include "getargs.h" |
#include "getargs.h" |
35 |
#include "gram.h" |
#include "gram.h" |
36 |
#include "reader.h" |
#include "reader.h" |
37 |
|
#include "uniqstr.h" |
38 |
|
|
39 |
#define YY_USER_INIT \ |
#define YY_USER_INIT \ |
40 |
do \ |
do \ |
48 |
/* Location of scanner cursor. */ |
/* Location of scanner cursor. */ |
49 |
boundary scanner_cursor; |
boundary scanner_cursor; |
50 |
|
|
51 |
static void adjust_location (location_t *, char const *, size_t); |
static void adjust_location (location *, char const *, size_t); |
52 |
#define YY_USER_ACTION adjust_location (loc, yytext, yyleng); |
#define YY_USER_ACTION adjust_location (loc, yytext, yyleng); |
53 |
|
|
54 |
static size_t no_cr_read (FILE *, char *, size_t); |
static size_t no_cr_read (FILE *, char *, size_t); |
55 |
#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size)) |
#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size)) |
56 |
|
|
57 |
|
|
58 |
/* STRING_OBSTACK -- Used to store all the characters that we need to |
/* OBSTACK_FOR_STRING -- Used to store all the characters that we need to |
59 |
keep (to construct ID, STRINGS etc.). Use the following macros to |
keep (to construct ID, STRINGS etc.). Use the following macros to |
60 |
use it. |
use it. |
61 |
|
|
64 |
STRING_FINISH also stores this string in LAST_STRING, which can be |
STRING_FINISH also stores this string in LAST_STRING, which can be |
65 |
used, and which is used by STRING_FREE to free the last string. */ |
used, and which is used by STRING_FREE to free the last string. */ |
66 |
|
|
67 |
static struct obstack string_obstack; |
static struct obstack obstack_for_string; |
68 |
|
|
69 |
/* A string representing the most recently saved token. */ |
/* A string representing the most recently saved token. */ |
70 |
static char *last_string; |
static char *last_string; |
71 |
|
|
72 |
|
|
73 |
#define STRING_GROW \ |
#define STRING_GROW \ |
74 |
obstack_grow (&string_obstack, yytext, yyleng) |
obstack_grow (&obstack_for_string, yytext, yyleng) |
75 |
|
|
76 |
#define STRING_FINISH \ |
#define STRING_FINISH \ |
77 |
do { \ |
do { \ |
78 |
obstack_1grow (&string_obstack, '\0'); \ |
obstack_1grow (&obstack_for_string, '\0'); \ |
79 |
last_string = obstack_finish (&string_obstack); \ |
last_string = obstack_finish (&obstack_for_string); \ |
80 |
} while (0) |
} while (0) |
81 |
|
|
82 |
#define STRING_FREE \ |
#define STRING_FREE \ |
83 |
obstack_free (&string_obstack, last_string) |
obstack_free (&obstack_for_string, last_string) |
84 |
|
|
85 |
void |
void |
86 |
scanner_last_string_free (void) |
scanner_last_string_free (void) |
96 |
Outside of well-formed rules, RULE_LENGTH has an undefined value. */ |
Outside of well-formed rules, RULE_LENGTH has an undefined value. */ |
97 |
static int rule_length; |
static int rule_length; |
98 |
|
|
99 |
static void handle_dollar (braced_code_t code_kind, |
static void handle_dollar (braced_code code_kind, char *cp, location loc); |
100 |
char *cp, location_t location); |
static void handle_at (braced_code code_kind, char *cp, location loc); |
|
static void handle_at (braced_code_t code_kind, |
|
|
char *cp, location_t location); |
|
101 |
static void handle_syncline (char *args); |
static void handle_syncline (char *args); |
102 |
static int convert_ucn_to_byte (char const *hex_text); |
static int convert_ucn_to_byte (char const *hex_text); |
103 |
static void unexpected_end_of_file (boundary, char const *); |
static void unexpected_end_of_file (boundary, char const *); |
132 |
int context_state IF_LINT (= 0); |
int context_state IF_LINT (= 0); |
133 |
|
|
134 |
/* Location of most recent identifier, when applicable. */ |
/* Location of most recent identifier, when applicable. */ |
135 |
location_t id_loc IF_LINT (= *loc); |
location id_loc IF_LINT (= *loc); |
136 |
|
|
137 |
/* Location where containing code started, when applicable. */ |
/* Where containing code started, when applicable. */ |
138 |
boundary code_start IF_LINT (= loc->start); |
boundary code_start IF_LINT (= loc->start); |
139 |
|
|
140 |
/* Location where containing comment or string or character literal |
/* Where containing comment or string or character literal started, |
141 |
started, when applicable. */ |
when applicable. */ |
142 |
boundary token_start IF_LINT (= loc->start); |
boundary token_start IF_LINT (= loc->start); |
143 |
%} |
%} |
144 |
|
|
224 |
|
|
225 |
{int} { |
{int} { |
226 |
unsigned long num; |
unsigned long num; |
227 |
errno = 0; |
set_errno (0); |
228 |
num = strtoul (yytext, 0, 10); |
num = strtoul (yytext, 0, 10); |
229 |
if (INT_MAX < num || errno) |
if (INT_MAX < num || get_errno ()) |
230 |
{ |
{ |
231 |
complain_at (*loc, _("integer out of range: %s"), quote (yytext)); |
complain_at (*loc, _("integer out of range: %s"), quote (yytext)); |
232 |
num = INT_MAX; |
num = INT_MAX; |
254 |
|
|
255 |
/* A type. */ |
/* A type. */ |
256 |
"<"{tag}">" { |
"<"{tag}">" { |
257 |
obstack_grow (&string_obstack, yytext + 1, yyleng - 2); |
obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2); |
258 |
STRING_FINISH; |
STRING_FINISH; |
259 |
val->struniq = struniq_new (last_string); |
val->uniqstr = uniqstr_new (last_string); |
260 |
STRING_FREE; |
STRING_FREE; |
261 |
return TYPE; |
return TYPE; |
262 |
} |
} |
350 |
STRING_GROW; |
STRING_GROW; |
351 |
STRING_FINISH; |
STRING_FINISH; |
352 |
loc->start = token_start; |
loc->start = token_start; |
353 |
val->string = last_string; |
val->chars = last_string; |
354 |
rule_length++; |
rule_length++; |
355 |
BEGIN INITIAL; |
BEGIN INITIAL; |
356 |
return STRING; |
return STRING; |
397 |
if (UCHAR_MAX < c) |
if (UCHAR_MAX < c) |
398 |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
399 |
else |
else |
400 |
obstack_1grow (&string_obstack, c); |
obstack_1grow (&obstack_for_string, c); |
401 |
} |
} |
402 |
|
|
403 |
\\x[0-9abcdefABCDEF]+ { |
\\x[0-9abcdefABCDEF]+ { |
404 |
unsigned long c; |
unsigned long c; |
405 |
errno = 0; |
set_errno (0); |
406 |
c = strtoul (yytext + 2, 0, 16); |
c = strtoul (yytext + 2, 0, 16); |
407 |
if (UCHAR_MAX < c || errno) |
if (UCHAR_MAX < c || get_errno ()) |
408 |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
409 |
else |
else |
410 |
obstack_1grow (&string_obstack, c); |
obstack_1grow (&obstack_for_string, c); |
411 |
} |
} |
412 |
|
|
413 |
\\a obstack_1grow (&string_obstack, '\a'); |
\\a obstack_1grow (&obstack_for_string, '\a'); |
414 |
\\b obstack_1grow (&string_obstack, '\b'); |
\\b obstack_1grow (&obstack_for_string, '\b'); |
415 |
\\f obstack_1grow (&string_obstack, '\f'); |
\\f obstack_1grow (&obstack_for_string, '\f'); |
416 |
\\n obstack_1grow (&string_obstack, '\n'); |
\\n obstack_1grow (&obstack_for_string, '\n'); |
417 |
\\r obstack_1grow (&string_obstack, '\r'); |
\\r obstack_1grow (&obstack_for_string, '\r'); |
418 |
\\t obstack_1grow (&string_obstack, '\t'); |
\\t obstack_1grow (&obstack_for_string, '\t'); |
419 |
\\v obstack_1grow (&string_obstack, '\v'); |
\\v obstack_1grow (&obstack_for_string, '\v'); |
420 |
|
|
421 |
/* \\[\"\'?\\] would be shorter, but it confuses xgettext. */ |
/* \\[\"\'?\\] would be shorter, but it confuses xgettext. */ |
422 |
\\("\""|"'"|"?"|"\\") obstack_1grow (&string_obstack, yytext[1]); |
\\("\""|"'"|"?"|"\\") obstack_1grow (&obstack_for_string, yytext[1]); |
423 |
|
|
424 |
\\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} { |
\\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} { |
425 |
int c = convert_ucn_to_byte (yytext); |
int c = convert_ucn_to_byte (yytext); |
426 |
if (c < 0) |
if (c < 0) |
427 |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext)); |
428 |
else |
else |
429 |
obstack_1grow (&string_obstack, c); |
obstack_1grow (&obstack_for_string, c); |
430 |
} |
} |
431 |
\\(.|\n) { |
\\(.|\n) { |
432 |
complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext)); |
complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext)); |
509 |
{ |
{ |
510 |
STRING_FINISH; |
STRING_FINISH; |
511 |
loc->start = code_start; |
loc->start = code_start; |
512 |
val->string = last_string; |
val->chars = last_string; |
513 |
rule_length++; |
rule_length++; |
514 |
BEGIN INITIAL; |
BEGIN INITIAL; |
515 |
return BRACED_CODE; |
return BRACED_CODE; |
538 |
"%}" { |
"%}" { |
539 |
STRING_FINISH; |
STRING_FINISH; |
540 |
loc->start = code_start; |
loc->start = code_start; |
541 |
val->string = last_string; |
val->chars = last_string; |
542 |
BEGIN INITIAL; |
BEGIN INITIAL; |
543 |
return PROLOGUE; |
return PROLOGUE; |
544 |
} |
} |
557 |
<<EOF>> { |
<<EOF>> { |
558 |
STRING_FINISH; |
STRING_FINISH; |
559 |
loc->start = code_start; |
loc->start = code_start; |
560 |
val->string = last_string; |
val->chars = last_string; |
561 |
BEGIN INITIAL; |
BEGIN INITIAL; |
562 |
return EPILOGUE; |
return EPILOGUE; |
563 |
} |
} |
571 |
|
|
572 |
<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE> |
<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE> |
573 |
{ |
{ |
574 |
\$ obstack_sgrow (&string_obstack, "$]["); |
\$ obstack_sgrow (&obstack_for_string, "$]["); |
575 |
\@ obstack_sgrow (&string_obstack, "@@"); |
\@ obstack_sgrow (&obstack_for_string, "@@"); |
576 |
\[ obstack_sgrow (&string_obstack, "@{"); |
\[ obstack_sgrow (&obstack_for_string, "@{"); |
577 |
\] obstack_sgrow (&string_obstack, "@}"); |
\] obstack_sgrow (&obstack_for_string, "@}"); |
578 |
.|\n STRING_GROW; |
.|\n STRING_GROW; |
579 |
} |
} |
580 |
|
|
585 |
size SIZE. */ |
size SIZE. */ |
586 |
|
|
587 |
static void |
static void |
588 |
adjust_location (location_t *loc, char const *token, size_t size) |
adjust_location (location *loc, char const *token, size_t size) |
589 |
{ |
{ |
590 |
int line = scanner_cursor.line; |
int line = scanner_cursor.line; |
591 |
int column = scanner_cursor.column; |
int column = scanner_cursor.column; |
670 |
| | |
| | |
671 |
| Possible inputs: $[<TYPENAME>]($|integer) | |
| Possible inputs: $[<TYPENAME>]($|integer) | |
672 |
| | |
| | |
673 |
| Output to the STRING_OBSTACK a reference to this semantic value. | |
| Output to OBSTACK_FOR_STRING a reference to this semantic value. | |
674 |
`------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
675 |
|
|
676 |
static inline void |
static inline void |
677 |
handle_action_dollar (char *text, location_t location) |
handle_action_dollar (char *text, location loc) |
678 |
{ |
{ |
679 |
const char *type_name = NULL; |
const char *type_name = NULL; |
680 |
char *cp = text + 1; |
char *cp = text + 1; |
692 |
if (*cp == '$') |
if (*cp == '$') |
693 |
{ |
{ |
694 |
if (!type_name) |
if (!type_name) |
695 |
type_name = symbol_list_n_type_name_get (current_rule, location, 0); |
type_name = symbol_list_n_type_name_get (current_rule, loc, 0); |
696 |
if (!type_name && typed) |
if (!type_name && typed) |
697 |
complain_at (location, _("$$ of `%s' has no declared type"), |
complain_at (loc, _("$$ of `%s' has no declared type"), |
698 |
current_rule->sym->tag); |
current_rule->sym->tag); |
699 |
if (!type_name) |
if (!type_name) |
700 |
type_name = ""; |
type_name = ""; |
701 |
obstack_fgrow1 (&string_obstack, |
obstack_fgrow1 (&obstack_for_string, |
702 |
"]b4_lhs_value([%s])[", type_name); |
"]b4_lhs_value([%s])[", type_name); |
703 |
} |
} |
704 |
else |
else |
705 |
{ |
{ |
706 |
long num; |
long num; |
707 |
errno = 0; |
set_errno (0); |
708 |
num = strtol (cp, 0, 10); |
num = strtol (cp, 0, 10); |
709 |
|
|
710 |
if (INT_MIN <= num && num <= rule_length && ! errno) |
if (INT_MIN <= num && num <= rule_length && ! get_errno ()) |
711 |
{ |
{ |
712 |
int n = num; |
int n = num; |
713 |
if (!type_name && n > 0) |
if (!type_name && n > 0) |
714 |
type_name = symbol_list_n_type_name_get (current_rule, location, |
type_name = symbol_list_n_type_name_get (current_rule, loc, n); |
|
n); |
|
715 |
if (!type_name && typed) |
if (!type_name && typed) |
716 |
complain_at (location, _("$%d of `%s' has no declared type"), |
complain_at (loc, _("$%d of `%s' has no declared type"), |
717 |
n, current_rule->sym->tag); |
n, current_rule->sym->tag); |
718 |
if (!type_name) |
if (!type_name) |
719 |
type_name = ""; |
type_name = ""; |
720 |
obstack_fgrow3 (&string_obstack, |
obstack_fgrow3 (&obstack_for_string, |
721 |
"]b4_rhs_value([%d], [%d], [%s])[", |
"]b4_rhs_value([%d], [%d], [%s])[", |
722 |
rule_length, n, type_name); |
rule_length, n, type_name); |
723 |
} |
} |
724 |
else |
else |
725 |
complain_at (location, _("integer out of range: %s"), quote (text)); |
complain_at (loc, _("integer out of range: %s"), quote (text)); |
726 |
} |
} |
727 |
} |
} |
728 |
|
|
733 |
`---------------------------------------------------------------*/ |
`---------------------------------------------------------------*/ |
734 |
|
|
735 |
static inline void |
static inline void |
736 |
handle_symbol_code_dollar (char *text, location_t location) |
handle_symbol_code_dollar (char *text, location loc) |
737 |
{ |
{ |
738 |
char *cp = text + 1; |
char *cp = text + 1; |
739 |
if (*cp == '$') |
if (*cp == '$') |
740 |
obstack_sgrow (&string_obstack, "]b4_dollar_dollar["); |
obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar["); |
741 |
else |
else |
742 |
complain_at (location, _("invalid value: %s"), quote (text)); |
complain_at (loc, _("invalid value: %s"), quote (text)); |
743 |
} |
} |
744 |
|
|
745 |
|
|
749 |
`-----------------------------------------------------------------*/ |
`-----------------------------------------------------------------*/ |
750 |
|
|
751 |
static void |
static void |
752 |
handle_dollar (braced_code_t braced_code_kind, |
handle_dollar (braced_code braced_code_kind, char *text, location loc) |
|
char *text, location_t location) |
|
753 |
{ |
{ |
754 |
switch (braced_code_kind) |
switch (braced_code_kind) |
755 |
{ |
{ |
756 |
case action_braced_code: |
case action_braced_code: |
757 |
handle_action_dollar (text, location); |
handle_action_dollar (text, loc); |
758 |
break; |
break; |
759 |
|
|
760 |
case destructor_braced_code: |
case destructor_braced_code: |
761 |
case printer_braced_code: |
case printer_braced_code: |
762 |
handle_symbol_code_dollar (text, location); |
handle_symbol_code_dollar (text, loc); |
763 |
break; |
break; |
764 |
} |
} |
765 |
} |
} |
767 |
|
|
768 |
/*------------------------------------------------------. |
/*------------------------------------------------------. |
769 |
| TEXT is a location token (i.e., a `@...'). Output to | |
| TEXT is a location token (i.e., a `@...'). Output to | |
770 |
| STRING_OBSTACK a reference to this location. | |
| OBSTACK_FOR_STRING a reference to this location. | |
771 |
`------------------------------------------------------*/ |
`------------------------------------------------------*/ |
772 |
|
|
773 |
static inline void |
static inline void |
774 |
handle_action_at (char *text, location_t location) |
handle_action_at (char *text, location loc) |
775 |
{ |
{ |
776 |
char *cp = text + 1; |
char *cp = text + 1; |
777 |
locations_flag = 1; |
locations_flag = 1; |
778 |
|
|
779 |
if (*cp == '$') |
if (*cp == '$') |
780 |
{ |
{ |
781 |
obstack_sgrow (&string_obstack, "]b4_lhs_location["); |
obstack_sgrow (&obstack_for_string, "]b4_lhs_location["); |
782 |
} |
} |
783 |
else |
else |
784 |
{ |
{ |
785 |
long num; |
long num; |
786 |
errno = 0; |
set_errno (0); |
787 |
num = strtol (cp, 0, 10); |
num = strtol (cp, 0, 10); |
788 |
|
|
789 |
if (INT_MIN <= num && num <= rule_length && ! errno) |
if (INT_MIN <= num && num <= rule_length && ! get_errno ()) |
790 |
{ |
{ |
791 |
int n = num; |
int n = num; |
792 |
obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[", |
obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location([%d], [%d])[", |
793 |
rule_length, n); |
rule_length, n); |
794 |
} |
} |
795 |
else |
else |
796 |
complain_at (location, _("integer out of range: %s"), quote (text)); |
complain_at (loc, _("integer out of range: %s"), quote (text)); |
797 |
} |
} |
798 |
} |
} |
799 |
|
|
804 |
`---------------------------------------------------------------*/ |
`---------------------------------------------------------------*/ |
805 |
|
|
806 |
static inline void |
static inline void |
807 |
handle_symbol_code_at (char *text, location_t location) |
handle_symbol_code_at (char *text, location loc) |
808 |
{ |
{ |
809 |
char *cp = text + 1; |
char *cp = text + 1; |
810 |
if (*cp == '$') |
if (*cp == '$') |
811 |
obstack_sgrow (&string_obstack, "]b4_at_dollar["); |
obstack_sgrow (&obstack_for_string, "]b4_at_dollar["); |
812 |
else |
else |
813 |
complain_at (location, _("invalid value: %s"), quote (text)); |
complain_at (loc, _("invalid value: %s"), quote (text)); |
814 |
} |
} |
815 |
|
|
816 |
|
|
820 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
821 |
|
|
822 |
static void |
static void |
823 |
handle_at (braced_code_t braced_code_kind, |
handle_at (braced_code braced_code_kind, char *text, location loc) |
|
char *text, location_t location) |
|
824 |
{ |
{ |
825 |
switch (braced_code_kind) |
switch (braced_code_kind) |
826 |
{ |
{ |
827 |
case action_braced_code: |
case action_braced_code: |
828 |
handle_action_at (text, location); |
handle_action_at (text, loc); |
829 |
break; |
break; |
830 |
|
|
831 |
case destructor_braced_code: |
case destructor_braced_code: |
832 |
case printer_braced_code: |
case printer_braced_code: |
833 |
handle_symbol_code_at (text, location); |
handle_symbol_code_at (text, loc); |
834 |
break; |
break; |
835 |
} |
} |
836 |
} |
} |
920 |
{ |
{ |
921 |
size_t i = strlen (token_end); |
size_t i = strlen (token_end); |
922 |
|
|
923 |
location_t location; |
location loc; |
924 |
location.start = start; |
loc.start = start; |
925 |
location.end = scanner_cursor; |
loc.end = scanner_cursor; |
926 |
complain_at (location, _("missing `%s' at end of file"), token_end); |
complain_at (loc, _("missing `%s' at end of file"), token_end); |
927 |
|
|
928 |
/* Adjust scanner cursor so that any later message does not count |
/* Adjust scanner cursor so that any later message does not count |
929 |
the characters about to be inserted. */ |
the characters about to be inserted. */ |
941 |
void |
void |
942 |
scanner_initialize (void) |
scanner_initialize (void) |
943 |
{ |
{ |
944 |
obstack_init (&string_obstack); |
obstack_init (&obstack_for_string); |
945 |
} |
} |
946 |
|
|
947 |
|
|
952 |
void |
void |
953 |
scanner_free (void) |
scanner_free (void) |
954 |
{ |
{ |
955 |
obstack_free (&string_obstack, 0); |
obstack_free (&obstack_for_string, 0); |
956 |
/* Reclaim Flex's buffers. */ |
/* Reclaim Flex's buffers. */ |
957 |
yy_delete_buffer (YY_CURRENT_BUFFER); |
yy_delete_buffer (YY_CURRENT_BUFFER); |
958 |
} |
} |