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