1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 *
14 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
15 * Use is subject to license terms.
16 */
17#pragma ident	"%Z%%M%	%I%	%E% SMI"
18
19#include "defs.h"
20
21	/* symbol types */
22#define VAR	1
23#define CONST	2
24
25struct syment {
26	int	s_type;
27	char	*s_name;
28	struct	namelist *s_value;
29	struct	syment *s_next;
30};
31
32static struct syment *hashtab[HASHSIZE];
33
34/*
35 * Define a variable from a command line argument.
36 */
37void
38define(name)
39	char *name;
40{
41	register char *cp, *s;
42	register struct namelist *nl;
43	struct namelist *value;
44
45	if (debug)
46		printf("define(%s)\n", name);
47
48	cp = index(name, '=');
49	if (cp == NULL)
50		value = NULL;
51	else if (cp[1] == '\0') {
52		*cp = '\0';
53		value = NULL;
54	} else if (cp[1] != '(') {
55		*cp++ = '\0';
56		value = makenl(cp);
57	} else {
58		nl = NULL;
59		*cp++ = '\0';
60		do
61			cp++;
62		while (*cp == ' ' || *cp == '\t');
63		for (s = cp; ; s++) {
64			switch (*s) {
65			case ')':
66				*s = '\0';
67			case '\0':
68				break;
69			case ' ':
70			case '\t':
71				*s++ = '\0';
72				while (*s == ' ' || *s == '\t')
73					s++;
74				if (*s == ')')
75					*s = '\0';
76				break;
77			default:
78				continue;
79			}
80			if (nl == NULL)
81				value = nl = makenl(cp);
82			else {
83				nl->n_next = makenl(cp);
84				nl = nl->n_next;
85			}
86			if (*s == '\0')
87				break;
88			cp = s;
89		}
90	}
91	(void) lookup(name, REPLACE, value);
92}
93
94/*
95 * Lookup name in the table and return a pointer to it.
96 * LOOKUP - just do lookup, return NULL if not found.
97 * INSERT - insert name with value, error if already defined.
98 * REPLACE - insert or replace name with value.
99 */
100
101struct namelist *
102lookup(name, action, value)
103	char *name;
104	int action;
105	struct namelist *value;
106{
107	register unsigned n;
108	register char *cp;
109	register struct syment *s;
110	char buf[256];
111
112	if (debug)
113		printf("lookup(%s, %d, %x)\n", name, action, value);
114
115	n = 0;
116	for (cp = name; *cp; )
117		n += *cp++;
118	n %= HASHSIZE;
119
120	for (s = hashtab[n]; s != NULL; s = s->s_next) {
121		if (strcmp(name, s->s_name))
122			continue;
123		if (action != LOOKUP) {
124			if (action != INSERT || s->s_type != CONST) {
125				(void)sprintf(buf, "%.*s redefined",
126				      sizeof(buf) - sizeof(" redefined"), name);
127				yyerror(buf);
128			}
129		}
130		return(s->s_value);
131	}
132
133	if (action == LOOKUP) {
134		(void)sprintf(buf, "%.*s undefined",
135			sizeof(buf) - sizeof(" undefined"), name);
136		yyerror(buf);
137		return(NULL);
138	}
139
140	s = ALLOC(syment);
141	if (s == NULL)
142		fatal("ran out of memory\n");
143	s->s_next = hashtab[n];
144	hashtab[n] = s;
145	s->s_type = action == INSERT ? VAR : CONST;
146	s->s_name = name;
147	s->s_value = value;
148	return(value);
149}
150