Commit | Line | Data |
---|---|---|
837386b3 | 1 | #ifndef lint |
82572cb6 | 2 | static char *sccsid = "@(#)lookup.c 4.2 (Berkeley) 83/09/27"; |
837386b3 RC |
3 | #endif |
4 | ||
5 | #include "defs.h" | |
6 | ||
7 | /* | |
8 | * Define a variable from a command line argument. | |
9 | */ | |
10 | define(name) | |
11 | char *name; | |
12 | { | |
13 | register char *cp, *s; | |
14 | register struct block *bp, *value; | |
15 | ||
16 | if (debug) | |
17 | printf("define(%s)\n", name); | |
18 | ||
19 | cp = index(name, '='); | |
20 | if (cp == NULL || cp[1] == '\0') | |
21 | value = NULL; | |
22 | else if (cp[1] != '(') { | |
23 | *cp++ = '\0'; | |
24 | value = makeblock(NAME, cp); | |
25 | } else { | |
26 | bp = NULL; | |
27 | *cp++ = '\0'; | |
28 | do | |
29 | cp++; | |
30 | while (*cp == ' ' || *cp == '\t'); | |
31 | for (s = cp; ; s++) { | |
32 | switch (*s) { | |
33 | case ')': | |
34 | *s = '\0'; | |
35 | case '\0': | |
36 | break; | |
37 | case ' ': | |
38 | case '\t': | |
39 | *s++ = '\0'; | |
40 | while (*s == ' ' || *s == '\t') | |
41 | s++; | |
42 | if (*s == ')') | |
43 | *s = '\0'; | |
44 | break; | |
45 | default: | |
46 | continue; | |
47 | } | |
48 | if (bp == NULL) | |
49 | value = bp = makeblock(NAME, cp); | |
50 | else { | |
51 | bp->b_next = makeblock(NAME, cp); | |
52 | bp = bp->b_next; | |
53 | } | |
54 | if (*s == '\0') | |
55 | break; | |
56 | cp = s; | |
57 | } | |
58 | } | |
59 | bp = makeblock(VAR, name); | |
60 | bp->b_args = value; | |
61 | (void) lookup(bp->b_name, bp, 1); | |
62 | } | |
63 | ||
64 | static struct block *hashtab[HASHSIZE]; | |
65 | ||
66 | /* | |
67 | * Lookup name in the table and return a pointer to it. | |
68 | * Insert == 0 - just do lookup, return NULL if not found. | |
69 | * insert == 1 - insert name with value, error if already defined. | |
70 | * insert == 2 - replace name with value if not entered with insert == 1. | |
71 | */ | |
72 | ||
73 | struct block * | |
74 | lookup(name, value, insert) | |
75 | char *name; | |
76 | struct block *value; | |
77 | int insert; | |
78 | { | |
79 | register unsigned n; | |
80 | register char *cp; | |
81 | register struct block *b, *f; | |
82 | ||
83 | if (debug) | |
84 | printf("lookup(%s, %x, %d)\n", name, value, insert); | |
85 | ||
86 | n = 0; | |
87 | for (cp = name; *cp; ) | |
88 | n += *cp++; | |
89 | n %= HASHSIZE; | |
90 | ||
91 | for (b = hashtab[n]; b != NULL; b = b->b_next) { | |
92 | if (strcmp(name, b->b_name)) | |
93 | continue; | |
94 | if (insert) { | |
95 | if (b->b_type == NAME) { | |
96 | warn("%s redefined\n", name); | |
97 | f = b->b_args; | |
98 | b->b_args = value->b_args; | |
99 | value->b_args = f; | |
100 | } else if (value->b_type == VAR) | |
101 | fatal("%s redefined\n", name); | |
102 | while (f = value->b_next) { | |
103 | value->b_next = f->b_next; | |
104 | free(f->b_name); | |
105 | free(f); | |
106 | } | |
107 | free(value->b_name); | |
108 | free(value); | |
109 | } | |
110 | return(b); | |
111 | } | |
112 | ||
113 | if (!insert) | |
114 | fatal("%s not defined", name); | |
115 | ||
116 | value->b_next = hashtab[n]; | |
117 | hashtab[n] = value; | |
118 | return(value); | |
119 | } | |
120 | ||
121 | /* | |
122 | * Make a block for lists of variables, commands, etc. | |
123 | */ | |
124 | struct block * | |
125 | makeblock(type, name) | |
126 | int type; | |
127 | register char *name; | |
128 | { | |
129 | register char *cp; | |
130 | register struct block *bp; | |
131 | ||
132 | bp = ALLOC(block); | |
133 | if (bp == NULL) | |
134 | fatal("ran out of memory\n"); | |
135 | bp->b_type = type; | |
136 | bp->b_next = bp->b_args = NULL; | |
137 | if (type == NAME || type == VAR) { | |
138 | bp->b_name = cp = (char *) malloc(strlen(name) + 1); | |
139 | if (cp == NULL) | |
140 | fatal("ran out of memory\n"); | |
141 | while (*cp++ = *name++) | |
142 | ; | |
143 | } else | |
144 | bp->b_name = NULL; | |
145 | return(bp); | |
146 | } |