Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / script / lexer.c
blob89cf67706509d0dd0920273cd00868971433583d
1 /* lexer.c - The scripting lexer. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #include <grub/parser.h>
23 #include <grub/misc.h>
24 #include <grub/mm.h>
25 #include <grub/script_sh.h>
26 #include <grub/i18n.h>
28 #define yytext_ptr char *
29 #include "grub_script.tab.h"
30 #include "grub_script.yy.h"
32 void
33 grub_script_lexer_ref (struct grub_lexer_param *state)
35 state->refs++;
38 void
39 grub_script_lexer_deref (struct grub_lexer_param *state)
41 state->refs--;
44 /* Start recording all characters passing through the lexer. */
45 unsigned
46 grub_script_lexer_record_start (struct grub_parser_param *parser)
48 struct grub_lexer_param *lexer = parser->lexerstate;
50 lexer->record++;
51 if (lexer->recording)
52 return lexer->recordpos;
54 lexer->recordpos = 0;
55 lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE;
56 lexer->recording = grub_malloc (lexer->recordlen);
57 if (!lexer->recording)
59 grub_script_yyerror (parser, 0);
60 lexer->recordlen = 0;
62 return lexer->recordpos;
65 char *
66 grub_script_lexer_record_stop (struct grub_parser_param *parser, unsigned offset)
68 int count;
69 char *result;
70 struct grub_lexer_param *lexer = parser->lexerstate;
72 if (!lexer->record)
73 return 0;
75 lexer->record--;
76 if (!lexer->recording)
77 return 0;
79 count = lexer->recordpos - offset;
80 result = grub_script_malloc (parser, count + 1);
81 if (result) {
82 grub_strncpy (result, lexer->recording + offset, count);
83 result[count] = '\0';
86 if (lexer->record == 0)
88 grub_free (lexer->recording);
89 lexer->recording = 0;
90 lexer->recordlen = 0;
91 lexer->recordpos = 0;
93 return result;
96 /* Record STR if input recording is enabled. */
97 void
98 grub_script_lexer_record (struct grub_parser_param *parser, char *str)
100 int len;
101 char *old;
102 struct grub_lexer_param *lexer = parser->lexerstate;
104 if (!lexer->record || !lexer->recording)
105 return;
107 len = grub_strlen (str);
108 if (lexer->recordpos + len + 1 > lexer->recordlen)
110 old = lexer->recording;
111 if (lexer->recordlen < len)
112 lexer->recordlen = len;
113 lexer->recordlen *= 2;
114 lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
115 if (!lexer->recording)
117 grub_free (old);
118 lexer->recordpos = 0;
119 lexer->recordlen = 0;
120 grub_script_yyerror (parser, 0);
121 return;
124 grub_strcpy (lexer->recording + lexer->recordpos, str);
125 lexer->recordpos += len;
128 /* Read next line of input if necessary, and set yyscanner buffers. */
130 grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
131 const char *input)
133 grub_size_t len = 0;
134 char *p = 0;
135 char *line = 0;
136 YY_BUFFER_STATE buffer;
137 struct grub_lexer_param *lexerstate = parserstate->lexerstate;
139 if (! lexerstate->refs && ! lexerstate->prefix && ! input)
140 return 1;
142 if (! lexerstate->getline && ! input)
144 grub_script_yyerror (parserstate, N_("unexpected end of file"));
145 return 1;
148 line = 0;
149 if (! input)
150 lexerstate->getline (&line, 1, lexerstate->getline_data);
151 else
152 line = grub_strdup (input);
154 if (! line)
156 grub_script_yyerror (parserstate, N_("out of memory"));
157 return 1;
160 len = grub_strlen (line);
162 /* Ensure '\n' at the end. */
163 if (line[0] == '\0')
165 grub_free (line);
166 line = grub_strdup ("\n");
167 len = 1;
169 else if (len && line[len - 1] != '\n')
171 p = grub_realloc (line, len + 2);
172 if (p)
174 p[len++] = '\n';
175 p[len] = '\0';
177 line = p;
180 if (! line)
182 grub_script_yyerror (parserstate, N_("out of memory"));
183 return 1;
186 /* Prepend any left over unput-text. */
187 if (lexerstate->prefix)
189 int plen = grub_strlen (lexerstate->prefix);
191 p = grub_malloc (len + plen + 1);
192 if (! p)
194 grub_free (line);
195 return 1;
197 grub_strcpy (p, lexerstate->prefix);
198 lexerstate->prefix = 0;
200 grub_strcpy (p + plen, line);
201 grub_free (line);
203 line = p;
204 len = len + plen;
207 buffer = yy_scan_string (line, lexerstate->yyscanner);
208 grub_free (line);
210 if (! buffer)
212 grub_script_yyerror (parserstate, 0);
213 return 1;
215 return 0;
218 struct grub_lexer_param *
219 grub_script_lexer_init (struct grub_parser_param *parser, char *script,
220 grub_reader_getline_t arg_getline, void *getline_data)
222 struct grub_lexer_param *lexerstate;
224 lexerstate = grub_zalloc (sizeof (*lexerstate));
225 if (!lexerstate)
226 return 0;
228 lexerstate->size = GRUB_LEXER_INITIAL_TEXT_SIZE;
229 lexerstate->text = grub_malloc (lexerstate->size);
230 if (!lexerstate->text)
232 grub_free (lexerstate);
233 return 0;
236 lexerstate->getline = arg_getline;
237 lexerstate->getline_data = getline_data;
238 /* The other elements of lexerstate are all zeros already. */
240 if (yylex_init (&lexerstate->yyscanner))
242 grub_free (lexerstate->text);
243 grub_free (lexerstate);
244 return 0;
247 yyset_extra (parser, lexerstate->yyscanner);
248 parser->lexerstate = lexerstate;
250 if (grub_script_lexer_yywrap (parser, script ?: "\n"))
252 parser->lexerstate = 0;
253 yylex_destroy (lexerstate->yyscanner);
254 grub_free (lexerstate->yyscanner);
255 grub_free (lexerstate->text);
256 grub_free (lexerstate);
257 return 0;
260 return lexerstate;
263 void
264 grub_script_lexer_fini (struct grub_lexer_param *lexerstate)
266 if (!lexerstate)
267 return;
269 yylex_destroy (lexerstate->yyscanner);
271 grub_free (lexerstate->recording);
272 grub_free (lexerstate->text);
273 grub_free (lexerstate);
277 grub_script_yylex (union YYSTYPE *value,
278 struct grub_parser_param *parserstate)
280 char *str;
281 int token;
282 grub_script_arg_type_t type;
283 struct grub_lexer_param *lexerstate = parserstate->lexerstate;
285 value->arg = 0;
286 if (parserstate->err)
287 return GRUB_PARSER_TOKEN_BAD;
289 if (lexerstate->eof)
290 return GRUB_PARSER_TOKEN_EOF;
293 * Words with environment variables, like foo${bar}baz needs
294 * multiple tokens to be merged into a single grub_script_arg. We
295 * use two variables to achieve this: lexerstate->merge_start and
296 * lexerstate->merge_end
299 lexerstate->merge_start = 0;
300 lexerstate->merge_end = 0;
303 /* Empty lexerstate->text. */
304 lexerstate->used = 1;
305 lexerstate->text[0] = '\0';
307 token = yylex (value, lexerstate->yyscanner);
308 if (token == GRUB_PARSER_TOKEN_BAD)
309 break;
311 /* Merging feature uses lexerstate->text instead of yytext. */
312 if (lexerstate->merge_start)
314 str = lexerstate->text;
315 type = lexerstate->type;
317 else
319 str = yyget_text (lexerstate->yyscanner);
320 type = GRUB_SCRIPT_ARG_TYPE_TEXT;
322 grub_dprintf("lexer", "token %u text [%s]\n", token, str);
324 value->arg = grub_script_arg_add (parserstate, value->arg, type, str);
326 while (lexerstate->merge_start && !lexerstate->merge_end);
328 if (!value->arg || parserstate->err)
329 return GRUB_PARSER_TOKEN_BAD;
331 return token;
334 void
335 grub_script_yyerror (struct grub_parser_param *state, char const *err)
337 if (err)
338 grub_error (GRUB_ERR_INVALID_COMMAND, err);
340 grub_print_error ();
341 state->err++;