📄 ncpp.c
字号:
break;
case OR:
rv1 |= rv2;
break;
case CIRC:
rv1 ^= rv2;
break;
case TILDE:
rv1 = ~rv1;
break;
case NOT:
rv1 = !rv1;
if (rtype != UND)
rtype = SGN;
break;
case SLASH:
if (rv2 == 0) {
rtype = UND;
break;
}
if (rtype == UNS)
rv1 /= (unsigned long) rv2;
else
rv1 /= rv2;
break;
case PCT:
if (rv2 == 0) {
rtype = UND;
break;
}
if (rtype == UNS)
rv1 %= (unsigned long) rv2;
else
rv1 %= rv2;
break;
case COLON:
if (op[-1] != QUEST)
error(CPPERROR, StrTab[128]); // <Bad ?: in #if/endif>
else {
op--;
if ((--vp)->val == 0)
v1 = v2;
rtype = v1.type;
rv1 = v1.val;
}
break;
case DEFINED:
break;
default:
error(CPPERROR, StrTab[129]); // <Eval botch (unknown operator)>
return 1;
}
/*lint +e574 +e644 */
v1.val = rv1;
v1.type = rtype;
*vp++ = v1;
}
return 0;
}
static struct value tokval(Token * tp)
{
struct value v;
Nlist *np;
int i, base, c;
unsigned long n;
uchar *p;
v.type = SGN;
v.val = 0;
switch (tp->type) {
case NAME:
v.val = 0;
break;
case NAME1:
if ((np = cpplookup(tp)) != NULL && np->flag & ISDEFINED)
v.val = 1;
break;
case NUMBER:
n = 0;
base = 10;
p = tp->t;
c = p[tp->len];
p[tp->len] = '\0';
if (*p == '0') {
base = 8;
if (p[1] == 'x' || p[1] == 'X') {
base = 16;
p++;
}
p++;
}
for (;; p++) {
if ((i = digit(*p)) < 0)
break;
if (i >= base)
error(CPPWARNING,
StrTab[130], tp); // <Bad digit in number %t>
n *= base;
n += i;
}
if (n >= 0x80000000 && base != 10)
v.type = UNS;
for (; *p; p++) {
if (*p == 'u' || *p == 'U')
v.type = UNS;
else if (*p == 'l' || *p == 'L');
else {
error(CPPERROR,
StrTab[131], tp); // <Bad number %t in #if/#elsif>
break;
}
}
v.val = n;
tp->t[tp->len] = (unsigned char) c;
break;
case CCON:
n = 0;
p = tp->t;
if (*p == 'L') {
p += 1;
error(CPPWARNING, StrTab[132]); // <Wide char constant value undefined>
}
p += 1;
if (*p == '\\') {
p += 1;
if ((i = digit(*p)) >= 0 && i <= 7) {
n = i;
p += 1;
if ((i = digit(*p)) >= 0 && i <= 7) {
p += 1;
n <<= 3;
n += i;
if ((i = digit(*p)) >= 0 && i <= 7) {
p += 1;
n <<= 3;
n += i;
}
}
}
else if (*p == 'x') {
p += 1;
while ((i = digit(*p)) >= 0 && i <= 15) {
p += 1;
n <<= 4;
n += i;
}
}
else {
static char cvcon[]
= "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\";
for (i = 0; i < sizeof(cvcon); i += 2) {
if (*p == cvcon[i]) {
n = cvcon[i + 1];
break;
}
}
p += 1;
if (i >= sizeof(cvcon))
error(CPPWARNING,
StrTab[133]); // <Undefined escape in character constant>
}
}
else if (*p == '\'')
error(CPPERROR, StrTab[134]); // <Empty character constant>
else
n = *p++;
if (*p != '\'')
error(CPPWARNING, StrTab[135]); // <Multibyte character constant undefined>
else if (n > 127)
error(CPPWARNING, StrTab[136]); // <Character constant taken as not signed>
v.val = n;
break;
case STRING:
error(CPPERROR, StrTab[137]); // <String in #if/#elsif>
break;
}
return v;
}
static int digit(int i)
{
if ('0' <= i && i <= '9')
i -= '0';
else if ('a' <= i && i <= 'f')
i -= 'a' - 10;
else if ('A' <= i && i <= 'F')
i -= 'A' - 10;
else
i = -1;
return i;
}
/*
* A hideset is a null-terminated array of Nlist pointers.
* They are referred to by indices in the hidesets array.
* Hideset 0 is empty.
*/
//#define HSSIZ 32
#define HSSIZ 512
typedef Nlist **Hideset;
static Hideset *hidesets;
static int nhidesets = 0;
static int maxhidesets = 3;
static int inserths(Hideset, Hideset, Nlist *);
/*
* Test for membership in a hideset
*/
static int checkhideset(int hs, Nlist * np)
{
Hideset hsp;
if (hs >= nhidesets)
abort();
for (hsp = hidesets[hs]; *hsp; hsp++) {
if (*hsp == np)
return 1;
}
return 0;
}
/*
* Return the (possibly new) hideset obtained by adding np to hs.
*/
static int newhideset(int hs, Nlist * np)
{
int i, len;
Nlist *nhs[HSSIZ + 3];
Hideset hs1, hs2;
len = inserths(nhs, hidesets[hs], np);
for (i = 0; i < nhidesets; i++) {
for (hs1 = nhs, hs2 = hidesets[i]; *hs1 == *hs2; hs1++, hs2++)
if (*hs1 == NULL)
return i;
}
if (len >= HSSIZ)
return hs;
if (nhidesets >= maxhidesets) {
maxhidesets = 3 * maxhidesets / 2 + 1;
hidesets = (Hideset *) realloc(hidesets, (sizeof(Hideset *)) * maxhidesets);
}
hs1 = (Hideset) domalloc(len * sizeof(Hideset));
memmove(hs1, nhs, len * sizeof(Hideset));
hidesets[nhidesets] = hs1;
return nhidesets++;
}
static int inserths(Hideset dhs, Hideset shs, Nlist * np)
{
Hideset odhs = dhs;
while (*shs && *shs < np)
*dhs++ = *shs++;
if (*shs != np)
*dhs++ = np;
do {
*dhs++ = *shs;
} while (*shs++);
return dhs - odhs;
}
/*
* Hideset union
*/
static int unionhideset(int hs1, int hs2)
{
Hideset hp;
for (hp = hidesets[hs2]; *hp; hp++)
hs1 = newhideset(hs1, *hp);
return hs1;
}
static void iniths(void)
{
hidesets = (Hideset *) domalloc(maxhidesets * sizeof(Hideset *));
hidesets[0] = (Hideset) domalloc(sizeof(Hideset));
*hidesets[0] = NULL;
nhidesets++;
}
static Includelist includelist[NINCLUDE];
static unsigned char *objname;
int IsAbsolutePath(unsigned char *fname)
{
int drive = *fname;
if (drive >= 'a' && drive <= 'z')
drive -= ' ';
if (fname[1] == ':' && (drive >= 'A' && drive <= 'Z'))
return (1);
if (drive == '\\')
return 1;
return (0);
}
typedef struct tagSourceFilesList {
struct tagSourceFilesList *Next;
char *Name;
} SourceFilesList;
static SourceFilesList *LoadedSources = NULL;
static int NewSourceFile(char *name)
{
SourceFilesList *rvp,*last;
if (LoadedSources == NULL) {
LoadedSources = domalloc(sizeof(SourceFilesList));
LoadedSources->Name = domalloc(strlen(name)+1);
strcpy(LoadedSources->Name,name);
return 1;
}
rvp = LoadedSources;
last = NULL;
while (rvp) {
if (!stricmp(name,rvp->Name))
return 0;
last = rvp;
rvp = rvp->Next;
}
last->Next = domalloc(sizeof(SourceFilesList));
last = last->Next;
last->Name = domalloc(strlen(name)+1);
strcpy(last->Name,name);
return 1;
}
static void doinclude(Tokenrow * trp,int importflag)
{
unsigned char fname[256], iname[256], *p;
Includelist *ip;
int angled, len, fd, i;
if (Mflag)
importflag = 1;
trp->tp += 1;
if (trp->tp >= trp->lp)
goto syntax;
if (trp->tp->type != STRING && trp->tp->type != LT) {
len = trp->tp - trp->bp;
expandrow(trp, (unsigned char *) "<include>");
trp->tp = trp->bp + len;
}
if (trp->tp->type == STRING) {
len = trp->tp->len - 2;
if (len > sizeof(fname) - 1)
len = sizeof(fname) - 1;
strncpy(fname, trp->tp->t + 1, len);
angled = 0;
}
else {
len = 0;
trp->tp++;
while (trp->tp->type != GT) {
if (trp->tp > trp->lp || len + trp->tp->len + 2 >= sizeof(fname))
goto syntax;
strncpy(fname + len, trp->tp->t, trp->tp->len);
len += trp->tp->len;
trp->tp++;
}
angled = 1;
}
trp->tp += 2;
if (trp->tp < trp->lp || len == 0)
goto syntax;
fname[len] = '\0';
p = fname;
while (*p) {
if (*p == '/')
*p = '\\';
p++;
}
if (IsAbsolutePath(fname)) {
if (!NewSourceFile(fname) && importflag) {
return;
}
fd = DoOpen(fname);
strcpy(iname, fname);
}
else
for (fd = -1, i = NINCLUDE - 1; i >= 0; i--) {
ip = &includelist[i];
if (ip->file == NULL || ip->deleted || (angled && ip->always == 0))
continue;
if (strlen(fname) + strlen(ip->file) + 2 > sizeof(iname))
continue;
sprintf(iname, "%s%c%s", ip->file, PATH_SEPARATOR, fname);
if ((fd = DoOpen(iname)) >= 0) {
if (!NewSourceFile(iname) && importflag) {
DoClose(fd);
return;
}
break;
}
}
#ifndef LRC
if (Mflag) {
if (Mflag > 1)
PrintIncludeTree(iname);
else if (IncPath && strncmp(IncPath,iname,strlen(IncPath))) {
fprintf(TraceIncludesFile,"%s\n",iname);
}
}
#endif
if (fd >= 0) {
if (++incdepth > 10)
error(CPPFATAL, StrTab[138]); // <#include too deeply nested>
setsource((char *) newstring((uchar *) iname, strlen(iname), 0), fd, NULL);
genline();
}
else {
trp->tp = trp->bp + 2;
error(CPPERROR, StrTab[139], trp); // <Could not find include file %r>
}
return;
syntax:
error(CPPERROR, StrTab[140]); // <Syntax error in #include>
return;
}
/*
* Generate a line directive for cursource
*/
extern int DoLineDirective;
static int genline(void)
{
static Token ta = {UNCLASS, 0, 0, 0};
static Tokenrow tr = {&ta, &ta, &ta + 1, 1};
uchar *p;
ta.t = p = (uchar *) OutputPtr;
if (DoLineDirective) {
if (outputLine) {
strcpy((char *) p, "#line ");
p += sizeof("#line ") - 1;
}
else {
strcpy((char *) p, "# ");
p += sizeof("# ") - 1;
}
p = (uchar *) outnum((char *) p, cursource->line);
*p++ = ' ';
*p++ = '"';
if (cursource->filename[0] != PATH_SEPARATOR && wd[0]) {
strcpy((char *) p, wd);
p += strlen(wd);
*p++ = PATH_SEPARATOR;
}
strcpy((char *) p, cursource->filename);
p += strlen((char *) p);
*p++ = '"';
*p++ = '\n';
}
ta.len = (char *) p - OutputPtr;
OutputPtr = (char *) p;
tr.tp = tr.bp;
return (puttokens(&tr));
}
static void setobjname(unsigned char *f)
{
if (objname == NULL) {
objname = (char *) domalloc(255);
}
strcpy(objname, f);
}
/*
* lexical FSM encoding
* when in state state, and one of the characters
* in ch arrives, enter nextstate.
* States >= S_SELF are either final, or at least require special action.
* In 'fsm' there is a line for each state X charset X nextstate.
* List chars that overwrite previous entries later (e.g. C_ALPH
* can be overridden by '_' by a later entry; and C_XX is the
* the universal set, and should always be first.
* States above S_SELF are represented in the big table as negative values.
* S_SELF and S_SELFB encode the resulting token type in the upper bits.
* These actions differ in that S_SELF doesn't have a lookahead char,
* S_SELFB does.
*
* The encoding is blown out into a big table for time-efficiency.
* Entries have
* nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits.
*/
#define MAXSTATE 32
#define ACT(tok,act) ((tok<<7)+act)
#define QBSBIT 0100
#define GETACT(st) (st>>7)&0x1ff
/* character classes */
#define C_WS 1
#define C_ALPH 2
#define C_NUM 3
#define C_EOF 4
#define C_XX 5
enum state {
START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
};
struct fsm {
int state; /* if in this state */
uchar ch[4]; /* and see one of these characters */
int nextstate; /* enter this state if +ve */
};
static struct fsm fsm[] = {
/* start state */
START, {C_XX}, ACT(UNCLASS, S_SELF),
START, {' ', '\t', '\v'}, WS1,
START, {C_NUM}, NUM1,
START, {'.'}, NUM3,
START, {C_ALPH}, ID1,
START, {'L'}, ST1,
START, {'"'}, ST2,
START, {'\''}, CC1,
START, {'/'}, COM1,
START, {EOFC}, S_EOF,
START, {'\n'}, S_NL,
START, {'\r'}, S_NL,
START, {'-'}, MINUS1,
START, {'+'}, PLUS1,
START, {'<'}, LT1,
START, {'>'}, GT1,
START, {'='}, ASG1,
START, {'!'}, NOT1,
START, {'&'}, AND1,
START, {'|'}, OR1,
START, {'#'}, SHARP1,
START, {'%'}, PCT1,
START, {'['}, ACT(SBRA, S_SELF),
START, {']'}, ACT(SKET, S_SELF),
START, {'('}, ACT(LP, S_SELF),
START, {')'}, ACT(RP, S_SELF),
START, {'*'}, STAR1,
START, {','}, ACT(COMMA, S_SELF),
START, {'?'}, ACT(QUEST, S_SELF),
START, {':'}, ACT(COLON, S_SELF),
START, {';'}, ACT(SEMIC, S_SELF),
START, {'{'}, ACT(CBRA, S_SELF),
START, {'}'}, ACT(CKET, S_SELF),
START, {'~'}, ACT(TILDE, S_SELF),
START, {'^'}, CIRC1,
/* saw a digit */
NUM1, {C_XX}, ACT(NUMBER, S_SELFB),
NUM1, {C_NUM, C_ALPH, '.'}, NUM1,
NUM1, {'E', 'e'}, NUM2,
NUM1, {'_'}, ACT(NUMBER, S_SELFB),
/* saw possible start of exponent, digits-e */
NUM2, {C_XX}, ACT(NUMBER, S_SELFB),
NUM2, {'+', '-'}, NUM1,
NUM2, {C_NUM, C_ALPH}, NUM1,
NUM2, {'_'}, ACT(NUMBER, S_SELFB),
/* saw a '.', which could be a number or an operator */
NUM3, {C_XX}, ACT(DOT, S_SELFB),
NUM3, {'.'}, DOTS1,
NUM3, {C_NUM}, NUM1,
DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB),
DOTS1, {C_NUM}, NUM1,
DOTS1, {'.'}, ACT(ELLIPS, S_SELF),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -