blob: 9b083a176fb42fffe7753e37af460e39dc650fac [file] [log] [blame]
Arnaud Lacombe674eed82011-06-07 13:34:05 -04001%option nostdinit noyywrap never-interactive full ecs
Masahiro Yamada18492682018-03-23 02:00:14 +09002%option 8bit nodefault yylineno
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +09003%x COMMAND HELP STRING PARAM ASSIGN_VAL
Linus Torvalds1da177e2005-04-16 15:20:36 -07004%{
5/*
6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
7 * Released under the terms of the GNU GPL v2.0.
8 */
9
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +090010#include <assert.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <limits.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <unistd.h>
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "lkc.h"
18
Masahiro Yamadacc66bca2018-12-11 20:00:49 +090019#define YY_DECL static int yylex1(void)
20
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#define START_STRSIZE 16
22
Roman Zippela02f0572005-11-08 21:34:53 -080023static struct {
24 struct file *file;
25 int lineno;
26} current_pos;
27
Masahiro Yamada824fa3b2018-12-11 20:01:08 +090028static int prev_prev_token = T_EOL;
Masahiro Yamadacc66bca2018-12-11 20:00:49 +090029static int prev_token = T_EOL;
Roman Zippel7a884882005-11-08 21:34:51 -080030static char *text;
Linus Torvalds1da177e2005-04-16 15:20:36 -070031static int text_size, text_asize;
32
33struct buffer {
Masahiro Yamadabb66fc62014-06-10 19:08:13 +090034 struct buffer *parent;
35 YY_BUFFER_STATE state;
Linus Torvalds1da177e2005-04-16 15:20:36 -070036};
37
38struct buffer *current_buf;
39
40static int last_ts, first_ts;
41
Masahiro Yamada104daea2018-05-28 18:21:40 +090042static char *expand_token(const char *in, size_t n);
43static void append_expanded_string(const char *in);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044static void zconf_endhelp(void);
Roman Zippela02f0572005-11-08 21:34:53 -080045static void zconf_endfile(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Josh Triplett65166572009-10-15 12:13:36 -070047static void new_string(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
Alan Cox177acf72012-11-06 14:32:08 +000049 text = xmalloc(START_STRSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 text_asize = START_STRSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 text_size = 0;
Roman Zippel7a884882005-11-08 21:34:51 -080052 *text = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053}
54
Josh Triplett65166572009-10-15 12:13:36 -070055static void append_string(const char *str, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
57 int new_size = text_size + size + 1;
58 if (new_size > text_asize) {
Roman Zippel7a884882005-11-08 21:34:51 -080059 new_size += START_STRSIZE - 1;
60 new_size &= -START_STRSIZE;
Masahiro Yamadad717f242018-02-09 01:19:07 +090061 text = xrealloc(text, new_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 text_asize = new_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 }
Roman Zippel7a884882005-11-08 21:34:51 -080064 memcpy(text + text_size, str, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 text_size += size;
Roman Zippel7a884882005-11-08 21:34:51 -080066 text[text_size] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067}
68
Josh Triplett65166572009-10-15 12:13:36 -070069static void alloc_string(const char *str, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070{
Alan Cox177acf72012-11-06 14:32:08 +000071 text = xmalloc(size + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 memcpy(text, str, size);
73 text[size] = 0;
74}
Andreas Ruprechtc2264562015-07-12 09:41:50 +020075
76static void warn_ignored_character(char chr)
77{
78 fprintf(stderr,
79 "%s:%d:warning: ignoring unsupported character '%c'\n",
Masahiro Yamada77c1c0f2018-12-11 20:00:44 +090080 current_file->name, yylineno, chr);
Andreas Ruprechtc2264562015-07-12 09:41:50 +020081}
Linus Torvalds1da177e2005-04-16 15:20:36 -070082%}
83
Andreas Ruprechtc2264562015-07-12 09:41:50 +020084n [A-Za-z0-9_-]
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86%%
87 int str = 0;
88 int ts, i;
89
Roman Zippela02f0572005-11-08 21:34:53 -080090[ \t]*#.*\n |
91[ \t]*\n {
Roman Zippela02f0572005-11-08 21:34:53 -080092 return T_EOL;
93}
Linus Torvalds1da177e2005-04-16 15:20:36 -070094[ \t]*#.*
Linus Torvalds1da177e2005-04-16 15:20:36 -070095. {
96 unput(yytext[0]);
97 BEGIN(COMMAND);
98}
99
100
101<COMMAND>{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 {n}+ {
Arnaud Lacombe61f956f2011-05-04 21:14:44 -0400103 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
Roman Zippel7a884882005-11-08 21:34:51 -0800104 if (id && id->flags & TF_COMMAND) {
Masahiro Yamada9de07152018-05-28 18:21:48 +0900105 BEGIN(PARAM);
Roman Zippel7a884882005-11-08 21:34:51 -0800106 return id->token;
107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 alloc_string(yytext, yyleng);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900109 yylval.string = text;
Masahiro Yamada171a5152018-12-11 20:01:02 +0900110 return T_WORD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 }
Masahiro Yamada82bc8bd2018-05-28 18:21:52 +0900112 ({n}|$)+ {
113 /* this token includes at least one '$' */
114 yylval.string = expand_token(yytext, yyleng);
115 if (strlen(yylval.string))
Masahiro Yamada171a5152018-12-11 20:01:02 +0900116 return T_WORD;
Masahiro Yamada82bc8bd2018-05-28 18:21:52 +0900117 free(yylval.string);
118 }
Masahiro Yamada824fa3b2018-12-11 20:01:08 +0900119 "=" return T_EQUAL;
120 ":=" return T_COLON_EQUAL;
121 "+=" return T_PLUS_EQUAL;
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +0900122 [[:blank:]]+
Andreas Ruprechtc2264562015-07-12 09:41:50 +0200123 . warn_ignored_character(*yytext);
Roman Zippela02f0572005-11-08 21:34:53 -0800124 \n {
125 BEGIN(INITIAL);
Roman Zippela02f0572005-11-08 21:34:53 -0800126 return T_EOL;
127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +0900130<ASSIGN_VAL>{
131 [^[:blank:]\n]+.* {
132 alloc_string(yytext, yyleng);
133 yylval.string = text;
134 return T_ASSIGN_VAL;
135 }
136 \n { BEGIN(INITIAL); return T_EOL; }
137 .
138}
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140<PARAM>{
Masahiro Yamadace2164a2018-12-11 20:01:00 +0900141 "modules" return T_MODULES;
142 "defconfig_list" return T_DEFCONFIG_LIST;
143 "allnoconfig_y" return T_ALLNOCONFIG_Y;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 "&&" return T_AND;
145 "||" return T_OR;
146 "(" return T_OPEN_PAREN;
147 ")" return T_CLOSE_PAREN;
148 "!" return T_NOT;
149 "=" return T_EQUAL;
150 "!=" return T_UNEQUAL;
Jan Beulich31847b62015-06-15 13:00:21 +0100151 "<=" return T_LESS_EQUAL;
152 ">=" return T_GREATER_EQUAL;
153 "<" return T_LESS;
154 ">" return T_GREATER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 \"|\' {
156 str = yytext[0];
157 new_string();
158 BEGIN(STRING);
159 }
Masahiro Yamada18492682018-03-23 02:00:14 +0900160 \n BEGIN(INITIAL); return T_EOL;
Masahiro Yamadaf5451582018-12-11 20:01:05 +0900161 {n}+ {
Arnaud Lacombe61f956f2011-05-04 21:14:44 -0400162 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
Roman Zippel3370f9f2005-11-08 21:34:52 -0800163 if (id && id->flags & TF_PARAM) {
Roman Zippel7a884882005-11-08 21:34:51 -0800164 return id->token;
Roman Zippel3370f9f2005-11-08 21:34:52 -0800165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 alloc_string(yytext, yyleng);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900167 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 return T_WORD;
169 }
Masahiro Yamadaf5451582018-12-11 20:01:05 +0900170 ({n}|$)+ {
Masahiro Yamada104daea2018-05-28 18:21:40 +0900171 /* 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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 #.* /* comment */
Masahiro Yamada18492682018-03-23 02:00:14 +0900178 \\\n ;
Jan Beulich2e0d7372015-01-20 12:52:48 +0000179 [[:blank:]]+
Andreas Ruprechtc2264562015-07-12 09:41:50 +0200180 . warn_ignored_character(*yytext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181}
182
183<STRING>{
Masahiro Yamada104daea2018-05-28 18:21:40 +0900184 "$".* append_expanded_string(yytext);
Masahiro Yamada104daea2018-05-28 18:21:40 +0900185 [^$'"\\\n]+ {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 append_string(yytext, yyleng);
187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 \\.? {
189 append_string(yytext + 1, yyleng - 1);
190 }
191 \'|\" {
192 if (str == yytext[0]) {
193 BEGIN(PARAM);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900194 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 return T_WORD_QUOTE;
196 } else
197 append_string(yytext, 1);
198 }
199 \n {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900200 fprintf(stderr,
201 "%s:%d:warning: multi-line strings not supported\n",
202 zconf_curname(), zconf_lineno());
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900203 unput('\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 BEGIN(INITIAL);
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900205 yylval.string = text;
206 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 }
208 <<EOF>> {
209 BEGIN(INITIAL);
Masahiro Yamadafbac5972018-12-11 20:00:45 +0900210 yylval.string = text;
211 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 }
213}
214
215<HELP>{
216 [ \t]+ {
217 ts = 0;
218 for (i = 0; i < yyleng; i++) {
219 if (yytext[i] == '\t')
220 ts = (ts & ~7) + 8;
221 else
222 ts++;
223 }
224 last_ts = ts;
225 if (first_ts) {
226 if (ts < first_ts) {
227 zconf_endhelp();
228 return T_HELPTEXT;
229 }
230 ts -= first_ts;
231 while (ts > 8) {
232 append_string(" ", 8);
233 ts -= 8;
234 }
235 append_string(" ", ts);
236 }
237 }
238 [ \t]*\n/[^ \t\n] {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 zconf_endhelp();
240 return T_HELPTEXT;
241 }
242 [ \t]*\n {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 append_string("\n", 1);
244 }
245 [^ \t\n].* {
EGRY Gaborf7a4b4c2008-01-11 23:55:20 +0100246 while (yyleng) {
247 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
248 break;
249 yyleng--;
250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 append_string(yytext, yyleng);
252 if (!first_ts)
253 first_ts = last_ts;
254 }
255 <<EOF>> {
256 zconf_endhelp();
257 return T_HELPTEXT;
258 }
259}
260
261<<EOF>> {
Masahiro Yamada0bcc5472018-12-11 20:00:50 +0900262 BEGIN(INITIAL);
263
Masahiro Yamada72367932018-12-11 20:00:51 +0900264 if (prev_token != T_EOL && prev_token != T_HELPTEXT)
265 fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
266 current_file->name, yylineno);
267
Roman Zippela02f0572005-11-08 21:34:53 -0800268 if (current_file) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 zconf_endfile();
Roman Zippela02f0572005-11-08 21:34:53 -0800270 return T_EOL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 }
272 fclose(yyin);
273 yyterminate();
274}
275
276%%
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900277
278/* second stage lexer */
279int yylex(void)
280{
281 int token;
282
283repeat:
284 token = yylex1();
285
Masahiro Yamada4b31a322018-12-11 20:01:09 +0900286 if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
287 if (token == T_EOL) {
288 /* Do not pass unneeded T_EOL to the parser. */
289 goto repeat;
290 } else {
291 /*
292 * For the parser, update file/lineno at the first token
293 * of each statement. Generally, \n is a statement
294 * terminator in Kconfig, but it is not always true
295 * because \n could be escaped by a backslash.
296 */
297 current_pos.file = current_file;
298 current_pos.lineno = yylineno;
299 }
300 }
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900301
Masahiro Yamada824fa3b2018-12-11 20:01:08 +0900302 if (prev_prev_token == T_EOL && prev_token == T_WORD &&
303 (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
304 BEGIN(ASSIGN_VAL);
305
306 prev_prev_token = prev_token;
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900307 prev_token = token;
308
309 return token;
310}
311
Masahiro Yamada104daea2018-05-28 18:21:40 +0900312static char *expand_token(const char *in, size_t n)
313{
314 char *out;
315 int c;
316 char c2;
317 const char *rest, *end;
318
319 new_string();
320 append_string(in, n);
321
322 /* get the whole line because we do not know the end of token. */
323 while ((c = input()) != EOF) {
324 if (c == '\n') {
325 unput(c);
326 break;
327 }
328 c2 = c;
329 append_string(&c2, 1);
330 }
331
332 rest = text;
333 out = expand_one_token(&rest);
334
335 /* push back unused characters to the input stream */
336 end = rest + strlen(rest);
337 while (end > rest)
338 unput(*--end);
339
340 free(text);
341
342 return out;
343}
344
345static void append_expanded_string(const char *str)
346{
347 const char *end;
348 char *res;
349
350 str++;
351
352 res = expand_dollar(&str);
353
354 /* push back unused characters to the input stream */
355 end = str + strlen(str);
356 while (end > str)
357 unput(*--end);
358
359 append_string(res, strlen(res));
360
361 free(res);
362}
363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364void zconf_starthelp(void)
365{
366 new_string();
367 last_ts = first_ts = 0;
368 BEGIN(HELP);
369}
370
371static void zconf_endhelp(void)
372{
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900373 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 BEGIN(INITIAL);
375}
376
377
378/*
379 * Try to open specified file with following names:
380 * ./name
381 * $(srctree)/name
382 * The latter is used when srctree is separate from objtree
383 * when compiling the kernel.
384 * Return NULL if file is not found.
385 */
386FILE *zconf_fopen(const char *name)
387{
388 char *env, fullname[PATH_MAX+1];
389 FILE *f;
390
391 f = fopen(name, "r");
Marcin Garski11de39e2007-05-05 22:49:00 +0200392 if (!f && name != NULL && name[0] != '/') {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 env = getenv(SRCTREE);
394 if (env) {
395 sprintf(fullname, "%s/%s", env, name);
396 f = fopen(fullname, "r");
397 }
398 }
399 return f;
400}
401
402void zconf_initscan(const char *name)
403{
404 yyin = zconf_fopen(name);
405 if (!yyin) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900406 fprintf(stderr, "can't find file %s\n", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 exit(1);
408 }
409
Alan Cox177acf72012-11-06 14:32:08 +0000410 current_buf = xmalloc(sizeof(*current_buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 memset(current_buf, 0, sizeof(*current_buf));
412
413 current_file = file_lookup(name);
Masahiro Yamada18492682018-03-23 02:00:14 +0900414 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
417void zconf_nextfile(const char *name)
418{
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100419 struct file *iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 struct file *file = file_lookup(name);
Alan Cox177acf72012-11-06 14:32:08 +0000421 struct buffer *buf = xmalloc(sizeof(*buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 memset(buf, 0, sizeof(*buf));
423
424 current_buf->state = YY_CURRENT_BUFFER;
Arnaud Lacombee82dae92010-09-04 16:09:26 -0400425 yyin = zconf_fopen(file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 if (!yyin) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900427 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
428 zconf_curname(), zconf_lineno(), file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 exit(1);
430 }
431 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
432 buf->parent = current_buf;
433 current_buf = buf;
434
Masahiro Yamada18492682018-03-23 02:00:14 +0900435 current_file->lineno = yylineno;
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900436 file->parent = current_file;
437
438 for (iter = current_file; iter; iter = iter->parent) {
439 if (!strcmp(iter->name, file->name)) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900440 fprintf(stderr,
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900441 "Recursive inclusion detected.\n"
442 "Inclusion path:\n"
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900443 " current file : %s\n", file->name);
444 iter = file;
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900445 do {
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100446 iter = iter->parent;
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900447 fprintf(stderr, " included from: %s:%d\n",
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900448 iter->name, iter->lineno - 1);
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900449 } while (strcmp(iter->name, file->name));
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100450 exit(1);
451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900453
Masahiro Yamada18492682018-03-23 02:00:14 +0900454 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 current_file = file;
456}
457
Roman Zippela02f0572005-11-08 21:34:53 -0800458static void zconf_endfile(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 struct buffer *parent;
461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 current_file = current_file->parent;
Masahiro Yamada18492682018-03-23 02:00:14 +0900463 if (current_file)
464 yylineno = current_file->lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 parent = current_buf->parent;
467 if (parent) {
468 fclose(yyin);
469 yy_delete_buffer(YY_CURRENT_BUFFER);
470 yy_switch_to_buffer(parent->state);
471 }
472 free(current_buf);
473 current_buf = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
475
476int zconf_lineno(void)
477{
Roman Zippela02f0572005-11-08 21:34:53 -0800478 return current_pos.lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479}
480
Arnaud Lacombe2e7a0912010-09-04 16:03:30 -0400481const char *zconf_curname(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
Roman Zippela02f0572005-11-08 21:34:53 -0800483 return current_pos.file ? current_pos.file->name : "<none>";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}