xref: /openbmc/linux/scripts/kconfig/lexer.l (revision 5ee9cd065836e5934710ca35653bce7905add20b)
1981e545aSMasahiro Yamada /* SPDX-License-Identifier: GPL-2.0 */
2981e545aSMasahiro Yamada /*
3981e545aSMasahiro Yamada  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4981e545aSMasahiro Yamada  */
5981e545aSMasahiro Yamada %option nostdinit noyywrap never-interactive full ecs
6981e545aSMasahiro Yamada %option 8bit nodefault yylineno
7981e545aSMasahiro Yamada %x ASSIGN_VAL HELP STRING
8981e545aSMasahiro Yamada %{
9981e545aSMasahiro Yamada 
10981e545aSMasahiro Yamada #include <assert.h>
11981e545aSMasahiro Yamada #include <limits.h>
12981e545aSMasahiro Yamada #include <stdio.h>
13981e545aSMasahiro Yamada #include <stdlib.h>
14981e545aSMasahiro Yamada #include <string.h>
15981e545aSMasahiro Yamada 
16981e545aSMasahiro Yamada #include "lkc.h"
17769a1c02SMasahiro Yamada #include "parser.tab.h"
18981e545aSMasahiro Yamada 
19981e545aSMasahiro Yamada #define YY_DECL		static int yylex1(void)
20981e545aSMasahiro Yamada 
21981e545aSMasahiro Yamada #define START_STRSIZE	16
22981e545aSMasahiro Yamada 
23981e545aSMasahiro Yamada static struct {
24981e545aSMasahiro Yamada 	struct file *file;
25981e545aSMasahiro Yamada 	int lineno;
26981e545aSMasahiro Yamada } current_pos;
27981e545aSMasahiro Yamada 
28981e545aSMasahiro Yamada static int prev_prev_token = T_EOL;
29981e545aSMasahiro Yamada static int prev_token = T_EOL;
30981e545aSMasahiro Yamada static char *text;
31981e545aSMasahiro Yamada static int text_size, text_asize;
32981e545aSMasahiro Yamada 
33981e545aSMasahiro Yamada struct buffer {
34981e545aSMasahiro Yamada 	struct buffer *parent;
35981e545aSMasahiro Yamada 	YY_BUFFER_STATE state;
36981e545aSMasahiro Yamada };
37981e545aSMasahiro Yamada 
38d41809ffSMasahiro Yamada static struct buffer *current_buf;
39981e545aSMasahiro Yamada 
40981e545aSMasahiro Yamada static int last_ts, first_ts;
41981e545aSMasahiro Yamada 
42981e545aSMasahiro Yamada static char *expand_token(const char *in, size_t n);
43981e545aSMasahiro Yamada static void append_expanded_string(const char *in);
44981e545aSMasahiro Yamada static void zconf_endhelp(void);
45981e545aSMasahiro Yamada static void zconf_endfile(void);
46981e545aSMasahiro Yamada 
new_string(void)47981e545aSMasahiro Yamada static void new_string(void)
48981e545aSMasahiro Yamada {
49981e545aSMasahiro Yamada 	text = xmalloc(START_STRSIZE);
50981e545aSMasahiro Yamada 	text_asize = START_STRSIZE;
51981e545aSMasahiro Yamada 	text_size = 0;
52981e545aSMasahiro Yamada 	*text = 0;
53981e545aSMasahiro Yamada }
54981e545aSMasahiro Yamada 
append_string(const char * str,int size)55981e545aSMasahiro Yamada static void append_string(const char *str, int size)
56981e545aSMasahiro Yamada {
57981e545aSMasahiro Yamada 	int new_size = text_size + size + 1;
58981e545aSMasahiro Yamada 	if (new_size > text_asize) {
59981e545aSMasahiro Yamada 		new_size += START_STRSIZE - 1;
60981e545aSMasahiro Yamada 		new_size &= -START_STRSIZE;
61981e545aSMasahiro Yamada 		text = xrealloc(text, new_size);
62981e545aSMasahiro Yamada 		text_asize = new_size;
63981e545aSMasahiro Yamada 	}
64981e545aSMasahiro Yamada 	memcpy(text + text_size, str, size);
65981e545aSMasahiro Yamada 	text_size += size;
66981e545aSMasahiro Yamada 	text[text_size] = 0;
67981e545aSMasahiro Yamada }
68981e545aSMasahiro Yamada 
alloc_string(const char * str,int size)69981e545aSMasahiro Yamada static void alloc_string(const char *str, int size)
70981e545aSMasahiro Yamada {
71981e545aSMasahiro Yamada 	text = xmalloc(size + 1);
72981e545aSMasahiro Yamada 	memcpy(text, str, size);
73981e545aSMasahiro Yamada 	text[size] = 0;
74981e545aSMasahiro Yamada }
75981e545aSMasahiro Yamada 
warn_ignored_character(char chr)76981e545aSMasahiro Yamada static void warn_ignored_character(char chr)
77981e545aSMasahiro Yamada {
78981e545aSMasahiro Yamada 	fprintf(stderr,
79981e545aSMasahiro Yamada 	        "%s:%d:warning: ignoring unsupported character '%c'\n",
80981e545aSMasahiro Yamada 	        current_file->name, yylineno, chr);
81981e545aSMasahiro Yamada }
82981e545aSMasahiro Yamada %}
83981e545aSMasahiro Yamada 
84981e545aSMasahiro Yamada n	[A-Za-z0-9_-]
85981e545aSMasahiro Yamada 
86981e545aSMasahiro Yamada %%
876988f70cSMasahiro Yamada 	char open_quote = 0;
88981e545aSMasahiro Yamada 
89981e545aSMasahiro Yamada #.*			/* ignore comment */
90981e545aSMasahiro Yamada [ \t]*			/* whitespaces */
91981e545aSMasahiro Yamada \\\n			/* escaped new line */
92981e545aSMasahiro Yamada \n			return T_EOL;
93981e545aSMasahiro Yamada "bool"			return T_BOOL;
94981e545aSMasahiro Yamada "choice"		return T_CHOICE;
95981e545aSMasahiro Yamada "comment"		return T_COMMENT;
96981e545aSMasahiro Yamada "config"		return T_CONFIG;
97981e545aSMasahiro Yamada "def_bool"		return T_DEF_BOOL;
98981e545aSMasahiro Yamada "def_tristate"		return T_DEF_TRISTATE;
99981e545aSMasahiro Yamada "default"		return T_DEFAULT;
100981e545aSMasahiro Yamada "depends"		return T_DEPENDS;
101981e545aSMasahiro Yamada "endchoice"		return T_ENDCHOICE;
102981e545aSMasahiro Yamada "endif"			return T_ENDIF;
103981e545aSMasahiro Yamada "endmenu"		return T_ENDMENU;
104f70f74d1SMasahiro Yamada "help"			return T_HELP;
105981e545aSMasahiro Yamada "hex"			return T_HEX;
106981e545aSMasahiro Yamada "if"			return T_IF;
107981e545aSMasahiro Yamada "imply"			return T_IMPLY;
108981e545aSMasahiro Yamada "int"			return T_INT;
109981e545aSMasahiro Yamada "mainmenu"		return T_MAINMENU;
110981e545aSMasahiro Yamada "menu"			return T_MENU;
111981e545aSMasahiro Yamada "menuconfig"		return T_MENUCONFIG;
112981e545aSMasahiro Yamada "modules"		return T_MODULES;
113981e545aSMasahiro Yamada "on"			return T_ON;
114981e545aSMasahiro Yamada "optional"		return T_OPTIONAL;
115981e545aSMasahiro Yamada "prompt"		return T_PROMPT;
116981e545aSMasahiro Yamada "range"			return T_RANGE;
117981e545aSMasahiro Yamada "select"		return T_SELECT;
118981e545aSMasahiro Yamada "source"		return T_SOURCE;
119981e545aSMasahiro Yamada "string"		return T_STRING;
120981e545aSMasahiro Yamada "tristate"		return T_TRISTATE;
121981e545aSMasahiro Yamada "visible"		return T_VISIBLE;
122981e545aSMasahiro Yamada "||"			return T_OR;
123981e545aSMasahiro Yamada "&&"			return T_AND;
124981e545aSMasahiro Yamada "="			return T_EQUAL;
125981e545aSMasahiro Yamada "!="			return T_UNEQUAL;
126981e545aSMasahiro Yamada "<"			return T_LESS;
127981e545aSMasahiro Yamada "<="			return T_LESS_EQUAL;
128981e545aSMasahiro Yamada ">"			return T_GREATER;
129981e545aSMasahiro Yamada ">="			return T_GREATER_EQUAL;
130981e545aSMasahiro Yamada "!"			return T_NOT;
131981e545aSMasahiro Yamada "("			return T_OPEN_PAREN;
132981e545aSMasahiro Yamada ")"			return T_CLOSE_PAREN;
133981e545aSMasahiro Yamada ":="			return T_COLON_EQUAL;
134981e545aSMasahiro Yamada "+="			return T_PLUS_EQUAL;
135981e545aSMasahiro Yamada \"|\'			{
1366988f70cSMasahiro Yamada 				open_quote = yytext[0];
137981e545aSMasahiro Yamada 				new_string();
138981e545aSMasahiro Yamada 				BEGIN(STRING);
139981e545aSMasahiro Yamada 			}
140981e545aSMasahiro Yamada {n}+			{
141981e545aSMasahiro Yamada 				alloc_string(yytext, yyleng);
142981e545aSMasahiro Yamada 				yylval.string = text;
143981e545aSMasahiro Yamada 				return T_WORD;
144981e545aSMasahiro Yamada 			}
145981e545aSMasahiro Yamada ({n}|$)+		{
146981e545aSMasahiro Yamada 				/* this token includes at least one '$' */
147981e545aSMasahiro Yamada 				yylval.string = expand_token(yytext, yyleng);
148981e545aSMasahiro Yamada 				if (strlen(yylval.string))
149981e545aSMasahiro Yamada 					return T_WORD;
150981e545aSMasahiro Yamada 				free(yylval.string);
151981e545aSMasahiro Yamada 			}
152981e545aSMasahiro Yamada .			warn_ignored_character(*yytext);
153981e545aSMasahiro Yamada 
154981e545aSMasahiro Yamada <ASSIGN_VAL>{
155981e545aSMasahiro Yamada 	[^[:blank:]\n]+.*	{
156981e545aSMasahiro Yamada 		alloc_string(yytext, yyleng);
157981e545aSMasahiro Yamada 		yylval.string = text;
158981e545aSMasahiro Yamada 		return T_ASSIGN_VAL;
159981e545aSMasahiro Yamada 	}
160981e545aSMasahiro Yamada 	\n	{ BEGIN(INITIAL); return T_EOL; }
161981e545aSMasahiro Yamada 	.
162981e545aSMasahiro Yamada }
163981e545aSMasahiro Yamada 
164981e545aSMasahiro Yamada <STRING>{
165981e545aSMasahiro Yamada 	"$".*	append_expanded_string(yytext);
166981e545aSMasahiro Yamada 	[^$'"\\\n]+	{
167981e545aSMasahiro Yamada 		append_string(yytext, yyleng);
168981e545aSMasahiro Yamada 	}
169981e545aSMasahiro Yamada 	\\.?	{
170981e545aSMasahiro Yamada 		append_string(yytext + 1, yyleng - 1);
171981e545aSMasahiro Yamada 	}
172981e545aSMasahiro Yamada 	\'|\"	{
1736988f70cSMasahiro Yamada 		if (open_quote == yytext[0]) {
174981e545aSMasahiro Yamada 			BEGIN(INITIAL);
175981e545aSMasahiro Yamada 			yylval.string = text;
176981e545aSMasahiro Yamada 			return T_WORD_QUOTE;
177981e545aSMasahiro Yamada 		} else
178981e545aSMasahiro Yamada 			append_string(yytext, 1);
179981e545aSMasahiro Yamada 	}
180981e545aSMasahiro Yamada 	\n	{
181981e545aSMasahiro Yamada 		fprintf(stderr,
182981e545aSMasahiro Yamada 			"%s:%d:warning: multi-line strings not supported\n",
183981e545aSMasahiro Yamada 			zconf_curname(), zconf_lineno());
184981e545aSMasahiro Yamada 		unput('\n');
185981e545aSMasahiro Yamada 		BEGIN(INITIAL);
186981e545aSMasahiro Yamada 		yylval.string = text;
187981e545aSMasahiro Yamada 		return T_WORD_QUOTE;
188981e545aSMasahiro Yamada 	}
189981e545aSMasahiro Yamada 	<<EOF>>	{
190981e545aSMasahiro Yamada 		BEGIN(INITIAL);
191981e545aSMasahiro Yamada 		yylval.string = text;
192981e545aSMasahiro Yamada 		return T_WORD_QUOTE;
193981e545aSMasahiro Yamada 	}
194981e545aSMasahiro Yamada }
195981e545aSMasahiro Yamada 
196981e545aSMasahiro Yamada <HELP>{
197981e545aSMasahiro Yamada 	[ \t]+	{
19865017d83SMasahiro Yamada 		int ts, i;
19965017d83SMasahiro Yamada 
200981e545aSMasahiro Yamada 		ts = 0;
201981e545aSMasahiro Yamada 		for (i = 0; i < yyleng; i++) {
202981e545aSMasahiro Yamada 			if (yytext[i] == '\t')
203981e545aSMasahiro Yamada 				ts = (ts & ~7) + 8;
204981e545aSMasahiro Yamada 			else
205981e545aSMasahiro Yamada 				ts++;
206981e545aSMasahiro Yamada 		}
207981e545aSMasahiro Yamada 		last_ts = ts;
208981e545aSMasahiro Yamada 		if (first_ts) {
209981e545aSMasahiro Yamada 			if (ts < first_ts) {
210981e545aSMasahiro Yamada 				zconf_endhelp();
211981e545aSMasahiro Yamada 				return T_HELPTEXT;
212981e545aSMasahiro Yamada 			}
213981e545aSMasahiro Yamada 			ts -= first_ts;
214981e545aSMasahiro Yamada 			while (ts > 8) {
215981e545aSMasahiro Yamada 				append_string("        ", 8);
216981e545aSMasahiro Yamada 				ts -= 8;
217981e545aSMasahiro Yamada 			}
218981e545aSMasahiro Yamada 			append_string("        ", ts);
219981e545aSMasahiro Yamada 		}
220981e545aSMasahiro Yamada 	}
221981e545aSMasahiro Yamada 	[ \t]*\n/[^ \t\n] {
222981e545aSMasahiro Yamada 		zconf_endhelp();
223981e545aSMasahiro Yamada 		return T_HELPTEXT;
224981e545aSMasahiro Yamada 	}
225981e545aSMasahiro Yamada 	[ \t]*\n	{
226981e545aSMasahiro Yamada 		append_string("\n", 1);
227981e545aSMasahiro Yamada 	}
228981e545aSMasahiro Yamada 	[^ \t\n].* {
229981e545aSMasahiro Yamada 		while (yyleng) {
230981e545aSMasahiro Yamada 			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
231981e545aSMasahiro Yamada 				break;
232981e545aSMasahiro Yamada 			yyleng--;
233981e545aSMasahiro Yamada 		}
234981e545aSMasahiro Yamada 		append_string(yytext, yyleng);
235981e545aSMasahiro Yamada 		if (!first_ts)
236981e545aSMasahiro Yamada 			first_ts = last_ts;
237981e545aSMasahiro Yamada 	}
238981e545aSMasahiro Yamada 	<<EOF>>	{
239981e545aSMasahiro Yamada 		zconf_endhelp();
240981e545aSMasahiro Yamada 		return T_HELPTEXT;
241981e545aSMasahiro Yamada 	}
242981e545aSMasahiro Yamada }
243981e545aSMasahiro Yamada 
244981e545aSMasahiro Yamada <<EOF>>	{
245981e545aSMasahiro Yamada 	BEGIN(INITIAL);
246981e545aSMasahiro Yamada 
247981e545aSMasahiro Yamada 	if (prev_token != T_EOL && prev_token != T_HELPTEXT)
248981e545aSMasahiro Yamada 		fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
249981e545aSMasahiro Yamada 			current_file->name, yylineno);
250981e545aSMasahiro Yamada 
251981e545aSMasahiro Yamada 	if (current_file) {
252981e545aSMasahiro Yamada 		zconf_endfile();
253981e545aSMasahiro Yamada 		return T_EOL;
254981e545aSMasahiro Yamada 	}
255981e545aSMasahiro Yamada 	fclose(yyin);
256981e545aSMasahiro Yamada 	yyterminate();
257981e545aSMasahiro Yamada }
258981e545aSMasahiro Yamada 
259981e545aSMasahiro Yamada %%
260981e545aSMasahiro Yamada 
261981e545aSMasahiro Yamada /* second stage lexer */
262981e545aSMasahiro Yamada int yylex(void)
263981e545aSMasahiro Yamada {
264981e545aSMasahiro Yamada 	int token;
265981e545aSMasahiro Yamada 
266981e545aSMasahiro Yamada repeat:
267981e545aSMasahiro Yamada 	token = yylex1();
268981e545aSMasahiro Yamada 
269981e545aSMasahiro Yamada 	if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
270981e545aSMasahiro Yamada 		if (token == T_EOL) {
271981e545aSMasahiro Yamada 			/* Do not pass unneeded T_EOL to the parser. */
272981e545aSMasahiro Yamada 			goto repeat;
273981e545aSMasahiro Yamada 		} else {
274981e545aSMasahiro Yamada 			/*
275981e545aSMasahiro Yamada 			 * For the parser, update file/lineno at the first token
276981e545aSMasahiro Yamada 			 * of each statement. Generally, \n is a statement
277981e545aSMasahiro Yamada 			 * terminator in Kconfig, but it is not always true
278981e545aSMasahiro Yamada 			 * because \n could be escaped by a backslash.
279981e545aSMasahiro Yamada 			 */
280981e545aSMasahiro Yamada 			current_pos.file = current_file;
281981e545aSMasahiro Yamada 			current_pos.lineno = yylineno;
282981e545aSMasahiro Yamada 		}
283981e545aSMasahiro Yamada 	}
284981e545aSMasahiro Yamada 
285981e545aSMasahiro Yamada 	if (prev_prev_token == T_EOL && prev_token == T_WORD &&
286981e545aSMasahiro Yamada 	    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
287981e545aSMasahiro Yamada 		BEGIN(ASSIGN_VAL);
288981e545aSMasahiro Yamada 
289981e545aSMasahiro Yamada 	prev_prev_token = prev_token;
290981e545aSMasahiro Yamada 	prev_token = token;
291981e545aSMasahiro Yamada 
292981e545aSMasahiro Yamada 	return token;
293981e545aSMasahiro Yamada }
294981e545aSMasahiro Yamada 
295981e545aSMasahiro Yamada static char *expand_token(const char *in, size_t n)
296981e545aSMasahiro Yamada {
297981e545aSMasahiro Yamada 	char *out;
298981e545aSMasahiro Yamada 	int c;
299981e545aSMasahiro Yamada 	char c2;
300981e545aSMasahiro Yamada 	const char *rest, *end;
301981e545aSMasahiro Yamada 
302981e545aSMasahiro Yamada 	new_string();
303981e545aSMasahiro Yamada 	append_string(in, n);
304981e545aSMasahiro Yamada 
305*3328ff75SMasahiro Yamada 	/*
306*3328ff75SMasahiro Yamada 	 * get the whole line because we do not know the end of token.
307*3328ff75SMasahiro Yamada 	 * input() returns 0 (not EOF!) when it reachs the end of file.
308*3328ff75SMasahiro Yamada 	 */
309*3328ff75SMasahiro Yamada 	while ((c = input()) != 0) {
310981e545aSMasahiro Yamada 		if (c == '\n') {
311981e545aSMasahiro Yamada 			unput(c);
312981e545aSMasahiro Yamada 			break;
313981e545aSMasahiro Yamada 		}
314981e545aSMasahiro Yamada 		c2 = c;
315981e545aSMasahiro Yamada 		append_string(&c2, 1);
316981e545aSMasahiro Yamada 	}
317981e545aSMasahiro Yamada 
318981e545aSMasahiro Yamada 	rest = text;
319981e545aSMasahiro Yamada 	out = expand_one_token(&rest);
320981e545aSMasahiro Yamada 
321981e545aSMasahiro Yamada 	/* push back unused characters to the input stream */
322981e545aSMasahiro Yamada 	end = rest + strlen(rest);
323981e545aSMasahiro Yamada 	while (end > rest)
324981e545aSMasahiro Yamada 		unput(*--end);
325981e545aSMasahiro Yamada 
326981e545aSMasahiro Yamada 	free(text);
327981e545aSMasahiro Yamada 
328981e545aSMasahiro Yamada 	return out;
329981e545aSMasahiro Yamada }
330981e545aSMasahiro Yamada 
331981e545aSMasahiro Yamada static void append_expanded_string(const char *str)
332981e545aSMasahiro Yamada {
333981e545aSMasahiro Yamada 	const char *end;
334981e545aSMasahiro Yamada 	char *res;
335981e545aSMasahiro Yamada 
336981e545aSMasahiro Yamada 	str++;
337981e545aSMasahiro Yamada 
338981e545aSMasahiro Yamada 	res = expand_dollar(&str);
339981e545aSMasahiro Yamada 
340981e545aSMasahiro Yamada 	/* push back unused characters to the input stream */
341981e545aSMasahiro Yamada 	end = str + strlen(str);
342981e545aSMasahiro Yamada 	while (end > str)
343981e545aSMasahiro Yamada 		unput(*--end);
344981e545aSMasahiro Yamada 
345981e545aSMasahiro Yamada 	append_string(res, strlen(res));
346981e545aSMasahiro Yamada 
347981e545aSMasahiro Yamada 	free(res);
348981e545aSMasahiro Yamada }
349981e545aSMasahiro Yamada 
350981e545aSMasahiro Yamada void zconf_starthelp(void)
351981e545aSMasahiro Yamada {
352981e545aSMasahiro Yamada 	new_string();
353981e545aSMasahiro Yamada 	last_ts = first_ts = 0;
354981e545aSMasahiro Yamada 	BEGIN(HELP);
355981e545aSMasahiro Yamada }
356981e545aSMasahiro Yamada 
357981e545aSMasahiro Yamada static void zconf_endhelp(void)
358981e545aSMasahiro Yamada {
359981e545aSMasahiro Yamada 	yylval.string = text;
360981e545aSMasahiro Yamada 	BEGIN(INITIAL);
361981e545aSMasahiro Yamada }
362981e545aSMasahiro Yamada 
363981e545aSMasahiro Yamada 
364981e545aSMasahiro Yamada /*
365981e545aSMasahiro Yamada  * Try to open specified file with following names:
366981e545aSMasahiro Yamada  * ./name
367981e545aSMasahiro Yamada  * $(srctree)/name
368981e545aSMasahiro Yamada  * The latter is used when srctree is separate from objtree
369981e545aSMasahiro Yamada  * when compiling the kernel.
370981e545aSMasahiro Yamada  * Return NULL if file is not found.
371981e545aSMasahiro Yamada  */
372981e545aSMasahiro Yamada FILE *zconf_fopen(const char *name)
373981e545aSMasahiro Yamada {
374981e545aSMasahiro Yamada 	char *env, fullname[PATH_MAX+1];
375981e545aSMasahiro Yamada 	FILE *f;
376981e545aSMasahiro Yamada 
377981e545aSMasahiro Yamada 	f = fopen(name, "r");
378981e545aSMasahiro Yamada 	if (!f && name != NULL && name[0] != '/') {
379981e545aSMasahiro Yamada 		env = getenv(SRCTREE);
380981e545aSMasahiro Yamada 		if (env) {
381b9d1a8e9SJacob Garber 			snprintf(fullname, sizeof(fullname),
382b9d1a8e9SJacob Garber 				 "%s/%s", env, name);
383981e545aSMasahiro Yamada 			f = fopen(fullname, "r");
384981e545aSMasahiro Yamada 		}
385981e545aSMasahiro Yamada 	}
386981e545aSMasahiro Yamada 	return f;
387981e545aSMasahiro Yamada }
388981e545aSMasahiro Yamada 
389981e545aSMasahiro Yamada void zconf_initscan(const char *name)
390981e545aSMasahiro Yamada {
391981e545aSMasahiro Yamada 	yyin = zconf_fopen(name);
392981e545aSMasahiro Yamada 	if (!yyin) {
393981e545aSMasahiro Yamada 		fprintf(stderr, "can't find file %s\n", name);
394981e545aSMasahiro Yamada 		exit(1);
395981e545aSMasahiro Yamada 	}
396981e545aSMasahiro Yamada 
397981e545aSMasahiro Yamada 	current_buf = xmalloc(sizeof(*current_buf));
398981e545aSMasahiro Yamada 	memset(current_buf, 0, sizeof(*current_buf));
399981e545aSMasahiro Yamada 
400981e545aSMasahiro Yamada 	current_file = file_lookup(name);
401981e545aSMasahiro Yamada 	yylineno = 1;
402981e545aSMasahiro Yamada }
403981e545aSMasahiro Yamada 
404981e545aSMasahiro Yamada void zconf_nextfile(const char *name)
405981e545aSMasahiro Yamada {
406981e545aSMasahiro Yamada 	struct file *iter;
407981e545aSMasahiro Yamada 	struct file *file = file_lookup(name);
408981e545aSMasahiro Yamada 	struct buffer *buf = xmalloc(sizeof(*buf));
409981e545aSMasahiro Yamada 	memset(buf, 0, sizeof(*buf));
410981e545aSMasahiro Yamada 
411981e545aSMasahiro Yamada 	current_buf->state = YY_CURRENT_BUFFER;
412981e545aSMasahiro Yamada 	yyin = zconf_fopen(file->name);
413981e545aSMasahiro Yamada 	if (!yyin) {
414981e545aSMasahiro Yamada 		fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
415981e545aSMasahiro Yamada 			zconf_curname(), zconf_lineno(), file->name);
416981e545aSMasahiro Yamada 		exit(1);
417981e545aSMasahiro Yamada 	}
418981e545aSMasahiro Yamada 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
419981e545aSMasahiro Yamada 	buf->parent = current_buf;
420981e545aSMasahiro Yamada 	current_buf = buf;
421981e545aSMasahiro Yamada 
422981e545aSMasahiro Yamada 	current_file->lineno = yylineno;
423981e545aSMasahiro Yamada 	file->parent = current_file;
424981e545aSMasahiro Yamada 
425981e545aSMasahiro Yamada 	for (iter = current_file; iter; iter = iter->parent) {
426981e545aSMasahiro Yamada 		if (!strcmp(iter->name, file->name)) {
427981e545aSMasahiro Yamada 			fprintf(stderr,
428981e545aSMasahiro Yamada 				"Recursive inclusion detected.\n"
429981e545aSMasahiro Yamada 				"Inclusion path:\n"
430981e545aSMasahiro Yamada 				"  current file : %s\n", file->name);
431981e545aSMasahiro Yamada 			iter = file;
432981e545aSMasahiro Yamada 			do {
433981e545aSMasahiro Yamada 				iter = iter->parent;
434981e545aSMasahiro Yamada 				fprintf(stderr, "  included from: %s:%d\n",
435981e545aSMasahiro Yamada 					iter->name, iter->lineno - 1);
436981e545aSMasahiro Yamada 			} while (strcmp(iter->name, file->name));
437981e545aSMasahiro Yamada 			exit(1);
438981e545aSMasahiro Yamada 		}
439981e545aSMasahiro Yamada 	}
440981e545aSMasahiro Yamada 
441981e545aSMasahiro Yamada 	yylineno = 1;
442981e545aSMasahiro Yamada 	current_file = file;
443981e545aSMasahiro Yamada }
444981e545aSMasahiro Yamada 
445981e545aSMasahiro Yamada static void zconf_endfile(void)
446981e545aSMasahiro Yamada {
447981e545aSMasahiro Yamada 	struct buffer *parent;
448981e545aSMasahiro Yamada 
449981e545aSMasahiro Yamada 	current_file = current_file->parent;
450981e545aSMasahiro Yamada 	if (current_file)
451981e545aSMasahiro Yamada 		yylineno = current_file->lineno;
452981e545aSMasahiro Yamada 
453981e545aSMasahiro Yamada 	parent = current_buf->parent;
454981e545aSMasahiro Yamada 	if (parent) {
455981e545aSMasahiro Yamada 		fclose(yyin);
456981e545aSMasahiro Yamada 		yy_delete_buffer(YY_CURRENT_BUFFER);
457981e545aSMasahiro Yamada 		yy_switch_to_buffer(parent->state);
458981e545aSMasahiro Yamada 	}
459981e545aSMasahiro Yamada 	free(current_buf);
460981e545aSMasahiro Yamada 	current_buf = parent;
461981e545aSMasahiro Yamada }
462981e545aSMasahiro Yamada 
463981e545aSMasahiro Yamada int zconf_lineno(void)
464981e545aSMasahiro Yamada {
465981e545aSMasahiro Yamada 	return current_pos.lineno;
466981e545aSMasahiro Yamada }
467981e545aSMasahiro Yamada 
468981e545aSMasahiro Yamada const char *zconf_curname(void)
469981e545aSMasahiro Yamada {
470981e545aSMasahiro Yamada 	return current_pos.file ? current_pos.file->name : "<none>";
471981e545aSMasahiro Yamada }
472