xref: /openbmc/u-boot/scripts/kconfig/zconf.l (revision 8ee59472)
1 %option nostdinit noyywrap never-interactive full ecs
2 %option 8bit nodefault perf-report perf-report
3 %option noinput
4 %x COMMAND HELP STRING PARAM
5 %{
6 /*
7  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
8  * Released under the terms of the GNU GPL v2.0.
9  */
10 
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include "lkc.h"
18 
19 #define START_STRSIZE	16
20 
21 static struct {
22 	struct file *file;
23 	int lineno;
24 } current_pos;
25 
26 static char *text;
27 static int text_size, text_asize;
28 
29 struct buffer {
30 	struct buffer *parent;
31 	YY_BUFFER_STATE state;
32 };
33 
34 struct buffer *current_buf;
35 
36 static int last_ts, first_ts;
37 
38 static void zconf_endhelp(void);
39 static void zconf_endfile(void);
40 
41 static void new_string(void)
42 {
43 	text = xmalloc(START_STRSIZE);
44 	text_asize = START_STRSIZE;
45 	text_size = 0;
46 	*text = 0;
47 }
48 
49 static void append_string(const char *str, int size)
50 {
51 	int new_size = text_size + size + 1;
52 	if (new_size > text_asize) {
53 		new_size += START_STRSIZE - 1;
54 		new_size &= -START_STRSIZE;
55 		text = realloc(text, new_size);
56 		text_asize = new_size;
57 	}
58 	memcpy(text + text_size, str, size);
59 	text_size += size;
60 	text[text_size] = 0;
61 }
62 
63 static void alloc_string(const char *str, int size)
64 {
65 	text = xmalloc(size + 1);
66 	memcpy(text, str, size);
67 	text[size] = 0;
68 }
69 
70 static void warn_ignored_character(char chr)
71 {
72 	fprintf(stderr,
73 	        "%s:%d:warning: ignoring unsupported character '%c'\n",
74 	        zconf_curname(), zconf_lineno(), chr);
75 }
76 %}
77 
78 n	[A-Za-z0-9_-]
79 
80 %%
81 	int str = 0;
82 	int ts, i;
83 
84 [ \t]*#.*\n	|
85 [ \t]*\n	{
86 	current_file->lineno++;
87 	return T_EOL;
88 }
89 [ \t]*#.*
90 
91 
92 [ \t]+	{
93 	BEGIN(COMMAND);
94 }
95 
96 .	{
97 	unput(yytext[0]);
98 	BEGIN(COMMAND);
99 }
100 
101 
102 <COMMAND>{
103 	{n}+	{
104 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
105 		BEGIN(PARAM);
106 		current_pos.file = current_file;
107 		current_pos.lineno = current_file->lineno;
108 		if (id && id->flags & TF_COMMAND) {
109 			zconflval.id = id;
110 			return id->token;
111 		}
112 		alloc_string(yytext, yyleng);
113 		zconflval.string = text;
114 		return T_WORD;
115 	}
116 	.	warn_ignored_character(*yytext);
117 	\n	{
118 		BEGIN(INITIAL);
119 		current_file->lineno++;
120 		return T_EOL;
121 	}
122 }
123 
124 <PARAM>{
125 	"&&"	return T_AND;
126 	"||"	return T_OR;
127 	"("	return T_OPEN_PAREN;
128 	")"	return T_CLOSE_PAREN;
129 	"!"	return T_NOT;
130 	"="	return T_EQUAL;
131 	"!="	return T_UNEQUAL;
132 	"<="	return T_LESS_EQUAL;
133 	">="	return T_GREATER_EQUAL;
134 	"<"	return T_LESS;
135 	">"	return T_GREATER;
136 	\"|\'	{
137 		str = yytext[0];
138 		new_string();
139 		BEGIN(STRING);
140 	}
141 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
142 	({n}|[/.])+	{
143 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
144 		if (id && id->flags & TF_PARAM) {
145 			zconflval.id = id;
146 			return id->token;
147 		}
148 		alloc_string(yytext, yyleng);
149 		zconflval.string = text;
150 		return T_WORD;
151 	}
152 	#.*	/* comment */
153 	\\\n	current_file->lineno++;
154 	[[:blank:]]+
155 	.	warn_ignored_character(*yytext);
156 	<<EOF>> {
157 		BEGIN(INITIAL);
158 	}
159 }
160 
161 <STRING>{
162 	[^'"\\\n]+/\n	{
163 		append_string(yytext, yyleng);
164 		zconflval.string = text;
165 		return T_WORD_QUOTE;
166 	}
167 	[^'"\\\n]+	{
168 		append_string(yytext, yyleng);
169 	}
170 	\\.?/\n	{
171 		append_string(yytext + 1, yyleng - 1);
172 		zconflval.string = text;
173 		return T_WORD_QUOTE;
174 	}
175 	\\.?	{
176 		append_string(yytext + 1, yyleng - 1);
177 	}
178 	\'|\"	{
179 		if (str == yytext[0]) {
180 			BEGIN(PARAM);
181 			zconflval.string = text;
182 			return T_WORD_QUOTE;
183 		} else
184 			append_string(yytext, 1);
185 	}
186 	\n	{
187 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
188 		current_file->lineno++;
189 		BEGIN(INITIAL);
190 		return T_EOL;
191 	}
192 	<<EOF>>	{
193 		BEGIN(INITIAL);
194 	}
195 }
196 
197 <HELP>{
198 	[ \t]+	{
199 		ts = 0;
200 		for (i = 0; i < yyleng; i++) {
201 			if (yytext[i] == '\t')
202 				ts = (ts & ~7) + 8;
203 			else
204 				ts++;
205 		}
206 		last_ts = ts;
207 		if (first_ts) {
208 			if (ts < first_ts) {
209 				zconf_endhelp();
210 				return T_HELPTEXT;
211 			}
212 			ts -= first_ts;
213 			while (ts > 8) {
214 				append_string("        ", 8);
215 				ts -= 8;
216 			}
217 			append_string("        ", ts);
218 		}
219 	}
220 	[ \t]*\n/[^ \t\n] {
221 		current_file->lineno++;
222 		zconf_endhelp();
223 		return T_HELPTEXT;
224 	}
225 	[ \t]*\n	{
226 		current_file->lineno++;
227 		append_string("\n", 1);
228 	}
229 	[^ \t\n].* {
230 		while (yyleng) {
231 			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
232 				break;
233 			yyleng--;
234 		}
235 		append_string(yytext, yyleng);
236 		if (!first_ts)
237 			first_ts = last_ts;
238 	}
239 	<<EOF>>	{
240 		zconf_endhelp();
241 		return T_HELPTEXT;
242 	}
243 }
244 
245 <<EOF>>	{
246 	if (current_file) {
247 		zconf_endfile();
248 		return T_EOL;
249 	}
250 	fclose(yyin);
251 	yyterminate();
252 }
253 
254 %%
255 void zconf_starthelp(void)
256 {
257 	new_string();
258 	last_ts = first_ts = 0;
259 	BEGIN(HELP);
260 }
261 
262 static void zconf_endhelp(void)
263 {
264 	zconflval.string = text;
265 	BEGIN(INITIAL);
266 }
267 
268 
269 /*
270  * Try to open specified file with following names:
271  * ./name
272  * $(srctree)/name
273  * The latter is used when srctree is separate from objtree
274  * when compiling the kernel.
275  * Return NULL if file is not found.
276  */
277 FILE *zconf_fopen(const char *name)
278 {
279 	char *env, fullname[PATH_MAX+1];
280 	FILE *f;
281 
282 	f = fopen(name, "r");
283 	if (!f && name != NULL && name[0] != '/') {
284 		env = getenv(SRCTREE);
285 		if (env) {
286 			sprintf(fullname, "%s/%s", env, name);
287 			f = fopen(fullname, "r");
288 		}
289 	}
290 	return f;
291 }
292 
293 void zconf_initscan(const char *name)
294 {
295 	yyin = zconf_fopen(name);
296 	if (!yyin) {
297 		printf("can't find file %s\n", name);
298 		exit(1);
299 	}
300 
301 	current_buf = xmalloc(sizeof(*current_buf));
302 	memset(current_buf, 0, sizeof(*current_buf));
303 
304 	current_file = file_lookup(name);
305 	current_file->lineno = 1;
306 }
307 
308 void zconf_nextfile(const char *name)
309 {
310 	struct file *iter;
311 	struct file *file = file_lookup(name);
312 	struct buffer *buf = xmalloc(sizeof(*buf));
313 	memset(buf, 0, sizeof(*buf));
314 
315 	current_buf->state = YY_CURRENT_BUFFER;
316 	yyin = zconf_fopen(file->name);
317 	if (!yyin) {
318 		printf("%s:%d: can't open file \"%s\"\n",
319 		    zconf_curname(), zconf_lineno(), file->name);
320 		exit(1);
321 	}
322 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
323 	buf->parent = current_buf;
324 	current_buf = buf;
325 
326 	for (iter = current_file->parent; iter; iter = iter->parent ) {
327 		if (!strcmp(current_file->name,iter->name) ) {
328 			printf("%s:%d: recursive inclusion detected. "
329 			       "Inclusion path:\n  current file : '%s'\n",
330 			       zconf_curname(), zconf_lineno(),
331 			       zconf_curname());
332 			iter = current_file->parent;
333 			while (iter && \
334 			       strcmp(iter->name,current_file->name)) {
335 				printf("  included from: '%s:%d'\n",
336 				       iter->name, iter->lineno-1);
337 				iter = iter->parent;
338 			}
339 			if (iter)
340 				printf("  included from: '%s:%d'\n",
341 				       iter->name, iter->lineno+1);
342 			exit(1);
343 		}
344 	}
345 	file->lineno = 1;
346 	file->parent = current_file;
347 	current_file = file;
348 }
349 
350 static void zconf_endfile(void)
351 {
352 	struct buffer *parent;
353 
354 	current_file = current_file->parent;
355 
356 	parent = current_buf->parent;
357 	if (parent) {
358 		fclose(yyin);
359 		yy_delete_buffer(YY_CURRENT_BUFFER);
360 		yy_switch_to_buffer(parent->state);
361 	}
362 	free(current_buf);
363 	current_buf = parent;
364 }
365 
366 int zconf_lineno(void)
367 {
368 	return current_pos.lineno;
369 }
370 
371 const char *zconf_curname(void)
372 {
373 	return current_pos.file ? current_pos.file->name : "<none>";
374 }
375