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
25 struct syment {
26 int s_type;
27 char *s_name;
28 struct namelist *s_value;
29 struct syment *s_next;
30 };
31
32 static struct syment *hashtab[HASHSIZE];
33
34 /*
35 * Define a variable from a command line argument.
36 */
37 void
define(name)38 define(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
101 struct namelist *
lookup(name,action,value)102 lookup(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