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 
18 #include "defs.h"
19 
20 	/* symbol types */
21 #define VAR	1
22 #define CONST	2
23 
24 struct syment {
25 	int	s_type;
26 	char	*s_name;
27 	struct	namelist *s_value;
28 	struct	syment *s_next;
29 };
30 
31 static struct syment *hashtab[HASHSIZE];
32 
33 /*
34  * Define a variable from a command line argument.
35  */
36 void
define(name)37 define(name)
38 	char *name;
39 {
40 	register char *cp, *s;
41 	register struct namelist *nl;
42 	struct namelist *value;
43 
44 	if (debug)
45 		printf("define(%s)\n", name);
46 
47 	cp = index(name, '=');
48 	if (cp == NULL)
49 		value = NULL;
50 	else if (cp[1] == '\0') {
51 		*cp = '\0';
52 		value = NULL;
53 	} else if (cp[1] != '(') {
54 		*cp++ = '\0';
55 		value = makenl(cp);
56 	} else {
57 		nl = NULL;
58 		*cp++ = '\0';
59 		do
60 			cp++;
61 		while (*cp == ' ' || *cp == '\t');
62 		for (s = cp; ; s++) {
63 			switch (*s) {
64 			case ')':
65 				*s = '\0';
66 			case '\0':
67 				break;
68 			case ' ':
69 			case '\t':
70 				*s++ = '\0';
71 				while (*s == ' ' || *s == '\t')
72 					s++;
73 				if (*s == ')')
74 					*s = '\0';
75 				break;
76 			default:
77 				continue;
78 			}
79 			if (nl == NULL)
80 				value = nl = makenl(cp);
81 			else {
82 				nl->n_next = makenl(cp);
83 				nl = nl->n_next;
84 			}
85 			if (*s == '\0')
86 				break;
87 			cp = s;
88 		}
89 	}
90 	(void) lookup(name, REPLACE, value);
91 }
92 
93 /*
94  * Lookup name in the table and return a pointer to it.
95  * LOOKUP - just do lookup, return NULL if not found.
96  * INSERT - insert name with value, error if already defined.
97  * REPLACE - insert or replace name with value.
98  */
99 
100 struct namelist *
lookup(name,action,value)101 lookup(name, action, value)
102 	char *name;
103 	int action;
104 	struct namelist *value;
105 {
106 	register unsigned n;
107 	register char *cp;
108 	register struct syment *s;
109 	char buf[256];
110 
111 	if (debug)
112 		printf("lookup(%s, %d, %x)\n", name, action, value);
113 
114 	n = 0;
115 	for (cp = name; *cp; )
116 		n += *cp++;
117 	n %= HASHSIZE;
118 
119 	for (s = hashtab[n]; s != NULL; s = s->s_next) {
120 		if (strcmp(name, s->s_name))
121 			continue;
122 		if (action != LOOKUP) {
123 			if (action != INSERT || s->s_type != CONST) {
124 				(void)sprintf(buf, "%.*s redefined",
125 				      sizeof(buf) - sizeof(" redefined"), name);
126 				yyerror(buf);
127 			}
128 		}
129 		return(s->s_value);
130 	}
131 
132 	if (action == LOOKUP) {
133 		(void)sprintf(buf, "%.*s undefined",
134 			sizeof(buf) - sizeof(" undefined"), name);
135 		yyerror(buf);
136 		return(NULL);
137 	}
138 
139 	s = ALLOC(syment);
140 	if (s == NULL)
141 		fatal("ran out of memory\n");
142 	s->s_next = hashtab[n];
143 	hashtab[n] = s;
144 	s->s_type = action == INSERT ? VAR : CONST;
145 	s->s_name = name;
146 	s->s_value = value;
147 	return(value);
148 }
149