This commit is contained in:
Akim Demaille
2020-06-13 10:47:12 +02:00
parent 5855da4722
commit e4d33cf579
2 changed files with 177 additions and 44 deletions

View File

@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.3.74-5ca2. */ /* A Bison parser, made by GNU Bison 3.6.3.87-3efc5-dirty. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -49,7 +49,7 @@
#define YYBISON 1 #define YYBISON 1
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "3.6.3.74-5ca2" #define YYBISON_VERSION "3.6.3.87-3efc5-dirty"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -257,17 +257,20 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
static char *strip_braces (char *code); static char *strip_braces (char *code);
/* Convert CODE by calling code_props_plain_init if PLAIN, otherwise /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise
code_props_symbol_action_init. Call code_props_symbol_action_init. Calls
gram_scanner_last_string_free to release the latest string from gram_scanner_last_string_free to release the latest string from
the scanner (should be CODE). */ the scanner (should be CODE). */
static char const *translate_code (char *code, location loc, bool plain); static char const *translate_code (char *code, location loc, bool plain);
/* Convert CODE by calling code_props_plain_init after having /* Convert CODE by calling code_props_plain_init after having
stripped the first and last characters (expected to be '{', and stripped the first and last characters (expected to be '{', and
'}'). Call gram_scanner_last_string_free to release the latest '}'). Calls gram_scanner_last_string_free to release the latest
string from the scanner (should be CODE). */ string from the scanner (should be CODE). */
static char const *translate_code_braceless (char *code, location loc); static char const *translate_code_braceless (char *code, location loc);
/* Handle a %defines directive. */
static void handle_defines (char const *value);
/* Handle a %error-verbose directive. */ /* Handle a %error-verbose directive. */
static void handle_error_verbose (location const *loc, char const *directive); static void handle_error_verbose (location const *loc, char const *directive);
@@ -276,6 +279,9 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
location const *dir_loc, location const *dir_loc,
char const *directive, char const *value); char const *directive, char const *value);
/* Handle a %language directive. */
static void handle_language (location const *loc, char const *lang);
/* Handle a %name-prefix directive. */ /* Handle a %name-prefix directive. */
static void handle_name_prefix (location const *loc, static void handle_name_prefix (location const *loc,
char const *directive, char const *value); char const *directive, char const *value);
@@ -302,6 +308,13 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
static void tron (FILE *yyo); static void tron (FILE *yyo);
static void troff (FILE *yyo); static void troff (FILE *yyo);
/* Interpret a quoted string (such as `"Hello, \"World\"\n\""`).
Manages the memory of the result. */
static char *unquote (const char *str);
/* Discard the latest unquoted string. */
static void unquote_free (char *last_string);
/** Add a lex-param and/or a parse-param. /** Add a lex-param and/or a parse-param.
* *
* \param type where to push this formal argument. * \param type where to push this formal argument.
@@ -621,19 +634,19 @@ union yyalloc
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] = static const yytype_int16 yyrline[] =
{ {
0, 287, 287, 296, 297, 301, 302, 308, 312, 317, 0, 308, 308, 317, 318, 322, 323, 329, 333, 338,
318, 323, 324, 325, 326, 327, 332, 337, 338, 339, 339, 340, 341, 342, 343, 344, 349, 354, 355, 356,
340, 341, 342, 342, 343, 344, 345, 346, 347, 348, 357, 358, 359, 359, 360, 361, 362, 363, 364, 365,
349, 350, 354, 355, 364, 365, 369, 380, 384, 388, 366, 367, 371, 372, 381, 382, 386, 397, 401, 405,
396, 406, 407, 417, 418, 424, 437, 437, 442, 442, 413, 423, 424, 434, 435, 441, 454, 454, 459, 459,
447, 451, 461, 462, 463, 464, 468, 469, 474, 475, 464, 468, 478, 479, 480, 481, 485, 486, 491, 492,
479, 480, 484, 485, 486, 499, 508, 512, 516, 524, 496, 497, 501, 502, 503, 516, 525, 529, 533, 541,
525, 529, 542, 543, 548, 549, 550, 568, 572, 576, 542, 546, 559, 560, 565, 566, 567, 585, 589, 593,
584, 586, 591, 598, 608, 612, 616, 624, 629, 641, 601, 603, 608, 615, 625, 629, 633, 641, 646, 658,
642, 648, 649, 650, 657, 657, 665, 666, 667, 672, 659, 665, 666, 667, 674, 674, 682, 683, 684, 689,
675, 677, 679, 681, 683, 685, 687, 689, 691, 696, 692, 694, 696, 698, 700, 702, 704, 706, 708, 713,
697, 706, 730, 731, 732, 733, 745, 747, 771, 776, 714, 723, 747, 748, 749, 750, 762, 764, 788, 793,
777, 782, 790, 791 794, 799, 807, 808
}; };
#endif #endif
@@ -2081,10 +2094,7 @@ yyreduce:
break; break;
case 10: /* prologue_declaration: "%defines" "string" */ case 10: /* prologue_declaration: "%defines" "string" */
{ { handle_defines ((yyvsp[0].STRING)); }
defines_flag = true;
spec_header_file = xstrdup ((yyvsp[0].STRING));
}
break; break;
case 11: /* prologue_declaration: "%error-verbose" */ case 11: /* prologue_declaration: "%error-verbose" */
@@ -2118,7 +2128,7 @@ yyreduce:
break; break;
case 17: /* prologue_declaration: "%language" "string" */ case 17: /* prologue_declaration: "%language" "string" */
{ language_argmatch ((yyvsp[0].STRING), grammar_prio, (yylsp[-1])); } { handle_language (&(yylsp[-1]), (yyvsp[0].STRING)); }
break; break;
case 18: /* prologue_declaration: "%name-prefix" "string" */ case 18: /* prologue_declaration: "%name-prefix" "string" */
@@ -2134,7 +2144,7 @@ yyreduce:
break; break;
case 21: /* prologue_declaration: "%output" "string" */ case 21: /* prologue_declaration: "%output" "string" */
{ spec_outfile = (yyvsp[0].STRING); } { spec_outfile = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free (); }
break; break;
case 22: /* $@1: %empty */ case 22: /* $@1: %empty */
@@ -2387,7 +2397,7 @@ yyreduce:
case 76: /* alias: "translatable string" */ case 76: /* alias: "translatable string" */
{ {
(yyval.alias) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].TSTRING)), (yylsp[0])); (yyval.alias) = symbol_get ((yyvsp[0].TSTRING), (yylsp[0]));
symbol_class_set ((yyval.alias), token_sym, (yylsp[0]), false); symbol_class_set ((yyval.alias), token_sym, (yylsp[0]), false);
(yyval.alias)->translatable = true; (yyval.alias)->translatable = true;
} }
@@ -2543,11 +2553,11 @@ yyreduce:
break; break;
case 114: /* value: "string" */ case 114: /* value: "string" */
{ (yyval.value).kind = muscle_string; (yyval.value).chars = (yyvsp[0].STRING); } { (yyval.value).kind = muscle_string; (yyval.value).chars = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free ();}
break; break;
case 115: /* value: "{...}" */ case 115: /* value: "{...}" */
{ (yyval.value).kind = muscle_code; (yyval.value).chars = strip_braces ((yyvsp[0].BRACED_CODE)); } { (yyval.value).kind = muscle_code; (yyval.value).chars = strip_braces ((yyvsp[0].BRACED_CODE)); gram_scanner_last_string_free (); }
break; break;
case 116: /* id: "identifier" */ case 116: /* id: "identifier" */
@@ -2583,7 +2593,7 @@ yyreduce:
case 121: /* string_as_id: "string" */ case 121: /* string_as_id: "string" */
{ {
(yyval.string_as_id) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].STRING)), (yylsp[0])); (yyval.string_as_id) = symbol_get ((yyvsp[0].STRING), (yylsp[0]));
symbol_class_set ((yyval.string_as_id), token_sym, (yylsp[0]), false); symbol_class_set ((yyval.string_as_id), token_sym, (yylsp[0]), false);
} }
break; break;
@@ -2940,6 +2950,17 @@ add_param (param_type type, char *decl, location loc)
} }
static void
handle_defines (char const *value)
{
defines_flag = true;
char *file = unquote (value);
spec_header_file = xstrdup (file);
gram_scanner_last_string_free ();
unquote_free (file);
}
static void static void
handle_error_verbose (location const *loc, char const *directive) handle_error_verbose (location const *loc, char const *directive)
{ {
@@ -2952,8 +2973,9 @@ handle_error_verbose (location const *loc, char const *directive)
static void static void
handle_file_prefix (location const *loc, handle_file_prefix (location const *loc,
location const *dir_loc, location const *dir_loc,
char const *directive, char const *value) char const *directive, char const *value_quoted)
{ {
char *value = unquote (value_quoted);
bison_directive (loc, directive); bison_directive (loc, directive);
bool warned = false; bool warned = false;
@@ -2973,11 +2995,18 @@ handle_file_prefix (location const *loc,
deprecated_directive (dir_loc, directive, "%file-prefix"); deprecated_directive (dir_loc, directive, "%file-prefix");
} }
static void
handle_language (location const *loc, char const *lang)
{
language_argmatch (unquote (lang), grammar_prio, *loc);
}
static void static void
handle_name_prefix (location const *loc, handle_name_prefix (location const *loc,
char const *directive, char const *value) char const *directive, char const *value_quoted)
{ {
char *value = unquote (value_quoted);
bison_directive (loc, directive); bison_directive (loc, directive);
char buf1[1024]; char buf1[1024];
@@ -3049,34 +3078,39 @@ str_to_version (char const *version)
static void static void
handle_require (location const *loc, char const *version) handle_require (location const *loc, char const *version_quoted)
{ {
char *version = unquote (version_quoted);
required_version = str_to_version (version); required_version = str_to_version (version);
if (required_version == -1) if (required_version == -1)
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),
version); version);
required_version = 0; required_version = 0;
return;
} }
else
/* Pretend to be at least that version, to check features published
in that version while developping it. */
const char* api_version = "3.6";
const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION;
if (0 < strverscmp (version, package_version))
{ {
complain (loc, complaint, _("require bison %s, but have %s"), /* Pretend to be at least that version, to check features published
version, package_version); in that version while developping it. */
exit (EX_MISMATCH); const char* api_version = "3.6";
const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION;
if (0 < strverscmp (version, package_version))
{
complain (loc, complaint, _("require bison %s, but have %s"),
version, package_version);
exit (EX_MISMATCH);
}
} }
unquote_free (version);
gram_scanner_last_string_free ();
} }
static void static void
handle_skeleton (location const *loc, char const *skel) handle_skeleton (location const *loc, char const *skel_quoted)
{ {
char *skel = unquote (skel_quoted);
char const *skeleton_user = skel; char const *skeleton_user = skel;
if (strchr (skeleton_user, '/')) if (strchr (skeleton_user, '/'))
{ {
@@ -3157,3 +3191,95 @@ static void troff (FILE *yyo)
{ {
end_use_class ("value", yyo); end_use_class ("value", yyo);
} }
/*----------.
| Unquote. |
`----------*/
struct obstack obstack_for_unquote;
void
parser_init (void)
{
obstack_init (&obstack_for_unquote);
}
void
parser_free (void)
{
obstack_free (&obstack_for_unquote, 0);
}
static void
unquote_free (char *last_string)
{
obstack_free (&obstack_for_unquote, last_string);
}
static char *
unquote (const char *cp)
{
#define GROW(Char) \
obstack_1grow (&obstack_for_unquote, Char);
for (++cp; *cp && *cp != '"'; ++cp)
switch (*cp)
{
case '"':
break;
case '\\':
++cp;
switch (*cp)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
int c = cp[0] - '0';
if (c_isdigit (cp[1]))
{
++cp;
c = c * 8 + cp[0] - '0';
}
if (c_isdigit (cp[1]))
{
++cp;
c = c * 8 + cp[0] - '0';
}
GROW (c);
}
break;
case 'a': GROW ('\a'); break;
case 'b': GROW ('\b'); break;
case 'f': GROW ('\f'); break;
case 'n': GROW ('\n'); break;
case 'r': GROW ('\r'); break;
case 't': GROW ('\t'); break;
case 'v': GROW ('\v'); break;
case 'x':
{
int c = 0;
while (c_isxdigit (cp[1]))
{
++cp;
c = (c * 16 + (c_isdigit (cp[0]) ? cp[0] - '0'
: c_isupper (cp[0]) ? cp[0] - 'A'
: cp[0] - '0'));
}
GROW (c);
break;
}
}
break;
default:
GROW (*cp);
break;
}
assert (*cp == '"');
++cp;
assert (*cp == '\0');
#undef GROW
return obstack_finish0 (&obstack_for_unquote);
}

View File

@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.3.74-5ca2. */ /* A Bison parser, made by GNU Bison 3.6.3.87-3efc5-dirty. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -215,5 +215,12 @@ struct GRAM_LTYPE
int gram_parse (void); int gram_parse (void);
/* "%code provides" blocks. */
/* Initialize unquote. */
void parser_init (void);
/* Deallocate storage for unquote. */
void parser_free (void);
#endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED */ #endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED */