nested recording support

This commit is contained in:
BVK Chaitanya 2010-04-29 18:10:22 +05:30
parent 4ba8d3540a
commit 0993355a68
3 changed files with 37 additions and 46 deletions

View file

@ -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 *);

View file

@ -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);
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; 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);
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;
} }

View file

@ -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);
} }
; ;