1 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */ 2 /* 3 4 Copyright (c) 1993, 1994 X Consortium 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23 Except as contained in this notice, the name of the X Consortium shall not be 24 used in advertising or otherwise to promote the sale, use or other dealings 25 in this Software without prior written authorization from the X Consortium. 26 27 */ 28 29 #include "def.h" 30 char *hash_lookup( char *symbol, struct symhash *symbols ); 31 void hash_undefine( char *symbol, struct symhash *symbols ); 32 int gobble( register struct filepointer *filep, struct inclist *file, 33 struct inclist *file_red, struct symhash *symbols ); 34 int deftype ( register char *line, register struct filepointer *filep, 35 register struct inclist *file_red, register struct inclist *file, 36 int parse_it, struct symhash *symbols); 37 int zero_value(register char *exp, register struct filepointer *filep, 38 register struct inclist *file_red, register struct symhash *symbols); 39 40 extern char *directives[]; 41 extern struct symhash *maininclist; 42 43 int find_includes(filep, file, file_red, recursion, failOK, incCollection, symbols) 44 struct filepointer *filep; 45 struct inclist *file, *file_red; 46 int recursion; 47 boolean failOK; 48 struct IncludesCollection* incCollection; 49 struct symhash *symbols; 50 { 51 register char *line; 52 register int type; 53 boolean recfailOK; 54 55 while ((line = get_line(filep))) { 56 switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) { 57 case IF: 58 doif: 59 type = find_includes(filep, file, 60 file_red, recursion+1, failOK, incCollection, symbols); 61 while ((type == ELIF) || (type == ELIFFALSE) || 62 (type == ELIFGUESSFALSE)) 63 type = gobble(filep, file, file_red, symbols); 64 if (type == ELSE) 65 gobble(filep, file, file_red, symbols); 66 break; 67 case IFFALSE: 68 case IFGUESSFALSE: 69 doiffalse: 70 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) 71 recfailOK = TRUE; 72 else 73 recfailOK = failOK; 74 type = gobble(filep, file, file_red, symbols); 75 if (type == ELSE) 76 find_includes(filep, file, 77 file_red, recursion+1, recfailOK, incCollection, symbols); 78 else 79 if (type == ELIF) 80 goto doif; 81 else 82 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) 83 goto doiffalse; 84 break; 85 case IFDEF: 86 case IFNDEF: 87 if ((type == IFDEF && hash_lookup(line, symbols)) 88 || (type == IFNDEF && !hash_lookup(line, symbols))) { 89 debug(1,(type == IFNDEF ? 90 "line %d: %s !def'd in %s via %s%s\n" : "", 91 filep->f_line, line, 92 file->i_file, file_red->i_file, ": doit")); 93 type = find_includes(filep, file, 94 file_red, recursion+1, failOK, incCollection, symbols); 95 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) 96 type = gobble(filep, file, file_red, symbols); 97 if (type == ELSE) 98 gobble(filep, file, file_red, symbols); 99 } 100 else { 101 debug(1,(type == IFDEF ? 102 "line %d: %s !def'd in %s via %s%s\n" : "", 103 filep->f_line, line, 104 file->i_file, file_red->i_file, ": gobble")); 105 type = gobble(filep, file, file_red, symbols); 106 if (type == ELSE) 107 find_includes(filep, file, 108 file_red, recursion + 1, failOK, incCollection, symbols); 109 else if (type == ELIF) 110 goto doif; 111 else if (type == ELIFFALSE || type == ELIFGUESSFALSE) 112 goto doiffalse; 113 } 114 break; 115 case ELSE: 116 case ELIFFALSE: 117 case ELIFGUESSFALSE: 118 case ELIF: 119 if (!recursion) 120 gobble(filep, file, file_red, symbols); 121 case ENDIF: 122 if (recursion) 123 return(type); 124 case DEFINE: 125 define(line, &symbols); 126 break; 127 case UNDEF: 128 if (!*line) { 129 warning("%s, line %d: incomplete undef == \"%s\"\n", 130 file_red->i_file, filep->f_line, line); 131 break; 132 } 133 hash_undefine(line, symbols); 134 break; 135 case INCLUDE: 136 add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols); 137 break; 138 case INCLUDEDOT: 139 add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols); 140 break; 141 case ERROR: 142 warning("%s: %d: %s\n", file_red->i_file, 143 filep->f_line, line); 144 break; 145 146 case PRAGMA: 147 case IDENT: 148 case SCCS: 149 case EJECT: 150 break; 151 case -1: 152 warning("%s", file_red->i_file); 153 if (file_red != file) 154 warning1(" (reading %s)", file->i_file); 155 warning1(", line %d: unknown directive == \"%s\"\n", 156 filep->f_line, line); 157 break; 158 case -2: 159 warning("%s", file_red->i_file); 160 if (file_red != file) 161 warning1(" (reading %s)", file->i_file); 162 warning1(", line %d: incomplete include == \"%s\"\n", 163 filep->f_line, line); 164 break; 165 } 166 } 167 return(-1); 168 } 169 170 int gobble(filep, file, file_red, symbols) 171 register struct filepointer *filep; 172 struct inclist *file, *file_red; 173 struct symhash *symbols; 174 { 175 register char *line; 176 register int type; 177 178 while ((line = get_line(filep))) { 179 switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) { 180 case IF: 181 case IFFALSE: 182 case IFGUESSFALSE: 183 case IFDEF: 184 case IFNDEF: 185 type = gobble(filep, file, file_red, symbols); 186 while ((type == ELIF) || (type == ELIFFALSE) || 187 (type == ELIFGUESSFALSE)) 188 type = gobble(filep, file, file_red, symbols); 189 if (type == ELSE) 190 (void)gobble(filep, file, file_red, symbols); 191 break; 192 case ELSE: 193 case ENDIF: 194 debug(0,("%s, line %d: #%s\n", 195 file->i_file, filep->f_line, 196 directives[type])); 197 return(type); 198 case DEFINE: 199 case UNDEF: 200 case INCLUDE: 201 case INCLUDEDOT: 202 case PRAGMA: 203 case ERROR: 204 case IDENT: 205 case SCCS: 206 case EJECT: 207 break; 208 case ELIF: 209 case ELIFFALSE: 210 case ELIFGUESSFALSE: 211 return(type); 212 case -1: 213 warning("%s, line %d: unknown directive == \"%s\"\n", 214 file_red->i_file, filep->f_line, line); 215 break; 216 } 217 } 218 return(-1); 219 } 220 221 /* 222 * Decide what type of # directive this line is. 223 */ 224 int deftype (line, filep, file_red, file, parse_it, symbols) 225 register char *line; 226 register struct filepointer *filep; 227 register struct inclist *file_red, *file; 228 int parse_it; 229 struct symhash *symbols; 230 { 231 register char *p; 232 char *directive, savechar; 233 register int ret; 234 235 /* 236 * Parse the directive... 237 */ 238 directive=line+1; 239 while (*directive == ' ' || *directive == '\t') 240 directive++; 241 242 p = directive; 243 while (*p >= 'a' && *p <= 'z') 244 p++; 245 savechar = *p; 246 *p = '\0'; 247 ret = match(directive, directives); 248 *p = savechar; 249 250 /* If we don't recognize this compiler directive or we happen to just 251 * be gobbling up text while waiting for an #endif or #elif or #else 252 * in the case of an #elif we must check the zero_value and return an 253 * ELIF or an ELIFFALSE. 254 */ 255 256 if (ret == ELIF && !parse_it) 257 { 258 while (*p == ' ' || *p == '\t') 259 p++; 260 /* 261 * parse an expression. 262 */ 263 debug(0,("%s, line %d: #elif %s ", 264 file->i_file, filep->f_line, p)); 265 ret = zero_value(p, filep, file_red, symbols); 266 if (ret != IF) 267 { 268 debug(0,("false...\n")); 269 if (ret == IFFALSE) 270 return(ELIFFALSE); 271 else 272 return(ELIFGUESSFALSE); 273 } 274 else 275 { 276 debug(0,("true...\n")); 277 return(ELIF); 278 } 279 } 280 281 if (ret < 0 || ! parse_it) 282 return(ret); 283 284 /* 285 * now decide how to parse the directive, and do it. 286 */ 287 while (*p == ' ' || *p == '\t') 288 p++; 289 switch (ret) { 290 case IF: 291 /* 292 * parse an expression. 293 */ 294 ret = zero_value(p, filep, file_red, symbols); 295 debug(0,("%s, line %d: %s #if %s\n", 296 file->i_file, filep->f_line, ret?"false":"true", p)); 297 break; 298 case IFDEF: 299 case IFNDEF: 300 debug(0,("%s, line %d: #%s %s\n", 301 file->i_file, filep->f_line, directives[ret], p)); 302 case UNDEF: 303 /* 304 * separate the name of a single symbol. 305 */ 306 while (isalnum(*p) || *p == '_') 307 *line++ = *p++; 308 *line = '\0'; 309 break; 310 case INCLUDE: 311 debug(2,("%s, line %d: #include %s\n", 312 file->i_file, filep->f_line, p)); 313 314 /* Support ANSI macro substitution */ 315 { 316 char *sym = hash_lookup(p, symbols); 317 while (sym) 318 { 319 p = sym; 320 debug(3,("%s : #includes SYMBOL %s\n", 321 file->i_incstring, 322 sym)); 323 /* mark file as having included a 'soft include' */ 324 file->i_included_sym = TRUE; 325 sym = hash_lookup(p, symbols); 326 } 327 } 328 329 /* 330 * Separate the name of the include file. 331 */ 332 while (*p && *p != '"' && *p != '<') 333 p++; 334 if (! *p) 335 return(-2); 336 if (*p++ == '"') { 337 ret = INCLUDEDOT; 338 while (*p && *p != '"') 339 *line++ = *p++; 340 } else 341 while (*p && *p != '>') 342 *line++ = *p++; 343 *line = '\0'; 344 break; 345 case DEFINE: 346 /* 347 * copy the definition back to the beginning of the line. 348 */ 349 { 350 int len = strlen(line); 351 memmove (line, p, len); 352 line[len] = '\0'; 353 } 354 break; 355 case ELSE: 356 case ENDIF: 357 case ELIF: 358 case PRAGMA: 359 case ERROR: 360 case IDENT: 361 case SCCS: 362 case EJECT: 363 debug(0,("%s, line %d: #%s\n", 364 file->i_file, filep->f_line, directives[ret])); 365 /* 366 * nothing to do. 367 */ 368 break; 369 } 370 return(ret); 371 } 372 373 /* 374 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c 375 * function... It's safe, functions from cppsetup.c don't return here. 376 */ 377 struct symhash *global_symbols = NULL; 378 379 char * isdefined( symbol ) 380 register char *symbol; 381 { 382 return hash_lookup( symbol, global_symbols ); 383 } 384 385 /* 386 * Return type based on if the #if expression evaluates to 0 387 */ 388 int zero_value(exp, filep, file_red, symbols) 389 register char *exp; 390 register struct filepointer *filep; 391 register struct inclist *file_red; 392 register struct symhash *symbols; 393 { 394 global_symbols = symbols; /* HACK! see above */ 395 if (cppsetup(exp, filep, file_red)) 396 return(IFFALSE); 397 else 398 return(IF); 399 } 400 401 void define( def, symbols ) 402 char *def; 403 struct symhash **symbols; 404 { 405 char *val; 406 407 /* Separate symbol name and its value */ 408 val = def; 409 while (isalnum(*val) || *val == '_') 410 val++; 411 if (*val) 412 *val++ = '\0'; 413 while (*val == ' ' || *val == '\t') 414 val++; 415 416 if (!*val) 417 val = "1"; 418 hash_define( def, val, symbols ); 419 } 420 421 static int hash( str ) 422 register char *str; 423 { 424 /* Hash (Kernighan and Ritchie) */ 425 register unsigned int hashval = 0; 426 //char *s = str; 427 428 for ( ; *str; str++ ) 429 { 430 hashval = ( hashval * SYMHASHSEED ) + ( *str ); 431 } 432 433 //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) ); 434 return hashval & ( SYMHASHMEMBERS - 1 ); 435 } 436 437 struct symhash *hash_copy( symbols ) 438 struct symhash *symbols; 439 { 440 int i; 441 struct symhash *newsym; 442 if ( !symbols ) 443 return NULL; 444 445 newsym = (struct symhash *) malloc( sizeof( struct symhash ) ); 446 447 for ( i = 0; i < SYMHASHMEMBERS; ++i ) 448 { 449 if ( !symbols->s_pairs[ i ] ) 450 newsym->s_pairs[ i ] = NULL; 451 else 452 { 453 struct pair *it = symbols->s_pairs[ i ]; 454 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) ); 455 nw->p_name = it->p_name; 456 nw->p_value = it->p_value; 457 nw->p_next = NULL; 458 459 while ( it->p_next ) 460 { 461 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) ); 462 it = it->p_next; 463 nw = nw->p_next; 464 nw->p_name = it->p_name; 465 nw->p_value = it->p_value; 466 nw->p_next = NULL; 467 } 468 } 469 } 470 return newsym; 471 } 472 473 void hash_free( symbols ) 474 struct symhash *symbols; 475 { 476 int i; 477 478 if ( !symbols ) 479 return; 480 481 for ( i = 0; i < SYMHASHMEMBERS; ++i ) 482 { 483 struct pair *it = symbols->s_pairs[ i ]; 484 struct pair *next; 485 while ( it ) 486 { 487 next = it->p_next; 488 free( it ); 489 it = next; 490 } 491 } 492 free( symbols->s_pairs ); 493 } 494 495 void hash_define( name, val, symbols ) 496 char *name, *val; 497 struct symhash **symbols; 498 { 499 int hashval; 500 struct pair *it; 501 502 if ( !symbols ) 503 return; 504 505 /* Make space if it's needed */ 506 if ( *symbols == NULL ) 507 { 508 int i; 509 510 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) ); 511 if ( *symbols == NULL ) 512 fatalerr( "malloc()/realloc() failure in insert_defn()\n" ); 513 514 for ( i = 0; i < SYMHASHMEMBERS; ++i ) 515 (*symbols)->s_pairs[i] = NULL; 516 } 517 518 hashval = hash( name ); 519 it = (*symbols)->s_pairs[ hashval ]; 520 521 /* Replace/insert the symbol */ 522 if ( it == NULL ) 523 { 524 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) ); 525 it->p_name = copy( name ); 526 it->p_value = copy( val ); 527 it->p_next = NULL; 528 } 529 else if ( strcmp( it->p_name, name ) == 0 ) 530 { 531 it->p_value = copy( val ); 532 } 533 else 534 { 535 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) ) 536 { 537 it = it->p_next; 538 } 539 if ( it->p_next ) 540 it->p_next->p_name = copy( name ); 541 else 542 { 543 it->p_next = (struct pair*) malloc( sizeof( struct pair ) ); 544 it->p_next->p_name = copy( name ); 545 it->p_next->p_value = copy( val ); 546 it->p_next->p_next = NULL; 547 } 548 } 549 } 550 551 char *hash_lookup( symbol, symbols ) 552 char *symbol; 553 struct symhash *symbols; 554 { 555 struct pair *it; 556 557 if ( !symbols ) 558 return NULL; 559 560 it = symbols->s_pairs[ hash( symbol ) ]; 561 562 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) ) 563 { 564 it = it->p_next; 565 } 566 if ( it ) 567 return it->p_value; 568 569 return NULL; 570 } 571 572 void hash_undefine( symbol, symbols ) 573 char *symbol; 574 struct symhash *symbols; 575 { 576 int hashval; 577 struct pair *it; 578 579 if ( !symbols ) 580 return; 581 582 hashval = hash( symbol ); 583 it = symbols->s_pairs[ hashval ]; 584 585 /* Replace/insert the symbol */ 586 if ( it == NULL ) 587 return; 588 else if ( strcmp( it->p_name, symbol ) == 0 ) 589 { 590 if ( it->p_next ) 591 { 592 struct pair *tmp; 593 it->p_name = it->p_next->p_name; 594 it->p_value = it->p_next->p_value; 595 tmp = it->p_next->p_next; 596 free( it->p_next ); 597 it->p_next = tmp; 598 } 599 else 600 { 601 free( it ); 602 symbols->s_pairs[ hashval ] = NULL; 603 } 604 } 605 else 606 { 607 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) ) 608 { 609 it = it->p_next; 610 } 611 if ( it->p_next ) 612 { 613 struct pair *tmp = it->p_next; 614 it->p_next = it->p_next->p_next; 615 free( tmp ); 616 } 617 } 618 } 619