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