blob: 05e2d95e3b220bad808b91f400fd9faf835d795b [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 Zippela02f0572005-11-08 21:34:53 -0800104 current_pos.file = current_file;
Masahiro Yamada18492682018-03-23 02:00:14 +0900105 current_pos.lineno = yylineno;
Roman Zippel7a884882005-11-08 21:34:51 -0800106 if (id && id->flags & TF_COMMAND) {
Masahiro Yamada9de07152018-05-28 18:21:48 +0900107 BEGIN(PARAM);
Roman Zippel7a884882005-11-08 21:34:51 -0800108 return id->token;
109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 alloc_string(yytext, yyleng);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900111 yylval.string = text;
Masahiro Yamada171a5152018-12-11 20:01:02 +0900112 return T_WORD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 }
Masahiro Yamada82bc8bd2018-05-28 18:21:52 +0900114 ({n}|$)+ {
115 /* this token includes at least one '$' */
116 yylval.string = expand_token(yytext, yyleng);
117 if (strlen(yylval.string))
Masahiro Yamada171a5152018-12-11 20:01:02 +0900118 return T_WORD;
Masahiro Yamada82bc8bd2018-05-28 18:21:52 +0900119 free(yylval.string);
120 }
Masahiro Yamada824fa3b2018-12-11 20:01:08 +0900121 "=" return T_EQUAL;
122 ":=" return T_COLON_EQUAL;
123 "+=" return T_PLUS_EQUAL;
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +0900124 [[:blank:]]+
Andreas Ruprechtc2264562015-07-12 09:41:50 +0200125 . warn_ignored_character(*yytext);
Roman Zippela02f0572005-11-08 21:34:53 -0800126 \n {
127 BEGIN(INITIAL);
Roman Zippela02f0572005-11-08 21:34:53 -0800128 return T_EOL;
129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
Masahiro Yamada9ced3bd2018-05-28 18:21:49 +0900132<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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142<PARAM>{
Masahiro Yamadace2164a2018-12-11 20:01:00 +0900143 "modules" return T_MODULES;
144 "defconfig_list" return T_DEFCONFIG_LIST;
145 "allnoconfig_y" return T_ALLNOCONFIG_Y;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 "&&" return T_AND;
147 "||" return T_OR;
148 "(" return T_OPEN_PAREN;
149 ")" return T_CLOSE_PAREN;
150 "!" return T_NOT;
151 "=" return T_EQUAL;
152 "!=" return T_UNEQUAL;
Jan Beulich31847b62015-06-15 13:00:21 +0100153 "<=" return T_LESS_EQUAL;
154 ">=" return T_GREATER_EQUAL;
155 "<" return T_LESS;
156 ">" return T_GREATER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 \"|\' {
158 str = yytext[0];
159 new_string();
160 BEGIN(STRING);
161 }
Masahiro Yamada18492682018-03-23 02:00:14 +0900162 \n BEGIN(INITIAL); return T_EOL;
Masahiro Yamadaf5451582018-12-11 20:01:05 +0900163 {n}+ {
Arnaud Lacombe61f956f2011-05-04 21:14:44 -0400164 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
Roman Zippel3370f9f2005-11-08 21:34:52 -0800165 if (id && id->flags & TF_PARAM) {
Roman Zippel7a884882005-11-08 21:34:51 -0800166 return id->token;
Roman Zippel3370f9f2005-11-08 21:34:52 -0800167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 alloc_string(yytext, yyleng);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900169 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 return T_WORD;
171 }
Masahiro Yamadaf5451582018-12-11 20:01:05 +0900172 ({n}|$)+ {
Masahiro Yamada104daea2018-05-28 18:21:40 +0900173 /* this token includes at least one '$' */
174 yylval.string = expand_token(yytext, yyleng);
175 if (strlen(yylval.string))
176 return T_WORD;
177 free(yylval.string);
178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 #.* /* comment */
Masahiro Yamada18492682018-03-23 02:00:14 +0900180 \\\n ;
Jan Beulich2e0d7372015-01-20 12:52:48 +0000181 [[:blank:]]+
Andreas Ruprechtc2264562015-07-12 09:41:50 +0200182 . warn_ignored_character(*yytext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183}
184
185<STRING>{
Masahiro Yamada104daea2018-05-28 18:21:40 +0900186 "$".* append_expanded_string(yytext);
Masahiro Yamada104daea2018-05-28 18:21:40 +0900187 [^$'"\\\n]+ {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 append_string(yytext, yyleng);
189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 \\.? {
191 append_string(yytext + 1, yyleng - 1);
192 }
193 \'|\" {
194 if (str == yytext[0]) {
195 BEGIN(PARAM);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900196 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 return T_WORD_QUOTE;
198 } else
199 append_string(yytext, 1);
200 }
201 \n {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900202 fprintf(stderr,
203 "%s:%d:warning: multi-line strings not supported\n",
204 zconf_curname(), zconf_lineno());
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900205 unput('\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 BEGIN(INITIAL);
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900207 yylval.string = text;
208 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 }
210 <<EOF>> {
211 BEGIN(INITIAL);
Masahiro Yamadafbac5972018-12-11 20:00:45 +0900212 yylval.string = text;
213 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 }
215}
216
217<HELP>{
218 [ \t]+ {
219 ts = 0;
220 for (i = 0; i < yyleng; i++) {
221 if (yytext[i] == '\t')
222 ts = (ts & ~7) + 8;
223 else
224 ts++;
225 }
226 last_ts = ts;
227 if (first_ts) {
228 if (ts < first_ts) {
229 zconf_endhelp();
230 return T_HELPTEXT;
231 }
232 ts -= first_ts;
233 while (ts > 8) {
234 append_string(" ", 8);
235 ts -= 8;
236 }
237 append_string(" ", ts);
238 }
239 }
240 [ \t]*\n/[^ \t\n] {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 zconf_endhelp();
242 return T_HELPTEXT;
243 }
244 [ \t]*\n {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 append_string("\n", 1);
246 }
247 [^ \t\n].* {
EGRY Gaborf7a4b4c2008-01-11 23:55:20 +0100248 while (yyleng) {
249 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
250 break;
251 yyleng--;
252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 append_string(yytext, yyleng);
254 if (!first_ts)
255 first_ts = last_ts;
256 }
257 <<EOF>> {
258 zconf_endhelp();
259 return T_HELPTEXT;
260 }
261}
262
263<<EOF>> {
Masahiro Yamada0bcc5472018-12-11 20:00:50 +0900264 BEGIN(INITIAL);
265
Masahiro Yamada72367932018-12-11 20:00:51 +0900266 if (prev_token != T_EOL && prev_token != T_HELPTEXT)
267 fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
268 current_file->name, yylineno);
269
Roman Zippela02f0572005-11-08 21:34:53 -0800270 if (current_file) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 zconf_endfile();
Roman Zippela02f0572005-11-08 21:34:53 -0800272 return T_EOL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274 fclose(yyin);
275 yyterminate();
276}
277
278%%
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900279
280/* second stage lexer */
281int yylex(void)
282{
283 int token;
284
285repeat:
286 token = yylex1();
287
288 /* Do not pass unneeded T_EOL to the parser. */
289 if ((prev_token == T_EOL || prev_token == T_HELPTEXT) && token == T_EOL)
290 goto repeat;
291
Masahiro Yamada824fa3b2018-12-11 20:01:08 +0900292 if (prev_prev_token == T_EOL && prev_token == T_WORD &&
293 (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
294 BEGIN(ASSIGN_VAL);
295
296 prev_prev_token = prev_token;
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900297 prev_token = token;
298
299 return token;
300}
301
Masahiro Yamada104daea2018-05-28 18:21:40 +0900302static char *expand_token(const char *in, size_t n)
303{
304 char *out;
305 int c;
306 char c2;
307 const char *rest, *end;
308
309 new_string();
310 append_string(in, n);
311
312 /* get the whole line because we do not know the end of token. */
313 while ((c = input()) != EOF) {
314 if (c == '\n') {
315 unput(c);
316 break;
317 }
318 c2 = c;
319 append_string(&c2, 1);
320 }
321
322 rest = text;
323 out = expand_one_token(&rest);
324
325 /* push back unused characters to the input stream */
326 end = rest + strlen(rest);
327 while (end > rest)
328 unput(*--end);
329
330 free(text);
331
332 return out;
333}
334
335static void append_expanded_string(const char *str)
336{
337 const char *end;
338 char *res;
339
340 str++;
341
342 res = expand_dollar(&str);
343
344 /* push back unused characters to the input stream */
345 end = str + strlen(str);
346 while (end > str)
347 unput(*--end);
348
349 append_string(res, strlen(res));
350
351 free(res);
352}
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354void zconf_starthelp(void)
355{
356 new_string();
357 last_ts = first_ts = 0;
358 BEGIN(HELP);
359}
360
361static void zconf_endhelp(void)
362{
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900363 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 BEGIN(INITIAL);
365}
366
367
368/*
369 * Try to open specified file with following names:
370 * ./name
371 * $(srctree)/name
372 * The latter is used when srctree is separate from objtree
373 * when compiling the kernel.
374 * Return NULL if file is not found.
375 */
376FILE *zconf_fopen(const char *name)
377{
378 char *env, fullname[PATH_MAX+1];
379 FILE *f;
380
381 f = fopen(name, "r");
Marcin Garski11de39e2007-05-05 22:49:00 +0200382 if (!f && name != NULL && name[0] != '/') {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 env = getenv(SRCTREE);
384 if (env) {
385 sprintf(fullname, "%s/%s", env, name);
386 f = fopen(fullname, "r");
387 }
388 }
389 return f;
390}
391
392void zconf_initscan(const char *name)
393{
394 yyin = zconf_fopen(name);
395 if (!yyin) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900396 fprintf(stderr, "can't find file %s\n", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 exit(1);
398 }
399
Alan Cox177acf72012-11-06 14:32:08 +0000400 current_buf = xmalloc(sizeof(*current_buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 memset(current_buf, 0, sizeof(*current_buf));
402
403 current_file = file_lookup(name);
Masahiro Yamada18492682018-03-23 02:00:14 +0900404 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406
407void zconf_nextfile(const char *name)
408{
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100409 struct file *iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 struct file *file = file_lookup(name);
Alan Cox177acf72012-11-06 14:32:08 +0000411 struct buffer *buf = xmalloc(sizeof(*buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 memset(buf, 0, sizeof(*buf));
413
414 current_buf->state = YY_CURRENT_BUFFER;
Arnaud Lacombee82dae92010-09-04 16:09:26 -0400415 yyin = zconf_fopen(file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (!yyin) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900417 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
418 zconf_curname(), zconf_lineno(), file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 exit(1);
420 }
421 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
422 buf->parent = current_buf;
423 current_buf = buf;
424
Masahiro Yamada18492682018-03-23 02:00:14 +0900425 current_file->lineno = yylineno;
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900426 file->parent = current_file;
427
428 for (iter = current_file; iter; iter = iter->parent) {
429 if (!strcmp(iter->name, file->name)) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900430 fprintf(stderr,
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900431 "Recursive inclusion detected.\n"
432 "Inclusion path:\n"
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900433 " current file : %s\n", file->name);
434 iter = file;
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900435 do {
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100436 iter = iter->parent;
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900437 fprintf(stderr, " included from: %s:%d\n",
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900438 iter->name, iter->lineno - 1);
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900439 } while (strcmp(iter->name, file->name));
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100440 exit(1);
441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 }
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900443
Masahiro Yamada18492682018-03-23 02:00:14 +0900444 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 current_file = file;
446}
447
Roman Zippela02f0572005-11-08 21:34:53 -0800448static void zconf_endfile(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
450 struct buffer *parent;
451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 current_file = current_file->parent;
Masahiro Yamada18492682018-03-23 02:00:14 +0900453 if (current_file)
454 yylineno = current_file->lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 parent = current_buf->parent;
457 if (parent) {
458 fclose(yyin);
459 yy_delete_buffer(YY_CURRENT_BUFFER);
460 yy_switch_to_buffer(parent->state);
461 }
462 free(current_buf);
463 current_buf = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464}
465
466int zconf_lineno(void)
467{
Roman Zippela02f0572005-11-08 21:34:53 -0800468 return current_pos.lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
Arnaud Lacombe2e7a0912010-09-04 16:03:30 -0400471const char *zconf_curname(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Roman Zippela02f0572005-11-08 21:34:53 -0800473 return current_pos.file ? current_pos.file->name : "<none>";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}