2
/* yylex.l The scripting lexer. */
4
* GRUB -- GRand Unified Bootloader
5
* Copyright (C) 2009,2010 Free Software Foundation, Inc.
7
* GRUB is free software: you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, either version 3 of the License, or
10
* (at your option) any later version.
12
* GRUB is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21
#include <grub/parser.h>
22
#include <grub/misc.h>
24
#include <grub/script_sh.h>
25
#include "grub_script.tab.h"
27
#define yyfree grub_lexer_yyfree
28
#define yyalloc grub_lexer_yyalloc
29
#define yyrealloc grub_lexer_yyrealloc
32
* As we don't have access to yyscanner, we cannot do much except to
33
* print the fatal error.
35
#define YY_FATAL_ERROR(msg) \
37
grub_printf ("fatal error: %s\n", msg); \
40
#define COPY(str, hint) \
42
copy_string (yyextra, str, hint); \
48
grub_script_lexer_record (yyextra, yytext); \
53
yyextra->lexerstate->type = t; \
54
return GRUB_PARSER_TOKEN_WORD; \
57
/* We don't need YY_INPUT, as we rely on yy_scan_strings */
58
#define YY_INPUT(buf,res,max) do { res = 0; } while (0)
60
/* forward declarations */
61
static void grub_lexer_yyfree (void *, yyscan_t yyscanner);
62
static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner);
63
static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner);
64
static void copy_string (struct grub_parser_param *, const char *,
71
#include <sys/types.h>
73
typedef size_t yy_size_t;
74
#define YY_TYPEDEF_YY_SIZE_T 1
77
* Some flex hacks for -nostdinc; XXX We need to fix these when libc
78
* support becomes availble in GRUB.
85
#define fprintf(...) 0
99
%option never-interactive
101
%option noyyfree noyyalloc noyyrealloc
102
%option nounistd nostdinit nodefault noyylineno noyywrap
104
/* Reduce lexer size, by not defining these. */
105
%option noyy_top_state
106
%option noinput nounput
107
%option noyyget_in noyyset_in
108
%option noyyget_out noyyset_out
109
%option noyyget_debug noyyset_debug
110
%option noyyget_lineno noyyset_lineno
112
%option extra-type="struct grub_parser_param*"
117
CHAR [^{}|&$;<> \t\n\'\"\\]
119
NAME [[:alpha:]_][[:alnum:]_]*
122
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}
123
DQSTR \"([^\\\"]|{ESC})*\"
125
WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
136
{COMMENT} { RECORD; }
138
/* Special symbols */
139
"\n" { RECORD; return GRUB_PARSER_TOKEN_NEWLINE; }
140
"||" { RECORD; return GRUB_PARSER_TOKEN_OR; }
141
"&&" { RECORD; return GRUB_PARSER_TOKEN_AND; }
142
";;" { RECORD; return GRUB_PARSER_TOKEN_SEMI2; }
143
"|" { RECORD; return GRUB_PARSER_TOKEN_PIPE; }
144
"&" { RECORD; return GRUB_PARSER_TOKEN_AMP; }
145
";" { RECORD; return GRUB_PARSER_TOKEN_SEMI; }
146
"<" { RECORD; return GRUB_PARSER_TOKEN_LT; }
147
">" { RECORD; return GRUB_PARSER_TOKEN_GT; }
150
"!" { RECORD; return GRUB_PARSER_TOKEN_NOT; }
151
"{" { RECORD; return GRUB_PARSER_TOKEN_LBR; }
152
"}" { RECORD; return GRUB_PARSER_TOKEN_RBR; }
153
"[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; }
154
"]]" { RECORD; return GRUB_PARSER_TOKEN_LSQBR2; }
155
"time" { RECORD; return GRUB_PARSER_TOKEN_TIME; }
156
"case" { RECORD; return GRUB_PARSER_TOKEN_CASE; }
157
"do" { RECORD; return GRUB_PARSER_TOKEN_DO; }
158
"done" { RECORD; return GRUB_PARSER_TOKEN_DONE; }
159
"elif" { RECORD; return GRUB_PARSER_TOKEN_ELIF; }
160
"else" { RECORD; return GRUB_PARSER_TOKEN_ELSE; }
161
"esac" { RECORD; return GRUB_PARSER_TOKEN_ESAC; }
162
"fi" { RECORD; return GRUB_PARSER_TOKEN_FI; }
163
"for" { RECORD; return GRUB_PARSER_TOKEN_FOR; }
164
"if" { RECORD; return GRUB_PARSER_TOKEN_IF; }
165
"in" { RECORD; return GRUB_PARSER_TOKEN_IN; }
166
"select" { RECORD; return GRUB_PARSER_TOKEN_SELECT; }
167
"then" { RECORD; return GRUB_PARSER_TOKEN_THEN; }
168
"until" { RECORD; return GRUB_PARSER_TOKEN_UNTIL; }
169
"while" { RECORD; return GRUB_PARSER_TOKEN_WHILE; }
170
"function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; }
171
"menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; }
173
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
177
grub_dprintf ("lexer", "word: [%s]\n", yytext);
178
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
179
if (yy_scan_string (yytext, yyscanner))
181
yyextra->lexerstate->merge_start = 1;
182
yy_push_state (SPLIT, yyscanner);
186
grub_script_yyerror (yyextra, 0);
187
yypop_buffer_state (yyscanner);
188
return GRUB_PARSER_TOKEN_WORD;
193
grub_script_yyerror (yyextra, "unrecognized token");
194
return GRUB_PARSER_TOKEN_BAD;
197
/* Split word into multiple args */
200
\\. { COPY (yytext + 1, yyleng - 1); }
202
yy_push_state (DQUOTE, yyscanner);
203
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
206
yy_push_state (SQUOTE, yyscanner);
207
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
210
yy_push_state (VAR, yyscanner);
211
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
214
[^\"\'\$\\]+ { COPY (yytext, yyleng); }
216
yy_pop_state (yyscanner);
217
yypop_buffer_state (yyscanner);
218
yyextra->lexerstate->merge_end = 1;
219
ARG (GRUB_SCRIPT_ARG_TYPE_TEXT);
227
COPY (yytext, yyleng);
228
yy_pop_state (yyscanner);
229
if (YY_START == SPLIT)
230
ARG (GRUB_SCRIPT_ARG_TYPE_VAR);
232
ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR);
237
yytext[yyleng - 1] = '\0';
238
COPY (yytext + 1, yyleng - 2);
239
yy_pop_state (yyscanner);
240
if (YY_START == SPLIT)
241
ARG (GRUB_SCRIPT_ARG_TYPE_VAR);
243
ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR);
245
.|\n { return GRUB_PARSER_TOKEN_BAD; }
250
yy_pop_state (yyscanner);
251
ARG (GRUB_SCRIPT_ARG_TYPE_SQSTR);
253
[^\']+ { COPY (yytext, yyleng); }
257
\\\$ { COPY ("$", 1); }
258
\\\\ { COPY ("\\", 1); }
259
\\\" { COPY ("\"", 1); }
260
\\\n { /* ignore */ }
261
[^\"\$\\\n]+ { COPY (yytext, yyleng); }
263
yy_pop_state (yyscanner);
264
ARG (GRUB_SCRIPT_ARG_TYPE_DQSTR);
267
yy_push_state (VAR, yyscanner);
268
ARG (GRUB_SCRIPT_ARG_TYPE_DQSTR);
270
(.|\n) { COPY (yytext, yyleng); }
274
yypop_buffer_state (yyscanner);
275
if (! grub_script_lexer_yywrap (yyextra))
277
yyextra->lexerstate->eof = 1;
278
return GRUB_PARSER_TOKEN_EOF;
285
grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused)))
291
grub_lexer_yyalloc (yy_size_t size, yyscan_t yyscanner __attribute__ ((unused)))
293
return grub_malloc (size);
297
grub_lexer_yyrealloc (void *ptr, yy_size_t size,
298
yyscan_t yyscanner __attribute__ ((unused)))
300
return grub_realloc (ptr, size);
303
#define MAX(a,b) ((a) < (b) ? (b) : (a))
305
static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint)
311
len = hint ? hint : grub_strlen (str);
312
if (parser->lexerstate->used + len >= parser->lexerstate->size)
314
size = MAX (len, parser->lexerstate->size) * 2;
315
ptr = grub_realloc (parser->lexerstate->text, size);
318
grub_script_yyerror (parser, 0);
322
parser->lexerstate->text = ptr;
323
parser->lexerstate->size = size;
325
grub_strcpy (parser->lexerstate->text + parser->lexerstate->used - 1, str);
326
parser->lexerstate->used += len;