%{

/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 *
 *	@(#)config.l	5.2 (Berkeley) 4/18/86
 */

#ident	"$Header: config.l 1.22 90/04/27 $"

#define TPRINTF(text) \
	if (trace_flag) { \
		printf((text)); \
	}

#define	TPRINTF2(text1,text2) \
	if (trace_flag) { \
		printf((text1),(text2)); \
	}

/*
 * Key word tables and initialization information.
 */
static int lex_keywords_initialized = 0;	/* keywords initialized */
static opaque_ptr sys_config_keys;		/* sys_config keyword table */
static opaque_ptr mod_config_keys;		/* mod_config keyword table */
static int parse_mode;				/* parse mode */

%}
KEYWORD_NAME	[A-Za-z_][-0-9A-Za-z_/.]*
PARAMETER_NAME	[A-Za-z_][0-9A-Za-z_]*
%START RESTRICTED_NAMES IN_EXPRESSION
%%
<INITIAL>{KEYWORD_NAME}	{
			int i;

			if ((i = keyword_lookup(yytext)) == -1)
			{
				yylval.str = (char *)yytext;
				TPRINTF2("id(%s) ", yytext);
				return(ID);
			}
			TPRINTF2("(%s) ", yytext);
			return(i);
		}
<IN_EXPRESSION,RESTRICTED_NAMES>{PARAMETER_NAME}	{
			int i;

			if ((i = generic_keyword_lookup(yytext)) == -1)
			{
				yylval.str = (char *)yytext;
				TPRINTF2("sym_id(%s) ", yytext);
				return(ID);
			}
			TPRINTF2("(%s) ", yytext);
			return(i);
		}
\"[^"]*\"	{
			TPRINTF2("string :%s:\n", yytext);
			if ( yytext[yyleng-2] == '\\' ) {
				TPRINTF("more set\n");
				yyless(yyleng-1);
				yymore();
			} else {
				yytext[strlen(yytext)-1] = '\0';
				yylval.str = (char *)(yytext + 1);
				return(ID);
			}
		}
"%RULES"	{
			if (parse_mode == PARSE_SYS) {
				TPRINTF("%%RULE ");
				return(PRULE_SYS);
			} else {
				yytext[strlen(yytext)-1] = '\0';
				yylval.str = (char *)(yytext + 1);
				return(ID);
			}
		}
0[0-7]*		{
			yylval.val = octal(yytext);
			TPRINTF2("#O:%o ", yylval.val);
			return(NUMBER);
		}
0x[0-9a-fA-F]+	{
			yylval.val = hex(yytext);
			TPRINTF2("#X:%x ", yylval.val);
			return(NUMBER);
		}
[1-9][0-9]*	{
			yylval.val = atoi(yytext);
			TPRINTF2("#D:%d ", yylval.val);
			return(NUMBER);
		}
"?"		{
			yylval.val = -1;
			TPRINTF("? ");
			return(NUMBER);
		}
<INITIAL,RESTRICTED_NAMES>\n	{
			TPRINTF("$\n");
			return(SEMICOLON);
		}
<IN_EXPRESSION>\n {	/* Ignored */;				}
[#].*		{	/* Ignored (comment) */;		}
[ \t]*		{	/* Ignored (white space) */;		}
","		{	TPRINTF(", "); return(COMMA);		}
";"		{	TPRINTF("; "); return(SEMICOLON);	}
"("		{	TPRINTF("( "); return(OPENP);		}
")"		{	TPRINTF(") "); return(CLOSEP);		}
"{"		{	TPRINTF("{ "); return(OPENC);		}
"}"		{	TPRINTF("} "); return(CLOSEC);		}
"["		{	TPRINTF("[ "); return(OPENB);		}
"]"		{	TPRINTF("] "); return(CLOSEB);		}
"<"		{	TPRINTF("< "); return(LESS);		}
"<="		{	TPRINTF("<= "); return(LESSEQ);		}
"="		{	TPRINTF("== "); return(EQ);		}
">="		{	TPRINTF(">= "); return(GTREQ);		}
">"		{	TPRINTF("> "); return(GTR);		}
"+"		{	TPRINTF("+ "); return(PLUS);		}
"*"		{	TPRINTF("* "); return(MULT);		}
"/"		{	TPRINTF("/ "); return(SLASH);		}
"-"		{	TPRINTF("- "); return(MINUS);		}
".."		{	TPRINTF(".. "); return(ELLIPSIS);	}
.		{	/* last rule to catch everything else.... */
			TPRINTF2("bad token:%s:\n", yytext);
			return(yytext[0]);
		}

%%
/*
 *  Initialize keyword tables.
 */
initialize_keywords()
{
#	define K_SYS	(1 << PARSE_SYS)	/* valid in sys_config */
#	define K_MOD	(1 << PARSE_MOD)	/* valid in mod_config */
	struct keywords {
		char *k_name;			/* keyword name */
		int k_value;			/* keyword yacc value */
		int k_visibility;		/* when it can be seen */
	};
	register struct keywords *kp;
	register opaque_ptr res;

	static struct keywords keywords[] = {
		{ "adjust",	ADJUST,		K_SYS|K_MOD },
		{ "arch_type",	ARCH_SYS,	K_SYS	    },
		{ "archive",	ARCHIVE_SYS,	K_SYS	    },
		{ "assert",	ASSERT,		K_SYS|K_MOD },
		{ "binaries",	BINARIES_MOD,	      K_MOD },
		{ "binary",	BINARIES_MOD,	      K_MOD },
		{ "block",	BLOCK_MOD,	      K_MOD },
		{ "bound",	BOUND,		K_SYS|K_MOD },
		{ "bus",	BUS_MOD,	      K_MOD },
		{ "busses",	BUS_MOD,	      K_MOD },
		{ "character",	CHARACTER_MOD,	      K_MOD },
		{ "checkfor",	CHECKFOR_MOD,	      K_MOD },
		{ "checkfor",	CHECKFOR_SYS,	K_SYS	    },
		{ "conf",	CONF,		K_SYS|K_MOD },
		{ "confh",	CONFH,		K_SYS|K_MOD },
		{ "declare",	DECLARE,	K_SYS|K_MOD },
		{ "default",	DEFAULT,	K_SYS|K_MOD },
		{ "desc",	DESC_SYS,	K_SYS       },
		{ "description",DESC_SYS,	K_SYS	    },
		{ "else",	ELSE,		K_SYS|K_MOD },
		{ "elsifconfig",ELSIFCONFIG,	K_SYS|K_MOD },
		{ "elsifdef",	ELSIFDEF,	K_SYS|K_MOD },
		{ "elsifnconfig",ELSIFNCONFIG,	K_SYS|K_MOD },
		{ "elsifndef",	ELSIFNDEF,	K_SYS|K_MOD },
		{ "elsifnproduct",ELSIFNPRODUCT,K_SYS|K_MOD },
		{ "elsifproduct",ELSIFPRODUCT,	K_SYS|K_MOD },
		{ "environment",ENVIRONMENT_SYS,K_SYS       },
		{ "fatal",	FATAL,		K_SYS|K_MOD },
		{ "filesystem",	FILESYSTEM_MOD,       K_MOD },
		{ "functions",	FUNCTIONS_MOD,	      K_MOD },
		{ "header",	HEADERS_MOD,	      K_MOD },
		{ "headers",	HEADERS_MOD,	      K_MOD },
		{ "ifconfig",	IFCONFIG,	K_SYS|K_MOD },
		{ "ifdef",	IFDEF,		K_SYS|K_MOD },
		{ "ifnconfig",	IFNCONFIG,	K_SYS|K_MOD },
		{ "ifndef",	IFNDEF,		K_SYS|K_MOD },
		{ "ifnproduct",	IFNPRODUCT,	K_SYS|K_MOD },
		{ "ifproduct",	IFPRODUCT,	K_SYS|K_MOD },
		{ "import",	IMPORT_SYS,	K_SYS	    },
		{ "include",	INCLUDE_SYS,	K_SYS       },
		{ "inits",	INITS,		K_SYS|K_MOD },
		{ "makefile",	MKFILE_SYS,	K_SYS       },
		{ "makeopts",	MKOPTS,		K_SYS|K_MOD },
		{ "maxpseudo",	MAXUNIT_MOD,	      K_MOD },
		{ "maxunit",	MAXUNIT_MOD,	      K_MOD },
		{ "minpseudo",	MINUNIT_MOD,	      K_MOD },
		{ "module",	MODULES,	K_SYS|K_MOD },
		{ "modules",	MODULES,	K_SYS|K_MOD },
		{ "new_default",NEW_DEFAULT,	K_SYS|K_MOD },
		{ "new-default",NEW_DEFAULT,	K_SYS|K_MOD },
		{ "NEXT",	NEXT_MOD,	      K_MOD },
		{ "nsegs",	NSEGS,		K_SYS|K_MOD },
		{ "on",		ON,		K_SYS|K_MOD },
		{ "on_bus",	ON_BUS,		      K_MOD },
		{ "on_busses",	ON_BUS,		      K_MOD },
		{ "prefix",	PREFIX_MOD,	      K_MOD },
		{ "print",	PRINT,		K_SYS|K_MOD },
		{ "pseudo-device",PSEUDO_DEVICE_MOD,  K_MOD },
		{ "pseudo_device",PSEUDO_DEVICE_MOD,  K_MOD },
		{ "pseudo-device",PSEUDO_DEVICE_SYS, K_SYS  },
		{ "pseudo_device",PSEUDO_DEVICE_SYS, K_SYS  },
		{ "segsize",	SEGSIZE,	K_SYS|K_MOD },
		{ "segalign",	SEGALIGN,	K_SYS|K_MOD },
		{ "set",	SET,		K_SYS|K_MOD },
		{ "space",	SPACE_MOD,	      K_MOD },
		{ "spaces",	SPACE_MOD,	      K_MOD },
		{ "streamd",	STREAMD_MOD,	      K_MOD },
		{ "streamm",	STREAMM_MOD,	      K_MOD },
		{ "stubs",	STUBS_MOD,	      K_MOD },
		{ "syscall",	SYSCALL_MOD,	      K_MOD },
		{ "syscalls",	SYSCALL_MOD,	      K_MOD },
		{ "trace",	TRACE,		K_SYS|K_MOD },
		{ "unit",	UNIT,		K_SYS|K_MOD },
		{ "version",	VERSION_SYS,	K_SYS       },
		{ "yydebug",	YYDEBUG,	K_SYS|K_MOD },
		{ 0, 0, 0 },
	};

	lex_keywords_initialized = 1;		/* Set initialized flag */

	sys_config_keys = create_symtab( sizeof(keywords)/sizeof(*kp) );
	mod_config_keys = create_symtab( sizeof(keywords)/sizeof(*kp) );
	kp = &keywords[0];
	while (kp->k_name) {
		if (kp->k_visibility & K_SYS) {	/* Enter sys_config keyword */
			res = insert_symtab(sys_config_keys, kp->k_name,
					    (opaque_ptr)&kp->k_value);
			if (res != (opaque_ptr)NULL) {
				fatal("internal error adding keyword\n");
				exit(1);
			}
		}
		if (kp->k_visibility & K_MOD) {	/* Enter mod_config keyword */
			res = insert_symtab(mod_config_keys, kp->k_name,
					    (opaque_ptr)&kp->k_value);
			if (res != (opaque_ptr)NULL) {
				fatal("internal error adding keyword\n");
				exit(1);
			}
		}
		kp++;				/* Go to next keyword */
	}
}

/*
 * generic_keyword_lookup
 *	Returns -1 if the given word is not a valid keyword in any parse
 *	mode.  Otherwise, the number of the keyword is returned.
 */
static int
generic_keyword_lookup (word)
register char *word;
{
	register opaque_ptr keyword_valuep;	/* Pointer to keyword value */

	keyword_valuep = search_symtab(sys_config_keys, word);
	if (keyword_valuep == (opaque_ptr)NULL)
		keyword_valuep = search_symtab(mod_config_keys, word);
	if (keyword_valuep != (opaque_ptr)NULL)
		return (*(int *)keyword_valuep);
	return (-1);
}

/*
 * keyword_lookup
 *	Look up a string in the appropriate keyword table.  Returns a -1 if
 *	the string is not a keyword; otherwise it returns the keyword number.
 */
static int
keyword_lookup(word)
register char *word;
{
	register opaque_ptr keyword_valuep;	/* Pointer to keyword value */

	switch (parse_mode) {
	case PARSE_SYS:			/* Parsing system configuration file */
		keyword_valuep = search_symtab(sys_config_keys, word);
		break;
	case PARSE_MOD:			/* Parsing module configuration file */
		keyword_valuep = search_symtab(mod_config_keys, word);
		break;
	default:
		fatal("Internal error in config.y: bad parse mode\n");
		exit(1);
	}
	if (keyword_valuep != (opaque_ptr)NULL)
		return (*(int *)keyword_valuep);
	return (-1);
}

/*
 * Number conversion routines
 */
static int
octal(str)
char *str;
{
	int num;

	(void) sscanf(str, "%o", &num);
	return num;
}

static int
hex(str)
char *str;
{
	int num;

	(void) sscanf(str+2, "%x", &num);
	return num;
}
