]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - scripts/kconfig/zconf.l
kconfig: fix ambiguous grammar in terms of new lines
[mirror_ubuntu-jammy-kernel.git] / scripts / kconfig / zconf.l
CommitLineData
674eed8a 1%option nostdinit noyywrap never-interactive full ecs
18492685 2%option 8bit nodefault yylineno
9ced3bdd 3%x COMMAND HELP STRING PARAM ASSIGN_VAL
1da177e4
LT
4%{
5/*
6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
7 * Released under the terms of the GNU GPL v2.0.
8 */
9
9ced3bdd 10#include <assert.h>
1da177e4
LT
11#include <limits.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <unistd.h>
16
1da177e4
LT
17#include "lkc.h"
18
cc66bca7
MY
19#define YY_DECL static int yylex1(void)
20
1da177e4
LT
21#define START_STRSIZE 16
22
a02f0570
RZ
23static struct {
24 struct file *file;
25 int lineno;
26} current_pos;
27
cc66bca7 28static int prev_token = T_EOL;
7a88488b 29static char *text;
1da177e4
LT
30static int text_size, text_asize;
31
32struct buffer {
bb66fc67
MY
33 struct buffer *parent;
34 YY_BUFFER_STATE state;
1da177e4
LT
35};
36
37struct buffer *current_buf;
38
39static int last_ts, first_ts;
40
104daea1
MY
41static char *expand_token(const char *in, size_t n);
42static void append_expanded_string(const char *in);
1da177e4 43static void zconf_endhelp(void);
a02f0570 44static void zconf_endfile(void);
1da177e4 45
65166571 46static void new_string(void)
1da177e4 47{
177acf78 48 text = xmalloc(START_STRSIZE);
1da177e4 49 text_asize = START_STRSIZE;
1da177e4 50 text_size = 0;
7a88488b 51 *text = 0;
1da177e4
LT
52}
53
65166571 54static void append_string(const char *str, int size)
1da177e4
LT
55{
56 int new_size = text_size + size + 1;
57 if (new_size > text_asize) {
7a88488b
RZ
58 new_size += START_STRSIZE - 1;
59 new_size &= -START_STRSIZE;
d717f24d 60 text = xrealloc(text, new_size);
1da177e4 61 text_asize = new_size;
1da177e4 62 }
7a88488b 63 memcpy(text + text_size, str, size);
1da177e4 64 text_size += size;
7a88488b 65 text[text_size] = 0;
1da177e4
LT
66}
67
65166571 68static void alloc_string(const char *str, int size)
1da177e4 69{
177acf78 70 text = xmalloc(size + 1);
1da177e4
LT
71 memcpy(text, str, size);
72 text[size] = 0;
73}
c2264564
AR
74
75static void warn_ignored_character(char chr)
76{
77 fprintf(stderr,
78 "%s:%d:warning: ignoring unsupported character '%c'\n",
77c1c0fa 79 current_file->name, yylineno, chr);
c2264564 80}
1da177e4
LT
81%}
82
c2264564 83n [A-Za-z0-9_-]
1da177e4
LT
84
85%%
86 int str = 0;
87 int ts, i;
88
a02f0570
RZ
89[ \t]*#.*\n |
90[ \t]*\n {
a02f0570
RZ
91 return T_EOL;
92}
1da177e4 93[ \t]*#.*
1da177e4
LT
94. {
95 unput(yytext[0]);
96 BEGIN(COMMAND);
97}
98
99
100<COMMAND>{
1da177e4 101 {n}+ {
61f956f5 102 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
a02f0570 103 current_pos.file = current_file;
18492685 104 current_pos.lineno = yylineno;
7a88488b 105 if (id && id->flags & TF_COMMAND) {
9de07153 106 BEGIN(PARAM);
765f4cde 107 yylval.id = id;
7a88488b
RZ
108 return id->token;
109 }
1da177e4 110 alloc_string(yytext, yyleng);
765f4cde 111 yylval.string = text;
9ced3bdd 112 return T_VARIABLE;
1da177e4 113 }
82bc8bd8
MY
114 ({n}|$)+ {
115 /* this token includes at least one '$' */
116 yylval.string = expand_token(yytext, yyleng);
117 if (strlen(yylval.string))
118 return T_VARIABLE;
119 free(yylval.string);
120 }
1175c025
MY
121 "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
122 ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
ed2a22f2 123 "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
9ced3bdd 124 [[:blank:]]+
c2264564 125 . warn_ignored_character(*yytext);
a02f0570
RZ
126 \n {
127 BEGIN(INITIAL);
a02f0570
RZ
128 return T_EOL;
129 }
1da177e4
LT
130}
131
9ced3bdd
MY
132<ASSIGN_VAL>{
133 [^[:blank:]\n]+.* {
134 alloc_string(yytext, yyleng);
135 yylval.string = text;
136 return T_ASSIGN_VAL;
137 }
138 \n { BEGIN(INITIAL); return T_EOL; }
139 .
140}
141
1da177e4
LT
142<PARAM>{
143 "&&" return T_AND;
144 "||" return T_OR;
145 "(" return T_OPEN_PAREN;
146 ")" return T_CLOSE_PAREN;
147 "!" return T_NOT;
148 "=" return T_EQUAL;
149 "!=" return T_UNEQUAL;
31847b67
JB
150 "<=" return T_LESS_EQUAL;
151 ">=" return T_GREATER_EQUAL;
152 "<" return T_LESS;
153 ">" return T_GREATER;
1da177e4
LT
154 \"|\' {
155 str = yytext[0];
156 new_string();
157 BEGIN(STRING);
158 }
18492685 159 \n BEGIN(INITIAL); return T_EOL;
c2264564 160 ({n}|[/.])+ {
61f956f5 161 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
3370f9f0 162 if (id && id->flags & TF_PARAM) {
765f4cde 163 yylval.id = id;
7a88488b 164 return id->token;
3370f9f0 165 }
1da177e4 166 alloc_string(yytext, yyleng);
765f4cde 167 yylval.string = text;
1da177e4
LT
168 return T_WORD;
169 }
104daea1
MY
170 ({n}|[/.$])+ {
171 /* this token includes at least one '$' */
172 yylval.string = expand_token(yytext, yyleng);
173 if (strlen(yylval.string))
174 return T_WORD;
175 free(yylval.string);
176 }
1da177e4 177 #.* /* comment */
18492685 178 \\\n ;
2e0d737f 179 [[:blank:]]+
c2264564 180 . warn_ignored_character(*yytext);
1da177e4
LT
181 <<EOF>> {
182 BEGIN(INITIAL);
183 }
184}
185
186<STRING>{
104daea1 187 "$".* append_expanded_string(yytext);
104daea1 188 [^$'"\\\n]+ {
1da177e4
LT
189 append_string(yytext, yyleng);
190 }
1da177e4
LT
191 \\.? {
192 append_string(yytext + 1, yyleng - 1);
193 }
194 \'|\" {
195 if (str == yytext[0]) {
196 BEGIN(PARAM);
765f4cde 197 yylval.string = text;
1da177e4
LT
198 return T_WORD_QUOTE;
199 } else
200 append_string(yytext, 1);
201 }
202 \n {
9e3e10c7
MY
203 fprintf(stderr,
204 "%s:%d:warning: multi-line strings not supported\n",
205 zconf_curname(), zconf_lineno());
21c5ecf6 206 unput('\n');
1da177e4 207 BEGIN(INITIAL);
21c5ecf6
MY
208 yylval.string = text;
209 return T_WORD_QUOTE;
1da177e4
LT
210 }
211 <<EOF>> {
212 BEGIN(INITIAL);
fbac5977
MY
213 yylval.string = text;
214 return T_WORD_QUOTE;
1da177e4
LT
215 }
216}
217
218<HELP>{
219 [ \t]+ {
220 ts = 0;
221 for (i = 0; i < yyleng; i++) {
222 if (yytext[i] == '\t')
223 ts = (ts & ~7) + 8;
224 else
225 ts++;
226 }
227 last_ts = ts;
228 if (first_ts) {
229 if (ts < first_ts) {
230 zconf_endhelp();
231 return T_HELPTEXT;
232 }
233 ts -= first_ts;
234 while (ts > 8) {
235 append_string(" ", 8);
236 ts -= 8;
237 }
238 append_string(" ", ts);
239 }
240 }
241 [ \t]*\n/[^ \t\n] {
1da177e4
LT
242 zconf_endhelp();
243 return T_HELPTEXT;
244 }
245 [ \t]*\n {
1da177e4
LT
246 append_string("\n", 1);
247 }
248 [^ \t\n].* {
f7a4b4cd
EG
249 while (yyleng) {
250 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
251 break;
252 yyleng--;
253 }
1da177e4
LT
254 append_string(yytext, yyleng);
255 if (!first_ts)
256 first_ts = last_ts;
257 }
258 <<EOF>> {
259 zconf_endhelp();
260 return T_HELPTEXT;
261 }
262}
263
264<<EOF>> {
a02f0570 265 if (current_file) {
1da177e4 266 zconf_endfile();
a02f0570 267 return T_EOL;
1da177e4
LT
268 }
269 fclose(yyin);
270 yyterminate();
271}
272
273%%
cc66bca7
MY
274
275/* second stage lexer */
276int yylex(void)
277{
278 int token;
279
280repeat:
281 token = yylex1();
282
283 /* Do not pass unneeded T_EOL to the parser. */
284 if ((prev_token == T_EOL || prev_token == T_HELPTEXT) && token == T_EOL)
285 goto repeat;
286
287 prev_token = token;
288
289 return token;
290}
291
104daea1
MY
292static char *expand_token(const char *in, size_t n)
293{
294 char *out;
295 int c;
296 char c2;
297 const char *rest, *end;
298
299 new_string();
300 append_string(in, n);
301
302 /* get the whole line because we do not know the end of token. */
303 while ((c = input()) != EOF) {
304 if (c == '\n') {
305 unput(c);
306 break;
307 }
308 c2 = c;
309 append_string(&c2, 1);
310 }
311
312 rest = text;
313 out = expand_one_token(&rest);
314
315 /* push back unused characters to the input stream */
316 end = rest + strlen(rest);
317 while (end > rest)
318 unput(*--end);
319
320 free(text);
321
322 return out;
323}
324
325static void append_expanded_string(const char *str)
326{
327 const char *end;
328 char *res;
329
330 str++;
331
332 res = expand_dollar(&str);
333
334 /* push back unused characters to the input stream */
335 end = str + strlen(str);
336 while (end > str)
337 unput(*--end);
338
339 append_string(res, strlen(res));
340
341 free(res);
342}
343
1da177e4
LT
344void zconf_starthelp(void)
345{
346 new_string();
347 last_ts = first_ts = 0;
348 BEGIN(HELP);
349}
350
351static void zconf_endhelp(void)
352{
765f4cde 353 yylval.string = text;
1da177e4
LT
354 BEGIN(INITIAL);
355}
356
357
358/*
359 * Try to open specified file with following names:
360 * ./name
361 * $(srctree)/name
362 * The latter is used when srctree is separate from objtree
363 * when compiling the kernel.
364 * Return NULL if file is not found.
365 */
366FILE *zconf_fopen(const char *name)
367{
368 char *env, fullname[PATH_MAX+1];
369 FILE *f;
370
371 f = fopen(name, "r");
11de39e2 372 if (!f && name != NULL && name[0] != '/') {
1da177e4
LT
373 env = getenv(SRCTREE);
374 if (env) {
375 sprintf(fullname, "%s/%s", env, name);
376 f = fopen(fullname, "r");
377 }
378 }
379 return f;
380}
381
382void zconf_initscan(const char *name)
383{
384 yyin = zconf_fopen(name);
385 if (!yyin) {
9e3e10c7 386 fprintf(stderr, "can't find file %s\n", name);
1da177e4
LT
387 exit(1);
388 }
389
177acf78 390 current_buf = xmalloc(sizeof(*current_buf));
1da177e4
LT
391 memset(current_buf, 0, sizeof(*current_buf));
392
393 current_file = file_lookup(name);
18492685 394 yylineno = 1;
1da177e4
LT
395}
396
397void zconf_nextfile(const char *name)
398{
f094f8a1 399 struct file *iter;
1da177e4 400 struct file *file = file_lookup(name);
177acf78 401 struct buffer *buf = xmalloc(sizeof(*buf));
1da177e4
LT
402 memset(buf, 0, sizeof(*buf));
403
404 current_buf->state = YY_CURRENT_BUFFER;
e82dae90 405 yyin = zconf_fopen(file->name);
1da177e4 406 if (!yyin) {
9e3e10c7
MY
407 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
408 zconf_curname(), zconf_lineno(), file->name);
1da177e4
LT
409 exit(1);
410 }
411 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
412 buf->parent = current_buf;
413 current_buf = buf;
414
18492685 415 current_file->lineno = yylineno;
379a8eb8
MY
416 file->parent = current_file;
417
418 for (iter = current_file; iter; iter = iter->parent) {
419 if (!strcmp(iter->name, file->name)) {
9e3e10c7 420 fprintf(stderr,
32a94b8b
MY
421 "Recursive inclusion detected.\n"
422 "Inclusion path:\n"
379a8eb8
MY
423 " current file : %s\n", file->name);
424 iter = file;
5ae6fcc4 425 do {
f094f8a1 426 iter = iter->parent;
32a94b8b 427 fprintf(stderr, " included from: %s:%d\n",
5ae6fcc4 428 iter->name, iter->lineno - 1);
379a8eb8 429 } while (strcmp(iter->name, file->name));
f094f8a1
YM
430 exit(1);
431 }
1da177e4 432 }
379a8eb8 433
18492685 434 yylineno = 1;
1da177e4
LT
435 current_file = file;
436}
437
a02f0570 438static void zconf_endfile(void)
1da177e4
LT
439{
440 struct buffer *parent;
441
1da177e4 442 current_file = current_file->parent;
18492685
MY
443 if (current_file)
444 yylineno = current_file->lineno;
1da177e4
LT
445
446 parent = current_buf->parent;
447 if (parent) {
448 fclose(yyin);
449 yy_delete_buffer(YY_CURRENT_BUFFER);
450 yy_switch_to_buffer(parent->state);
451 }
452 free(current_buf);
453 current_buf = parent;
1da177e4
LT
454}
455
456int zconf_lineno(void)
457{
a02f0570 458 return current_pos.lineno;
1da177e4
LT
459}
460
2e7a0918 461const char *zconf_curname(void)
1da177e4 462{
a02f0570 463 return current_pos.file ? current_pos.file->name : "<none>";
1da177e4 464}