merge with mainline

This commit is contained in:
BVK Chaitanya 2010-09-04 14:41:08 +05:30
commit cd652829a1
61 changed files with 872 additions and 345 deletions

View file

@ -18,6 +18,7 @@
*/
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/script_sh.h>
/* Return nearest power of two that is >= v. */
@ -55,6 +56,7 @@ grub_script_argv_free (struct grub_script_argv *argv)
argv->argc = 0;
argv->args = 0;
argv->script = 0;
}
/* Prepare for next argc. */
@ -63,7 +65,7 @@ grub_script_argv_next (struct grub_script_argv *argv)
{
char **p = argv->args;
if (argv->args && argv->args[argv->argc - 1] == 0)
if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0)
return 0;
p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *)));

View file

@ -25,6 +25,7 @@
#include <grub/menu.h>
#include <grub/lib/arg.h>
#include <grub/normal.h>
#include <grub/extcmd.h>
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it
is sizeof (int) * 3, and one extra for a possible -ve sign. */
@ -129,7 +130,7 @@ grub_env_special (const char *name)
static char **
grub_script_env_get (const char *name, grub_script_arg_type_t type)
{
struct grub_script_argv result = { 0, 0 };
struct grub_script_argv result = { 0, 0, 0 };
if (grub_script_argv_next (&result))
goto fail;
@ -247,7 +248,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
int i;
char **values = 0;
struct grub_script_arg *arg = 0;
struct grub_script_argv result = { 0, 0 };
struct grub_script_argv result = { 0, 0, 0 };
for (; arglist && arglist->arg; arglist = arglist->next)
{
@ -273,6 +274,14 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
grub_free (values);
break;
case GRUB_SCRIPT_ARG_TYPE_BLOCK:
if (grub_script_argv_append (&result, "{") ||
grub_script_argv_append (&result, arg->str) ||
grub_script_argv_append (&result, "}"))
goto fail;
result.script = arg->script;
break;
case GRUB_SCRIPT_ARG_TYPE_TEXT:
if (grub_strlen (arg->str) &&
grub_script_argv_append (&result, arg->str))
@ -351,7 +360,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
grub_script_function_t func = 0;
char errnobuf[18];
char *cmdname;
struct grub_script_argv argv = { 0, 0 };
struct grub_script_argv argv = { 0, 0, 0 };
/* Lookup the command. */
if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
@ -395,7 +404,14 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
/* Execute the GRUB command or function. */
if (grubcmd)
ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1);
{
if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) &&
(grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD))
ret = grub_extcmd_dispatcher (grubcmd, argv.argc - 1, argv.args + 1,
argv.script);
else
ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1);
}
else
ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1);
@ -466,8 +482,7 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
{
unsigned i;
grub_err_t result;
struct grub_script_argv argv = { 0, 0 };
struct grub_script_argv argv = { 0, 0, 0 };
struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd;
if (grub_script_arglist_to_argv (cmdfor->words, &argv))
@ -537,7 +552,7 @@ grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
{
struct grub_script_cmd_menuentry *cmd_menuentry;
struct grub_script_argv argv = { 0, 0 };
struct grub_script_argv argv = { 0, 0, 0 };
cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;

View file

@ -38,68 +38,57 @@ grub_script_lexer_deref (struct grub_lexer_param *state)
}
/* Start recording all characters passing through the lexer. */
void
unsigned
grub_script_lexer_record_start (struct grub_parser_param *parser)
{
struct grub_lexer_param *lexer = parser->lexerstate;
lexer->record = 1;
lexer->recordpos = 0;
if (lexer->recording) /* reuse last record */
return;
lexer->record++;
if (lexer->recording)
return lexer->recordpos;
lexer->recordpos = 0;
lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE;
lexer->recording = grub_malloc (lexer->recordlen);
if (!lexer->recording)
{
grub_script_yyerror (parser, 0);
lexer->record = 0;
lexer->recordlen = 0;
}
return lexer->recordpos;
}
char *
grub_script_lexer_record_stop (struct grub_parser_param *parser)
grub_script_lexer_record_stop (struct grub_parser_param *parser, unsigned offset)
{
char *ptr;
int count;
char *result;
struct grub_lexer_param *lexer = parser->lexerstate;
auto char *compact (char *start, char *end);
char *compact (char *start, char *end)
{
/* Delete '{' and '}' characters and whitespaces. */
while (*start && grub_isspace (*start)) start++;
if (*start == '{') start++;
while (*start && grub_isspace (*start)) start++;
while (*end && grub_isspace (*end)) end--;
if (*end == '}') end--;
while (*end && grub_isspace (*end)) end--;
end[1] = '\0';
return start;
}
if (!lexer->record || !lexer->recording)
if (!lexer->record)
return 0;
/* XXX This is not necessary in BASH. */
lexer->record--;
if (!lexer->recording)
return 0;
ptr = compact (lexer->recording, lexer->recording + lexer->recordpos - 1);
lexer->record = 0;
lexer->recordpos = 0;
/* This memory would be freed by, grub_script_free. */
result = grub_script_malloc (parser, grub_strlen (ptr) + 1);
if (result)
grub_strcpy (result, ptr);
count = lexer->recordpos - offset;
result = grub_script_malloc (parser, count + 1);
if (result) {
grub_strncpy (result, lexer->recording + offset, count);
result[count] = '\0';
}
if (lexer->record == 0)
{
grub_free (lexer->recording);
lexer->recording = 0;
lexer->recordlen = 0;
lexer->recordpos = 0;
}
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)
@ -108,21 +97,20 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str)
char *old;
struct grub_lexer_param *lexer = parser->lexerstate;
if (!lexer->record)
if (!lexer->record || !lexer->recording)
return;
len = grub_strlen (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)
{
grub_free (old);
lexer->record = 0;
lexer->recordpos = 0;
lexer->recordlen /= 2;
lexer->recordlen = 0;
grub_script_yyerror (parser, 0);
return;
}
@ -131,76 +119,86 @@ 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)
{
grub_script_yyerror (parserstate, 0); /* XXX this could be for ^C case? */
return 0;
}
len = grub_strlen (line);
if (line[len - 1] == '\n')
{
buffer = yy_scan_string (line, lexerstate->yyscanner);
}
if (! input)
lexerstate->getline (&line, 1);
else
line = grub_strdup (input);
/* Ensure '\n' at the end. */
if (line && line[0] == '\0')
{
line2 = append_newline (line);
if (line2)
{
buffer = yy_scan_string (line2, lexerstate->yyscanner);
grub_free (line2);
}
grub_free (line);
line = grub_strdup ("\n");
}
if (line && (len = grub_strlen(line)) && line[len - 1] != '\n')
{
p = grub_realloc (line, len + 2);
if (p)
{
p[len++] = '\n';
p[len] = '\0';
}
line = p;
}
if (! line)
{
grub_script_yyerror (parserstate, "out of memory");
return 1;
}
/* Prepend any left over unput-text. */
if (lexerstate->prefix)
{
int plen = grub_strlen (lexerstate->prefix);
p = grub_malloc (len + plen + 1);
if (! p)
{
grub_free (line);
return 1;
}
grub_strcpy (p, lexerstate->prefix);
lexerstate->prefix = 0;
grub_strcpy (p + plen, line);
grub_free (line);
line = p;
len = len + plen;
}
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 *
@ -208,7 +206,6 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script,
grub_reader_getline_t getline)
{
int len;
char *script2;
YY_BUFFER_STATE buffer;
struct grub_lexer_param *lexerstate;
@ -232,34 +229,18 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script,
return 0;
}
buffer = 0;
script = script ? : "\n";
len = grub_strlen (script);
yyset_extra (parser, lexerstate->yyscanner);
parser->lexerstate = lexerstate;
if (len != 0 && 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;
}

View file

@ -35,7 +35,7 @@ grub_normal_parse_line (char *line, grub_reader_getline_t getline)
grub_script_execute (parsed_script);
/* The parsed script was executed, throw it away. */
grub_script_free (parsed_script);
grub_script_unref (parsed_script);
}
return grub_errno;

View file

@ -20,6 +20,7 @@
%{
#include <grub/script_sh.h>
#include <grub/mm.h>
#include <grub/misc.h>
#define YYFREE grub_free
#define YYMALLOC grub_malloc
@ -34,6 +35,11 @@
struct grub_script_arglist *arglist;
struct grub_script_arg *arg;
char *string;
struct {
unsigned offset;
struct grub_script_mem *memory;
struct grub_script *scripts;
};
}
%token GRUB_PARSER_TOKEN_BAD
@ -74,6 +80,7 @@
%token <arg> GRUB_PARSER_TOKEN_NAME "name"
%token <arg> GRUB_PARSER_TOKEN_WORD "word"
%type <arg> block block0
%type <arglist> word argument arguments0 arguments1
%type <cmd> script_init script
@ -146,6 +153,74 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); }
| word { $$ = $1; }
;
/*
Block parameter is passed to commands in two forms: as unparsed
string and as pre-parsed grub_script object. Passing as grub_script
object makes memory management difficult, because:
(1) Command may want to keep a reference to grub_script objects for
later use, so script framework may not free the grub_script
object after command completes.
(2) Command may get called multiple times with same grub_script
object under loops, so we should not let command implementation
to free the grub_script object.
To solve above problems, we rely on reference counting for
grub_script objects. Commands that want to keep the grub_script
object must take a reference to it.
Other complexity comes with arbitrary nesting of grub_script
objects: a grub_script object may have commands with several block
parameters, and each block parameter may further contain multiple
block parameters nested. We use temporary variable, state->scripts
to collect nested child scripts (that are linked by siblings and
children members), and will build grub_scripts tree from bottom.
*/
block: "{"
{
grub_script_lexer_ref (state->lexerstate);
$<offset>$ = grub_script_lexer_record_start (state);
$<memory>$ = grub_script_mem_record (state);
/* save currently known scripts. */
$<scripts>$ = state->scripts;
state->scripts = 0;
}
commands1 delimiters0 "}"
{
char *p;
struct grub_script_mem *memory;
struct grub_script *s = $<scripts>2;
memory = grub_script_mem_record_stop (state, $<memory>2);
if ((p = grub_script_lexer_record_stop (state, $<offset>2)))
*grub_strrchr (p, '}') = '\0';
$$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p);
if (! $$ || ! ($$->script = grub_script_create ($3, memory)))
grub_script_mem_free (memory);
else {
/* attach nested scripts to $$->script as children */
$$->script->children = state->scripts;
/* restore old scripts; append $$->script to siblings. */
state->scripts = $<scripts>2 ?: $$->script;
if (s) {
while (s->next_siblings)
s = s->next_siblings;
s->next_siblings = $$->script;
}
}
grub_script_lexer_deref (state->lexerstate);
}
;
block0: /* Empty */ { $$ = 0; }
| block { $$ = $1; }
;
arguments0: /* Empty */ { $$ = 0; }
| arguments1 { $$ = $1; }
;
@ -161,13 +236,19 @@ arguments1: argument arguments0
}
;
grubcmd: word arguments0
grubcmd: word arguments0 block0
{
if ($1 && $2) {
$1->next = $2;
$1->argcount += $2->argcount;
$2->argcount = 0;
}
struct grub_script_arglist *x = $2;
if ($3)
x = grub_script_add_arglist (state, $2, $3);
if ($1 && x)
{
$1->next = x;
$1->argcount += x->argcount;
x->argcount = 0;
}
$$ = grub_script_create_cmdline (state, $1);
}
;
@ -191,10 +272,13 @@ commands1: newlines0 command
}
;
function: "function" "name"
function: "function" "name"
{
grub_script_lexer_ref (state->lexerstate);
state->func_mem = grub_script_mem_record (state);
$<scripts>$ = state->scripts;
state->scripts = 0;
}
delimiters0 "{" commands1 delimiters1 "}"
{
@ -202,9 +286,14 @@ function: "function" "name"
state->func_mem = grub_script_mem_record_stop (state,
state->func_mem);
script = grub_script_create ($6, state->func_mem);
if (script)
grub_script_function_create ($2, script);
if (! script)
grub_script_mem_free (state->func_mem);
else {
script->children = state->scripts;
grub_script_function_create ($2, script);
}
state->scripts = $<scripts>3;
grub_script_lexer_deref (state->lexerstate);
}
;
@ -215,14 +304,16 @@ menuentry: "menuentry"
}
arguments1
{
grub_script_lexer_record_start (state);
$<offset>$ = grub_script_lexer_record_start (state);
}
delimiters0 "{" commands1 delimiters1 "}"
{
char *menu_entry;
menu_entry = grub_script_lexer_record_stop (state);
char *def;
def = grub_script_lexer_record_stop (state, $<offset>4);
*grub_strrchr(def, '}') = '\0';
grub_script_lexer_deref (state->lexerstate);
$$ = grub_script_create_cmdmenu (state, $3, menu_entry, 0);
$$ = grub_script_create_cmdmenu (state, $3, def, 0);
}
;

View file

@ -54,7 +54,7 @@ grub_script_malloc (struct grub_parser_param *state, grub_size_t size)
}
/* Free all memory described by MEM. */
static void
void
grub_script_mem_free (struct grub_script_mem *mem)
{
struct grub_script_mem *memfree;
@ -94,9 +94,21 @@ grub_script_mem_record_stop (struct grub_parser_param *state,
void
grub_script_free (struct grub_script *script)
{
if (!script)
struct grub_script *s;
struct grub_script *t;
if (! script)
return;
grub_script_mem_free (script->mem);
if (script->mem)
grub_script_mem_free (script->mem);
s = script->children;
while (s) {
t = s->next_siblings;
grub_script_unref (s);
s = t;
}
grub_free (script);
}
@ -119,6 +131,8 @@ grub_script_arg_add (struct grub_parser_param *state,
return arg;
argpart->type = type;
argpart->script = 0;
len = grub_strlen (str) + 1;
argpart->str = grub_script_malloc (state, len);
if (!argpart->str)
@ -335,16 +349,14 @@ grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem)
struct grub_script *parsed;
parsed = grub_malloc (sizeof (*parsed));
if (!parsed)
{
grub_script_mem_free (mem);
grub_free (cmd);
return 0;
}
if (! parsed)
return 0;
parsed->mem = mem;
parsed->cmd = cmd;
parsed->refcnt = 0;
parsed->children = 0;
parsed->next_siblings = 0;
return parsed;
}
@ -359,7 +371,7 @@ grub_script_parse (char *script, grub_reader_getline_t getline)
struct grub_lexer_param *lexstate;
struct grub_parser_param *parsestate;
parsed = grub_malloc (sizeof (*parsed));
parsed = grub_script_create (0, 0);
if (!parsed)
return 0;
@ -397,6 +409,7 @@ grub_script_parse (char *script, grub_reader_getline_t getline)
parsed->mem = grub_script_mem_record_stop (parsestate, membackup);
parsed->cmd = parsestate->parsed;
parsed->children = parsestate->scripts;
grub_script_lexer_fini (lexstate);
grub_free (parsestate);

View file

@ -58,6 +58,9 @@
#define YY_INPUT(buf,res,max) do { res = 0; } while (0)
/* forward declarations */
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);
@ -99,7 +102,7 @@ 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
@ -118,13 +121,17 @@ CHAR [^{}|&$;<> \t\n\'\"\\]
DIGITS [[:digit:]]+
NAME [[:alpha:]_][[:alnum:]_]*
ESC \\.
ESC \\(.|\n)
SQCHR [^\']
DQCHR {ESC}|[^\\\"]
DQSTR \"{DQCHR}*\"
SQSTR \'{SQCHR}*\'
SPECIAL \?|\#|\*|\@
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|${SPECIAL}|$\{{SPECIAL}\}
DQSTR \"([^\\\"]|{ESC})*\"
SQSTR \'[^\']*\'
WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n))
%x SPLIT
%x DQUOTE
%x SQUOTE
@ -171,34 +178,32 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
"function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; }
"menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; }
{MULTILINE} {
if (grub_lexer_unput (yytext, yyscanner))
return GRUB_PARSER_TOKEN_BAD;
}
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
{WORD} {
RECORD;
/* resplit yytext */
grub_dprintf ("lexer", "word: [%s]\n", yytext);
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (yy_scan_string (yytext, yyscanner))
{
yyextra->lexerstate->merge_start = 1;
yy_push_state (SPLIT, yyscanner);
}
else
{
grub_script_yyerror (yyextra, 0);
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (grub_lexer_resplit (yytext, yyscanner))
{
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
yyextra->lexerstate->resplit = 1;
}
.|\n {
grub_script_yyerror (yyextra, "unrecognized token");
return GRUB_PARSER_TOKEN_BAD;
. {
grub_script_yyerror (yyextra, yytext);
return GRUB_PARSER_TOKEN_BAD;
}
/* Split word into multiple args */
<SPLIT>{
\\. { COPY (yytext + 1, yyleng - 1); }
\\\n { /* ignore */ }
\" {
yy_push_state (DQUOTE, yyscanner);
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
@ -216,6 +221,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
<<EOF>> {
yy_pop_state (yyscanner);
yypop_buffer_state (yyscanner);
yyextra->lexerstate->resplit = 0;
yyextra->lexerstate->merge_end = 1;
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
}
@ -273,15 +279,20 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
<<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;
}
%%
int
yywrap (yyscan_t yyscanner)
{
if (yyget_extra (yyscanner)->lexerstate->resplit)
return 1;
return grub_script_lexer_yywrap (yyget_extra (yyscanner), 0);
}
static void
grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused)))
{
@ -301,8 +312,6 @@ grub_lexer_yyrealloc (void *ptr, yy_size_t size,
return grub_realloc (ptr, size);
}
#define MAX(a,b) ((a) < (b) ? (b) : (a))
static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint)
{
int size;
@ -312,7 +321,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi
len = hint ? hint : grub_strlen (str);
if (parser->lexerstate->used + len >= parser->lexerstate->size)
{
size = MAX (len, parser->lexerstate->size) * 2;
size = grub_max (len, parser->lexerstate->size) * 2;
ptr = grub_realloc (parser->lexerstate->text, size);
if (!ptr)
{
@ -326,3 +335,34 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi
grub_strcpy (parser->lexerstate->text + parser->lexerstate->used - 1, str);
parser->lexerstate->used += len;
}
static int
grub_lexer_resplit (const char *text, yyscan_t yyscanner)
{
/* resplit text */
if (yy_scan_string (text, yyscanner))
{
yyget_extra (yyscanner)->lexerstate->merge_start = 1;
yy_push_state (SPLIT, yyscanner);
return 0;
}
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 = grub_strdup (text);
if (! lexerstate->prefix)
{
grub_script_yyerror (yyget_extra (yyscanner), "out of memory");
return 1;
}
return 0;
}