1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
%{
#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 *"
%option header-file="lexer.h"
%option outfile="lexer.c"
%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);
}
|