xref: /openbmc/u-boot/scripts/kconfig/zconf.l (revision 5c8fd32b)
1 %option nostdinit noyywrap never-interactive full ecs
2 %option 8bit nodefault yylineno
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 = xrealloc(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 	return T_EOL;
87 }
88 [ \t]*#.*
89 
90 
91 [ \t]+	{
92 	BEGIN(COMMAND);
93 }
94 
95 .	{
96 	unput(yytext[0]);
97 	BEGIN(COMMAND);
98 }
99 
100 
101 <COMMAND>{
102 	{n}+	{
103 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
104 		BEGIN(PARAM);
105 		current_pos.file = current_file;
106 		current_pos.lineno = yylineno;
107 		if (id && id->flags & TF_COMMAND) {
108 			yylval.id = id;
109 			return id->token;
110 		}
111 		alloc_string(yytext, yyleng);
112 		yylval.string = text;
113 		return T_WORD;
114 	}
115 	.	warn_ignored_character(*yytext);
116 	\n	{
117 		BEGIN(INITIAL);
118 		return T_EOL;
119 	}
120 }
121 
122 <PARAM>{
123 	"&&"	return T_AND;
124 	"||"	return T_OR;
125 	"("	return T_OPEN_PAREN;
126 	")"	return T_CLOSE_PAREN;
127 	"!"	return T_NOT;
128 	"="	return T_EQUAL;
129 	"!="	return T_UNEQUAL;
130 	"<="	return T_LESS_EQUAL;
131 	">="	return T_GREATER_EQUAL;
132 	"<"	return T_LESS;
133 	">"	return T_GREATER;
134 	\"|\'	{
135 		str = yytext[0];
136 		new_string();
137 		BEGIN(STRING);
138 	}
139 	\n	BEGIN(INITIAL); return T_EOL;
140 	({n}|[/.])+	{
141 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
142 		if (id && id->flags & TF_PARAM) {
143 			yylval.id = id;
144 			return id->token;
145 		}
146 		alloc_string(yytext, yyleng);
147 		yylval.string = text;
148 		return T_WORD;
149 	}
150 	#.*	/* comment */
151 	\\\n	;
152 	[[:blank:]]+
153 	.	warn_ignored_character(*yytext);
154 	<<EOF>> {
155 		BEGIN(INITIAL);
156 	}
157 }
158 
159 <STRING>{
160 	[^'"\\\n]+/\n	{
161 		append_string(yytext, yyleng);
162 		yylval.string = text;
163 		return T_WORD_QUOTE;
164 	}
165 	[^'"\\\n]+	{
166 		append_string(yytext, yyleng);
167 	}
168 	\\.?/\n	{
169 		append_string(yytext + 1, yyleng - 1);
170 		yylval.string = text;
171 		return T_WORD_QUOTE;
172 	}
173 	\\.?	{
174 		append_string(yytext + 1, yyleng - 1);
175 	}
176 	\'|\"	{
177 		if (str == yytext[0]) {
178 			BEGIN(PARAM);
179 			yylval.string = text;
180 			return T_WORD_QUOTE;
181 		} else
182 			append_string(yytext, 1);
183 	}
184 	\n	{
185 		fprintf(stderr,
186 			"%s:%d:warning: multi-line strings not supported\n",
187 			zconf_curname(), zconf_lineno());
188 		BEGIN(INITIAL);
189 		return T_EOL;
190 	}
191 	<<EOF>>	{
192 		BEGIN(INITIAL);
193 	}
194 }
195 
196 <HELP>{
197 	[ \t]+	{
198 		ts = 0;
199 		for (i = 0; i < yyleng; i++) {
200 			if (yytext[i] == '\t')
201 				ts = (ts & ~7) + 8;
202 			else
203 				ts++;
204 		}
205 		last_ts = ts;
206 		if (first_ts) {
207 			if (ts < first_ts) {
208 				zconf_endhelp();
209 				return T_HELPTEXT;
210 			}
211 			ts -= first_ts;
212 			while (ts > 8) {
213 				append_string("        ", 8);
214 				ts -= 8;
215 			}
216 			append_string("        ", ts);
217 		}
218 	}
219 	[ \t]*\n/[^ \t\n] {
220 		zconf_endhelp();
221 		return T_HELPTEXT;
222 	}
223 	[ \t]*\n	{
224 		append_string("\n", 1);
225 	}
226 	[^ \t\n].* {
227 		while (yyleng) {
228 			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
229 				break;
230 			yyleng--;
231 		}
232 		append_string(yytext, yyleng);
233 		if (!first_ts)
234 			first_ts = last_ts;
235 	}
236 	<<EOF>>	{
237 		zconf_endhelp();
238 		return T_HELPTEXT;
239 	}
240 }
241 
242 <<EOF>>	{
243 	if (current_file) {
244 		zconf_endfile();
245 		return T_EOL;
246 	}
247 	fclose(yyin);
248 	yyterminate();
249 }
250 
251 %%
252 void zconf_starthelp(void)
253 {
254 	new_string();
255 	last_ts = first_ts = 0;
256 	BEGIN(HELP);
257 }
258 
259 static void zconf_endhelp(void)
260 {
261 	yylval.string = text;
262 	BEGIN(INITIAL);
263 }
264 
265 
266 /*
267  * Try to open specified file with following names:
268  * ./name
269  * $(srctree)/name
270  * The latter is used when srctree is separate from objtree
271  * when compiling the kernel.
272  * Return NULL if file is not found.
273  */
274 FILE *zconf_fopen(const char *name)
275 {
276 	char *env, fullname[PATH_MAX+1];
277 	FILE *f;
278 
279 	f = fopen(name, "r");
280 	if (!f && name != NULL && name[0] != '/') {
281 		env = getenv(SRCTREE);
282 		if (env) {
283 			sprintf(fullname, "%s/%s", env, name);
284 			f = fopen(fullname, "r");
285 		}
286 	}
287 	return f;
288 }
289 
290 void zconf_initscan(const char *name)
291 {
292 	yyin = zconf_fopen(name);
293 	if (!yyin) {
294 		fprintf(stderr, "can't find file %s\n", name);
295 		exit(1);
296 	}
297 
298 	current_buf = xmalloc(sizeof(*current_buf));
299 	memset(current_buf, 0, sizeof(*current_buf));
300 
301 	current_file = file_lookup(name);
302 	yylineno = 1;
303 }
304 
305 void zconf_nextfile(const char *name)
306 {
307 	struct file *iter;
308 	struct file *file = file_lookup(name);
309 	struct buffer *buf = xmalloc(sizeof(*buf));
310 	memset(buf, 0, sizeof(*buf));
311 
312 	current_buf->state = YY_CURRENT_BUFFER;
313 	yyin = zconf_fopen(file->name);
314 	if (!yyin) {
315 		fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
316 			zconf_curname(), zconf_lineno(), file->name);
317 		exit(1);
318 	}
319 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
320 	buf->parent = current_buf;
321 	current_buf = buf;
322 
323 	current_file->lineno = yylineno;
324 	file->parent = current_file;
325 
326 	for (iter = current_file; iter; iter = iter->parent) {
327 		if (!strcmp(iter->name, file->name)) {
328 			fprintf(stderr,
329 				"Recursive inclusion detected.\n"
330 				"Inclusion path:\n"
331 				"  current file : %s\n", file->name);
332 			iter = file;
333 			do {
334 				iter = iter->parent;
335 				fprintf(stderr, "  included from: %s:%d\n",
336 					iter->name, iter->lineno - 1);
337 			} while (strcmp(iter->name, file->name));
338 			exit(1);
339 		}
340 	}
341 
342 	yylineno = 1;
343 	current_file = file;
344 }
345 
346 static void zconf_endfile(void)
347 {
348 	struct buffer *parent;
349 
350 	current_file = current_file->parent;
351 	if (current_file)
352 		yylineno = current_file->lineno;
353 
354 	parent = current_buf->parent;
355 	if (parent) {
356 		fclose(yyin);
357 		yy_delete_buffer(YY_CURRENT_BUFFER);
358 		yy_switch_to_buffer(parent->state);
359 	}
360 	free(current_buf);
361 	current_buf = parent;
362 }
363 
364 int zconf_lineno(void)
365 {
366 	return current_pos.lineno;
367 }
368 
369 const char *zconf_curname(void)
370 {
371 	return current_pos.file ? current_pos.file->name : "<none>";
372 }
373