]> git.ozlabs.org Git - petitboot/blob - discover/grub2/lexer.l
discover/grub2: Improve error handling
[petitboot] / discover / grub2 / lexer.l
1
2 %{
3 #include "grub2.h"
4 #include "parser.h"
5 #include <talloc/talloc.h>
6 %}
7
8 %option nounput noinput
9 %option batch never-interactive
10 %option warn
11 %option noyywrap
12 %option stack noyy_top_state
13 %option reentrant
14 %option bison-bridge
15 %option yylineno
16 %option noyyalloc noyyfree noyyrealloc
17 %option extra-type="struct grub2_parser *"
18 %option header-file="lexer.h"
19 %option outfile="lexer.c"
20
21 %x sqstring
22 %x dqstring
23
24 WORD    [^{}|&$;<> \t\n'"]+
25 VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
26
27 %%
28
29  /* discard leading & trailing whitespace, but keep inter-word delimeters */
30 ^[ \t]+ ;
31 [ \t]+$ ;
32 [ \t]*  return TOKEN_DELIM;
33
34  /* reserved words */
35 "[["         return TOKEN_LDSQBRACKET;
36 "]]"         return TOKEN_RDSQBRACKET;
37 "case"       return TOKEN_CASE;
38 "do"         return TOKEN_DO;
39 "done"       return TOKEN_DONE;
40 "elif"       return TOKEN_ELIF;
41 "else"       return TOKEN_ELSE;
42 "esac"       return TOKEN_ESAC;
43 "fi"         return TOKEN_FI;
44 "for"        return TOKEN_FOR;
45 "function"   return TOKEN_FUNCTION;
46 "if"         return TOKEN_IF;
47 "in"         return TOKEN_IN;
48 "menuentry"  return TOKEN_MENUENTRY;
49 "select"     return TOKEN_SELECT;
50 "then"       return TOKEN_THEN;
51 "time"       return TOKEN_TIME;
52 "until"      return TOKEN_UTIL;
53 "while"      return TOKEN_WHILE;
54
55  /* anything that's not a metachar: return as a plain word */
56 {WORD}  {
57                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
58                 return TOKEN_WORD;
59         }
60
61 \${VARNAME} |
62 \$\{{VARNAME}\} {
63                 if (yytext[1] == '{') {
64                         yytext[yyleng-1] = '\0';
65                         yytext++;
66                 }
67                 yytext++;
68                 yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
69                                                 true);
70                 return TOKEN_WORD;
71         }
72
73  /* single-quoted strings: return a single, non-expanded word token */
74 \'      {
75                 yy_push_state(sqstring, yyscanner);
76         }
77 <sqstring>\' {
78                 yy_pop_state(yyscanner);
79         }
80 <sqstring>[^']+ {
81                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
82                 return TOKEN_WORD;
83         }
84
85  /* double-quoted strings: return a single, expanded word token */
86 \"      {
87                 yy_push_state(dqstring, yyscanner);
88         }
89 <dqstring>\" {
90                 yy_pop_state(yyscanner);
91         }
92 <dqstring>([^"\$]|\\\")+ {
93                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
94                 return TOKEN_WORD;
95         }
96 <dqstring>\${VARNAME} |
97 <dqstring>\$\{{VARNAME}\} {
98                 if (yytext[1] == '{') {
99                         yytext[yyleng-1] = '\0';
100                         yytext++;
101                 }
102                 yytext++;
103                 yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
104                                                 false);
105                 return TOKEN_WORD;
106         }
107
108
109
110  /* blocks */
111 "{"     return '{';
112 "}"     return '}';
113
114  /* end-of-line */
115 [ \t]*(;|\n)[ \t]*      return TOKEN_EOL;
116
117  /* strip comments */
118 #.*$    ;
119
120
121 .       printf("unknown token '%s'\n", yytext); exit(1);
122
123 %%
124
125 struct grub2_parser;
126
127 void *yyalloc(size_t bytes, void *yyscanner)
128 {
129         struct grub2_parser *parser = yyget_extra(yyscanner);
130         return talloc_size(parser, bytes);
131 }
132
133 void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
134 {
135         struct grub2_parser *parser = yyget_extra(yyscanner);
136         return talloc_realloc_size(parser, ptr, bytes);
137 }
138
139 void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
140 {
141         talloc_free(ptr);
142 }