home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / scpp.t.Z / scpp.t / io.c < prev    next >
Text File  |  2009-11-06  |  9KB  |  442 lines

  1. /*
  2.  * io.c - input and output primitives for the selective C preprocessor, scpp.
  3.  *
  4.  * Copyright (c) 1985 by
  5.  * Tektronix, Incorporated Beaverton, Oregon 97077
  6.  * All rights reserved.
  7.  *
  8.  * Permission is hereby granted for personal, non-commercial
  9.  * reproduction and use of this program, provided that this
  10.  * notice and all copyright notices are included in any copy.
  11.  */
  12.  
  13. # include <stdio.h>
  14. # include "scpp.h"
  15.  
  16. # define STDINPUT 0    /* file descriptor of stdin        */
  17. # define BSIZE    512
  18.             /*
  19.              * # of bytes per read -- controls how quickly
  20.              * istk[] is consumed.
  21.              */
  22. int dooutput = 1;    /* "actually write data" rather than tossing it    */
  23.  
  24. /*
  25.  * nxtc() - return the next character from the input stream.
  26.  *   Nxtc() is used only by lex.
  27.  */
  28.  
  29. char
  30. nxtc()
  31. {
  32.     char ch;
  33.     int readcnt;
  34.  
  35.  
  36.     while ((ch = *nxtin++) == ATTN) {
  37.         switch (ch = *nxtin++) {
  38.         case AT_EPUSH:    /* end of pushback (interpreted text)    */
  39.             curfile->af_raw = TRUE;
  40.             break;
  41.         case AT_EBLK:    /* end of block    */
  42.  
  43.             /*
  44.              * The current block is exhausted.
  45.              * Mark the end of the new block
  46.              * then read in the new block (if there's space)
  47.              * and adjust the top of stack.
  48.              */
  49.  
  50.             unc(AT_EBLK);
  51.             unc(ATTN);
  52.             if (nxtin < &istk[BSIZE]) {
  53.                 over();
  54.             }
  55.             nxtin -= BSIZE;
  56.             readcnt = read(curfile->af_fd, nxtin, BSIZE);
  57.             if (readcnt < 0) {
  58.                 bombf("read error");
  59.             }
  60.             if (readcnt > 0) {
  61.                 if (readcnt < BSIZE) {
  62.                     /* slide the new data into place */
  63.  
  64.                     register char *src, *dst;
  65.  
  66.                     for (dst = nxtin + BSIZE,
  67.                          src = nxtin + readcnt;
  68.                          src > nxtin; *--dst = *--src)
  69.                         ;
  70.                     nxtin = dst;
  71.                 }
  72.                 break;
  73.             }
  74.  
  75.             /*
  76.              * The current file is exhausted.
  77.              * Pop the nonexistent block and the ATTN bytes
  78.              *  from the input stack;
  79.              * Turn on the output if necessary;
  80.              * Close and pop the file.
  81.              */
  82.  
  83.             nxtin += BSIZE + 2;
  84.             if (curfile->af_hide) {
  85.                 if (--hidecnt == 0 && falsecnt == 0) {
  86.                     quec(ATTN);
  87.                     quec(AT_OUTON);
  88.                 }
  89.             }
  90.             if (curfile->af_fd != STDINPUT) {
  91.                 close(curfile->af_fd);
  92.             }
  93.             free(curfile->af_name);
  94.             if (--curfile >= &filestk[0]){
  95.                 break;
  96.             }
  97.  
  98.             /*
  99.              * no more current files remain - open the next
  100.              * file to be processed (if there is one),
  101.              * or pushback the EOF character and an ATTN
  102.              * so that further nxtc() calls return EOF.
  103.              */
  104.  
  105.             if (*nxtfile == (char *) 0) {
  106.                 unc(AT_EBLK);
  107.                 unc(ATTN);
  108.                 unc('\0');
  109.                 break;
  110.             }
  111.             pushfile(*nxtfile++, PF_NOLOOK, PF_NOHIDE);
  112.             break;
  113.  
  114.         default:
  115.             bombf("illegal character in input: 0x%x", ATTN);
  116.         }
  117.     }
  118.  
  119.     return(ch);
  120. }
  121.  
  122. /*
  123.  * untok() - push back the most recent token (less ATTN bytes)
  124.  *  from the output stream into the input stream.
  125.  */
  126.  
  127. untok()
  128. {
  129.     char *cp;
  130.  
  131.     for (cp = nxtout - 1; cp >= curtext; --cp) {
  132.         if (cp > curtext && *(cp - 1) == ATTN) {
  133.             --cp;
  134.         } else {
  135.             if (*cp == '\n' && curfile->af_raw) {
  136.                 curfile->af_line--;
  137.             }
  138.             unc(*cp);
  139.         }
  140.     }
  141.     nxtout = dispose(curtext);
  142. }
  143.  
  144. /*
  145.  * pushmac() - push the given macro value back into the input stream.
  146.  *  Used to expand a macro.
  147.  * pushmac() is passed a pointer to the END of a string to be pushed
  148.  *  (some part of a macro's replacement text).  Pushmac() pushes the string
  149.  *  backwards onto the input stack until it comes to a null-terminator or
  150.  *  an ATTN byte.  It returns a pointer to the terminator.
  151.  */
  152.  
  153. char *
  154. pushmac(v)
  155. char *v;    /* points to a null-terminator or other ignored byte    */
  156. {
  157.     if (curfile->af_raw) {
  158.         unc(AT_EPUSH);
  159.         unc(ATTN);
  160.         curfile->af_raw = FALSE;
  161.     }
  162.     while (*--v != '\0' && *v != ATTN) {
  163.         if (nxtin-- < &istk[0]) {
  164.             over();
  165.         }
  166.         *nxtin = *v;
  167.     }
  168.     return(v);
  169. }
  170.  
  171. /*
  172.  * pushfile() - effectively push the given file into the input stream.
  173.  *  Used to include a file.
  174.  */
  175.  
  176. pushfile(name, itype, hide)
  177. char *name;
  178. int itype;
  179. {
  180. #define PNLEN 257
  181.     char pname[PNLEN];
  182.     char *cp;
  183.     char **dp;
  184.     struct afile *ip;
  185.     char *rindex();
  186.     char *malloc();
  187.  
  188.  
  189.     if (++curfile >= &filestk[FILESIZ]) {
  190.         --curfile;
  191.         warnf("too many nested include files.  skipping `%s'", name);
  192.         return;
  193.     }
  194.  
  195.     /*
  196.      * if the name is to be opened with no modification, do that.
  197.      * If the directory of the current file is to be searched, do that.
  198.      * Search each directory in the list for the file.
  199.      */
  200.  
  201.     if (name[0] == '/' || itype == PF_NOLOOK) {
  202.         (void) strcpy(pname, name);
  203.         if (strcmp(name, "-") == 0) {
  204.             curfile->af_fd = STDINPUT;
  205.         } else {
  206.             curfile->af_fd = open(pname, 1);
  207.         }
  208.     } else {
  209.         curfile->af_fd = -1;
  210.         if (itype == PF_DOT) {
  211.             (void) strcpy(pname, (curfile - 1)->af_name);
  212.             if ((cp = rindex(pname, '/'))) {
  213.                 ++cp;
  214.             } else {
  215.                 cp = &pname[0];
  216.             }
  217.             if (cp + strlen(name) >= &pname[PNLEN]) {
  218.                 --curfile;
  219.                 bombf("name too long `%s%s'", pname, name);
  220.             }
  221.             (void) strcpy(cp, name);
  222.             curfile->af_fd = open(pname, 1);
  223.         }
  224.         for (dp = &dirlist[0]; *dp && curfile->af_fd < 0; dp++) {
  225.             cp = &pname[0] + strlen(*dp);
  226.             if (cp >= &pname[PNLEN]) {
  227.                 --curfile;
  228.                 bombf("name too long `%s'", *dp);
  229.             }
  230.             (void) strcpy(pname, *dp);
  231.             if (cp > &pname[0] && *(cp - 1) != '/') {
  232.                 *cp++ = '/';
  233.                 *cp = '\0';
  234.             }
  235.             if (cp + strlen(name) >= &pname[PNLEN]) {
  236.                 --curfile;
  237.                 bombf("name too long `%s%s'", pname, name);
  238.             }
  239.             (void) strcpy(cp, name);
  240.             curfile->af_fd = open(pname, 1);
  241.         }
  242.     }
  243.     if (curfile->af_fd < 0) {
  244.         --curfile;
  245.         warnf("cannot find%s file `%s'",
  246.           curfile > &filestk[0] ? " include" : "", name);
  247.         return;
  248.     }
  249.  
  250.     /*
  251.      * the file is open.
  252.      * See if this is a recursive include.
  253.      */
  254.  
  255.     for (ip = &filestk[0]; ip < curfile; ip++) {
  256.         if (strcmp(ip->af_name, pname) == 0) {
  257.             close(curfile->af_fd);
  258.             --curfile;
  259.             warnf("skipping recursive inclusion of `%s'", pname);
  260.             return;
  261.         }
  262.     }
  263.  
  264.     /*
  265.      * fill in the rest of the afile structure.
  266.      */
  267.  
  268.     if (!(curfile->af_name = malloc((unsigned) strlen(pname) + 1))) {
  269.         --curfile;
  270.         bombf("out of memory");
  271.     }
  272.     (void) strcpy(curfile->af_name, pname);
  273.     curfile->af_line = 1;
  274.     curfile->af_raw = TRUE;
  275.     curfile->af_hide = hide;
  276.     if (hide) {
  277.         if (hidecnt++ == 0 && falsecnt == 0) {
  278.             quec(ATTN);
  279.             quec(AT_OUTOFF);
  280.         }
  281.     }
  282.     unc(AT_EBLK);
  283.     unc(ATTN);
  284.  
  285. #undef PNLEN
  286. }
  287.  
  288. /*
  289.  * quec() - move a character to the output queue, pend[]
  290.  */
  291.  
  292. quec(c)
  293. char c;
  294. {
  295.     *nxtout = c;
  296.     if (++nxtout >= &pend[PENDSIZ]) {
  297.         bombf("too much forward search");
  298.     }
  299. }
  300.  
  301. /*
  302.  * questr() - move the null-terminated string to the output queue, pend[]
  303.  *  Used only by xxlex().
  304.  */
  305.  
  306. questr(s, len)
  307. register char *s;
  308. int len;        /* length (in bytes) of the string to be moved */
  309. {
  310.     register char *d = nxtout;
  311.  
  312.  
  313.     if (d + len < &pend[PENDSIZ]) {
  314.         while (*d++ = *s++)
  315.             ;
  316.         nxtout += len;
  317.     } else {
  318.         bombf("too much forward search");
  319.     }
  320. }
  321.  
  322. /*
  323.  * writepend() - write pending data to the output file, scanning for
  324.  *  output control characters.  Called only by the macro outpend().
  325.  */
  326.  
  327. writepend()
  328. {
  329.     char *cp;
  330.  
  331.     for (cp = &pend[0]; cp < nxtout; cp++) {
  332.         if (*cp != ATTN) {
  333.             if (dooutput) {
  334.                 putchar(*cp);
  335.             }
  336.         } else {
  337.             switch(*++cp) {
  338.             case AT_OUTON:
  339.                 dooutput = TRUE;
  340.                 break;
  341.             case AT_OUTOFF:
  342.                 dooutput = FALSE;
  343.                 break;
  344.             default:
  345.                 bombf("INTERNAL illegal character in output: 0x%x", ATTN);
  346.             }
  347.         }
  348.     }
  349.     nxtout = &pend[0];
  350. }
  351.  
  352. /*
  353.  * dispose() - dispose of pending output.
  354.  *  output from the given point to nxtout is discarded, output control ATTN's
  355.  *  are not discarded.
  356.  */
  357.  
  358. char *        /* returns the new end of the buffer (nxttok)    */
  359. dispose(f)
  360. char *f;
  361. {
  362.     char *cp;
  363.  
  364.     for (cp = f; cp < nxtout; cp++) {
  365.         if (*cp == ATTN) {
  366.             /* copy the ATTN byte and the following code    */
  367.  
  368.             *f++ = *cp++;
  369.             *f++ = *cp;
  370.         }
  371.     }
  372.     nxtout = f;
  373.     return(f);
  374. }
  375.  
  376. /*
  377.  * warnf - print a file-specific error and continue;
  378.  */
  379.  
  380. /*VARARGS1*/
  381. warnf(s, x1, x2, x3, x4, x5, x6, x7, x8)
  382. char *s;
  383. int x1, x2, x3, x4, x5, x6, x7, x8;
  384. {
  385.     if (curfile >= &filestk[0]) {
  386.         fprintf(stderr, "\"%s\", line %d: ",
  387.           curfile->af_name, curfile->af_line);
  388.     }
  389.     fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
  390.     fprintf(stderr, "\n");
  391.     sawerror = TRUE;
  392. }
  393.  
  394. /*
  395.  * bombf - print a file-specific error and exit.
  396.  */
  397.  
  398. /*VARARGS1*/
  399. bombf(s, x1, x2, x3, x4, x5, x6, x7, x8)
  400. char *s;
  401. int x1, x2, x3, x4, x5, x6, x7, x8;
  402. {
  403.     warnf(s, x1, x2, x3, x4, x5, x6, x7, x8);
  404.     exit(1);
  405. }
  406.  
  407. /*
  408.  * warn - print a non-file-specific error and continue.
  409.  */
  410.  
  411. /*VARARGS1*/
  412. warn(s, x1, x2, x3, x4, x5, x6, x7, x8)
  413. char *s;
  414. int x1, x2, x3, x4, x5, x6, x7, x8;
  415. {
  416.     fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
  417.     fprintf(stderr, "\n");
  418.     sawerror = TRUE;
  419. }
  420.  
  421. /*
  422.  * bomb - print a non-file-specific error and exit.
  423.  */
  424.  
  425. /*VARARGS1*/
  426. bomb(s, x1, x2, x3, x4, x5, x6, x7, x8)
  427. char *s;
  428. int x1, x2, x3, x4, x5, x6, x7, x8;
  429. {
  430.     fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
  431.     exit(1);
  432. }
  433.  
  434. /*
  435.  * over() - input pushback overflow
  436.  */
  437.  
  438. over()
  439. {
  440.     bombf("too much pushback");
  441. }
  442.