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: }

Defined functions

addincdir defined in line 58; used 2 times
findinclude defined in line 98; used 6 times
getI defined in line 192; used 4 times
getinclude defined in line 235; used 6 times
inclink defined in line 282; used 9 times
instalinclude defined in line 308; used 15 times
lookupinclude defined in line 357; used 10 times
mkdepend defined in line 386; used 2 times
notfound defined in line 458; used 6 times
readC defined in line 486; used 3 times
readF defined in line 589; used 3 times
readP defined in line 693; used 3 times

Defined variables

C_INCDIR defined in line 45; used 4 times
C_INCLUDETABLE defined in line 37; used 4 times
EXTLIST defined in line 49; used 5 times
F_INCDIR defined in line 46; used 4 times
F_INCLUDETABLE defined in line 38; used 4 times
P_INCDIR defined in line 47; used 4 times
P_INCLUDETABLE defined in line 39; used 4 times

Defined macros

CURINCLUDE defined in line 19; never used
EXTERNAL defined in line 27; used 6 times
FROMRULE defined in line 29; used 7 times
INCLUDETYPE defined in line 96; used 3 times
INTERNAL defined in line 28; used 4 times
LOCALDIR defined in line 95; used 2 times
NOTFOUND defined in line 26; used 3 times
SKIPWHITESPACE defined in line 21; used 2 times
TOLOWER defined in line 20; used 2 times
USRINCLUDE defined in line 18; used 4 times
Last modified: 1986-05-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2265
Valid CSS Valid XHTML 1.0 Strict