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