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 }