|
|
coherent
/*
* C preprocessor.
* Read next character.
*/
#include <time.h>
#ifdef vax
#include "INC$LIB:cc0.h"
#else
#include "cc0.h"
#endif
/*
* Look ahead for '#' or '(',
* and restore the stream if you fail.
* This gets reentered looking for '#'
* when the search for a '(' passes newline.
*/
skipto(d) int d;
{
register char *p, *sp;
register int c;
sp = dpshp;
while ((c = get()) >= 0 && ct[c] == SKIP)
dpshc(c);
if (c >= 0)
dpshc(c);
if (c != d) {
for (p = dpshp; p < sp; ++p)
unget(*p);
dpshp = sp;
return 0;
}
dpshp = sp;
return 1;
}
/*
* Look at a newly opened file.
*/
emptyfilep()
{
int c;
c = getc(ifp);
if (c == EOF) {
c = '\n';
}
ungetc(c, ifp);
}
/*
* Get a character.
* This function returns the next character,
* and implements one character pushback,
* as well as the expanded macro stack.
*/
get()
{
register int c;
for (;;) {
switch (dstackp->ds_type) {
case DS_FUNGET: /* Ungotten character from file */
c = (dstackp++)->ds_char & 0377;
goto file_char;
case DS_FILE: /* Read next character from source file */
while ((c = getc(ifp)) < 0) { /* Pop include stack */
eof: fclose(ifp);
if (lastchar != '\n' && lastchar != EOF)
eof_in_line: cfatal("EOF in midline");
if (istackp < istack+NLEV) {
if (cstackp != istackp->i_cstackp)
cerror("missing #endif");
cstackp = istackp->i_cstackp;
line = istackp->i_line;
if (notvariant(VCPP)) {
bput(LINE);
iput((ival_t)line);
}
idp = istackp->i_file;
setfname();
ifp = istackp->i_fp;
++istackp;
continue;
}
if (cstackp < cstack+NLEV)
cerror("missing #endif");
cstackp = cstack + NLEV;
lastchar = c;
return c; /* ie, EOF */
}
file_char: lastchar = c;
switch (ct[c]) {
case SKIP: /* New line? */
#if GEMDOS || MSDOS /* Assuming use of bingetc() */
if (c == '\r')
continue;
#endif
if (c == '\n') {
if (incpp) {
ungetc(c, ifp);
return EOF;
}
if (instring) {
cerror("new line in %s literal",
instring=='"' ? "string" : "character");
++line;
c = ' ';
} else
notskip = 0;
}
notskip -= 1;
break;
case QUEST: /* Trigraph? */
if (notvariant(V3GRAPH))
break;
if ((c = getc(ifp)) < 0)
goto eof_in_line;
if (c != '?') {
ungetc(c, ifp);
c = '?';
break;
}
if ((c = getc(ifp)) < 0)
goto eof_in_line;
switch (c) {
case '=': ungetc('#', ifp); continue;
case '(': ungetc('[', ifp); continue;
case '/': ungetc('\\', ifp); continue;
case ')': ungetc(']', ifp); continue;
case '\'': ungetc('^', ifp); continue;
case '<': ungetc('{', ifp); continue;
case '!': ungetc('|', ifp); continue;
case '>': ungetc('}', ifp); continue;
case '-': ungetc('~', ifp); continue;
default:
ungetc(c, ifp);
dspushc(DS_FUNGET, '?');
c = '?';
}
break;
case DIV: /* Comment? */
if (instring)
break;
if ((c = getc(ifp))< 0)
goto eof_in_line;
if (c != '*') {
ungetc(c, ifp);
c = '/';
break;
}
for (;;) {
if ((c = getc(ifp)) < 0)
eof_in_comment: cfatal("EOF in comment");
if (c == '*') {
if ((c = getc(ifp)) < 0)
goto eof_in_comment;
if (c == '/')
break;
ungetc(c, ifp);
} else if (c == '/') {
if ((c = getc(ifp)) < 0)
goto eof_in_comment;
if (c == '*')
cwarn("nested comments");
ungetc(c, ifp);
} else if (c == '\n')
++line;
}
c = ' ';
break;
case BACKDIV: /* Splice? */
try_again: if ((c = getc(ifp)) < 0)
goto eof_in_line;
if (c != '\n') {
#if GEMDOS || MSDOS /* Assuming use of bingetc() */
if (c == '\r')
goto try_again;
#endif
ungetc(c, ifp);
c = '\\';
break;
}
++line;
continue;
case HIGH0:
case HIGH1:
case HIGH2:
case HIGH3:
case JUNK:
#if GEMDOS || MSDOS /* Assuming use of bingetc() */
if (c == 26) /* ^Z */
goto eof;
#endif
if (instring || (c > ' ' && c < 0177))
break;
cerror("illegal cpp character (%d decimal)", c);
continue;
case SHARP:
if (notskip != 0)
break;
++incpp;
control();
--incpp;
continue;
}
notskip += 1;
break;
case DS_UNGET: /* Read ungotten character */
c = (dstackp++)->ds_char & 0377;
break;
case DS_STRNG:
if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
++dstackp;
continue;
}
break;
case DS_UFILE: /* Convert file name into string */
if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
++dstackp;
continue;
}
if (c == '\\' || c == '"') {
unget(c);
c = '\\';
}
break;
case DS_SHARP: /* Read and stringize */
if ((c = *dstackp->ds_ptr++ & 0377) == 0) {
++dstackp;
continue;
}
if (dstackp->ds_char) {
if (c == dstackp->ds_char) {
dstackp->ds_char = 0;
if (c == '"') {
unget(c);
c = '\\';
}
} else if (c == '\\') {
c = *dstackp->ds_ptr++;
unget(c);
if (c == '"')
unget('\\');
unget('\\');
c = '\\';
}
} else if (c == '"') {
dstackp->ds_char = c;
unget(c);
c = '\\';
} else if (c == '\'')
dstackp->ds_char = c;
else if (c >= SET0)
continue;
break;
case DS_DPUTP:
dputp = (dstackp++)->ds_ptr;
continue;
case DS_NAME:
++dstackp;
continue;
case DS_IEOF:
c = EOF;
break;
default:
cbotch("bad ds_type %d", dstackp->ds_type);
}
if (c == '\n') ++line;
if (cstate != 0 && incpp == 0)
continue;
return c;
}
}
/*
* One character pushback
* for the callers of get().
*/
unget(c) int c;
{
if (c < 0)
return;
dspushc(DS_UNGET, c);
if (c == '\n')
--line;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.