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 >
Wrap
Text File
|
2009-11-06
|
9KB
|
442 lines
/*
* io.c - input and output primitives for the selective C preprocessor, scpp.
*
* Copyright (c) 1985 by
* Tektronix, Incorporated Beaverton, Oregon 97077
* All rights reserved.
*
* Permission is hereby granted for personal, non-commercial
* reproduction and use of this program, provided that this
* notice and all copyright notices are included in any copy.
*/
# include <stdio.h>
# include "scpp.h"
# define STDINPUT 0 /* file descriptor of stdin */
# define BSIZE 512
/*
* # of bytes per read -- controls how quickly
* istk[] is consumed.
*/
int dooutput = 1; /* "actually write data" rather than tossing it */
/*
* nxtc() - return the next character from the input stream.
* Nxtc() is used only by lex.
*/
char
nxtc()
{
char ch;
int readcnt;
while ((ch = *nxtin++) == ATTN) {
switch (ch = *nxtin++) {
case AT_EPUSH: /* end of pushback (interpreted text) */
curfile->af_raw = TRUE;
break;
case AT_EBLK: /* end of block */
/*
* The current block is exhausted.
* Mark the end of the new block
* then read in the new block (if there's space)
* and adjust the top of stack.
*/
unc(AT_EBLK);
unc(ATTN);
if (nxtin < &istk[BSIZE]) {
over();
}
nxtin -= BSIZE;
readcnt = read(curfile->af_fd, nxtin, BSIZE);
if (readcnt < 0) {
bombf("read error");
}
if (readcnt > 0) {
if (readcnt < BSIZE) {
/* slide the new data into place */
register char *src, *dst;
for (dst = nxtin + BSIZE,
src = nxtin + readcnt;
src > nxtin; *--dst = *--src)
;
nxtin = dst;
}
break;
}
/*
* The current file is exhausted.
* Pop the nonexistent block and the ATTN bytes
* from the input stack;
* Turn on the output if necessary;
* Close and pop the file.
*/
nxtin += BSIZE + 2;
if (curfile->af_hide) {
if (--hidecnt == 0 && falsecnt == 0) {
quec(ATTN);
quec(AT_OUTON);
}
}
if (curfile->af_fd != STDINPUT) {
close(curfile->af_fd);
}
free(curfile->af_name);
if (--curfile >= &filestk[0]){
break;
}
/*
* no more current files remain - open the next
* file to be processed (if there is one),
* or pushback the EOF character and an ATTN
* so that further nxtc() calls return EOF.
*/
if (*nxtfile == (char *) 0) {
unc(AT_EBLK);
unc(ATTN);
unc('\0');
break;
}
pushfile(*nxtfile++, PF_NOLOOK, PF_NOHIDE);
break;
default:
bombf("illegal character in input: 0x%x", ATTN);
}
}
return(ch);
}
/*
* untok() - push back the most recent token (less ATTN bytes)
* from the output stream into the input stream.
*/
untok()
{
char *cp;
for (cp = nxtout - 1; cp >= curtext; --cp) {
if (cp > curtext && *(cp - 1) == ATTN) {
--cp;
} else {
if (*cp == '\n' && curfile->af_raw) {
curfile->af_line--;
}
unc(*cp);
}
}
nxtout = dispose(curtext);
}
/*
* pushmac() - push the given macro value back into the input stream.
* Used to expand a macro.
* pushmac() is passed a pointer to the END of a string to be pushed
* (some part of a macro's replacement text). Pushmac() pushes the string
* backwards onto the input stack until it comes to a null-terminator or
* an ATTN byte. It returns a pointer to the terminator.
*/
char *
pushmac(v)
char *v; /* points to a null-terminator or other ignored byte */
{
if (curfile->af_raw) {
unc(AT_EPUSH);
unc(ATTN);
curfile->af_raw = FALSE;
}
while (*--v != '\0' && *v != ATTN) {
if (nxtin-- < &istk[0]) {
over();
}
*nxtin = *v;
}
return(v);
}
/*
* pushfile() - effectively push the given file into the input stream.
* Used to include a file.
*/
pushfile(name, itype, hide)
char *name;
int itype;
{
#define PNLEN 257
char pname[PNLEN];
char *cp;
char **dp;
struct afile *ip;
char *rindex();
char *malloc();
if (++curfile >= &filestk[FILESIZ]) {
--curfile;
warnf("too many nested include files. skipping `%s'", name);
return;
}
/*
* if the name is to be opened with no modification, do that.
* If the directory of the current file is to be searched, do that.
* Search each directory in the list for the file.
*/
if (name[0] == '/' || itype == PF_NOLOOK) {
(void) strcpy(pname, name);
if (strcmp(name, "-") == 0) {
curfile->af_fd = STDINPUT;
} else {
curfile->af_fd = open(pname, 1);
}
} else {
curfile->af_fd = -1;
if (itype == PF_DOT) {
(void) strcpy(pname, (curfile - 1)->af_name);
if ((cp = rindex(pname, '/'))) {
++cp;
} else {
cp = &pname[0];
}
if (cp + strlen(name) >= &pname[PNLEN]) {
--curfile;
bombf("name too long `%s%s'", pname, name);
}
(void) strcpy(cp, name);
curfile->af_fd = open(pname, 1);
}
for (dp = &dirlist[0]; *dp && curfile->af_fd < 0; dp++) {
cp = &pname[0] + strlen(*dp);
if (cp >= &pname[PNLEN]) {
--curfile;
bombf("name too long `%s'", *dp);
}
(void) strcpy(pname, *dp);
if (cp > &pname[0] && *(cp - 1) != '/') {
*cp++ = '/';
*cp = '\0';
}
if (cp + strlen(name) >= &pname[PNLEN]) {
--curfile;
bombf("name too long `%s%s'", pname, name);
}
(void) strcpy(cp, name);
curfile->af_fd = open(pname, 1);
}
}
if (curfile->af_fd < 0) {
--curfile;
warnf("cannot find%s file `%s'",
curfile > &filestk[0] ? " include" : "", name);
return;
}
/*
* the file is open.
* See if this is a recursive include.
*/
for (ip = &filestk[0]; ip < curfile; ip++) {
if (strcmp(ip->af_name, pname) == 0) {
close(curfile->af_fd);
--curfile;
warnf("skipping recursive inclusion of `%s'", pname);
return;
}
}
/*
* fill in the rest of the afile structure.
*/
if (!(curfile->af_name = malloc((unsigned) strlen(pname) + 1))) {
--curfile;
bombf("out of memory");
}
(void) strcpy(curfile->af_name, pname);
curfile->af_line = 1;
curfile->af_raw = TRUE;
curfile->af_hide = hide;
if (hide) {
if (hidecnt++ == 0 && falsecnt == 0) {
quec(ATTN);
quec(AT_OUTOFF);
}
}
unc(AT_EBLK);
unc(ATTN);
#undef PNLEN
}
/*
* quec() - move a character to the output queue, pend[]
*/
quec(c)
char c;
{
*nxtout = c;
if (++nxtout >= &pend[PENDSIZ]) {
bombf("too much forward search");
}
}
/*
* questr() - move the null-terminated string to the output queue, pend[]
* Used only by xxlex().
*/
questr(s, len)
register char *s;
int len; /* length (in bytes) of the string to be moved */
{
register char *d = nxtout;
if (d + len < &pend[PENDSIZ]) {
while (*d++ = *s++)
;
nxtout += len;
} else {
bombf("too much forward search");
}
}
/*
* writepend() - write pending data to the output file, scanning for
* output control characters. Called only by the macro outpend().
*/
writepend()
{
char *cp;
for (cp = &pend[0]; cp < nxtout; cp++) {
if (*cp != ATTN) {
if (dooutput) {
putchar(*cp);
}
} else {
switch(*++cp) {
case AT_OUTON:
dooutput = TRUE;
break;
case AT_OUTOFF:
dooutput = FALSE;
break;
default:
bombf("INTERNAL illegal character in output: 0x%x", ATTN);
}
}
}
nxtout = &pend[0];
}
/*
* dispose() - dispose of pending output.
* output from the given point to nxtout is discarded, output control ATTN's
* are not discarded.
*/
char * /* returns the new end of the buffer (nxttok) */
dispose(f)
char *f;
{
char *cp;
for (cp = f; cp < nxtout; cp++) {
if (*cp == ATTN) {
/* copy the ATTN byte and the following code */
*f++ = *cp++;
*f++ = *cp;
}
}
nxtout = f;
return(f);
}
/*
* warnf - print a file-specific error and continue;
*/
/*VARARGS1*/
warnf(s, x1, x2, x3, x4, x5, x6, x7, x8)
char *s;
int x1, x2, x3, x4, x5, x6, x7, x8;
{
if (curfile >= &filestk[0]) {
fprintf(stderr, "\"%s\", line %d: ",
curfile->af_name, curfile->af_line);
}
fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
fprintf(stderr, "\n");
sawerror = TRUE;
}
/*
* bombf - print a file-specific error and exit.
*/
/*VARARGS1*/
bombf(s, x1, x2, x3, x4, x5, x6, x7, x8)
char *s;
int x1, x2, x3, x4, x5, x6, x7, x8;
{
warnf(s, x1, x2, x3, x4, x5, x6, x7, x8);
exit(1);
}
/*
* warn - print a non-file-specific error and continue.
*/
/*VARARGS1*/
warn(s, x1, x2, x3, x4, x5, x6, x7, x8)
char *s;
int x1, x2, x3, x4, x5, x6, x7, x8;
{
fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
fprintf(stderr, "\n");
sawerror = TRUE;
}
/*
* bomb - print a non-file-specific error and exit.
*/
/*VARARGS1*/
bomb(s, x1, x2, x3, x4, x5, x6, x7, x8)
char *s;
int x1, x2, x3, x4, x5, x6, x7, x8;
{
fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
exit(1);
}
/*
* over() - input pushback overflow
*/
over()
{
bombf("too much pushback");
}