nested recording support
This commit is contained in:
parent
4ba8d3540a
commit
0993355a68
3 changed files with 37 additions and 46 deletions
|
@ -282,8 +282,8 @@ struct grub_lexer_param *grub_script_lexer_init (struct grub_parser_param *parse
|
||||||
void grub_script_lexer_fini (struct grub_lexer_param *);
|
void grub_script_lexer_fini (struct grub_lexer_param *);
|
||||||
void grub_script_lexer_ref (struct grub_lexer_param *);
|
void grub_script_lexer_ref (struct grub_lexer_param *);
|
||||||
void grub_script_lexer_deref (struct grub_lexer_param *);
|
void grub_script_lexer_deref (struct grub_lexer_param *);
|
||||||
void grub_script_lexer_record_start (struct grub_parser_param *);
|
unsigned grub_script_lexer_record_start (struct grub_parser_param *);
|
||||||
char *grub_script_lexer_record_stop (struct grub_parser_param *);
|
char *grub_script_lexer_record_stop (struct grub_parser_param *, unsigned);
|
||||||
int grub_script_lexer_yywrap (struct grub_parser_param *);
|
int grub_script_lexer_yywrap (struct grub_parser_param *);
|
||||||
void grub_script_lexer_record (struct grub_parser_param *, char *);
|
void grub_script_lexer_record (struct grub_parser_param *, char *);
|
||||||
|
|
||||||
|
|
|
@ -38,68 +38,57 @@ grub_script_lexer_deref (struct grub_lexer_param *state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start recording all characters passing through the lexer. */
|
/* Start recording all characters passing through the lexer. */
|
||||||
void
|
unsigned
|
||||||
grub_script_lexer_record_start (struct grub_parser_param *parser)
|
grub_script_lexer_record_start (struct grub_parser_param *parser)
|
||||||
{
|
{
|
||||||
struct grub_lexer_param *lexer = parser->lexerstate;
|
struct grub_lexer_param *lexer = parser->lexerstate;
|
||||||
|
|
||||||
lexer->record = 1;
|
lexer->record++;
|
||||||
lexer->recordpos = 0;
|
if (lexer->recording)
|
||||||
if (lexer->recording) /* reuse last record */
|
return lexer->recordpos;
|
||||||
return;
|
|
||||||
|
|
||||||
|
lexer->recordpos = 0;
|
||||||
lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE;
|
lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE;
|
||||||
lexer->recording = grub_malloc (lexer->recordlen);
|
lexer->recording = grub_malloc (lexer->recordlen);
|
||||||
if (!lexer->recording)
|
if (!lexer->recording)
|
||||||
{
|
{
|
||||||
grub_script_yyerror (parser, 0);
|
grub_script_yyerror (parser, 0);
|
||||||
lexer->record = 0;
|
|
||||||
lexer->recordlen = 0;
|
lexer->recordlen = 0;
|
||||||
}
|
}
|
||||||
|
return lexer->recordpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
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;
|
char *result;
|
||||||
struct grub_lexer_param *lexer = parser->lexerstate;
|
struct grub_lexer_param *lexer = parser->lexerstate;
|
||||||
|
|
||||||
auto char *compact (char *start, char *end);
|
if (!lexer->record)
|
||||||
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)
|
|
||||||
return 0;
|
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);
|
count = lexer->recordpos - offset;
|
||||||
lexer->record = 0;
|
result = grub_script_malloc (parser, count + 1);
|
||||||
lexer->recordpos = 0;
|
if (result) {
|
||||||
|
grub_strncpy (result, lexer->recording + offset, count);
|
||||||
/* This memory would be freed by, grub_script_free. */
|
result[count] = '\0';
|
||||||
result = grub_script_malloc (parser, grub_strlen (ptr) + 1);
|
}
|
||||||
if (result)
|
|
||||||
grub_strcpy (result, ptr);
|
|
||||||
|
|
||||||
|
if (lexer->record == 0)
|
||||||
|
{
|
||||||
|
grub_free (lexer->recording);
|
||||||
|
lexer->recording = 0;
|
||||||
|
lexer->recordlen = 0;
|
||||||
|
lexer->recordpos = 0;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
|
||||||
|
|
||||||
/* Record STR if input recording is enabled. */
|
/* Record STR if input recording is enabled. */
|
||||||
void
|
void
|
||||||
grub_script_lexer_record (struct grub_parser_param *parser, char *str)
|
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;
|
char *old;
|
||||||
struct grub_lexer_param *lexer = parser->lexerstate;
|
struct grub_lexer_param *lexer = parser->lexerstate;
|
||||||
|
|
||||||
if (!lexer->record)
|
if (!lexer->record || !lexer->recording)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
len = grub_strlen (str);
|
len = grub_strlen (str);
|
||||||
if (lexer->recordpos + len + 1 > lexer->recordlen)
|
if (lexer->recordpos + len + 1 > lexer->recordlen)
|
||||||
{
|
{
|
||||||
old = lexer->recording;
|
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);
|
lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
|
||||||
if (!lexer->recording)
|
if (!lexer->recording)
|
||||||
{
|
{
|
||||||
grub_free (old);
|
grub_free (old);
|
||||||
lexer->record = 0;
|
|
||||||
lexer->recordpos = 0;
|
lexer->recordpos = 0;
|
||||||
lexer->recordlen /= 2;
|
lexer->recordlen = 0;
|
||||||
grub_script_yyerror (parser, 0);
|
grub_script_yyerror (parser, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
struct grub_script_arglist *arglist;
|
struct grub_script_arglist *arglist;
|
||||||
struct grub_script_arg *arg;
|
struct grub_script_arg *arg;
|
||||||
char *string;
|
char *string;
|
||||||
|
unsigned offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token GRUB_PARSER_TOKEN_BAD
|
%token GRUB_PARSER_TOKEN_BAD
|
||||||
|
@ -217,14 +218,16 @@ menuentry: "menuentry"
|
||||||
}
|
}
|
||||||
arguments1
|
arguments1
|
||||||
{
|
{
|
||||||
grub_script_lexer_record_start (state);
|
$<offset>$ = grub_script_lexer_record_start (state);
|
||||||
}
|
}
|
||||||
delimiters0 "{" commands1 delimiters1 "}"
|
delimiters0 "{" commands1 delimiters1 "}"
|
||||||
{
|
{
|
||||||
char *menu_entry;
|
char *def;
|
||||||
menu_entry = grub_script_lexer_record_stop (state);
|
def = grub_script_lexer_record_stop (state, $<offset>4);
|
||||||
|
*grub_strrchr(def, '}') = '\0';
|
||||||
|
|
||||||
grub_script_lexer_deref (state->lexerstate);
|
grub_script_lexer_deref (state->lexerstate);
|
||||||
$$ = grub_script_create_cmdmenu (state, $3, menu_entry, 0);
|
$$ = grub_script_create_cmdmenu (state, $3, def, 0);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue