📄 ncpp.c
字号:
return;
}
}
switch (np->val) {
case KDEFINE:
dodefine(trp);
break;
case KUNDEF:
tp += 1;
if (tp->type != NAME || trp->lp - trp->bp != 4) {
error(CPPERROR, StrTab[106]); // <Syntax error in #undef>
break;
}
if ((np = cpplookup(tp)) != NULL)
np->flag &= ~ISDEFINED;
break;
case KPRAGMA:
return;
case KIFDEF:
case KIFNDEF:
case KIF:
if (++ifdepth >= NIF)
error(CPPFATAL, StrTab[107]); // <#if too deeply nested>
++cursource->ifdepth;
ifsatisfied[ifdepth] = 0;
if (eval(trp, np->val))
ifsatisfied[ifdepth] = 1;
else
skipping = ifdepth;
break;
case KELIF:
if (ifdepth == 0) {
error(CPPERROR, StrTab[108]); // <#elif with no #if>
return;
}
if (ifsatisfied[ifdepth] == 2)
error(CPPERROR, StrTab[109]); // <#elif after #else>
if (eval(trp, np->val)) {
if (ifsatisfied[ifdepth])
skipping = ifdepth;
else {
skipping = 0;
ifsatisfied[ifdepth] = 1;
}
}
else
skipping = ifdepth;
break;
case KELSE:
if (ifdepth == 0 || cursource->ifdepth == 0) {
error(CPPERROR, StrTab[110]); // <#else with no #if>
return;
}
if (ifsatisfied[ifdepth] == 2)
error(CPPERROR, StrTab[111]); // <#else after #else>
if (trp->lp - trp->bp != 3)
error(CPPERROR, StrTab[112]); // <Syntax error in #else>
skipping = ifsatisfied[ifdepth] ? ifdepth : 0;
ifsatisfied[ifdepth] = 2;
break;
case KENDIF:
if (ifdepth == 0 || cursource->ifdepth == 0) {
error(CPPERROR, StrTab[113]); // <#endif with no #if>
return;
}
--ifdepth;
--cursource->ifdepth;
if (trp->lp - trp->bp != 3)
error(CPPWARNING, StrTab[114]); // <Syntax error in #endif>
break;
case KWARNING:
trp->tp = tp + 1;
error(CPPWARNING, StrTab[432], trp); // <#warning directive: %r>
break;
case KERROR:
trp->tp = tp + 1;
error(CPPWARNING, StrTab[115], trp); // <#error directive: %r>
break;
case KLINE:
trp->tp = tp + 1;
expandrow(trp, (unsigned char *) "<line>");
tp = trp->bp + 2;
kline:
if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp
|| (tp + 3 == trp->lp && ((tp + 1)->type != STRING) || *(tp + 1)->t == 'L')) {
error(CPPERROR, StrTab[116]); // <Syntax error in #line>
return;
}
cursource->line = atol((char *) tp->t) - 1;
if (cursource->line < 0 || cursource->line >= 32768)
error(CPPWARNING, StrTab[117]); // <#line specifies number out of range>
tp = tp + 1;
if (tp + 1 < trp->lp)
cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0);
return;
case KDEFINED:
error(CPPERROR, StrTab[118]); // <Bad syntax for control line>
break;
case KINCLUDE:
doinclude(trp,0);
trp->lp = trp->bp;
return;
case KIMPORT:
doinclude(trp,1);
trp->lp = trp->bp;
return;
case KEVAL:
eval(trp, np->val);
break;
default:
error(CPPERROR, StrTab[119], tp); // <Preprocessor control `%t' not yet implemented>
break;
}
setempty(trp);
return;
}
static void *_stdcall domalloc(int size)
{
void *p;
#ifdef DEBUGCPP
if (!HeapValidate(GetProcessHeap(),0,NULL)) {
return NULL;
}
#endif
p = malloc(size);
if (p == NULL)
error(CPPFATAL, StrTab[120]); // <Out of memory from malloc>
memset(p, 0, size);
return p;
}
static void _stdcall dofree(void *p)
{
#ifdef DEBUGCPP
if (!HeapValidate(GetProcessHeap(),0,NULL)) {
return ;
}
#endif
free(p);
}
static void error(enum errtype type, char *string,...)
{
va_list ap;
char *cp, *ep;
Token *tp;
Tokenrow *trp;
Source *s;
int i;
#ifdef LRC
fprintf(stderr, "lrc: ");
#else
if (TraceDependencies && type == CPPWARNING)
return;
fprintf(stderr, "cpp: ");
#endif
for (s = cursource; s; s = s->next)
if (*s->filename)
fprintf(stderr, "%s:%d ", s->filename, s->line);
va_start(ap, string);
for (ep = string; *ep; ep++) {
if (*ep == '%') {
switch (*++ep) {
case 's':
cp = va_arg(ap, char *);
fprintf(stderr, "%s", cp);
break;
case 'd':
i = va_arg(ap, int);
fprintf(stderr, "%d", i);
break;
case 't':
tp = va_arg(ap, Token *);
fprintf(stderr, "%.*s", tp->len, tp->t);
break;
case 'r':
trp = va_arg(ap, Tokenrow *);
for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++) {
if (tp > trp->tp && tp->wslen)
fputc(' ', stderr);
fprintf(stderr, "%.*s", tp->len, tp->t);
}
break;
default:
fputc(*ep, stderr);
break;
}
}
else
fputc(*ep, stderr);
}
va_end(ap);
fputc('\n', stderr);
if (type == CPPFATAL)
exit(1);
if (type != CPPWARNING)
nerrs = 1;
fflush(stderr);
}
#define NSTAK 32
#define SGN 0
#define UNS 1
#define UND 2
#define UNSMARK 0x1000
struct value {
long val;
int type;
};
/* conversion types */
#define RELAT 1
#define ARITH 2
#define LOGIC 3
#define SPCL 4
#define SHIFT 5
#define UNARY 6
/* operator priority, arity, and conversion type, indexed by tokentype */
static struct pri {
char pri;
char arity;
char ctype;
} priority[] = {
{0, 0, 0 }, /* END */
{0, 0, 0 }, /* UNCLASS */
{0, 0, 0 }, /* NAME */
{0, 0, 0 }, /* NUMBER */
{0, 0, 0 }, /* STRING */
{0, 0, 0 }, /* CCON */
{0, 0, 0 }, /* NL */
{0, 0, 0 }, /* WS */
{0, 0, 0 }, /* DSHARP */
{11, 2, RELAT }, /* EQ */
{11, 2, RELAT }, /* NEQ */
{12, 2, RELAT }, /* LEQ */
{12, 2, RELAT }, /* GEQ */
{13, 2, SHIFT }, /* LSH */
{13, 2, SHIFT }, /* RSH */
{7, 2, LOGIC }, /* LAND */
{6, 2, LOGIC }, /* LOR */
{0, 0, 0 }, /* PPLUS */
{0, 0, 0 }, /* MMINUS */
{0, 0, 0 }, /* ARROW */
{0, 0, 0 }, /* SBRA */
{0, 0, 0 }, /* SKET */
{3, 0, 0 }, /* LP */
{3, 0, 0 }, /* RP */
{0, 0, 0 }, /* DOT */
{10, 2, ARITH }, /* AND */
{15, 2, ARITH }, /* STAR */
{14, 2, ARITH }, /* PLUS */
{14, 2, ARITH }, /* MINUS */
{16, 1, UNARY }, /* TILDE */
{16, 1, UNARY }, /* NOT */
{15, 2, ARITH }, /* SLASH */
{15, 2, ARITH }, /* PCT */
{12, 2, RELAT }, /* LT */
{12, 2, RELAT }, /* GT */
{9, 2, ARITH }, /* CIRC */
{8, 2, ARITH }, /* OR */
{5, 2, SPCL }, /* QUEST */
{5, 2, SPCL }, /* COLON */
{0, 0, 0 }, /* ASGN */
{4, 2, 0 }, /* COMMA */
{0, 0, 0 }, /* SHARP */
{0, 0, 0 }, /* SEMIC */
{0, 0, 0 }, /* CBRA */
{0, 0, 0 }, /* CKET */
{0, 0, 0 }, /* ASPLUS */
{0, 0, 0 }, /* ASMINUS */
{0, 0, 0 }, /* ASSTAR */
{0, 0, 0 }, /* ASSLASH */
{0, 0, 0 }, /* ASPCT */
{0, 0, 0 }, /* ASCIRC */
{0, 0, 0 }, /* ASLSH */
{0, 0, 0 }, /* ASRSH */
{0, 0, 0 }, /* ASOR */
{0, 0, 0 }, /* ASAND */
{0, 0, 0 }, /* ELLIPS */
{0, 0, 0 }, /* DSHARP1 */
{0, 0, 0 }, /* NAME1 */
{16, 1, UNARY }, /* DEFINED */
{16, 0, UNARY }, /* UMINUS */
};
static int evalop(struct pri);
static struct value tokval(Token *);
static struct value vals[NSTAK], *vp;
static enum toktype ops[NSTAK], *op;
/*
* Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword.
*/
static long eval(Tokenrow * trp, int kw)
{
Token *tp;
Nlist *np;
int ntok, rand;
trp->tp++;
if (kw == KIFDEF || kw == KIFNDEF) {
if (trp->lp - trp->bp != 4 || trp->tp->type != NAME) {
error(CPPERROR, StrTab[121]); // <Syntax error in #ifdef/#ifndef>
return 0;
}
np = cpplookup(trp->tp);
return (kw == KIFDEF) == (np && np->flag & ISDEFINED);
}
ntok = trp->tp - trp->bp;
kwdefined->val = KDEFINED; /* activate special meaning of defined */
expandrow(trp, (unsigned char *) "<if>");
kwdefined->val = NAME;
vp = vals;
op = ops;
*op++ = END;
for (rand = 0, tp = trp->bp + ntok; tp < trp->lp; tp++) {
switch (tp->type) {
case WS:
case NL:
continue;
/* nilary */
case NAME:
case NAME1:
case NUMBER:
case CCON:
case STRING:
if (rand)
goto syntax;
*vp++ = tokval(tp);
rand = 1;
continue;
/* unary */
case DEFINED:
case TILDE:
case NOT:
if (rand)
goto syntax;
*op++ = tp->type;
continue;
/* unary-binary */
case PLUS:
case MINUS:
case STAR:
case AND:
if (rand == 0) {
if (tp->type == MINUS)
*op++ = UMINUS;
if (tp->type == STAR || tp->type == AND) {
error(CPPERROR, StrTab[122]); // <Illegal operator * or & in #if/#elsif>
return 0;
}
continue;
}
/* flow through */
/* plain binary */
case EQ:
case NEQ:
case LEQ:
case GEQ:
case LSH:
case RSH:
case LAND:
case LOR:
case SLASH:
case PCT:
case LT:
case GT:
case CIRC:
case OR:
case QUEST:
case COLON:
case COMMA:
if (rand == 0)
goto syntax;
if (evalop(priority[tp->type]) != 0)
return 0;
*op++ = tp->type;
rand = 0;
continue;
case LP:
if (rand)
goto syntax;
*op++ = LP;
continue;
case RP:
if (!rand)
goto syntax;
if (evalop(priority[RP]) != 0)
return 0;
if (op <= ops || op[-1] != LP) {
goto syntax;
}
op--;
continue;
default:
error(CPPERROR, StrTab[123], tp); // <Bad operator (%t) in #if/#elsif>
return 0;
}
}
if (rand == 0)
goto syntax;
if (evalop(priority[END]) != 0)
return 0;
if (op != &ops[1] || vp != &vals[1]) {
error(CPPERROR, StrTab[124]); // <Botch in #if/#elsif>
return 0;
}
if (vals[0].type == UND)
error(CPPERROR, StrTab[125]); // <Undefined expression value>
return vals[0].val;
syntax:
error(CPPERROR, StrTab[126]); // <Syntax error in #if/#elsif>
return 0;
}
static int evalop(struct pri pri)
{
struct value v1, v2;
long rv1, rv2;
int rtype, oper;
rv2 = 0;
rtype = 0;
while (pri.pri < priority[op[-1]].pri) {
oper = *--op;
if (priority[oper].arity == 2) {
v2 = *--vp;
rv2 = v2.val;
}
v1 = *--vp;
rv1 = v1.val;
/*lint -e574 -e644 */
switch (priority[oper].ctype) {
case 0:
default:
error(CPPWARNING, StrTab[127]); // <Syntax error in #if/#endif>
return 1;
case ARITH:
case RELAT:
if (v1.type == UNS || v2.type == UNS)
rtype = UNS;
else
rtype = SGN;
if (v1.type == UND || v2.type == UND)
rtype = UND;
if (priority[oper].ctype == RELAT && rtype == UNS) {
oper |= UNSMARK;
rtype = SGN;
}
break;
case SHIFT:
if (v1.type == UND || v2.type == UND)
rtype = UND;
else
rtype = v1.type;
if (rtype == UNS)
oper |= UNSMARK;
break;
case UNARY:
rtype = v1.type;
break;
case LOGIC:
case SPCL:
break;
}
switch (oper) {
case EQ:
case EQ | UNSMARK:
rv1 = rv1 == rv2;
break;
case NEQ:
case NEQ | UNSMARK:
rv1 = rv1 != rv2;
break;
case LEQ:
rv1 = rv1 <= rv2;
break;
case GEQ:
rv1 = rv1 >= rv2;
break;
case LT:
rv1 = rv1 < rv2;
break;
case GT:
rv1 = rv1 > rv2;
break;
case LEQ | UNSMARK:
rv1 = (rv1 <= rv2);
break;
case GEQ | UNSMARK:
rv1 = rv1 >= rv2;
break;
case LT | UNSMARK:
rv1 = rv1 < rv2;
break;
case GT | UNSMARK:
rv1 = rv1 > rv2;
break;
case LSH:
rv1 <<= rv2;
break;
case LSH | UNSMARK:
rv1 = (unsigned long) rv1 << rv2;
break;
case RSH:
rv1 >>= rv2;
break;
case RSH | UNSMARK:
rv1 = (unsigned long) rv1 >> rv2;
break;
case LAND:
rtype = UND;
if (v1.type == UND)
break;
if (rv1 != 0) {
if (v2.type == UND)
break;
rv1 = rv2 != 0;
}
else
rv1 = 0;
rtype = SGN;
break;
case LOR:
rtype = UND;
if (v1.type == UND)
break;
if (rv1 == 0) {
if (v2.type == UND)
break;
rv1 = rv2 != 0;
}
else
rv1 = 1;
rtype = SGN;
break;
case AND:
rv1 &= rv2;
break;
case STAR:
rv1 *= rv2;
break;
case PLUS:
rv1 += rv2;
break;
case MINUS:
rv1 -= rv2;
break;
case UMINUS:
if (v1.type == UND)
rtype = UND;
rv1 = -rv1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -