1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include "parser.h"
32 #include "trace.h"
33 #include "util.h"
34 #include "errlog.h"
35
36 #define TABLE_INITIAL 50
37 #define TABLE_INCREMENT 50
38
39 /*
40 * String processing
41 */
42
43 /*
44 * strnormalize -- combined tab-to-space and strtrim, plus removal
45 * of leading and trailing *$%$^@!!! semicolons.
46 * Not internationalized: TBD.
47 */
48 char *
strnormalize(char * str)49 strnormalize(char *str)
50 {
51 char *p;
52
53 if (str == NULL || *str == '\0')
54 return (str);
55 for (p = str; *p != '\0'; p++) {
56 if (isspace(*p)) {
57 *p = ' ';
58 }
59 }
60 p--;
61 while (p >= str && (isspace(*p) || *p == ';'))
62 *p-- = '\0';
63
64 /* ERA - remove leading spaces */
65 while (isspace(*str))
66 str++;
67
68 return (str);
69 }
70
71 char *
strtrim(char * str)72 strtrim(char *str)
73 {
74 char *p;
75
76 for (p = str; *p != '\0'; p++)
77 continue;
78 p--;
79 while (p >= str && isspace(*p))
80 *p-- = '\0';
81 return (str);
82 }
83
84 /*
85 * strlower -- make a string lower-case, destructively.
86 * Not internationalized: TBD.
87 */
88 char *
strlower(char * str)89 strlower(char *str)
90 {
91 char *p;
92
93 for (p = str; *p != '\0'; p++) {
94 *p = tolower(*p);
95 }
96 return (str);
97 }
98
99 /*
100 * strset -- update a dynamically-allocated string or die trying.
101 */
102 char *
strset(char * string,char * value)103 strset(char *string, char *value)
104 {
105 size_t vlen;
106
107 assert(value != NULL, "passed a NULL value to strset");
108 vlen = strlen(value);
109 if (string == NULL) {
110 /* It was never allocated, so allocate it. */
111 if ((string = malloc(vlen+1)) == NULL) {
112 errlog(FATAL, "malloc ran out of space");
113 }
114 } else if (strlen(string) < vlen) {
115
116 /* Reallocate bigger. */
117 if ((string = realloc(string, vlen+1)) == NULL) {
118 errlog(FATAL, "realloc ran out of space", "", 0);
119 }
120 }
121 (void) strcpy(string, value);
122 return (string);
123 }
124
125 /*
126 * in_string_set --see if string matches any member of a space-separated
127 * set of strings.
128 */
129 int
in_string_set(char * p,char * set)130 in_string_set(char *p, char *set)
131 {
132 char *q;
133 char save;
134
135 errlog(BEGIN, "in_string_set( p = \"%s\", set = \"%s\") {", p, set);
136
137 for (;;) {
138 set = skipb(set);
139 q = nextsep(set);
140 if (q == set) {
141 /* We've hit the end */
142 break;
143 }
144 save = *q;
145 *q = '\0';
146 if (strcmp(p, set) == 0) {
147 *q = save;
148 errlog(VERBOSE, "return YES");
149 errlog(END, "}");
150 return (YES);
151 }
152 *q = save;
153 set = q;
154 }
155 errlog(VERBOSE, "return NO");
156 errlog(END, "}");
157 return (NO);
158
159 }
160
161 char *
strend(char * p)162 strend(char *p)
163 {
164
165 while (*p)
166 p++;
167 return (p);
168 }
169
170 char *
lastspace(char * p)171 lastspace(char *p)
172 {
173 char *q;
174
175 q = strend(p);
176 q--;
177 while (q >= p && isspace(*q))
178 q--;
179 return (++q);
180 }
181
182 /*
183 * skipb -- skip over blanks (whitespace, actually), stopping
184 * on first non-blank.
185 */
186 char *
skipb(char * p)187 skipb(char *p)
188 {
189 while (*p && isspace(*p))
190 p++;
191 return (p);
192 }
193
194 /*
195 * nextb -- skip over non-blanks (including operators!)
196 * stopping on first blank.
197 */
198 char *
nextb(char * p)199 nextb(char *p)
200 {
201 while (*p && !isspace(*p))
202 p++;
203 return (p);
204 }
205
206 /*
207 * skipsep -- skip over separators (all but alnum and _),
208 * stopping on first non-separator.
209 */
210 char *
skipsep(char * p)211 skipsep(char *p)
212 {
213 errlog(BEGIN, "skipsep() {");
214 errlog(VERBOSE, "p (in) = %s", p);
215 while (*p && !(isalnum(*p) || *p == '_' || *p == '$'))
216 p++;
217 errlog(VERBOSE, "p (out) = %s", p);
218 errlog(END, "}");
219 return (p);
220 }
221
222 /*
223 * nextsep -- skip over non-separators (alnum and _, actually),
224 * stopping on first separator.
225 */
226 char *
nextsep(char * p)227 nextsep(char *p)
228 {
229 errlog(BEGIN, "nextsep() {");
230 errlog(VERBOSE, "p (in) = %s", p);
231 while (*p && isalnum(*p) || *p == '_' || *p == '$')
232 p++;
233 errlog(VERBOSE, "p (out) = %s", p);
234 errlog(END, "}");
235 return (p);
236 }
237
238 /*
239 * nextsep2 -- same as nextsep but also skips '.'
240 */
241 char *
nextsep2(char * p)242 nextsep2(char *p)
243 {
244 errlog(BEGIN, "nextsep() {");
245 errlog(VERBOSE, "p (in) = %s", p);
246 while (*p && isalnum(*p) || *p == '_' || *p == '$' || *p == '.')
247 p++;
248 errlog(VERBOSE, "p (out) = %s", p);
249 errlog(END, "}");
250 return (p);
251 }
252
253 /*
254 * objectname -- basename was taken (in man3c), so...
255 */
256 char *
objectname(char * name)257 objectname(char *name)
258 {
259 char *p;
260 static char basename[MAXLINE];
261
262 p = strrchr(name, '/');
263 while (p != NULL && *(p+1) == '\0') {
264 /* The / was at the end of the name. */
265 *p = '\0';
266 p = strrchr(name, '/');
267 }
268 (void) strlcpy(basename, p? p+1: name, MAXLINE);
269 if ((p = strstr(basename, ".c")) != NULL) {
270 *p = '\0';
271 }
272 return (strcat(basename, ".o"));
273 }
274
275 /*
276 * String tables
277 */
278
279 table_t *
create_string_table(int size)280 create_string_table(int size)
281 {
282 table_t *t;
283
284 errlog(BEGIN, "create_string_table() {");
285 if ((t = (table_t *)calloc((size_t)1,
286 (size_t)(sizeof (table_t) + (sizeof (char *)*size)))) == NULL) {
287 errlog(FATAL, "out of memory creating a string table");
288 }
289 t->nelem = size;
290 t->used = -1;
291 errlog(END, "}");
292 return (t);
293 }
294
295 table_t *
add_string_table(table_t * t,char * value)296 add_string_table(table_t *t, char *value)
297 {
298 table_t *t2;
299 int i;
300
301 if (t == NULL) {
302 errlog(FATAL, "programmer error: tried to add to "
303 "a NULL table");
304 }
305 if (in_string_table(t, value)) {
306 return (t);
307 }
308 t->used++;
309 if (t->used >= t->nelem) {
310 if ((t2 = realloc(t, (size_t)(sizeof (table_t)+(sizeof
311 (char *)*(t->nelem+TABLE_INCREMENT)))))
312 == NULL) {
313 errlog(FATAL, "out of memory extending string table");
314 }
315 t = t2;
316 t->nelem += TABLE_INCREMENT;
317 for (i = t->used; i < t->nelem; i++) {
318 t->elements[i] = NULL;
319 }
320 }
321
322 t->elements[t->used] = strset(t->elements[t->used], value);
323 return (t);
324 }
325
326 /*
327 * free_string_table -- really only mark it empty for reuse.
328 */
329 table_t *
free_string_table(table_t * t)330 free_string_table(table_t *t)
331 {
332 errlog(BEGIN, "free_string_table() {");
333 if (t != NULL) {
334 t->used = -1;
335 }
336 errlog(END, "}");
337 return (t);
338 }
339
340 char *
get_string_table(table_t * t,int index)341 get_string_table(table_t *t, int index)
342 {
343 if (t == NULL) {
344 return (NULL);
345 } else if (index > t->used) {
346 return (NULL);
347 } else {
348 return (t->elements[index]);
349 }
350 }
351
352 int
in_string_table(table_t * t,char * value)353 in_string_table(table_t *t, char *value)
354 {
355 int i;
356 size_t len = strlen(value);
357
358 if (t == NULL) {
359 return (0);
360 }
361 for (i = 0; i <= t->used; i++) {
362 if (strncmp(value, t->elements[i], len) == 0 &&
363 (t->elements[i][len] == '\0' ||
364 t->elements[i][len] == ','))
365 return (1);
366 }
367 return (0);
368 }
369
370 static int
compare(const void * p,const void * q)371 compare(const void *p, const void *q)
372 {
373 return (strcmp((char *)(*(char **)p), (char *)(*(char **)q)));
374 }
375
376 void
sort_string_table(table_t * t)377 sort_string_table(table_t *t)
378 {
379 if (t) {
380 qsort((char *)t->elements, (size_t)t->used,
381 sizeof (char *), compare);
382 }
383 }
384