]> Git Repo - linux.git/blob - scripts/kconfig/lexer.l
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / scripts / kconfig / lexer.l
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2002 Roman Zippel <[email protected]>
4  */
5 %option nostdinit noyywrap never-interactive full ecs
6 %option 8bit nodefault yylineno
7 %x ASSIGN_VAL HELP STRING
8 %{
9
10 #include <assert.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "lkc.h"
17 #include "preprocess.h"
18
19 #include "parser.tab.h"
20
21 #define YY_DECL         static int yylex1(void)
22
23 #define START_STRSIZE   16
24
25 /* The Kconfig file currently being parsed.  */
26 const char *cur_filename;
27
28 /*
29  * The line number of the current statement. This does not match yylineno.
30  * yylineno is used by the lexer, while cur_lineno is used by the parser.
31  */
32 int cur_lineno;
33
34 static int prev_prev_token = T_EOL;
35 static int prev_token = T_EOL;
36 static char *text;
37 static int text_size, text_asize;
38
39 struct buffer {
40         struct buffer *parent;
41         YY_BUFFER_STATE state;
42         int yylineno;
43         const char *filename;
44         int source_lineno;
45 };
46
47 static struct buffer *current_buf;
48
49 static int last_ts, first_ts;
50
51 static char *expand_token(const char *in, size_t n);
52 static void append_expanded_string(const char *in);
53 static void zconf_endhelp(void);
54 static void zconf_endfile(void);
55
56 static void new_string(void)
57 {
58         text = xmalloc(START_STRSIZE);
59         text_asize = START_STRSIZE;
60         text_size = 0;
61         *text = 0;
62 }
63
64 static void append_string(const char *str, int size)
65 {
66         int new_size = text_size + size + 1;
67         if (new_size > text_asize) {
68                 new_size += START_STRSIZE - 1;
69                 new_size &= -START_STRSIZE;
70                 text = xrealloc(text, new_size);
71                 text_asize = new_size;
72         }
73         memcpy(text + text_size, str, size);
74         text_size += size;
75         text[text_size] = 0;
76 }
77
78 static void alloc_string(const char *str, int size)
79 {
80         text = xmalloc(size + 1);
81         memcpy(text, str, size);
82         text[size] = 0;
83 }
84
85 static void warn_ignored_character(char chr)
86 {
87         fprintf(stderr,
88                 "%s:%d:warning: ignoring unsupported character '%c'\n",
89                 cur_filename, yylineno, chr);
90 }
91 %}
92
93 n       [A-Za-z0-9_-]
94
95 %%
96         char open_quote = 0;
97
98 #.*                     /* ignore comment */
99 [ \t]*                  /* whitespaces */
100 \\\n                    /* escaped new line */
101 \n                      return T_EOL;
102 "bool"                  return T_BOOL;
103 "choice"                return T_CHOICE;
104 "comment"               return T_COMMENT;
105 "config"                return T_CONFIG;
106 "def_bool"              return T_DEF_BOOL;
107 "def_tristate"          return T_DEF_TRISTATE;
108 "default"               return T_DEFAULT;
109 "depends"               return T_DEPENDS;
110 "endchoice"             return T_ENDCHOICE;
111 "endif"                 return T_ENDIF;
112 "endmenu"               return T_ENDMENU;
113 "help"                  return T_HELP;
114 "hex"                   return T_HEX;
115 "if"                    return T_IF;
116 "imply"                 return T_IMPLY;
117 "int"                   return T_INT;
118 "mainmenu"              return T_MAINMENU;
119 "menu"                  return T_MENU;
120 "menuconfig"            return T_MENUCONFIG;
121 "modules"               return T_MODULES;
122 "on"                    return T_ON;
123 "prompt"                return T_PROMPT;
124 "range"                 return T_RANGE;
125 "select"                return T_SELECT;
126 "source"                return T_SOURCE;
127 "string"                return T_STRING;
128 "tristate"              return T_TRISTATE;
129 "visible"               return T_VISIBLE;
130 "||"                    return T_OR;
131 "&&"                    return T_AND;
132 "="                     return T_EQUAL;
133 "!="                    return T_UNEQUAL;
134 "<"                     return T_LESS;
135 "<="                    return T_LESS_EQUAL;
136 ">"                     return T_GREATER;
137 ">="                    return T_GREATER_EQUAL;
138 "!"                     return T_NOT;
139 "("                     return T_OPEN_PAREN;
140 ")"                     return T_CLOSE_PAREN;
141 ":="                    return T_COLON_EQUAL;
142 "+="                    return T_PLUS_EQUAL;
143 \"|\'                   {
144                                 open_quote = yytext[0];
145                                 new_string();
146                                 BEGIN(STRING);
147                         }
148 {n}+                    {
149                                 alloc_string(yytext, yyleng);
150                                 yylval.string = text;
151                                 return T_WORD;
152                         }
153 ({n}|$)+                {
154                                 /* this token includes at least one '$' */
155                                 yylval.string = expand_token(yytext, yyleng);
156                                 if (strlen(yylval.string))
157                                         return T_WORD;
158                                 free(yylval.string);
159                         }
160 .                       warn_ignored_character(*yytext);
161
162 <ASSIGN_VAL>{
163         [^[:blank:]\n]+.*       {
164                 alloc_string(yytext, yyleng);
165                 yylval.string = text;
166                 return T_ASSIGN_VAL;
167         }
168         \n      { BEGIN(INITIAL); return T_EOL; }
169         .
170 }
171
172 <STRING>{
173         "$".*   append_expanded_string(yytext);
174         [^$'"\\\n]+     {
175                 append_string(yytext, yyleng);
176         }
177         \\.?    {
178                 append_string(yytext + 1, yyleng - 1);
179         }
180         \'|\"   {
181                 if (open_quote == yytext[0]) {
182                         BEGIN(INITIAL);
183                         yylval.string = text;
184                         return T_WORD_QUOTE;
185                 } else
186                         append_string(yytext, 1);
187         }
188         \n      {
189                 fprintf(stderr,
190                         "%s:%d:warning: multi-line strings not supported\n",
191                         cur_filename, cur_lineno);
192                 unput('\n');
193                 BEGIN(INITIAL);
194                 yylval.string = text;
195                 return T_WORD_QUOTE;
196         }
197         <<EOF>> {
198                 BEGIN(INITIAL);
199                 yylval.string = text;
200                 return T_WORD_QUOTE;
201         }
202 }
203
204 <HELP>{
205         [ \t]+  {
206                 int ts, i;
207
208                 ts = 0;
209                 for (i = 0; i < yyleng; i++) {
210                         if (yytext[i] == '\t')
211                                 ts = (ts & ~7) + 8;
212                         else
213                                 ts++;
214                 }
215                 last_ts = ts;
216                 if (first_ts) {
217                         if (ts < first_ts) {
218                                 zconf_endhelp();
219                                 return T_HELPTEXT;
220                         }
221                         ts -= first_ts;
222                         while (ts > 8) {
223                                 append_string("        ", 8);
224                                 ts -= 8;
225                         }
226                         append_string("        ", ts);
227                 }
228         }
229         [ \t]*\n/[^ \t\n] {
230                 zconf_endhelp();
231                 return T_HELPTEXT;
232         }
233         [ \t]*\n        {
234                 append_string("\n", 1);
235         }
236         [^ \t\n].* {
237                 while (yyleng) {
238                         if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
239                                 break;
240                         yyleng--;
241                 }
242                 append_string(yytext, yyleng);
243                 if (!first_ts)
244                         first_ts = last_ts;
245         }
246         <<EOF>> {
247                 zconf_endhelp();
248                 return T_HELPTEXT;
249         }
250 }
251
252 <<EOF>> {
253         BEGIN(INITIAL);
254
255         if (prev_token != T_EOL && prev_token != T_HELPTEXT)
256                 fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
257                         cur_filename, yylineno);
258
259         if (current_buf) {
260                 zconf_endfile();
261                 return T_EOL;
262         }
263         fclose(yyin);
264         yyterminate();
265 }
266
267 %%
268
269 /* second stage lexer */
270 int yylex(void)
271 {
272         int token;
273
274 repeat:
275         token = yylex1();
276
277         if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
278                 if (token == T_EOL)
279                         /* Do not pass unneeded T_EOL to the parser. */
280                         goto repeat;
281                 else
282                         /*
283                          * For the parser, update lineno at the first token
284                          * of each statement. Generally, \n is a statement
285                          * terminator in Kconfig, but it is not always true
286                          * because \n could be escaped by a backslash.
287                          */
288                         cur_lineno = yylineno;
289         }
290
291         if (prev_prev_token == T_EOL && prev_token == T_WORD &&
292             (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
293                 BEGIN(ASSIGN_VAL);
294
295         prev_prev_token = prev_token;
296         prev_token = token;
297
298         return token;
299 }
300
301 static char *expand_token(const char *in, size_t n)
302 {
303         char *out;
304         int c;
305         char c2;
306         const char *rest, *end;
307
308         new_string();
309         append_string(in, n);
310
311         /*
312          * get the whole line because we do not know the end of token.
313          * input() returns 0 (not EOF!) when it reachs the end of file.
314          */
315         while ((c = input()) != 0) {
316                 if (c == '\n') {
317                         unput(c);
318                         break;
319                 }
320                 c2 = c;
321                 append_string(&c2, 1);
322         }
323
324         rest = text;
325         out = expand_one_token(&rest);
326
327         /* push back unused characters to the input stream */
328         end = rest + strlen(rest);
329         while (end > rest)
330                 unput(*--end);
331
332         free(text);
333
334         return out;
335 }
336
337 static void append_expanded_string(const char *str)
338 {
339         const char *end;
340         char *res;
341
342         str++;
343
344         res = expand_dollar(&str);
345
346         /* push back unused characters to the input stream */
347         end = str + strlen(str);
348         while (end > str)
349                 unput(*--end);
350
351         append_string(res, strlen(res));
352
353         free(res);
354 }
355
356 void zconf_starthelp(void)
357 {
358         new_string();
359         last_ts = first_ts = 0;
360         BEGIN(HELP);
361 }
362
363 static void zconf_endhelp(void)
364 {
365         yylval.string = text;
366         BEGIN(INITIAL);
367 }
368
369
370 /*
371  * Try to open specified file with following names:
372  * ./name
373  * $(srctree)/name
374  * The latter is used when srctree is separate from objtree
375  * when compiling the kernel.
376  * Return NULL if file is not found.
377  */
378 FILE *zconf_fopen(const char *name)
379 {
380         char *env, fullname[PATH_MAX+1];
381         FILE *f;
382
383         f = fopen(name, "r");
384         if (!f && name != NULL && name[0] != '/') {
385                 env = getenv(SRCTREE);
386                 if (env) {
387                         snprintf(fullname, sizeof(fullname),
388                                  "%s/%s", env, name);
389                         f = fopen(fullname, "r");
390                 }
391         }
392         return f;
393 }
394
395 void zconf_initscan(const char *name)
396 {
397         yyin = zconf_fopen(name);
398         if (!yyin) {
399                 fprintf(stderr, "can't find file %s\n", name);
400                 exit(1);
401         }
402
403         cur_filename = file_lookup(name);
404         yylineno = 1;
405 }
406
407 void zconf_nextfile(const char *name)
408 {
409         struct buffer *buf = xmalloc(sizeof(*buf));
410         bool recur_include = false;
411
412         buf->state = YY_CURRENT_BUFFER;
413         buf->yylineno = yylineno;
414         buf->filename = cur_filename;
415         buf->source_lineno = cur_lineno;
416         buf->parent = current_buf;
417         current_buf = buf;
418         yyin = zconf_fopen(name);
419         if (!yyin) {
420                 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
421                         cur_filename, cur_lineno, name);
422                 exit(1);
423         }
424         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
425
426         for (buf = current_buf; buf; buf = buf->parent) {
427                 if (!strcmp(buf->filename, name))
428                         recur_include = true;
429         }
430
431         if (recur_include) {
432                 fprintf(stderr,
433                         "Recursive inclusion detected.\n"
434                         "Inclusion path:\n"
435                         "  current file : %s\n", name);
436
437                 for (buf = current_buf; buf; buf = buf->parent)
438                         fprintf(stderr, "  included from: %s:%d\n",
439                                 buf->filename, buf->source_lineno);
440                 exit(1);
441         }
442
443         yylineno = 1;
444         cur_filename = file_lookup(name);
445 }
446
447 static void zconf_endfile(void)
448 {
449         struct buffer *tmp;
450
451         fclose(yyin);
452         yy_delete_buffer(YY_CURRENT_BUFFER);
453         yy_switch_to_buffer(current_buf->state);
454         yylineno = current_buf->yylineno;
455         cur_filename = current_buf->filename;
456         tmp = current_buf;
457         current_buf = current_buf->parent;
458         free(tmp);
459 }
This page took 0.059696 seconds and 4 git commands to generate.