]> git.ozlabs.org Git - petitboot/commitdiff
discover/grub2: distinguish parser.h from grub2/parser.h
authorJeremy Kerr <jk@ozlabs.org>
Mon, 4 Aug 2014 01:46:00 +0000 (09:46 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 5 Aug 2014 02:31:28 +0000 (10:31 +0800)
'make distcheck' will do a 'make all' srcdir == objdir, then later a
'make check' sith srcdir != objdir. Since gcc's cpp always assumes that
a source file's directory is first in the include paths, we may see
discover/parser.h included when we wanted the generated
discover/grub2/parser.h.

This change renames the grub2 lexer and parser files, to work-around
this behaviour, and fix 'make distcheck'.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/grub2/Makefile.am
discover/grub2/grub2-lexer.l [new file with mode: 0644]
discover/grub2/grub2-parser.y [new file with mode: 0644]
discover/grub2/lexer.l [deleted file]
discover/grub2/parser.y [deleted file]
test/parser/Makefile.am

index 0bff9fa772d4c98d8847028b23f67f97080ce1c9..496dac3fbab2bdb1932316af230cdc92d5a4cf4f 100644 (file)
@@ -19,21 +19,21 @@ discover_grub2_grub2_parser_ro_SOURCES = \
        discover/grub2/env.c \
        discover/grub2/grub2.h \
        discover/grub2/grub2.c \
        discover/grub2/env.c \
        discover/grub2/grub2.h \
        discover/grub2/grub2.c \
-       discover/grub2/lexer.l \
-       discover/grub2/parser.y \
+       discover/grub2/grub2-lexer.l \
+       discover/grub2/grub2-parser.y \
        discover/grub2/script.c
 
 BUILT_SOURCES += \
        discover/grub2/script.c
 
 BUILT_SOURCES += \
-       discover/grub2/parser.c \
-       discover/grub2/parser.h \
-       discover/grub2/lexer.h \
-       discover/grub2/lexer.c
+       discover/grub2/grub2-parser.c \
+       discover/grub2/grub2-parser.h \
+       discover/grub2/grub2-lexer.h \
+       discover/grub2/grub2-lexer.c
 
 CLEANFILES += \
 
 CLEANFILES += \
-       discover/grub2/parser.c \
-       discover/grub2/parser.h \
-       discover/grub2/lexer.c \
-       discover/grub2/lexer.h
+       discover/grub2/grub2-parser.c \
+       discover/grub2/grub2-parser.h \
+       discover/grub2/grub2-lexer.c \
+       discover/grub2/grub2-lexer.h
 
 discover_grub2_grub2_parser_ro_CPPFLAGS = \
        $(AM_CPPFLAGS) \
 
 discover_grub2_grub2_parser_ro_CPPFLAGS = \
        $(AM_CPPFLAGS) \
@@ -44,14 +44,14 @@ discover_grub2_grub2_parser_ro_LINK = \
        $(LD) -r -o $@
 
 # ylwrap doesn't handle flex header files well; use our own rule here.
        $(LD) -r -o $@
 
 # ylwrap doesn't handle flex header files well; use our own rule here.
-discover/grub2/lexer.h discover/grub2/lexer.c: \
-               $(top_srcdir)/discover/grub2/lexer.l
-       $(AM_V_LEX)$(LEXCOMPILE) --header-file=discover/grub2/lexer.h \
-                                      -o discover/grub2/lexer.c $^
+discover/grub2/grub2-lexer.h discover/grub2/grub2-lexer.c: \
+               $(top_srcdir)/discover/grub2/grub2-lexer.l
+       $(AM_V_LEX)$(LEXCOMPILE) --header-file=discover/grub2/grub2-lexer.h \
+                                      -o discover/grub2/grub2-lexer.c $^
 
 # We need to loosen our warnings for the generated lexer code.
 
 # We need to loosen our warnings for the generated lexer code.
-discover/grub2/%lexer.o discover/grub2/lexer.o: \
+discover/grub2/%grub2-lexer.o discover/grub2/grub2-lexer.o: \
                AM_CFLAGS += -Wno-unused-parameter -Wno-missing-prototypes \
                               -Wno-missing-declarations
 
                AM_CFLAGS += -Wno-unused-parameter -Wno-missing-prototypes \
                               -Wno-missing-declarations
 
-$(discover_grub2_grub2_parser_ro_OBJECTS): discover/grub2/parser.h
+$(discover_grub2_grub2_parser_ro_OBJECTS): discover/grub2/grub2-parser.h
diff --git a/discover/grub2/grub2-lexer.l b/discover/grub2/grub2-lexer.l
new file mode 100644 (file)
index 0000000..7c9fcfe
--- /dev/null
@@ -0,0 +1,145 @@
+
+%{
+#include "grub2.h"
+#include "grub2-parser.h"
+#include <talloc/talloc.h>
+
+void yyerror(struct grub2_parser *parser, const char *fmt, ...);
+%}
+
+%option nounput noinput
+%option batch never-interactive
+%option warn
+%option noyywrap
+%option stack noyy_top_state
+%option reentrant
+%option bison-bridge
+%option yylineno
+%option noyyalloc noyyfree noyyrealloc
+%option extra-type="struct grub2_parser *"
+
+%x sqstring
+%x dqstring
+
+WORD   [^{}|&$;<> \t\n'"#]+
+VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
+
+%%
+
+ /* discard leading & trailing whitespace, but keep inter-word delimeters */
+^[ \t]+        ;
+[ \t]+$        ;
+[ \t]+ return TOKEN_DELIM;
+
+ /* reserved words */
+"[["         return TOKEN_LDSQBRACKET;
+"]]"         return TOKEN_RDSQBRACKET;
+"case"       return TOKEN_CASE;
+"do"         return TOKEN_DO;
+"done"       return TOKEN_DONE;
+"elif"       return TOKEN_ELIF;
+"else"       return TOKEN_ELSE;
+"esac"       return TOKEN_ESAC;
+"fi"         return TOKEN_FI;
+"for"        return TOKEN_FOR;
+"function"   return TOKEN_FUNCTION;
+"if"         return TOKEN_IF;
+"in"         return TOKEN_IN;
+"menuentry"  return TOKEN_MENUENTRY;
+"select"     return TOKEN_SELECT;
+"submenu"    return TOKEN_SUBMENU;
+"then"       return TOKEN_THEN;
+"time"       return TOKEN_TIME;
+"until"      return TOKEN_UTIL;
+"while"      return TOKEN_WHILE;
+
+ /* anything that's not a metachar: return as a plain word */
+{WORD} {
+               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+               return TOKEN_WORD;
+       }
+
+\${VARNAME} |
+\$\{{VARNAME}\} {
+               if (yytext[1] == '{') {
+                       yytext[yyleng-1] = '\0';
+                       yytext++;
+               }
+               yytext++;
+               yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
+                                               true);
+               return TOKEN_WORD;
+       }
+
+ /* single-quoted strings: return a single, non-expanded word token */
+\'     {
+               yy_push_state(sqstring, yyscanner);
+       }
+<sqstring>\' {
+               yy_pop_state(yyscanner);
+       }
+<sqstring>[^']+ {
+               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+               return TOKEN_WORD;
+       }
+
+ /* double-quoted strings: return a single, expanded word token */
+\"     {
+               yy_push_state(dqstring, yyscanner);
+       }
+<dqstring>\" {
+               yy_pop_state(yyscanner);
+       }
+<dqstring>([^"\$]|\\\")+ {
+               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+               return TOKEN_WORD;
+       }
+<dqstring>\${VARNAME} |
+<dqstring>\$\{{VARNAME}\} {
+               if (yytext[1] == '{') {
+                       yytext[yyleng-1] = '\0';
+                       yytext++;
+               }
+               yytext++;
+               yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
+                                               false);
+               return TOKEN_WORD;
+       }
+
+
+
+ /* blocks */
+"{"    return '{';
+"}"    return '}';
+
+ /* end-of-line */
+[ \t]*(;|\n)[ \t]*     return TOKEN_EOL;
+
+ /* strip comments */
+#.*    ;
+
+.      {
+               yyerror(yyget_extra(yyscanner), "unknown token '%s'\n", yytext);
+               yyterminate();
+       }
+
+%%
+
+struct grub2_parser;
+
+void *yyalloc(size_t bytes, void *yyscanner)
+{
+       struct grub2_parser *parser = yyget_extra(yyscanner);
+       return talloc_size(parser, bytes);
+}
+
+void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
+{
+       struct grub2_parser *parser = yyget_extra(yyscanner);
+       return talloc_realloc_size(parser, ptr, bytes);
+}
+
+void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
+{
+       talloc_free(ptr);
+}
diff --git a/discover/grub2/grub2-parser.y b/discover/grub2/grub2-parser.y
new file mode 100644 (file)
index 0000000..4d351d4
--- /dev/null
@@ -0,0 +1,347 @@
+
+%pure-parser
+%lex-param { yyscan_t scanner }
+%parse-param { struct grub2_parser *parser }
+%parse-param { void *scanner }
+%error-verbose
+
+%{
+#include <talloc/talloc.h>
+#include <log/log.h>
+
+#include "grub2.h"
+
+void yyerror(struct grub2_parser *parser, const char *fmt, ...);
+%}
+
+%union {
+       struct grub2_word       *word;
+       struct grub2_argv       *argv;
+       struct grub2_statement  *statement;
+       struct grub2_statements *statements;
+}
+
+/* reserved words */
+%token TOKEN_LDSQBRACKET       "[["
+%token TOKEN_RDSQBRACKET       "]]"
+%token TOKEN_CASE              "case"
+%token TOKEN_DO                "do"
+%token TOKEN_DONE              "done"
+%token TOKEN_ELIF              "elif"
+%token TOKEN_ELSE              "else"
+%token TOKEN_ESAC              "esac"
+%token TOKEN_FI                "fi"
+%token TOKEN_FOR               "for"
+%token TOKEN_FUNCTION          "function"
+%token TOKEN_IF                "if"
+%token TOKEN_IN                "in"
+%token TOKEN_MENUENTRY         "menuentry"
+%token TOKEN_SELECT            "select"
+%token TOKEN_SUBMENU           "submenu"
+%token TOKEN_THEN              "then"
+%token TOKEN_TIME              "time"
+%token TOKEN_UTIL              "until"
+%token TOKEN_WHILE             "while"
+
+%type <statement>      statement
+%type <statements>     statements
+%type <statement>      conditional
+%type <statement>      elif
+%type <statements>     elifs
+%type <argv>           words
+%type <word>           word
+
+/* syntax */
+%token TOKEN_EOL
+%token TOKEN_DELIM
+%token <word> TOKEN_WORD
+%token TOKEN_EOF 0
+
+%start script
+%debug
+
+%{
+#include "grub2-lexer.h"
+%}
+
+%%
+
+script:        statements {
+               parser->script->statements = $1;
+       }
+
+eol:   TOKEN_EOL | TOKEN_EOF;
+
+statements: /* empty */ {
+               $$ = create_statements(parser);
+       }
+       | statements statement eol {
+               statement_append($1, $2);
+               $$ = $1;
+       }
+       | statements TOKEN_EOL {
+               $$ = $1;
+       }
+
+sep:   TOKEN_DELIM | TOKEN_EOL;
+
+conditional: statement TOKEN_EOL "then" sep statements {
+               $$ = create_statement_conditional(parser, $1, $5);
+       }
+
+elif: "elif" TOKEN_DELIM conditional {
+               $$ = $3;
+      }
+
+elifs: /* empty */ {
+               $$ = create_statements(parser);
+       }
+       | elifs elif {
+               statement_append($1, $2);
+               $$ = $1;
+       }
+
+statement:
+       words {
+                  $$ = 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" TOKEN_DELIM conditional
+               elifs
+               "else" sep
+               statements
+               "fi" {
+               $$ = create_statement_if(parser, $3, $4, $7);
+       }
+       | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
+               $$ = create_statement_function(parser, $3, $6);
+       }
+       | "menuentry" TOKEN_DELIM words TOKEN_DELIM
+               '{' statements '}' {
+               $$ = create_statement_menuentry(parser, $3, $6);
+       }
+       | "submenu" TOKEN_DELIM words TOKEN_DELIM
+               '{' statements '}' {
+               /* we just flatten everything */
+               $$ = create_statement_block(parser, $6);
+       }
+       | "for" TOKEN_DELIM word TOKEN_DELIM "in" TOKEN_DELIM words TOKEN_EOL
+               "do" sep
+               statements
+               "done" {
+               $$ = create_statement_for(parser, $3, $7, $11);
+       }
+
+words: word {
+               $$ = create_argv(parser);
+               argv_append($$, $1);
+       }
+       | words TOKEN_DELIM word {
+               argv_append($1, $3);
+               $$ = $1;
+       }
+
+word:  TOKEN_WORD
+       | word TOKEN_WORD {
+               word_append($1, $2);
+               $$ = $1;
+       }
+
+%%
+void yyerror(struct grub2_parser *parser, const char *fmt, ...)
+{
+       const char *str;
+       va_list ap;
+
+       va_start(ap, fmt);
+       str = talloc_vasprintf(parser, fmt, ap);
+       va_end(ap);
+
+       pb_log("parse error: %d('%s'): %s\n", yyget_lineno(parser->scanner),
+                                       yyget_text(parser->scanner), str);
+}
+
+struct grub2_statements *create_statements(struct grub2_parser *parser)
+{
+       struct grub2_statements *stmts = talloc(parser,
+                       struct grub2_statements);
+       list_init(&stmts->list);
+       return stmts;
+}
+
+struct grub2_statement *create_statement_simple(struct grub2_parser *parser,
+               struct grub2_argv *argv)
+{
+       struct grub2_statement_simple *stmt =
+               talloc(parser, struct grub2_statement_simple);
+       stmt->st.type = STMT_TYPE_SIMPLE;
+       stmt->st.exec = statement_simple_execute;
+       stmt->argv = argv;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser,
+               struct grub2_argv *argv, struct grub2_statements *stmts)
+{
+       struct grub2_statement_menuentry *stmt =
+               talloc(parser, struct grub2_statement_menuentry);
+       stmt->st.type = STMT_TYPE_MENUENTRY;
+       stmt->st.exec = statement_menuentry_execute;
+       stmt->argv = argv;
+       stmt->statements = stmts;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_conditional(
+               struct grub2_parser *parser,
+               struct grub2_statement *condition,
+               struct grub2_statements *statements)
+{
+       struct grub2_statement_conditional *stmt =
+               talloc(parser, struct grub2_statement_conditional);
+       stmt->st.type = STMT_TYPE_CONDITIONAL;
+       stmt->condition = condition;
+       stmt->statements = statements;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_if(struct grub2_parser *parser,
+               struct grub2_statement *conditional,
+               struct grub2_statements *elifs,
+               struct grub2_statements *else_case)
+{
+       struct grub2_statement_if *stmt =
+               talloc(parser, struct grub2_statement_if);
+
+       list_add(&elifs->list, &conditional->list);
+
+       stmt->st.type = STMT_TYPE_IF;
+       stmt->st.exec = statement_if_execute;
+       stmt->conditionals = elifs;
+       stmt->else_case = else_case;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_block(struct grub2_parser *parser,
+               struct grub2_statements *stmts)
+{
+       struct grub2_statement_block *stmt =
+               talloc(parser, struct grub2_statement_block);
+       stmt->st.type = STMT_TYPE_BLOCK;
+       stmt->st.exec = statement_block_execute;
+       stmt->statements = stmts;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_function(struct grub2_parser *parser,
+               struct grub2_word *name, struct grub2_statements *body)
+{
+       struct grub2_statement_function *stmt =
+               talloc(parser, struct grub2_statement_function);
+       stmt->st.exec = statement_function_execute;
+       stmt->name = name;
+       stmt->body = body;
+       return &stmt->st;
+}
+
+struct grub2_statement *create_statement_for(struct grub2_parser *parser,
+               struct grub2_word *var, struct grub2_argv *list,
+               struct grub2_statements *body)
+{
+       struct grub2_statement_for *stmt =
+               talloc(parser, struct grub2_statement_for);
+       stmt->st.exec = statement_for_execute;
+       stmt->var = var;
+       stmt->list = list;
+       stmt->body = body;
+       return &stmt->st;
+}
+
+void statement_append(struct grub2_statements *stmts,
+               struct grub2_statement *stmt)
+{
+       if (!stmt)
+               return;
+       list_add_tail(&stmts->list, &stmt->list);
+}
+
+struct grub2_word *create_word_text(struct grub2_parser *parser,
+               const char *text)
+{
+       struct grub2_word *word = talloc(parser, struct grub2_word);
+       word->type = GRUB2_WORD_TEXT;
+       word->split = false;
+       word->text = talloc_strdup(word, text);
+       word->next = NULL;
+       word->last = word;
+       return word;
+}
+
+struct grub2_word *create_word_var(struct grub2_parser *parser,
+               const char *name, bool split)
+{
+       struct grub2_word *word = talloc(parser, struct grub2_word);
+       word->type = GRUB2_WORD_VAR;
+       word->name = talloc_strdup(word, name);
+       word->split = split;
+       word->next = NULL;
+       word->last = word;
+       return word;
+}
+
+struct grub2_argv *create_argv(struct grub2_parser *parser)
+{
+       struct grub2_argv *argv = talloc(parser, struct grub2_argv);
+       list_init(&argv->words);
+       return argv;
+}
+
+void argv_append(struct grub2_argv *argv, struct grub2_word *word)
+{
+       list_add_tail(&argv->words, &word->argv_list);
+}
+
+void word_append(struct grub2_word *w1, struct grub2_word *w2)
+{
+       w1->last->next = w2;
+       w1->last = w2;
+}
+
+struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
+{
+       struct grub2_parser *parser;
+
+       parser = talloc(ctx, struct grub2_parser);
+       yylex_init_extra(parser, &parser->scanner);
+       parser->script = create_script(parser, ctx);
+
+       return parser;
+}
+
+void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
+               char *buf, int len)
+{
+       YY_BUFFER_STATE bufstate;
+       int rc;
+
+       if (!len)
+               return;
+
+       parser->script->filename = filename;
+
+       bufstate = yy_scan_bytes(buf, len - 1, parser->scanner);
+       yyset_lineno(1, parser->scanner);
+
+       rc = yyparse(parser, parser->scanner);
+
+       yy_delete_buffer(bufstate, parser->scanner);
+
+       if (!rc)
+               script_execute(parser->script);
+}
+
diff --git a/discover/grub2/lexer.l b/discover/grub2/lexer.l
deleted file mode 100644 (file)
index e557146..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-
-%{
-#include "grub2.h"
-#include "parser.h"
-#include <talloc/talloc.h>
-
-void yyerror(struct grub2_parser *parser, const char *fmt, ...);
-%}
-
-%option nounput noinput
-%option batch never-interactive
-%option warn
-%option noyywrap
-%option stack noyy_top_state
-%option reentrant
-%option bison-bridge
-%option yylineno
-%option noyyalloc noyyfree noyyrealloc
-%option extra-type="struct grub2_parser *"
-
-%x sqstring
-%x dqstring
-
-WORD   [^{}|&$;<> \t\n'"#]+
-VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
-
-%%
-
- /* discard leading & trailing whitespace, but keep inter-word delimeters */
-^[ \t]+        ;
-[ \t]+$        ;
-[ \t]+ return TOKEN_DELIM;
-
- /* reserved words */
-"[["         return TOKEN_LDSQBRACKET;
-"]]"         return TOKEN_RDSQBRACKET;
-"case"       return TOKEN_CASE;
-"do"         return TOKEN_DO;
-"done"       return TOKEN_DONE;
-"elif"       return TOKEN_ELIF;
-"else"       return TOKEN_ELSE;
-"esac"       return TOKEN_ESAC;
-"fi"         return TOKEN_FI;
-"for"        return TOKEN_FOR;
-"function"   return TOKEN_FUNCTION;
-"if"         return TOKEN_IF;
-"in"         return TOKEN_IN;
-"menuentry"  return TOKEN_MENUENTRY;
-"select"     return TOKEN_SELECT;
-"submenu"    return TOKEN_SUBMENU;
-"then"       return TOKEN_THEN;
-"time"       return TOKEN_TIME;
-"until"      return TOKEN_UTIL;
-"while"      return TOKEN_WHILE;
-
- /* anything that's not a metachar: return as a plain word */
-{WORD} {
-               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
-               return TOKEN_WORD;
-       }
-
-\${VARNAME} |
-\$\{{VARNAME}\} {
-               if (yytext[1] == '{') {
-                       yytext[yyleng-1] = '\0';
-                       yytext++;
-               }
-               yytext++;
-               yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
-                                               true);
-               return TOKEN_WORD;
-       }
-
- /* single-quoted strings: return a single, non-expanded word token */
-\'     {
-               yy_push_state(sqstring, yyscanner);
-       }
-<sqstring>\' {
-               yy_pop_state(yyscanner);
-       }
-<sqstring>[^']+ {
-               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
-               return TOKEN_WORD;
-       }
-
- /* double-quoted strings: return a single, expanded word token */
-\"     {
-               yy_push_state(dqstring, yyscanner);
-       }
-<dqstring>\" {
-               yy_pop_state(yyscanner);
-       }
-<dqstring>([^"\$]|\\\")+ {
-               yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
-               return TOKEN_WORD;
-       }
-<dqstring>\${VARNAME} |
-<dqstring>\$\{{VARNAME}\} {
-               if (yytext[1] == '{') {
-                       yytext[yyleng-1] = '\0';
-                       yytext++;
-               }
-               yytext++;
-               yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
-                                               false);
-               return TOKEN_WORD;
-       }
-
-
-
- /* blocks */
-"{"    return '{';
-"}"    return '}';
-
- /* end-of-line */
-[ \t]*(;|\n)[ \t]*     return TOKEN_EOL;
-
- /* strip comments */
-#.*    ;
-
-.      {
-               yyerror(yyget_extra(yyscanner), "unknown token '%s'\n", yytext);
-               yyterminate();
-       }
-
-%%
-
-struct grub2_parser;
-
-void *yyalloc(size_t bytes, void *yyscanner)
-{
-       struct grub2_parser *parser = yyget_extra(yyscanner);
-       return talloc_size(parser, bytes);
-}
-
-void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
-{
-       struct grub2_parser *parser = yyget_extra(yyscanner);
-       return talloc_realloc_size(parser, ptr, bytes);
-}
-
-void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
-{
-       talloc_free(ptr);
-}
diff --git a/discover/grub2/parser.y b/discover/grub2/parser.y
deleted file mode 100644 (file)
index 9d79d9b..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-
-%pure-parser
-%lex-param { yyscan_t scanner }
-%parse-param { struct grub2_parser *parser }
-%parse-param { void *scanner }
-%error-verbose
-
-%{
-#include <talloc/talloc.h>
-#include <log/log.h>
-
-#include "grub2.h"
-
-void yyerror(struct grub2_parser *parser, const char *fmt, ...);
-%}
-
-%union {
-       struct grub2_word       *word;
-       struct grub2_argv       *argv;
-       struct grub2_statement  *statement;
-       struct grub2_statements *statements;
-}
-
-/* reserved words */
-%token TOKEN_LDSQBRACKET       "[["
-%token TOKEN_RDSQBRACKET       "]]"
-%token TOKEN_CASE              "case"
-%token TOKEN_DO                "do"
-%token TOKEN_DONE              "done"
-%token TOKEN_ELIF              "elif"
-%token TOKEN_ELSE              "else"
-%token TOKEN_ESAC              "esac"
-%token TOKEN_FI                "fi"
-%token TOKEN_FOR               "for"
-%token TOKEN_FUNCTION          "function"
-%token TOKEN_IF                "if"
-%token TOKEN_IN                "in"
-%token TOKEN_MENUENTRY         "menuentry"
-%token TOKEN_SELECT            "select"
-%token TOKEN_SUBMENU           "submenu"
-%token TOKEN_THEN              "then"
-%token TOKEN_TIME              "time"
-%token TOKEN_UTIL              "until"
-%token TOKEN_WHILE             "while"
-
-%type <statement>      statement
-%type <statements>     statements
-%type <statement>      conditional
-%type <statement>      elif
-%type <statements>     elifs
-%type <argv>           words
-%type <word>           word
-
-/* syntax */
-%token TOKEN_EOL
-%token TOKEN_DELIM
-%token <word> TOKEN_WORD
-%token TOKEN_EOF 0
-
-%start script
-%debug
-
-%{
-#include "lexer.h"
-%}
-
-%%
-
-script:        statements {
-               parser->script->statements = $1;
-       }
-
-eol:   TOKEN_EOL | TOKEN_EOF;
-
-statements: /* empty */ {
-               $$ = create_statements(parser);
-       }
-       | statements statement eol {
-               statement_append($1, $2);
-               $$ = $1;
-       }
-       | statements TOKEN_EOL {
-               $$ = $1;
-       }
-
-sep:   TOKEN_DELIM | TOKEN_EOL;
-
-conditional: statement TOKEN_EOL "then" sep statements {
-               $$ = create_statement_conditional(parser, $1, $5);
-       }
-
-elif: "elif" TOKEN_DELIM conditional {
-               $$ = $3;
-      }
-
-elifs: /* empty */ {
-               $$ = create_statements(parser);
-       }
-       | elifs elif {
-               statement_append($1, $2);
-               $$ = $1;
-       }
-
-statement:
-       words {
-                  $$ = 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" TOKEN_DELIM conditional
-               elifs
-               "else" sep
-               statements
-               "fi" {
-               $$ = create_statement_if(parser, $3, $4, $7);
-       }
-       | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
-               $$ = create_statement_function(parser, $3, $6);
-       }
-       | "menuentry" TOKEN_DELIM words TOKEN_DELIM
-               '{' statements '}' {
-               $$ = create_statement_menuentry(parser, $3, $6);
-       }
-       | "submenu" TOKEN_DELIM words TOKEN_DELIM
-               '{' statements '}' {
-               /* we just flatten everything */
-               $$ = create_statement_block(parser, $6);
-       }
-       | "for" TOKEN_DELIM word TOKEN_DELIM "in" TOKEN_DELIM words TOKEN_EOL
-               "do" sep
-               statements
-               "done" {
-               $$ = create_statement_for(parser, $3, $7, $11);
-       }
-
-words: word {
-               $$ = create_argv(parser);
-               argv_append($$, $1);
-       }
-       | words TOKEN_DELIM word {
-               argv_append($1, $3);
-               $$ = $1;
-       }
-
-word:  TOKEN_WORD
-       | word TOKEN_WORD {
-               word_append($1, $2);
-               $$ = $1;
-       }
-
-%%
-void yyerror(struct grub2_parser *parser, const char *fmt, ...)
-{
-       const char *str;
-       va_list ap;
-
-       va_start(ap, fmt);
-       str = talloc_vasprintf(parser, fmt, ap);
-       va_end(ap);
-
-       pb_log("parse error: %d('%s'): %s\n", yyget_lineno(parser->scanner),
-                                       yyget_text(parser->scanner), str);
-}
-
-struct grub2_statements *create_statements(struct grub2_parser *parser)
-{
-       struct grub2_statements *stmts = talloc(parser,
-                       struct grub2_statements);
-       list_init(&stmts->list);
-       return stmts;
-}
-
-struct grub2_statement *create_statement_simple(struct grub2_parser *parser,
-               struct grub2_argv *argv)
-{
-       struct grub2_statement_simple *stmt =
-               talloc(parser, struct grub2_statement_simple);
-       stmt->st.type = STMT_TYPE_SIMPLE;
-       stmt->st.exec = statement_simple_execute;
-       stmt->argv = argv;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser,
-               struct grub2_argv *argv, struct grub2_statements *stmts)
-{
-       struct grub2_statement_menuentry *stmt =
-               talloc(parser, struct grub2_statement_menuentry);
-       stmt->st.type = STMT_TYPE_MENUENTRY;
-       stmt->st.exec = statement_menuentry_execute;
-       stmt->argv = argv;
-       stmt->statements = stmts;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_conditional(
-               struct grub2_parser *parser,
-               struct grub2_statement *condition,
-               struct grub2_statements *statements)
-{
-       struct grub2_statement_conditional *stmt =
-               talloc(parser, struct grub2_statement_conditional);
-       stmt->st.type = STMT_TYPE_CONDITIONAL;
-       stmt->condition = condition;
-       stmt->statements = statements;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_if(struct grub2_parser *parser,
-               struct grub2_statement *conditional,
-               struct grub2_statements *elifs,
-               struct grub2_statements *else_case)
-{
-       struct grub2_statement_if *stmt =
-               talloc(parser, struct grub2_statement_if);
-
-       list_add(&elifs->list, &conditional->list);
-
-       stmt->st.type = STMT_TYPE_IF;
-       stmt->st.exec = statement_if_execute;
-       stmt->conditionals = elifs;
-       stmt->else_case = else_case;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_block(struct grub2_parser *parser,
-               struct grub2_statements *stmts)
-{
-       struct grub2_statement_block *stmt =
-               talloc(parser, struct grub2_statement_block);
-       stmt->st.type = STMT_TYPE_BLOCK;
-       stmt->st.exec = statement_block_execute;
-       stmt->statements = stmts;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_function(struct grub2_parser *parser,
-               struct grub2_word *name, struct grub2_statements *body)
-{
-       struct grub2_statement_function *stmt =
-               talloc(parser, struct grub2_statement_function);
-       stmt->st.exec = statement_function_execute;
-       stmt->name = name;
-       stmt->body = body;
-       return &stmt->st;
-}
-
-struct grub2_statement *create_statement_for(struct grub2_parser *parser,
-               struct grub2_word *var, struct grub2_argv *list,
-               struct grub2_statements *body)
-{
-       struct grub2_statement_for *stmt =
-               talloc(parser, struct grub2_statement_for);
-       stmt->st.exec = statement_for_execute;
-       stmt->var = var;
-       stmt->list = list;
-       stmt->body = body;
-       return &stmt->st;
-}
-
-void statement_append(struct grub2_statements *stmts,
-               struct grub2_statement *stmt)
-{
-       if (!stmt)
-               return;
-       list_add_tail(&stmts->list, &stmt->list);
-}
-
-struct grub2_word *create_word_text(struct grub2_parser *parser,
-               const char *text)
-{
-       struct grub2_word *word = talloc(parser, struct grub2_word);
-       word->type = GRUB2_WORD_TEXT;
-       word->split = false;
-       word->text = talloc_strdup(word, text);
-       word->next = NULL;
-       word->last = word;
-       return word;
-}
-
-struct grub2_word *create_word_var(struct grub2_parser *parser,
-               const char *name, bool split)
-{
-       struct grub2_word *word = talloc(parser, struct grub2_word);
-       word->type = GRUB2_WORD_VAR;
-       word->name = talloc_strdup(word, name);
-       word->split = split;
-       word->next = NULL;
-       word->last = word;
-       return word;
-}
-
-struct grub2_argv *create_argv(struct grub2_parser *parser)
-{
-       struct grub2_argv *argv = talloc(parser, struct grub2_argv);
-       list_init(&argv->words);
-       return argv;
-}
-
-void argv_append(struct grub2_argv *argv, struct grub2_word *word)
-{
-       list_add_tail(&argv->words, &word->argv_list);
-}
-
-void word_append(struct grub2_word *w1, struct grub2_word *w2)
-{
-       w1->last->next = w2;
-       w1->last = w2;
-}
-
-struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
-{
-       struct grub2_parser *parser;
-
-       parser = talloc(ctx, struct grub2_parser);
-       yylex_init_extra(parser, &parser->scanner);
-       parser->script = create_script(parser, ctx);
-
-       return parser;
-}
-
-void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
-               char *buf, int len)
-{
-       YY_BUFFER_STATE bufstate;
-       int rc;
-
-       if (!len)
-               return;
-
-       parser->script->filename = filename;
-
-       bufstate = yy_scan_bytes(buf, len - 1, parser->scanner);
-       yyset_lineno(1, parser->scanner);
-
-       rc = yyparse(parser, parser->scanner);
-
-       yy_delete_buffer(bufstate, parser->scanner);
-
-       if (!rc)
-               script_execute(parser->script);
-}
-
index 75411496526f2034874a50984fb9e60f3b7a2233..95ee0023bccf7c5f769a0a70de2ec533956c1fab 100644 (file)
@@ -106,6 +106,7 @@ test_parser_libtest_ro_CPPFLAGS = \
        $(AM_CPPFLAGS) \
        -I$(top_srcdir)/discover \
        -I$(top_srcdir)/discover/grub2 \
        $(AM_CPPFLAGS) \
        -I$(top_srcdir)/discover \
        -I$(top_srcdir)/discover/grub2 \
+       -I$(top_builddir)/discover/grub2 \
        -DPETITBOOT_TEST \
        -DLOCAL_STATE_DIR='"$(localstatedir)"' \
        -DTEST_CONF_BASE='"$(top_srcdir)/test/parser/data"'
        -DPETITBOOT_TEST \
        -DLOCAL_STATE_DIR='"$(localstatedir)"' \
        -DTEST_CONF_BASE='"$(top_srcdir)/test/parser/data"'