00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "def.h"
00031
00032 extern char *directives[];
00033 extern struct inclist maininclist;
00034
00035 extern int deftype(char *line, struct filepointer *filep,
00036 struct inclist *file_red, struct inclist *file,
00037 int parse_it);
00038 extern int match(char *str, char **list);
00039 extern int zero_value(char *exp, struct filepointer *filep,
00040 struct inclist *file_red);
00041 extern int merge2defines(struct inclist *file1, struct inclist *file2);
00042 extern int cppsetup(char *line, struct filepointer *filep,
00043 struct inclist *inc);
00044 extern void add_include(struct filepointer *filep, struct inclist *file,
00045 struct inclist *file_red, char *include,
00046 boolean dot, boolean failOK);
00047
00048
00049
00050 int
00051 gobble(filep, file, file_red)
00052 register struct filepointer *filep;
00053 struct inclist *file, *file_red;
00054 {
00055 register char *line;
00056 register int type;
00057
00058 while ((line = rgetline(filep))) {
00059 switch (type = deftype(line, filep, file_red, file, FALSE)) {
00060 case IF:
00061 case IFFALSE:
00062 case IFGUESSFALSE:
00063 case IFDEF:
00064 case IFNDEF:
00065 type = gobble(filep, file, file_red);
00066 while ((type == ELIF) || (type == ELIFFALSE) ||
00067 (type == ELIFGUESSFALSE))
00068 type = gobble(filep, file, file_red);
00069 if (type == ELSE)
00070 (void)gobble(filep, file, file_red);
00071 break;
00072 case ELSE:
00073 case ENDIF:
00074 debug(0, ("%s, line %d: #%s\n",
00075 file->i_file, filep->f_line,
00076 directives[type]));
00077 return(type);
00078 case DEFINE:
00079 case UNDEF:
00080 case INCLUDE:
00081 case INCLUDEDOT:
00082 case PRAGMA:
00083 case ERROR:
00084 case IDENT:
00085 case SCCS:
00086 case EJECT:
00087 case WARNING:
00088 break;
00089 case ELIF:
00090 case ELIFFALSE:
00091 case ELIFGUESSFALSE:
00092 return(type);
00093 case -1:
00094 warning("%s, line %d: unknown directive == \"%s\"\n",
00095 file_red->i_file, filep->f_line, line);
00096 break;
00097 }
00098 }
00099 return(-1);
00100 }
00101
00102
00103 static void inplace_strcpy(char* to, const char* from)
00104 {
00105 while (*from)
00106 *to++ = *from++;
00107 *to = *from;
00108 }
00109
00110
00111
00112
00113 int deftype(line, filep, file_red, file, parse_it)
00114 register char *line;
00115 register struct filepointer *filep;
00116 register struct inclist *file_red, *file;
00117 int parse_it;
00118 {
00119 register char *p;
00120 char *directive, savechar;
00121 register int ret;
00122
00123
00124
00125
00126 directive = line + 1;
00127 while (*directive == ' ' || *directive == '\t')
00128 directive++;
00129
00130 p = directive;
00131 while (*p >= 'a' && *p <= 'z')
00132 p++;
00133 savechar = *p;
00134 *p = '\0';
00135 ret = match(directive, directives);
00136 *p = savechar;
00137
00138
00139
00140
00141
00142
00143
00144 if (ret == ELIF && !parse_it) {
00145 while (*p == ' ' || *p == '\t')
00146 p++;
00147
00148
00149
00150 debug(0, ("%s, line %d: #elif %s ",
00151 file->i_file, filep->f_line, p));
00152 ret = zero_value(p, filep, file_red);
00153 if (ret != IF) {
00154 debug(0, ("false...\n"));
00155 if (ret == IFFALSE)
00156 return(ELIFFALSE);
00157 else
00158 return(ELIFGUESSFALSE);
00159 } else {
00160 debug(0, ("true...\n"));
00161 return(ELIF);
00162 }
00163 }
00164
00165 if (ret < 0 || ! parse_it)
00166 return(ret);
00167
00168
00169
00170
00171 while (*p == ' ' || *p == '\t')
00172 p++;
00173 switch (ret) {
00174 case IF:
00175
00176
00177
00178 ret = zero_value(p, filep, file_red);
00179 debug(0, ("%s, line %d: %s #if %s\n",
00180 file->i_file, filep->f_line, ret ? "false" : "true", p));
00181 break;
00182 case IFDEF:
00183 case IFNDEF:
00184 debug(0, ("%s, line %d: #%s %s\n",
00185 file->i_file, filep->f_line, directives[ret], p));
00186 case UNDEF:
00187
00188
00189
00190 while (isalnum((int)*p) || *p == '_')
00191 *line++ = *p++;
00192 *line = '\0';
00193 break;
00194 case INCLUDE:
00195 debug(2, ("%s, line %d: #include %s\n",
00196 file->i_file, filep->f_line, p));
00197
00198
00199 {
00200 struct symtab **sym = isdefined(p, file_red, NULL);
00201 while (sym) {
00202 p = (*sym)->s_value;
00203 debug(3, ("%s : #includes SYMBOL %s = %s\n",
00204 file->i_incstring,
00205 (*sym) -> s_name,
00206 (*sym) -> s_value));
00207
00208 file->i_flags |= INCLUDED_SYM;
00209 sym = isdefined(p, file_red, NULL);
00210 }
00211 }
00212
00213
00214
00215
00216 while (*p && *p != '"' && *p != '<')
00217 p++;
00218 if (! *p)
00219 return(-2);
00220 if (*p++ == '"') {
00221 ret = INCLUDEDOT;
00222 while (*p && *p != '"')
00223 *line++ = *p++;
00224 } else
00225 while (*p && *p != '>')
00226 *line++ = *p++;
00227 *line = '\0';
00228 break;
00229 case DEFINE:
00230
00231
00232
00233 inplace_strcpy(line, p);
00234 break;
00235 case ELSE:
00236 case ENDIF:
00237 case ELIF:
00238 case PRAGMA:
00239 case ERROR:
00240 case IDENT:
00241 case SCCS:
00242 case EJECT:
00243 case WARNING:
00244 debug(0, ("%s, line %d: #%s\n",
00245 file->i_file, filep->f_line, directives[ret]));
00246
00247
00248
00249 break;
00250 }
00251 return(ret);
00252 }
00253
00254 struct symtab **fdefined(symbol, file, srcfile)
00255 register char *symbol;
00256 struct inclist *file;
00257 struct inclist **srcfile;
00258 {
00259 register struct inclist **ip;
00260 register struct symtab **val;
00261 register int i;
00262 static int recurse_lvl = 0;
00263
00264 if (file->i_flags & DEFCHECKED)
00265 return(NULL);
00266 file->i_flags |= DEFCHECKED;
00267 if ((val = slookup(symbol, file))) {
00268 debug(1, ("%s defined in %s as %s\n",
00269 symbol, file->i_file, (*val)->s_value));
00270 }
00271 if (val == NULL && file->i_list) {
00272 for (ip = file->i_list, i = 0; i < file->i_listlen; i++, ip++)
00273 if (file->i_merged[i] == FALSE) {
00274 val = fdefined(symbol, *ip, srcfile);
00275 if ((*ip)->i_flags & FINISHED) {
00276 merge2defines(file, *ip);
00277 file->i_merged[i] = TRUE;
00278 }
00279 if (val != NULL) break;
00280 }
00281 } else if (val != NULL && srcfile != NULL) *srcfile = file;
00282 recurse_lvl--;
00283 file->i_flags &= ~DEFCHECKED;
00284
00285 return(val);
00286 }
00287
00288 struct symtab **isdefined(symbol, file, srcfile)
00289 register char *symbol;
00290 struct inclist *file;
00291 struct inclist **srcfile;
00292 {
00293 register struct symtab **val;
00294
00295 if ((val = slookup(symbol, &maininclist))) {
00296 debug(1, ("%s defined on command line\n", symbol));
00297 if (srcfile != NULL) *srcfile = &maininclist;
00298 return(val);
00299 }
00300 if ((val = fdefined(symbol, file, srcfile)))
00301 return(val);
00302 debug(1, ("%s not defined in %s\n", symbol, file->i_file));
00303 return(NULL);
00304 }
00305
00306
00307
00308
00309 int
00310 zero_value(exp, filep, file_red)
00311 register char *exp;
00312 register struct filepointer *filep;
00313 register struct inclist *file_red;
00314 {
00315 if (cppsetup(exp, filep, file_red))
00316 return(IFFALSE);
00317 else
00318 return(IF);
00319 }
00320
00321 void
00322 define2(name, val, file)
00323 char *name, *val;
00324 struct inclist *file;
00325 {
00326 int first, last, below;
00327 register struct symtab **sp = NULL, **dest;
00328 struct symtab *stab;
00329
00330
00331 if (file->i_defs == NULL) {
00332 file->i_defs = (struct symtab **)
00333 malloc(sizeof(struct symtab*) * SYMTABINC);
00334 file->i_ndefs = 0;
00335 } else if (!(file->i_ndefs % SYMTABINC))
00336 file->i_defs = (struct symtab **)
00337 realloc(file->i_defs,
00338 sizeof(struct symtab*) * (file->i_ndefs + SYMTABINC));
00339
00340 if (file->i_defs == NULL)
00341 fatalerr("malloc()/realloc() failure in insert_defn()\n");
00342
00343 below = first = 0;
00344 last = file->i_ndefs - 1;
00345 while (last >= first) {
00346
00347 register char *s1;
00348 register char *s2;
00349 register int middle = (first + last) / 2;
00350
00351
00352 s1 = name;
00353 s2 = file->i_defs[middle]->s_name;
00354 while (*s1++ == *s2++)
00355 if (s2[-1] == '\0') break;
00356
00357
00358 if (*--s1 == *--s2) {
00359 sp = file->i_defs + middle;
00360 break;
00361 }
00362
00363
00364 if (*s1 > *s2) {
00365 below = first;
00366 first = middle + 1;
00367 }
00368
00369 else {
00370 below = last = middle - 1;
00371 }
00372 }
00373
00374
00375
00376 if (sp != NULL) {
00377 free((*sp)->s_value);
00378 (*sp)->s_value = copy(val);
00379 return;
00380 }
00381
00382 sp = file->i_defs + file->i_ndefs++;
00383 dest = file->i_defs + below + 1;
00384 while (sp > dest) {
00385 *sp = sp[-1];
00386 sp--;
00387 }
00388 stab = (struct symtab *) malloc(sizeof(struct symtab));
00389 if (stab == NULL)
00390 fatalerr("malloc()/realloc() failure in insert_defn()\n");
00391
00392 stab->s_name = copy(name);
00393 stab->s_value = copy(val);
00394 *sp = stab;
00395 }
00396
00397 void
00398 define(def, file)
00399 char *def;
00400 struct inclist *file;
00401 {
00402 char *val;
00403
00404
00405 val = def;
00406 while (isalnum((int)*val) || *val == '_')
00407 val++;
00408 if (*val)
00409 *val++ = '\0';
00410 while (*val == ' ' || *val == '\t')
00411 val++;
00412
00413 if (!*val)
00414 val = "1";
00415 define2(def, val, file);
00416 }
00417
00418 struct symtab **slookup(symbol, file)
00419 register char *symbol;
00420 register struct inclist *file;
00421 {
00422 register int first = 0;
00423 register int last = file->i_ndefs - 1;
00424
00425 while (last >= first) {
00426
00427 register char *s1;
00428 register char *s2;
00429 register int middle = (first + last) / 2;
00430
00431
00432 s1 = symbol;
00433 s2 = file->i_defs[middle]->s_name;
00434 while (*s1++ == *s2++)
00435 if (s2[-1] == '\0') break;
00436
00437
00438 if (*--s1 == *--s2) {
00439 return file->i_defs + middle;
00440 }
00441
00442
00443 if (*s1 > *s2) {
00444 first = middle + 1;
00445 }
00446
00447 else {
00448 last = middle - 1;
00449 }
00450 }
00451 return(NULL);
00452 }
00453
00454 int merge2defines(file1, file2)
00455 struct inclist *file1;
00456 struct inclist *file2;
00457 {
00458 if ((file1 != NULL) && (file2 != NULL)) {
00459 int first1 = 0;
00460 int last1 = file1->i_ndefs - 1;
00461
00462 int first2 = 0;
00463 int last2 = file2->i_ndefs - 1;
00464
00465 int first = 0;
00466 struct symtab** i_defs = NULL;
00467 int deflen = file1->i_ndefs + file2->i_ndefs;
00468
00469 if (deflen > 0) {
00470
00471 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
00472 i_defs = (struct symtab**)malloc(deflen * sizeof(struct symtab*));
00473 }
00474 if (i_defs == NULL) return 0;
00475
00476 while ((last1 >= first1) && (last2 >= first2)) {
00477 char *s1 = file1->i_defs[first1]->s_name;
00478 char *s2 = file2->i_defs[first2]->s_name;
00479
00480 if (strcmp(s1, s2) < 0)
00481 i_defs[first++] = file1->i_defs[first1++];
00482 else if (strcmp(s1, s2) > 0)
00483 i_defs[first++] = file2->i_defs[first2++];
00484 else {
00485 i_defs[first++] = file2->i_defs[first2++];
00486 first1++;
00487 }
00488 }
00489 while (last1 >= first1) {
00490 i_defs[first++] = file1->i_defs[first1++];
00491 }
00492 while (last2 >= first2) {
00493 i_defs[first++] = file2->i_defs[first2++];
00494 }
00495
00496 if (file1->i_defs) free(file1->i_defs);
00497 file1->i_defs = i_defs;
00498 file1->i_ndefs = first;
00499
00500 return 1;
00501 }
00502 return 0;
00503 }
00504
00505 void
00506 undefine(symbol, file)
00507 char *symbol;
00508 register struct inclist *file;
00509 {
00510 register struct symtab **ptr;
00511 struct inclist *srcfile;
00512 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL) {
00513 srcfile->i_ndefs--;
00514 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
00515 *ptr = ptr[1];
00516 }
00517 }
00518
00519 void
00520 undefine_all(file)
00521 register struct inclist *file;
00522 {
00523 register struct symtab **ptr;
00524
00525 for (ptr = file->i_defs; ptr < file->i_defs + file->i_ndefs; ptr++)
00526 *ptr = 0;
00527
00528 file->i_ndefs = 0;
00529 }
00530
00531 int
00532 find_includes(filep, file, file_red, recursion, failOK)
00533 struct filepointer *filep;
00534 struct inclist *file, *file_red;
00535 int recursion;
00536 boolean failOK;
00537 {
00538 register char *line;
00539 register int type;
00540 boolean recfailOK;
00541
00542 while ((line = rgetline(filep))) {
00543 switch (type = deftype(line, filep, file_red, file, TRUE)) {
00544 case IF:
00545 doif:
00546 type = find_includes(filep, file,
00547 file_red, recursion + 1, failOK);
00548 while ((type == ELIF) || (type == ELIFFALSE) ||
00549 (type == ELIFGUESSFALSE))
00550 type = gobble(filep, file, file_red);
00551 if (type == ELSE)
00552 gobble(filep, file, file_red);
00553 break;
00554 case IFFALSE:
00555 case IFGUESSFALSE:
00556 doiffalse:
00557 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
00558 recfailOK = TRUE;
00559 else
00560 recfailOK = failOK;
00561 type = gobble(filep, file, file_red);
00562 if (type == ELSE)
00563 find_includes(filep, file,
00564 file_red, recursion + 1, recfailOK);
00565 else
00566 if (type == ELIF)
00567 goto doif;
00568 else
00569 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
00570 goto doiffalse;
00571 break;
00572 case IFDEF:
00573 case IFNDEF:
00574 if ((type == IFDEF && isdefined(line, file_red, (struct inclist**)0))
00575 || (type == IFNDEF && !isdefined(line, file_red, (struct inclist **)0))) {
00576 debug(1, (type == IFNDEF ?
00577 "line %d: %s !def'd in %s via %s%s\n" : "",
00578 filep->f_line, line,
00579 file->i_file, file_red->i_file, ": doit"));
00580 type = find_includes(filep, file,
00581 file_red, recursion + 1, failOK);
00582 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
00583 type = gobble(filep, file, file_red);
00584 if (type == ELSE)
00585 gobble(filep, file, file_red);
00586 } else {
00587 debug(1, (type == IFDEF ?
00588 "line %d: %s !def'd in %s via %s%s\n" : "",
00589 filep->f_line, line,
00590 file->i_file, file_red->i_file, ": gobble"));
00591 type = gobble(filep, file, file_red);
00592 if (type == ELSE)
00593 find_includes(filep, file,
00594 file_red, recursion + 1, failOK);
00595 else if (type == ELIF)
00596 goto doif;
00597 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
00598 goto doiffalse;
00599 }
00600 break;
00601 case ELSE:
00602 case ELIFFALSE:
00603 case ELIFGUESSFALSE:
00604 case ELIF:
00605 if (!recursion)
00606 gobble(filep, file, file_red);
00607
00608 case ENDIF:
00609 if (recursion)
00610 return(type);
00611
00612 case DEFINE:
00613 define(line, file);
00614 break;
00615 case UNDEF:
00616 if (!*line) {
00617 warning("%s, line %d: incomplete undef == \"%s\"\n",
00618 file_red->i_file, filep->f_line, line);
00619 break;
00620 }
00621 undefine(line, file_red);
00622 break;
00623 case INCLUDE:
00624 add_include(filep, file, file_red, line, FALSE, failOK);
00625 break;
00626 case INCLUDEDOT:
00627 add_include(filep, file, file_red, line, TRUE, failOK);
00628 break;
00629 case ERROR:
00630 case WARNING:
00631 warning("%s: %d: %s\n", file_red->i_file,
00632 filep->f_line, line);
00633 break;
00634
00635 case PRAGMA:
00636 case IDENT:
00637 case SCCS:
00638 case EJECT:
00639 break;
00640 case - 1:
00641 warning("%s", file_red->i_file);
00642 if (file_red != file)
00643 warning1(" (reading %s)", file->i_file);
00644 warning1(", line %d: unknown directive == \"%s\"\n",
00645 filep->f_line, line);
00646 break;
00647 case - 2:
00648 warning("%s", file_red->i_file);
00649 if (file_red != file)
00650 warning1(" (reading %s)", file->i_file);
00651 warning1(", line %d: incomplete include == \"%s\"\n",
00652 filep->f_line, line);
00653 break;
00654 }
00655 }
00656 file->i_flags |= FINISHED;
00657 return(-1);
00658 }