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