home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / PAMAKE18.ZIP / MAKE.C < prev    next >
C/C++ Source or Header  |  1989-09-30  |  18KB  |  700 lines

  1. /*************************************************************************
  2. |                                                                        |
  3. |   MAKE.C                                                      30.09.89 |
  4. |   PAMAKE Utility:  do the actual making                                |
  5. |                                                                        |
  6. *************************************************************************/
  7.  
  8. #ifdef VMS
  9. #include stdio
  10. #include processes
  11. #include "h.h"
  12. #include errno
  13. #include ctype
  14. #include string
  15. #include stdlib
  16. #include types
  17. #include stat
  18. #endif
  19.  
  20. #ifdef LATTICE
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <dos.h>
  24. #include "h.h"
  25. #include <errno.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #endif
  30.  
  31. #ifdef __TURBOC__
  32. #include <stdio.h>
  33. #include <fcntl.h>
  34. #include <dos.h>
  35. #include "h.h"
  36. #include <errno.h>
  37. #include <ctype.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <process.h>
  41. #endif
  42.  
  43. #ifdef MSC
  44. #include <stdio.h>
  45. #include <fcntl.h>
  46. #include <io.h>
  47. #include <sys\types.h>
  48. #include <sys\stat.h>
  49. #include <process.h>
  50. #include <dos.h>
  51. #include "h.h"
  52. #include <errno.h>
  53. #include <ctype.h>
  54. #include <string.h>
  55. #include <stdlib.h>
  56. #endif
  57.  
  58. #define ARGN 64
  59.  
  60. static int  lifmade = 0;
  61. static char lifname[128] = "";
  62.  
  63. #ifdef DOLLAR
  64. static char dollarbuf[1024];
  65. #endif
  66.  
  67. #ifdef LATTICE
  68. #define O_TEXT 0
  69. #endif
  70.  
  71. #ifdef PAMDOS
  72. #define TESTINTERNAL 8      /* number of internal commands to test for */ 
  73. #endif
  74. #ifdef PAMOS2
  75. #define TESTINTERNAL 8      /* number of internal commands to test for */ 
  76. #endif
  77.  
  78.                             /* Dos internal commands, augment list if reqd */
  79. #ifdef TESTINTERNAL
  80. static char * internal[] =
  81. {
  82.     "ECHO",
  83.     "DEL",
  84.     "ERASE",
  85.     "MD",
  86.     "MKDIR",
  87.     "REN",
  88.     "RENAME",
  89.     "COPY",
  90. };
  91. #endif
  92.  
  93. /*****  remove special $ markers */
  94.  
  95. #ifdef DOLLAR
  96.  
  97. char *
  98. dollar(p)
  99. char *          p;
  100. {
  101.     register char *         q = dollarbuf;
  102.     
  103.     while (*p)
  104.     {
  105.         if ((*p & 0xff) == 0244) 
  106.         {
  107.             *q++ = '$';
  108.             p++;
  109.         }
  110.         else *q++ = *p++;
  111.     }
  112.     *q = '\0';
  113.     return dollarbuf;
  114. }
  115.  
  116. #endif
  117.  
  118. /****   test for common DOS and OS/2 internal commands, true if found */
  119.  
  120. #ifdef TESTINTERNAL
  121.  
  122. int dos_internal(s)
  123. char *          s;
  124. {
  125.     register int            i;
  126.     char *                  p;
  127.     char *                  q;
  128.  
  129.     while ((*s == ' ') && (*s != '\0')) s++;
  130.     for (i = 0; i < TESTINTERNAL; i++)
  131.     {
  132.         p = s;
  133.         q = internal[i];
  134.         while ( (*p != ' ') && ( (*p & 0x5f) == *q )) p++,q++;
  135.         if ((*p == ' ') && (*q == '\0')) return 1;
  136.     }
  137.     return 0;
  138. }
  139.  
  140. #endif
  141.  
  142. /*****  do the command */
  143.  
  144. int
  145. dosh(p, shell)
  146. char *          p;
  147. int             shell;
  148. {
  149. #ifdef VMS
  150.  
  151.     int result;
  152.  
  153.     result = 0xffff & system(dollar(p));
  154.     if (result == 33384) return 0;      /* LINK: compilation warnings */
  155.     if (result == PXNORMAL) return 0;
  156.     return result;
  157.     
  158. #else
  159.  
  160.     int                     argc;
  161.     char *                  argv[ARGN];
  162.     char                    c;
  163.     char *                  q;
  164.     char                    token[64];
  165.     register int            i;
  166.     char *                  mode;
  167.     int                     ret;
  168.     int                     r0,r1,r2;     
  169.  
  170.     p = dollar(p);
  171.     if (shell) return system(p);
  172.  
  173. #ifdef TESTINTERNAL         /* must be DOS or OS/2 */
  174.  
  175.     r0 = r1 = r2 = 0;       /* clear redirection switches */
  176.     if ((q = pstrstr(p,"<")) != (char *)0)
  177.     {
  178.         i = 0;
  179.         *q++ = ' ';
  180.         while (*q == ' ') q++;
  181.         while (!pspace(*q) && (*q != '\0') && (i < 63))
  182.         {
  183.             token[i++] = *q;
  184.             *q++ = ' ';
  185.         }
  186.         token[i] = '\0';
  187.         if (0 == freopen(token,"r",stdin)) return 999;
  188.         r0 = 1;
  189.     }
  190.     if ((q = pstrstr(p,"2>")) != (char *)0)
  191.     {
  192.         i = 0;
  193.         mode = "w";
  194.         *q++ = ' ';
  195.         *q++ = ' ';
  196.         if (*q == '>')
  197.         {
  198.             mode = "a";
  199.             *q++ = ' ';
  200.         }
  201.         while (*q == ' ') q++;
  202.         while (!pspace(*q) && (*q != '\0') && (i < 63))
  203.         {
  204.             token[i++] = *q;
  205.             *q++ = ' ';
  206.         }
  207.         token[i] = '\0';
  208.         if (0 == freopen(token,mode,stderr)) return 999;
  209.         r2 = 1;
  210.     }
  211.     if ((q = pstrstr(p,">")) != (char *)0)
  212.     {
  213.         i = 0;
  214.         mode = "w";
  215.         *q++ = ' ';
  216.         if (*q == '>')
  217.         {
  218.             mode = "a";
  219.             *q++ = ' ';
  220.         }
  221.         while (*q == ' ') q++;
  222.         while (!pspace(*q) && (*q != '\0') && (i < 63))
  223.         {
  224.             token[i++] = *q;
  225.             *q++ = ' ';
  226.         }
  227.         token[i] = '\0';
  228.         if (0 == freopen(token,mode,stdout)) return 999;
  229.         r1 = 1;
  230.     }
  231. #endif
  232.  
  233.     for (argc = 0; argc < ARGN-1; argc++) argv[argc] = 0;
  234.     for (argc = 0; argc < ARGN-1; )
  235.     {
  236.         while(pspace(*p)) p++;
  237.         if (*p == '\0') break;
  238.         argv[argc++] = p;
  239.         while ((*p != '\0') && (! pspace(*p))) p++;
  240.         c = *p;
  241.         *p++ = '\0';
  242.         if (c == '\0') break;
  243.     }
  244.  
  245. #ifdef LATTICE
  246.     if (-1 == forkvp(argv[0],argv)) ret = -1;
  247.     else
  248.     {
  249.         ret = wait();
  250.         if ((ret >> 8) == 1) ret = 4;
  251.         else if (ret) ret &= 0xff;
  252.     }
  253. #else
  254.     ret = spawnvp(P_WAIT,argv[0],argv);
  255. #endif
  256.  
  257. #ifdef TESTINTERNAL         /* must be DOS or OS/2 */
  258.  
  259.     if (r0) freopen("CON","r",stdin);
  260.     if (r1) freopen("CON","w",stdout);
  261.     if (r2) freopen("CON","w",stderr);
  262.  
  263. #endif
  264.     return ret;
  265. #endif
  266. }
  267.  
  268. /*****  create the local input file */
  269.  
  270. void
  271. makelif(cp)
  272. struct cmd *    cp;
  273. {
  274.     FILE *                  lifile;
  275.     struct lif *            lp;
  276.     struct macro *          mp;
  277.     char *                  p = lifname;
  278.     char *                  q;
  279.     static char *           ermsg = {"Unable to write local input file"};
  280.  
  281.     lifmade = 0;
  282.     if ( cp->c_lif == (struct lif *)0 ) return;
  283.     if ((mp = getmp("-")) != (struct macro *)0)
  284.     {
  285.         if (mp->m_sub) 
  286.         {
  287.             strncpy(lifname,mp->m_sub,127);
  288.             free(mp->m_sub);
  289.         }
  290.         else 
  291.             strncpy(lifname,mp->m_val,127);
  292.     }
  293.     else
  294.         lifname[0] = '\0';
  295.     while (*p == ' ') p++;
  296. #ifdef DOLLAR
  297.     strcpy(lifname,dollar(lifname));
  298. #endif
  299.     if (*p == '\0') strcpy(lifname,LIFNAME);
  300.     if ( (lifile = fopen(lifname,"w")) == NULL) fatal(ermsg);
  301.     for (lp = cp->c_lif; lp; lp = lp->f_next)
  302.     {
  303.         strcpy(str2, lp->f_lif);
  304.         expand(str2);
  305.         if (!strcmp(str2,"\\<")) strcpy(str2,"<");
  306.         while ((q = pstrstr(str2,"\\n")) != (char *)0)
  307.         {
  308.             *q++ = '\n';
  309.             while (*++q) *(q-1) = *q;
  310.             *--q = '\0';
  311.         }
  312.         if (fputs(dollar(str2),lifile) == EOF) fatal(ermsg);
  313.         if (fputs("\n",lifile) == EOF) fatal(ermsg);
  314.     }
  315.     if (fclose(lifile) == EOF) fatal(ermsg);
  316.     lifmade = 1;
  317. }
  318.  
  319. /*****  kill the local input file */
  320.  
  321. void
  322. killlif()
  323. {
  324.     if (lifmade) unlink(lifname);
  325. }
  326.  
  327. /*****  do the %set command */
  328.  
  329. void
  330. dosetcmd(p)
  331. char *          p;
  332. {
  333.     char *                  q;
  334.     char *                  pp;
  335.  
  336.     while (pspace(*p)) p++;    /* find first target */
  337.  
  338.     pp = p;
  339.     while (((q = strchr(p, '=')) != (char *)0) &&
  340.         (p != q) && (q[-1] == '\\'))        /*  Find value */
  341.     {
  342.         register char * a;
  343.  
  344.         a = q - 1;              /* del \ chr; move rest back */
  345.         p = q;
  346.         while ((*a++ = *q++) != '\0') ;
  347.     }
  348.  
  349.     if (q != (char *)0)
  350.     {
  351.         register char * a;
  352.  
  353.         *q++ = '\0';            /* separate name and val */
  354.         while (pspace(*q)) q++;
  355.         if ((a = gettok(&pp)) == (char *)0)
  356.             error("Macro definition without macro name");
  357.         setmacro(a, q);
  358.     }
  359. }
  360.  
  361. /*****  do the %stat command */
  362.  
  363. void
  364. dostatcmd(p)
  365. char *          p;
  366. {
  367.     struct name *           q;
  368.  
  369.     while (pspace(*p)) p++;    /* find filename */
  370.     q = newname(p);
  371.     if (q->n_flag & N_TARG)
  372.     {
  373.         modtime(q);
  374.         q->n_flag &= ~N_DONE;
  375.     }
  376. }
  377.  
  378. /*****  do a set of commands to make a target */
  379.  
  380. void
  381. docmds1(np,lp)
  382. struct name *   np;
  383. struct line *   lp;
  384. {
  385.     bool                    ssilent;
  386.     bool                    signore;
  387.     bool                    sdomake;
  388.     int                     estat;
  389.     register char *         q;
  390.     register char *         p;
  391.     int                     shell;
  392.     register struct cmd *   cp;
  393.     int                     specialhash;
  394.  
  395.     for (cp = lp->l_cmd; cp; cp = cp->c_next)
  396.     {
  397.         shell = 0;
  398.         ssilent = silent;
  399.         signore = ignore;
  400.         sdomake = domake;
  401.         strcpy(str1, cp->c_cmd);
  402.         if (!strncmp(str1,"%ifn",4)) specialhash = 2;
  403.         else if (!strncmp(str1,"%if",3)) specialhash = 1;
  404.         else if (!strncmp(str1,"%else",5)) specialhash = 3;
  405.         else if (!strncmp(str1,"%endif",6)) specialhash = 4;
  406.         else if (!strncmp(str1,"%set",4)) specialhash = 5;
  407.         else if (!strncmp(str1,"%exit",5)) specialhash = 6;
  408.         else if (!strncmp(str1,"%stat",5)) specialhash = 7;
  409.         else specialhash = 0;
  410.  
  411.         if (ifproc(str1,specialhash)) continue;
  412.         if (specialhash == 6) exit(atoi(str1+5));
  413.         if (specialhash == 5)
  414.         {
  415.             dosetcmd(str1+4);
  416.             continue;
  417.         }
  418.         if (specialhash == 7)
  419.         {
  420.             dostatcmd(str1+5);
  421.             continue;
  422.         }
  423.  
  424.         if (pstrstr(str1,"$(MAKE)")) sdomake = TRUE;
  425.         expand(str1);
  426.         q = str1;
  427.         while ((*q == '@') || (*q == '-') || (*q == '+') || (*q == '\\'))
  428.         {
  429.             if (*q == '@') ssilent = TRUE;      /* specific silent */
  430.             else if (*q == '-') signore = TRUE; /* specific ignore */
  431.             else if (*q == '+') shell = 1;      /* specific shell */
  432.             else                                /* must be \ */
  433.             {
  434.                 q++;                            /* skip past \ */
  435.                 if ((*q == '@') || (*q == '-') || (*q == '+')) break;
  436.                 else                            /* \ is a real char */
  437.                 {
  438.                     q--;                        /* make it start command */
  439.                     break;                      /* no more specials */
  440.                 }
  441.             }
  442.             q++;                                /* skip past special char */
  443.         }
  444. #ifdef TESTINTERNAL
  445.         if ( dos_internal(q) ) shell = 1;
  446. #endif
  447.  
  448.         if (!ssilent) fputs("    ", stdout);
  449.  
  450.         for (p = q; *p; p++)
  451.         {
  452.             if (*p == '\n' && p[1] != '\0')
  453.             {
  454.                 *p = ' ';
  455.                 if (!ssilent) fputs("\\\n", stdout);
  456.             }
  457.             else if (!ssilent)
  458.             {
  459. #ifdef DOLLAR
  460.                 if ((*p & 0xff) == 0244) 
  461.                     putchar('$');
  462.                 else
  463. #endif
  464.                     putchar(*p);
  465.             }
  466.         }
  467.         if (!ssilent) putchar('\n');
  468.  
  469.         if (sdomake)
  470.         {                       /*  Get the shell to execute it  */
  471.             makelif(cp);
  472.             estat = dosh(q, shell);
  473.             killlif();
  474. #ifdef PAMDOS
  475.             bdos(0xb,0,0);    /* check control break */
  476. #endif
  477.             if (estat != 0)
  478.             {
  479.                 if (shell)
  480.                 {
  481.                     if (pamakeos2 & signore) fputs("(Ignored)\n",stdout);
  482.                     else
  483.                         fatal("Couldn't execute shell");
  484.                 }
  485.                 else
  486.                 {
  487.                     if (estat==4) printf("%s: Interrupted", myname);
  488.                     else if (estat==-1) printf("%s: Couldn't execute command",myname);
  489.                     else if (estat==999) printf("%s: Redirection error",myname);
  490.                     else printf("%s: Error return %d", myname, estat);
  491.                     if ( (signore || !domake) && (estat != 4))
  492.                         fputs(" (Ignored)\n", stdout);
  493.                     else 
  494.                     {
  495.                         putchar('\n');
  496.                         if (!(np->n_flag & N_PREC) && (estat != -1))
  497.                             if (unlink(dollar(np->n_name)) == 0)
  498.                                 printf("%s: '%s' removed\n", myname, dollar(np->n_name));
  499.                         exit(estat);
  500.                     }
  501.                 }
  502.             }
  503.         }
  504.     }
  505.     ifeoc();         /* check for unterminated if in cmds */
  506. }
  507.  
  508. /***** do commands to make a target */
  509.  
  510. void
  511. docmds(np)
  512. struct name *   np;
  513. {
  514.     struct name *           dft;
  515.     register struct line *  rp;
  516.     struct line *           lp;
  517.     bool                    hascmds = FALSE;
  518.  
  519.     for
  520.         (
  521.         rp = np->n_line;
  522.         rp;
  523.         rp = rp->l_next
  524.         )
  525.         if (rp->l_cmd) hascmds = TRUE;
  526.  
  527.     if (!hascmds)
  528.     {
  529.         dft = newname(".DEFAULT");
  530.         if (dft->n_flag & N_TARG) np->n_line = dft->n_line;
  531.     }
  532.  
  533.     for (lp = np->n_line; lp; lp = lp->l_next)
  534.         docmds1(np,lp);
  535. }
  536.  
  537.  
  538.  
  539. /*****  set $< and $* for the first dependancy name */
  540. /*****  set $? to list of out-of-date dependency names */
  541.  
  542. void
  543. setdmacros(np,qdp)
  544. struct name *   np;
  545. struct depend * qdp;
  546. {
  547.     char *                  p;
  548.     char *                  q;
  549.     char *                  suff;
  550.     char *                  suffix();
  551.     register struct depend *dp;
  552.     register struct line *  lp;
  553.     int                     found = 0;
  554.  
  555.     strcpy(str1, "");
  556.     for (dp = qdp; dp; dp = qdp)
  557.     {
  558.         if ((strlen(str1) + strlen(dp->d_name->n_name) + 2) > LZ)
  559.             fatal("$? macro is too long");
  560.         if (strlen(str1)) strcat(str1, " ");
  561.         strcat(str1, dp->d_name->n_name);
  562.         qdp = dp->d_next;
  563.         free(dp);
  564.     }
  565.     setmacro("?", str1);
  566.  
  567.     for (lp = np->n_line; lp; lp = lp->l_next)
  568.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  569.         {
  570.             if ( (!found) || (dp->d_name->n_flag & N_DYND) )
  571.             {
  572.                 q = dp->d_name->n_name;
  573.                 setmacro("<",q);
  574.                 p = str1;
  575.                 suff = suffix(q);
  576.                 while (q < suff) *p++ = *q++;
  577.                 *p = '\0';
  578.                 setmacro("*",str1);
  579.                 if (found) return;
  580.                 found++;
  581.             }
  582.         }
  583. }
  584.  
  585. /*****  clear the dynamic dep flag for all deps of this target */
  586. /*****  (in case this dep is used again for another target) */
  587.  
  588. void
  589. cleardynflag(np)
  590. struct name *   np;
  591. {
  592.     register struct depend *dp;
  593.     register struct line *  lp;
  594.  
  595.     for (lp = np->n_line; lp; lp = lp->l_next)
  596.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  597.             dp->d_name->n_flag &= ~N_DYND;
  598. }
  599.  
  600. /*****  make one thing */
  601.  
  602. void            
  603. make1(np, lp, qdp)
  604. struct depend *                qdp;
  605. struct line *                  lp;
  606. struct name *                  np;
  607. {
  608.     if (dotouch) touch(np);
  609.     else
  610.     {
  611.         setmacro("@", np->n_name);  /* NOTE: *not* dollar() */
  612.         setdmacros(np,qdp);
  613.         if (lp) docmds1(np, lp);    /* lp set if doing a :: rule */
  614.         else docmds(np);
  615.     }
  616. }
  617.  
  618. /*****  recursive routine to make a target */
  619.  
  620. int
  621. make(np, level)
  622. struct name *   np;
  623. int             level;
  624. {
  625.     register struct depend *dp;
  626.     register struct line *  lp;
  627.     long                    dtime = 1;
  628.     register struct depend *qdp;
  629.     int                     didsomething = 0;
  630.  
  631.     if (np->n_flag & N_DONE)
  632.     {
  633.         if ( display ) dodisp(dollar(np->n_name),np->n_time);
  634.         return 0;
  635.     }
  636.  
  637.     if (!np->n_time)
  638.         modtime(np);            /*  Gets modtime of this file  */
  639.  
  640.     if ( display ) dodisp(dollar(np->n_name),np->n_time);
  641.  
  642.     for (lp = np->n_line; lp; lp = lp->l_next)
  643.         if (lp->l_cmd) break;
  644.     if (!lp) dyndep(np);
  645.  
  646.     if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  647.         fatal("Don't know how to make %s", dollar(np->n_name));
  648.  
  649.     for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
  650.     {
  651.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  652.         {
  653.             make(dp->d_name, level+1);
  654. #ifdef DEBUG
  655.             printf("%s, %lx, %s, %lx\n",
  656.                 np->n_name,np->n_time, dp->d_name->n_name, dp->d_name->n_time);
  657. #endif
  658.             if (np->n_time < dp->d_name->n_time)
  659.                 qdp = newdep(dp->d_name, qdp);
  660.             if (dtime < dp->d_name->n_time) dtime = dp->d_name->n_time; 
  661.         }
  662.         if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
  663.         {
  664.             make1(np, lp, qdp);     /* free()'s qdp */
  665.             dtime = 1;
  666.             qdp = (struct depend *)0;
  667.             didsomething++;
  668.         }
  669.     }
  670.  
  671.     np->n_flag |= N_DONE;
  672.  
  673.     if (quest)
  674.     {
  675.         long t;
  676.         t = np->n_time;
  677.         np->n_time = curtime();
  678.         cleardynflag(np);
  679.         return t < dtime;
  680.     }
  681.     else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
  682.     {
  683. #ifdef DEBUG
  684.             printf("%s, %lx, dtime, %lx\n",
  685.                 np->n_name,np->n_time, dtime);
  686. #endif
  687.         make1(np, (struct line *)0, qdp);
  688.         if (confirm)
  689.             modtime(np);
  690.         else
  691.         {
  692.             np->n_time = curtime();
  693.         }
  694.     }
  695.     else if (level == 0 && !didsomething)
  696.         printf("%s: '%s' is up to date\n", myname, dollar(np->n_name));
  697.     cleardynflag(np);
  698.     return 0;
  699. }
  700.