a better fix
This commit is contained in:
parent
e2413da901
commit
b06f83e3ba
3 changed files with 110 additions and 142 deletions
|
@ -195,6 +195,12 @@ struct grub_lexer_param
|
|||
/* Type of text. */
|
||||
grub_script_arg_type_t type;
|
||||
|
||||
/* Flag to indicate resplit in progres. */
|
||||
unsigned resplit;
|
||||
|
||||
/* Text that is unput. */
|
||||
char *prefix;
|
||||
|
||||
/* Flex scanner. */
|
||||
void *yyscanner;
|
||||
|
||||
|
@ -284,7 +290,7 @@ void grub_script_lexer_ref (struct grub_lexer_param *);
|
|||
void grub_script_lexer_deref (struct grub_lexer_param *);
|
||||
void grub_script_lexer_record_start (struct grub_parser_param *);
|
||||
char *grub_script_lexer_record_stop (struct grub_parser_param *);
|
||||
int grub_script_lexer_yywrap (struct grub_parser_param *);
|
||||
int grub_script_lexer_yywrap (struct grub_parser_param *, const char *input);
|
||||
void grub_script_lexer_record (struct grub_parser_param *, char *);
|
||||
|
||||
/* Functions to track allocated memory. */
|
||||
|
|
126
script/lexer.c
126
script/lexer.c
|
@ -98,8 +98,6 @@ grub_script_lexer_record_stop (struct grub_parser_param *parser)
|
|||
return result;
|
||||
}
|
||||
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
|
||||
/* Record STR if input recording is enabled. */
|
||||
void
|
||||
grub_script_lexer_record (struct grub_parser_param *parser, char *str)
|
||||
|
@ -115,7 +113,7 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str)
|
|||
if (lexer->recordpos + len + 1 > lexer->recordlen)
|
||||
{
|
||||
old = lexer->recording;
|
||||
lexer->recordlen = MAX (len, lexer->recordlen) * 2;
|
||||
lexer->recordlen = grub_max (len, lexer->recordlen) * 2;
|
||||
lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
|
||||
if (!lexer->recording)
|
||||
{
|
||||
|
@ -131,76 +129,85 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str)
|
|||
lexer->recordpos += len;
|
||||
}
|
||||
|
||||
/* Append '\n' to SRC, before '\0' */
|
||||
static char *
|
||||
append_newline (const char *src)
|
||||
{
|
||||
char *line;
|
||||
grub_size_t len;
|
||||
|
||||
len = grub_strlen (src);
|
||||
line = grub_malloc (len + 2);
|
||||
if (!line)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (line, src);
|
||||
|
||||
line[len] = '\n';
|
||||
line[len + 1] = '\0';
|
||||
return line;
|
||||
}
|
||||
|
||||
/* Read next line of input if necessary, and set yyscanner buffers. */
|
||||
int
|
||||
grub_script_lexer_yywrap (struct grub_parser_param *parserstate)
|
||||
grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
|
||||
const char *input)
|
||||
{
|
||||
int len;
|
||||
char *line;
|
||||
char *line2;
|
||||
char *p = 0;
|
||||
char *line = 0;
|
||||
YY_BUFFER_STATE buffer;
|
||||
struct grub_lexer_param *lexerstate = parserstate->lexerstate;
|
||||
|
||||
if (!lexerstate->refs)
|
||||
return 0;
|
||||
if (! lexerstate->refs && ! lexerstate->prefix && ! input)
|
||||
return 1;
|
||||
|
||||
if (!lexerstate->getline)
|
||||
if (! lexerstate->getline && ! input)
|
||||
{
|
||||
grub_script_yyerror (parserstate, "unexpected end of file");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
line = 0;
|
||||
buffer = 0;
|
||||
lexerstate->getline (&line, 1);
|
||||
if (!line)
|
||||
if (! input)
|
||||
lexerstate->getline (&line, 1);
|
||||
else
|
||||
line = grub_strdup (input);
|
||||
if (! line)
|
||||
{
|
||||
grub_script_yyerror (parserstate, 0); /* XXX this could be for ^C case? */
|
||||
return 0;
|
||||
grub_script_yyerror (parserstate, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = grub_strlen (line);
|
||||
if (line[len - 1] == '\n')
|
||||
if (lexerstate->prefix)
|
||||
{
|
||||
buffer = yy_scan_string (line, lexerstate->yyscanner);
|
||||
}
|
||||
else
|
||||
{
|
||||
line2 = append_newline (line);
|
||||
if (line2)
|
||||
int plen = grub_strlen (lexerstate->prefix);
|
||||
|
||||
p = grub_malloc (len + plen + 2);
|
||||
if (! p)
|
||||
{
|
||||
buffer = yy_scan_string (line2, lexerstate->yyscanner);
|
||||
grub_free (line2);
|
||||
grub_free (line);
|
||||
return 1;
|
||||
}
|
||||
grub_strcpy (p, lexerstate->prefix);
|
||||
lexerstate->prefix = 0;
|
||||
|
||||
if (! line[0])
|
||||
{
|
||||
line = "\n";
|
||||
len = 1;
|
||||
}
|
||||
grub_strcpy (p + plen, line);
|
||||
|
||||
line = p;
|
||||
len = len + plen;
|
||||
}
|
||||
|
||||
if (line[len - 1] != '\n')
|
||||
{
|
||||
char *p;
|
||||
p = grub_realloc (line, len + 2);
|
||||
if (! p)
|
||||
{
|
||||
grub_free (line);
|
||||
return 1;
|
||||
}
|
||||
line = p;
|
||||
line[len++] = '\n';
|
||||
line[len] = '\0';
|
||||
}
|
||||
|
||||
buffer = yy_scan_string (line, lexerstate->yyscanner);
|
||||
grub_free (line);
|
||||
if (!buffer)
|
||||
|
||||
if (! buffer)
|
||||
{
|
||||
grub_script_yyerror (parserstate, 0);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_lexer_param *
|
||||
|
@ -231,35 +238,18 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script,
|
|||
grub_free (lexerstate);
|
||||
return 0;
|
||||
}
|
||||
yyset_extra (parser, lexerstate->yyscanner);
|
||||
parser->lexerstate = lexerstate;
|
||||
|
||||
buffer = 0;
|
||||
script = script ? : "\n";
|
||||
len = grub_strlen (script);
|
||||
|
||||
if (script[len - 1] == '\n')
|
||||
{
|
||||
buffer = yy_scan_string (script, lexerstate->yyscanner);
|
||||
}
|
||||
else
|
||||
{
|
||||
script2 = append_newline (script);
|
||||
if (script2)
|
||||
{
|
||||
buffer = yy_scan_string (script2, lexerstate->yyscanner);
|
||||
grub_free (script2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer)
|
||||
if (grub_script_lexer_yywrap (parser, script ?: "\n"))
|
||||
{
|
||||
parser->lexerstate = 0;
|
||||
yylex_destroy (lexerstate->yyscanner);
|
||||
grub_free (lexerstate->yyscanner);
|
||||
|
||||
grub_free (lexerstate->text);
|
||||
grub_free (lexerstate);
|
||||
return 0;
|
||||
}
|
||||
yyset_extra (parser, lexerstate->yyscanner);
|
||||
|
||||
return lexerstate;
|
||||
}
|
||||
|
|
118
script/yylex.l
118
script/yylex.l
|
@ -58,7 +58,9 @@
|
|||
#define YY_INPUT(buf,res,max) do { res = 0; } while (0)
|
||||
|
||||
/* forward declarations */
|
||||
static int resplit (const char *input, yyscan_t yyscanner);
|
||||
static int grub_lexer_unput (const char *input, yyscan_t yyscanner);
|
||||
static int grub_lexer_resplit (const char *input, yyscan_t yyscanner);
|
||||
|
||||
static void grub_lexer_yyfree (void *, yyscan_t yyscanner);
|
||||
static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner);
|
||||
static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner);
|
||||
|
@ -100,10 +102,9 @@ typedef size_t yy_size_t;
|
|||
%option never-interactive
|
||||
|
||||
%option noyyfree noyyalloc noyyrealloc
|
||||
%option nounistd nostdinit nodefault noyylineno noyywrap
|
||||
%option nounistd nostdinit nodefault noyylineno
|
||||
|
||||
/* Reduce lexer size, by not defining these. */
|
||||
%option noyy_top_state
|
||||
%option noinput nounput
|
||||
%option noyyget_in noyyset_in
|
||||
%option noyyget_out noyyset_out
|
||||
|
@ -120,20 +121,19 @@ DIGITS [[:digit:]]+
|
|||
NAME [[:alpha:]_][[:alnum:][:digit:]_]*
|
||||
|
||||
ESC \\.
|
||||
SQCHR [^\']
|
||||
DQCHR {ESC}|[^\"]
|
||||
DQSTR \"{DQCHR}*\"
|
||||
SQSTR \'{SQCHR}*\'
|
||||
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}
|
||||
DQSTR \"([^\"]|{ESC})*\"
|
||||
SQSTR \'([^\'])*\'
|
||||
WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
|
||||
|
||||
DQSTR2 {WORD}?\"({ESC}|[^\"])*\n
|
||||
SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
|
||||
MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*))
|
||||
|
||||
%x SPLIT
|
||||
%x DQUOTE
|
||||
%x SQUOTE
|
||||
%x VAR
|
||||
%x DQMULTILINE
|
||||
%x SQMULTILINE
|
||||
|
||||
%%
|
||||
|
||||
|
@ -179,55 +179,22 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
|
|||
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
|
||||
{WORD} {
|
||||
RECORD;
|
||||
yyextra->lexerstate->resplit = 1;
|
||||
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
|
||||
if (resplit (yytext, yyscanner))
|
||||
if (grub_lexer_resplit (yytext, yyscanner))
|
||||
{
|
||||
yypop_buffer_state (yyscanner);
|
||||
return GRUB_PARSER_TOKEN_WORD;
|
||||
}
|
||||
}
|
||||
{DQSTR2} {
|
||||
yy_push_state (DQMULTILINE, yyscanner);
|
||||
grub_script_lexer_ref (yyextra->lexerstate);
|
||||
yymore ();
|
||||
{MULTILINE} {
|
||||
if (grub_lexer_unput (yytext, yyscanner))
|
||||
return GRUB_PARSER_TOKEN_BAD;
|
||||
}
|
||||
. {
|
||||
grub_script_yyerror (yyextra, yytext);
|
||||
return GRUB_PARSER_TOKEN_BAD;
|
||||
}
|
||||
<DQMULTILINE>{
|
||||
\"{WORD}? {
|
||||
RECORD;
|
||||
grub_script_lexer_deref (yyextra->lexerstate);
|
||||
yy_pop_state (yyscanner);
|
||||
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
|
||||
if (resplit (yytext, yyscanner))
|
||||
{
|
||||
yypop_buffer_state (yyscanner);
|
||||
return GRUB_PARSER_TOKEN_WORD;
|
||||
}
|
||||
}
|
||||
{ESC} { yymore(); }
|
||||
[^\"] { yymore(); }
|
||||
}
|
||||
|
||||
{SQSTR2} {
|
||||
yy_push_state (SQMULTILINE, yyscanner);
|
||||
grub_script_lexer_ref (yyextra->lexerstate);
|
||||
yymore ();
|
||||
}
|
||||
|
||||
<SQMULTILINE>{
|
||||
\'{WORD}? {
|
||||
RECORD;
|
||||
grub_script_lexer_deref (yyextra->lexerstate);
|
||||
yy_pop_state (yyscanner);
|
||||
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
|
||||
if (resplit (yytext, yyscanner))
|
||||
{
|
||||
yypop_buffer_state (yyscanner);
|
||||
return GRUB_PARSER_TOKEN_WORD;
|
||||
}
|
||||
}
|
||||
{ESC} { yymore(); }
|
||||
[^\'] { yymore(); }
|
||||
}
|
||||
|
||||
/* Split word into multiple args */
|
||||
|
||||
|
@ -250,6 +217,7 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
|
|||
<<EOF>> {
|
||||
yy_pop_state (yyscanner);
|
||||
yypop_buffer_state (yyscanner);
|
||||
yyextra->lexerstate->resplit = 0;
|
||||
yyextra->lexerstate->merge_end = 1;
|
||||
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
|
||||
}
|
||||
|
@ -305,37 +273,21 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
|
|||
(.|\n) { COPY (yytext, yyleng); }
|
||||
}
|
||||
|
||||
. { /* ignore */ }
|
||||
<<EOF>> {
|
||||
yypop_buffer_state (yyscanner);
|
||||
if (! grub_script_lexer_yywrap (yyextra))
|
||||
{
|
||||
yyextra->lexerstate->eof = 1;
|
||||
return GRUB_PARSER_TOKEN_EOF;
|
||||
}
|
||||
yyextra->lexerstate->eof = 1;
|
||||
return GRUB_PARSER_TOKEN_EOF;
|
||||
}
|
||||
%%
|
||||
|
||||
#if 0
|
||||
int
|
||||
yywrap (yyscan_t yyscanner)
|
||||
{
|
||||
char *line = 0;
|
||||
struct grub_lexer_param *lexerstate = yyget_extra(yyscanner)->lexerstate;
|
||||
if (yyget_extra (yyscanner)->lexerstate->resplit)
|
||||
return 1;
|
||||
|
||||
grub_printf ("yywrap\n");
|
||||
if (lexerstate->getline)
|
||||
{
|
||||
lexerstate->getline (&line, 1);
|
||||
if (! line)
|
||||
return 1;
|
||||
|
||||
yy_scan_string (line, yyscanner);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return grub_script_lexer_yywrap (yyget_extra (yyscanner), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused)))
|
||||
|
@ -381,7 +333,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi
|
|||
}
|
||||
|
||||
static int
|
||||
resplit (const char *text, yyscan_t yyscanner)
|
||||
grub_lexer_resplit (const char *text, yyscan_t yyscanner)
|
||||
{
|
||||
/* resplit text */
|
||||
if (yy_scan_string (text, yyscanner))
|
||||
|
@ -393,3 +345,23 @@ resplit (const char *text, yyscan_t yyscanner)
|
|||
grub_script_yyerror (yyget_extra (yyscanner), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_lexer_unput (const char *text, yyscan_t yyscanner)
|
||||
{
|
||||
struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate;
|
||||
|
||||
if (lexerstate->prefix)
|
||||
{
|
||||
grub_free (lexerstate->prefix);
|
||||
lexerstate->prefix = 0;
|
||||
}
|
||||
|
||||
lexerstate->prefix = grub_strdup (text);
|
||||
if (! lexerstate->prefix)
|
||||
{
|
||||
grub_script_yyerror (yyget_extra (yyscanner), "out of memory");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue