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