home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 186_01 / makeio.c < prev    next >
Text File  |  1985-08-21  |  12KB  |  380 lines

  1. /* MAKEIO.C -- Input/Output and messaging for MAKE.C
  2.  * 
  3.  * For information on compilation, see MAKE.C.  For usage, see
  4.  * MAKE.DOC
  5.  *
  6.  * CREDITS:
  7.  * 
  8.  * -- getline(), getblock(), stov(), err(), and serr() functions by
  9.  *    Allen Holub (DDJ #106).
  10.  * -- prompt(), batch(), addfile(), push(), and pop() functions 
  11.  *    by James Pritchett.
  12.  * -- All code by Allen Holub adapted for BDS C (where necessary)
  13.  *    by James Pritchett.
  14.  *
  15.  * Version 1.0 -- 10/28/85
  16.  * Version 1.1 -- 12/06/85
  17.  */
  18.  
  19. #include <bdscio.h>
  20. #include "make.h"
  21.  
  22.  
  23. void prompt()   /* This is an escape hatch */
  24. {
  25.     printf("\nHit any key to execute commands (^C aborts)");
  26.     getchar();
  27. }
  28.  
  29. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  30.  
  31. void batch()    /* Make the batch file, getting command lines from
  32.                  * the command stack.
  33.                  */
  34. {
  35.     int i;              /* Counter for $$$.SUB records */
  36.     char *com;          /* Pointer to command line */
  37.     char subrec[128];   /* SUB file record */
  38.     int fd;             /* For disk I/O calls */
  39.  
  40.  
  41. /* In order to batch SUBMITs, first check to see if A:$$$.SUB currently
  42.  * exists.  If so, seek to the end of file, and append new commands.
  43.  * If A:$$$.SUB does not exist, create it.
  44.  */
  45.  
  46.     if ((fd = open("A:$$$.SUB",1)) != ERROR)
  47.         seek(fd,0,2);
  48.     else if ((fd = creat("A:$$$.SUB")) == ERROR)
  49.         err("Can't create A:$$$.SUB\n",0);
  50.  
  51. /* NOTE: In a pending SUBMIT file, the commands must be in reverse
  52.  * order.  Hence, commands are stored in a stack, with the commands
  53.  * pushed in the proper order, and thus popped in reverse order.
  54.  * Also, pending SUBMIT files must have their commands in a 
  55.  * particular format: Each command must be preceded by a count of
  56.  * the number of chars in it; the commands must be null-terminated;
  57.  * and each command must be padded out to take up exactly one 
  58.  * record (128 bytes) of the file.
  59.  */
  60.  
  61.     while (com = pop()) {
  62.         i = 0;
  63.         subrec[i++] = strlen(com)+1;    /* put the length first */
  64.         while (i < 127 && *com)         /* put the command line */
  65.             subrec[i++] = *(com++);
  66.         while (i < 128)                 /* pad with nulls */
  67.             subrec[i++] = 0;
  68.         if (write(fd,subrec,1) != 1)    /* write this record */
  69.             err("Error in writing to A:$$$.SUB\n",0);
  70.     }
  71.     if(close(fd) == ERROR) 
  72.         err("Error in closing A:$$$.SUB\n",0);
  73. }
  74.  
  75. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  76.  
  77. TNODE   *addfile(file)  /* Handle a file-dependancy.  This function
  78.                          * makes a node for the filename, evaluates
  79.                          * truth/falsity by means of an attribute
  80.                          * bit, and sets that bit after evaluation.
  81.                          */
  82. char *file;             /* Filename */
  83. {
  84.     TNODE   *nodep;     /* Pointer to node made for this filename */
  85.     char    fcb[36];    /* FCB for BDOS calls */
  86.     char    *name;      /* Filename as exists in directory */
  87.     int     entry;      /* Directory code returned from SEARCH_F call */
  88.     int     i;
  89.     char    curuser;    /* Current user area */
  90.     char    fileuser;   /* User area of file */
  91.  
  92. /* Make the node for this file and place in tree. */
  93.  
  94.     nodep = gmem(NODESIZE);
  95.     nodep->rnode = nodep->lnode = 0;
  96.     nodep->being_made = file;
  97.     nodep->depends_on = 0;
  98.     nodep->do_this = 0;
  99.  
  100. #ifdef  DEBUG
  101. debug("DEBUG addfile: Node made for %s\n",nodep->being_made);
  102. #endif
  103.  
  104.     tree(nodep,&root);  /* place the node */
  105.  
  106.  
  107. /* Handle any user area specified in filename */
  108.  
  109.     curuser = bdos(GS_USER,0x0FF);  /* Get current user */
  110.  
  111. /* If filename has a user spec (defined by '/'), set the new user
  112.  * and increment file past the '/'.
  113.  */
  114.  
  115.     if ((*(file+1) == '/') || (*(file+2) == '/')) {
  116.         if ((fileuser = atoi(file)) > MAXUSER)
  117.             fileuser = curuser;
  118.         while (*(file++) != '/')
  119.             ;
  120.     }
  121.  
  122. /* If there is no user spec on filename, but there is a default user,
  123.  * set it accordingly.
  124.  */
  125.  
  126.     else if (defuser != UNKNOWN)
  127.         fileuser = defuser;
  128.  
  129. /* If no user spec and no default user, just stay put. */
  130.  
  131.     else
  132.         fileuser = curuser;
  133.  
  134. /* Now, set that user! */
  135.  
  136.     bdos(GS_USER,fileuser);
  137.  
  138.  
  139. /* Find the file and check the attribute bit */
  140.  
  141.     bdos(SET_DMA,DMA);
  142.     setfcb(fcb,file);   /* Make an FCB for the filename */
  143.     if (!(*fcb))        /* If no drive name, use default */
  144.         *fcb = defdsk;
  145.     entry = bdos(SEARCH_F,fcb);
  146.     if (entry == 255)           /* BDOS error code */
  147.         serr("Dependancy file %s does not exist\n",file);
  148.     else {
  149.         name = DMA + (entry*32);    /* convert BDOS code to pointer */
  150.  
  151. /* If attribute is set, status = FALSE */
  152.  
  153.         if (*(name+MATTRIB) & 0x80) {
  154.             nodep->changed = FALSE;
  155.  
  156. #ifdef  DEBUG
  157. debug("DEBUG addfile: File %s not changed\n",fcb+1);
  158. #endif
  159.  
  160.         }
  161.  
  162. /* Else, set status to TRUE and set bit again (-n and -r options
  163.  * override the attribute set).
  164.  */
  165.  
  166.         else {
  167.  
  168. #ifdef  DEBUG
  169. debug("DEBUG addfile: File %s changed\n",fcb+1);
  170. #endif
  171.  
  172.             nodep->changed = TRUE;
  173.             if (!nopt && !ropt) {
  174.  
  175. /* In order to preserve any other attributes that may be set for this
  176.  * file, the filename is copied from the directory (where attribute 
  177.  * bits are set) to the FCB before setting MATTRIB.
  178.  */
  179.  
  180.                 for (i = 1; i <= 11; i++)
  181.                     fcb[i] = *(name+i);
  182.                 fcb[MATTRIB] |= 0x80;
  183.  
  184. #ifdef PUBLIC
  185. /* If using Plu*Perfect's public files system, the following must be
  186.  * done to keep public files in their proper place.
  187.  */
  188. if (*name != fileuser)
  189.     bdos(GS_USER,*name);
  190. #endif
  191.  
  192.                 bdos(SET_ATT,fcb);
  193.             }
  194.         }
  195.  
  196. /* Now, reset the user to curuser before ending */
  197.  
  198.         bdos(GS_USER,curuser);
  199.         return nodep;
  200.     }
  201. }
  202.  
  203. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  204.  
  205. char *getline(maxline)      /* Get one logical line from the file.
  206.                              * Strips CR-LF's and returns null-terminated
  207.                              * string. If EOF is encountered, returns 0.
  208.                              * Else, returns pointer to the line.
  209.                              */
  210. int maxline;        /* Maximum line length */
  211. {
  212.     char *bp;       /* Pointer to line buffer (external) */
  213.     int c,lastc;
  214.  
  215. /* Read in a line, concatenating lines ending in '\' and terminating with
  216.  * CR-LF or CPMEOF.  Line is placed in a temporary buffer of MAXLINE chars
  217.  * (linbuf[]) and then copied into free memory in order to save space.
  218.  */
  219.  
  220.     bp = linbuf;    
  221.     while(1) {
  222.         inputline++;
  223.         for (lastc = 0; (c = getc(iobuff)) != CPMEOF 
  224.                                     && c != '\r'; lastc = c) {
  225.             if (--maxline > 0)
  226.                 *bp++ = toupper(c); /* All input folded to uppercase */
  227.         }
  228.         if (c == '\r')
  229.             c = getc(iobuff);   /* skip the CR in CR-LF pair */
  230.         if (!(c == '\n' && lastc == '\\'))
  231.             break;              /* end of the line */
  232.         else if (maxline > 0)   /* concatenate lines */
  233.             --bp;
  234.         else
  235.             err("Line too long (%d chars maximum)",MAXLINE);
  236.     }
  237.     *bp = 0;    /* Terminate with null */
  238.  
  239.  
  240. /* Allocate just enough space for the line and move it there.  EOF or
  241.  * Out of memory returns 0
  242.  */
  243.  
  244.     if ((c == CPMEOF && bp == linbuf) || !(bp = alloc((bp-linbuf)+1))) {
  245.         return NULL;
  246.     }
  247.     strcpy(bp,linbuf);
  248.     return bp;
  249. }
  250.  
  251. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  252.  
  253. char **getblock()       /* Get a block of lines ended by an empty line.
  254.                          * Creates an array of pointers to those lines.
  255.                          * This function is used to create the do_this
  256.                          * arrays.
  257.                          */
  258. {
  259.     char *p;                /* Pointer to line of text from makefile */
  260.     char *lines[MAXBLOCK];  /* Local line vector */
  261.     char **blockv;          /* Pointer to this vector */
  262.     int  blockc;            /* Count of lines in vector */
  263.  
  264.     blockv = lines;
  265.     blockc = 0;
  266.  
  267.  
  268. /* Read lines from file until a blank line is encountered.  Skip over
  269.  * all white space, and place pointer to first char of text into the
  270.  * local line vector.  Abort if too many lines.
  271.  */
  272.  
  273.     while (p = getline(MAXLINE)) {
  274.         if (!(*p))
  275.             break;
  276.         skipwhite(p);
  277.         if (++blockc <= MAXBLOCK)
  278.             *blockv++ = p;
  279.         else
  280.             err("Action too long (max = %d lines)",MAXBLOCK);
  281.     }
  282.  
  283. /* Allocate enough space for the line vector and put it there.
  284.  * Terminate the vector with a null.
  285.  */
  286.  
  287.     blockv = gmem((blockc + 1) * sizeof(blockv[0]));
  288.     movmem(lines, blockv, blockc*sizeof(blockv[0]));
  289.     blockv[blockc] = NULL;
  290.  
  291.     return blockv;
  292. }
  293.  
  294. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  295.  
  296. char **stov(str,maxvect)    /* Convert a string of tokens separated
  297.                              * by white space to an array of pointers
  298.                              * to the tokens, substituting nulls for
  299.                              * the white space.
  300.                              * This routine is used to create the
  301.                              * depends_on vector in an object node.
  302.                              */
  303. char *str;                  /* String to convert */
  304. int maxvect;                /* Maximum size of vector */
  305. {
  306.     char    **vect, **vp;   /* Pointers to the vector */
  307.  
  308. /* Allocate enough space for a worst-case scenario. */
  309.  
  310.     vp = vect = gmem((maxvect+1) * sizeof(str));
  311.  
  312. /* Parse the line, storing pointers in vector */
  313.  
  314.     while(*str && --maxvect >= 0) {
  315.         skipwhite(str);
  316.         *vp++ = str;
  317.         skipnonwhite(str);
  318.         if (*str)
  319.             *str++ = 0; /* replace space with null */
  320.     }
  321.     *vp = 0;    /* null-terminate array */
  322.     if (maxvect < 0)
  323.         err("Too many dependancies! (%d maximum)",MAXDEP);
  324.     return vect; 
  325. }
  326.  
  327. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  328.  
  329. void err(msg,param)     /* Error message.  Prints message with int
  330.                          * param, then aborts.
  331.                          */
  332. char    *msg;
  333. int param;
  334. {
  335.     printf("FATAL ERROR (%s line %d): ",filename,inputline);
  336.     printf(msg,param);
  337.     exit();
  338. }
  339.  
  340. void serr(msg,param)    /* As above, except with a string param */
  341. char *msg, *param;
  342. {
  343.     printf("FATAL ERROR (%s line %d): ",filename,inputline);
  344.     printf(msg,param);
  345.     exit();
  346. }
  347.  
  348. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  349.  
  350. void push(elem)         /* Push a stack element onto the stack */
  351. char *elem;             /* Data to push */
  352. {
  353.     STACK   *elemptr;   /* Pointer to new stack element */
  354.  
  355.     elemptr = gmem(STACKSIZE);      /* Allocate space */
  356.     elemptr->comline = elem;        /* Fill with data */
  357.     elemptr->next = stackp;         /* Point to previous top */
  358.     stackp = elemptr;               /* Reset stack pointer */
  359. }
  360.  
  361. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  362.  
  363. char *pop()             /* Pop element off stack and return the 
  364.                          * data therein.
  365.                          */
  366. {
  367.     STACK   *elemptr;   /* Pointer to top of stack */
  368.  
  369.     if (elemptr = stackp) {
  370.         stackp = elemptr->next;     /* Set stackp to new top */
  371.         return elemptr->comline;    /* And return data */
  372.     }
  373.     else                            /* If stack is empty, return NULL */
  374.         return NULL;
  375. }
  376.  
  377. /* end */
  378.  
  379.  
  380. * * * * * * * * * * * * *