home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / pdmake / make.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-12-16  |  11.5 KB  |  526 lines

  1.     /***************************************************************\
  2.     *                                *
  3.     *  PDMAKE, Atari ST version                    *
  4.     *                                *
  5.     *  Adapted from mod.sources Vol 7 Issue 71, 1986-12-03.        *
  6.     *                                *
  7.     *  This port makes extensive use of the original net.sources    *
  8.     *  port by Jwahar Bammi.                    *
  9.     *                                *
  10.     *      Ton van Overbeek                        *
  11.     *      Email: TPC862@ESTEC.BITNET                *
  12.     *             TPC862%ESTEC.BITNET@WISCVM.WISC.EDU    (ARPA)    *
  13.     *             ...!mcvax!tpc862%estec.bitnet   (UUCP Europe)    *
  14.     *             ...!ucbvax!tpc862%estec.bitnet  (UUCP U.S.A.)    *
  15.     *             71450,3537  (CompuServe)                *
  16.     *                                *
  17.     \***************************************************************/
  18.  
  19. /*
  20.  *    Do the actual making for make
  21.  */
  22.  
  23. #include <stdio.h>
  24.  
  25. #ifdef unix
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/errno.h>
  29. #endif
  30. #ifdef eon
  31. #include <sys/stat.h>
  32. #include <sys/err.h>
  33. #endif
  34. #ifdef os9
  35. #include <time.h>
  36. #include <os9.h>
  37. #include <modes.h>
  38. #include <direct.h>
  39. #include <errno.h>
  40. #endif
  41. #ifdef ATARIST
  42. #include "astat.h"
  43. #endif
  44.  
  45. #include "h.h"
  46.  
  47.  
  48.  
  49. /*
  50.  *    Exec a shell that returns exit status correctly (/bin/esh).
  51.  *    The standard EON shell returns the process number of the last
  52.  *    async command, used by the debugger (ugg).
  53.  *    [exec on eon is like a fork+exec on unix]
  54.  */
  55. int
  56. dosh(string, shell)
  57. char *    string;
  58. char *    shell;
  59. {
  60.     int    number;
  61.  
  62. #ifdef unix
  63.     return system(string);
  64. #endif
  65. #ifdef ATARIST
  66.     return system(string);
  67. #endif
  68. #ifdef eon
  69.     return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
  70.         -1:    /* couldn't start the shell */
  71.         wait(number);    /* return its exit status */
  72. #endif
  73. #ifdef os9
  74.     int    status, pid;
  75.  
  76.     strcat(string, "\n");
  77.     if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  78.         return -1;        /* Couldn't start a shell */
  79.     do
  80.     {
  81.         if ((pid = wait(&status)) == -1)
  82.             return -1;    /* child already died!?!? */
  83.     } while (pid != number);
  84.  
  85.     return status;
  86. #endif
  87. }
  88.  
  89.  
  90. /*
  91.  *    Do commands to make a target
  92.  */
  93. void
  94. docmds1(np, lp)
  95. struct name *        np;
  96. struct line *        lp;
  97. {
  98.     bool            ssilent;
  99.     bool            signore;
  100.     int            estat;
  101.     register char *        q;
  102.     register char *        p;
  103.     char *            shell;
  104.     register struct cmd *    cp;
  105.  
  106.  
  107.     if (*(shell = getmacro("SHELL")) == '\0')
  108. #ifdef eon
  109.         shell = ":bin/esh";
  110. #endif
  111. #ifdef unix
  112.         shell = "/bin/sh";
  113. #endif
  114. #ifdef os9
  115.         shell = "shell";
  116. #endif
  117.  
  118.     for (cp = lp->l_cmd; cp; cp = cp->c_next)
  119.     {
  120.         strcpy(str1, cp->c_cmd);
  121.         expand(str1);
  122.         q = str1;
  123.         ssilent = silent;
  124.         signore = ignore;
  125.         while ((*q == '@') || (*q == '-'))
  126.         {
  127.             if (*q == '@')       /*  Specific silent  */
  128.                 ssilent = TRUE;
  129.             else           /*  Specific ignore  */
  130.                 signore = TRUE;
  131.             q++;           /*  Not part of the command  */
  132.         }
  133.  
  134.         if (!domake)
  135.             ssilent = 0;
  136.  
  137.         if (!ssilent)
  138.             fputs("    ", stdout);
  139.  
  140.         for (p=q; *p; p++)
  141.         {
  142.             if (*p == '\n' && p[1] != '\0')
  143.             {
  144.                 *p = ' ';
  145.                 if (!ssilent)
  146.                     fputs("\\\n", stdout);
  147.             }
  148.             else if (!ssilent)
  149.                 putchar(*p);
  150.         }
  151.         if (!ssilent)
  152.             putchar('\n');
  153.  
  154.         if (domake)
  155.         {            /*  Get the shell to execute it  */
  156.             if ((estat = dosh(q, shell)) != 0)
  157.             {
  158.                 if (estat == -1)
  159. #ifdef ATARIST
  160.                     fatal("Couldn't execute %s", q);
  161. #else
  162.                     fatal("Couldn't execute %s", shell);
  163. #endif
  164.                 else
  165.                 {
  166.                     printf("%s: Error code %d", myname, estat);
  167.                     if (signore)
  168.                         fputs(" (Ignored)\n", stdout);
  169.                     else
  170.                     {
  171.                         putchar('\n');
  172.                         if (!(np->n_flag & N_PREC))
  173.                             if (unlink(np->n_name) == 0)
  174.                                 printf("%s: '%s' removed.\n", myname,
  175.                                        np->n_name);
  176.                         exit(estat);
  177.                     }
  178.                 }
  179.             }
  180.         }
  181.     }
  182. }
  183.  
  184.  
  185. docmds(np)
  186. struct name *    np;
  187. {
  188.     register struct line *    lp;
  189.  
  190.  
  191.     for (lp = np->n_line; lp; lp = lp->l_next)
  192.         docmds1(np, lp);
  193. }
  194.  
  195.  
  196. #ifdef os9
  197. /*
  198.  *    Some stuffing around to get the modified time of a file
  199.  *    in an os9 file system
  200.  */
  201. getmdate(fd, tbp)
  202. struct sgtbuf *        tbp;
  203. {
  204.     struct registers    regs;
  205.     static struct fildes    fdbuf;
  206.  
  207.  
  208.     regs.rg_a = fd;
  209.     regs.rg_b = SS_FD;
  210.     regs.rg_x = &fdbuf;
  211.     regs.rg_y = sizeof (fdbuf);
  212.  
  213.     if (_os9(I_GETSTT, ®s) == -1)
  214.     {
  215.         errno = regs.rg_b & 0xff;
  216.         return -1;
  217.     }
  218.     if (tbp)
  219.     {
  220.         _strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
  221.         tbp->t_second = 0;    /* Files are only acurate to mins */
  222.     }
  223.     return 0;
  224. }
  225.  
  226.  
  227. /*
  228.  *    Kludge routine to return an aproximation of how many
  229.  *    seconds since 1980.  Dates will be in order, but will not
  230.  *    be lineer
  231.  */
  232. time_t
  233. cnvtime(tbp)
  234. struct sgtbuf        *tbp;
  235. {
  236.     long            acc;
  237.  
  238.  
  239.     acc = tbp->t_year - 80;        /* Baseyear is 1980 */
  240.     acc = acc * 12 + tbp->t_month;
  241.     acc = acc * 31 + tbp->t_day;
  242.     acc = acc * 24 + tbp->t_hour;
  243.     acc = acc * 60 + tbp->t_minute;
  244.     acc = acc * 60 + tbp->t_second;
  245.  
  246.     return acc;
  247. }
  248.  
  249.  
  250. /*
  251.  *    Get the current time in the internal format
  252.  */
  253. time(tp)
  254. time_t *        tp;
  255. {
  256.     struct sgtbuf        tbuf;
  257.  
  258.  
  259.     if (getime(&tbuf) < 0)
  260.         return -1;
  261.  
  262.     if (tp)
  263.         *tp = cnvtime(&tbuf);
  264.  
  265.     return 0;
  266. }
  267. #endif
  268.  
  269. #ifdef ATARIST
  270. /*
  271.  *    Get the current time in the internal format
  272.  */
  273. time(tp)
  274. time_t *        tp;
  275. {
  276.     if (tp)
  277.         *tp = Gettime();
  278.  
  279.     return 0;
  280. }
  281. #endif
  282.  
  283. /*
  284.  *    Get the modification time of a file.  If the first
  285.  *    doesn't exist, it's modtime is set to 0.
  286.  */
  287. void
  288. modtime(np)
  289. struct name *    np;
  290. {
  291. #ifdef unix
  292.     struct stat        info;
  293.     int            fd;
  294.  
  295.  
  296.     if (stat(np->n_name, &info) < 0)
  297.     {
  298.         if (errno != ENOENT)
  299.             fatal("Can't open %s; error %d", np->n_name, errno);
  300.  
  301.         np->n_time = 0L;
  302.     }
  303.     else
  304.         np->n_time = info.st_mtime;
  305. #endif
  306. #ifdef eon
  307.     struct stat        info;
  308.     int            fd;
  309.  
  310.  
  311.     if ((fd = open(np->n_name, 0)) < 0)
  312.     {
  313.         if (errno != ER_NOTF)
  314.             fatal("Can't open %s; error %02x", np->n_name, errno);
  315.  
  316.         np->n_time = 0L;
  317.     }
  318.     else if (getstat(fd, &info) < 0)
  319.         fatal("Can't getstat %s; error %02x", np->n_name, errno);
  320.     else
  321.         np->n_time = info.st_mod;
  322.  
  323.     close(fd);
  324. #endif
  325. #ifdef os9
  326.     struct sgtbuf    info;
  327.     int            fd;
  328.  
  329.  
  330.     if ((fd = open(np->n_name, 0)) < 0)
  331.     {
  332.         if (errno != E_PNNF)
  333.             fatal("Can't open %s; error %02x", np->n_name, errno);
  334.  
  335.         np->n_time = 0L;
  336.     }
  337.     else if (getmdate(fd, &info) < 0)
  338.         fatal("Can't getstat %s; error %02x", np->n_name, errno);
  339.     else
  340.         np->n_time = cnvtime(&info);
  341.  
  342.     close(fd);
  343. #endif
  344. #ifdef ATARIST
  345.     struct stat        info;
  346.     extern int        getstat();        /*  in ststuff.c  */
  347.     extern void        FlipWords();        /*  in ststuff.c  */
  348.  
  349.     if (getstat(np->n_name, &info) < 0)
  350.         np->n_time = 0L;
  351.     else
  352.     {
  353.         FlipWords(&info.st_mod);
  354.         np->n_time = info.st_mod;
  355.     }
  356. #endif
  357. }
  358.  
  359.  
  360. /*
  361.  *    Update the mod time of a file to now.
  362.  */
  363. void
  364. touch(np)
  365. struct name *    np;
  366. {
  367.     char    c;
  368.     int        fd;
  369.  
  370.  
  371.     if (!domake || !silent)
  372.         printf("    touch(%s)\n", np->n_name);
  373.  
  374.     if (domake)
  375.     {
  376. #ifdef unix
  377.         long    a[2];
  378.  
  379.         a[0] = a[1] = time(0);
  380.         if (utime(np->n_name, &a[0]) < 0)
  381.             printf("%s: '%s' not touched - non-existant\n",
  382.                     myname, np->n_name);
  383. #endif
  384. #ifdef eon
  385.         if ((fd = open(np->n_name, 0)) < 0)
  386.             printf("%s: '%s' not touched - non-existant\n",
  387.                     myname, np->n_name);
  388.         else
  389.         {
  390.             uread(fd, &c, 1, 0);
  391.             uwrite(fd, &c, 1);
  392.         }
  393.         close(fd);
  394. #endif
  395. #ifdef os9
  396.         /*
  397.          *    Strange that something almost as totally useless
  398.          *    as this is easy to do in os9!
  399.          */
  400.         if ((fd = open(np->n_name, S_IWRITE)) < 0)
  401.             printf("%s: '%s' not touched - non-existant\n",
  402.                     myname, np->n_name);
  403.         close(fd);
  404. #endif
  405. #ifdef ATARIST
  406.         if ((fd = Fopen(np->n_name, 0)) < 0)
  407.             printf("%s: '%s' not touched - non-existant\n",
  408.                     myname, np->n_name);
  409.         else
  410.         {
  411.             long tim;
  412.  
  413.             tim = Gettime();
  414.             FlipWords(&tim);
  415.             if (Fdatime( &tim, fd, 1) < 0)
  416.                 printf("%s: '%s' not touched - disk protected ?\n",
  417.                         myname, np->n_name);
  418.             Fclose(fd);
  419.         }
  420. #endif
  421.     }
  422. }
  423.  
  424.  
  425. /*
  426.  *    Recursive routine to make a target.
  427.  */
  428. int
  429. make(np, level)
  430. struct name *    np;
  431. int        level;
  432. {
  433.     register struct depend *    dp;
  434.     register struct line *    lp;
  435.     register struct depend *    qdp;
  436.     time_t            dtime = 1;
  437.     bool            didsomething = 0;
  438.  
  439.  
  440.     if (np->n_flag & N_DONE)
  441.         return 0;
  442.  
  443.     if (!np->n_time)
  444.         modtime(np);            /*  Gets modtime of this file  */
  445.  
  446.     if (rules)
  447.     {
  448.         for (lp = np->n_line; lp; lp = lp->l_next)
  449.             if (lp->l_cmd)
  450.                 break;
  451.         if (!lp)
  452.             dyndep(np);
  453.     }
  454.  
  455.     if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  456.         fatal("Don't know how to make %s", np->n_name);
  457.  
  458.     for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
  459.     {
  460.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  461.         {
  462.             make(dp->d_name, level+1);
  463.             if (np->n_time < dp->d_name->n_time)
  464.                 qdp = newdep(dp->d_name, qdp);
  465.             dtime = max(dtime, dp->d_name->n_time);
  466.         }
  467.         if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
  468.         {
  469.             make1(np, lp, qdp);            /* free()'s qdp */
  470.             dtime = 1;
  471.             qdp = (struct depend *)0;
  472.             didsomething++;
  473.         }
  474.     }
  475.  
  476.     np->n_flag |= N_DONE;
  477.  
  478.     if (quest)
  479.     {
  480.         long        t;
  481.  
  482.         t = np->n_time;
  483.         time(&np->n_time);
  484.         return t < dtime;
  485.     }
  486.     else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
  487.     {
  488.         make1(np, (struct line *)0, qdp);    /* free()'s qdp */
  489.         time(&np->n_time);
  490.     }
  491.     else if (level == 0 && !didsomething)
  492.         printf("%s: '%s' is up to date\n", myname, np->n_name);
  493.     return 0;
  494. }
  495.  
  496.  
  497. make1(np, lp, qdp)
  498. register struct depend *    qdp;
  499. struct line *    lp;
  500. struct name *    np;
  501. {
  502.     register struct depend *    dp;
  503.  
  504.  
  505.     if (dotouch)
  506.         touch(np);
  507.     else
  508.     {
  509.         strcpy(str1, "");
  510.         for (dp = qdp; dp; dp = qdp)
  511.         {
  512.             if (strlen(str1))
  513.                 strcat(str1, " ");
  514.             strcat(str1, dp->d_name->n_name);
  515.             qdp = dp->d_next;
  516.             free(dp);
  517.         }
  518.         setmacro("?", str1);
  519.         setmacro("@", np->n_name);
  520.         if (lp)                    /* lp set if doing a :: rule */
  521.             docmds1(np, lp);
  522.         else
  523.             docmds(np);
  524.     }
  525. }
  526.