10eb10989Smrg/* 20eb10989Smrg 30eb10989SmrgCopyright (c) 1993, 1994, 1998 The Open Group 40eb10989Smrg 50eb10989SmrgPermission to use, copy, modify, distribute, and sell this software and its 60eb10989Smrgdocumentation for any purpose is hereby granted without fee, provided that 70eb10989Smrgthe above copyright notice appear in all copies and that both that 80eb10989Smrgcopyright notice and this permission notice appear in supporting 90eb10989Smrgdocumentation. 100eb10989Smrg 110eb10989SmrgThe above copyright notice and this permission notice shall be included in 120eb10989Smrgall copies or substantial portions of the Software. 130eb10989Smrg 140eb10989SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 150eb10989SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 160eb10989SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 170eb10989SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 180eb10989SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 190eb10989SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 200eb10989Smrg 210eb10989SmrgExcept as contained in this notice, the name of The Open Group shall not be 220eb10989Smrgused in advertising or otherwise to promote the sale, use or other dealings 230eb10989Smrgin this Software without prior written authorization from The Open Group. 240eb10989Smrg 250eb10989Smrg*/ 260eb10989Smrg 270eb10989Smrg#include "def.h" 280eb10989Smrg 29fadff096Smrgstatic int deftype(char *line, struct filepointer *filep, 30fadff096Smrg struct inclist *file_red, struct inclist *file, 31fadff096Smrg int parse_it); 320eb10989Smrgstatic int zero_value(char *filename, char *exp, struct filepointer *filep, 33fadff096Smrg struct inclist *file_red); 34fadff096Smrgstatic struct symtab **slookup(const char *symbol, struct inclist *file); 35fadff096Smrgstatic boolean merge2defines(struct inclist *file1, struct inclist *file2); 36fadff096Smrg 37fadff096Smrgstatic const char *const directives[] = { 38fadff096Smrg "if", 39fadff096Smrg "ifdef", 40fadff096Smrg "ifndef", 41fadff096Smrg "else", 42fadff096Smrg "endif", 43fadff096Smrg "define", 44fadff096Smrg "undef", 45fadff096Smrg "include", 46fadff096Smrg "line", 47fadff096Smrg "pragma", 48fadff096Smrg "error", 49fadff096Smrg "ident", 50fadff096Smrg "sccs", 51fadff096Smrg "elif", 52fadff096Smrg "eject", 53fadff096Smrg "warning", 54fadff096Smrg "include_next", 55fadff096Smrg NULL 56fadff096Smrg}; 570eb10989Smrg 580eb10989Smrgstatic int 590eb10989Smrggobble(struct filepointer *filep, struct inclist *file, 600eb10989Smrg struct inclist *file_red) 610eb10989Smrg{ 62fadff096Smrg char *line; 63fadff096Smrg 64fadff096Smrg while ((line = getnextline(filep))) { 65fadff096Smrg int type = deftype(line, filep, file_red, file, FALSE); 66fadff096Smrg 67fadff096Smrg switch (type) { 68fadff096Smrg case IF: 69fadff096Smrg case IFFALSE: 70fadff096Smrg case IFGUESSFALSE: 71fadff096Smrg case IFDEF: 72fadff096Smrg case IFNDEF: 73fadff096Smrg type = gobble(filep, file, file_red); 74fadff096Smrg while ((type == ELIF) || (type == ELIFFALSE) || 75fadff096Smrg (type == ELIFGUESSFALSE)) 76fadff096Smrg type = gobble(filep, file, file_red); 77fadff096Smrg if (type == ELSE) 78fadff096Smrg (void) gobble(filep, file, file_red); 79fadff096Smrg break; 80fadff096Smrg case ELSE: 81fadff096Smrg case ENDIF: 82fadff096Smrg debug(0, ("%s, line %d: #%s\n", 83fadff096Smrg file->i_file, filep->f_line, directives[type])); 84fadff096Smrg return (type); 85fadff096Smrg case DEFINE: 86fadff096Smrg case UNDEF: 87fadff096Smrg case INCLUDE: 88fadff096Smrg case INCLUDEDOT: 89fadff096Smrg case PRAGMA: 90fadff096Smrg case ERROR: 91fadff096Smrg case IDENT: 92fadff096Smrg case SCCS: 93fadff096Smrg case EJECT: 94fadff096Smrg case WARNING: 95fadff096Smrg case INCLUDENEXT: 96fadff096Smrg case INCLUDENEXTDOT: 97fadff096Smrg break; 98fadff096Smrg case ELIF: 99fadff096Smrg case ELIFFALSE: 100fadff096Smrg case ELIFGUESSFALSE: 101fadff096Smrg return (type); 102fadff096Smrg case -1: 103fadff096Smrg warning("%s", file_red->i_file); 104fadff096Smrg if (file_red != file) 105fadff096Smrg warning1(" (reading %s)", file->i_file); 106fadff096Smrg warning1(", line %ld: unknown directive == \"%s\"\n", 107fadff096Smrg filep->f_line, line); 108fadff096Smrg break; 109fadff096Smrg } 110fadff096Smrg } 111fadff096Smrg return (-1); 1120eb10989Smrg} 1130eb10989Smrg 1140eb10989Smrg/* 1150eb10989Smrg * Decide what type of # directive this line is. 1160eb10989Smrg */ 117d43532a6Smrgstatic int 118fadff096Smrgdeftype(char *line, struct filepointer *filep, 119fadff096Smrg struct inclist *file_red, struct inclist *file, int parse_it) 1200eb10989Smrg{ 121fadff096Smrg char *p; 122fadff096Smrg char *directive, savechar, *q; 123fadff096Smrg int ret; 124fadff096Smrg 125fadff096Smrg /* 126fadff096Smrg * Parse the directive... 127fadff096Smrg */ 128fadff096Smrg directive = line + 1; 129fadff096Smrg while (*directive == ' ' || *directive == '\t') 130fadff096Smrg directive++; 131fadff096Smrg 132fadff096Smrg p = directive; 133fadff096Smrg while ((*p == '_') || (*p >= 'a' && *p <= 'z')) 134fadff096Smrg p++; 135fadff096Smrg savechar = *p; 136fadff096Smrg *p = '\0'; 137fadff096Smrg ret = match(directive, directives); 138fadff096Smrg *p = savechar; 139fadff096Smrg 140fadff096Smrg /* If we don't recognize this compiler directive or we happen to just 141fadff096Smrg * be gobbling up text while waiting for an #endif or #elif or #else 142fadff096Smrg * in the case of an #elif we must check the zero_value and return an 143fadff096Smrg * ELIF or an ELIFFALSE. 144fadff096Smrg */ 145fadff096Smrg 146fadff096Smrg if (ret == ELIF && !parse_it) { 147fadff096Smrg while (*p == ' ' || *p == '\t') 148fadff096Smrg p++; 149fadff096Smrg /* 150fadff096Smrg * parse an expression. 151fadff096Smrg */ 152fadff096Smrg debug(0, ("%s, line %d: #elif %s ", file->i_file, filep->f_line, p)); 153fadff096Smrg ret = zero_value(file->i_file, p, filep, file_red); 154fadff096Smrg if (ret != IF) { 155fadff096Smrg debug(0, ("false...\n")); 156fadff096Smrg if (ret == IFFALSE) 157fadff096Smrg return (ELIFFALSE); 158fadff096Smrg else 159fadff096Smrg return (ELIFGUESSFALSE); 160fadff096Smrg } 161fadff096Smrg else { 162fadff096Smrg debug(0, ("true...\n")); 163fadff096Smrg return (ELIF); 164fadff096Smrg } 165fadff096Smrg } 166fadff096Smrg 167fadff096Smrg if (ret < 0 || !parse_it) 168fadff096Smrg return (ret); 169fadff096Smrg 170fadff096Smrg /* 171fadff096Smrg * now decide how to parse the directive, and do it. 172fadff096Smrg */ 173fadff096Smrg while (*p == ' ' || *p == '\t') 174fadff096Smrg p++; 175fadff096Smrg q = p + strlen(p); 176fadff096Smrg do { 177fadff096Smrg q--; 178fadff096Smrg } while (*q == ' ' || *q == '\t'); 179fadff096Smrg q[1] = '\0'; 180fadff096Smrg switch (ret) { 181fadff096Smrg case IF: 182fadff096Smrg /* 183fadff096Smrg * parse an expression. 184fadff096Smrg */ 185fadff096Smrg ret = zero_value(file->i_file, p, filep, file_red); 186fadff096Smrg debug(0, ("%s, line %d: %s #if %s\n", 187fadff096Smrg file->i_file, filep->f_line, ret ? "false" : "true", p)); 188fadff096Smrg break; 189fadff096Smrg case IFDEF: 190fadff096Smrg case IFNDEF: 191fadff096Smrg debug(0, ("%s, line %d: #%s %s\n", 192fadff096Smrg file->i_file, filep->f_line, directives[ret], p)); 193fadff096Smrg case UNDEF: 194fadff096Smrg /* 195fadff096Smrg * separate the name of a single symbol. 196fadff096Smrg */ 197fadff096Smrg while (isalnum(*p) || *p == '_') 198fadff096Smrg *line++ = *p++; 199fadff096Smrg *line = '\0'; 200fadff096Smrg break; 201fadff096Smrg case INCLUDE: 202fadff096Smrg case INCLUDENEXT: 203fadff096Smrg debug(2, ("%s, line %d: #include%s %s\n", 204fadff096Smrg file->i_file, filep->f_line, 205fadff096Smrg (ret == INCLUDE) ? "" : "_next", p)); 206fadff096Smrg 207fadff096Smrg /* Support ANSI macro substitution */ 208fadff096Smrg while (1) { 209fadff096Smrg struct symtab **sym; 210fadff096Smrg 211fadff096Smrg if (!*p || *p == '"' || *p == '<') 212fadff096Smrg break; 213fadff096Smrg 214fadff096Smrg sym = isdefined(p, file_red, NULL); 215fadff096Smrg if (!sym) 216fadff096Smrg break; 217fadff096Smrg 218fadff096Smrg p = (*sym)->s_value; 219fadff096Smrg debug(3, ("%s : #includes SYMBOL %s = %s\n", 220fadff096Smrg file->i_incstring, (*sym)->s_name, (*sym)->s_value)); 221fadff096Smrg /* mark file as having included a 'soft include' */ 222fadff096Smrg file->i_flags |= INCLUDED_SYM; 223fadff096Smrg } 224fadff096Smrg 225fadff096Smrg /* 226fadff096Smrg * Separate the name of the include file. 227fadff096Smrg */ 228fadff096Smrg while (*p && *p != '"' && *p != '<') 229fadff096Smrg p++; 230fadff096Smrg if (!*p) 231fadff096Smrg return (-2); 232fadff096Smrg if (*p++ == '"') { 233fadff096Smrg if (ret == INCLUDE) 234fadff096Smrg ret = INCLUDEDOT; 235fadff096Smrg else 236fadff096Smrg ret = INCLUDENEXTDOT; 237fadff096Smrg while (*p && *p != '"') 238fadff096Smrg *line++ = *p++; 239fadff096Smrg } 240fadff096Smrg else 241fadff096Smrg while (*p && *p != '>') 242fadff096Smrg *line++ = *p++; 243fadff096Smrg *line = '\0'; 244fadff096Smrg break; 245fadff096Smrg case DEFINE: 246fadff096Smrg /* 247fadff096Smrg * copy the definition back to the beginning of the line. 248fadff096Smrg */ 249fadff096Smrg memmove(line, p, strlen(p) + 1); 250fadff096Smrg break; 251fadff096Smrg case ELSE: 252fadff096Smrg case ENDIF: 253fadff096Smrg case ELIF: 254fadff096Smrg case PRAGMA: 255fadff096Smrg case ERROR: 256fadff096Smrg case IDENT: 257fadff096Smrg case SCCS: 258fadff096Smrg case EJECT: 259fadff096Smrg case WARNING: 260fadff096Smrg debug(0, ("%s, line %d: #%s\n", 261fadff096Smrg file->i_file, filep->f_line, directives[ret])); 262fadff096Smrg /* 263fadff096Smrg * nothing to do. 264fadff096Smrg */ 265fadff096Smrg break; 266fadff096Smrg } 267fadff096Smrg return (ret); 2680eb10989Smrg} 2690eb10989Smrg 270fadff096Smrgstatic struct symtab ** 271d43532a6Smrgfdefined(const char *symbol, struct inclist *file, struct inclist **srcfile) 2720eb10989Smrg{ 273fadff096Smrg struct symtab **val; 274fadff096Smrg static int recurse_lvl = 0; 275fadff096Smrg 276fadff096Smrg if (file->i_flags & DEFCHECKED) 277fadff096Smrg return (NULL); 278fadff096Smrg debug(2, ("Looking for %s in %s\n", symbol, file->i_file)); 279fadff096Smrg file->i_flags |= DEFCHECKED; 280fadff096Smrg if ((val = slookup(symbol, file))) 281fadff096Smrg debug(1, ("%s defined in %s as %s\n", 282fadff096Smrg symbol, file->i_file, (*val)->s_value)); 283fadff096Smrg if (val == NULL && file->i_list) { 284fadff096Smrg struct inclist **ip; 285fadff096Smrg unsigned int i; 286fadff096Smrg 287fadff096Smrg for (ip = file->i_list, i = 0; i < file->i_listlen; i++, ip++) { 288fadff096Smrg if (file->i_merged[i] == FALSE) { 289fadff096Smrg val = fdefined(symbol, *ip, srcfile); 290fadff096Smrg file->i_merged[i] = merge2defines(file, *ip); 291fadff096Smrg if (val != NULL) 292fadff096Smrg break; 293fadff096Smrg } 294fadff096Smrg } 295fadff096Smrg } 296fadff096Smrg else if (val != NULL && srcfile != NULL) 297fadff096Smrg *srcfile = file; 298fadff096Smrg recurse_lvl--; 299fadff096Smrg file->i_flags &= ~DEFCHECKED; 300fadff096Smrg 301fadff096Smrg return (val); 3020eb10989Smrg} 3030eb10989Smrg 3040eb10989Smrgstruct symtab ** 305d43532a6Smrgisdefined(const char *symbol, struct inclist *file, struct inclist **srcfile) 3060eb10989Smrg{ 307fadff096Smrg struct symtab **val; 308fadff096Smrg 309fadff096Smrg if ((val = slookup(symbol, &maininclist))) { 310fadff096Smrg debug(1, ("%s defined on command line\n", symbol)); 311fadff096Smrg if (srcfile != NULL) 312fadff096Smrg *srcfile = &maininclist; 313fadff096Smrg return (val); 314fadff096Smrg } 315fadff096Smrg if ((val = fdefined(symbol, file, srcfile))) 316fadff096Smrg return (val); 317fadff096Smrg debug(1, ("%s not defined in %s\n", symbol, file->i_file)); 318fadff096Smrg return (NULL); 3190eb10989Smrg} 3200eb10989Smrg 3210eb10989Smrg/* 3220eb10989Smrg * Return type based on if the #if expression evaluates to 0 3230eb10989Smrg */ 3240eb10989Smrgstatic int 325fadff096Smrgzero_value(char *filename, char *exp, 326fadff096Smrg struct filepointer *filep, struct inclist *file_red) 3270eb10989Smrg{ 328fadff096Smrg if (cppsetup(filename, exp, filep, file_red)) 329fadff096Smrg return (IFFALSE); 330fadff096Smrg else 331fadff096Smrg return (IF); 3320eb10989Smrg} 3330eb10989Smrg 3340eb10989Smrgvoid 335d43532a6Smrgdefine2(const char *name, const char *val, struct inclist *file) 3360eb10989Smrg{ 3370eb10989Smrg int first, last, below; 338fadff096Smrg struct symtab **sp = NULL, **dest; 3390eb10989Smrg struct symtab *stab; 3400eb10989Smrg 3410eb10989Smrg /* Make space if it's needed */ 342fadff096Smrg if (file->i_defs == NULL) { 343fadff096Smrg file->i_defs = mallocarray(SYMTABINC, sizeof(struct symtab *)); 344fadff096Smrg file->i_ndefs = 0; 3450eb10989Smrg } 3460eb10989Smrg else if (!(file->i_ndefs % SYMTABINC)) 347fadff096Smrg file->i_defs = reallocarray(file->i_defs, (file->i_ndefs + SYMTABINC), 348fadff096Smrg sizeof(struct symtab *)); 3490eb10989Smrg 3500eb10989Smrg if (file->i_defs == NULL) 351fadff096Smrg fatalerr("malloc()/realloc() failure in insert_defn()\n"); 3520eb10989Smrg 3530eb10989Smrg below = first = 0; 3540eb10989Smrg last = file->i_ndefs - 1; 355fadff096Smrg while (last >= first) { 356fadff096Smrg /* Fast inline binary search */ 357fadff096Smrg const char *s1; 358fadff096Smrg const char *s2; 359fadff096Smrg int middle = (first + last) / 2; 360fadff096Smrg 361fadff096Smrg /* Fast inline strcmp() */ 362fadff096Smrg s1 = name; 363fadff096Smrg s2 = file->i_defs[middle]->s_name; 364fadff096Smrg while (*s1++ == *s2++) 365fadff096Smrg if (s2[-1] == '\0') 366fadff096Smrg break; 367fadff096Smrg 368fadff096Smrg /* If exact match, set sp and break */ 369fadff096Smrg if (*--s1 == *--s2) { 370fadff096Smrg sp = file->i_defs + middle; 371fadff096Smrg break; 372fadff096Smrg } 373fadff096Smrg 374fadff096Smrg /* If name > i_defs[middle] ... */ 375fadff096Smrg if (*s1 > *s2) { 376fadff096Smrg below = first; 377fadff096Smrg first = middle + 1; 378fadff096Smrg } 379fadff096Smrg /* else ... */ 380fadff096Smrg else { 381fadff096Smrg below = last = middle - 1; 382fadff096Smrg } 3830eb10989Smrg } 3840eb10989Smrg 3850eb10989Smrg /* Search is done. If we found an exact match to the symbol name, 3860eb10989Smrg just replace its s_value */ 387fadff096Smrg if (sp != NULL) { 388fadff096Smrg debug(1, ("redefining %s from %s to %s in file %s\n", 389fadff096Smrg name, (*sp)->s_value, val, file->i_file)); 390fadff096Smrg free((*sp)->s_value); 391fadff096Smrg (*sp)->s_value = strdup(val); 392fadff096Smrg if ((*sp)->s_value == NULL) 393fadff096Smrg fatalerr("strdup() failure in %s()\n", __func__); 394fadff096Smrg return; 3950eb10989Smrg } 3960eb10989Smrg 3970eb10989Smrg sp = file->i_defs + file->i_ndefs++; 3980eb10989Smrg dest = file->i_defs + below + 1; 399fadff096Smrg while (sp > dest) { 400fadff096Smrg *sp = sp[-1]; 401fadff096Smrg sp--; 4020eb10989Smrg } 403fadff096Smrg stab = malloc(sizeof(struct symtab)); 4040eb10989Smrg if (stab == NULL) 405fadff096Smrg fatalerr("malloc()/realloc() failure in insert_defn()\n"); 4060eb10989Smrg 407fadff096Smrg debug(1, ("defining %s to %s in file %s\n", name, val, file->i_file)); 408d43532a6Smrg stab->s_name = strdup(name); 409d43532a6Smrg stab->s_value = strdup(val); 410fadff096Smrg if ((stab->s_name == NULL) || (stab->s_value == NULL)) 411fadff096Smrg fatalerr("strdup() failure in %s()\n", __func__); 4120eb10989Smrg *sp = stab; 4130eb10989Smrg} 4140eb10989Smrg 4150eb10989Smrgvoid 4160eb10989Smrgdefine(char *def, struct inclist *file) 4170eb10989Smrg{ 4180eb10989Smrg char *val; 4190eb10989Smrg 4200eb10989Smrg /* Separate symbol name and its value */ 4210eb10989Smrg val = def; 4220eb10989Smrg while (isalnum(*val) || *val == '_') 423fadff096Smrg val++; 4240eb10989Smrg if (*val) 425fadff096Smrg *val++ = '\0'; 4260eb10989Smrg while (*val == ' ' || *val == '\t') 427fadff096Smrg val++; 4280eb10989Smrg 4290eb10989Smrg if (!*val) 430fadff096Smrg define2(def, "1", file); 431d43532a6Smrg else 432fadff096Smrg define2(def, val, file); 4330eb10989Smrg} 4340eb10989Smrg 4350eb10989Smrgstruct symtab ** 436d43532a6Smrgslookup(const char *symbol, struct inclist *file) 4370eb10989Smrg{ 438fadff096Smrg int first = 0; 439fadff096Smrg int last; 440fadff096Smrg 441fadff096Smrg if (file == NULL) 442fadff096Smrg return NULL; 443fadff096Smrg 444fadff096Smrg last = file->i_ndefs - 1; 445fadff096Smrg 446fadff096Smrg while (last >= first) { 447fadff096Smrg /* Fast inline binary search */ 448fadff096Smrg const char *s1; 449fadff096Smrg const char *s2; 450fadff096Smrg int middle = (first + last) / 2; 451fadff096Smrg 452fadff096Smrg /* Fast inline strcmp() */ 453fadff096Smrg s1 = symbol; 454fadff096Smrg s2 = file->i_defs[middle]->s_name; 455fadff096Smrg while (*s1++ == *s2++) 456fadff096Smrg if (s2[-1] == '\0') 457fadff096Smrg break; 458fadff096Smrg 459fadff096Smrg /* If exact match, we're done */ 460fadff096Smrg if (*--s1 == *--s2) { 461fadff096Smrg return file->i_defs + middle; 462fadff096Smrg } 463fadff096Smrg 464fadff096Smrg /* If symbol > i_defs[middle] ... */ 465fadff096Smrg if (*s1 > *s2) { 466fadff096Smrg first = middle + 1; 467fadff096Smrg } 468fadff096Smrg /* else ... */ 469fadff096Smrg else { 470fadff096Smrg last = middle - 1; 471fadff096Smrg } 472fadff096Smrg } 473fadff096Smrg return (NULL); 4740eb10989Smrg} 4750eb10989Smrg 476fadff096Smrgstatic boolean 4770eb10989Smrgmerge2defines(struct inclist *file1, struct inclist *file2) 4780eb10989Smrg{ 479fadff096Smrg if ((file1 == NULL) || (file2 == NULL) || !(file2->i_flags & FINISHED)) 480fadff096Smrg return 0; 481fadff096Smrg 482fadff096Smrg for (unsigned int i = 0; i < file2->i_listlen; i++) 483fadff096Smrg if (file2->i_merged[i] == FALSE) 484fadff096Smrg return 0; 485fadff096Smrg 486fadff096Smrg { 487fadff096Smrg int first1 = 0; 488fadff096Smrg int last1 = file1->i_ndefs - 1; 489fadff096Smrg 490fadff096Smrg int first2 = 0; 491fadff096Smrg int last2 = file2->i_ndefs - 1; 492fadff096Smrg 493fadff096Smrg int first = 0; 494fadff096Smrg struct symtab **i_defs = NULL; 495fadff096Smrg int deflen = file1->i_ndefs + file2->i_ndefs; 496fadff096Smrg 497fadff096Smrg debug(2, ("merging %s into %s\n", file2->i_file, file1->i_file)); 498fadff096Smrg 499fadff096Smrg if (deflen > 0) { 500fadff096Smrg /* make sure deflen % SYMTABINC == 0 is still true */ 501fadff096Smrg deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC; 502fadff096Smrg i_defs = mallocarray(deflen, sizeof(struct symtab *)); 503fadff096Smrg if (i_defs == NULL) 504fadff096Smrg return 0; 505fadff096Smrg } 506fadff096Smrg 507fadff096Smrg while ((last1 >= first1) && (last2 >= first2)) { 508fadff096Smrg const char *s1 = file1->i_defs[first1]->s_name; 509fadff096Smrg const char *s2 = file2->i_defs[first2]->s_name; 510fadff096Smrg 511fadff096Smrg if (strcmp(s1, s2) < 0) 512fadff096Smrg i_defs[first++] = file1->i_defs[first1++]; 513fadff096Smrg else if (strcmp(s1, s2) > 0) 514fadff096Smrg i_defs[first++] = file2->i_defs[first2++]; 515fadff096Smrg else { /* equal */ 516fadff096Smrg i_defs[first++] = file2->i_defs[first2++]; 517fadff096Smrg first1++; 518fadff096Smrg } 519fadff096Smrg } 520fadff096Smrg while (last1 >= first1) { 521fadff096Smrg i_defs[first++] = file1->i_defs[first1++]; 522fadff096Smrg } 523fadff096Smrg while (last2 >= first2) { 524fadff096Smrg i_defs[first++] = file2->i_defs[first2++]; 525fadff096Smrg } 526fadff096Smrg 527fadff096Smrg if (file1->i_defs) 528fadff096Smrg free(file1->i_defs); 529fadff096Smrg file1->i_defs = i_defs; 530fadff096Smrg file1->i_ndefs = first; 531fadff096Smrg 532fadff096Smrg return 1; 533fadff096Smrg } 5340eb10989Smrg} 5350eb10989Smrg 5360eb10989Smrgvoid 537d43532a6Smrgundefine(const char *symbol, struct inclist *file) 5380eb10989Smrg{ 539fadff096Smrg struct symtab **ptr; 540fadff096Smrg struct inclist *srcfile; 541fadff096Smrg 542fadff096Smrg while ((ptr = isdefined(symbol, file, &srcfile)) != NULL) { 543fadff096Smrg srcfile->i_ndefs--; 544fadff096Smrg for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++) 545fadff096Smrg *ptr = ptr[1]; 546fadff096Smrg } 5470eb10989Smrg} 5480eb10989Smrg 5490eb10989Smrgint 550d43532a6Smrgfind_includes(struct filepointer *filep, struct inclist *file, 551fadff096Smrg struct inclist *file_red, int recursion, boolean failOK) 5520eb10989Smrg{ 553fadff096Smrg char *line; 554fadff096Smrg 555fadff096Smrg while ((line = getnextline(filep))) { 556fadff096Smrg int type = deftype(line, filep, file_red, file, TRUE); 557fadff096Smrg 558fadff096Smrg switch (type) { 559fadff096Smrg case IF: 560fadff096Smrg doif: 561fadff096Smrg type = find_includes(filep, file, file_red, recursion + 1, failOK); 562fadff096Smrg while ((type == ELIF) || (type == ELIFFALSE) || 563fadff096Smrg (type == ELIFGUESSFALSE)) 564fadff096Smrg type = gobble(filep, file, file_red); 565fadff096Smrg if (type == ELSE) 566fadff096Smrg gobble(filep, file, file_red); 567fadff096Smrg break; 568fadff096Smrg case IFFALSE: 569fadff096Smrg case IFGUESSFALSE: 570fadff096Smrg doiffalse: 571fadff096Smrg { 572fadff096Smrg boolean recfailOK; 573fadff096Smrg 574fadff096Smrg if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) 575fadff096Smrg recfailOK = TRUE; 576fadff096Smrg else 577fadff096Smrg recfailOK = failOK; 578fadff096Smrg type = gobble(filep, file, file_red); 579fadff096Smrg if (type == ELSE) 580fadff096Smrg find_includes(filep, file, file_red, recursion + 1, recfailOK); 581fadff096Smrg else if (type == ELIF) 582fadff096Smrg goto doif; 583fadff096Smrg else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) 584fadff096Smrg goto doiffalse; 585fadff096Smrg } 586fadff096Smrg break; 587fadff096Smrg case IFDEF: 588fadff096Smrg case IFNDEF: 589fadff096Smrg if ((type == IFDEF && isdefined(line, file_red, NULL)) 590fadff096Smrg || (type == IFNDEF && !isdefined(line, file_red, NULL))) { 591fadff096Smrg debug(1, (type == IFNDEF ? 592fadff096Smrg "line %d: %s !def'd in %s via %s%s\n" : "", 593fadff096Smrg filep->f_line, line, 594fadff096Smrg file->i_file, file_red->i_file, ": doit")); 595fadff096Smrg type = find_includes(filep, file, 596fadff096Smrg file_red, recursion + 1, failOK); 597fadff096Smrg while (type == ELIF || type == ELIFFALSE || 598fadff096Smrg type == ELIFGUESSFALSE) 599fadff096Smrg type = gobble(filep, file, file_red); 600fadff096Smrg if (type == ELSE) 601fadff096Smrg gobble(filep, file, file_red); 602fadff096Smrg } 603fadff096Smrg else { 604fadff096Smrg debug(1, (type == IFDEF ? 605fadff096Smrg "line %d: %s !def'd in %s via %s%s\n" : "", 606fadff096Smrg filep->f_line, line, 607fadff096Smrg file->i_file, file_red->i_file, ": gobble")); 608fadff096Smrg type = gobble(filep, file, file_red); 609fadff096Smrg if (type == ELSE) 610fadff096Smrg find_includes(filep, file, file_red, recursion + 1, failOK); 611fadff096Smrg else if (type == ELIF) 612fadff096Smrg goto doif; 613fadff096Smrg else if (type == ELIFFALSE || type == ELIFGUESSFALSE) 614fadff096Smrg goto doiffalse; 615fadff096Smrg } 616fadff096Smrg break; 617fadff096Smrg case ELSE: 618fadff096Smrg case ELIFFALSE: 619fadff096Smrg case ELIFGUESSFALSE: 620fadff096Smrg case ELIF: 621fadff096Smrg if (!recursion) 622fadff096Smrg gobble(filep, file, file_red); 623fadff096Smrg case ENDIF: 624fadff096Smrg if (recursion) 625fadff096Smrg return (type); 626fadff096Smrg case DEFINE: 627fadff096Smrg define(line, file); 628fadff096Smrg break; 629fadff096Smrg case UNDEF: 630fadff096Smrg if (!*line) { 631fadff096Smrg warning("%s", file_red->i_file); 632fadff096Smrg if (file_red != file) 633fadff096Smrg warning1(" (reading %s)", file->i_file); 634fadff096Smrg warning1(", line %ld: incomplete undef == \"%s\"\n", 635fadff096Smrg filep->f_line, line); 636fadff096Smrg break; 637fadff096Smrg } 638fadff096Smrg undefine(line, file_red); 639fadff096Smrg break; 640fadff096Smrg case INCLUDE: 641fadff096Smrg case INCLUDEDOT: 642fadff096Smrg case INCLUDENEXT: 643fadff096Smrg case INCLUDENEXTDOT: 644fadff096Smrg { 645fadff096Smrg struct inclist *inclist_save = inclistnext; 646fadff096Smrg const char **includedirs_save = includedirsnext; 647fadff096Smrg 648fadff096Smrg debug(2, ("%s, reading %s, includes %s\n", 649fadff096Smrg file_red->i_file, file->i_file, line)); 650fadff096Smrg add_include(filep, file, file_red, line, type, failOK); 651fadff096Smrg inclistnext = inclist_save; 652fadff096Smrg includedirsnext = includedirs_save; 653fadff096Smrg } 654fadff096Smrg break; 655fadff096Smrg case ERROR: 656fadff096Smrg case WARNING: 657fadff096Smrg warning("%s", file_red->i_file); 658fadff096Smrg if (file_red != file) 659fadff096Smrg warning1(" (reading %s)", file->i_file); 660fadff096Smrg warning1(", line %ld: %s\n", filep->f_line, line); 661fadff096Smrg break; 662fadff096Smrg 663fadff096Smrg case PRAGMA: 664fadff096Smrg case IDENT: 665fadff096Smrg case SCCS: 666fadff096Smrg case EJECT: 667fadff096Smrg break; 668fadff096Smrg case -1: 669fadff096Smrg warning("%s", file_red->i_file); 670fadff096Smrg if (file_red != file) 671fadff096Smrg warning1(" (reading %s)", file->i_file); 672fadff096Smrg warning1(", line %ld: unknown directive == \"%s\"\n", 673fadff096Smrg filep->f_line, line); 674fadff096Smrg break; 675fadff096Smrg case -2: 676fadff096Smrg warning("%s", file_red->i_file); 677fadff096Smrg if (file_red != file) 678fadff096Smrg warning1(" (reading %s)", file->i_file); 679fadff096Smrg warning1(", line %ld: incomplete include == \"%s\"\n", 680fadff096Smrg filep->f_line, line); 681fadff096Smrg break; 682fadff096Smrg } 683fadff096Smrg } 684fadff096Smrg file->i_flags |= FINISHED; 685fadff096Smrg debug(2, ("finished with %s\n", file->i_file)); 686fadff096Smrg return (-1); 6870eb10989Smrg} 688