blob: 847ba4248092854c48bcada6fc4a30c3af26665b [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 Yamadacc66bca2018-12-11 20:00:49 +090028static int prev_token = T_EOL;
Roman Zippel7a884882005-11-08 21:34:51 -080029static char *text;
Linus Torvalds1da177e2005-04-16 15:20:36 -070030static int text_size, text_asize;
31
32struct buffer {
Masahiro Yamadabb66fc62014-06-10 19:08:13 +090033 struct buffer *parent;
34 YY_BUFFER_STATE state;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035};
36
37struct buffer *current_buf;
38
39static int last_ts, first_ts;
40
Masahiro Yamada104daea2018-05-28 18:21:40 +090041static char *expand_token(const char *in, size_t n);
42static void append_expanded_string(const char *in);
Linus Torvalds1da177e2005-04-16 15:20:36 -070043static void zconf_endhelp(void);
Roman Zippela02f0572005-11-08 21:34:53 -080044static void zconf_endfile(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Josh Triplett65166572009-10-15 12:13:36 -070046static void new_string(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047{
Alan Cox177acf72012-11-06 14:32:08 +000048 text = xmalloc(START_STRSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 text_asize = START_STRSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 text_size = 0;
Roman Zippel7a884882005-11-08 21:34:51 -080051 *text = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052}
53
Josh Triplett65166572009-10-15 12:13:36 -070054static void append_string(const char *str, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055{
56 int new_size = text_size + size + 1;
57 if (new_size > text_asize) {
Roman Zippel7a884882005-11-08 21:34:51 -080058 new_size += START_STRSIZE - 1;
59 new_size &= -START_STRSIZE;
Masahiro Yamadad717f242018-02-09 01:19:07 +090060 text = xrealloc(text, new_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 text_asize = new_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 }
Roman Zippel7a884882005-11-08 21:34:51 -080063 memcpy(text + text_size, str, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 text_size += size;
Roman Zippel7a884882005-11-08 21:34:51 -080065 text[text_size] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066}
67
Josh Triplett65166572009-10-15 12:13:36 -070068static void alloc_string(const char *str, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069{
Alan Cox177acf72012-11-06 14:32:08 +000070 text = xmalloc(size + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 memcpy(text, str, size);
72 text[size] = 0;
73}
Andreas Ruprechtc2264562015-07-12 09:41:50 +020074
75static void warn_ignored_character(char chr)
76{
77 fprintf(stderr,
78 "%s:%d:warning: ignoring unsupported character '%c'\n",
Masahiro Yamada77c1c0f2018-12-11 20:00:44 +090079 current_file->name, yylineno, chr);
Andreas Ruprechtc2264562015-07-12 09:41:50 +020080}
Linus Torvalds1da177e2005-04-16 15:20:36 -070081%}
82
Andreas Ruprechtc2264562015-07-12 09:41:50 +020083n [A-Za-z0-9_-]
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85%%
86 int str = 0;
87 int ts, i;
88
Roman Zippela02f0572005-11-08 21:34:53 -080089[ \t]*#.*\n |
90[ \t]*\n {
Roman Zippela02f0572005-11-08 21:34:53 -080091 return T_EOL;
92}
Linus Torvalds1da177e2005-04-16 15:20:36 -070093[ \t]*#.*
Linus Torvalds1da177e2005-04-16 15:20:36 -070094. {
95 unput(yytext[0]);
96 BEGIN(COMMAND);
97}
98
99
100<COMMAND>{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 {n}+ {
Arnaud Lacombe61f956f2011-05-04 21:14:44 -0400102 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
Roman Zippela02f0572005-11-08 21:34:53 -0800103 current_pos.file = current_file;
Masahiro Yamada18492682018-03-23 02:00:14 +0900104 current_pos.lineno = yylineno;
Roman Zippel7a884882005-11-08 21:34:51 -0800105 if (id && id->flags & TF_COMMAND) {
Masahiro Yamada9de07152018-05-28 18:21:48 +0900106 BEGIN(PARAM);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900107 yylval.id = id;
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 Yamada9ced3bd2018-05-28 18:21:49 +0900112 return T_VARIABLE;
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))
118 return T_VARIABLE;
119 free(yylval.string);
120 }
Masahiro Yamada1175c022018-05-28 18:21:50 +0900121 "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
122 ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
Masahiro Yamadaed2a22f2018-05-28 18:21:51 +0900123 "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
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>{
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;
Jan Beulich31847b62015-06-15 13:00:21 +0100150 "<=" return T_LESS_EQUAL;
151 ">=" return T_GREATER_EQUAL;
152 "<" return T_LESS;
153 ">" return T_GREATER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 \"|\' {
155 str = yytext[0];
156 new_string();
157 BEGIN(STRING);
158 }
Masahiro Yamada18492682018-03-23 02:00:14 +0900159 \n BEGIN(INITIAL); return T_EOL;
Andreas Ruprechtc2264562015-07-12 09:41:50 +0200160 ({n}|[/.])+ {
Arnaud Lacombe61f956f2011-05-04 21:14:44 -0400161 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
Roman Zippel3370f9f2005-11-08 21:34:52 -0800162 if (id && id->flags & TF_PARAM) {
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900163 yylval.id = id;
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 Yamada104daea2018-05-28 18:21:40 +0900170 ({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 }
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 <<EOF>> {
182 BEGIN(INITIAL);
183 }
184}
185
186<STRING>{
Masahiro Yamada104daea2018-05-28 18:21:40 +0900187 "$".* append_expanded_string(yytext);
Masahiro Yamada104daea2018-05-28 18:21:40 +0900188 [^$'"\\\n]+ {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 append_string(yytext, yyleng);
190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 \\.? {
192 append_string(yytext + 1, yyleng - 1);
193 }
194 \'|\" {
195 if (str == yytext[0]) {
196 BEGIN(PARAM);
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900197 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return T_WORD_QUOTE;
199 } else
200 append_string(yytext, 1);
201 }
202 \n {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900203 fprintf(stderr,
204 "%s:%d:warning: multi-line strings not supported\n",
205 zconf_curname(), zconf_lineno());
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900206 unput('\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 BEGIN(INITIAL);
Masahiro Yamada21c5ecf2018-12-11 20:00:48 +0900208 yylval.string = text;
209 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 }
211 <<EOF>> {
212 BEGIN(INITIAL);
Masahiro Yamadafbac5972018-12-11 20:00:45 +0900213 yylval.string = text;
214 return T_WORD_QUOTE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 }
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] {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 zconf_endhelp();
243 return T_HELPTEXT;
244 }
245 [ \t]*\n {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 append_string("\n", 1);
247 }
248 [^ \t\n].* {
EGRY Gaborf7a4b4c2008-01-11 23:55:20 +0100249 while (yyleng) {
250 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
251 break;
252 yyleng--;
253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 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>> {
Roman Zippela02f0572005-11-08 21:34:53 -0800265 if (current_file) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 zconf_endfile();
Roman Zippela02f0572005-11-08 21:34:53 -0800267 return T_EOL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269 fclose(yyin);
270 yyterminate();
271}
272
273%%
Masahiro Yamadacc66bca2018-12-11 20:00:49 +0900274
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
Masahiro Yamada104daea2018-05-28 18:21:40 +0900292static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344void zconf_starthelp(void)
345{
346 new_string();
347 last_ts = first_ts = 0;
348 BEGIN(HELP);
349}
350
351static void zconf_endhelp(void)
352{
Masahiro Yamada765f4cd2018-01-12 00:50:50 +0900353 yylval.string = text;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 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");
Marcin Garski11de39e2007-05-05 22:49:00 +0200372 if (!f && name != NULL && name[0] != '/') {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 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) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900386 fprintf(stderr, "can't find file %s\n", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 exit(1);
388 }
389
Alan Cox177acf72012-11-06 14:32:08 +0000390 current_buf = xmalloc(sizeof(*current_buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 memset(current_buf, 0, sizeof(*current_buf));
392
393 current_file = file_lookup(name);
Masahiro Yamada18492682018-03-23 02:00:14 +0900394 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395}
396
397void zconf_nextfile(const char *name)
398{
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100399 struct file *iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 struct file *file = file_lookup(name);
Alan Cox177acf72012-11-06 14:32:08 +0000401 struct buffer *buf = xmalloc(sizeof(*buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 memset(buf, 0, sizeof(*buf));
403
404 current_buf->state = YY_CURRENT_BUFFER;
Arnaud Lacombee82dae92010-09-04 16:09:26 -0400405 yyin = zconf_fopen(file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 if (!yyin) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900407 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
408 zconf_curname(), zconf_lineno(), file->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 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
Masahiro Yamada18492682018-03-23 02:00:14 +0900415 current_file->lineno = yylineno;
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900416 file->parent = current_file;
417
418 for (iter = current_file; iter; iter = iter->parent) {
419 if (!strcmp(iter->name, file->name)) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900420 fprintf(stderr,
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900421 "Recursive inclusion detected.\n"
422 "Inclusion path:\n"
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900423 " current file : %s\n", file->name);
424 iter = file;
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900425 do {
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100426 iter = iter->parent;
Masahiro Yamada32a94b82018-03-23 02:00:12 +0900427 fprintf(stderr, " included from: %s:%d\n",
Masahiro Yamada5ae6fcc2018-03-02 16:05:12 +0900428 iter->name, iter->lineno - 1);
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900429 } while (strcmp(iter->name, file->name));
Yann E. MORINf094f8a2011-02-24 19:36:42 +0100430 exit(1);
431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 }
Masahiro Yamada379a8eb2018-03-23 02:00:13 +0900433
Masahiro Yamada18492682018-03-23 02:00:14 +0900434 yylineno = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 current_file = file;
436}
437
Roman Zippela02f0572005-11-08 21:34:53 -0800438static void zconf_endfile(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 struct buffer *parent;
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 current_file = current_file->parent;
Masahiro Yamada18492682018-03-23 02:00:14 +0900443 if (current_file)
444 yylineno = current_file->lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
456int zconf_lineno(void)
457{
Roman Zippela02f0572005-11-08 21:34:53 -0800458 return current_pos.lineno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459}
460
Arnaud Lacombe2e7a0912010-09-04 16:03:30 -0400461const char *zconf_curname(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
Roman Zippela02f0572005-11-08 21:34:53 -0800463 return current_pos.file ? current_pos.file->name : "<none>";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464}