📄 ncpp.c
字号:
/* saw a letter or _ */
ID1, {C_XX}, ACT(NAME, S_NAME),
ID1, {C_ALPH, C_NUM}, ID1,
/* saw L (start of wide string?) */
ST1, {C_XX}, ACT(NAME, S_NAME),
ST1, {C_ALPH, C_NUM}, ID1,
ST1, {'"'}, ST2,
ST1, {'\''}, CC1,
/* saw " beginning string */
ST2, {C_XX}, ST2,
ST2, {'"'}, ACT(STRING, S_SELF),
ST2, {'\\'}, ST3,
ST2, {'\n'}, S_STNL,
ST2, {EOFC}, S_EOFSTR,
/* saw \ in string */
ST3, {C_XX}, ST2,
ST3, {'\n'}, S_STNL,
ST3, {EOFC}, S_EOFSTR,
/* saw ' beginning character const */
CC1, {C_XX}, CC1,
CC1, {'\''}, ACT(CCON, S_SELF),
CC1, {'\\'}, CC2,
CC1, {'\n'}, S_STNL,
CC1, {EOFC}, S_EOFSTR,
/* saw \ in ccon */
CC2, {C_XX}, CC1,
CC2, {'\n'}, S_STNL,
CC2, {EOFC}, S_EOFSTR,
/* saw /, perhaps start of comment */
COM1, {C_XX}, ACT(SLASH, S_SELFB),
COM1, {'='}, ACT(ASSLASH, S_SELF),
COM1, {'*'}, COM2,
COM1, {'/'}, COM4,
/* saw "/ *", start of comment */
COM2, {C_XX}, COM2,
COM2, {'\n'}, S_COMNL,
COM2, {'*'}, COM3,
COM2, {EOFC}, S_EOFCOM,
/* saw the * possibly ending a comment */
COM3, {C_XX}, COM2,
COM3, {'\n'}, S_COMNL,
COM3, {'*'}, COM3,
COM3, {'/'}, S_COMMENT,
/* // comment */
COM4, {C_XX}, COM4,
COM4, {'\n'}, S_NL,
COM4, {EOFC}, S_EOFCOM,
/* saw white space, eat it up */
WS1, {C_XX}, S_WS,
WS1, {' ', '\t', '\v'}, WS1,
/* saw -, check --, -=, -> */
MINUS1, {C_XX}, ACT(MINUS, S_SELFB),
MINUS1, {'-'}, ACT(MMINUS, S_SELF),
MINUS1, {'='}, ACT(ASMINUS, S_SELF),
MINUS1, {'>'}, ACT(ARROW, S_SELF),
/* saw +, check ++, += */
PLUS1, {C_XX}, ACT(PLUS, S_SELFB),
PLUS1, {'+'}, ACT(PPLUS, S_SELF),
PLUS1, {'='}, ACT(ASPLUS, S_SELF),
/* saw <, check <<, <<=, <= */
LT1, {C_XX}, ACT(LT, S_SELFB),
LT1, {'<'}, LT2,
LT1, {'='}, ACT(LEQ, S_SELF),
LT2, {C_XX}, ACT(LSH, S_SELFB),
LT2, {'='}, ACT(ASLSH, S_SELF),
/* saw >, check >>, >>=, >= */
GT1, {C_XX}, ACT(GT, S_SELFB),
GT1, {'>'}, GT2,
GT1, {'='}, ACT(GEQ, S_SELF),
GT2, {C_XX}, ACT(RSH, S_SELFB),
GT2, {'='}, ACT(ASRSH, S_SELF),
/* = */
ASG1, {C_XX}, ACT(ASGN, S_SELFB),
ASG1, {'='}, ACT(EQ, S_SELF),
/* ! */
NOT1, {C_XX}, ACT(NOT, S_SELFB),
NOT1, {'='}, ACT(NEQ, S_SELF),
/* & */
AND1, {C_XX}, ACT(AND, S_SELFB),
AND1, {'&'}, ACT(LAND, S_SELF),
AND1, {'='}, ACT(ASAND, S_SELF),
/* | */
OR1, {C_XX}, ACT(OR, S_SELFB),
OR1, {'|'}, ACT(LOR, S_SELF),
OR1, {'='}, ACT(ASOR, S_SELF),
/* # */
SHARP1, {C_XX}, ACT(SHARP, S_SELFB),
SHARP1, {'#'}, ACT(DSHARP, S_SELF),
/* % */
PCT1, {C_XX}, ACT(PCT, S_SELFB),
PCT1, {'='}, ACT(ASPCT, S_SELF),
/* * */
STAR1, {C_XX}, ACT(STAR, S_SELFB),
STAR1, {'='}, ACT(ASSTAR, S_SELF),
/* ^ */
CIRC1, {C_XX}, ACT(CIRC, S_SELFB),
CIRC1, {'='}, ACT(ASCIRC, S_SELF),
-1
};
/* first index is char, second is state */
/* increase #states to power of 2 to encourage use of shift */
static short bigfsm[256][MAXSTATE];
static void expandlex(void)
{
/* const */ struct fsm *fp;
int i, j, nstate;
for (fp = fsm; fp->state >= 0; fp++) {
for (i = 0; fp->ch[i]; i++) {
nstate = fp->nextstate;
if (nstate >= S_SELF)
nstate = ~nstate;
switch (fp->ch[i]) {
case C_XX: /* random characters */
for (j = 0; j < 256; j++)
bigfsm[j][fp->state] = (short) nstate;
continue;
case C_ALPH:
for (j = 0; j <= 256; j++)
if ('a' <= j && j <= 'z' || 'A' <= j && j <= 'Z'
|| j == '_')
bigfsm[j][fp->state] = (short) nstate;
continue;
case C_NUM:
for (j = '0'; j <= '9'; j++)
bigfsm[j][fp->state] = (short) nstate;
continue;
default:
bigfsm[fp->ch[i]][fp->state] = (short) nstate;
}
}
}
/* install special cases for ? (trigraphs), \ (splicing), runes, and
EOB */
for (i = 0; i < MAXSTATE; i++) {
for (j = 0; j < 0xFF; j++)
if (j == '?' || j == '\\') {
if (bigfsm[j][i] > 0)
bigfsm[j][i] = (short) ~bigfsm[j][i];
bigfsm[j][i] &= ~QBSBIT;
}
bigfsm[EOB][i] = ~S_EOB;
if (bigfsm[EOFC][i] >= 0)
bigfsm[EOFC][i] = ~S_EOF;
}
}
static void fixlex(void)
{
/* do C++ comments? */
if (Cplusplus == 0)
bigfsm['/'][COM1] = bigfsm['x'][COM1];
}
/*
* fill in a row of tokens from input, terminated by NL or END
* First token is put at trp->lp.
* Reset is non-zero when the input buffer can be "rewound."
* The value is a flag indicating that possible macros have
* been seen in the row.
*/
static int gettokens(Tokenrow * trp, int reset)
{
register unsigned int c;
int state, oldstate;
register uchar *ip;
register Token *tp, *maxp;
int runelen;
Source *s = cursource;
int nmac = 0;
tp = trp->lp;
ip = s->inp;
if (reset) {
s->lineinc = 0;
if (ip >= s->inl) { /* nothing in buffer */
s->inl = s->inb;
fillbuf(s);
ip = s->inp = s->inb;
}
else if (ip >= s->inb + (3 * INS / 4)) {
memmove(s->inb, ip, 4 + s->inl - ip);
s->inl = s->inb + (s->inl - ip);
ip = s->inp = s->inb;
}
}
maxp = &trp->bp[trp->max];
runelen = 1;
for (;;) {
continue2:
if (tp >= maxp) {
trp->lp = tp;
tp = growtokenrow(trp);
maxp = &trp->bp[trp->max];
}
tp->type = UNCLASS;
tp->hideset = 0;
tp->t = ip;
tp->wslen = 0;
tp->flag = 0;
state = START;
for (;;) {
oldstate = state;
c = *ip;
if (c == EOB && ip[1] != EOB) {
state = bigfsm['a'][state];
}
else
state = bigfsm[c][state];
if (state >= 0) {
ip += runelen;
runelen = 1;
continue;
}
state = ~state;
reswitch:
switch (state & 0177) {
case S_SELF:
ip += runelen;
runelen = 1;
case S_SELFB:
tp->type = (unsigned char) GETACT(state);
tp->len = ip - tp->t;
tp++;
goto continue2;
case S_NAME: /* like S_SELFB but with nmac check */
tp->type = NAME;
tp->len = ip - tp->t;
nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
tp++;
goto continue2;
case S_WS:
tp->wslen = ip - tp->t;
tp->t = ip;
state = START;
continue;
default:
if ((state & QBSBIT) == 0) {
ip += runelen;
runelen = 1;
continue;
}
state &= ~QBSBIT;
s->inp = ip;
if (c == '?') { /* check trigraph */
if (trigraph(s)) {
state = oldstate;
continue;
}
goto reswitch;
}
if (c == '\\') {/* line-folding */
if (foldline(s)) {
s->lineinc++;
state = oldstate;
continue;
}
goto reswitch;
}
error(CPPWARNING, StrTab[141]); // <Lexical botch in cpp>
ip += runelen;
runelen = 1;
continue;
case S_EOB:
s->inp = ip;
fillbuf(cursource);
state = oldstate;
continue;
case S_EOF:
tp->type = END;
tp->len = 0;
s->inp = ip;
if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
error(CPPWARNING, StrTab[142]); // <No newline at end of file>
trp->lp = tp + 1;
return nmac;
case S_STNL:
error(CPPERROR, StrTab[143]); // <Unterminated string or char const>
case S_NL:
tp->t = ip;
tp->type = NL;
tp->len = 1;
tp->wslen = 0;
s->lineinc++;
s->inp = ip + 1;
trp->lp = tp + 1;
return nmac;
case S_EOFSTR:
error(CPPFATAL, StrTab[144]); // <EOF in string or char constant>
break;
case S_COMNL:
s->lineinc++;
state = COM2;
ip += runelen;
runelen = 1;
/* patch proposed by dave hanson an 3 June 1998 */
if (ip >= s->inb+(7*INS/8)) { /* very long comment */
memmove(tp->t,ip,4+s->inl-ip);
s->inl -= ip-tp->t;
ip = tp->t+1;
}
continue;
case S_EOFCOM:
error(CPPWARNING, StrTab[145]); // <EOF inside comment>
--ip;
case S_COMMENT:
++ip;
tp->t = ip;
tp->t[-1] = ' ';
tp->wslen = 1;
state = START;
continue;
}
break;
}
ip += runelen;
runelen = 1;
tp->len = ip - tp->t;
tp++;
}
}
/* have seen ?; handle the trigraph it starts (if any) else 0 */
static int trigraph(Source * s)
{
int c;
while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
if (s->inp[1] != '?')
return 0;
c = 0;
switch (s->inp[2]) {
case '=':
c = '#';
break;
case '(':
c = '[';
break;
case '/':
c = '\\';
break;
case ')':
c = ']';
break;
case '\'':
c = '^';
break;
case '<':
c = '{';
break;
case '!':
c = '|';
break;
case '>':
c = '}';
break;
case '-':
c = '~';
break;
}
if (c) {
*s->inp = (unsigned char) c;
memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
s->inl -= 2;
}
return c;
}
static int foldline(Source * s)
{
while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
if (s->inp[1] == '\n') {
memmove(s->inp, s->inp + 2, s->inl - s->inp + 3);
s->inl -= 2;
return 1;
}
return 0;
}
static int fillbuf(Source * s)
{
int n;
if (s->fd < 0 || (n = DoRead(s->fd, (char *) s->inl, INS / 8)) <= 0)
n = 0;
s->inl += n;
s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
if (n == 0) {
s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
return EOF;
}
return 0;
}
/*
* Push down to new source of characters.
* If fd>0 and str==NULL, then from a file `name';
* if fd==-1 and str, then from the string.
*/
static Source *setsource(unsigned char *name, int fd, char *str)
{
Source *s = new(Source);
int len;
s->line = 1;
s->lineinc = 0;
s->fd = fd;
s->filename = name;
s->next = cursource;
s->ifdepth = 0;
cursource = s;
/* slop at right for EOB */
if (str) {
len = strlen(str);
s->inb = domalloc(len + 4);
s->inp = s->inb;
strncpy((char *) s->inp, str, len);
}
else {
s->inb = domalloc(INS + 4);
s->inp = s->inb;
len = 0;
}
s->inl = s->inp + len;
s->inl[0] = s->inl[1] = EOB;
#ifndef LRC
if (fd >= 0 && xrefFile) {
fprintf(xrefFile, "f %s\n", name);
AddToFileTable(name);
}
#endif
return s;
}
static void unsetsource(void)
{
Source *s = cursource;
if (s->fd >= 0) {
DoClose(s->fd);
dofree(s->inb);
if (Mflag > 1) {
fprintf(TraceIncludesFile,"closing %s\n",cursource->filename);
}
}
cursource = s->next;
dofree(s);
}
#define MAXMACROARGS 256
/*
* do a macro definition. tp points to the name being defined in the line
*/
static Nlist *dodefine(Tokenrow * trp)
{
Token *tp;
Nlist *np;
Tokenrow *def, args,*pargs;
Token tmpTokenRow[MAXMACROARGS];
tp = trp->tp + 1;
if (tp >= trp->lp || tp->type != NAME) {
error(CPPERROR, StrTab[146]); // <#defined token is not a name>
return NULL;
}
np = InstallToken(tp);
if (np->flag & ISUNCHANGE) {
error(CPPWARNING, StrTab[147], tp); // <#defined token %t can't be redefined>
return NULL;
}
/* collect arguments */
tp += 1;
pargs = NULL;
if (tp < trp->lp && tp->type == LP && tp->wslen == 0) {
/* macro with args */
int narg = 0;
tp += 1;
memset(tmpTokenRow,0,sizeof(tmpTokenRow));
args.bp = tmpTokenRow;
args.max = MAXMACROARGS;
args.tp = tmpTokenRow;
args.lp = tmpTokenRow;
pargs = &args;
if (tp->type != RP) {
int err = 0;
for (;;) {
Token *atp;
if (tp->type != NAME) {
err++;
break;
}
if (narg >= args.max) {
error(CPPFATAL,"Maximum number of macro arguments exceeded");
exit(1);
}
for (atp = args.bp; atp < args.lp; atp++)
if (atp->len == tp->len
&& strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0)
error(CPPERROR, StrTab[148]); // <Duplicate macro argument>
*args.lp++ = *tp;
narg++;
tp += 1;
if (tp->type == RP)
break;
if (tp->type != COMMA) {
err++;
break;
}
tp += 1;
}
if (err) {
error(CPPERROR, StrTab[149]); // <Syntax error in macro parameters>
return NULL;
}
}
tp += 1;
}
trp->tp = tp;
if (((trp->lp) - 1)->type == NL)
trp->lp -= 1;
def = normtokenrow(trp);
if (np->flag & ISDEFINED) {
if (comparetokens(def, np->vp)
|| (np->ap == NULL) != (pargs == NULL)
|| np->ap && comparetokens(pargs, np->ap))
error(CPPERROR, StrTab[150], trp->bp + 2); // <Macro redefinition of %t>
}
if (pargs) {
Tokenrow *tap;
tap = normtokenrow(pargs);
pargs = tap;
}
np->ap = pargs;
np->vp = def;
np->flag |= ISDEFINED;
np->srcline = (unsigned short) cursource->line;
np->filename = cursource->filename;
return np;
}
/*
* Definition received via -D or -U
*/
static Nlist *doadefine(Tokenrow * trp, int type)
{
Nlist *np;
static Token onetoken[1] = {{NUMBER, 0, 0, 0, 1, (uchar *) "1"}};
static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1};
trp->tp = trp->bp;
if (type == 'U') {
if (trp->lp - trp->tp != 2 || trp->tp->type != NAME)
goto syntax;
if ((np = cpplookup(trp->tp)) == NULL)
return NULL;
np->flag &= ~ISDEFINED;
return NULL;
}
if (trp->tp >= trp->lp || trp->tp->type != NAME)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -