예제 #1
0
파일: error.c 프로젝트: StarchLinux/bmake
/* VARARGS */
void
Parse_Error(int type, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	ParseVErrorInternal(Parse_Getfilename(), Parse_Getlineno(), type,
	    fmt, ap);
	va_end(ap);
}
예제 #2
0
/* Evaluate conditional in line.
 * returns COND_SKIP, COND_PARSE, COND_INVALID, COND_ISFOR, COND_ISINCLUDE,
 * COND_ISUNDEF.
 * A conditional line looks like this:
 *	<cond-type> <expr>
 *	where <cond-type> is any of if, ifmake, ifnmake, ifdef,
 *	ifndef, elif, elifmake, elifnmake, elifdef, elifndef
 *	and <expr> consists of &&, ||, !, make(target), defined(variable)
 *	and parenthetical groupings thereof.
 */
int
Cond_Eval(const char *line)
{
	/* find end of keyword */
	const char *end;
	uint32_t k;
	size_t len;
	struct If *ifp;
	bool value = false;
	int level;	/* Level at which to report errors. */

	level = PARSE_FATAL;

	for (end = line; islower(*end); end++)
		;
	/* quick path: recognize special targets early on */
	if (*end == '.' || *end == ':')
		return COND_INVALID;
	len = end - line;
	k = ohash_interval(line, &end);
	switch(k % MAGICSLOTS2) {
	case K_COND_IF % MAGICSLOTS2:
		if (k == K_COND_IF && len == strlen(COND_IF) &&
		    strncmp(line, COND_IF, len) == 0) {
			ifp = ifs + COND_IF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_IFDEF % MAGICSLOTS2:
		if (k == K_COND_IFDEF && len == strlen(COND_IFDEF) &&
		    strncmp(line, COND_IFDEF, len) == 0) {
			ifp = ifs + COND_IFDEF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_IFNDEF % MAGICSLOTS2:
		if (k == K_COND_IFNDEF && len == strlen(COND_IFNDEF) &&
		    strncmp(line, COND_IFNDEF, len) == 0) {
			ifp = ifs + COND_IFNDEF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_IFMAKE % MAGICSLOTS2:
		if (k == K_COND_IFMAKE && len == strlen(COND_IFMAKE) &&
		    strncmp(line, COND_IFMAKE, len) == 0) {
			ifp = ifs + COND_IFMAKE_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_IFNMAKE % MAGICSLOTS2:
		if (k == K_COND_IFNMAKE && len == strlen(COND_IFNMAKE) &&
		    strncmp(line, COND_IFNMAKE, len) == 0) {
			ifp = ifs + COND_IFNMAKE_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELIF % MAGICSLOTS2:
		if (k == K_COND_ELIF && len == strlen(COND_ELIF) &&
		    strncmp(line, COND_ELIF, len) == 0) {
			ifp = ifs + COND_ELIF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELIFDEF % MAGICSLOTS2:
		if (k == K_COND_ELIFDEF && len == strlen(COND_ELIFDEF) &&
		    strncmp(line, COND_ELIFDEF, len) == 0) {
			ifp = ifs + COND_ELIFDEF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELIFNDEF % MAGICSLOTS2:
		if (k == K_COND_ELIFNDEF && len == strlen(COND_ELIFNDEF) &&
		    strncmp(line, COND_ELIFNDEF, len) == 0) {
			ifp = ifs + COND_ELIFNDEF_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELIFMAKE % MAGICSLOTS2:
		if (k == K_COND_ELIFMAKE && len == strlen(COND_ELIFMAKE) &&
		    strncmp(line, COND_ELIFMAKE, len) == 0) {
			ifp = ifs + COND_ELIFMAKE_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELIFNMAKE % MAGICSLOTS2:
		if (k == K_COND_ELIFNMAKE && len == strlen(COND_ELIFNMAKE) &&
		    strncmp(line, COND_ELIFNMAKE, len) == 0) {
			ifp = ifs + COND_ELIFNMAKE_INDEX;
		} else
			return COND_INVALID;
		break;
	case K_COND_ELSE % MAGICSLOTS2:
		/* valid conditional whose value is the inverse
		 * of the previous if we parsed.  */
		if (k == K_COND_ELSE && len == strlen(COND_ELSE) &&
		    strncmp(line, COND_ELSE, len) == 0) {
			if (condTop == MAXIF) {
				Parse_Error(level, "if-less else");
				return COND_INVALID;
			} else if (skipIfLevel == 0) {
				value = !condStack[condTop].value;
				ifp = ifs + COND_ELSE_INDEX;
			} else
				return COND_SKIP;
		} else
			return COND_INVALID;
		break;
	case K_COND_ENDIF % MAGICSLOTS2:
		if (k == K_COND_ENDIF && len == strlen(COND_ENDIF) &&
		    strncmp(line, COND_ENDIF, len) == 0) {
			/* End of a conditional section. If skipIfLevel is
			 * non-zero, that conditional was skipped, so lines
			 * following it should also be skipped. Hence, we
			 * return COND_SKIP. Otherwise, the conditional was
			 * read so succeeding lines should be parsed (think
			 * about it...) so we return COND_PARSE, unless this
			 * endif isn't paired with a decent if.  */
			if (skipIfLevel != 0) {
				skipIfLevel--;
				return COND_SKIP;
			} else {
				if (condTop == MAXIF) {
					Parse_Error(level, "if-less endif");
					return COND_INVALID;
				} else {
					skipLine = false;
					condTop++;
					return COND_PARSE;
				}
			}
		} else
			return COND_INVALID;
		break;

	/* Recognize other keywords there, to simplify parser's task */
	case K_COND_FOR % MAGICSLOTS2:
		if (k == K_COND_FOR && len == strlen(COND_FOR) &&
		    strncmp(line, COND_FOR, len) == 0)
			return COND_ISFOR;
		else
			return COND_INVALID;
	case K_COND_UNDEF % MAGICSLOTS2:
		if (k == K_COND_UNDEF && len == strlen(COND_UNDEF) &&
		    strncmp(line, COND_UNDEF, len) == 0)
			return COND_ISUNDEF;
		else
			return COND_INVALID;
	case K_COND_POISON % MAGICSLOTS2:
		if (k == K_COND_POISON && len == strlen(COND_POISON) &&
		    strncmp(line, COND_POISON, len) == 0)
			return COND_ISPOISON;
		else
			return COND_INVALID;
	case K_COND_INCLUDE % MAGICSLOTS2:
		if (k == K_COND_INCLUDE && len == strlen(COND_INCLUDE) &&
		    strncmp(line, COND_INCLUDE, len) == 0)
			return COND_ISINCLUDE;
		else
			return COND_INVALID;
	default:
		/* Not a valid conditional type. No error...  */
		return COND_INVALID;
	}

	if (ifp->isElse) {
		if (condTop == MAXIF) {
			Parse_Error(level, "if-less elif");
			return COND_INVALID;
		} else if (skipIfLevel != 0 || condStack[condTop].value) {
			/*
			 * Skip if we're meant to or is an else-type
			 * conditional and previous corresponding one was
			 * evaluated to true.
			 */
			skipLine = true;
			return COND_SKIP;
		}
	} else if (skipLine) {
		/* Don't even try to evaluate a conditional that's not an else
		 * if we're skipping things...  */
		skipIfLevel++;
		return COND_SKIP;
	} else
		condTop--;

	if (condTop < 0) {
		/* This is the one case where we can definitely proclaim a fatal
		 * error. If we don't, we're hosed.  */
		Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.", 
		    MAXIF);
		condTop = 0;
		return COND_INVALID;
	}

	if (ifp->defProc) {
		/* Initialize file-global variables for parsing.  */
		condDefProc = ifp->defProc;
		condInvert = ifp->doNot;

		line += len;

		while (*line == ' ' || *line == '\t')
			line++;

		condExpr = line;
		condPushBack = None;

		switch (CondE(true)) {
		case True:
			if (CondToken(true) == EndOfFile) {
				value = true;
				break;
			}
			goto err;
			/* FALLTHROUGH */
		case False:
			if (CondToken(true) == EndOfFile) {
				value = false;
				break;
			}
			/* FALLTHROUGH */
		case Err:
err:
			Parse_Error(level, "Malformed conditional (%s)", line);
			return COND_INVALID;
		default:
			break;
		}
	}

	condStack[condTop].value = value;
	condStack[condTop].lineno = Parse_Getlineno();
	condStack[condTop].filename = Parse_Getfilename();
	skipLine = !value;
	return value ? COND_PARSE : COND_SKIP;
}