summaryrefslogtreecommitdiffstats
path: root/discover/grub2
diff options
context:
space:
mode:
Diffstat (limited to 'discover/grub2')
-rw-r--r--discover/grub2/grub2-lexer.l21
-rw-r--r--discover/grub2/grub2-parser.y76
-rw-r--r--discover/grub2/grub2.h1
3 files changed, 57 insertions, 41 deletions
diff --git a/discover/grub2/grub2-lexer.l b/discover/grub2/grub2-lexer.l
index 066af60..52575e3 100644
--- a/discover/grub2/grub2-lexer.l
+++ b/discover/grub2/grub2-lexer.l
@@ -22,14 +22,13 @@ void yyerror(struct grub2_parser *parser, const char *fmt, ...);
%x dqstring
WORD [^{}|&$;<> \t\n'"#]+
+DELIM [ \t]+
VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
%%
- /* discard leading & trailing whitespace, but keep inter-word delimeters */
-^[ \t]+ ;
-[ \t]+$ ;
-[ \t]+ return TOKEN_DELIM;
+ /* discard whitespace, unless we're looking for inter-word delimiters */
+{DELIM} { if (yyget_extra(yyscanner)->inter_word) return TOKEN_DELIM; }
/* reserved words */
"[[" return TOKEN_LDSQBRACKET;
@@ -56,6 +55,7 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
/* anything that's not a metachar: return as a plain word */
{WORD} {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
@@ -68,6 +68,7 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
yytext++;
yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
true);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
@@ -80,6 +81,7 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
}
<sqstring>[^']+ {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
@@ -92,6 +94,7 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
}
<dqstring>([^"\$]|\\\")+ {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
<dqstring>\${VARNAME} |
@@ -103,17 +106,21 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
yytext++;
yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
false);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
/* blocks */
-"{" return '{';
-"}" return '}';
+"{" { yyget_extra(yyscanner)->inter_word = false; return '{'; }
+"}" { yyget_extra(yyscanner)->inter_word = false; return '}'; }
/* end-of-line */
-[ \t]*(;|\n)[ \t]* return TOKEN_EOL;
+[ \t]*(;|\n)[ \t]* {
+ yyget_extra(yyscanner)->inter_word = false;
+ return TOKEN_EOL;
+ }
/* strip comments */
#.* ;
diff --git a/discover/grub2/grub2-parser.y b/discover/grub2/grub2-parser.y
index 7f9961b..598f0fe 100644
--- a/discover/grub2/grub2-parser.y
+++ b/discover/grub2/grub2-parser.y
@@ -21,6 +21,11 @@ void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...);
struct grub2_statements *statements;
}
+%printer { fprintf(yyoutput, "%s%s:'%s'",
+ $$->type == GRUB2_WORD_VAR ? "var" : "text",
+ $$->type == GRUB2_WORD_VAR && !$$->split ? "[nosplit]" : "",
+ $$->name); } <word>
+
/* reserved words */
%token TOKEN_LDSQBRACKET "[["
%token TOKEN_RDSQBRACKET "]]"
@@ -70,27 +75,21 @@ script: statements {
parser->script->statements = $1;
}
-eol: TOKEN_EOL | TOKEN_EOF;
-
-statements: /* empty */ {
+statements: statement {
$$ = create_statements(parser);
+ statement_append($$, $1);
}
- | statements statement eol {
- statement_append($1, $2);
- $$ = $1;
- }
- | statements TOKEN_EOL {
+ | statements eol statement {
+ statement_append($1, $3);
$$ = $1;
}
-sep: TOKEN_DELIM | TOKEN_EOL;
-
-conditional: statement TOKEN_EOL "then" sep statements {
- $$ = create_statement_conditional(parser, $1, $5);
+conditional: statement eol "then" statements {
+ $$ = create_statement_conditional(parser, $1, $4);
}
-elif: "elif" TOKEN_DELIM conditional {
- $$ = $3;
+elif: "elif" conditional {
+ $$ = $2;
}
elifs: /* empty */ {
@@ -101,47 +100,49 @@ elifs: /* empty */ {
$$ = $1;
}
-statement:
- words {
+statement: {
+ $$ = NULL;
+ }
+ | words delim0 {
$$ = create_statement_simple(parser, $1);
}
| '{' statements '}' {
$$ = create_statement_block(parser, $2);
}
- | "if" TOKEN_DELIM conditional elifs "fi" {
- $$ = create_statement_if(parser, $3, $4, NULL);
+ | "if" conditional elifs "fi" {
+ $$ = create_statement_if(parser, $2, $3, NULL);
}
- | "if" TOKEN_DELIM conditional
+ | "if" conditional
elifs
- "else" sep
+ "else"
statements
"fi" {
- $$ = create_statement_if(parser, $3, $4, $7);
+ $$ = create_statement_if(parser, $2, $3, $5);
}
- | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
- $$ = create_statement_function(parser, $3, $6);
+ | "function" word delim '{' statements '}' {
+ $$ = create_statement_function(parser, $2, $5);
}
- | "menuentry" TOKEN_DELIM words TOKEN_DELIM
+ | "menuentry" words delim
'{' statements '}' {
- $$ = create_statement_menuentry(parser, $3, $6);
+ $$ = create_statement_menuentry(parser, $2, $5);
}
- | "submenu" TOKEN_DELIM words TOKEN_DELIM
+ | "submenu" words delim
'{' statements '}' {
/* we just flatten everything */
- $$ = create_statement_block(parser, $6);
+ $$ = create_statement_block(parser, $5);
}
- | "for" TOKEN_DELIM word TOKEN_DELIM "in" TOKEN_DELIM words TOKEN_EOL
- "do" sep
+ | "for" word delim "in" delim words eol
+ "do"
statements
"done" {
- $$ = create_statement_for(parser, $3, $7, $11);
+ $$ = create_statement_for(parser, $2, $6, $9);
}
words: word {
$$ = create_argv(parser);
argv_append($$, $1);
}
- | words TOKEN_DELIM word {
+ | words delim word {
argv_append($1, $3);
$$ = $1;
}
@@ -152,6 +153,13 @@ word: TOKEN_WORD
$$ = $1;
}
+delim0: /* empty */ |
+ delim
+
+delim: TOKEN_DELIM |
+ delim TOKEN_DELIM
+
+eol: TOKEN_EOL;
%%
void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...)
{
@@ -265,9 +273,8 @@ struct grub2_statement *create_statement_for(struct grub2_parser *parser,
void statement_append(struct grub2_statements *stmts,
struct grub2_statement *stmt)
{
- if (!stmt)
- return;
- list_add_tail(&stmts->list, &stmt->list);
+ if (stmt)
+ list_add_tail(&stmts->list, &stmt->list);
}
struct grub2_word *create_word_text(struct grub2_parser *parser,
@@ -319,6 +326,7 @@ struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
parser = talloc(ctx, struct grub2_parser);
yylex_init_extra(parser, &parser->scanner);
parser->script = create_script(parser, ctx);
+ parser->inter_word = false;
return parser;
}
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
index e79bf41..0a89324 100644
--- a/discover/grub2/grub2.h
+++ b/discover/grub2/grub2.h
@@ -103,6 +103,7 @@ struct grub2_script {
struct grub2_parser {
void *scanner;
struct grub2_script *script;
+ bool inter_word;
};
/* type for builtin functions */
OpenPOWER on IntegriCloud