18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci%option nostdinit noyywrap never-interactive full ecs
68c2ecf20Sopenharmony_ci%option 8bit nodefault yylineno
78c2ecf20Sopenharmony_ci%x ASSIGN_VAL HELP STRING
88c2ecf20Sopenharmony_ci%{
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <assert.h>
118c2ecf20Sopenharmony_ci#include <limits.h>
128c2ecf20Sopenharmony_ci#include <stdio.h>
138c2ecf20Sopenharmony_ci#include <stdlib.h>
148c2ecf20Sopenharmony_ci#include <string.h>
158c2ecf20Sopenharmony_ci#include <unistd.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "lkc.h"
188c2ecf20Sopenharmony_ci#include "parser.tab.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define YY_DECL		static int yylex1(void)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define START_STRSIZE	16
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic const char *kconfig_white_list[] = {
258c2ecf20Sopenharmony_ci	"vendor/Kconfig",
268c2ecf20Sopenharmony_ci	"net/newip/Kconfig",
278c2ecf20Sopenharmony_ci	"drivers/tzdriver/Kconfig",
288c2ecf20Sopenharmony_ci	"security/xpm/Kconfig",
298c2ecf20Sopenharmony_ci	"drivers/auth_ctl/Kconfig",
308c2ecf20Sopenharmony_ci	"drivers/staging/ucollection/Kconfig",
318c2ecf20Sopenharmony_ci	"fs/proc/memory_security/Kconfig",
328c2ecf20Sopenharmony_ci	"fs/code_sign/Kconfig",
338c2ecf20Sopenharmony_ci	"fs/dec/Kconfig",
348c2ecf20Sopenharmony_ci	"security/container_escape_detection/Kconfig",
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic struct {
388c2ecf20Sopenharmony_ci	struct file *file;
398c2ecf20Sopenharmony_ci	int lineno;
408c2ecf20Sopenharmony_ci} current_pos;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic int prev_prev_token = T_EOL;
438c2ecf20Sopenharmony_cistatic int prev_token = T_EOL;
448c2ecf20Sopenharmony_cistatic char *text;
458c2ecf20Sopenharmony_cistatic int text_size, text_asize;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistruct buffer {
488c2ecf20Sopenharmony_ci	struct buffer *parent;
498c2ecf20Sopenharmony_ci	YY_BUFFER_STATE state;
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic struct buffer *current_buf;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic int last_ts, first_ts;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic char *expand_token(const char *in, size_t n);
578c2ecf20Sopenharmony_cistatic void append_expanded_string(const char *in);
588c2ecf20Sopenharmony_cistatic void zconf_endhelp(void);
598c2ecf20Sopenharmony_cistatic void zconf_endfile(void);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic void new_string(void)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	text = xmalloc(START_STRSIZE);
648c2ecf20Sopenharmony_ci	text_asize = START_STRSIZE;
658c2ecf20Sopenharmony_ci	text_size = 0;
668c2ecf20Sopenharmony_ci	*text = 0;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void append_string(const char *str, int size)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	int new_size = text_size + size + 1;
728c2ecf20Sopenharmony_ci	if (new_size > text_asize) {
738c2ecf20Sopenharmony_ci		new_size += START_STRSIZE - 1;
748c2ecf20Sopenharmony_ci		new_size &= -START_STRSIZE;
758c2ecf20Sopenharmony_ci		text = xrealloc(text, new_size);
768c2ecf20Sopenharmony_ci		text_asize = new_size;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci	memcpy(text + text_size, str, size);
798c2ecf20Sopenharmony_ci	text_size += size;
808c2ecf20Sopenharmony_ci	text[text_size] = 0;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic void alloc_string(const char *str, int size)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	text = xmalloc(size + 1);
868c2ecf20Sopenharmony_ci	memcpy(text, str, size);
878c2ecf20Sopenharmony_ci	text[size] = 0;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic void warn_ignored_character(char chr)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	fprintf(stderr,
938c2ecf20Sopenharmony_ci	        "%s:%d:warning: ignoring unsupported character '%c'\n",
948c2ecf20Sopenharmony_ci	        current_file->name, yylineno, chr);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci%}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cin	[A-Za-z0-9_-]
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci%%
1018c2ecf20Sopenharmony_ci	int str = 0;
1028c2ecf20Sopenharmony_ci	int ts, i;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci#.*			/* ignore comment */
1058c2ecf20Sopenharmony_ci[ \t]*			/* whitespaces */
1068c2ecf20Sopenharmony_ci\\\n			/* escaped new line */
1078c2ecf20Sopenharmony_ci\n			return T_EOL;
1088c2ecf20Sopenharmony_ci"allnoconfig_y"		return T_ALLNOCONFIG_Y;
1098c2ecf20Sopenharmony_ci"bool"			return T_BOOL;
1108c2ecf20Sopenharmony_ci"choice"		return T_CHOICE;
1118c2ecf20Sopenharmony_ci"comment"		return T_COMMENT;
1128c2ecf20Sopenharmony_ci"config"		return T_CONFIG;
1138c2ecf20Sopenharmony_ci"def_bool"		return T_DEF_BOOL;
1148c2ecf20Sopenharmony_ci"def_tristate"		return T_DEF_TRISTATE;
1158c2ecf20Sopenharmony_ci"default"		return T_DEFAULT;
1168c2ecf20Sopenharmony_ci"defconfig_list"	return T_DEFCONFIG_LIST;
1178c2ecf20Sopenharmony_ci"depends"		return T_DEPENDS;
1188c2ecf20Sopenharmony_ci"endchoice"		return T_ENDCHOICE;
1198c2ecf20Sopenharmony_ci"endif"			return T_ENDIF;
1208c2ecf20Sopenharmony_ci"endmenu"		return T_ENDMENU;
1218c2ecf20Sopenharmony_ci"help"			return T_HELP;
1228c2ecf20Sopenharmony_ci"hex"			return T_HEX;
1238c2ecf20Sopenharmony_ci"if"			return T_IF;
1248c2ecf20Sopenharmony_ci"imply"			return T_IMPLY;
1258c2ecf20Sopenharmony_ci"int"			return T_INT;
1268c2ecf20Sopenharmony_ci"mainmenu"		return T_MAINMENU;
1278c2ecf20Sopenharmony_ci"menu"			return T_MENU;
1288c2ecf20Sopenharmony_ci"menuconfig"		return T_MENUCONFIG;
1298c2ecf20Sopenharmony_ci"modules"		return T_MODULES;
1308c2ecf20Sopenharmony_ci"on"			return T_ON;
1318c2ecf20Sopenharmony_ci"option"		return T_OPTION;
1328c2ecf20Sopenharmony_ci"optional"		return T_OPTIONAL;
1338c2ecf20Sopenharmony_ci"prompt"		return T_PROMPT;
1348c2ecf20Sopenharmony_ci"range"			return T_RANGE;
1358c2ecf20Sopenharmony_ci"select"		return T_SELECT;
1368c2ecf20Sopenharmony_ci"source"		return T_SOURCE;
1378c2ecf20Sopenharmony_ci"string"		return T_STRING;
1388c2ecf20Sopenharmony_ci"tristate"		return T_TRISTATE;
1398c2ecf20Sopenharmony_ci"visible"		return T_VISIBLE;
1408c2ecf20Sopenharmony_ci"||"			return T_OR;
1418c2ecf20Sopenharmony_ci"&&"			return T_AND;
1428c2ecf20Sopenharmony_ci"="			return T_EQUAL;
1438c2ecf20Sopenharmony_ci"!="			return T_UNEQUAL;
1448c2ecf20Sopenharmony_ci"<"			return T_LESS;
1458c2ecf20Sopenharmony_ci"<="			return T_LESS_EQUAL;
1468c2ecf20Sopenharmony_ci">"			return T_GREATER;
1478c2ecf20Sopenharmony_ci">="			return T_GREATER_EQUAL;
1488c2ecf20Sopenharmony_ci"!"			return T_NOT;
1498c2ecf20Sopenharmony_ci"("			return T_OPEN_PAREN;
1508c2ecf20Sopenharmony_ci")"			return T_CLOSE_PAREN;
1518c2ecf20Sopenharmony_ci":="			return T_COLON_EQUAL;
1528c2ecf20Sopenharmony_ci"+="			return T_PLUS_EQUAL;
1538c2ecf20Sopenharmony_ci\"|\'			{
1548c2ecf20Sopenharmony_ci				str = yytext[0];
1558c2ecf20Sopenharmony_ci				new_string();
1568c2ecf20Sopenharmony_ci				BEGIN(STRING);
1578c2ecf20Sopenharmony_ci			}
1588c2ecf20Sopenharmony_ci{n}+			{
1598c2ecf20Sopenharmony_ci				alloc_string(yytext, yyleng);
1608c2ecf20Sopenharmony_ci				yylval.string = text;
1618c2ecf20Sopenharmony_ci				return T_WORD;
1628c2ecf20Sopenharmony_ci			}
1638c2ecf20Sopenharmony_ci({n}|$)+		{
1648c2ecf20Sopenharmony_ci				/* this token includes at least one '$' */
1658c2ecf20Sopenharmony_ci				yylval.string = expand_token(yytext, yyleng);
1668c2ecf20Sopenharmony_ci				if (strlen(yylval.string))
1678c2ecf20Sopenharmony_ci					return T_WORD;
1688c2ecf20Sopenharmony_ci				free(yylval.string);
1698c2ecf20Sopenharmony_ci			}
1708c2ecf20Sopenharmony_ci.			warn_ignored_character(*yytext);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci<ASSIGN_VAL>{
1738c2ecf20Sopenharmony_ci	[^[:blank:]\n]+.*	{
1748c2ecf20Sopenharmony_ci		alloc_string(yytext, yyleng);
1758c2ecf20Sopenharmony_ci		yylval.string = text;
1768c2ecf20Sopenharmony_ci		return T_ASSIGN_VAL;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci	\n	{ BEGIN(INITIAL); return T_EOL; }
1798c2ecf20Sopenharmony_ci	.
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci<STRING>{
1838c2ecf20Sopenharmony_ci	"$".*	append_expanded_string(yytext);
1848c2ecf20Sopenharmony_ci	[^$'"\\\n]+	{
1858c2ecf20Sopenharmony_ci		append_string(yytext, yyleng);
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci	\\.?	{
1888c2ecf20Sopenharmony_ci		append_string(yytext + 1, yyleng - 1);
1898c2ecf20Sopenharmony_ci	}
1908c2ecf20Sopenharmony_ci	\'|\"	{
1918c2ecf20Sopenharmony_ci		if (str == yytext[0]) {
1928c2ecf20Sopenharmony_ci			BEGIN(INITIAL);
1938c2ecf20Sopenharmony_ci			yylval.string = text;
1948c2ecf20Sopenharmony_ci			return T_WORD_QUOTE;
1958c2ecf20Sopenharmony_ci		} else
1968c2ecf20Sopenharmony_ci			append_string(yytext, 1);
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci	\n	{
1998c2ecf20Sopenharmony_ci		fprintf(stderr,
2008c2ecf20Sopenharmony_ci			"%s:%d:warning: multi-line strings not supported\n",
2018c2ecf20Sopenharmony_ci			zconf_curname(), zconf_lineno());
2028c2ecf20Sopenharmony_ci		unput('\n');
2038c2ecf20Sopenharmony_ci		BEGIN(INITIAL);
2048c2ecf20Sopenharmony_ci		yylval.string = text;
2058c2ecf20Sopenharmony_ci		return T_WORD_QUOTE;
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci	<<EOF>>	{
2088c2ecf20Sopenharmony_ci		BEGIN(INITIAL);
2098c2ecf20Sopenharmony_ci		yylval.string = text;
2108c2ecf20Sopenharmony_ci		return T_WORD_QUOTE;
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci<HELP>{
2158c2ecf20Sopenharmony_ci	[ \t]+	{
2168c2ecf20Sopenharmony_ci		ts = 0;
2178c2ecf20Sopenharmony_ci		for (i = 0; i < yyleng; i++) {
2188c2ecf20Sopenharmony_ci			if (yytext[i] == '\t')
2198c2ecf20Sopenharmony_ci				ts = (ts & ~7) + 8;
2208c2ecf20Sopenharmony_ci			else
2218c2ecf20Sopenharmony_ci				ts++;
2228c2ecf20Sopenharmony_ci		}
2238c2ecf20Sopenharmony_ci		last_ts = ts;
2248c2ecf20Sopenharmony_ci		if (first_ts) {
2258c2ecf20Sopenharmony_ci			if (ts < first_ts) {
2268c2ecf20Sopenharmony_ci				zconf_endhelp();
2278c2ecf20Sopenharmony_ci				return T_HELPTEXT;
2288c2ecf20Sopenharmony_ci			}
2298c2ecf20Sopenharmony_ci			ts -= first_ts;
2308c2ecf20Sopenharmony_ci			while (ts > 8) {
2318c2ecf20Sopenharmony_ci				append_string("        ", 8);
2328c2ecf20Sopenharmony_ci				ts -= 8;
2338c2ecf20Sopenharmony_ci			}
2348c2ecf20Sopenharmony_ci			append_string("        ", ts);
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci	[ \t]*\n/[^ \t\n] {
2388c2ecf20Sopenharmony_ci		zconf_endhelp();
2398c2ecf20Sopenharmony_ci		return T_HELPTEXT;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci	[ \t]*\n	{
2428c2ecf20Sopenharmony_ci		append_string("\n", 1);
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci	[^ \t\n].* {
2458c2ecf20Sopenharmony_ci		while (yyleng) {
2468c2ecf20Sopenharmony_ci			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
2478c2ecf20Sopenharmony_ci				break;
2488c2ecf20Sopenharmony_ci			yyleng--;
2498c2ecf20Sopenharmony_ci		}
2508c2ecf20Sopenharmony_ci		append_string(yytext, yyleng);
2518c2ecf20Sopenharmony_ci		if (!first_ts)
2528c2ecf20Sopenharmony_ci			first_ts = last_ts;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci	<<EOF>>	{
2558c2ecf20Sopenharmony_ci		zconf_endhelp();
2568c2ecf20Sopenharmony_ci		return T_HELPTEXT;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci<<EOF>>	{
2618c2ecf20Sopenharmony_ci	BEGIN(INITIAL);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	if (prev_token != T_EOL && prev_token != T_HELPTEXT)
2648c2ecf20Sopenharmony_ci		fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
2658c2ecf20Sopenharmony_ci			current_file->name, yylineno);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (current_file) {
2688c2ecf20Sopenharmony_ci		zconf_endfile();
2698c2ecf20Sopenharmony_ci		return T_EOL;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci	fclose(yyin);
2728c2ecf20Sopenharmony_ci	yyterminate();
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci%%
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci/* second stage lexer */
2788c2ecf20Sopenharmony_ciint yylex(void)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	int token;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cirepeat:
2838c2ecf20Sopenharmony_ci	token = yylex1();
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
2868c2ecf20Sopenharmony_ci		if (token == T_EOL) {
2878c2ecf20Sopenharmony_ci			/* Do not pass unneeded T_EOL to the parser. */
2888c2ecf20Sopenharmony_ci			goto repeat;
2898c2ecf20Sopenharmony_ci		} else {
2908c2ecf20Sopenharmony_ci			/*
2918c2ecf20Sopenharmony_ci			 * For the parser, update file/lineno at the first token
2928c2ecf20Sopenharmony_ci			 * of each statement. Generally, \n is a statement
2938c2ecf20Sopenharmony_ci			 * terminator in Kconfig, but it is not always true
2948c2ecf20Sopenharmony_ci			 * because \n could be escaped by a backslash.
2958c2ecf20Sopenharmony_ci			 */
2968c2ecf20Sopenharmony_ci			current_pos.file = current_file;
2978c2ecf20Sopenharmony_ci			current_pos.lineno = yylineno;
2988c2ecf20Sopenharmony_ci		}
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	if (prev_prev_token == T_EOL && prev_token == T_WORD &&
3028c2ecf20Sopenharmony_ci	    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
3038c2ecf20Sopenharmony_ci		BEGIN(ASSIGN_VAL);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	prev_prev_token = prev_token;
3068c2ecf20Sopenharmony_ci	prev_token = token;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return token;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic char *expand_token(const char *in, size_t n)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	char *out;
3148c2ecf20Sopenharmony_ci	int c;
3158c2ecf20Sopenharmony_ci	char c2;
3168c2ecf20Sopenharmony_ci	const char *rest, *end;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	new_string();
3198c2ecf20Sopenharmony_ci	append_string(in, n);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/* get the whole line because we do not know the end of token. */
3228c2ecf20Sopenharmony_ci	while ((c = input()) != EOF) {
3238c2ecf20Sopenharmony_ci		if (c == '\n') {
3248c2ecf20Sopenharmony_ci			unput(c);
3258c2ecf20Sopenharmony_ci			break;
3268c2ecf20Sopenharmony_ci		}
3278c2ecf20Sopenharmony_ci		c2 = c;
3288c2ecf20Sopenharmony_ci		append_string(&c2, 1);
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	rest = text;
3328c2ecf20Sopenharmony_ci	out = expand_one_token(&rest);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	/* push back unused characters to the input stream */
3358c2ecf20Sopenharmony_ci	end = rest + strlen(rest);
3368c2ecf20Sopenharmony_ci	while (end > rest)
3378c2ecf20Sopenharmony_ci		unput(*--end);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	free(text);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	return out;
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic void append_expanded_string(const char *str)
3458c2ecf20Sopenharmony_ci{
3468c2ecf20Sopenharmony_ci	const char *end;
3478c2ecf20Sopenharmony_ci	char *res;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	str++;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	res = expand_dollar(&str);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	/* push back unused characters to the input stream */
3548c2ecf20Sopenharmony_ci	end = str + strlen(str);
3558c2ecf20Sopenharmony_ci	while (end > str)
3568c2ecf20Sopenharmony_ci		unput(*--end);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	append_string(res, strlen(res));
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	free(res);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_civoid zconf_starthelp(void)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	new_string();
3668c2ecf20Sopenharmony_ci	last_ts = first_ts = 0;
3678c2ecf20Sopenharmony_ci	BEGIN(HELP);
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cistatic void zconf_endhelp(void)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	yylval.string = text;
3738c2ecf20Sopenharmony_ci	BEGIN(INITIAL);
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/*
3788c2ecf20Sopenharmony_ci * Try to open specified file with following names:
3798c2ecf20Sopenharmony_ci * ./name
3808c2ecf20Sopenharmony_ci * $(srctree)/name
3818c2ecf20Sopenharmony_ci * The latter is used when srctree is separate from objtree
3828c2ecf20Sopenharmony_ci * when compiling the kernel.
3838c2ecf20Sopenharmony_ci * Return NULL if file is not found.
3848c2ecf20Sopenharmony_ci */
3858c2ecf20Sopenharmony_ciFILE *zconf_fopen(const char *name)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	char *env, fullname[PATH_MAX+1];
3888c2ecf20Sopenharmony_ci	FILE *f;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	f = fopen(name, "r");
3918c2ecf20Sopenharmony_ci	if (!f && name != NULL && name[0] != '/') {
3928c2ecf20Sopenharmony_ci		env = getenv(SRCTREE);
3938c2ecf20Sopenharmony_ci		if (env) {
3948c2ecf20Sopenharmony_ci			snprintf(fullname, sizeof(fullname),
3958c2ecf20Sopenharmony_ci				 "%s/%s", env, name);
3968c2ecf20Sopenharmony_ci			f = fopen(fullname, "r");
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci	return f;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_civoid zconf_initscan(const char *name)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	yyin = zconf_fopen(name);
4058c2ecf20Sopenharmony_ci	if (!yyin) {
4068c2ecf20Sopenharmony_ci		fprintf(stderr, "can't find file %s\n", name);
4078c2ecf20Sopenharmony_ci		exit(1);
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	current_buf = xmalloc(sizeof(*current_buf));
4118c2ecf20Sopenharmony_ci	memset(current_buf, 0, sizeof(*current_buf));
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	current_file = file_lookup(name);
4148c2ecf20Sopenharmony_ci	yylineno = 1;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cistatic bool zconf_in_whitelist(const char *path)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	int i;
4208c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(kconfig_white_list) / sizeof(kconfig_white_list[0]); i++) {
4218c2ecf20Sopenharmony_ci		if(strcmp(kconfig_white_list[i], path) == 0)
4228c2ecf20Sopenharmony_ci			return true;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci	return false;
4258c2ecf20Sopenharmony_ci}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_civoid zconf_nextfile(const char *name)
4288c2ecf20Sopenharmony_ci{
4298c2ecf20Sopenharmony_ci	struct file *iter;
4308c2ecf20Sopenharmony_ci	struct file *file = file_lookup(name);
4318c2ecf20Sopenharmony_ci	struct buffer *buf = NULL;
4328c2ecf20Sopenharmony_ci	FILE *yyin_tmp = zconf_fopen(file->name);
4338c2ecf20Sopenharmony_ci	if (!yyin_tmp) {
4348c2ecf20Sopenharmony_ci		if (zconf_in_whitelist(name) == true)
4358c2ecf20Sopenharmony_ci			return;
4368c2ecf20Sopenharmony_ci		fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
4378c2ecf20Sopenharmony_ci			zconf_curname(), zconf_lineno(), file->name);
4388c2ecf20Sopenharmony_ci		exit(1);
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	buf = xmalloc(sizeof(*buf));
4428c2ecf20Sopenharmony_ci	memset(buf, 0, sizeof(*buf));
4438c2ecf20Sopenharmony_ci	current_buf->state = YY_CURRENT_BUFFER;
4448c2ecf20Sopenharmony_ci	yyin = yyin_tmp;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
4478c2ecf20Sopenharmony_ci	buf->parent = current_buf;
4488c2ecf20Sopenharmony_ci	current_buf = buf;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	current_file->lineno = yylineno;
4518c2ecf20Sopenharmony_ci	file->parent = current_file;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	for (iter = current_file; iter; iter = iter->parent) {
4548c2ecf20Sopenharmony_ci		if (!strcmp(iter->name, file->name)) {
4558c2ecf20Sopenharmony_ci			fprintf(stderr,
4568c2ecf20Sopenharmony_ci				"Recursive inclusion detected.\n"
4578c2ecf20Sopenharmony_ci				"Inclusion path:\n"
4588c2ecf20Sopenharmony_ci				"  current file : %s\n", file->name);
4598c2ecf20Sopenharmony_ci			iter = file;
4608c2ecf20Sopenharmony_ci			do {
4618c2ecf20Sopenharmony_ci				iter = iter->parent;
4628c2ecf20Sopenharmony_ci				fprintf(stderr, "  included from: %s:%d\n",
4638c2ecf20Sopenharmony_ci					iter->name, iter->lineno - 1);
4648c2ecf20Sopenharmony_ci			} while (strcmp(iter->name, file->name));
4658c2ecf20Sopenharmony_ci			exit(1);
4668c2ecf20Sopenharmony_ci		}
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	yylineno = 1;
4708c2ecf20Sopenharmony_ci	current_file = file;
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_cistatic void zconf_endfile(void)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	struct buffer *parent;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	current_file = current_file->parent;
4788c2ecf20Sopenharmony_ci	if (current_file)
4798c2ecf20Sopenharmony_ci		yylineno = current_file->lineno;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	parent = current_buf->parent;
4828c2ecf20Sopenharmony_ci	if (parent) {
4838c2ecf20Sopenharmony_ci		fclose(yyin);
4848c2ecf20Sopenharmony_ci		yy_delete_buffer(YY_CURRENT_BUFFER);
4858c2ecf20Sopenharmony_ci		yy_switch_to_buffer(parent->state);
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci	free(current_buf);
4888c2ecf20Sopenharmony_ci	current_buf = parent;
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ciint zconf_lineno(void)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	return current_pos.lineno;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ciconst char *zconf_curname(void)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	return current_pos.file ? current_pos.file->name : "<none>";
4998c2ecf20Sopenharmony_ci}
500