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