home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / pmake2.lbr / PMAKE.CQ / ÐMAKE.C
Encoding:
C/C++ Source or Header  |  1986-11-16  |  16.0 KB  |  684 lines

  1. /* pmake -- bring a system of files up to date                              */
  2. /* Portions copyright 1984  Michael M Rubenstein                            */
  3. /* Portions copyright 1984  John M Sellens                                  */
  4.  
  5. /* based on pc-make by John M Sellens.  Significant portions have been      */
  6. /* copied almost verbatim from pc-make.  Mr. Sellens has requested the      */
  7. /* following notice be included in all copies of his program:               */
  8.  
  9. /*
  10. Written by John M Sellens, April, 1984
  11.  
  12. Until August, 1984:
  13.     jmsellens@watrose.UUCP
  14.  
  15.     107 - 180 Brybeck Cres.
  16.     Kitchener, Ontario
  17.     N2M 5G4
  18.  
  19. After August, 1984:
  20.     c/o 1135 Lansdowne Ave. SW
  21.     Calgary, Alberta
  22.     T2S 1A4
  23.  
  24. (c) Copyright 1984 John M Sellens
  25. Permission is granted to use, distribute and/or modify this code unless
  26. done for direct commercial profit.  If you find these routines useful,
  27. modest contributions (monetary or otherwise) will be gratefully accepted.
  28. Author's name, address and this notice must be included in any copies.
  29.  
  30. */
  31.  
  32. #define PGMNAME         "pmake"
  33. #include <stdio.h>
  34. #include "pmake.h"
  35.  
  36. int                     modbit = MODBIT;
  37. unsigned                submax = SUBMAX;
  38. char                    submit[9] = SUBMIT;
  39. struct howrec {         char            *howcom;
  40.                         struct howrec   *nexthow;
  41.               };
  42.  
  43. struct deprec {         char            *name;
  44.                         char            *def;   /* really struct defnrec * */
  45.                         struct deprec   *nextdep;
  46.               };
  47.  
  48. struct defnrec {        char            *name;
  49.                         int             uptodate;
  50.                         int             modified;
  51.                         struct deprec   *dependson;
  52.                         struct howrec   *howto;
  53.                         struct defnrec  *nextdefn;
  54.                };
  55.  
  56. struct dorec {          char            *name;
  57.                         struct dorec    *nextdo;
  58.              };
  59.  
  60. struct setrec {         char            *name;
  61.                         struct setrec   *nextset;
  62.               };
  63.  
  64. struct defnrec          *defnlist = NULL;
  65. struct dorec            *dolist = NULL;
  66. struct defnrec          *initrec = NULL,
  67.                         *finrec = NULL;
  68. struct setrec           *setlist = NULL;
  69.  
  70. int                     subsize;
  71.  
  72. int                     stopOnErr = TRUE;
  73. int                     madesomething;
  74. int                     knowhow;
  75. int                     noinit = FALSE;
  76. FILE                    *outfile;
  77. int                     outnum = 0;
  78.  
  79. char                    *vars;
  80. char                    *endvars;
  81.  
  82. #ifdef DEBUG
  83. int                     debug = 0;
  84. #endif
  85.  
  86. int                     xargc;
  87. char                    **xargv;
  88.  
  89. char                    *findvar();
  90.  
  91. main(argc, argv)
  92.   int                   argc;
  93.   char                  *argv[];
  94. {
  95.   static int            didsomething = FALSE;
  96.   char                    vars_[MAXLVAR + 1];
  97.  
  98.   vars = endvars = vars_;
  99.   *vars = '\0';
  100.   xargc = argc;
  101.   xargv = argv;
  102.   init();
  103.  
  104.   /* now fall down the dolist and do them all */
  105.   while (dolist != NULL)
  106.   {
  107.     madesomething = FALSE;
  108.     make(dolist->name);
  109.     didsomething |= madesomething;
  110.     if (!madesomething)
  111.     {
  112.       if (knowhow)
  113.         fprintf(stderr,"pmake: '%s' is up to date\n",dolist->name);
  114.       else
  115.       {
  116.         fprintf(stderr,"pmake: Don't know how to make '%s'\n", dolist->name);
  117.         if (stopOnErr)
  118.           exit(1);
  119.       }
  120.     }
  121.     dolist = dolist->nextdo;
  122.   }
  123.   if (didsomething || setlist != NULL)
  124.   {
  125.     setdone();
  126.     if (finrec != NULL && didsomething)
  127.     {
  128.       finrec->uptodate = FALSE;
  129.       make(".FIN");
  130.     }
  131.   }
  132.   else
  133.   {
  134.     setflg(outfile, "d");
  135.     fclose(outfile);
  136.     exit(1);
  137.   }
  138.   fclose(outfile);
  139. }
  140.  
  141.  
  142. init()
  143. {
  144.   static int            usedefault = TRUE;
  145.   static int            argind = 0;
  146.   static int            i;
  147.   static int            done = FALSE;
  148.  
  149.   extern int            optind;
  150.   extern char           *optarg;
  151.  
  152. #ifdef DEBUG
  153. #define OPTFLAGS        "-DF:IN:O:V:"
  154. #else
  155. #define OPTFLAGS        "-F:IN:O:V:"
  156. #endif
  157.  
  158.   do
  159.   {
  160.     switch (getopt(xargc, xargv, OPTFLAGS))
  161.     {
  162. #ifdef DEBUG
  163.       case 'D':         /* debug */
  164.                         ++debug;
  165.                         break;
  166. #endif
  167.  
  168.       case 'F':         /* arg following is a makefile */
  169.                         if (*optarg == '\0')
  170.                           error("'-f' requires filename");
  171.                         readmakefile(optarg);
  172.                         usedefault = FALSE;
  173.                         break;
  174.  
  175.       case 'I':         /* ignore errors on execution */
  176.                         stopOnErr = FALSE;
  177.                         break;
  178.  
  179.       case 'N':         if ((submax = atoi(optarg)) == 0)
  180.                           submax = 0xffff;
  181.                         break;
  182.  
  183.       case 'V':         addvar(optarg);
  184.                         break;
  185.  
  186.       case '?':         break;
  187.  
  188.       case EOF:         if (optind < xargc)
  189.                           add_do(xargv[optind++]);
  190.                         else
  191.                           done = TRUE;
  192.                         break;
  193.  
  194.       default:          error("dryrot -- invalid option parse");
  195.     }
  196.   } while (!done);
  197.  
  198.   if (dolist == NULL)
  199.     add_do(DEFDO);
  200.   if (usedefault)
  201.     readmakefile(DEFAULT);
  202.   opnout();
  203. }
  204.  
  205. opnout()
  206. {
  207.   char                  outname[13];
  208.  
  209.  
  210.   if (outnum)
  211.   {
  212.     fprintf(outfile, "%s MAKEF%03d\n", submit, outnum);
  213.     fclose(outfile);
  214.   }
  215.  
  216.   sprintf(outname, "MAKEF%03d.SUB", outnum++);
  217.  
  218.   if ((outfile = fopen(outname, "w")) == NULL)
  219.     error("Cannot create output file");
  220.  
  221.   subsize = 0;
  222.  
  223. #ifdef DEBUG
  224.   if (debug)
  225.     setflg(outfile, "e");
  226. #endif
  227.  
  228.   delfil(outname);
  229. }
  230.  
  231. make(s)
  232.   char                  *s;
  233. {
  234.   struct defnrec        *defnp;
  235.   struct deprec         *depp;
  236.   struct howrec         *howp;
  237.   int                   latest;
  238.  
  239. #ifdef DEBUG
  240.   if (debug > 1)
  241.     fprintf(stderr, "***Making %s\n", s);
  242. #endif
  243.  
  244.   /* look for the definition */
  245.   for (defnp = defnlist;
  246.        defnp != NULL && strcmp(defnp->name, s);
  247.        defnp = defnp->nextdefn)
  248.     ;
  249.  
  250.   if (defnp == NULL)                    /* don't know how to make it */
  251.   {
  252.     knowhow = FALSE;
  253.     latest = getmod(s);
  254.     if (latest == 0)                    /* doesn't exist */
  255.     {                                   /* but don't know how to make */
  256.       fprintf(stderr,"pmake: Can't make '%s'\n",s);
  257.       if (stopOnErr)
  258.         exit(1);
  259.       return NOTTHERE;
  260.     } 
  261.     else                                /* exists - assume it's up to date */
  262.     {
  263.       if (latest == CHANGED)
  264.       {
  265.         addset(s);
  266.         return THISRUN;
  267.       }
  268.       return latest;                    /* since we don't know */
  269.     }
  270.   }
  271.  
  272.   if (defnp->uptodate)
  273.     return defnp->modified;
  274.  
  275.   /* now make sure everything that it depends on is up to date */
  276.   latest = 0;
  277.   depp = defnp->dependson;
  278.   while (depp != NULL)
  279.   {
  280.     latest = max(make(depp->name),latest);
  281.     depp = depp->nextdep;
  282.   }
  283.  
  284.   knowhow = TRUE;                       /* has dependencies -- we know how */
  285.  
  286.   /* if necessary, execute all of the commands to make it */
  287.   /* if (out of date) || (depends on nothing)             */
  288.   if (latest > defnp->modified || defnp->dependson == NULL)
  289.   {
  290.     /* make those suckers */
  291.     if ((defnp->howto != NULL || defnp->modified == CHANGED)
  292.      && initrec != NULL)
  293.     {
  294.       initrec->uptodate = FALSE;
  295.       initrec = NULL;
  296.       make(".INIT");
  297.     }
  298.     for (howp = defnp->howto; howp != NULL; howp = howp->nexthow)
  299.     {
  300.       if (subsize >= submax)
  301.         opnout();
  302.       fputs(howp->howcom, outfile);
  303.       putc('\n', outfile);
  304.       ++subsize;
  305.     }
  306.  
  307.     if (*s == '.')
  308.       defnp->modified = (defnp->dependson == NULL) ? THISRUN : latest;
  309.     else
  310.       {
  311.       defnp->modified = THISRUN;
  312.       addset(s);
  313.     }
  314.     defnp->uptodate = TRUE;
  315.     if (defnp->howto != NULL)           /* we had instructions */
  316.       madesomething = TRUE;
  317.   }
  318.  
  319.   if (defnp->modified == CHANGED)
  320.   {
  321.     addset(s);
  322.     defnp->modified = THISRUN;
  323.     defnp->uptodate = TRUE;
  324.   }
  325.  
  326.   return defnp->modified;
  327. }
  328.  
  329.  
  330. add_do(s)
  331.   char                  *s;
  332. {
  333.   struct dorec          *ptr1, *ptr2;
  334.   char                  *getmem();
  335.  
  336. #ifdef DEBUG
  337.   if (debug > 1)
  338.     fprintf(stderr, "***Adding %s to do-list\n", s);
  339. #endif
  340.  
  341.   ptr1 = getmem(sizeof(struct dorec));
  342.  
  343.   ptr1->name = s;                       /* okay since only called with */
  344.   ptr1->nextdo = NULL;                  /* an argv or constant */
  345.  
  346.   upcase(ptr1->name);
  347.  
  348.   /* now go down the dolist */
  349.   if (dolist == NULL)
  350.     dolist = ptr1;
  351.   else
  352.   {
  353.     ptr2 = dolist;
  354.     while (ptr2->nextdo != NULL)
  355.       ptr2 = ptr2->nextdo;
  356.     ptr2->nextdo = ptr1;
  357.   }
  358. }
  359.  
  360. addset(s)
  361.   char                  *s;
  362. {
  363.   struct setrec         *setp, *setp2;
  364.  
  365.   char                  *getmem();
  366.  
  367.   if (setlist == NULL)
  368.     setlist = setp = getmem(sizeof(struct setrec));
  369.   else
  370.   {
  371.     for (setp = setlist; setp != NULL; setp = setp->nextset)
  372.     {
  373.       if (strcmp(s, setp->name) == 0)
  374.         return;
  375.       setp2 = setp;
  376.     }
  377.     setp2->nextset = setp = getmem(sizeof(struct setrec));
  378.   }
  379.   setp->name = s;
  380.   setp->nextset = NULL;
  381. }
  382.  
  383.     
  384.  
  385. readmakefile(s)
  386.   char                  *s;
  387. {
  388.   static FILE           *fil;
  389.   static int            doneline, pos, i, j, c;
  390.   char                  inline[INMAX + 1], info[INMAX + 1];
  391.   char                  *getmem();
  392.   static struct defnrec *defnp, *defnp2;
  393.   static struct deprec  *depp, *depp2;
  394.   static struct howrec  *howp, *howp2;
  395.  
  396.   if ( (fil = fopen(s,"r")) == NULL)
  397.   {
  398.     fprintf(stderr,"pmake: Couldn't open '%s'\n",s);
  399.     return;
  400.   }
  401.  
  402. #ifdef DEBUG
  403.   if (debug > 1)
  404.     fprintf(stderr, "***Reading make file %s\n", s);
  405. #endif
  406.  
  407.   while (fgets(inline, INMAX, fil) != NULL)
  408.   {
  409.     if (inline[0] == COMMENT)
  410.       continue;
  411.     inline[strlen(inline)-1] = '\0';    /* strip trailing newline */
  412.     if (inline[0] == '\0')              /* ignore blank lines */
  413.       continue;
  414.  
  415.     if (inline[0] == VARCHAR)
  416.     {
  417.       addvar(inline + 1);
  418.       continue;
  419.     }
  420.  
  421.     xlate(inline);
  422.  
  423.     if (inline[0] != '\t')              /* start of a new definition */
  424.     {
  425.       upcase(inline);
  426.       /* get what we're defining into info */
  427.       for (pos = 0; isspace(inline[pos]); ++pos)
  428.         ;
  429.       i = 0;
  430.       while (!isspace(inline[pos]) && inline[pos]!='\0')
  431.         info[i++] = inline[pos++];
  432.       info[i] = '\0';
  433.  
  434.       /* get a new struct */
  435.       defnp = getmem(sizeof(struct defnrec));
  436.       /* add it to the end of defnlist */
  437.       if (defnlist == NULL)
  438.         defnlist = defnp;
  439.       else
  440.       {
  441.         defnp2 = defnlist;
  442.         while (defnp2->nextdefn != NULL)
  443.           defnp2 = defnp2->nextdefn;
  444.         defnp2->nextdefn = defnp;
  445.       }
  446.       /* initialize it */
  447.       defnp->name = getmem(strlen(info)+1);
  448.       strcpy(defnp->name,info);
  449.       if (!noinit && strcmp(info, ".INIT") == 0)
  450.       {
  451.         initrec = defnp;
  452.         defnp->uptodate = TRUE;
  453.         defnp->modified = THISRUN;
  454.       }
  455.       else
  456.       if (strcmp(info, ".FIN") == 0)
  457.       {
  458.         finrec = defnp;
  459.         defnp->uptodate = TRUE;
  460.         defnp->modified = THISRUN;
  461.       }
  462.       else
  463.       {
  464.         defnp->uptodate = FALSE;            /* actually unknown */
  465.         defnp->modified = getmod(defnp->name);
  466.       }
  467.       defnp->dependson = NULL;
  468.       defnp->howto = NULL;
  469.       defnp->nextdefn = NULL;
  470.  
  471.       /* now go through all of its dependecies */
  472.       /* first move past the first name */
  473.       /* now loop through those suckers */
  474.       doneline = FALSE;
  475.       while (!doneline)
  476.       {
  477.         while (isspace(inline[pos]))
  478.           pos++;
  479.         if (inline[pos] == '\0')
  480.         {
  481.           doneline = TRUE;
  482.           continue;
  483.         }
  484.         for(i = 0; !isspace(inline[pos]) && inline[pos]!='\0';)
  485.           info[i++] = inline[pos++];
  486.         info[i] = '\0';
  487.         /* get a new struct */
  488.         depp = getmem(sizeof(struct deprec));
  489.         /* add it to the end of deplist */
  490.         if (defnp->dependson == NULL)
  491.           defnp->dependson = depp;
  492.         else
  493.         {
  494.           depp2 = defnp->dependson;
  495.           while (depp2->nextdep != NULL)
  496.             depp2 = depp2->nextdep;
  497.           depp2->nextdep = depp;
  498.         }
  499.         depp->name = getmem(strlen(info)+1);
  500.         strcpy(depp->name,info);
  501.         depp->nextdep = NULL;
  502.       }
  503.     }
  504.     else
  505.     {    /* a how to line */
  506.       if (defnp == NULL)
  507.       {
  508.         fprintf(stderr,"pmake: Howto line without a definition:\n");
  509.         fprintf(stderr,"pmake: '%s'\n",inline);
  510.       }
  511.       /* remove leading & trailing spaces */
  512.       for (pos=0;isspace(inline[pos]); pos++);
  513.         ;
  514.       for (i=strlen(inline); i>pos && isspace(inline[i-1]); --i)
  515.         ;
  516.       /* if there is something there, allocate mem and copy */
  517.       if (i > pos)
  518.       {
  519.         /* get a new struct */
  520.         howp = getmem(sizeof(struct howrec));
  521.         /* add it to the end of howlist */
  522.         if (defnp->howto == NULL)
  523.           defnp->howto = howp;
  524.         else
  525.         {
  526.           howp2 = defnp->howto;
  527.           while (howp2->nexthow != NULL)
  528.             howp2 = howp2->nexthow;
  529.           howp2->nexthow = howp;
  530.         }
  531.         /* copy command filename */
  532.         howp->howcom = getmem(i-pos+1);
  533.         for(j=0; pos < i;)
  534.           howp->howcom[j++] = inline[pos++];
  535.         howp->howcom[j] = '\0';
  536.         howp->nexthow = NULL;
  537.       }
  538.     }
  539.   }
  540. }
  541.  
  542.  
  543. setdone()
  544. {
  545.   static struct setrec  *setp;
  546.   static FILE           *setfile;
  547.  
  548.   if ((setfile = fopen(SETFILE, "w")) == NULL)
  549.     error("cannot open set file");
  550.  
  551.   for (setp = setlist; setp != NULL; setp = setp->nextset)
  552.   {
  553.     fputs(setp->name, setfile);
  554.     putc('\n', setfile);
  555.   }
  556.   fclose(setfile);
  557. }
  558.  
  559. addvar(vdef)
  560.   char                    *vdef;
  561. {
  562.   char                    name[VNAMELEN + 1];
  563.   static                int i;
  564.   static char            *s;
  565.  
  566.   for (s = vdef; isspace(*s); ++s)
  567.     ;
  568.   i = 0;
  569.   for (;issymch(*s); ++s)
  570.     if (i < VNAMELEN)
  571.       name[i++] = toupper(*s);
  572.   name[i] = '\0';
  573.   while (isspace(*s))
  574.     ++s;
  575.   if (!name[0])
  576.   {
  577.     fprintf(stderr, "pmake: Illegal variable definition: %s\n", vdef);
  578.     exit(1);
  579.   }
  580.   if (findvar(name) != NULL)
  581.     return;
  582.   for (i = 0; name[i];)
  583.     addchar(name[i++]);
  584.   addchar('\0');
  585.   s = (*s == '=') ? (s + 1) : name;
  586.   while (*s)
  587.     addchar(*(s++));
  588.   addchar('\0');
  589.   *endvars = '\0';
  590. }
  591.  
  592. addchar(c)
  593.   int                    c;
  594. {
  595.   if (endvars - vars >= MAXLVAR)
  596.     error("Variable space exhausted");
  597.   *(endvars++) = c;
  598. }
  599.  
  600. char *findvar(s)
  601.   register char            *s;
  602. {
  603.   static char            *p;
  604.  
  605.   if (!*s)
  606.     return NULL;
  607.   for (p = vars; *p; p += strlen(p) + 1, p += strlen(p) + 1)
  608.     if (strcmp(s, p) == 0)
  609.       return p + strlen(p) + 1;
  610.   return NULL;
  611. }
  612.  
  613. xlate(line)
  614.   register char            *line;
  615. {
  616.   char                    wkline[INMAX + 1];
  617.   static int            i, j;
  618.   static char            *p, *q;
  619.   char                    name[VNAMELEN + 1];
  620.   static int            changed;
  621.  
  622. #ifdef DEBUG
  623.   if (debug >1)
  624.     fprintf(stderr, "***TRANSLATING: %s\n", line);
  625. #endif
  626.  
  627.   do
  628.   {
  629.     changed = FALSE;
  630.     strcpy(wkline, line);
  631.     for (p = wkline, i = 0; *p;)
  632.     {
  633.       if (*p != VARCHAR || *++p == VARCHAR)
  634.         {
  635.         if (i >= INMAX)
  636.         {
  637.           fprintf("pmake: Line too long:\n%s\n", stderr);
  638.            exit(1);
  639.         }
  640.         line[i++] = *(p++);
  641.         continue;
  642.       }
  643.  
  644.       j = 0;
  645.       changed = TRUE;
  646.        for (; issymch(*p); ++p)
  647.       {
  648.         if (j < VNAMELEN)
  649.           name[j++] = toupper(*p);
  650.       }
  651.       name[j] = '\0';
  652.       if (*p == '%')
  653.         ++p;
  654.       if ((q = findvar(name)) == NULL)
  655.         continue;
  656.       if (i + (j = strlen(q)) > INMAX)
  657.       {
  658.         fprintf("pmake: Line too long:\n%s\n", stderr);
  659.         exit(1);
  660.       }
  661.       strcpy(&line[i], q);
  662.       i += j;
  663.     }
  664.     line[i] = '\0';
  665.   } while (changed);
  666.  
  667. #ifdef DEBUG
  668.   if (debug >1)
  669.     fprintf(stderr, "***NEW VALUE: %s\n", line);
  670. #endif
  671. }
  672.  
  673. issymch(c)
  674.   register int            c;
  675. {
  676.   return isalpha(c) || isdigit(c) || c == '-' || c == '_' || c == '.';
  677. }
  678. UG
  679.   if (debug >1)
  680.     fprintf(stderr, "***TRANSLATING: %s\n", line);
  681. #endif
  682.  
  683.   do
  684.   {