1: /* $Header: depend.c,v 1.14 86/05/15 09:01:04 lepreau Exp $ */ 2: 3: /* 4: * Author: Peter J. Nicklin 5: */ 6: #include <ctype.h> 7: #include <stdio.h> 8: #include "Mkmf.h" 9: #include "dlist.h" 10: #include "hash.h" 11: #include "macro.h" 12: #include "null.h" 13: #include "path.h" 14: #include "slist.h" 15: #include "system.h" 16: #include "yesno.h" 17: 18: #define USRINCLUDE "/usr/include/" 19: #define CURINCLUDE "./" 20: #define TOLOWER(c) (isupper(c) ? tolower(c) : (c)) 21: #define SKIPWHITESPACE(c, f) while ((c = getc(f))==' ' || c=='\t'); ungetc(c,f); 22: 23: /* 24: * Include file state 25: */ 26: #define NOTFOUND 0 /* not found anywhere */ 27: #define EXTERNAL 1 /* not found in current directory */ 28: #define INTERNAL 2 /* found in current directory */ 29: #define FROMRULE 3 /* derived from tranformation rule */ 30: 31: /* 32: * Include files are stored in hash tables by direct chaining (See 33: * p. 134 in `The C Programming Language' by Kernighan and Ritchie). 34: * Included include files are also added to a singly-linked list 35: * attached to the hash table entry for the include file. 36: */ 37: static HASH *C_INCLUDETABLE = NULL; /* C include file hash table */ 38: static HASH *F_INCLUDETABLE = NULL; /* Fortran include file hash table */ 39: static HASH *P_INCLUDETABLE = NULL; /* Pascal include file hash table */ 40: /* 41: * Additional include directories are specified via the -I compiler 42: * command line option. These directories are stored in singly-linked lists. 43: * We also assume that the last look-up directory is "/usr/include". 44: */ 45: static SLIST *C_INCDIR; /* C include directories */ 46: static SLIST *F_INCDIR; /* Fortran include directories */ 47: static SLIST *P_INCDIR; /* Pascal include directories */ 48: 49: SLIST *EXTLIST; /* external header file name list */ 50: 51: extern char *PGN; /* program name */ 52: 53: /* 54: * addincdir() adds directories containing include files to the 55: * appropriate singly-linked list. The pathnames to the directories 56: * are derived from makefile macro definitions. 57: */ 58: void 59: addincdir() 60: { 61: extern HASH *MDEFTABLE; /* macro definition table */ 62: char *slappend(); /* append to singly-linked list */ 63: HASHBLK *htb; /* hash table entry block */ 64: HASHBLK *htlookup(); /* find hash table entry */ 65: int cleanup(); /* remove temporary makefile and exit */ 66: void getI(); /* get include directory pathnames */ 67: 68: /* C files */ 69: if ((htb = htlookup(MCFLAGS, MDEFTABLE)) != NULL) 70: getI(htb->h_key, htb->h_def, C_INCDIR); 71: if (slappend(USRINCLUDE, C_INCDIR) == NULL) 72: cleanup(); 73: 74: /* Fortran files */ 75: if ((htb = htlookup(MFFLAGS, MDEFTABLE)) != NULL) 76: getI(htb->h_key, htb->h_def, F_INCDIR); 77: if (slappend(USRINCLUDE, F_INCDIR) == NULL) 78: cleanup(); 79: 80: /* Pascal files */ 81: if ((htb = htlookup(MPFLAGS, MDEFTABLE)) != NULL) 82: getI(htb->h_key, htb->h_def, P_INCDIR); 83: if (slappend(USRINCLUDE, P_INCDIR) == NULL) 84: cleanup(); 85: } 86: 87: 88: 89: /* 90: * findinclude() tries to find the pathname of an include file. Returns 91: * integer INTERNAL if found in the current directory, EXTERNAL if found 92: * somewhere else, FROMRULE if derived from a transformation rule, 93: * otherwise NOTFOUND. The pathname is copied into incpath. 94: */ 95: #define LOCALDIR(f) (index(f, _PSC) == NULL) 96: #define INCLUDETYPE(f) ((index(f, _PSC) == NULL) ? INTERNAL : EXTERNAL) 97: 98: findinclude(incpath, incname, lastname, type) 99: char *incpath; /* pathname receiving buffer */ 100: register char *incname; /* include file name */ 101: char *lastname; /* file that includes incname */ 102: int type; /* file type */ 103: { 104: register char *pp; /* include file path pointer */ 105: char *index(); /* find occurrence of character */ 106: char *optpath(); /* optimize pathname */ 107: char *pathcat(); /* pathname concatenation */ 108: char *pathhead(); /* remove pathname tail */ 109: char *strcpy(); /* string copy */ 110: char *strpcpy(); /* string copy and update pointer */ 111: int lookuprule(); /* look up transformation rules */ 112: SLBLK *slb; /* singly-linked list block */ 113: SLIST *slist; /* include directory list pointer */ 114: 115: /* 116: * look in /usr/include only 117: */ 118: if (*incname == '<') 119: { 120: pp = strpcpy(incpath, USRINCLUDE); 121: for (incname++; *incname != '>'; incname++, pp++) 122: *pp = *incname; 123: *pp = '\0'; 124: return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND); 125: } 126: 127: /* 128: * look for an absolute include file name 129: */ 130: if (*incname == '/') 131: { 132: strcpy(incpath, incname); 133: return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND); 134: } 135: 136: /* 137: * look in current include directory to see if the file exists, 138: * or can be generated by a transformation rule in the current 139: * working directory. 140: */ 141: if (LOCALDIR(lastname)) 142: { 143: if (LOCALDIR(incname)) 144: { 145: if (lookuprule(incname, incpath) == YES) 146: return(FROMRULE); 147: } 148: strcpy(incpath, incname); 149: if (FILEXIST(incpath)) 150: return(INCLUDETYPE(incpath)); 151: } 152: else { 153: strcpy(incpath, lastname); 154: pathcat(incpath, pathhead(incpath), incname); 155: optpath(incpath); 156: if (FILEXIST(incpath)) 157: return(INCLUDETYPE(incpath)); 158: } 159: 160: /* 161: * search directory list 162: */ 163: switch (type) 164: { 165: case INCLUDE_C: 166: slist = C_INCDIR; 167: break; 168: case INCLUDE_FORTRAN: 169: slist = F_INCDIR; 170: break; 171: case INCLUDE_PASCAL: 172: slist = P_INCDIR; 173: break; 174: } 175: for (slb = slist->head; slb != NULL; slb = slb->next) 176: { 177: pp = strpcpy(incpath, slb->key); 178: strcpy(pp, incname); 179: optpath(incpath); 180: if (FILEXIST(incpath)) 181: return(INCLUDETYPE(incpath)); 182: } 183: return(NOTFOUND); 184: } 185: 186: 187: 188: /* 189: * getI() appends include directories found via the -I compiler option to 190: * a singly linked list. 191: */ 192: void 193: getI(mnam, mdef, slist) 194: char *mnam; /* compiler options macro name */ 195: char *mdef; /* compiler options macro definition */ 196: SLIST *slist; /* singly-linked list */ 197: { 198: char *gettoken(); /* get next token */ 199: char incpath[PATHSIZE]; /* include directory pathname buffer */ 200: char *slappend(); /* append to singly-linked list */ 201: char *strcat(); /* string concatenation */ 202: int cleanup(); /* remove temporary makefile and exit */ 203: 204: while ((mdef = gettoken(incpath, mdef)) != NULL) 205: if (incpath[0] == '-' && incpath[1] == 'I') 206: if (incpath[2] == '\0') /* -I dir option */ 207: { 208: if ((mdef = gettoken(incpath, mdef)) != NULL) 209: { 210: strcat(incpath, PATHSEP); 211: if (slappend(incpath, slist) == NULL) 212: cleanup(); 213: } 214: else { 215: warn2("missing include directory in %s %s", 216: mnam, "macro definition"); 217: break; 218: } 219: } 220: else { /* -Idir option */ 221: strcat(incpath+2, PATHSEP); 222: if (slappend(incpath+2, slist) == NULL) 223: cleanup(); 224: } 225: } 226: 227: 228: 229: /* 230: * getinclude() fetchs an include file name from a line of source code. 231: * /usr/include '<' and '>' delimiters remain with the filename to 232: * distinguish it from an include file in a local directory. Returns 233: * NO if syntax error, otherwise YES. 234: */ 235: getinclude(incname, curname, lineno, ifp) 236: char *curname; /* current file name */ 237: char *incname; /* include file name receiving buffer */ 238: int lineno; /* current line number */ 239: register FILE *ifp; /* input stream */ 240: { 241: register char *ip; /* include file name buffer pointer */ 242: register int c; /* current character */ 243: 244: SKIPWHITESPACE(c, ifp); 245: for (ip = incname; (c = getc(ifp)) != EOF; ip++) 246: { 247: *ip = c; 248: if (c == '\n' || c == '\t' || c == ' ' || c == ';' || c == ',') 249: { 250: ungetc(c, ifp); 251: break; 252: } 253: } 254: *ip = '\0'; 255: if ((*incname == '<' && ip[-1] != '>') || 256: (*incname == '\"' && ip[-1] != '\"') || 257: (*incname == '\'' && ip[-1] != '\'') || 258: (*incname == '(' && ip[-1] != ')')) 259: { 260: fprintf(stderr, 261: "%s: \"%s\", line %d: bad include syntax for %s\n", 262: PGN, curname, lineno, incname); 263: return(NO); 264: } 265: if (*incname == '\"' || *incname == '\'' || *incname == '(') 266: { 267: ip[-1] = '\0'; 268: ip = incname + 1; 269: while (*incname++ = *ip++) 270: continue; 271: } 272: return(YES); 273: } 274: 275: 276: 277: /* 278: * inclink() stores a pointer to a hash table block (which contains 279: * include file information) somewhere. Returns a pointer to the somewhere, 280: * or calls cleanup() if out of memory. 281: */ 282: INCBLK * 283: inclink(htb) 284: HASHBLK *htb; /* hash table block pointer to save */ 285: { 286: char *malloc(); /* memory allocator */ 287: INCBLK *iblk; /* pointer to new include chain block */ 288: int cleanup(); /* remove temporary makefile and exit */ 289: 290: if ((iblk = (INCBLK *) malloc(sizeof(INCBLK))) == NULL) 291: { 292: warn("out of memory"); 293: cleanup(); 294: } 295: iblk->i_loop = NO; 296: iblk->i_hblk = htb; 297: iblk->i_next = NULL; 298: return(iblk); 299: } 300: 301: 302: 303: /* 304: * instalinclude() adds an include file name to the appropriate include 305: * file hash table. Returns a pointer to the hash table block, or calls 306: * cleanup() if out of memory. 307: */ 308: HASHBLK * 309: instalinclude(incname, incpath, type) 310: char *incname; /* name of include file */ 311: char *incpath; /* path to include file */ 312: int type; /* type of source file */ 313: { 314: HASH *htinit(); /* initialize hash table */ 315: HASHBLK *htb = NULL; /* hash table block */ 316: HASHBLK *htinstall(); /* install hash table entry */ 317: int cleanup(); /* remove temporary makefile and exit */ 318: int ilen; /* include path length */ 319: int strlen(); /* string length */ 320: 321: ilen = strlen(incpath); 322: switch (type) 323: { 324: case INCLUDE_C: 325: if (C_INCLUDETABLE == NULL) 326: { 327: C_INCLUDETABLE = htinit(INCLUDETABLESIZE); 328: } 329: htb = htinstall(incname, incpath, ilen, C_INCLUDETABLE); 330: break; 331: case INCLUDE_FORTRAN: 332: if (F_INCLUDETABLE == NULL) 333: { 334: F_INCLUDETABLE = htinit(INCLUDETABLESIZE); 335: } 336: htb = htinstall(incname, incpath, ilen, F_INCLUDETABLE); 337: break; 338: case INCLUDE_PASCAL: 339: if (P_INCLUDETABLE == NULL) 340: { 341: P_INCLUDETABLE = htinit(INCLUDETABLESIZE); 342: } 343: htb = htinstall(incname, incpath, ilen, P_INCLUDETABLE); 344: break; 345: } 346: if (htb == NULL) 347: cleanup(); 348: return(htb); 349: } 350: 351: 352: 353: /* 354: * lookupinclude() returns a pointer to an include hash table block 355: * corresponding to incname and type. Returns null if not found. 356: */ 357: HASHBLK * 358: lookupinclude(incname, type) 359: char *incname; /* name of include file */ 360: int type; /* type of source file */ 361: { 362: HASH *includetable = NULL; /* include file hash table */ 363: HASHBLK *htlookup(); /* find hash table entry */ 364: 365: switch (type) 366: { 367: case INCLUDE_C: 368: includetable = C_INCLUDETABLE; 369: break; 370: case INCLUDE_FORTRAN: 371: includetable = F_INCLUDETABLE; 372: break; 373: case INCLUDE_PASCAL: 374: includetable = P_INCLUDETABLE; 375: break; 376: } 377: return((includetable == NULL) ? NULL : htlookup(incname, includetable)); 378: } 379: 380: 381: 382: /* 383: * mkdepend() creates include file dependencies for object files and installs 384: * them to dependency list dlp. Returns a pointer to the dependency list. 385: */ 386: DLIST * 387: mkdepend() 388: { 389: extern SLIST *SRCLIST; /* source file name list */ 390: char *rindex(); /* find last occurrence of character */ 391: char *suffix; /* suffix pointer */ 392: DLBLK *dlappend(); /* append dependency list */ 393: DLIST *dlinit(); /* initialize dependency list */ 394: DLIST *dlist; /* dependency list */ 395: INCBLK *ibp; /* pointer to chain of include files */ 396: INCBLK *readC(); /* read C include-style files */ 397: INCBLK *readF(); /* read Fortran include-style files */ 398: INCBLK *readP(); /* read Pascal include-style files */ 399: int cleanup(); /* remove temporary makefile and exit */ 400: int lookuptypeofinclude(); /* look up the brand of include */ 401: int slsort(); /* sort singly-linked list */ 402: int strcmp(); /* string comparison */ 403: int type; /* source file type */ 404: SLBLK *lbp; /* list block pointer */ 405: SLIST *slinit(); /* initialize singly-linked list */ 406: void addincdir(); /* add to list of include directories */ 407: void rmprinttag(); /* remove "already printed" tags */ 408: 409: /* initialize include file look-up lists */ 410: C_INCDIR = slinit(); 411: F_INCDIR = slinit(); 412: P_INCDIR = slinit(); 413: 414: /* add additional include directories */ 415: addincdir(); 416: 417: /* initialize external header file name list */ 418: EXTLIST = slinit(); 419: 420: /* initialize dependency list */ 421: dlist = dlinit(); 422: 423: for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next) 424: { 425: suffix = rindex(lbp->key, '.'); 426: type = lookuptypeofinclude(++suffix); 427: switch (type) 428: { 429: case INCLUDE_C: 430: ibp = readC(lbp->key, 0, lbp->key); 431: break; 432: case INCLUDE_FORTRAN: 433: ibp = readF(lbp->key, 0, lbp->key); 434: break; 435: case INCLUDE_PASCAL: 436: ibp = readP(lbp->key, 0, lbp->key); 437: break; 438: case INCLUDE_NONE: 439: ibp = NULL; 440: break; 441: } 442: if (ibp != NULL) 443: { 444: if (dlappend(type, lbp, ibp, dlist) == NULL) 445: cleanup(); 446: } 447: } 448: if (slsort(strcmp, EXTLIST) == NO) 449: cleanup(); 450: return(dlist); 451: } 452: 453: 454: 455: /* 456: * notfound() prints a "can't find" filename error message. 457: */ 458: void 459: notfound(curname, lineno, incname) 460: char *curname; /* current file name */ 461: char *incname; /* name of include file */ 462: int lineno; /* current line number */ 463: { 464: if (PGN != NULL && *PGN != '\0') 465: { 466: fprintf(stderr, "%s: ", PGN); 467: } 468: if (*incname == '<') 469: { 470: fprintf(stderr, "\"%s\", line %d: can't find %s\n", 471: curname, lineno, incname); 472: } 473: else { 474: fprintf(stderr, "\"%s\", line %d: can't find \"%s\"\n", 475: curname, lineno, incname); 476: } 477: } 478: 479: 480: 481: /* 482: * readC() searches C files for included files. Returns a pointer to 483: * the chain of include files installed or found in the include file 484: * hash table, or null if no include files found. 485: */ 486: INCBLK * 487: readC(lastfile, lastline, curname) 488: char *lastfile; /* parent file name */ 489: int lastline; /* current line in parent file */ 490: char *curname; /* current file name */ 491: { 492: register char *p; /* include string pointer */ 493: register FILE *ifp; /* input file stream */ 494: register int c; /* current character */ 495: char incname[PATHSIZE]; /* name of include file */ 496: char incpath[PATHSIZE]; /* path to include file */ 497: char *slappend(); /* append pathname to list */ 498: FILE *fopen(); /* open file */ 499: HASHBLK *ftb; /* fromrule hash table entry block */ 500: HASHBLK *htb = NULL; /* hash table entry block */ 501: HASHBLK *instalinclude(); /* install include name in hash table */ 502: HASHBLK *lookupinclude(); /* look up include in hash table */ 503: INCBLK *i_head = NULL; /* head of include chain */ 504: INCBLK *i_tail = NULL; /* tail of include chain */ 505: INCBLK *inclink(); /* link include file hash blocks */ 506: int cleanup(); /* remove temporary makefile and exit */ 507: int findinclude(); /* locate include file */ 508: int getinclude(); /* get include name from input line */ 509: int inctype; /* origin of include file */ 510: int lineno = 1; /* current line number */ 511: int strlen(); /* string length */ 512: int type; /* file type */ 513: void notfound(); /* print "can't find" filename msg */ 514: 515: type = INCLUDE_C; 516: 517: if ((ifp = fopen(curname, "r")) == NULL) 518: { 519: if (lastline > 0) 520: fprintf(stderr, "%s: \"%s\", line %d: ", PGN, 521: lastfile, lastline); 522: else 523: fprintf(stderr, "%s: ", PGN); 524: perror(curname); 525: return(NULL); 526: } 527: while ((c = getc(ifp)) != EOF) 528: { 529: if (c != '#') 530: goto nextline; 531: SKIPWHITESPACE(c, ifp); 532: for (p = "include"; (c = getc(ifp)) == *p && *p != '\0' ; p++) 533: continue; 534: if (*p != '\0') 535: goto nextline; 536: if (getinclude(incname, curname, lineno, ifp) == NO) 537: goto nextline; 538: if ((htb = lookupinclude(incname, type)) == NULL) 539: { 540: inctype = findinclude(incpath, incname, curname, type); 541: if (inctype == INTERNAL) 542: { 543: htb = instalinclude(incname, incpath, type); 544: } 545: else if (inctype == EXTERNAL) 546: { 547: htb = instalinclude(incname, incpath, type); 548: if (slappend(incpath, EXTLIST) == NULL) 549: cleanup(); 550: } 551: else if (inctype == FROMRULE) 552: { 553: htb = instalinclude(incname, incname, type); 554: ftb = instalinclude(incpath, incpath, type); 555: } 556: else { 557: notfound(curname, lineno, incname); 558: goto nextline; 559: } 560: 561: /* look for nested include files */ 562: htb->h_sub = readC(curname, lineno, incpath); 563: 564: if (inctype == FROMRULE) 565: ftb->h_sub = htb->h_sub; 566: } 567: if (i_tail == NULL) 568: { 569: i_head = i_tail = inclink(htb); 570: } 571: else { 572: i_tail = i_tail->i_next = inclink(htb); 573: } 574: nextline: while (c != '\n' && c != EOF) 575: c = getc(ifp); 576: lineno++; 577: } 578: fclose(ifp); 579: return(i_head); 580: } 581: 582: 583: 584: /* 585: * readF() searches Fortran files for included files. Returns a pointer 586: * to the chain of include files installed or found in the include file 587: * hash table, or null if no include files found. 588: */ 589: INCBLK * 590: readF(lastfile, lastline, curname) 591: char *lastfile; /* parent file name */ 592: int lastline; /* current line in parent file */ 593: char *curname; /* current file name */ 594: { 595: register char *p; /* include string pointer */ 596: register FILE *ifp; /* input file stream */ 597: register int c; /* current character */ 598: char incname[PATHSIZE]; /* name of include file */ 599: char incpath[PATHSIZE]; /* path to include file */ 600: char *slappend(); /* append pathname to list */ 601: FILE *fopen(); /* open file */ 602: HASHBLK *ftb; /* fromrule hash table entry block */ 603: HASHBLK *htb = NULL; /* hash table entry block */ 604: HASHBLK *instalinclude(); /* install include name in hash table */ 605: HASHBLK *lookupinclude(); /* look up include in hash table */ 606: INCBLK *i_head = NULL; /* head of include chain */ 607: INCBLK *i_tail = NULL; /* tail of include chain */ 608: INCBLK *inclink(); /* link include file hash blocks */ 609: int cleanup(); /* remove temporary makefile and exit */ 610: int findinclude(); /* locate include file */ 611: int getinclude(); /* get include name from input line */ 612: int inctype; /* origin of include file */ 613: int lineno = 1; /* current line number */ 614: int strlen(); /* string length */ 615: int type; /* file type */ 616: void notfound(); /* print "can't find" filename msg */ 617: 618: type = INCLUDE_FORTRAN; 619: 620: if ((ifp = fopen(curname, "r")) == NULL) 621: { 622: if (lastline > 0) 623: fprintf(stderr, "%s: \"%s\", line %d: ", PGN, 624: lastfile, lastline); 625: else 626: fprintf(stderr, "%s: ", PGN); 627: perror(curname); 628: return(NULL); 629: } 630: while ((c = getc(ifp)) != EOF) 631: { 632: if (c == 'c' || c == 'C' || c == '*' || c == '\n') 633: goto nextline; 634: while ((c = getc(ifp)) == ' ' || c == '\t') 635: continue; 636: for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++) 637: c = getc(ifp); 638: if (*p != '\0') 639: goto nextline; 640: if (getinclude(incname, curname, lineno, ifp) == NO) 641: goto nextline; 642: if ((htb = lookupinclude(incname, type)) == NULL) 643: { 644: inctype = findinclude(incpath, incname, curname, type); 645: if (inctype == INTERNAL) 646: { 647: htb = instalinclude(incname, incpath, type); 648: } 649: else if (inctype == EXTERNAL) 650: { 651: htb = instalinclude(incname, incpath, type); 652: if (slappend(incpath, EXTLIST) == NULL) 653: cleanup(); 654: } 655: else if (inctype == FROMRULE) 656: { 657: htb = instalinclude(incname, incname, type); 658: ftb = instalinclude(incpath, incpath, type); 659: } 660: else { 661: notfound(curname, lineno, incname); 662: goto nextline; 663: } 664: 665: /* look for nested include files */ 666: htb->h_sub = readF(curname, lineno, incpath); 667: 668: if (inctype == FROMRULE) 669: ftb->h_sub = htb->h_sub; 670: } 671: if (i_tail == NULL) 672: { 673: i_head = i_tail = inclink(htb); 674: } 675: else { 676: i_tail = i_tail->i_next = inclink(htb); 677: } 678: nextline: while (c != '\n' && c != EOF) 679: c = getc(ifp); 680: lineno++; 681: } 682: fclose(ifp); 683: return(i_head); 684: } 685: 686: 687: 688: /* 689: * readP() searches Pascal files for included files. Returns a pointer 690: * to the chain of include files installed or found in the include file 691: * hash table, or null if no include files found. 692: */ 693: INCBLK * 694: readP(lastfile, lastline, curname) 695: char *lastfile; /* parent file name */ 696: int lastline; /* current line in parent file */ 697: char *curname; /* current file name */ 698: { 699: register char *p; /* include string pointer */ 700: register FILE *ifp; /* input file stream */ 701: register int c; /* current character */ 702: char incname[PATHSIZE]; /* name of include file */ 703: char incpath[PATHSIZE]; /* path to include file */ 704: char *slappend(); /* append pathname to list */ 705: FILE *fopen(); /* open file */ 706: HASHBLK *ftb; /* fromrule hash table entry block */ 707: HASHBLK *htb = NULL; /* hash table entry block */ 708: HASHBLK *instalinclude(); /* install include name in hash table */ 709: HASHBLK *lookupinclude(); /* look up include in hash table */ 710: INCBLK *i_head = NULL; /* head of include chain */ 711: INCBLK *i_tail = NULL; /* tail of include chain */ 712: INCBLK *inclink(); /* link include file hash blocks */ 713: int cleanup(); /* remove temporary makefile and exit */ 714: int findinclude(); /* locate include file */ 715: int getinclude(); /* get include name from input line */ 716: int inctype; /* origin of include file */ 717: int lineno = 1; /* current line number */ 718: int strlen(); /* string length */ 719: int type; /* file type */ 720: void notfound(); /* print "can't find" filename msg */ 721: 722: type = INCLUDE_PASCAL; 723: 724: if ((ifp = fopen(curname, "r")) == NULL) 725: { 726: if (lastline > 0) 727: fprintf(stderr, "%s: \"%s\", line %d: ", PGN, 728: lastfile, lastline); 729: else 730: fprintf(stderr, "%s: ", PGN); 731: perror(curname); 732: return(NULL); 733: } 734: while ((c = getc(ifp)) != EOF) 735: { 736: if (c != '#') 737: goto nextline; 738: while ((c = getc(ifp)) == ' ' || c == '\t') 739: continue; 740: for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++) 741: c = getc(ifp); 742: if (*p != '\0') 743: goto nextline; 744: if (getinclude(incname, curname, lineno, ifp) == NO) 745: goto nextline; 746: if ((htb = lookupinclude(incname, type)) == NULL) 747: { 748: inctype = findinclude(incpath, incname, curname, type); 749: if (inctype == INTERNAL) 750: { 751: htb = instalinclude(incname, incpath, type); 752: } 753: else if (inctype == EXTERNAL) 754: { 755: htb = instalinclude(incname, incpath, type); 756: if (slappend(incpath, EXTLIST) == NULL) 757: cleanup(); 758: } 759: else if (inctype == FROMRULE) 760: { 761: htb = instalinclude(incname, incname, type); 762: ftb = instalinclude(incpath, incpath, type); 763: } 764: else { 765: notfound(curname, lineno, incname); 766: goto nextline; 767: } 768: 769: /* look for nested include files */ 770: htb->h_sub = readP(curname, lineno, incpath); 771: 772: if (inctype == FROMRULE) 773: ftb->h_sub = htb->h_sub; 774: } 775: if (i_tail == NULL) 776: { 777: i_head = i_tail = inclink(htb); 778: } 779: else { 780: i_tail = i_tail->i_next = inclink(htb); 781: } 782: nextline: while (c != '\n' && c != EOF) 783: c = getc(ifp); 784: lineno++; 785: } 786: fclose(ifp); 787: return(i_head); 788: }