1753d2d2eSraf /*
2753d2d2eSraf * CDDL HEADER START
3753d2d2eSraf *
4753d2d2eSraf * The contents of this file are subject to the terms of the
5753d2d2eSraf * Common Development and Distribution License, Version 1.0 only
6753d2d2eSraf * (the "License"). You may not use this file except in compliance
7753d2d2eSraf * with the License.
8753d2d2eSraf *
9753d2d2eSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10753d2d2eSraf * or http://www.opensolaris.org/os/licensing.
11753d2d2eSraf * See the License for the specific language governing permissions
12753d2d2eSraf * and limitations under the License.
13753d2d2eSraf *
14753d2d2eSraf * When distributing Covered Code, include this CDDL HEADER in each
15753d2d2eSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16753d2d2eSraf * If applicable, add the following below this CDDL HEADER, with the
17753d2d2eSraf * fields enclosed by brackets "[]" replaced with your own identifying
18753d2d2eSraf * information: Portions Copyright [yyyy] [name of copyright owner]
19753d2d2eSraf *
20753d2d2eSraf * CDDL HEADER END
21753d2d2eSraf */
22753d2d2eSraf /*
23753d2d2eSraf * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
24753d2d2eSraf * Use is subject to license terms.
25753d2d2eSraf */
26753d2d2eSraf
27753d2d2eSraf #include <stdio.h>
28753d2d2eSraf #include <string.h>
29753d2d2eSraf #include <ctype.h>
30753d2d2eSraf #include <stdlib.h>
31753d2d2eSraf #include "parser.h"
32753d2d2eSraf #include "trace.h"
33753d2d2eSraf #include "util.h"
34753d2d2eSraf #include "errlog.h"
35753d2d2eSraf
36753d2d2eSraf #define TABLE_INITIAL 50
37753d2d2eSraf #define TABLE_INCREMENT 50
38753d2d2eSraf
39753d2d2eSraf /*
40753d2d2eSraf * String processing
41753d2d2eSraf */
42753d2d2eSraf
43753d2d2eSraf /*
44753d2d2eSraf * strnormalize -- combined tab-to-space and strtrim, plus removal
45753d2d2eSraf * of leading and trailing *$%$^@!!! semicolons.
46753d2d2eSraf * Not internationalized: TBD.
47753d2d2eSraf */
48753d2d2eSraf char *
strnormalize(char * str)49753d2d2eSraf strnormalize(char *str)
50753d2d2eSraf {
51753d2d2eSraf char *p;
52753d2d2eSraf
53*07c94cbfSToomas Soome if (str == NULL || *str == '\0')
54753d2d2eSraf return (str);
55*07c94cbfSToomas Soome for (p = str; *p != '\0'; p++) {
56753d2d2eSraf if (isspace(*p)) {
57753d2d2eSraf *p = ' ';
58753d2d2eSraf }
59753d2d2eSraf }
60753d2d2eSraf p--;
61753d2d2eSraf while (p >= str && (isspace(*p) || *p == ';'))
62*07c94cbfSToomas Soome *p-- = '\0';
63753d2d2eSraf
64753d2d2eSraf /* ERA - remove leading spaces */
65753d2d2eSraf while (isspace(*str))
66753d2d2eSraf str++;
67753d2d2eSraf
68753d2d2eSraf return (str);
69753d2d2eSraf }
70753d2d2eSraf
71753d2d2eSraf char *
strtrim(char * str)72753d2d2eSraf strtrim(char *str)
73753d2d2eSraf {
74753d2d2eSraf char *p;
75753d2d2eSraf
76*07c94cbfSToomas Soome for (p = str; *p != '\0'; p++)
77753d2d2eSraf continue;
78753d2d2eSraf p--;
79753d2d2eSraf while (p >= str && isspace(*p))
80*07c94cbfSToomas Soome *p-- = '\0';
81753d2d2eSraf return (str);
82753d2d2eSraf }
83753d2d2eSraf
84753d2d2eSraf /*
85753d2d2eSraf * strlower -- make a string lower-case, destructively.
86753d2d2eSraf * Not internationalized: TBD.
87753d2d2eSraf */
88753d2d2eSraf char *
strlower(char * str)89753d2d2eSraf strlower(char *str)
90753d2d2eSraf {
91753d2d2eSraf char *p;
92753d2d2eSraf
93*07c94cbfSToomas Soome for (p = str; *p != '\0'; p++) {
94753d2d2eSraf *p = tolower(*p);
95753d2d2eSraf }
96753d2d2eSraf return (str);
97753d2d2eSraf }
98753d2d2eSraf
99753d2d2eSraf /*
100753d2d2eSraf * strset -- update a dynamically-allocated string or die trying.
101753d2d2eSraf */
102753d2d2eSraf char *
strset(char * string,char * value)103753d2d2eSraf strset(char *string, char *value)
104753d2d2eSraf {
105753d2d2eSraf size_t vlen;
106753d2d2eSraf
107753d2d2eSraf assert(value != NULL, "passed a NULL value to strset");
108753d2d2eSraf vlen = strlen(value);
109753d2d2eSraf if (string == NULL) {
110753d2d2eSraf /* It was never allocated, so allocate it. */
111753d2d2eSraf if ((string = malloc(vlen+1)) == NULL) {
112753d2d2eSraf errlog(FATAL, "malloc ran out of space");
113753d2d2eSraf }
114753d2d2eSraf } else if (strlen(string) < vlen) {
115753d2d2eSraf
116753d2d2eSraf /* Reallocate bigger. */
117753d2d2eSraf if ((string = realloc(string, vlen+1)) == NULL) {
118753d2d2eSraf errlog(FATAL, "realloc ran out of space", "", 0);
119753d2d2eSraf }
120753d2d2eSraf }
121753d2d2eSraf (void) strcpy(string, value);
122753d2d2eSraf return (string);
123753d2d2eSraf }
124753d2d2eSraf
125753d2d2eSraf /*
126753d2d2eSraf * in_string_set --see if string matches any member of a space-separated
127753d2d2eSraf * set of strings.
128753d2d2eSraf */
129753d2d2eSraf int
in_string_set(char * p,char * set)130753d2d2eSraf in_string_set(char *p, char *set)
131753d2d2eSraf {
132753d2d2eSraf char *q;
133753d2d2eSraf char save;
134753d2d2eSraf
135753d2d2eSraf errlog(BEGIN, "in_string_set( p = \"%s\", set = \"%s\") {", p, set);
136753d2d2eSraf
137753d2d2eSraf for (;;) {
138753d2d2eSraf set = skipb(set);
139753d2d2eSraf q = nextsep(set);
140753d2d2eSraf if (q == set) {
141753d2d2eSraf /* We've hit the end */
142753d2d2eSraf break;
143753d2d2eSraf }
144753d2d2eSraf save = *q;
145*07c94cbfSToomas Soome *q = '\0';
146753d2d2eSraf if (strcmp(p, set) == 0) {
147753d2d2eSraf *q = save;
148753d2d2eSraf errlog(VERBOSE, "return YES");
149753d2d2eSraf errlog(END, "}");
150753d2d2eSraf return (YES);
151753d2d2eSraf }
152753d2d2eSraf *q = save;
153753d2d2eSraf set = q;
154753d2d2eSraf }
155753d2d2eSraf errlog(VERBOSE, "return NO");
156753d2d2eSraf errlog(END, "}");
157753d2d2eSraf return (NO);
158753d2d2eSraf
159753d2d2eSraf }
160753d2d2eSraf
161753d2d2eSraf char *
strend(char * p)162753d2d2eSraf strend(char *p)
163753d2d2eSraf {
164753d2d2eSraf
165753d2d2eSraf while (*p)
166753d2d2eSraf p++;
167753d2d2eSraf return (p);
168753d2d2eSraf }
169753d2d2eSraf
170753d2d2eSraf char *
lastspace(char * p)171753d2d2eSraf lastspace(char *p)
172753d2d2eSraf {
173753d2d2eSraf char *q;
174753d2d2eSraf
175753d2d2eSraf q = strend(p);
176753d2d2eSraf q--;
177753d2d2eSraf while (q >= p && isspace(*q))
178753d2d2eSraf q--;
179753d2d2eSraf return (++q);
180753d2d2eSraf }
181753d2d2eSraf
182753d2d2eSraf /*
183753d2d2eSraf * skipb -- skip over blanks (whitespace, actually), stopping
184753d2d2eSraf * on first non-blank.
185753d2d2eSraf */
186753d2d2eSraf char *
skipb(char * p)187753d2d2eSraf skipb(char *p)
188753d2d2eSraf {
189753d2d2eSraf while (*p && isspace(*p))
190753d2d2eSraf p++;
191753d2d2eSraf return (p);
192753d2d2eSraf }
193753d2d2eSraf
194753d2d2eSraf /*
195753d2d2eSraf * nextb -- skip over non-blanks (including operators!)
196753d2d2eSraf * stopping on first blank.
197753d2d2eSraf */
198753d2d2eSraf char *
nextb(char * p)199753d2d2eSraf nextb(char *p)
200753d2d2eSraf {
201753d2d2eSraf while (*p && !isspace(*p))
202753d2d2eSraf p++;
203753d2d2eSraf return (p);
204753d2d2eSraf }
205753d2d2eSraf
206753d2d2eSraf /*
207753d2d2eSraf * skipsep -- skip over separators (all but alnum and _),
208753d2d2eSraf * stopping on first non-separator.
209753d2d2eSraf */
210753d2d2eSraf char *
skipsep(char * p)211753d2d2eSraf skipsep(char *p)
212753d2d2eSraf {
213753d2d2eSraf errlog(BEGIN, "skipsep() {");
214753d2d2eSraf errlog(VERBOSE, "p (in) = %s", p);
215753d2d2eSraf while (*p && !(isalnum(*p) || *p == '_' || *p == '$'))
216753d2d2eSraf p++;
217753d2d2eSraf errlog(VERBOSE, "p (out) = %s", p);
218753d2d2eSraf errlog(END, "}");
219753d2d2eSraf return (p);
220753d2d2eSraf }
221753d2d2eSraf
222753d2d2eSraf /*
223753d2d2eSraf * nextsep -- skip over non-separators (alnum and _, actually),
224753d2d2eSraf * stopping on first separator.
225753d2d2eSraf */
226753d2d2eSraf char *
nextsep(char * p)227753d2d2eSraf nextsep(char *p)
228753d2d2eSraf {
229753d2d2eSraf errlog(BEGIN, "nextsep() {");
230753d2d2eSraf errlog(VERBOSE, "p (in) = %s", p);
231753d2d2eSraf while (*p && isalnum(*p) || *p == '_' || *p == '$')
232753d2d2eSraf p++;
233753d2d2eSraf errlog(VERBOSE, "p (out) = %s", p);
234753d2d2eSraf errlog(END, "}");
235753d2d2eSraf return (p);
236753d2d2eSraf }
237753d2d2eSraf
238753d2d2eSraf /*
239753d2d2eSraf * nextsep2 -- same as nextsep but also skips '.'
240753d2d2eSraf */
241753d2d2eSraf char *
nextsep2(char * p)242753d2d2eSraf nextsep2(char *p)
243753d2d2eSraf {
244753d2d2eSraf errlog(BEGIN, "nextsep() {");
245753d2d2eSraf errlog(VERBOSE, "p (in) = %s", p);
246753d2d2eSraf while (*p && isalnum(*p) || *p == '_' || *p == '$' || *p == '.')
247753d2d2eSraf p++;
248753d2d2eSraf errlog(VERBOSE, "p (out) = %s", p);
249753d2d2eSraf errlog(END, "}");
250753d2d2eSraf return (p);
251753d2d2eSraf }
252753d2d2eSraf
253753d2d2eSraf /*
254753d2d2eSraf * objectname -- basename was taken (in man3c), so...
255753d2d2eSraf */
256753d2d2eSraf char *
objectname(char * name)257753d2d2eSraf objectname(char *name)
258753d2d2eSraf {
259753d2d2eSraf char *p;
260753d2d2eSraf static char basename[MAXLINE];
261753d2d2eSraf
262753d2d2eSraf p = strrchr(name, '/');
263*07c94cbfSToomas Soome while (p != NULL && *(p+1) == '\0') {
264753d2d2eSraf /* The / was at the end of the name. */
265*07c94cbfSToomas Soome *p = '\0';
266753d2d2eSraf p = strrchr(name, '/');
267753d2d2eSraf }
268753d2d2eSraf (void) strlcpy(basename, p? p+1: name, MAXLINE);
269753d2d2eSraf if ((p = strstr(basename, ".c")) != NULL) {
270*07c94cbfSToomas Soome *p = '\0';
271753d2d2eSraf }
272753d2d2eSraf return (strcat(basename, ".o"));
273753d2d2eSraf }
274753d2d2eSraf
275753d2d2eSraf /*
276753d2d2eSraf * String tables
277753d2d2eSraf */
278753d2d2eSraf
279753d2d2eSraf table_t *
create_string_table(int size)280753d2d2eSraf create_string_table(int size)
281753d2d2eSraf {
282753d2d2eSraf table_t *t;
283753d2d2eSraf
284753d2d2eSraf errlog(BEGIN, "create_string_table() {");
285753d2d2eSraf if ((t = (table_t *)calloc((size_t)1,
286753d2d2eSraf (size_t)(sizeof (table_t) + (sizeof (char *)*size)))) == NULL) {
287753d2d2eSraf errlog(FATAL, "out of memory creating a string table");
288753d2d2eSraf }
289753d2d2eSraf t->nelem = size;
290753d2d2eSraf t->used = -1;
291753d2d2eSraf errlog(END, "}");
292753d2d2eSraf return (t);
293753d2d2eSraf }
294753d2d2eSraf
295753d2d2eSraf table_t *
add_string_table(table_t * t,char * value)296753d2d2eSraf add_string_table(table_t *t, char *value)
297753d2d2eSraf {
298753d2d2eSraf table_t *t2;
299753d2d2eSraf int i;
300753d2d2eSraf
301753d2d2eSraf if (t == NULL) {
302753d2d2eSraf errlog(FATAL, "programmer error: tried to add to "
303753d2d2eSraf "a NULL table");
304753d2d2eSraf }
305753d2d2eSraf if (in_string_table(t, value)) {
306753d2d2eSraf return (t);
307753d2d2eSraf }
308753d2d2eSraf t->used++;
309753d2d2eSraf if (t->used >= t->nelem) {
310753d2d2eSraf if ((t2 = realloc(t, (size_t)(sizeof (table_t)+(sizeof
311753d2d2eSraf (char *)*(t->nelem+TABLE_INCREMENT)))))
312753d2d2eSraf == NULL) {
313753d2d2eSraf errlog(FATAL, "out of memory extending string table");
314753d2d2eSraf }
315753d2d2eSraf t = t2;
316753d2d2eSraf t->nelem += TABLE_INCREMENT;
317753d2d2eSraf for (i = t->used; i < t->nelem; i++) {
318753d2d2eSraf t->elements[i] = NULL;
319753d2d2eSraf }
320753d2d2eSraf }
321753d2d2eSraf
322753d2d2eSraf t->elements[t->used] = strset(t->elements[t->used], value);
323753d2d2eSraf return (t);
324753d2d2eSraf }
325753d2d2eSraf
326753d2d2eSraf /*
327753d2d2eSraf * free_string_table -- really only mark it empty for reuse.
328753d2d2eSraf */
329753d2d2eSraf table_t *
free_string_table(table_t * t)330753d2d2eSraf free_string_table(table_t *t)
331753d2d2eSraf {
332753d2d2eSraf errlog(BEGIN, "free_string_table() {");
333753d2d2eSraf if (t != NULL) {
334753d2d2eSraf t->used = -1;
335753d2d2eSraf }
336753d2d2eSraf errlog(END, "}");
337753d2d2eSraf return (t);
338753d2d2eSraf }
339753d2d2eSraf
340753d2d2eSraf char *
get_string_table(table_t * t,int index)341753d2d2eSraf get_string_table(table_t *t, int index)
342753d2d2eSraf {
343753d2d2eSraf if (t == NULL) {
344753d2d2eSraf return (NULL);
345753d2d2eSraf } else if (index > t->used) {
346753d2d2eSraf return (NULL);
347753d2d2eSraf } else {
348753d2d2eSraf return (t->elements[index]);
349753d2d2eSraf }
350753d2d2eSraf }
351753d2d2eSraf
352753d2d2eSraf int
in_string_table(table_t * t,char * value)353753d2d2eSraf in_string_table(table_t *t, char *value)
354753d2d2eSraf {
355753d2d2eSraf int i;
356753d2d2eSraf size_t len = strlen(value);
357753d2d2eSraf
358753d2d2eSraf if (t == NULL) {
359753d2d2eSraf return (0);
360753d2d2eSraf }
361753d2d2eSraf for (i = 0; i <= t->used; i++) {
362753d2d2eSraf if (strncmp(value, t->elements[i], len) == 0 &&
363*07c94cbfSToomas Soome (t->elements[i][len] == '\0' ||
364753d2d2eSraf t->elements[i][len] == ','))
365753d2d2eSraf return (1);
366753d2d2eSraf }
367753d2d2eSraf return (0);
368753d2d2eSraf }
369753d2d2eSraf
370753d2d2eSraf static int
compare(const void * p,const void * q)371753d2d2eSraf compare(const void *p, const void *q)
372753d2d2eSraf {
373753d2d2eSraf return (strcmp((char *)(*(char **)p), (char *)(*(char **)q)));
374753d2d2eSraf }
375753d2d2eSraf
376753d2d2eSraf void
sort_string_table(table_t * t)377753d2d2eSraf sort_string_table(table_t *t)
378753d2d2eSraf {
379753d2d2eSraf if (t) {
380753d2d2eSraf qsort((char *)t->elements, (size_t)t->used,
381753d2d2eSraf sizeof (char *), compare);
382753d2d2eSraf }
383753d2d2eSraf }
384