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