home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / make / make.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-12-02  |  7.5 KB  |  453 lines

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