diff options
Diffstat (limited to 'discover/grub2/grub2-lexer.l')
-rw-r--r-- | discover/grub2/grub2-lexer.l | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/discover/grub2/grub2-lexer.l b/discover/grub2/grub2-lexer.l new file mode 100644 index 0000000..7c9fcfe --- /dev/null +++ b/discover/grub2/grub2-lexer.l @@ -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); +} |