]> git.ozlabs.org Git - petitboot/blob - discover/grub2/grub2-lexer.l
81dc5fe8ac78678d883a8c8325ace472fe953fed
[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 VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
28
29 %%
30
31  /* discard whitespace, unless we're looking for inter-word delimiters */
32 {DELIM}      { if (yyget_extra(yyscanner)->inter_word) 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 "submenu"    return TOKEN_SUBMENU;
51 "then"       return TOKEN_THEN;
52 "time"       return TOKEN_TIME;
53 "until"      return TOKEN_UTIL;
54 "while"      return TOKEN_WHILE;
55
56  /* ignore quoted empty strings */
57 {BLANK} {
58                 yylval->word = create_word_text(yyget_extra(yyscanner), "");
59                 yyget_extra(yyscanner)->inter_word = true;
60                 return TOKEN_WORD;
61         }
62  /* anything that's not a metachar: return as a plain word */
63 {WORD}  {
64                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
65                 yyget_extra(yyscanner)->inter_word = true;
66                 return TOKEN_WORD;
67         }
68
69 \${VARNAME} |
70 \$\{{VARNAME}\} {
71                 if (yytext[1] == '{') {
72                         yytext[yyleng-1] = '\0';
73                         yytext++;
74                 }
75                 yytext++;
76                 yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
77                                                 true);
78                 yyget_extra(yyscanner)->inter_word = true;
79                 return TOKEN_WORD;
80         }
81
82  /* single-quoted strings: return a single, non-expanded word token */
83 \'      {
84                 yy_push_state(sqstring, yyscanner);
85         }
86 <sqstring>\' {
87                 yy_pop_state(yyscanner);
88         }
89 <sqstring>[^']+ {
90                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
91                 yyget_extra(yyscanner)->inter_word = true;
92                 return TOKEN_WORD;
93         }
94
95  /* double-quoted strings: return a single, expanded word token */
96 \"      {
97                 yy_push_state(dqstring, yyscanner);
98         }
99 <dqstring>\" {
100                 yy_pop_state(yyscanner);
101         }
102 <dqstring>([^"\$]|\\\")+ {
103                 yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
104                 yyget_extra(yyscanner)->inter_word = true;
105                 return TOKEN_WORD;
106         }
107 <dqstring>\${VARNAME} |
108 <dqstring>\$\{{VARNAME}\} {
109                 if (yytext[1] == '{') {
110                         yytext[yyleng-1] = '\0';
111                         yytext++;
112                 }
113                 yytext++;
114                 yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
115                                                 false);
116                 yyget_extra(yyscanner)->inter_word = true;
117                 return TOKEN_WORD;
118         }
119
120
121
122  /* blocks */
123 "{"     { yyget_extra(yyscanner)->inter_word = false; return '{'; }
124 "}"     { yyget_extra(yyscanner)->inter_word = false; return '}'; }
125
126  /* end-of-line */
127 [ \t]*(;|\n)[ \t]*      {
128                 yyget_extra(yyscanner)->inter_word = false;
129                 return TOKEN_EOL;
130         }
131
132  /* strip comments */
133 #.*     ;
134
135 .       {
136                 yyerror(yyget_extra(yyscanner), yyscanner,
137                                 "unknown token '%s'\n", yytext);
138                 yyterminate();
139         }
140
141 %%
142
143 struct grub2_parser;
144
145 void *yyalloc(size_t bytes, void *yyscanner)
146 {
147         struct grub2_parser *parser = yyget_extra(yyscanner);
148         return talloc_size(parser, bytes);
149 }
150
151 void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
152 {
153         struct grub2_parser *parser = yyget_extra(yyscanner);
154         return talloc_realloc_size(parser, ptr, bytes);
155 }
156
157 void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
158 {
159         talloc_free(ptr);
160 }