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 * 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 * 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 * 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 * 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 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 * 162 strend(char *p) 163 { 164 165 while (*p) 166 p++; 167 return (p); 168 } 169 170 char * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 371 compare(const void *p, const void *q) 372 { 373 return (strcmp((char *)(*(char **)p), (char *)(*(char **)q))); 374 } 375 376 void 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