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
21static struct {
22	struct file *file;
23	int lineno;
24} current_pos;
25
26static char *text;
27static int text_size, text_asize;
28
29struct buffer {
30        struct buffer *parent;
31        YY_BUFFER_STATE state;
32};
33
34struct buffer *current_buf;
35
36static int last_ts, first_ts;
37
38static void zconf_endhelp(void);
39static void zconf_endfile(void);
40
41void new_string(void)
42{
43	text = malloc(START_STRSIZE);
44	text_asize = START_STRSIZE;
45	text_size = 0;
46	*text = 0;
47}
48
49void 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
67void 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
75ws	[ \n\t]
76n	[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%%
244void zconf_starthelp(void)
245{
246	new_string();
247	last_ts = first_ts = 0;
248	BEGIN(HELP);
249}
250
251static 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 */
266FILE *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
283void 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
299void 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
329static 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
347int zconf_lineno(void)
348{
349	return current_pos.lineno;
350}
351
352char *zconf_curname(void)
353{
354	return current_pos.file ? current_pos.file->name : "<none>";
355}
356