⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncpp.c

📁 window下的c编译器。
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -