📄 ccpp.c
字号:
int c;
{
if (backstr)
{
backstr--; /* pushed string input, back up over it */
if(c != *backstr)
int_error("pushch: bad backup char");
return;
}
/* File input, back up over that.
** Note that errlin and t/f/line only need to be fixed up for file input.
*/
if (c != ungetc(c, in))
int_error("pushch: ungetc failed: %o", c);
if (isceol(c))
{
line--; /* dont lose track of line count */
fline--;
tline--;
}
/* Back up over char of saved context */
if (erptr == errlin) /* If at start of buffer */
{
erptr = errlin + ERRLSIZE; /* Wrap back to end */
erpleft = 0;
}
*--erptr = '\0'; /* Back up and zap what we previously stored */
++erpleft;
}
static
int
pushstr(cp)
char *cp;
{
bstrpush(cp);
return nextch();
}
static
void
bstrpush(cp)
char *cp;
{
if (bkstrlev >= MAXBKSTRS-1)
{
int_error("bstrpush: bkstrs overflow");
bkstrlev = MAXBKSTRS-1;
}
else
{
bkstrs[bkstrlev++] = backstr;
backstr = cp;
}
}
static
void
bstrpop (void)
{
if (--bkstrlev < 0)
{
int_error("bstrpop: bkstrs underflow");
backstr = NULL, bkstrlev = 0;
}
else
backstr = bkstrs[bkstrlev];
}
/* NEXTRAWPP() Phase 3 - produce raw PP tokens
** (handles comments, flushes WSP)
**
*/
#define retchk(chr,no,yes) if (nextch () != chr) \
rawpp = no; \
else \
{ \
nextch (); \
rawpp = yes; \
}
#define retchk2(ch1,ch2,no,yes1,yes2) switch (nextch ()) \
{ \
case ch1: \
nextch (); \
rawpp = yes1; \
break; \
case ch2: \
nextch (); \
rawpp = yes2; \
break; \
default: \
rawpp = no; \
break; \
}
static
int
nextrawpp (void)
{
int retflag = 0;
rawval.i = 0;
switch (ch)
{
case EOF:
rawpp = T_EOF;
retflag = 1;
break;
/* Check for "bad" horiz whitespace (may give error msg) */
case '\r': /* Include CR here for now */
case '\v': /* Vert tab */
case '\f': /* Ditto FF */
pushch (ch); /* Ensure scanhwsp () will see this char */
/* Drop thru to call scanner */
/* Check for "good" horiz whitespace */
case '\t': /* Horiz tab */
case ' ': /* Space */
scanhwsp ();
retflag = 1;
break;
case '\n':
rawpp = T_EOL;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ppnconst (0);
retflag = 1;
break;
case '\'':
ppsconst (0); /* Char constant */
rawpp = T_CCONST;
retflag = 1;
break;
case '"':
ppsconst (0); /* String constant */
rawpp = T_SCONST;
retflag = 1;
break;
case '.':
if (isdigit (nextch ())) /* If followed by digit, */
{
ppnconst ('.');
retflag = 1;
break;
}
if (ch != '.')
{
rawpp = Q_DOT;
retflag = 1;
break;
}
if (nextch() != '.') /* Ellipsis "..."? */
{
pushch(ch); /* Nope, push it back */
ch = '.'; /* And restore prev char */
rawpp = Q_DOT;
retflag = 1;
break;
}
rawpp = T_ELPSIS; /* ... */
break;
case '#':
retchk('#', T_SHARP, T_SHARP2) /* # and ## */
retflag = 1;
break;
case '=': /* KAR-11/91, usage before initialization code */
if (nextch() != '=')
{
ra_expr = 1;
rawpp = Q_ASGN;
retflag = 1;
break;
}
nextch();
rawpp = Q_EQUAL;
retflag = 1;
break;
case '!':
retchk('=', Q_NOT, Q_NEQ) /* ! and != */
retflag = 1;
break;
case '*':
retchk('=', Q_MPLY, Q_ASMPLY) /* * and *= */
retflag = 1;
break;
case '%':
retchk('=', Q_MOD, Q_ASMOD) /* % and %= */
retflag = 1;
break;
case '^':
retchk('=', Q_XORT, Q_ASXOR) /* ^ and ^= */
retflag = 1;
break;
case '/': /* Special, to check for comments! */
switch (nextch ())
{
default:
rawpp = Q_DIV;
break;
case '=':
nextch();
rawpp = Q_ASDIV;
break;
case '*':
scancomm ();
scanhwsp ();
break;
case '/': /* KAR-2/93, PPS 4574; C++ comments */
if (!clevnocpp) /* FW 2A(46) August 1993 */
{
comment_type = CPP;
scancomm ();
pushch (ch); /* FW 2A(50) September 1993 */
comment_type = C;
}
scanhwsp ();
break;
}
retflag = 1;
break;
case '|':
retchk2('=','|', Q_OR, Q_ASOR, Q_LOR) /* | and |= and || */
retflag = 1;
break;
case '&':
retchk2('=','&', Q_ANDT, Q_ASAND, Q_LAND) /* & and &= and && */
retflag = 1;
break;
case '+':
retchk2('=','+', Q_PLUS, Q_ASPLUS, T_INC) /* + and += and ++ */
retflag = 1;
break;
case '-':
switch (nextch())
{
case '-':
rawpp = T_DEC;
break; /* -- */
case '=':
rawpp = Q_ASMINUS;
break;/* -= */
case '>':
rawpp = Q_MEMBER;
break;/* -> */
default:
rawpp = Q_MINUS;
retflag = 1;
break;
}
break;
case '>':
switch (nextch())
{
default:
rawpp = Q_GREAT;
retflag = 1;
break;
case '=':
rawpp = Q_GEQ;
break; /* >= */
case '>':
retchk ('=', Q_RSHFT, Q_ASRSH) /* >> and >>= */
retflag = 1;
break;
}
break;
case '<':
switch (nextch())
{
default:
rawpp = Q_LESS;
retflag = 1;
break;
case '=':
rawpp = Q_LEQ; /* <= */
break;
case '<':
retchk('=', Q_LSHFT, Q_ASLSH) /* << and <<= */
retflag = 1;
break;
}
break;
case '(':
rawpp = T_LPAREN;
break;
case ')':
rawpp = T_RPAREN;
break;
case ',':
rawpp = T_COMMA;
ra_expr = 0;
break;
case ':':
rawpp = T_COLON;
break;
case ';':
rawpp = T_SCOLON;
ra_expr = 0;
break;
case '?':
rawpp = Q_QUERY;
break;
case '[':
rawpp = T_LBRACK;
break;
case ']':
rawpp = T_RBRACK;
break;
case '{':
rawpp = T_LBRACE;
ra_expr = 0;
break;
case '}':
rawpp = T_RBRACE;
break;
case '~':
rawpp = Q_COMPL;
break;
case '`': /* KCC extension: identifier quoter */
if (clevkcc) /* If extensions in effect, */
{
ppsconst(0); /* parse like string literal! */
rawpp = T_IDENT;
}
else
ppunknwn();
retflag = 1;
break;
default:
if (!iscsymf(ch)) /* Can char be start of identifier? */
{
ppunknwn();
retflag = 1;
break;
}
/* Handle identifier! */
rawval.cp = ppcbeg(); /* Assume ident, harmless if not */
if (ch == 'L') /* Possible "wide char" indicator? (BARF!!) */
{
int ch2 = nextch();
if (ch2 =='\'')
{
ppsconst('L');
rawpp = T_CCONST;
retflag = 1;
break;
}
else if (ch2 =='\"')
{
ppsconst('L');
rawpp = T_SCONST;
retflag = 1;
break;
}
ppcput('L'); /* Not a wide char, recover from peekahead */
if (!iscsym(ch)) /* Was it just "L"? Barf, barf */
{
rawpplen = ppcend();
rawpp = T_IDENT;
retflag = 1;
break;
}
}
do
{
ppcput(ch); /* Gobble up identifier */
}
while (iscsym(nextch()));
rawpplen = ppcend();
rawpp = T_IDENT;
retflag = 1;
break;
} /* End of switch(ch) */
if (!retflag)
nextch(); /* Done, set up next char after this token */
/*
* A tokenizing pre-compilation scheme will break the input stream
* at this point. Tokens, and their associated string literals
* if any, will be diverted to a file.
*/
return rawpp;
}
/* SCANHWSP - gobbles all horiz whitespace starting with current char, and
** returns a T_WSP token.
*/
static
int
scanhwsp (void)
{
for (;;)
{
while (iscppwsp(nextch())) ; /* Skip all valid PP whitespace */
switch (ch)
{
case '\r':
if (nextch() == '\n') /* Peek ahead */
{
note("Stray '\\r' seen, ignoring");
break;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -