home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 216.lha / PdMake / make.c < prev    next >
C/C++ Source or Header  |  1996-02-15  |  9KB  |  370 lines

  1. /*
  2.  *     Do the actual making for make
  3.  */
  4.  
  5. #include <stdio.h>
  6.  
  7. #ifdef unix
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <sys/errno.h>
  11. #endif
  12.  
  13. #include "h.h"
  14.  
  15. #ifdef MCH_AMIGA
  16.  
  17. /* test if timestamp is NULL */
  18.  
  19. null_time(t) TimeStamp *t;
  20. {    return !(t->t[0] || t->t[1] || t->t[2]);
  21. }
  22.  
  23. /* cmp_time(t1,t2) - compare two timestamps
  24.  
  25.  returns    >0 if (t1 > t2)
  26.              0 if (t1 = t2)
  27.             <0 if (t1 < t2)
  28. */
  29.  
  30. cmp_time(t1,t2) TimeStamp *t1,*t2;
  31. {    long l;
  32.     if (l = t1->t[0] - t2->t[0]) return l;
  33.     if (l = t1->t[1] - t2->t[1]) return l;
  34.     return t1->t[2]-t2->t[2];
  35. }
  36.  
  37. TimeStamp time_zero = { 0,0,0 };            /* a null timestamp */
  38. TimeStamp time_one  = { 0,0,1 };            /* a mostly null timestamp */
  39.  
  40. #endif
  41.  
  42. /* DJ notes -
  43.     is the idea of alternate shells applicaple here? Do we want this make
  44.     to support things like ARexx?
  45.     Currently there's no support for such in the code...
  46. */
  47.  
  48. /*
  49.  *     Exec a shell that returns exit status correctly (/bin/esh).
  50.  */
  51. int
  52. dosh(string, shell)
  53. char *            string;
  54. char *            shell;
  55. {    return xsystem(string);
  56. }
  57.  
  58.  
  59. /*
  60.  *     Do commands to make a target
  61.  */
  62. void
  63. docmds1(np, lp)
  64. struct name                *np;
  65. struct line                *lp;
  66. {
  67.     bool                ssilent;
  68.     bool                signore;
  69.     int                    estat;
  70.     register char        *q;
  71.     register char        *p;
  72.     char                *shell;
  73.     register struct cmd    *cp;
  74.  
  75.     /* shell code is commented out for now */
  76. #if 0
  77.     if (*(shell = getmacro("SHELL")) == '\0')        /* if no shell defined */
  78. #ifdef unix
  79.         shell = "/bin/sh";                            /* use default shell */
  80. #else
  81.         shell = NULL;                                /* use normal shell */
  82. #endif
  83. #endif
  84.  
  85.     for (cp = lp->l_cmd; cp; cp = cp->c_next)        /* for each command in line */
  86.     {
  87.         strcpy(str1, cp->c_cmd);                    /* get command string */
  88.         expand(str1);                                /* expand macros */
  89.         q = str1;                                    /* string pointer */
  90.         ssilent = silent;                            /* get 'silent' flag */
  91.         signore = ignore;                            /* get 'ignore' flag */
  92.         while ((*q == '@') || (*q == '-'))
  93.         {    if (*q == '@')                             /* Specific silent  */
  94.                 ssilent = TRUE;                        /* silence this command */
  95.             else                                    /* Specific ignore  */
  96.                 signore = TRUE;                        /* ignore return code */
  97.             q++;                                     /*  Not part of the command  */
  98.         }
  99.  
  100.         if (!domake) ssilent = 0;                    /* not silent if no make */
  101.         if (!ssilent) fputs("    ", stdout);        /* put out a tab */
  102.  
  103.         for (p=q; *p; p++)
  104.         {    if (*p == '\n' && p[1] != '\0')            /* if a carriage return */
  105.             {    *p = ' ';                            /* make it a space */
  106.                 if (!ssilent)                        /* and if not silent */
  107.                     fputs("\\\n", stdout);            /* print a slash */
  108.             }
  109.             else if (!ssilent)                        /* if not silent */
  110.                 putchar(*p);                        /* print the character */
  111.         }
  112.         if (!ssilent)                                /* if not silent */
  113.             putchar('\n');                            /* print a newline */
  114.  
  115.         if (!domake) return;                        /* return if pretending */
  116.  
  117.             /*  Get the shell to execute it    */
  118.         if ((estat = dosh(q, shell)) != 0)            /* if an error code */
  119.         {
  120.  
  121. /* add some more status stuff in here, like 'Interrupted', etc. */
  122.  
  123.             if (estat == -1)                        /* -1 = couldn't execute */
  124.                 fatal("Couldn't execute %s", shell);
  125.             else
  126.             {    printf("%s: Error code %d", myname, estat);
  127.                 if (signore)                        /* if ignore command return */
  128.                     fputs(" (Ignored)\n", stdout);    /* then indicate so */
  129.                 else                                /* otherwise */
  130.                 {    putchar('\n');                    /* newline */
  131.                     if (!(np->n_flag & N_PREC))        /* delete target file ?? */
  132.                         if (unlink(np->n_name) == 0)
  133.                             printf("%s: '%s' removed.\n", myname, np->n_name);
  134.                     exit(estat);
  135.                 }
  136.             }
  137.         }
  138.     }
  139. }
  140.  
  141. docmds(np)
  142. struct name                    *np;
  143. {
  144.     register struct line    *lp;
  145.  
  146.     for (lp = np->n_line; lp; lp = lp->l_next)    /* for each line in the entry */
  147.         docmds1(np, lp);                        /* do the command */
  148. }
  149.  
  150.  
  151. /*
  152.  *     Get the modification time of a file.  If the first
  153.  *     doesn't exist, it's modtime is set to 0.
  154.  */
  155. void
  156. modtime(np)
  157. struct name *        np;
  158. {
  159. #ifdef unix
  160.     struct stat        info;
  161.     int            fd;
  162.  
  163.  
  164.     if (stat(np->n_name, &info) < 0)
  165.     {
  166.         if (errno != ENOENT)
  167.             fatal("Can't open %s; error %d", np->n_name, errno);
  168.  
  169.         np->n_time = 0L;
  170.     }
  171.     else
  172.         np->n_time = info.st_mtime;
  173. #endif
  174. #ifdef MCH_AMIGA
  175.     {    if (!GetFileDate(np->n_name,&np->n_time))
  176.         {    if (IoErr()==205) np->n_time = time_zero;
  177.             else fatal("Can't get date for file %s", np->n_name);
  178.         }
  179.     }
  180. #endif
  181. }
  182.  
  183. /*
  184.  *     Update the mod time of a file to now.
  185.  */
  186. void
  187. touch(np)
  188. struct name *        np;
  189. {
  190.     char            c;
  191.     int            fd;
  192.  
  193.  
  194.     if (!domake || !silent)
  195.         printf("    touch(%s)\n", np->n_name);
  196.  
  197.     if (domake)
  198.     {
  199. #ifdef unix
  200.         long        a[2];
  201.  
  202.         a[0] = a[1] = time(0);
  203.         if (utime(np->n_name, &a[0]) < 0)
  204.             printf("%s: '%s' not touched - non-existant\n",
  205.                     myname, np->n_name);
  206. #endif
  207. #ifdef MCH_AMIGA
  208.     /* insert a SetFileDate function here */
  209. #endif
  210.     }
  211. }
  212.  
  213. /* from PAMAKE */
  214.  
  215. #if 0
  216.  
  217. /*
  218.  *      Clear the dynamic dep flag for all deps of this target,
  219.  *      in case this dep is used again for another target
  220.  */
  221.  
  222. void cleardynflag(np)
  223.     struct name                *np;
  224. {    register struct depend    *dp;
  225.     register struct line    *lp;
  226.  
  227.     for (lp = np->n_line; lp; lp = lp->l_next)
  228.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  229.                dp->d_name->n_flag &= ~N_DYND;
  230. }
  231.  
  232. /*
  233.  *      Display the timestamp
  234.  */
  235. void dodisp(name,t)
  236. char         *name;
  237. time_t         t;            /* fix */
  238. {
  239.         if (t < 10)
  240.            printf("... %s Timestamp %ld\n",name,t);
  241.         else 
  242.          printf("... %s Timestamp %s",name,ctime(&t));
  243. }
  244. #endif
  245.  
  246. /*
  247.  *     Recursive routine to make a target.
  248.  */
  249. int make(np, level)
  250.     struct name                 *np;                /* name pointer */
  251.     int                            level;                /* how many levels down */
  252. {    register struct depend         *dp;                /* dependancy */
  253.     register struct line        *lp;
  254.     register struct depend         *qdp;
  255.     TimeStamp                    dtime;
  256.     bool                        didsomething = 0;
  257.  
  258.     dtime = time_zero;
  259.  
  260. #if 0
  261.         /* from PAMAKE */
  262.     if (np->n_flag & N_DONE)
  263.         {
  264.         if ( display ) dodisp(np->n_name,np->n_time);
  265.         return 0;
  266.         }
  267. #endif
  268.  
  269.     if (np->n_flag & N_DONE) return 0;    /* if we already did this... */
  270.  
  271.     if (null_time(&np->n_time))            /* if time == time_zero */
  272.         modtime(np);                    /*  get modtime of this file  */
  273.  
  274. /*    if ( display ) dodisp(np->n_name,&np->n_time); */ /* from PAMAKE */
  275.  
  276.     if (rules)                            /* if using inbuilt rules */
  277.     {    for (lp = np->n_line; lp; lp = lp->l_next)    /* search line list of entry */
  278.             if (lp->l_cmd) break;        /* if line has a command, then do it */
  279.         if (!lp) dyndep(np);            /* else look for a dynamic dependancy */
  280.     }
  281.  
  282.     /* if at this point the file doesn't exist, and it's not a target,
  283.         then no way to tell how to make it.
  284.     */
  285.  
  286.     if (!(np->n_flag & N_TARG) && null_time(&np->n_time))
  287.         fatal("Don't know how to make %s", np->n_name);
  288.  
  289.     /* for each entry for the name, for each depndancy in the line */
  290.  
  291.     for (qdp = NULL, lp = np->n_line; lp; lp = lp->l_next)
  292.     {
  293.         for (dp = lp->l_dep; dp; dp = dp->d_next)
  294.         {
  295.             make(dp->d_name, level+1);                /* try making it */
  296.  
  297.                 /* if the file is earlier than the dependancy, make it a
  298.                     dependant (on a temp list) */
  299.  
  300.             if (cmp_time(&np->n_time,&dp->d_name->n_time) < 0)
  301.                 qdp = newdep(dp->d_name, qdp);
  302.  
  303.                 /* our time is MAX(our time,dependant's time) */
  304.  
  305.             if (cmp_time(&dtime,&dp->d_name->n_time) < 0)
  306.                 dtime = dp->d_name->n_time;
  307.         }
  308.  
  309.         if (!quest && (np->n_flag & N_DOUBLE) && cmp_time(&np->n_time,&dtime) < 0)
  310.         {    make1(np, lp, qdp);             /* free()'s qdp */
  311.             dtime = time_one;
  312.             qdp = (struct depend *)0;
  313.             didsomething++;
  314.         }
  315.     }
  316.  
  317.     np->n_flag |= N_DONE;                    /* mark as done */
  318.  
  319.     if (quest)                                /* if 'question up-to-date' */
  320.     {    TimeStamp    t;                        /* temp time variable */
  321.  
  322.         t = np->n_time;                        /* old time of file */
  323.         DateStamp(&np->n_time);                /* new time of file = current time */
  324.     /*    cleardynflag(np); */                /* from PAMAKE */
  325.         return (cmp_time(&t,&dtime) < 0);    /* return comparison */
  326.     }
  327.     else if (makeall || cmp_time(&np->n_time,&dtime) < 0 && !(np->n_flag & N_DOUBLE))
  328.     {
  329.         /* here's the actual part that starts commands executing (normally) */
  330.  
  331.         make1(np, (struct line *)0, qdp);    /* free()'s qdp */
  332.         DateStamp(&np->n_time);                /* np's time is now current time */
  333.     }
  334.     else if (level == 0 && !didsomething)
  335.         printf("%s: '%s' is up to date\n", myname, np->n_name);
  336. /*    cleardynflag(np); */                    /* from PAMAKE */
  337.     return 0;
  338. }
  339.  
  340. /* DJ notes:
  341.     Frees all dependancy structures (What good that does, I'm not sure).
  342.     Builds a macro called '?' which is the names of all the dependancies.
  343.     Then executes each command in np.
  344. */
  345.  
  346. make1(np, lp, qdp)
  347.     register struct depend     *qdp;
  348.     struct line             *lp;
  349.     struct name                *np;
  350. {    register struct depend    *dp;
  351.  
  352.     if (dotouch)                                /* if 'touch' flag */
  353.         touch(np);                                /* touch the file */
  354.     else
  355.     {    strcpy(str1, "");                        /* intialize string var */
  356.         for (dp = qdp; dp; dp = qdp)            /* for each dependancy */
  357.         {    if (strlen(str1))                    /* if not the first name */
  358.                 strcat(str1, " ");                /* add a space */
  359.             strcat(str1, dp->d_name->n_name);    /* concatenate the depndancy name */
  360.             qdp = dp->d_next;                    /* address of next dependancy */
  361.             free(dp);                            /* free dependancy */
  362.         }
  363.         setmacro("?", str1);                    /* set '?' as name of deps */
  364.         setmacro("@", np->n_name);                /* and '@' as name of self */
  365.         if (lp)                                    /* lp set if doing a :: rule */
  366.             docmds1(np, lp);                    /* do a specific line */
  367.         else docmds(np);                        /* do all lines for that name */
  368.     }
  369. }
  370.