| 1 | /* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */
|
|---|
| 2 | /*
|
|---|
| 3 |
|
|---|
| 4 | Copyright (c) 1993, 1994, 1998 The Open Group
|
|---|
| 5 |
|
|---|
| 6 | Permission to use, copy, modify, distribute, and sell this software and its
|
|---|
| 7 | documentation for any purpose is hereby granted without fee, provided that
|
|---|
| 8 | the above copyright notice appear in all copies and that both that
|
|---|
| 9 | copyright notice and this permission notice appear in supporting
|
|---|
| 10 | documentation.
|
|---|
| 11 |
|
|---|
| 12 | The above copyright notice and this permission notice shall be included in
|
|---|
| 13 | all copies or substantial portions of the Software.
|
|---|
| 14 |
|
|---|
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|---|
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|---|
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|---|
| 18 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|---|
| 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|---|
| 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|---|
| 21 |
|
|---|
| 22 | Except as contained in this notice, the name of The Open Group shall not be
|
|---|
| 23 | used in advertising or otherwise to promote the sale, use or other dealings
|
|---|
| 24 | in this Software without prior written authorization from The Open Group.
|
|---|
| 25 |
|
|---|
| 26 | */
|
|---|
| 27 | /* $XFree86: xc/config/makedepend/parse.c,v 1.11 2001/12/17 20:52:22 dawes Exp $ */
|
|---|
| 28 |
|
|---|
| 29 | #include "def.h"
|
|---|
| 30 |
|
|---|
| 31 | extern char *directives[];
|
|---|
| 32 | extern struct inclist inclist[ MAXFILES ],
|
|---|
| 33 | *inclistnext,
|
|---|
| 34 | maininclist;
|
|---|
| 35 | extern char *includedirs[ ],
|
|---|
| 36 | **includedirsnext;
|
|---|
| 37 |
|
|---|
| 38 | static int deftype (char *line, struct filepointer *filep,
|
|---|
| 39 | struct inclist *file_red, struct inclist *file,
|
|---|
| 40 | int parse_it);
|
|---|
| 41 | static int zero_value(char *filename, char *exp, struct filepointer *filep,
|
|---|
| 42 | struct inclist *file_red);
|
|---|
| 43 | static int merge2defines(struct inclist *file1, struct inclist *file2);
|
|---|
| 44 |
|
|---|
| 45 | static int
|
|---|
| 46 | gobble(struct filepointer *filep, struct inclist *file,
|
|---|
| 47 | struct inclist *file_red)
|
|---|
| 48 | {
|
|---|
| 49 | char *line;
|
|---|
| 50 | int type;
|
|---|
| 51 |
|
|---|
| 52 | while ((line = getnextline(filep))) {
|
|---|
| 53 | switch(type = deftype(line, filep, file_red, file, FALSE)) {
|
|---|
| 54 | case IF:
|
|---|
| 55 | case IFFALSE:
|
|---|
| 56 | case IFGUESSFALSE:
|
|---|
| 57 | case IFDEF:
|
|---|
| 58 | case IFNDEF:
|
|---|
| 59 | type = gobble(filep, file, file_red);
|
|---|
| 60 | while ((type == ELIF) || (type == ELIFFALSE) ||
|
|---|
| 61 | (type == ELIFGUESSFALSE))
|
|---|
| 62 | type = gobble(filep, file, file_red);
|
|---|
| 63 | if (type == ELSE)
|
|---|
| 64 | (void)gobble(filep, file, file_red);
|
|---|
| 65 | break;
|
|---|
| 66 | case ELSE:
|
|---|
| 67 | case ENDIF:
|
|---|
| 68 | debug(0,("%s, line %d: #%s\n",
|
|---|
| 69 | file->i_file, filep->f_line,
|
|---|
| 70 | directives[type]));
|
|---|
| 71 | return(type);
|
|---|
| 72 | case DEFINE:
|
|---|
| 73 | case UNDEF:
|
|---|
| 74 | case INCLUDE:
|
|---|
| 75 | case INCLUDEDOT:
|
|---|
| 76 | case PRAGMA:
|
|---|
| 77 | case ERROR:
|
|---|
| 78 | case IDENT:
|
|---|
| 79 | case SCCS:
|
|---|
| 80 | case EJECT:
|
|---|
| 81 | case WARNING:
|
|---|
| 82 | case INCLUDENEXT:
|
|---|
| 83 | case INCLUDENEXTDOT:
|
|---|
| 84 | break;
|
|---|
| 85 | case ELIF:
|
|---|
| 86 | case ELIFFALSE:
|
|---|
| 87 | case ELIFGUESSFALSE:
|
|---|
| 88 | return(type);
|
|---|
| 89 | case -1:
|
|---|
| 90 | warning("%s", file_red->i_file);
|
|---|
| 91 | if (file_red != file)
|
|---|
| 92 | warning1(" (reading %s)", file->i_file);
|
|---|
| 93 | warning1(", line %d: unknown directive == \"%s\"\n",
|
|---|
| 94 | filep->f_line, line);
|
|---|
| 95 | break;
|
|---|
| 96 | }
|
|---|
| 97 | }
|
|---|
| 98 | return(-1);
|
|---|
| 99 | }
|
|---|
| 100 |
|
|---|
| 101 | /*
|
|---|
| 102 | * Decide what type of # directive this line is.
|
|---|
| 103 | */
|
|---|
| 104 | static int
|
|---|
| 105 | deftype (char *line, struct filepointer *filep,
|
|---|
| 106 | struct inclist *file_red, struct inclist *file, int parse_it)
|
|---|
| 107 | {
|
|---|
| 108 | register char *p;
|
|---|
| 109 | char *directive, savechar, *q;
|
|---|
| 110 | register int ret;
|
|---|
| 111 |
|
|---|
| 112 | /*
|
|---|
| 113 | * Parse the directive...
|
|---|
| 114 | */
|
|---|
| 115 | directive=line+1;
|
|---|
| 116 | while (*directive == ' ' || *directive == '\t')
|
|---|
| 117 | directive++;
|
|---|
| 118 |
|
|---|
| 119 | p = directive;
|
|---|
| 120 | while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
|
|---|
| 121 | p++;
|
|---|
| 122 | savechar = *p;
|
|---|
| 123 | *p = '\0';
|
|---|
| 124 | ret = match(directive, directives);
|
|---|
| 125 | *p = savechar;
|
|---|
| 126 |
|
|---|
| 127 | /* If we don't recognize this compiler directive or we happen to just
|
|---|
| 128 | * be gobbling up text while waiting for an #endif or #elif or #else
|
|---|
| 129 | * in the case of an #elif we must check the zero_value and return an
|
|---|
| 130 | * ELIF or an ELIFFALSE.
|
|---|
| 131 | */
|
|---|
| 132 |
|
|---|
| 133 | if (ret == ELIF && !parse_it)
|
|---|
| 134 | {
|
|---|
| 135 | while (*p == ' ' || *p == '\t')
|
|---|
| 136 | p++;
|
|---|
| 137 | /*
|
|---|
| 138 | * parse an expression.
|
|---|
| 139 | */
|
|---|
| 140 | debug(0,("%s, line %d: #elif %s ",
|
|---|
| 141 | file->i_file, filep->f_line, p));
|
|---|
| 142 | ret = zero_value(file->i_file, p, filep, file_red);
|
|---|
| 143 | if (ret != IF)
|
|---|
| 144 | {
|
|---|
| 145 | debug(0,("false...\n"));
|
|---|
| 146 | if (ret == IFFALSE)
|
|---|
| 147 | return(ELIFFALSE);
|
|---|
| 148 | else
|
|---|
| 149 | return(ELIFGUESSFALSE);
|
|---|
| 150 | }
|
|---|
| 151 | else
|
|---|
| 152 | {
|
|---|
| 153 | debug(0,("true...\n"));
|
|---|
| 154 | return(ELIF);
|
|---|
| 155 | }
|
|---|
| 156 | }
|
|---|
| 157 |
|
|---|
| 158 | if (ret < 0 || ! parse_it)
|
|---|
| 159 | return(ret);
|
|---|
| 160 |
|
|---|
| 161 | /*
|
|---|
| 162 | * now decide how to parse the directive, and do it.
|
|---|
| 163 | */
|
|---|
| 164 | while (*p == ' ' || *p == '\t')
|
|---|
| 165 | p++;
|
|---|
| 166 | q = p + strlen(p);
|
|---|
| 167 | do {
|
|---|
| 168 | q--;
|
|---|
| 169 | } while (*q == ' ' || *q == '\t');
|
|---|
| 170 | q[1] = '\0';
|
|---|
| 171 | switch (ret) {
|
|---|
| 172 | case IF:
|
|---|
| 173 | /*
|
|---|
| 174 | * parse an expression.
|
|---|
| 175 | */
|
|---|
| 176 | ret = zero_value(file->i_file, p, filep, file_red);
|
|---|
| 177 | debug(0,("%s, line %d: %s #if %s\n",
|
|---|
| 178 | file->i_file, filep->f_line, ret?"false":"true", p));
|
|---|
| 179 | break;
|
|---|
| 180 | case IFDEF:
|
|---|
| 181 | case IFNDEF:
|
|---|
| 182 | debug(0,("%s, line %d: #%s %s\n",
|
|---|
| 183 | file->i_file, filep->f_line, directives[ret], p));
|
|---|
| 184 | case UNDEF:
|
|---|
| 185 | /*
|
|---|
| 186 | * separate the name of a single symbol.
|
|---|
| 187 | */
|
|---|
| 188 | while (isalnum(*p) || *p == '_')
|
|---|
| 189 | *line++ = *p++;
|
|---|
| 190 | *line = '\0';
|
|---|
| 191 | break;
|
|---|
| 192 | case INCLUDE:
|
|---|
| 193 | case INCLUDENEXT:
|
|---|
| 194 | debug(2,("%s, line %d: #include%s %s\n",
|
|---|
| 195 | file->i_file, filep->f_line,
|
|---|
| 196 | (ret == INCLUDE) ? "" : "_next", p));
|
|---|
| 197 |
|
|---|
| 198 | /* Support ANSI macro substitution */
|
|---|
| 199 | while (1) {
|
|---|
| 200 | struct symtab **sym;
|
|---|
| 201 |
|
|---|
| 202 | if (!*p || *p == '"' || *p == '<')
|
|---|
| 203 | break;
|
|---|
| 204 |
|
|---|
| 205 | sym = isdefined(p, file_red, NULL);
|
|---|
| 206 | if (!sym)
|
|---|
| 207 | break;
|
|---|
| 208 |
|
|---|
| 209 | p = (*sym)->s_value;
|
|---|
| 210 | debug(3,("%s : #includes SYMBOL %s = %s\n",
|
|---|
| 211 | file->i_incstring,
|
|---|
| 212 | (*sym) -> s_name,
|
|---|
| 213 | (*sym) -> s_value));
|
|---|
| 214 | /* mark file as having included a 'soft include' */
|
|---|
| 215 | file->i_flags |= INCLUDED_SYM;
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 | /*
|
|---|
| 219 | * Separate the name of the include file.
|
|---|
| 220 | */
|
|---|
| 221 | while (*p && *p != '"' && *p != '<')
|
|---|
| 222 | p++;
|
|---|
| 223 | if (! *p)
|
|---|
| 224 | return(-2);
|
|---|
| 225 | if (*p++ == '"') {
|
|---|
| 226 | if (ret == INCLUDE)
|
|---|
| 227 | ret = INCLUDEDOT;
|
|---|
| 228 | else
|
|---|
| 229 | ret = INCLUDENEXTDOT;
|
|---|
| 230 | while (*p && *p != '"')
|
|---|
| 231 | *line++ = *p++;
|
|---|
| 232 | } else
|
|---|
| 233 | while (*p && *p != '>')
|
|---|
| 234 | *line++ = *p++;
|
|---|
| 235 | *line = '\0';
|
|---|
| 236 | break;
|
|---|
| 237 | case DEFINE:
|
|---|
| 238 | /*
|
|---|
| 239 | * copy the definition back to the beginning of the line.
|
|---|
| 240 | */
|
|---|
| 241 | strcpy (line, p);
|
|---|
| 242 | break;
|
|---|
| 243 | case ELSE:
|
|---|
| 244 | case ENDIF:
|
|---|
| 245 | case ELIF:
|
|---|
| 246 | case PRAGMA:
|
|---|
| 247 | case ERROR:
|
|---|
| 248 | case IDENT:
|
|---|
| 249 | case SCCS:
|
|---|
| 250 | case EJECT:
|
|---|
| 251 | case WARNING:
|
|---|
| 252 | debug(0,("%s, line %d: #%s\n",
|
|---|
| 253 | file->i_file, filep->f_line, directives[ret]));
|
|---|
| 254 | /*
|
|---|
| 255 | * nothing to do.
|
|---|
| 256 | */
|
|---|
| 257 | break;
|
|---|
| 258 | }
|
|---|
| 259 | return(ret);
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | struct symtab **
|
|---|
| 263 | fdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
|
|---|
| 264 | {
|
|---|
| 265 | struct inclist **ip;
|
|---|
| 266 | struct symtab **val;
|
|---|
| 267 | int i;
|
|---|
| 268 | static int recurse_lvl = 0;
|
|---|
| 269 |
|
|---|
| 270 | if (file->i_flags & DEFCHECKED)
|
|---|
| 271 | return(NULL);
|
|---|
| 272 | debug(2,("Looking for %s in %s\n", symbol, file->i_file));
|
|---|
| 273 | file->i_flags |= DEFCHECKED;
|
|---|
| 274 | if ((val = slookup(symbol, file)))
|
|---|
| 275 | debug(1,("%s defined in %s as %s\n",
|
|---|
| 276 | symbol, file->i_file, (*val)->s_value));
|
|---|
| 277 | if (val == NULL && file->i_list)
|
|---|
| 278 | {
|
|---|
| 279 | for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
|
|---|
| 280 | if (file->i_merged[i]==FALSE) {
|
|---|
| 281 | val = fdefined(symbol, *ip, srcfile);
|
|---|
| 282 | file->i_merged[i]=merge2defines(file,*ip);
|
|---|
| 283 | if (val!=NULL) break;
|
|---|
| 284 | }
|
|---|
| 285 | }
|
|---|
| 286 | else if (val != NULL && srcfile != NULL) *srcfile = file;
|
|---|
| 287 | recurse_lvl--;
|
|---|
| 288 | file->i_flags &= ~DEFCHECKED;
|
|---|
| 289 |
|
|---|
| 290 | return(val);
|
|---|
| 291 | }
|
|---|
| 292 |
|
|---|
| 293 | struct symtab **
|
|---|
| 294 | isdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
|
|---|
| 295 | {
|
|---|
| 296 | struct symtab **val;
|
|---|
| 297 |
|
|---|
| 298 | if ((val = slookup(symbol, &maininclist))) {
|
|---|
| 299 | debug(1,("%s defined on command line\n", symbol));
|
|---|
| 300 | if (srcfile != NULL) *srcfile = &maininclist;
|
|---|
| 301 | return(val);
|
|---|
| 302 | }
|
|---|
| 303 | if ((val = fdefined(symbol, file, srcfile)))
|
|---|
| 304 | return(val);
|
|---|
| 305 | debug(1,("%s not defined in %s\n", symbol, file->i_file));
|
|---|
| 306 | return(NULL);
|
|---|
| 307 | }
|
|---|
| 308 |
|
|---|
| 309 | /*
|
|---|
| 310 | * Return type based on if the #if expression evaluates to 0
|
|---|
| 311 | */
|
|---|
| 312 | static int
|
|---|
| 313 | zero_value(char *filename,
|
|---|
| 314 | char *exp,
|
|---|
| 315 | struct filepointer *filep,
|
|---|
| 316 | struct inclist *file_red)
|
|---|
| 317 | {
|
|---|
| 318 | if (cppsetup(filename, exp, filep, file_red))
|
|---|
| 319 | return(IFFALSE);
|
|---|
| 320 | else
|
|---|
| 321 | return(IF);
|
|---|
| 322 | }
|
|---|
| 323 |
|
|---|
| 324 | void
|
|---|
| 325 | define2(char *name, char *val, struct inclist *file)
|
|---|
| 326 | {
|
|---|
| 327 | int first, last, below;
|
|---|
| 328 | register struct symtab **sp = NULL, **dest;
|
|---|
| 329 | struct symtab *stab;
|
|---|
| 330 |
|
|---|
| 331 | /* Make space if it's needed */
|
|---|
| 332 | if (file->i_defs == NULL)
|
|---|
| 333 | {
|
|---|
| 334 | file->i_defs = (struct symtab **)
|
|---|
| 335 | malloc(sizeof (struct symtab*) * SYMTABINC);
|
|---|
| 336 | file->i_ndefs = 0;
|
|---|
| 337 | }
|
|---|
| 338 | else if (!(file->i_ndefs % SYMTABINC))
|
|---|
| 339 | file->i_defs = (struct symtab **)
|
|---|
| 340 | realloc(file->i_defs,
|
|---|
| 341 | sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
|
|---|
| 342 |
|
|---|
| 343 | if (file->i_defs == NULL)
|
|---|
| 344 | fatalerr("malloc()/realloc() failure in insert_defn()\n");
|
|---|
| 345 |
|
|---|
| 346 | below = first = 0;
|
|---|
| 347 | last = file->i_ndefs - 1;
|
|---|
| 348 | while (last >= first)
|
|---|
| 349 | {
|
|---|
| 350 | /* Fast inline binary search */
|
|---|
| 351 | register char *s1;
|
|---|
| 352 | register char *s2;
|
|---|
| 353 | register int middle = (first + last) / 2;
|
|---|
| 354 |
|
|---|
| 355 | /* Fast inline strchr() */
|
|---|
| 356 | s1 = name;
|
|---|
| 357 | s2 = file->i_defs[middle]->s_name;
|
|---|
| 358 | while (*s1++ == *s2++)
|
|---|
| 359 | if (s2[-1] == '\0') break;
|
|---|
| 360 |
|
|---|
| 361 | /* If exact match, set sp and break */
|
|---|
| 362 | if (*--s1 == *--s2)
|
|---|
| 363 | {
|
|---|
| 364 | sp = file->i_defs + middle;
|
|---|
| 365 | break;
|
|---|
| 366 | }
|
|---|
| 367 |
|
|---|
| 368 | /* If name > i_defs[middle] ... */
|
|---|
| 369 | if (*s1 > *s2)
|
|---|
| 370 | {
|
|---|
| 371 | below = first;
|
|---|
| 372 | first = middle + 1;
|
|---|
| 373 | }
|
|---|
| 374 | /* else ... */
|
|---|
| 375 | else
|
|---|
| 376 | {
|
|---|
| 377 | below = last = middle - 1;
|
|---|
| 378 | }
|
|---|
| 379 | }
|
|---|
| 380 |
|
|---|
| 381 | /* Search is done. If we found an exact match to the symbol name,
|
|---|
| 382 | just replace its s_value */
|
|---|
| 383 | if (sp != NULL)
|
|---|
| 384 | {
|
|---|
| 385 | debug(1,("redefining %s from %s to %s in file %s\n",
|
|---|
| 386 | name, (*sp)->s_value, val, file->i_file));
|
|---|
| 387 | free((*sp)->s_value);
|
|---|
| 388 | (*sp)->s_value = copy(val);
|
|---|
| 389 | return;
|
|---|
| 390 | }
|
|---|
| 391 |
|
|---|
| 392 | sp = file->i_defs + file->i_ndefs++;
|
|---|
| 393 | dest = file->i_defs + below + 1;
|
|---|
| 394 | while (sp > dest)
|
|---|
| 395 | {
|
|---|
| 396 | *sp = sp[-1];
|
|---|
| 397 | sp--;
|
|---|
| 398 | }
|
|---|
| 399 | stab = (struct symtab *) malloc(sizeof (struct symtab));
|
|---|
| 400 | if (stab == NULL)
|
|---|
| 401 | fatalerr("malloc()/realloc() failure in insert_defn()\n");
|
|---|
| 402 |
|
|---|
| 403 | debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
|
|---|
| 404 | stab->s_name = copy(name);
|
|---|
| 405 | stab->s_value = copy(val);
|
|---|
| 406 | *sp = stab;
|
|---|
| 407 | }
|
|---|
| 408 |
|
|---|
| 409 | void
|
|---|
| 410 | define(char *def, struct inclist *file)
|
|---|
| 411 | {
|
|---|
| 412 | char *val;
|
|---|
| 413 |
|
|---|
| 414 | /* Separate symbol name and its value */
|
|---|
| 415 | val = def;
|
|---|
| 416 | while (isalnum(*val) || *val == '_')
|
|---|
| 417 | val++;
|
|---|
| 418 | if (*val)
|
|---|
| 419 | *val++ = '\0';
|
|---|
| 420 | while (*val == ' ' || *val == '\t')
|
|---|
| 421 | val++;
|
|---|
| 422 |
|
|---|
| 423 | if (!*val)
|
|---|
| 424 | val = "1";
|
|---|
| 425 | define2(def, val, file);
|
|---|
| 426 | }
|
|---|
| 427 |
|
|---|
| 428 | struct symtab **
|
|---|
| 429 | slookup(char *symbol, struct inclist *file)
|
|---|
| 430 | {
|
|---|
| 431 | register int first = 0;
|
|---|
| 432 | register int last = file->i_ndefs - 1;
|
|---|
| 433 |
|
|---|
| 434 | if (file) while (last >= first)
|
|---|
| 435 | {
|
|---|
| 436 | /* Fast inline binary search */
|
|---|
| 437 | register char *s1;
|
|---|
| 438 | register char *s2;
|
|---|
| 439 | register int middle = (first + last) / 2;
|
|---|
| 440 |
|
|---|
| 441 | /* Fast inline strchr() */
|
|---|
| 442 | s1 = symbol;
|
|---|
| 443 | s2 = file->i_defs[middle]->s_name;
|
|---|
| 444 | while (*s1++ == *s2++)
|
|---|
| 445 | if (s2[-1] == '\0') break;
|
|---|
| 446 |
|
|---|
| 447 | /* If exact match, we're done */
|
|---|
| 448 | if (*--s1 == *--s2)
|
|---|
| 449 | {
|
|---|
| 450 | return file->i_defs + middle;
|
|---|
| 451 | }
|
|---|
| 452 |
|
|---|
| 453 | /* If symbol > i_defs[middle] ... */
|
|---|
| 454 | if (*s1 > *s2)
|
|---|
| 455 | {
|
|---|
| 456 | first = middle + 1;
|
|---|
| 457 | }
|
|---|
| 458 | /* else ... */
|
|---|
| 459 | else
|
|---|
| 460 | {
|
|---|
| 461 | last = middle - 1;
|
|---|
| 462 | }
|
|---|
| 463 | }
|
|---|
| 464 | return(NULL);
|
|---|
| 465 | }
|
|---|
| 466 |
|
|---|
| 467 | static int
|
|---|
| 468 | merge2defines(struct inclist *file1, struct inclist *file2)
|
|---|
| 469 | {
|
|---|
| 470 | int i;
|
|---|
| 471 |
|
|---|
| 472 | if ((file1==NULL) || (file2==NULL) ||
|
|---|
| 473 | !(file2->i_flags & FINISHED))
|
|---|
| 474 | return 0;
|
|---|
| 475 |
|
|---|
| 476 | for (i=0; i < file2->i_listlen; i++)
|
|---|
| 477 | if (file2->i_merged[i]==FALSE)
|
|---|
| 478 | return 0;
|
|---|
| 479 |
|
|---|
| 480 | {
|
|---|
| 481 | int first1 = 0;
|
|---|
| 482 | int last1 = file1->i_ndefs - 1;
|
|---|
| 483 |
|
|---|
| 484 | int first2 = 0;
|
|---|
| 485 | int last2 = file2->i_ndefs - 1;
|
|---|
| 486 |
|
|---|
| 487 | int first=0;
|
|---|
| 488 | struct symtab** i_defs = NULL;
|
|---|
| 489 | int deflen=file1->i_ndefs+file2->i_ndefs;
|
|---|
| 490 |
|
|---|
| 491 | debug(2,("merging %s into %s\n",
|
|---|
| 492 | file2->i_file, file1->i_file));
|
|---|
| 493 |
|
|---|
| 494 | if (deflen>0)
|
|---|
| 495 | {
|
|---|
| 496 | /* make sure deflen % SYMTABINC == 0 is still true */
|
|---|
| 497 | deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
|
|---|
| 498 | i_defs=(struct symtab**)
|
|---|
| 499 | malloc(deflen*sizeof(struct symtab*));
|
|---|
| 500 | if (i_defs==NULL) return 0;
|
|---|
| 501 | }
|
|---|
| 502 |
|
|---|
| 503 | while ((last1 >= first1) && (last2 >= first2))
|
|---|
| 504 | {
|
|---|
| 505 | char *s1=file1->i_defs[first1]->s_name;
|
|---|
| 506 | char *s2=file2->i_defs[first2]->s_name;
|
|---|
| 507 |
|
|---|
| 508 | if (strcmp(s1,s2) < 0)
|
|---|
| 509 | i_defs[first++]=file1->i_defs[first1++];
|
|---|
| 510 | else if (strcmp(s1,s2) > 0)
|
|---|
| 511 | i_defs[first++]=file2->i_defs[first2++];
|
|---|
| 512 | else /* equal */
|
|---|
| 513 | {
|
|---|
| 514 | i_defs[first++]=file2->i_defs[first2++];
|
|---|
| 515 | first1++;
|
|---|
| 516 | }
|
|---|
| 517 | }
|
|---|
| 518 | while (last1 >= first1)
|
|---|
| 519 | {
|
|---|
| 520 | i_defs[first++]=file1->i_defs[first1++];
|
|---|
| 521 | }
|
|---|
| 522 | while (last2 >= first2)
|
|---|
| 523 | {
|
|---|
| 524 | i_defs[first++]=file2->i_defs[first2++];
|
|---|
| 525 | }
|
|---|
| 526 |
|
|---|
| 527 | if (file1->i_defs) free(file1->i_defs);
|
|---|
| 528 | file1->i_defs=i_defs;
|
|---|
| 529 | file1->i_ndefs=first;
|
|---|
| 530 |
|
|---|
| 531 | return 1;
|
|---|
| 532 | }
|
|---|
| 533 | }
|
|---|
| 534 |
|
|---|
| 535 | void
|
|---|
| 536 | undefine(char *symbol, struct inclist *file)
|
|---|
| 537 | {
|
|---|
| 538 | register struct symtab **ptr;
|
|---|
| 539 | struct inclist *srcfile;
|
|---|
| 540 | while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
|
|---|
| 541 | {
|
|---|
| 542 | srcfile->i_ndefs--;
|
|---|
| 543 | for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
|
|---|
| 544 | *ptr = ptr[1];
|
|---|
| 545 | }
|
|---|
| 546 | }
|
|---|
| 547 |
|
|---|
| 548 | int
|
|---|
| 549 | find_includes(struct filepointer *filep, struct inclist *file,
|
|---|
| 550 | struct inclist *file_red, int recursion, boolean failOK)
|
|---|
| 551 | {
|
|---|
| 552 | struct inclist *inclistp;
|
|---|
| 553 | char **includedirsp;
|
|---|
| 554 | register char *line;
|
|---|
| 555 | register int type;
|
|---|
| 556 | boolean recfailOK;
|
|---|
| 557 |
|
|---|
| 558 | while ((line = getnextline(filep))) {
|
|---|
| 559 | switch(type = deftype(line, filep, file_red, file, TRUE)) {
|
|---|
| 560 | case IF:
|
|---|
| 561 | doif:
|
|---|
| 562 | type = find_includes(filep, file,
|
|---|
| 563 | file_red, recursion+1, failOK);
|
|---|
| 564 | while ((type == ELIF) || (type == ELIFFALSE) ||
|
|---|
| 565 | (type == ELIFGUESSFALSE))
|
|---|
| 566 | type = gobble(filep, file, file_red);
|
|---|
| 567 | if (type == ELSE)
|
|---|
| 568 | gobble(filep, file, file_red);
|
|---|
| 569 | break;
|
|---|
| 570 | case IFFALSE:
|
|---|
| 571 | case IFGUESSFALSE:
|
|---|
| 572 | doiffalse:
|
|---|
| 573 | if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
|
|---|
| 574 | recfailOK = TRUE;
|
|---|
| 575 | else
|
|---|
| 576 | recfailOK = failOK;
|
|---|
| 577 | type = gobble(filep, file, file_red);
|
|---|
| 578 | if (type == ELSE)
|
|---|
| 579 | find_includes(filep, file,
|
|---|
| 580 | file_red, recursion+1, recfailOK);
|
|---|
| 581 | else
|
|---|
| 582 | if (type == ELIF)
|
|---|
| 583 | goto doif;
|
|---|
| 584 | else
|
|---|
| 585 | if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
|
|---|
| 586 | goto doiffalse;
|
|---|
| 587 | break;
|
|---|
| 588 | case IFDEF:
|
|---|
| 589 | case IFNDEF:
|
|---|
| 590 | if ((type == IFDEF && isdefined(line, file_red, NULL))
|
|---|
| 591 | || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
|
|---|
| 592 | debug(1,(type == IFNDEF ?
|
|---|
| 593 | "line %d: %s !def'd in %s via %s%s\n" : "",
|
|---|
| 594 | filep->f_line, line,
|
|---|
| 595 | file->i_file, file_red->i_file, ": doit"));
|
|---|
| 596 | type = find_includes(filep, file,
|
|---|
| 597 | file_red, recursion+1, failOK);
|
|---|
| 598 | while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
|
|---|
| 599 | type = gobble(filep, file, file_red);
|
|---|
| 600 | if (type == ELSE)
|
|---|
| 601 | gobble(filep, file, file_red);
|
|---|
| 602 | }
|
|---|
| 603 | else {
|
|---|
| 604 | debug(1,(type == IFDEF ?
|
|---|
| 605 | "line %d: %s !def'd in %s via %s%s\n" : "",
|
|---|
| 606 | filep->f_line, line,
|
|---|
| 607 | file->i_file, file_red->i_file, ": gobble"));
|
|---|
| 608 | type = gobble(filep, file, file_red);
|
|---|
| 609 | if (type == ELSE)
|
|---|
| 610 | find_includes(filep, file,
|
|---|
| 611 | file_red, recursion+1, failOK);
|
|---|
| 612 | else if (type == ELIF)
|
|---|
| 613 | goto doif;
|
|---|
| 614 | else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
|
|---|
| 615 | goto doiffalse;
|
|---|
| 616 | }
|
|---|
| 617 | break;
|
|---|
| 618 | case ELSE:
|
|---|
| 619 | case ELIFFALSE:
|
|---|
| 620 | case ELIFGUESSFALSE:
|
|---|
| 621 | case ELIF:
|
|---|
| 622 | if (!recursion)
|
|---|
| 623 | gobble(filep, file, file_red);
|
|---|
| 624 | case ENDIF:
|
|---|
| 625 | if (recursion)
|
|---|
| 626 | return(type);
|
|---|
| 627 | case DEFINE:
|
|---|
| 628 | define(line, file);
|
|---|
| 629 | break;
|
|---|
| 630 | case UNDEF:
|
|---|
| 631 | if (!*line) {
|
|---|
| 632 | warning("%s", file_red->i_file);
|
|---|
| 633 | if (file_red != file)
|
|---|
| 634 | warning1(" (reading %s)", file->i_file);
|
|---|
| 635 | warning1(", line %d: incomplete undef == \"%s\"\n",
|
|---|
| 636 | filep->f_line, line);
|
|---|
| 637 | break;
|
|---|
| 638 | }
|
|---|
| 639 | undefine(line, file_red);
|
|---|
| 640 | break;
|
|---|
| 641 | case INCLUDE:
|
|---|
| 642 | case INCLUDEDOT:
|
|---|
| 643 | case INCLUDENEXT:
|
|---|
| 644 | case INCLUDENEXTDOT:
|
|---|
| 645 | inclistp = inclistnext;
|
|---|
| 646 | includedirsp = includedirsnext;
|
|---|
| 647 | debug(2,("%s, reading %s, includes %s\n",
|
|---|
| 648 | file_red->i_file, file->i_file, line));
|
|---|
| 649 | add_include(filep, file, file_red, line, type, failOK);
|
|---|
| 650 | inclistnext = inclistp;
|
|---|
| 651 | includedirsnext = includedirsp;
|
|---|
| 652 | break;
|
|---|
| 653 | case ERROR:
|
|---|
| 654 | case WARNING:
|
|---|
| 655 | warning("%s", file_red->i_file);
|
|---|
| 656 | if (file_red != file)
|
|---|
| 657 | warning1(" (reading %s)", file->i_file);
|
|---|
| 658 | warning1(", line %d: %s\n",
|
|---|
| 659 | filep->f_line, line);
|
|---|
| 660 | break;
|
|---|
| 661 |
|
|---|
| 662 | case PRAGMA:
|
|---|
| 663 | case IDENT:
|
|---|
| 664 | case SCCS:
|
|---|
| 665 | case EJECT:
|
|---|
| 666 | break;
|
|---|
| 667 | case -1:
|
|---|
| 668 | warning("%s", file_red->i_file);
|
|---|
| 669 | if (file_red != file)
|
|---|
| 670 | warning1(" (reading %s)", file->i_file);
|
|---|
| 671 | warning1(", line %d: unknown directive == \"%s\"\n",
|
|---|
| 672 | filep->f_line, line);
|
|---|
| 673 | break;
|
|---|
| 674 | case -2:
|
|---|
| 675 | warning("%s", file_red->i_file);
|
|---|
| 676 | if (file_red != file)
|
|---|
| 677 | warning1(" (reading %s)", file->i_file);
|
|---|
| 678 | warning1(", line %d: incomplete include == \"%s\"\n",
|
|---|
| 679 | filep->f_line, line);
|
|---|
| 680 | break;
|
|---|
| 681 | }
|
|---|
| 682 | }
|
|---|
| 683 | file->i_flags |= FINISHED;
|
|---|
| 684 | debug(2,("finished with %s\n", file->i_file));
|
|---|
| 685 | return(-1);
|
|---|
| 686 | }
|
|---|