home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / make-ds.lbr / MAKE.CQ / MAKE.C
Encoding:
C/C++ Source or Header  |  1986-09-04  |  8.8 KB  |  397 lines

  1. /* File MAKE.C. */
  2. /* BDS-C Version 1.2 6/14/85 */
  3. #define VERSION "V1.2  6/14/85"
  4.  
  5. /* v 1.2 [bmm]
  6.  * compatible with DateStamper v 2.0
  7.  * fixed relative time display in prtree 
  8.  * coded alloc() and free() in ASM
  9.  * read entire time&date file on first drive
  10.  * omit script file if no actual commands to execute
  11.  */
  12.  
  13. #include <bdscio.h>
  14. #include "make.h"
  15.  
  16. /*
  17.  *    MAKE - Maintain seperate source files
  18.  *
  19.  *    SYNOPSIS
  20.  *        MAKE [-f file] [-a] [-n] [-d] [name] ...
  21.  *           f: use 'file' instead of default makefile
  22.  *           a: assume all modules are obsolete (recompile everything)
  23.  *           n: don't recompile, just list steps to recompile
  24.  *           d: debugging (print tree, file info)
  25.  *           name: module name to recompile
  26.  *
  27.  *        'secret' options (not to be used by humans):
  28.  *           -ofile    'file' is the script file to write to
  29.  *
  30.  *    AUTHOR
  31.  *        Landon M. Dyer, Atari Inc.
  32.  *
  33.  *    MODIFICATIONS
  34.  *        Neil Maron: Converted to CP/M 80 (tm), BDS-C(tm), using
  35.  *            DateStamper(tm).
  36.  *        v 1.2 Bridger Mitchell (Plu*Perfect Systems)
  37.  */
  38.  
  39. #define SCRIPTFILE "make$$$$.sub"    /* (default) script-listing file */
  40. #define    INIT    "~INIT"            /* initialization macro */
  41. #define    DEINIT    "~DEINIT"        /* de-init macro */
  42. #define    BEFORE    "~BEFORE"        /* the per-root 'startup' method */
  43. #define    AFTER    "~AFTER"        /* the per-root 'wrapup' method */
  44. #define BATCH    "~BATCH"        /* the batch processor to run */
  45.  
  46.  
  47. /*MACRO *mroot;*/    /* root of macro-list */
  48. /*FILENODE *froot;*/    /* root of filenode-list */
  49. FILENODE *firstf;    /* the very first filenode */
  50. char mkfpbuf[BUFSIZ];    /* output file buffer */
  51. FILE *mkfp;        /* script file */
  52. char *modnames[MAXMODS];    /* module-names mentioned in commandline */
  53. int modcount;        /* #of module-names */
  54. int debug;        /* nonzero: turn on debugging */
  55. int obsolete;        /* nonzero: every file should be recompiled */
  56. int noscript;        /* nonzero: print methods on standard output */
  57. char *scriptf;        /* default script file */
  58. /*DATE *bigbang;*/    /* a date, the very earliest possible */
  59. /*DATE *endoftime;*/    /* a date, the very last possible */
  60.  
  61. main(argc, argv)
  62. int argc;
  63. char **argv;
  64. {
  65.     int arg, i;
  66.     char *mfile;
  67.     DATE *adate();
  68.     char *gdsadate();
  69.     char *m;
  70.  
  71. /* Inits */
  72.     mfile=NULL;
  73.     mroot=NULL; froot=NULL; firstf=NULL; mkfp=NULL;
  74.     modcount=debug=obsolete=noscript=0;
  75.     scriptf=SCRIPTFILE;
  76.     datesdisk = -1;    /* signal initial read to getfdate() */
  77.     havedates = somechanges = FALSE;
  78. /* End of inits */ 
  79.  
  80.     bigbang   = adate("\000\000\000\000\000");    /* init root dates */
  81.     endoftime = adate("\377\377\377\377\377");
  82.  
  83.     if (bdos(12) != 0x0022) {
  84.         printf("\7Requires CP/M 2.2\nAborting\n");
  85.         exit();
  86.     }
  87.  
  88.     /* Get the date for output of version string.*/
  89.     ascidate=gdsadate();
  90.     if(!ascidate) ascidate="No Date";
  91.  
  92.     printf("MAKE %s   on %s\n", VERSION, ascidate);
  93.  
  94.     if(argc < 2) {
  95.       printf("Usage: MAKE [-f file] [-a] [-n] [-d] [name] ...\n");
  96.        printf("\tf: use 'file' instead of default MAKEFILE.\n");
  97.       printf("\ta: assume all modules are obsolete (recompile everything)\n");
  98.       printf("\tn: don't recompile, just list steps to recompile\n");
  99.       printf("\td: debugging (print tree, file info)\n");
  100.       printf("\tname: module name to recompile\n");
  101.          exit();
  102.     }
  103.  
  104.     for(arg = 1; arg < argc; ++arg)
  105.         if(*argv[arg] == '-') switch(tolower(argv[arg][1]))
  106.         {
  107.            case 'f':
  108.             if(++arg >= argc || argv[arg][0]=='-')
  109.             {
  110.                 printf("\7-f needs filename argument.\n");
  111.                 return;
  112.             }
  113.             mfile = argv[arg];
  114.             break;
  115.  
  116.            case 'a':
  117.             obsolete = 1;
  118.             break;
  119.  
  120.            case 'n':
  121.             noscript = 1;
  122.             break;
  123.  
  124.            case 'd':
  125.             debug = 1;
  126.             break;
  127.  
  128.            case 'o':
  129.                scriptf = argv[arg] + 2;
  130.             break;
  131.  
  132.            default:
  133.             printf("Unknown switch: %c\n", argv[arg][1]);
  134.             break;
  135.         } else if(modcount < MAXMODS)
  136.             modnames[modcount++] = argv[arg];
  137.         else
  138.         {
  139.             printf("Too many module names.\n");
  140.             return;
  141.         }
  142.  
  143.  
  144.     mfilename = (mfile != NULL) ? mfile :  "MAKEFILE";
  145.  
  146.     if(fmakesb(mfilename) == -1)
  147.         printf("Cannot open makefile '%s'.\n", mfilename);
  148.  
  149.     if(debug) prtree();
  150.  
  151.     if ((m=gmacro(BATCH)) != NULL && !noscript && somechanges) {
  152.         execl(m, scriptf,0);
  153.         printf("Can't start %s\n", m);
  154.     }
  155.     exit(1);
  156. }
  157.  
  158.  
  159. /*
  160.  * Construct dependency tree from the makefile 'fn'.
  161.  * Figure out what has to be recompiled, and write a script file to do that.
  162.  */
  163. fmakesb(fn)
  164. char *fn;
  165. {
  166.     FILE *fp;
  167.     char fpbuf[BUFSIZ];
  168.  
  169.     if((fp = fopen(fn, fpbuf)) == ERROR) return -1;
  170.     fp=&fpbuf;        /* BDS-C buffered I/O */
  171.  
  172.     fparse(fp);
  173.     determ();
  174.  
  175.     fclose(fp);
  176.     return 0;
  177. }
  178.  
  179.  
  180. /*
  181.  * Parse the input file, defining macros and building the dependency tree.
  182.  */
  183. fparse(fp)
  184. FILE *fp;
  185. {
  186.     char ibuf[STRSIZ], ebuf[STRSIZ];
  187.     char *strp, *tok1, *tok2, *s;
  188.     FILENODE *lastf;
  189.     FILENODE *sf;
  190.  
  191.     lastf=NULL;
  192.     for(;;)
  193.     {
  194.         if(fgets(ibuf, fp) == NULL) break;
  195.         mexpand(ibuf, ebuf, STRSIZ, MACCHAR);
  196.         escape(ebuf, COMCHAR);
  197.  
  198.             /* clobber last newline in string */
  199.         s = ebuf + strlen(ebuf) - 1;
  200.         if(s >= ebuf && *s == '\n') *s = '\0';
  201.  
  202.         if(*ebuf == '\t')
  203.         {
  204.             addmeth(lastf, ebuf+1);
  205.             continue;
  206.         }
  207.  
  208.         strp = ebuf;
  209.         if((tok1 = token(&strp)) == NULL) continue;
  210.         if((tok2 = token(&strp)) != NULL)
  211.             if(strcieq(tok2, DEFMAC))
  212.             {
  213.                 if(*strp) defmac(tok1, strp);
  214.                 else if(undefmac(tok1) < 0)
  215.                     printf(
  216.                         "Can't undefine macro '%s'\n", tok1);
  217.                 continue;
  218.             }
  219.             else if(strcieq(tok2, DEPEND))
  220.             {
  221.                 addmeth(lastf, gmacro(AFTER));
  222.  
  223.                 lastf = filenode(tok1);
  224.                 if(firstf == NULL) firstf = lastf;
  225.                 lastf->fmake = NULL;
  226.  
  227.                 addmeth(lastf, gmacro(BEFORE));
  228.  
  229.                 lastf->fflag |= ROOTP;
  230.                 while((tok1 = token(&strp)) != NULL)
  231.                     addfile(lastf, tok1);
  232.                 continue;
  233.             }
  234.             else addfile(lastf, tok2);
  235.  
  236.         do {
  237.             addfile(lastf, tok1);
  238.         } while((tok1 = token(&strp)) != NULL);
  239.     }
  240.  
  241.     addmeth(lastf, gmacro(AFTER));
  242. }
  243.  
  244. /*
  245.  * Determine sequence of recompiles from the creation dates.
  246.  * If there's anything to recompile, then create a script file of commands.
  247.  */
  248. determ()
  249. {
  250.     FILENODE *f;
  251.     int i;
  252.     char *m;
  253.  
  254.     if(firstf == NULL)            /* empty tree */
  255.     {
  256.         nochanges();
  257.         somechanges = FALSE;
  258.         return;
  259.     }
  260.  
  261.     if(modcount == 0) examine(firstf, endoftime);
  262.     else for(i = 0; i < modcount; ++i)
  263.     {
  264.         if((f = gfile(modnames[i])) == NULL)
  265.         {
  266.             printf("Can't find root '%s'.\n", modnames[i]);
  267.             continue;
  268.         }
  269.  
  270.         if(f->fflag & ROOTP == 0)
  271.         {
  272.             printf("'%s' is not a root!\n", f->fname);
  273.             continue;
  274.         }
  275.         examine(f, endoftime);
  276.     }
  277.  
  278.     if(mkfp != NULL)
  279.     {
  280.         if((m = gmacro(DEINIT)) != NULL)
  281.         {
  282.             if (mkfp == 1) puts(m);
  283.             else fputs(m, mkfp);
  284.             putc('\r', mkfp);
  285.             putc('\n', mkfp);
  286.         }
  287.         if (mkfp != 1) {
  288.             putc('\032', mkfp);    /* CPM e-o-f */
  289.             fflush(mkfp);
  290.             fclose(mkfp);
  291.             if (!somechanges) {
  292.                 unlink(scriptf); nochanges();}
  293.         }
  294.         else
  295.             if (!somechanges)
  296.                 nochanges();
  297.         
  298.     } else nochanges();
  299. }
  300. nochanges()
  301. {
  302.     printf("No changes.\n");
  303.     }
  304.  
  305. /*
  306.  * Examine filenode 'fnd' and see if it has to be recompiled.
  307.  * 'date' is the last-touched date of the node's father
  308.  * (or 'endoftime' if its a root file.)
  309.  * Root files with NO dependencies are assumed not to be up to date.
  310.  */
  311. examine(fnd, date)
  312. FILENODE *fnd;
  313. DATE *date;
  314. {
  315.     int rebuildp;
  316.     NODE *n;
  317.  
  318.     rebuildp=0;
  319.     getdate(fnd);
  320.     if(fnd->fnode == NULL && fnd->fflag & ROOTP)
  321.         rebuildp = 1;
  322.     else for(n = fnd->fnode; n != NULL; n = n->nnext)
  323.         if(examine(n->nfile, fnd->fdate)) rebuildp = 1;
  324.  
  325.     if(rebuildp) recomp(fnd);
  326.     if(obsolete || laterdt(fnd->fdate, date) >= 0)
  327.         rebuildp = 1;
  328.     return rebuildp;
  329. }
  330.  
  331.  
  332. /*
  333.  * Make sure a filenode gets recompiled.
  334.  */
  335. recomp(f)
  336. FILENODE *f;
  337. {
  338.     FILENODE *sf;
  339.     char *m;
  340.  
  341.     if(mkfp == NULL) {
  342.         if(noscript) mkfp=1;
  343.         else if((mkfp = fcreat(scriptf, mkfpbuf)) == NULL)
  344.             printf("Cannot create: '%s'\n", scriptf);
  345.         else {
  346.             mkfp=&mkfpbuf;
  347.         /* Install current time as a comment in the file. [nm] */
  348.             fprintf(mkfp,"; script created from %s  at %s\r\n",
  349.                  mfilename,ascidate);
  350.             }
  351.  
  352.         if((m = gmacro(INIT)) != NULL) {
  353.             if (mkfp == 1) puts(m);
  354.             else fputs(m, mkfp);
  355.             putc('\r', mkfp);
  356.             putc('\n', mkfp);
  357.         }
  358.     }
  359.  
  360.     if(f->fflag & REBUILT) return;
  361.     if(f->fmake != NULL) {
  362.         if (mkfp == 1) puts(f->fmake);
  363.         else    {
  364.             fputs(f->fmake, mkfp);
  365.             somechanges = TRUE; }
  366.     }
  367.     f->fflag |= REBUILT;
  368. }
  369.  
  370.  
  371. /*
  372.  * Complain about being out of memory, and then die.
  373.  */
  374. allerr() {
  375.     printf("Can't alloc -- no space left (I give up!)\n");
  376.     exit(1);
  377. }
  378.  
  379. /*-- v 1.2 in csm library ---
  380.  
  381. /* Case independant string equality.
  382.  * Return TRUE is same, FALSE if not.
  383.  */
  384. strcieq(str1, str2)
  385. char *str1, *str2;
  386. {
  387.     char toupper();
  388.     while (*str1 && *str2)
  389.         if (toupper(*str1++) != toupper(*str2++)) return FALSE;
  390.     if (*str1 == *str2) return TRUE;
  391.     return FALSE;
  392. }
  393. ---  --*/
  394. Cannot create: '%s'\n", scriptf);
  395.         else {
  396.             mkfp=&mkfpbuf;
  397.         /* Install curren