home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / dmake_440.lzh / DMake / main.c < prev    next >
C/C++ Source or Header  |  1991-01-19  |  33KB  |  1,283 lines

  1.  
  2. /*
  3.  *  DMAKE.C
  4.  *
  5.  *  (c)Copyright 1989 by Matthew Dillon, All Rights Reserved.
  6.  *
  7.  *    ONLY AN APPROPRIATE AMIGA EXECUTABLE MAY BE DISTRIBUTED.  DO
  8.  *    NOT DISTRIBUTE SOURCE!
  9.  *
  10.  *  This is a new try at makefiles ...    read the documentation.
  11.  */
  12.  
  13. #include "defs.h"
  14.  
  15.  
  16. MLIST    DepList;    /*    Dependancies    */
  17.  
  18. short Verbose;
  19. short Silent;
  20. short LineNo;
  21. short XDebug;
  22. short ForceAll;
  23. short ListOnly;
  24. short Order;
  25. long  SaveLock;
  26. char MakeFile[128];
  27.  
  28. main(ac, av)
  29. char *av[];
  30. {
  31.     short dofirst = 1;
  32.     short error = 0;
  33.  
  34.  
  35.     NewList(&DepList);
  36.     strcpy(MakeFile, "DMakefile");
  37.  
  38.     SaveLock = CurrentDir(Lock("", SHARED_LOCK));
  39.     {
  40.     register short i;
  41.     short notenoughargs = 0;
  42.     for (i = 1; i < ac; ++i) {
  43.         register char *ptr = av[i];
  44.         if (*ptr != '-')
  45.         continue;
  46.         while (*++ptr) {
  47.         switch(*ptr) {
  48.         case 's':
  49.             ++Silent;
  50.             break;
  51.         case 'v':
  52.             ++Verbose;
  53.             break;
  54.         case 'd':
  55.             ++XDebug;
  56.             break;
  57.         case 'n':
  58.             ListOnly = 1;
  59.             break;
  60.         case 'a':
  61.             ForceAll = 1;
  62.             break;
  63.         case 'f':
  64.             if (i + 1 < ac) {
  65.             strcpy(MakeFile, av[++i]);
  66.             av[i][0] = '-'; /* kill it */
  67.             } else {
  68.             notenoughargs = 1;
  69.             }
  70.             break;
  71.         }
  72.         }
  73.     }
  74.     if (notenoughargs) {
  75.         puts("Not enough args for option!");
  76.         xexit(20);
  77.     }
  78.     }
  79.     if (!Silent) {
  80.     puts("DMake Beta V0.6 26-Jan-89");
  81.     puts("(c)Copyright 1989 by Matthew Dillon, All Rights Reserved");
  82.     }
  83.     {
  84.     FILE *fi;
  85.     if (fi = fopen(MakeFile, "r")) {
  86.         ScanFile(fi);
  87.         fclose(fi);
  88.     } else {
  89.         printf("Unable to open %s\n", MakeFile);
  90.         xexit(25);
  91.     }
  92.     }
  93.     {
  94.     register short i;
  95.     for (i = 1; i < ac; ++i) {
  96.         register char *ptr = av[i];
  97.         register DEPEND *dep;
  98.         if (*ptr == '-')
  99.         continue;
  100.         dofirst = 0;
  101.         for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
  102.         if (strcmp(ptr, dep->Left) == 0) {
  103.             /* XXX ? */
  104.             Order = FindBeginPoint(dep, Order, 1);
  105.             break;
  106.         }
  107.         }
  108.         if (dep == NULL) {
  109.         printf("Could not find %s dependancy\n", ptr);
  110.         error = 10;
  111.         }
  112.     }
  113.     }
  114.     if (dofirst) {
  115.     register DEPEND *dep = GetHead(&DepList);
  116.     if (dep)
  117.         Order = FindBeginPoint(dep, Order, 1);
  118.     }
  119.     CombineRefCnts(NULL);
  120.     if (XDebug)
  121.     PrintDepList(&DepList);
  122.     ExecuteDepList();
  123.     xexit(error);
  124. }
  125.  
  126. xexit(error)
  127. {
  128.     UnLock(CurrentDir(SaveLock));
  129.     exit(error);
  130. }
  131.  
  132. ScanFile(fi)
  133. FILE *fi;
  134. {
  135.     char *ptr;
  136.  
  137.     LineNo = 0;
  138.     while (ptr = getline(fi, NULL)) {
  139.     MLIST    *cmdlist = malloc(sizeof(MLIST));
  140.     NewList(cmdlist);
  141.  
  142.     ++LineNo;
  143.     if (*ptr == 0) {
  144.         free(cmdlist);
  145.         continue;
  146.     }
  147.     {
  148.         register char *str = ptr;
  149.         while ((*str >= 'a' && *str <= 'z') || (*str >= 'A' && *str <= 'Z') ||
  150.             (*str >= '0' && *str <= '9') ||
  151.             *str == '_' || *str == ' ' || *str == '\t')
  152.         ++str;
  153.         if (*str == '=') {      /* macro assignment */
  154.         MacroAssign(ptr, str);
  155.         continue;
  156.         }
  157.     }
  158.     {
  159.         short ac;
  160.         register char **av;
  161.         register short i;
  162.  
  163.         av = parseline(ptr, &ac);
  164.         for (i = 0; i < ac; ++i) {
  165.         if (av[i][0] == ':' && av[i][1] == 0)
  166.             break;
  167.         }
  168.         if (i == ac) {  /*  could be blah:  */
  169.         register char *str = av[0];
  170.         register short len = strlen(str);
  171.         if (len && str[len-1] == ':') {     /*  blah:   */
  172.             str[len-1] = 0;
  173.             CreateDependancies(cmdlist, av, 0, 1, 1, ac);
  174.         } else {
  175.             short cmmnt;
  176.             printf("Badly formed command line %ld\n", LineNo);
  177.             while (ptr = getline(fi, &cmmnt)) {
  178.             if (ptr[0] == 0 && !cmmnt)
  179.                 break;
  180.             }
  181.         }
  182.         } else {
  183.         CreateDependancies(cmdlist, av, 0, i, i + 1, ac);
  184.         }
  185.     }
  186.     {
  187.         register NODE *node;
  188.         short cmmnt;
  189.         while (ptr = getline(fi, &cmmnt)) {
  190.         if (ptr[0] == 0 && !cmmnt)
  191.             break;
  192.         if (ptr[0]) {
  193.             node = malloc(sizeof(NODE) + strlen(ptr) + 1);
  194.             node->ln_Name = (char *)(node + 1);
  195.             strcpy(node->ln_Name, ptr);
  196.             AddTail(cmdlist, node);
  197.         }
  198.         }
  199.     }
  200.     }
  201.     if (XDebug)
  202.     PrintDepList(&DepList);
  203. }
  204.  
  205. /*
  206.  *  COMBINEREFCNTS()
  207.  *
  208.  *  All dependancies with the same left hand side are supposed to have
  209.  *  the same (shared) common structure.  This ensures they do and is
  210.  *  called after operations which might invalidate the rule.
  211.  */
  212.  
  213. CombineRefCnts(newlist)
  214. MLIST *newlist;
  215. {
  216.     register DEPEND *d1, *d2;
  217.  
  218.     /*
  219.      *    First combine references within a new list, then combine references
  220.      *    from the new list to the master list, then combine references in
  221.      *    the master list.
  222.      */
  223.  
  224.     if (newlist) {
  225.     for (d1 = GetHead(newlist); d1; d1 = GetSucc(d1)) {
  226.         for (d2 = GetSucc(d1); d2; d2 = GetSucc(d2)) {
  227.         if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
  228.             Combine(d1, d2);
  229.         }
  230.     }
  231.     for (d1 = GetHead(newlist); d1; d1 = GetSucc(d1)) {
  232.         for (d2 = GetHead(&DepList); d2; d2 = GetSucc(d2)) {
  233.         if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
  234.             Combine(d1, d2);    /*  deplist's gets it   */
  235.         }
  236.     }
  237.     }
  238.     for (d1 = GetHead(&DepList); d1; d1 = GetSucc(d1)) {
  239.     for (d2 = GetSucc(d1); d2; d2 = GetSucc(d2)) {
  240.         if (strcmp(d1->Left, d2->Left) == 0 && d1->Common != d2->Common)
  241.         Combine(d1, d2);
  242.     }
  243.     }
  244. }
  245.  
  246. Combine(d1, d2)
  247. DEPEND *d1, *d2;
  248. {
  249.     register COMMON *c1 = d1->Common;
  250.     register COMMON *c2 = d2->Common;
  251.  
  252.     if (XDebug) {
  253.     printf("Combine (%s : %s -> %s : %s) com %08lx %08lx (%ld+%ld) %02lx|%02lx\n",
  254.         d1->Left, d1->Right, d2->Left, d2->Right, c1, c2,
  255.         c1->RefCnt, c2->RefCnt,
  256.         c1->Flags, c2->Flags
  257.     );
  258.     }
  259.     c2->RefCnt += c1->RefCnt;
  260.     c2->Flags  |= c1->Flags;
  261.     c1->RefCnt = 0;
  262.     c1->Flags  = 0;
  263.     d1->Common = c2;
  264. }
  265.  
  266. /*
  267.  *  FINDBEGINPOINT()
  268.  *
  269.  *  The specified left side was requested to execute.  Search the list for
  270.  *  common points (left side the same)
  271.  *
  272.  *  Find those entries whos left sides match this entry's right side
  273.  *  (depth first, recursively) and assign an ordering number.  The ordering
  274.  *  number is essential to guarentee proper execution order of dependancies
  275.  *  since their list positions are random.
  276.  */
  277.  
  278. FindBeginPoint(db, order, add)
  279. register DEPEND *db;
  280. {
  281.     register DEPEND *dep;
  282.  
  283.     db->Flags |= DF_ALLOWED;
  284.     db->Order = order;
  285.     order += add;
  286.  
  287.     for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
  288.     if (dep->Flags & DF_ALLOWED)
  289.         continue;
  290.     if (strcmp(dep->Left, db->Right) == 0)
  291.         order = FindBeginPoint(dep, order, add);  /*  DEPTH FIRST    */
  292.     }
  293.     for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
  294.     if (dep->Flags & DF_ALLOWED)
  295.         continue;
  296.     if (dep->Common == db->Common)                /*  BREADTH SECOND */
  297.         order = FindBeginPoint(dep, order, add);
  298.     }
  299.     return(order);
  300. }
  301.  
  302. /*
  303.  *  EXECUTEDEPLIST()
  304.  *                MAIN EXECUTION LOOP
  305.  *
  306.  *  This is the main execution loop for DMake.    It scans the dependancy
  307.  *  list calling appropriate functions, determining associations, and
  308.  *  doing timestamp comparisons if necessary.
  309.  *
  310.  *  (1) For all dependancies which have yet to be handled by this loop
  311.  *    (DF_DIDTHIS is NOT set).
  312.  *
  313.  *    (i) does the right side exist as the left side of some other
  314.  *        dependancy?  If not
  315.  *
  316.  *    (ii) unless forced or a wildcard, check the file timestamps
  317.  *         on the left vs right side and set appropriate flags.
  318.  *
  319.  *  (2) Execution phase.  Take the highest priority (lowest Ordered)
  320.  *    dependancy and attempt to execute it.    Collect all dependancies
  321.  *    with a common left side.  At this time any dependancies marked
  322.  *    DF_EXPANDRIGHT must be expanded (this may result in the reference
  323.  *    count becomming non-zero in which case we must abort the execution
  324.  *    phase until the new dependancies have been resolved).
  325.  *
  326.  *    If all non-special (the 'meat', not the exhausted wildcarded
  327.  *    dependancies) timestamp flag checks out, execute the command
  328.  *    list.
  329.  *
  330.  *
  331.  */
  332.  
  333. ExecuteDepList()
  334. {
  335.     register DEPEND *dep, *dp;
  336.     register short changed = 1;
  337.     DEPEND *lowdep;
  338.  
  339.     if (Verbose == 1) {
  340.     puts("\nINITIAL DEPLIST");
  341.     PrintDepList(&DepList);
  342.     puts("");
  343.     }
  344.  
  345.     if (XDebug)
  346.     puts("ExecuteDepList");
  347.     while (changed) {
  348.     char identchanged = 1;
  349.  
  350.     /*
  351.      *  (1) Determine highest priority ready dependancy to execute and
  352.      *    handle datestamp checking.
  353.      */
  354.  
  355.     changed = 0;
  356.     if (XDebug)
  357.         puts("while-changed-loop");
  358.     while (identchanged) {
  359.         if (XDebug)
  360.         puts("while-ident-changed-loop");
  361.         identchanged = 0;
  362.         lowdep = NULL;
  363.         for (dep = GetHead(&DepList); dep; dep = GetSucc(dep)) {
  364.         if (dep->Common->RefCnt < 0 || !(dep->Flags & DF_ALLOWED))
  365.             continue;
  366.         if (!(dep->Flags & DF_DIDTHIS)) {
  367.             /*
  368.              *    (i) does the right side exist as the left side of
  369.              *        some other dependancy?  If not, decrement the
  370.              *        reference count and if a wildcard handle
  371.              *        expansion.
  372.              */
  373.  
  374.             for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
  375.             if (strcmp(dep->Right, dp->Left) == 0)
  376.                 break;    /* valid references exist   */
  377.             }
  378.  
  379.  
  380.             if (dp == NULL) { /* don't exist, dec. ref cnt*/
  381.             identchanged = 1;
  382.  
  383.             --dep->Common->RefCnt;
  384.             dep->Flags |= DF_DIDTHIS;
  385.             if (XDebug)
  386.                 printf("EDL1: DECREMENT REF: %s : %s (%08lx) -> %ld\n",
  387.                 dep->Left, dep->Right, dep->Common, dep->Common->RefCnt
  388.                 );
  389.  
  390.             /*
  391.              *  handling expansion.  If the right side is a wild
  392.              *  card defer expansion until the execution phase
  393.              *  (2).  This is in case files have yet to be
  394.              *  created that will effect the expansion.  If not
  395.              *  a wildcard, and not APPLYALL, then we must
  396.              *  expand the left side (a rare occurance but what
  397.              *  if somebody does this?:  *.c : charlie)
  398.              */
  399.  
  400.             if (IsWildCard(dep->Right))   /* defer expansion unless a-a */
  401.                 dep->Flags |= DF_EXPANDRIGHT;
  402.             else if (dep->Common->RefCnt == 0) {
  403.                 if (IsWildCard(dep->Left) && !(dep->Flags & DF_APPLYALL))
  404.                 DirectoryWildScan(dep, NULL, 1);
  405.                 else
  406.                 ;/*AddCollect(dep, dep);*/
  407.             }
  408.             }
  409.  
  410.            /*
  411.             *    (ii)
  412.             *  Unless forced or a wildcard, we do a time-date comparison
  413.             *  on the left and right side.  If the right side does not
  414.             *  exist as a file, nothing changes.  If the right side
  415.             *  DOES exist as a file, the time-date comparison overides
  416.             *  anything propogated from below.    This allows:
  417.             *
  418.             *  $(OBJS) : $(SRCS)
  419.             *       cc ..
  420.             *
  421.             *  $(SRCS) : ram:symbols.m
  422.             */
  423.  
  424.             if (!(dep->Flags & DF_OUTDATED) && !ForceAll && IsWildCard(dep->Left) == 0) {
  425.             short validright;
  426.             short od = OutDated(dep->Left, dep->Right, &validright);
  427.  
  428.             if (Verbose == 2)
  429.                 printf("COMPARE %s : %s, od = %ld  vr = %ld\n", dep->Left, dep->Right, od, validright);
  430.             if (validright && !(dep->Flags & DF_OUTDATED)) {
  431.                 if (od)
  432.                 dep->Flags |= DF_OUTDATED;
  433.                 else
  434.                 dep->Flags |= DF_DATEDOK;
  435.             }
  436.             }
  437.         }
  438.         if (dep->Common->RefCnt != 0)
  439.             continue;
  440.         if (lowdep == NULL || dep->Order < lowdep->Order)
  441.             lowdep = dep;
  442.         }
  443.     }
  444.     if (Verbose == 1) {
  445.         puts("\nSTABLE DEPLIST:");
  446.         PrintDepList(&DepList);
  447.         puts("");
  448.     }
  449.  
  450.     /*
  451.      *  (2) Execution phase.                    **************
  452.      *
  453.      */
  454.  
  455.     dep = lowdep;
  456.     if (dep == NULL || dep->Common->RefCnt != 0)
  457.         continue;
  458.     changed = 1;
  459.  
  460.     if (Verbose)
  461.         printf("PICKED: %s : %s (seq# %d)\n", dep->Left, dep->Right, dep->Order);
  462.  
  463.     /*
  464.      *  References have fallen to zero.  We must scan the dependancies
  465.      *  for all common nodes (common to left hand side), combine
  466.      *  various collected variables (i.e. *.c etc..) and do a single
  467.      *  execution run.
  468.      *
  469.      *  But, if a right hand side is a wildcard and therefore has
  470.      *  not been determined yet, we must do a DirectoryWildScan()
  471.      *  and if the refcnt is no longer 0 abort the execution.
  472.      */
  473.  
  474.     if (XDebug) {
  475.         printf("\nEDL: Refs have fallen to 0 %s : %s (%08lx)\n",
  476.         dep->Left, dep->Right, dep->Common
  477.         );
  478.         PrintDepList(&DepList);
  479.     }
  480.  
  481.     {
  482.         MLIST exelist;
  483.         DEPEND *nextdp;
  484.         char numdatedok = 0;
  485.         char numdeps    = 0;
  486.  
  487.         NewList(&exelist);
  488.         for (dp = GetHead(&DepList); dp; dp = nextdp) {
  489.         nextdp = GetSucc(dp);
  490.  
  491.         /*
  492.          *  Gather the common entries together into a list.
  493.          *  Look at the time stamp information and handle that.
  494.          *  Collect all non-wildcarded entries into a separate list
  495.          *  in preparation for execution.
  496.          */
  497.  
  498.         if (dep->Common == dp->Common && (dp->Flags & DF_DIDTHIS)) {
  499.             if (XDebug)
  500.             printf("ready exe date: %s : %s  %02lx\n", dp->Left, dp->Right, dp->Flags & DF_DATEDOK);
  501.             if (dp->Flags & DF_EXPANDRIGHT) {
  502.             dp->Flags &= ~DF_EXPANDRIGHT;
  503.             DirectoryWildScan(dp, NULL, 0);
  504.             }
  505.  
  506.             if (IsWildCard(dp->Right)) {
  507.             if (XDebug)
  508.                 printf("Warn: IsWildCard! %s : %s\n", dp->Left, dp->Right);
  509.             } else {    /*  remove into separate list */
  510.             ++numdeps;
  511.             if ((dp->Flags & DF_DATEDOK) && !(dp->Flags & DF_OUTDATED))
  512.                 ++numdatedok;
  513.             Remove(dp);
  514.             AddTail(&exelist, dp);
  515.             }
  516.         }
  517.         }
  518.  
  519.         /*
  520.          *    If there are any dependancies in the list, the reference
  521.          *    count is still 0, the left side is not a wildcard, and the
  522.          *    date doesn't checkout, execute the list.    Set the common
  523.          *    flags according to whether the list was executed or not
  524.          *    (propogation upwards of the timestamp comparison results).
  525.          */
  526.  
  527.         if (dep->Common->RefCnt == 0 && GetHead(&exelist) && !IsWildCard(dep->Left)) {
  528.         if (numdeps != numdatedok || numdeps == 0) {
  529.             ExecuteCmdCollection(&exelist);
  530.             dep->Common->Flags |= DF_OUTDATED;
  531.         } else {
  532.             dep->Common->Flags |= DF_DATEDOK;
  533.         }
  534.         }
  535.         while (dp = RemHead(&exelist))
  536.         AddTail(&DepList, dp);
  537.     }
  538.  
  539.     /*
  540.      *  RefCnt != 0, abort cleanup
  541.      */
  542.  
  543.     if (dep->Common->RefCnt != 0)
  544.         continue;
  545.  
  546.     dep->Common->RefCnt = -1;   /*    RAN!    */
  547.  
  548.     /*
  549.      *  After execution has completed, decrement any occurances
  550.      *  of our left side (now complete) on the right of other
  551.      *  dependancies.
  552.      */
  553.  
  554.     for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
  555.         if (strcmp(dep->Left, dp->Right) == 0 && !(dp->Flags & DF_DIDTHIS)) {
  556.         --dp->Common->RefCnt;
  557.         dp->Flags |= DF_DIDTHIS;
  558.         if (XDebug)
  559.             printf("EDL2: DECREMENT REF (RHR): %s : %s (%08lx) -> %ld\n",
  560.             dp->Left, dp->Right, dp->Common, dp->Common->RefCnt
  561.             );
  562.         /*
  563.          *  If all of the dependancies for dep->Left had a valid
  564.          *  time (nothing needed to be executed), propogate the
  565.          *  information upwards.
  566.          */
  567.  
  568.         dp->Flags |= dep->Common->Flags & (DF_DATEDOK | DF_OUTDATED);
  569.         if (Verbose == 2) {
  570.             if (dep->Common->Flags & DF_OUTDATED)
  571.             printf("Propogate outdated (%s:%s) -> (%s:%s)\n", dep->Left, dep->Right, dp->Left, dp->Right);
  572.             else if (dep->Common->Flags & DF_DATEDOK)
  573.             printf("Propogate date ok (%s:%s) -> (%s:%s)\n", dep->Left, dep->Right, dp->Left, dp->Right);
  574.         }
  575.         if (IsWildCard(dp->Right))    /* defer expansion ??APPLYALL */
  576.             dp->Flags |= DF_EXPANDRIGHT;
  577.         if (dp->Common->RefCnt == 0) {
  578.             if (IsWildCard(dp->Left) && !(dp->Flags & DF_APPLYALL))
  579.             DirectoryWildScan(dp, NULL, 1);
  580.         }
  581.         }
  582.  
  583.         if (XDebug)
  584.         PrintDepList(&DepList);
  585.     }
  586.     }
  587.     if (XDebug) {
  588.     puts("ExecuteDepList End");
  589.     PrintDepList(&DepList);
  590.     }
  591. }
  592.  
  593. /*
  594.  *  ExecuteCmdCollect()
  595.  *
  596.  *    Given a list of dependancies (all with the same left side), add
  597.  *    their right sides into the %(variable) table under the name
  598.  *    specified by their collection entry.  This is how all those object
  599.  *    modules in all : *.o get combined to so the programmer can
  600.  *    specify %(*.o) in the command list.
  601.  *
  602.  */
  603.  
  604. ExecuteCmdCollection(list)
  605. MLIST *list;
  606. {
  607.     register DEPEND *dep = GetHead(list);
  608.  
  609.     if (XDebug) {
  610.     printf("EXECUTE %s :", dep->Left);
  611.     for (; dep; dep = GetSucc(dep))
  612.         printf("<%s> ", dep->Right);
  613.     puts("");
  614.     }
  615.     ResetVarCollector();
  616.     for (dep = GetHead(list); dep; dep = GetSucc(dep)) {
  617.     if (dep->ColDep)
  618.         AddVarCollector(dep->Right, dep->ColDep->Right, 1);
  619.     else
  620.         AddVarCollector(dep->Right, dep->Right, 1);
  621.     AddVarCollector(dep->Right, "right", 0);
  622.     }
  623.     dep = GetHead(list);
  624.     AddVarCollector(dep->Left, "left", 0);
  625.     ExecuteCmdList(dep->CmdList);
  626. }
  627.  
  628. /*
  629.  *  Test if a file contains a wildcard or not.
  630.  */
  631.  
  632. IsWildCard(str)
  633. register char *str;
  634. {
  635.     while (*str) {
  636.     if (*str == '*' || *str == '?')
  637.         return(1);
  638.     ++str;
  639.     }
  640.     return(0);
  641. }
  642.  
  643. /*
  644.  *  DirectoryWildScan(dep, autolist, scanleft)
  645.  *
  646.  *  This is the major wildcard dependancy handling call.
  647.  *
  648.  *  (1) If we have *.o : <any>  which is flagged DF_APPLYALL (any must
  649.  *    depend on each derived .o file), we cannot handle the dependancy
  650.  *    at this point so we undo the DF_DIDTHIS flag and return.
  651.  *
  652.  *  (2) Either the right side is expanded and the left side derived or
  653.  *    the left side is expanded and the right side derived.  When one
  654.  *    side is expanded, if the other side is NOT a wildcard it is left
  655.  *    alone ( all:*.c -> all:a.c, all:b.c, all:c.c etc.. ).
  656.  *
  657.  *  (3)
  658.  *
  659.  */
  660.  
  661. DirectoryWildScan(dep, autolist, scanleft)
  662. DEPEND *dep;
  663. MLIST *autolist;
  664. {
  665.     MLIST DList;
  666.     register DEPEND *dp;
  667.     short iswcleft = IsWildCard(dep->Left);
  668.  
  669.     if (XDebug)
  670.     printf("DirectoryWildScan: %s : %s  (%ld)\n", dep->Left, dep->Right, scanleft);
  671.     NewList(&DList);
  672.  
  673.     /*
  674.      *    (1) Unless scanleft is set (set when we must expand ONE side because
  675.      *        it *IS* DF_APPLYALL, i.e. *.c : *.h -> a.c : *.h, b.c : *.h),
  676.      *        we defer DF_APPLYALL operation until all other associated
  677.      *        dependancies have been resolved.  Otherwise we would be forced
  678.      *        to evaluate the left-side wildcard too early .. perhaps before
  679.      *        the files have been created.
  680.      */
  681.  
  682.     if (!scanleft && iswcleft && (dep->Flags & DF_APPLYALL)) {
  683.     ++dep->Common->RefCnt;
  684.     dep->Flags &= ~DF_DIDTHIS;
  685.     return(0);
  686.     }
  687.  
  688.     /*
  689.      *    (2) Expand either the left side or the right side.  Do either
  690.      *        a directory scan or use a predetermined list.  Handle the
  691.      *        three cases: <wild>:<wild>, <norm>:<wild>, <wild:norm>
  692.      *
  693.      *        The only time <wild>:<wild> will occur is with the DF_APPLYALL
  694.      *        case.
  695.      */
  696.  
  697.     {
  698.     char *left = (iswcleft) ? dep->Left : dep->Right;
  699.     char *right= (scanleft) ? dep->Left : dep->Right;
  700.  
  701.     if (autolist)
  702.         AutoExpandRightSide(&DList, left, right, autolist);
  703.     else
  704.         ExpandRightSide(&DList, left, right);
  705.  
  706.     /*
  707.      *  if not wc must set left side all the same (cause we did a hack
  708.      *  above so we could call the Virtuo routine).  Also, assign the
  709.      *
  710.      *  if scanleft (left side guarenteed to be a wildcard), we need
  711.      *  to set the right side all the same (cause... )
  712.      */
  713.  
  714.     for (dp = GetHead(&DList); dp; dp = GetSucc(dp)) {
  715.         dp->Flags |= DF_ALLOWED;
  716.         dp->Order = dep->Order;
  717.         if (iswcleft == 0)
  718.         dp->Left = dep->Left;
  719.         else if (scanleft)
  720.         dp->Right= dep->Right;
  721.         AddCollect(dp, dep);
  722.     }
  723.  
  724.     CombineRefCnts(&DList);    /*  combine reference counts for new left sides */
  725.  
  726.     }
  727.  
  728.     /*
  729.      *    (3) If the left side is not a wildcard we are done for now.
  730.      */
  731.  
  732.     if (XDebug)
  733.     puts("Main Combinational complete");
  734.  
  735.     if (iswcleft == 0) {
  736.     if (XDebug)
  737.         puts("Left side not wc, end");
  738.     while (dp = RemHead(&DList)) {
  739.         dp->CmdList = dep->CmdList;
  740.         Order = FindBeginPoint(dp, Order, 1);
  741.         AddTail(&DepList, dp);
  742.     }
  743.     return(1);
  744.     }
  745.  
  746.     /*
  747.      *    (3) If the left side IS a wildcard, then scan the list for two cases
  748.      *        (a) if the left wildcard appears on the LEFT side of any other
  749.      *        dependancy in which DF_APPLYALL is set, we must break up
  750.      *        those dependancies.
  751.      *
  752.      *            *.o : *.c *.h -> *.o : *.c and *.o : *.h (APPLYALL),
  753.      *            when *.o : *.c is resolved in (1)&(2), we must break up
  754.      *            the apply all case *.o : *.h -> a.o : *.h, b.o : *.h
  755.      *            etc...
  756.      *
  757.      *        (b) if the left wildcard appears on the RIGHT side of any
  758.      *        other dependancy we must expand them as well:
  759.      *
  760.      *            all : *.o
  761.      *            *.o : *.c    when *.o : *.c is resolved, we must also
  762.      *            resolve all : *.o -> all : a.o, all : b.o
  763.      *
  764.      *        NOTE:    all : *.o is allowed to DF_DIDTHIS since several
  765.      *        dependancies might reference it:
  766.      *
  767.      *            *.o : *.c
  768.      *            *.o : *.asm
  769.      *
  770.      *        There are THREE cases in this expansion.  (i) the left side
  771.      *        of the found dep (i.e. all : *.o in the example above) is
  772.      *        NOT a wildcard (simple).  (ii) the left side IS a wildcard
  773.      *        and DF_APPLYALL is set, (iii) the left side IS a wildcard
  774.      *        and DF_APPLYALL is not set.
  775.      *
  776.      *            (i) all : *.o   -> all : a.o, all : b.o
  777.      *           (ii) *.x : *.h   -> *.x : mike.h, *.x : ben.h
  778.      *                 ^DF_APPLYALL (ii)
  779.      *          (iii) *.x : *.o   -> a.x : a.o, b.x : b.o
  780.      */
  781.  
  782.     for (dp = GetHead(&DepList); dp; dp = GetSucc(dp)) {
  783.     /*
  784.      *  (3a)
  785.      */
  786.     if (strcmp(dep->Left, dp->Left) == 0 && (dp->Flags & DF_APPLYALL)) {
  787.         DEPEND *dp2, *newdep;
  788.  
  789.         if (!(dp->Flags & DF_DIDTHIS)) {
  790.         --dp->Common->RefCnt;
  791.         dp->Flags |= DF_DIDTHIS;
  792.         }
  793.         dp->Flags &= ~(DF_APPLYALL | DF_EXPANDRIGHT);
  794.  
  795.         if (XDebug)
  796.         printf("DidThis FLAG SET (DWS1) for %s : %s (%ld)\n",
  797.             dp->Left, dp->Right, dp->Common->RefCnt
  798.         );
  799.  
  800.         /*
  801.          *    For each expanded left side, generate left : wildright
  802.          */
  803.  
  804.         for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
  805.         newdep = MakeOneDepend(dp2->Common, &DepList, dp2->Left, dp->Right);
  806.         newdep->Order = dp2->Order;
  807.         newdep->Flags |= DF_ALLOWED;
  808.         newdep->CmdList = dp->CmdList;
  809.         AddCollect(newdep, dp);
  810.         if (XDebug)
  811.             printf("*** Created APPLYALL dep: %s : %s\n", newdep->Left, newdep->Right);
  812.         }
  813.     }
  814.  
  815.     /*
  816.      *  If our wild left side appears on the right side of anybody
  817.      *  else, we must expand them.    How we expand them depends whether
  818.      *  they are wildcarded &| APPLYALL.
  819.      *
  820.      *  (3b.i,ii,iii)
  821.      */
  822.  
  823.     if (strcmp(dep->Left, dp->Right) == 0 && (dp->Flags & DF_ALLOWED)) {
  824.         if (XDebug)
  825.         printf("DidThis FLAG SET (DWS2) for %s : %s (%ld)(%08lx)\n",
  826.             dp->Left, dp->Right, dp->Common->RefCnt, dp
  827.         );
  828.         if (!(dp->Flags & DF_DIDTHIS)) {
  829.         if (XDebug)
  830.             printf("SET %08lx ref %08lx\n", dp, dp->Common);
  831.         --dp->Common->RefCnt;
  832.         dp->Flags |= DF_DIDTHIS;
  833.         } else {
  834.         if (XDebug)
  835.             printf("NOTSET %08lx ref %08lx\n", dp, dp->Common);
  836.         }
  837.         if (dp->Common->RefCnt < 0) {
  838.         puts("INTERNAL ERROR #Directory-1");
  839.         xexit(30);
  840.         }
  841.  
  842.         /*
  843.          *    (3b. i, ii, iii).  Here (i) is taken care of by checking
  844.          *    if the left side is a wildcard... we skip the if. Inside
  845.          *    the if (ii) and (iii) are handled.
  846.          */
  847.  
  848.         if (IsWildCard(dp->Left)) {     /* create mult refs to mult objects   */
  849.         /*
  850.          * (ii) APPLYALL flagged
  851.          */
  852.         if (dp->Flags & DF_APPLYALL) {
  853.             DEPEND *dp2, *newdep;
  854.  
  855.             if (!(dp->Flags & DF_DIDTHIS)) {
  856.             dp->Flags |= DF_DIDTHIS;
  857.             --dp->Common->RefCnt;
  858.             for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
  859.                 newdep = MakeOneDepend(dp->Common, &DepList, dp->Left, dp2->Left);
  860.                 newdep->Order = dp->Order;
  861.                 if (XDebug)
  862.                 printf("Common: %s : %s  now %d\n", dp->Left, dp->Right, dp->Common->RefCnt);
  863.                 newdep->Flags |= DF_ALLOWED | DF_APPLYALL;
  864.                 newdep->CmdList = dp->CmdList;
  865.                 AddCollect(newdep, dp);     /* RefCnt must be stable */
  866.             }
  867.             }
  868.         } else {
  869.             /*
  870.              *    (iii) *.o : *.c -> a.o : a.c, b.o : b.c etc...
  871.              *        Simple recurse.
  872.              */
  873.  
  874.             DirectoryWildScan(dp, &DList, 0);
  875.         }
  876.         } else {                /* create multiple refs to one object */
  877.         /*
  878.          *  (i) left side is not a wildcard, all : *.o
  879.          */
  880.  
  881.         DEPEND *dp2, *newdep;
  882.  
  883.         for (dp2 = GetHead(&DList); dp2; dp2 = GetSucc(dp2)) {
  884.             newdep = MakeOneDepend(dp->Common, &DepList, dp->Left, dp2->Left);
  885.             newdep->Order = dp->Order;
  886.             if (XDebug)
  887.             printf("Common: %s : %s  now %d\n", dp->Left, dp->Right, dp->Common->RefCnt);
  888.             newdep->Flags |= DF_ALLOWED;
  889.             newdep->CmdList = dp->CmdList;
  890.             AddCollect(newdep, dp);     /* RefCnt must be stable */
  891.         }
  892.         }
  893.     }
  894.     }
  895.  
  896.     /*
  897.      *    For each of the new dependancies, FindBeginPoint() them (to handle
  898.      *    special cases for wildcarded objects) and add them to the main list.
  899.      *    Also note that we must CombineRefCnts() to combine the common
  900.      *    structures (all dependancies with the same left side must point
  901.      *    to the same shared common structure).
  902.      *
  903.      *    (4) i.e. you have   *.o : *.c  and also have a special case like
  904.      *        charlie.o : cook_takes_the_cake
  905.      *
  906.      */
  907.  
  908.     CombineRefCnts(&DList);
  909.  
  910.     while (dp = RemHead(&DList)) {
  911.     dp->CmdList = dep->CmdList;
  912.     FindBeginPoint(dp, dep->Order, 0);
  913.     AddTail(&DepList, dp);
  914.     }
  915.     return(1);
  916. }
  917.  
  918. /*
  919.  *  AutoExpandRightSide()
  920.  *
  921.  *  This routine works like ExpandRightSide(), but instead of scanning a
  922.  *  directory it derives the results from a passed list of dependancies.
  923.  *  The reasoning behind this follows:     ram:*.o : *.c , DMake will
  924.  *  scan the directory for *.c and derive ram:*.o without scaning ram:.
  925.  *  After all, there might be additional .o files in ram: that we do NOT
  926.  *  want to include.
  927.  *
  928.  *  The previously found file's left side matches the new right side.
  929.  */
  930.  
  931. AutoExpandRightSide(newlist, left, right, oldlist)
  932. MLIST *newlist;
  933. char *left;
  934. char *right;
  935. MLIST *oldlist;
  936. {
  937.     register DEPEND *dp;
  938.  
  939.     if (XDebug)
  940.     printf("AutoExpandRightSide %s : %s\n", left, right);
  941.     for (dp = GetHead(oldlist); dp; dp = GetSucc(dp)) {
  942.     MakeOneDepend(NULL, newlist, VirtuoExpand(left, right, dp->Left), dp->Left);
  943.     }
  944.     if (XDebug)
  945.     puts("AutoExpandRightSide done");
  946. }
  947.  
  948. /*
  949.  *  ExpandRightSide()
  950.  *
  951.  *  This routine does a directory scan of the right side and creates
  952.  *  a set of dependancies, placing them in the specified list.
  953.  */
  954.  
  955. ExpandRightSide(newlist, left, right)
  956. MLIST *newlist;
  957. char *left;
  958. char *right;
  959. {
  960.     char *ptr;
  961.     int ac;
  962.     register char **av;
  963.     register short i;
  964.     char **expand();
  965.  
  966.     if (XDebug)
  967.     printf("ExpandRightSide <%s> : <%s>\n", left, right);
  968.     av = expand(right, &ac);
  969.     if (XDebug) {
  970.     for (i = 0; i < ac; ++i)
  971.         printf("(%s)", av[i]);
  972.     puts("");
  973.     }
  974.  
  975.     for (i = 0; i < ac; ++i)
  976.     MakeOneDepend(NULL, newlist, VirtuoExpand(left, right, av[i]), av[i]);
  977.     if (XDebug)
  978.     puts("ExpandRightSide done");
  979. }
  980.  
  981. /*
  982.  *  VirtuoExpand("x*.poof", "*.o", "charlie.o") -> xcharlie.poof
  983.  *
  984.  *  This converts a filename from one name to another using the two
  985.  *  provided wildcards (old and new).
  986.  */
  987.  
  988. char *
  989. VirtuoExpand(newwc, oldwc, filename)
  990. register char *newwc, *oldwc, *filename;
  991. {
  992.     char *newbase = newwc;
  993.  
  994.     if (XDebug)
  995.     printf("VEIN: <%s> <%s> <%s>\n", newwc, oldwc, filename);
  996.     {                    /*  skip non-wildcards    */
  997.     register char *old = oldwc;
  998.     register char *name = filename;
  999.  
  1000.     while (*old && *old != '*' && *old != '?') {
  1001.         if (*name != *old)      /*  failure!    */
  1002.         return(NULL);
  1003.         ++name;
  1004.         ++old;
  1005.     }
  1006.     oldwc = old;
  1007.     filename = name;
  1008.     }
  1009.     {                    /* skip non wildcards in new */
  1010.     register char *new = newwc;
  1011.     while (*new && *new != '*' && *new != '?')
  1012.         ++new;
  1013.     newwc = new;
  1014.     }
  1015.     if (*newwc != *oldwc)           /*  new pattern must match old */
  1016.     return(NULL);
  1017.     if (*oldwc == 0 && *filename == 0)
  1018.     return(newbase);            /*  success!                   */
  1019.     /*
  1020.      *    at this point, *oldwc == *newwc == '*' or '?'
  1021.      */
  1022.  
  1023.     if (*oldwc == '?') {            /*  match a single char in *filename   */
  1024.     char *last = VirtuoExpand(newwc + 1, oldwc + 1, filename + 1);
  1025.     char *str;
  1026.     short i;
  1027.  
  1028.     if (!last)
  1029.         return(NULL);
  1030.     /*
  1031.      *  combine (newbase..newwc) with *filename with last
  1032.      */
  1033.     i = newwc - newbase;
  1034.     str = malloc(i + strlen(last) + 2);
  1035.     movmem(newbase, str, i);
  1036.     str[i] = *filename;
  1037.     strcpy(str+i+1, last);
  1038.     return(str);
  1039.     }
  1040.  
  1041.     /*
  1042.      *    *oldwc == *newwc == '*', we must try to match all or part of
  1043.      *    the remaining filename.
  1044.      */
  1045.  
  1046.     {
  1047.     char *fi = filename + strlen(filename);
  1048.  
  1049.     while (fi >= filename) {
  1050.         char *last;
  1051.         char *str;
  1052.         short i, j;
  1053.  
  1054.         if (last = VirtuoExpand(newwc + 1, oldwc + 1, fi)) {
  1055.         /*
  1056.          *  combine (newbase..newwc with filename..fi with last
  1057.          */
  1058.         i = newwc - newbase;
  1059.         j = fi - filename;
  1060.         str = malloc(i + j + strlen(last) + 1);
  1061.         movmem(newbase, str, i);
  1062.         movmem(filename, str + i, j);
  1063.         strcpy(str + i + j, last);
  1064.         return(str);
  1065.         }
  1066.         --fi;
  1067.     }
  1068.     }
  1069.     return(NULL);
  1070. }
  1071.  
  1072. /*
  1073.  *  CreateDependancies()
  1074.  *
  1075.  *  Given a just-parsed line from the initial file scan, this routine
  1076.  *  breaks it up into individual dependancies with a left and right side.
  1077.  *
  1078.  *  It is pretty straight forward (see the dmake rules).  Note that the
  1079.  *  APPLYALL flag must be set for dependancies like this:
  1080.  *        *.o : *.c *.h    (set APPLYALL for *.o : *.h to prevent
  1081.  *                it from being misinterpreted later)
  1082.  *
  1083.  *  each .c files depends on its .o file, but each .o files depends on
  1084.  *  ALL the .h files.
  1085.  */
  1086.  
  1087. CreateDependancies(cmdlist, av, ls, le, rs, re)
  1088. MLIST *cmdlist;
  1089. char **av;
  1090. short ls, le, rs, re;
  1091. {
  1092.     register short i;
  1093.     MLIST deplist;
  1094.  
  1095.     NewList(&deplist);
  1096.  
  1097.     if (Verbose == 4) {
  1098.     printf("CreateDependancies %08lx %08lx %ld %ld %ld %ld\n",
  1099.         cmdlist, av, ls, le, rs, re
  1100.     );
  1101.     for (i = 0; i + ls < le; ++i)
  1102.         printf("left: %08lx <%s>\n", av[ls+i], av[ls+i]);
  1103.     for (i = 0; i + rs < re; ++i)
  1104.         printf("rght: %08lx <%s>\n", av[rs+i], av[rs+i]);
  1105.     }
  1106.  
  1107.     for (i = 0; ls + i < le && rs + i < re; ++i) {
  1108.     MakeOneDepend(NULL, &deplist, av[ls+i], av[rs+i]);
  1109.     }
  1110.     while (ls + i < le) {   /*  only left guys remain               */
  1111.     if (rs == re) {     /*  special case, right side was empty  */
  1112.         MakeOneDepend(NULL, &deplist, av[ls + i], NULL);
  1113.     } else if (rs + 1 == re) {
  1114.         MakeOneDepend(NULL, &deplist, av[ls + i], av[rs]);
  1115.     } else {
  1116.         printf("Error line %ld.  Under normal conditions one has the\n", LineNo);
  1117.         puts("same number of dependancies on the left as on the right,");
  1118.         puts("or more on the right.  The only two cases allowed for more");
  1119.         puts("on the left is when the right has 0 or 1 arguments");
  1120.         xexit(25);
  1121.     }
  1122.     ++i;
  1123.     }
  1124.  
  1125.     {    /*  only right guys remain.  Make all left's dep. on them.  */
  1126.     /*  note: operation must be defered for wildcards on left   */
  1127.  
  1128.     register DEPEND *dbase = GetTail(&deplist);
  1129.     if (dbase) {
  1130.         while (rs + i < re) {
  1131.         register DEPEND *dep, *new;
  1132.         for (dep = dbase; dep; dep = GetPred(dep)) {
  1133.             new = MakeOneDepend(dep->Common, &deplist, dep->Left, av[rs + i]);
  1134.             if (IsWildCard(new->Left) /*&& !IsWildCard(new->Right)*/)
  1135.             new->Flags |= DF_APPLYALL;
  1136.         }
  1137.         ++i;
  1138.         }
  1139.     }
  1140.     }
  1141.  
  1142.     {
  1143.     register DEPEND *dep;
  1144.     while (dep = RemHead(&deplist)) {
  1145.         dep->CmdList = cmdlist;
  1146.         AddTail(&DepList, dep);
  1147.     }
  1148.     }
  1149. }
  1150.  
  1151. /*
  1152.  *  MakeOneDepend()
  1153.  *
  1154.  *  Note: the fact that it adds to the tail of the list is counted on in
  1155.  *  an earlier routine.  This creates a new dependancy.  Note, however,
  1156.  *  that the common node might be allocated thus invalidating the rule
  1157.  *  that all dependancies with the same dep->Left have the same common
  1158.  *  structure.    This is dealt with by calling CombineRefCnts().
  1159.  */
  1160.  
  1161. DEPEND *
  1162. MakeOneDepend(common, list, left, right)
  1163. register COMMON *common;
  1164. MLIST *list;
  1165. char *left;
  1166. char *right;
  1167. {
  1168.     register DEPEND *dep = malloc(sizeof(DEPEND));
  1169.     if (!common) {
  1170.     common = malloc(sizeof(COMMON));
  1171.     clrmem(common, sizeof(COMMON));
  1172.     }
  1173.     clrmem(dep, sizeof(DEPEND));
  1174.  
  1175.     ++common->RefCnt;
  1176.     dep->Common = common;
  1177.     dep->Left = left;
  1178.     dep->Right= (right) ? right : "";
  1179.     AddTail(list, dep);
  1180.     if (XDebug)
  1181.     printf("MakeOneDepend dep %08lx com %08lx %d %s : %s\n", dep, common, common->RefCnt, left, right);
  1182.     return(dep);
  1183. }
  1184.  
  1185. /*
  1186.  *  ADDCOLLECT()
  1187.  *
  1188.  *  Set dep's collection to dp (always dp->Right).  I.E. when you have
  1189.  *  something like:  *.o : *.c *.h, cc %(*.c) -o %(left).  The individual
  1190.  *  C files get placed in the *.c collection one at a time so they can be
  1191.  *  referenced by a % variable
  1192.  */
  1193.  
  1194. AddCollect(dep, dp)
  1195. register DEPEND *dep;
  1196. DEPEND *dp;
  1197. {
  1198.     dep->Flags |= DF_COLLECT;
  1199.     dep->Common->Flags |= DF_COLLECT;
  1200.     dep->ColDep = dp;
  1201. }
  1202.  
  1203. /*
  1204.  *  low level routines
  1205.  */
  1206.  
  1207. char LineBuf[4096];
  1208.  
  1209. char *
  1210. getline(fi, pcmmnt)
  1211. FILE *fi;
  1212. short *pcmmnt;
  1213. {
  1214.     register short i = 0;
  1215.     if (pcmmnt)
  1216.     *pcmmnt = 0;
  1217.     while (fgets(LineBuf + i, sizeof(LineBuf) - i, fi)) {
  1218.     if (i == 0 && LineBuf[i] == '#') {
  1219.         LineBuf[i] = 0;
  1220.         if (pcmmnt)
  1221.         *pcmmnt = 1;
  1222.     }
  1223.     i += MacroReplace(0, LineBuf + i, strlen(LineBuf + i));
  1224.     while (i-- && (LineBuf[i] == '\n' || LineBuf[i] == '\t' || LineBuf[i] == ' '))
  1225.         LineBuf[i] = 0;
  1226.     if (LineBuf[i] == '\\')     /*  line continuance    */
  1227.         continue;
  1228.     if (XDebug)
  1229.         printf("LINE: %s\n", LineBuf);
  1230.     return(LineBuf);
  1231.     }
  1232.     return(NULL);
  1233. }
  1234.  
  1235. char **
  1236. parseline(ptr, pac)
  1237. register char *ptr;
  1238. short *pac;
  1239. {
  1240.     char *pbuf = malloc(strlen(ptr)+1);
  1241.     static char *av[1024];
  1242.     register short ac = 0;
  1243.  
  1244.     strcpy(pbuf, ptr);
  1245.     ptr = pbuf;
  1246.     while (*ptr) {
  1247.     while (*ptr == ' ' || *ptr == '\t')
  1248.         ++ptr;
  1249.     av[ac++] = ptr;
  1250.     while (*ptr && *ptr != ' ' && *ptr != '\t')
  1251.         ++ptr;
  1252.     if (*ptr)
  1253.         *ptr++ = 0;
  1254.     }
  1255.     *pac = ac;
  1256.     return(av);
  1257. }
  1258.  
  1259. PrintDepList(list)
  1260. MLIST *list;
  1261. {
  1262.     register DEPEND *dep;
  1263.  
  1264.     puts("(DEP LIST)");
  1265.     for (dep = GetHead(list); dep; dep = GetSucc(dep)) {
  1266.     printf("dep: %02lx %2ld (#%2ld)(%08lx) %s : %s",
  1267.         dep->Flags,
  1268.         dep->Common->RefCnt,
  1269.         dep->Order,
  1270.         dep->Common,
  1271.         dep->Left,
  1272.         dep->Right
  1273.     );
  1274.     if (dep->Flags & DF_COLLECT) {
  1275.         printf("  (collect to %s)", dep->ColDep->Right);
  1276.     }
  1277.     puts("");
  1278.     }
  1279.     puts("(END OF DEP LIST)");
  1280. }
  1281.  
  1282.  
  1283.