Linux Audio

Check our new training course

Loading...
v5.14.15
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  4 */
  5%option nostdinit noyywrap never-interactive full ecs
  6%option 8bit nodefault yylineno
  7%x ASSIGN_VAL HELP STRING
  8%{
  9
 10#include <assert.h>
 11#include <limits.h>
 12#include <stdio.h>
 13#include <stdlib.h>
 14#include <string.h>
 
 15
 16#include "lkc.h"
 17#include "parser.tab.h"
 18
 19#define YY_DECL		static int yylex1(void)
 20
 21#define START_STRSIZE	16
 22
 23static struct {
 24	struct file *file;
 25	int lineno;
 26} current_pos;
 27
 28static int prev_prev_token = T_EOL;
 29static int prev_token = T_EOL;
 30static char *text;
 31static int text_size, text_asize;
 32
 33struct buffer {
 34	struct buffer *parent;
 35	YY_BUFFER_STATE state;
 36};
 37
 38static struct buffer *current_buf;
 39
 40static int last_ts, first_ts;
 41
 42static char *expand_token(const char *in, size_t n);
 43static void append_expanded_string(const char *in);
 44static void zconf_endhelp(void);
 45static void zconf_endfile(void);
 46
 47static void new_string(void)
 48{
 49	text = xmalloc(START_STRSIZE);
 50	text_asize = START_STRSIZE;
 51	text_size = 0;
 52	*text = 0;
 53}
 54
 55static void append_string(const char *str, int size)
 56{
 57	int new_size = text_size + size + 1;
 58	if (new_size > text_asize) {
 59		new_size += START_STRSIZE - 1;
 60		new_size &= -START_STRSIZE;
 61		text = xrealloc(text, new_size);
 62		text_asize = new_size;
 63	}
 64	memcpy(text + text_size, str, size);
 65	text_size += size;
 66	text[text_size] = 0;
 67}
 68
 69static void alloc_string(const char *str, int size)
 70{
 71	text = xmalloc(size + 1);
 72	memcpy(text, str, size);
 73	text[size] = 0;
 74}
 75
 76static void warn_ignored_character(char chr)
 77{
 78	fprintf(stderr,
 79	        "%s:%d:warning: ignoring unsupported character '%c'\n",
 80	        current_file->name, yylineno, chr);
 81}
 82%}
 83
 84n	[A-Za-z0-9_-]
 85
 86%%
 87	int str = 0;
 88	int ts, i;
 89
 90#.*			/* ignore comment */
 91[ \t]*			/* whitespaces */
 92\\\n			/* escaped new line */
 93\n			return T_EOL;
 
 94"bool"			return T_BOOL;
 95"choice"		return T_CHOICE;
 96"comment"		return T_COMMENT;
 97"config"		return T_CONFIG;
 98"def_bool"		return T_DEF_BOOL;
 99"def_tristate"		return T_DEF_TRISTATE;
100"default"		return T_DEFAULT;
 
101"depends"		return T_DEPENDS;
102"endchoice"		return T_ENDCHOICE;
103"endif"			return T_ENDIF;
104"endmenu"		return T_ENDMENU;
105"help"			return T_HELP;
106"hex"			return T_HEX;
107"if"			return T_IF;
108"imply"			return T_IMPLY;
109"int"			return T_INT;
110"mainmenu"		return T_MAINMENU;
111"menu"			return T_MENU;
112"menuconfig"		return T_MENUCONFIG;
113"modules"		return T_MODULES;
114"on"			return T_ON;
 
115"optional"		return T_OPTIONAL;
116"prompt"		return T_PROMPT;
117"range"			return T_RANGE;
118"select"		return T_SELECT;
119"source"		return T_SOURCE;
120"string"		return T_STRING;
121"tristate"		return T_TRISTATE;
122"visible"		return T_VISIBLE;
123"||"			return T_OR;
124"&&"			return T_AND;
125"="			return T_EQUAL;
126"!="			return T_UNEQUAL;
127"<"			return T_LESS;
128"<="			return T_LESS_EQUAL;
129">"			return T_GREATER;
130">="			return T_GREATER_EQUAL;
131"!"			return T_NOT;
132"("			return T_OPEN_PAREN;
133")"			return T_CLOSE_PAREN;
134":="			return T_COLON_EQUAL;
135"+="			return T_PLUS_EQUAL;
136\"|\'			{
137				str = yytext[0];
138				new_string();
139				BEGIN(STRING);
140			}
141{n}+			{
142				alloc_string(yytext, yyleng);
143				yylval.string = text;
144				return T_WORD;
145			}
146({n}|$)+		{
147				/* this token includes at least one '$' */
148				yylval.string = expand_token(yytext, yyleng);
149				if (strlen(yylval.string))
150					return T_WORD;
151				free(yylval.string);
152			}
153.			warn_ignored_character(*yytext);
154
155<ASSIGN_VAL>{
156	[^[:blank:]\n]+.*	{
157		alloc_string(yytext, yyleng);
158		yylval.string = text;
159		return T_ASSIGN_VAL;
160	}
161	\n	{ BEGIN(INITIAL); return T_EOL; }
162	.
163}
164
165<STRING>{
166	"$".*	append_expanded_string(yytext);
167	[^$'"\\\n]+	{
168		append_string(yytext, yyleng);
169	}
170	\\.?	{
171		append_string(yytext + 1, yyleng - 1);
172	}
173	\'|\"	{
174		if (str == yytext[0]) {
175			BEGIN(INITIAL);
176			yylval.string = text;
177			return T_WORD_QUOTE;
178		} else
179			append_string(yytext, 1);
180	}
181	\n	{
182		fprintf(stderr,
183			"%s:%d:warning: multi-line strings not supported\n",
184			zconf_curname(), zconf_lineno());
185		unput('\n');
186		BEGIN(INITIAL);
187		yylval.string = text;
188		return T_WORD_QUOTE;
189	}
190	<<EOF>>	{
191		BEGIN(INITIAL);
192		yylval.string = text;
193		return T_WORD_QUOTE;
194	}
195}
196
197<HELP>{
198	[ \t]+	{
199		ts = 0;
200		for (i = 0; i < yyleng; i++) {
201			if (yytext[i] == '\t')
202				ts = (ts & ~7) + 8;
203			else
204				ts++;
205		}
206		last_ts = ts;
207		if (first_ts) {
208			if (ts < first_ts) {
209				zconf_endhelp();
210				return T_HELPTEXT;
211			}
212			ts -= first_ts;
213			while (ts > 8) {
214				append_string("        ", 8);
215				ts -= 8;
216			}
217			append_string("        ", ts);
218		}
219	}
220	[ \t]*\n/[^ \t\n] {
221		zconf_endhelp();
222		return T_HELPTEXT;
223	}
224	[ \t]*\n	{
225		append_string("\n", 1);
226	}
227	[^ \t\n].* {
228		while (yyleng) {
229			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
230				break;
231			yyleng--;
232		}
233		append_string(yytext, yyleng);
234		if (!first_ts)
235			first_ts = last_ts;
236	}
237	<<EOF>>	{
238		zconf_endhelp();
239		return T_HELPTEXT;
240	}
241}
242
243<<EOF>>	{
244	BEGIN(INITIAL);
245
246	if (prev_token != T_EOL && prev_token != T_HELPTEXT)
247		fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
248			current_file->name, yylineno);
249
250	if (current_file) {
251		zconf_endfile();
252		return T_EOL;
253	}
254	fclose(yyin);
255	yyterminate();
256}
257
258%%
259
260/* second stage lexer */
261int yylex(void)
262{
263	int token;
264
265repeat:
266	token = yylex1();
267
268	if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
269		if (token == T_EOL) {
270			/* Do not pass unneeded T_EOL to the parser. */
271			goto repeat;
272		} else {
273			/*
274			 * For the parser, update file/lineno at the first token
275			 * of each statement. Generally, \n is a statement
276			 * terminator in Kconfig, but it is not always true
277			 * because \n could be escaped by a backslash.
278			 */
279			current_pos.file = current_file;
280			current_pos.lineno = yylineno;
281		}
282	}
283
284	if (prev_prev_token == T_EOL && prev_token == T_WORD &&
285	    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
286		BEGIN(ASSIGN_VAL);
287
288	prev_prev_token = prev_token;
289	prev_token = token;
290
291	return token;
292}
293
294static char *expand_token(const char *in, size_t n)
295{
296	char *out;
297	int c;
298	char c2;
299	const char *rest, *end;
300
301	new_string();
302	append_string(in, n);
303
304	/* get the whole line because we do not know the end of token. */
305	while ((c = input()) != EOF) {
306		if (c == '\n') {
307			unput(c);
308			break;
309		}
310		c2 = c;
311		append_string(&c2, 1);
312	}
313
314	rest = text;
315	out = expand_one_token(&rest);
316
317	/* push back unused characters to the input stream */
318	end = rest + strlen(rest);
319	while (end > rest)
320		unput(*--end);
321
322	free(text);
323
324	return out;
325}
326
327static void append_expanded_string(const char *str)
328{
329	const char *end;
330	char *res;
331
332	str++;
333
334	res = expand_dollar(&str);
335
336	/* push back unused characters to the input stream */
337	end = str + strlen(str);
338	while (end > str)
339		unput(*--end);
340
341	append_string(res, strlen(res));
342
343	free(res);
344}
345
346void zconf_starthelp(void)
347{
348	new_string();
349	last_ts = first_ts = 0;
350	BEGIN(HELP);
351}
352
353static void zconf_endhelp(void)
354{
355	yylval.string = text;
356	BEGIN(INITIAL);
357}
358
359
360/*
361 * Try to open specified file with following names:
362 * ./name
363 * $(srctree)/name
364 * The latter is used when srctree is separate from objtree
365 * when compiling the kernel.
366 * Return NULL if file is not found.
367 */
368FILE *zconf_fopen(const char *name)
369{
370	char *env, fullname[PATH_MAX+1];
371	FILE *f;
372
373	f = fopen(name, "r");
374	if (!f && name != NULL && name[0] != '/') {
375		env = getenv(SRCTREE);
376		if (env) {
377			snprintf(fullname, sizeof(fullname),
378				 "%s/%s", env, name);
379			f = fopen(fullname, "r");
380		}
381	}
382	return f;
383}
384
385void zconf_initscan(const char *name)
386{
387	yyin = zconf_fopen(name);
388	if (!yyin) {
389		fprintf(stderr, "can't find file %s\n", name);
390		exit(1);
391	}
392
393	current_buf = xmalloc(sizeof(*current_buf));
394	memset(current_buf, 0, sizeof(*current_buf));
395
396	current_file = file_lookup(name);
397	yylineno = 1;
398}
399
400void zconf_nextfile(const char *name)
401{
402	struct file *iter;
403	struct file *file = file_lookup(name);
404	struct buffer *buf = xmalloc(sizeof(*buf));
405	memset(buf, 0, sizeof(*buf));
406
407	current_buf->state = YY_CURRENT_BUFFER;
408	yyin = zconf_fopen(file->name);
409	if (!yyin) {
410		fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
411			zconf_curname(), zconf_lineno(), file->name);
412		exit(1);
413	}
414	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
415	buf->parent = current_buf;
416	current_buf = buf;
417
418	current_file->lineno = yylineno;
419	file->parent = current_file;
420
421	for (iter = current_file; iter; iter = iter->parent) {
422		if (!strcmp(iter->name, file->name)) {
423			fprintf(stderr,
424				"Recursive inclusion detected.\n"
425				"Inclusion path:\n"
426				"  current file : %s\n", file->name);
427			iter = file;
428			do {
429				iter = iter->parent;
430				fprintf(stderr, "  included from: %s:%d\n",
431					iter->name, iter->lineno - 1);
432			} while (strcmp(iter->name, file->name));
433			exit(1);
434		}
435	}
436
437	yylineno = 1;
438	current_file = file;
439}
440
441static void zconf_endfile(void)
442{
443	struct buffer *parent;
444
445	current_file = current_file->parent;
446	if (current_file)
447		yylineno = current_file->lineno;
448
449	parent = current_buf->parent;
450	if (parent) {
451		fclose(yyin);
452		yy_delete_buffer(YY_CURRENT_BUFFER);
453		yy_switch_to_buffer(parent->state);
454	}
455	free(current_buf);
456	current_buf = parent;
457}
458
459int zconf_lineno(void)
460{
461	return current_pos.lineno;
462}
463
464const char *zconf_curname(void)
465{
466	return current_pos.file ? current_pos.file->name : "<none>";
467}
v5.9
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  4 */
  5%option nostdinit noyywrap never-interactive full ecs
  6%option 8bit nodefault yylineno
  7%x ASSIGN_VAL HELP STRING
  8%{
  9
 10#include <assert.h>
 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#include "parser.tab.h"
 19
 20#define YY_DECL		static int yylex1(void)
 21
 22#define START_STRSIZE	16
 23
 24static struct {
 25	struct file *file;
 26	int lineno;
 27} current_pos;
 28
 29static int prev_prev_token = T_EOL;
 30static int prev_token = T_EOL;
 31static char *text;
 32static int text_size, text_asize;
 33
 34struct buffer {
 35	struct buffer *parent;
 36	YY_BUFFER_STATE state;
 37};
 38
 39static struct buffer *current_buf;
 40
 41static int last_ts, first_ts;
 42
 43static char *expand_token(const char *in, size_t n);
 44static void append_expanded_string(const char *in);
 45static void zconf_endhelp(void);
 46static void zconf_endfile(void);
 47
 48static void new_string(void)
 49{
 50	text = xmalloc(START_STRSIZE);
 51	text_asize = START_STRSIZE;
 52	text_size = 0;
 53	*text = 0;
 54}
 55
 56static void append_string(const char *str, int size)
 57{
 58	int new_size = text_size + size + 1;
 59	if (new_size > text_asize) {
 60		new_size += START_STRSIZE - 1;
 61		new_size &= -START_STRSIZE;
 62		text = xrealloc(text, new_size);
 63		text_asize = new_size;
 64	}
 65	memcpy(text + text_size, str, size);
 66	text_size += size;
 67	text[text_size] = 0;
 68}
 69
 70static void alloc_string(const char *str, int size)
 71{
 72	text = xmalloc(size + 1);
 73	memcpy(text, str, size);
 74	text[size] = 0;
 75}
 76
 77static void warn_ignored_character(char chr)
 78{
 79	fprintf(stderr,
 80	        "%s:%d:warning: ignoring unsupported character '%c'\n",
 81	        current_file->name, yylineno, chr);
 82}
 83%}
 84
 85n	[A-Za-z0-9_-]
 86
 87%%
 88	int str = 0;
 89	int ts, i;
 90
 91#.*			/* ignore comment */
 92[ \t]*			/* whitespaces */
 93\\\n			/* escaped new line */
 94\n			return T_EOL;
 95"allnoconfig_y"		return T_ALLNOCONFIG_Y;
 96"bool"			return T_BOOL;
 97"choice"		return T_CHOICE;
 98"comment"		return T_COMMENT;
 99"config"		return T_CONFIG;
100"def_bool"		return T_DEF_BOOL;
101"def_tristate"		return T_DEF_TRISTATE;
102"default"		return T_DEFAULT;
103"defconfig_list"	return T_DEFCONFIG_LIST;
104"depends"		return T_DEPENDS;
105"endchoice"		return T_ENDCHOICE;
106"endif"			return T_ENDIF;
107"endmenu"		return T_ENDMENU;
108"help"			return T_HELP;
109"hex"			return T_HEX;
110"if"			return T_IF;
111"imply"			return T_IMPLY;
112"int"			return T_INT;
113"mainmenu"		return T_MAINMENU;
114"menu"			return T_MENU;
115"menuconfig"		return T_MENUCONFIG;
116"modules"		return T_MODULES;
117"on"			return T_ON;
118"option"		return T_OPTION;
119"optional"		return T_OPTIONAL;
120"prompt"		return T_PROMPT;
121"range"			return T_RANGE;
122"select"		return T_SELECT;
123"source"		return T_SOURCE;
124"string"		return T_STRING;
125"tristate"		return T_TRISTATE;
126"visible"		return T_VISIBLE;
127"||"			return T_OR;
128"&&"			return T_AND;
129"="			return T_EQUAL;
130"!="			return T_UNEQUAL;
131"<"			return T_LESS;
132"<="			return T_LESS_EQUAL;
133">"			return T_GREATER;
134">="			return T_GREATER_EQUAL;
135"!"			return T_NOT;
136"("			return T_OPEN_PAREN;
137")"			return T_CLOSE_PAREN;
138":="			return T_COLON_EQUAL;
139"+="			return T_PLUS_EQUAL;
140\"|\'			{
141				str = yytext[0];
142				new_string();
143				BEGIN(STRING);
144			}
145{n}+			{
146				alloc_string(yytext, yyleng);
147				yylval.string = text;
148				return T_WORD;
149			}
150({n}|$)+		{
151				/* this token includes at least one '$' */
152				yylval.string = expand_token(yytext, yyleng);
153				if (strlen(yylval.string))
154					return T_WORD;
155				free(yylval.string);
156			}
157.			warn_ignored_character(*yytext);
158
159<ASSIGN_VAL>{
160	[^[:blank:]\n]+.*	{
161		alloc_string(yytext, yyleng);
162		yylval.string = text;
163		return T_ASSIGN_VAL;
164	}
165	\n	{ BEGIN(INITIAL); return T_EOL; }
166	.
167}
168
169<STRING>{
170	"$".*	append_expanded_string(yytext);
171	[^$'"\\\n]+	{
172		append_string(yytext, yyleng);
173	}
174	\\.?	{
175		append_string(yytext + 1, yyleng - 1);
176	}
177	\'|\"	{
178		if (str == yytext[0]) {
179			BEGIN(INITIAL);
180			yylval.string = text;
181			return T_WORD_QUOTE;
182		} else
183			append_string(yytext, 1);
184	}
185	\n	{
186		fprintf(stderr,
187			"%s:%d:warning: multi-line strings not supported\n",
188			zconf_curname(), zconf_lineno());
189		unput('\n');
190		BEGIN(INITIAL);
191		yylval.string = text;
192		return T_WORD_QUOTE;
193	}
194	<<EOF>>	{
195		BEGIN(INITIAL);
196		yylval.string = text;
197		return T_WORD_QUOTE;
198	}
199}
200
201<HELP>{
202	[ \t]+	{
203		ts = 0;
204		for (i = 0; i < yyleng; i++) {
205			if (yytext[i] == '\t')
206				ts = (ts & ~7) + 8;
207			else
208				ts++;
209		}
210		last_ts = ts;
211		if (first_ts) {
212			if (ts < first_ts) {
213				zconf_endhelp();
214				return T_HELPTEXT;
215			}
216			ts -= first_ts;
217			while (ts > 8) {
218				append_string("        ", 8);
219				ts -= 8;
220			}
221			append_string("        ", ts);
222		}
223	}
224	[ \t]*\n/[^ \t\n] {
225		zconf_endhelp();
226		return T_HELPTEXT;
227	}
228	[ \t]*\n	{
229		append_string("\n", 1);
230	}
231	[^ \t\n].* {
232		while (yyleng) {
233			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
234				break;
235			yyleng--;
236		}
237		append_string(yytext, yyleng);
238		if (!first_ts)
239			first_ts = last_ts;
240	}
241	<<EOF>>	{
242		zconf_endhelp();
243		return T_HELPTEXT;
244	}
245}
246
247<<EOF>>	{
248	BEGIN(INITIAL);
249
250	if (prev_token != T_EOL && prev_token != T_HELPTEXT)
251		fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
252			current_file->name, yylineno);
253
254	if (current_file) {
255		zconf_endfile();
256		return T_EOL;
257	}
258	fclose(yyin);
259	yyterminate();
260}
261
262%%
263
264/* second stage lexer */
265int yylex(void)
266{
267	int token;
268
269repeat:
270	token = yylex1();
271
272	if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
273		if (token == T_EOL) {
274			/* Do not pass unneeded T_EOL to the parser. */
275			goto repeat;
276		} else {
277			/*
278			 * For the parser, update file/lineno at the first token
279			 * of each statement. Generally, \n is a statement
280			 * terminator in Kconfig, but it is not always true
281			 * because \n could be escaped by a backslash.
282			 */
283			current_pos.file = current_file;
284			current_pos.lineno = yylineno;
285		}
286	}
287
288	if (prev_prev_token == T_EOL && prev_token == T_WORD &&
289	    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
290		BEGIN(ASSIGN_VAL);
291
292	prev_prev_token = prev_token;
293	prev_token = token;
294
295	return token;
296}
297
298static char *expand_token(const char *in, size_t n)
299{
300	char *out;
301	int c;
302	char c2;
303	const char *rest, *end;
304
305	new_string();
306	append_string(in, n);
307
308	/* get the whole line because we do not know the end of token. */
309	while ((c = input()) != EOF) {
310		if (c == '\n') {
311			unput(c);
312			break;
313		}
314		c2 = c;
315		append_string(&c2, 1);
316	}
317
318	rest = text;
319	out = expand_one_token(&rest);
320
321	/* push back unused characters to the input stream */
322	end = rest + strlen(rest);
323	while (end > rest)
324		unput(*--end);
325
326	free(text);
327
328	return out;
329}
330
331static void append_expanded_string(const char *str)
332{
333	const char *end;
334	char *res;
335
336	str++;
337
338	res = expand_dollar(&str);
339
340	/* push back unused characters to the input stream */
341	end = str + strlen(str);
342	while (end > str)
343		unput(*--end);
344
345	append_string(res, strlen(res));
346
347	free(res);
348}
349
350void zconf_starthelp(void)
351{
352	new_string();
353	last_ts = first_ts = 0;
354	BEGIN(HELP);
355}
356
357static void zconf_endhelp(void)
358{
359	yylval.string = text;
360	BEGIN(INITIAL);
361}
362
363
364/*
365 * Try to open specified file with following names:
366 * ./name
367 * $(srctree)/name
368 * The latter is used when srctree is separate from objtree
369 * when compiling the kernel.
370 * Return NULL if file is not found.
371 */
372FILE *zconf_fopen(const char *name)
373{
374	char *env, fullname[PATH_MAX+1];
375	FILE *f;
376
377	f = fopen(name, "r");
378	if (!f && name != NULL && name[0] != '/') {
379		env = getenv(SRCTREE);
380		if (env) {
381			snprintf(fullname, sizeof(fullname),
382				 "%s/%s", env, name);
383			f = fopen(fullname, "r");
384		}
385	}
386	return f;
387}
388
389void zconf_initscan(const char *name)
390{
391	yyin = zconf_fopen(name);
392	if (!yyin) {
393		fprintf(stderr, "can't find file %s\n", name);
394		exit(1);
395	}
396
397	current_buf = xmalloc(sizeof(*current_buf));
398	memset(current_buf, 0, sizeof(*current_buf));
399
400	current_file = file_lookup(name);
401	yylineno = 1;
402}
403
404void zconf_nextfile(const char *name)
405{
406	struct file *iter;
407	struct file *file = file_lookup(name);
408	struct buffer *buf = xmalloc(sizeof(*buf));
409	memset(buf, 0, sizeof(*buf));
410
411	current_buf->state = YY_CURRENT_BUFFER;
412	yyin = zconf_fopen(file->name);
413	if (!yyin) {
414		fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
415			zconf_curname(), zconf_lineno(), file->name);
416		exit(1);
417	}
418	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
419	buf->parent = current_buf;
420	current_buf = buf;
421
422	current_file->lineno = yylineno;
423	file->parent = current_file;
424
425	for (iter = current_file; iter; iter = iter->parent) {
426		if (!strcmp(iter->name, file->name)) {
427			fprintf(stderr,
428				"Recursive inclusion detected.\n"
429				"Inclusion path:\n"
430				"  current file : %s\n", file->name);
431			iter = file;
432			do {
433				iter = iter->parent;
434				fprintf(stderr, "  included from: %s:%d\n",
435					iter->name, iter->lineno - 1);
436			} while (strcmp(iter->name, file->name));
437			exit(1);
438		}
439	}
440
441	yylineno = 1;
442	current_file = file;
443}
444
445static void zconf_endfile(void)
446{
447	struct buffer *parent;
448
449	current_file = current_file->parent;
450	if (current_file)
451		yylineno = current_file->lineno;
452
453	parent = current_buf->parent;
454	if (parent) {
455		fclose(yyin);
456		yy_delete_buffer(YY_CURRENT_BUFFER);
457		yy_switch_to_buffer(parent->state);
458	}
459	free(current_buf);
460	current_buf = parent;
461}
462
463int zconf_lineno(void)
464{
465	return current_pos.lineno;
466}
467
468const char *zconf_curname(void)
469{
470	return current_pos.file ? current_pos.file->name : "<none>";
471}