コード例 #1
0
static Token
CondHandleComparison(char *lhs, bool doFree, bool doEval)
{
	Token t;
	const char *rhs;
	const char *op;

	t = Err;
	/* Skip whitespace to get to the operator.	*/
	while (isspace(*condExpr))
		condExpr++;

	/* Make sure the operator is a valid one. If it isn't a
	 * known relational operator, pretend we got a
	 * != 0 comparison.  */
	op = condExpr;
	switch (*condExpr) {
	case '!':
	case '=':
	case '<':
	case '>':
		if (condExpr[1] == '=')
			condExpr += 2;
		else
			condExpr += 1;
		break;
	default:
		op = "!=";
		rhs = "0";

		goto do_compare;
	}
	while (isspace(*condExpr))
		condExpr++;
	if (*condExpr == '\0') {
		Parse_Error(PARSE_WARNING,
		    "Missing right-hand-side of operator");
		goto error;
	}
	rhs = condExpr;
do_compare:
	if (*rhs == '"') {
		/* Doing a string comparison. Only allow == and != for
		 * operators.  */
		char *string;
		const char *cp;
		int qt;
		BUFFER buf;

do_string_compare:
		if ((*op != '!' && *op != '=') || op[1] != '=') {
			Parse_Error(PARSE_WARNING,
			    "String comparison operator should be either == or !=");
			goto error;
		}

		Buf_Init(&buf, 0);
		qt = *rhs == '"' ? 1 : 0;

		for (cp = &rhs[qt]; ((qt && *cp != '"') ||
		    (!qt && strchr(" \t)", *cp) == NULL)) && *cp != '\0';) {
			if (*cp == '$') {
				size_t len;

				if (Var_ParseBuffer(&buf, cp, NULL, doEval,
				    &len)) {
					cp += len;
					continue;
				}
			} else if (*cp == '\\' && cp[1] != '\0')
				/* Backslash escapes things -- skip over next
				 * character, if it exists.  */
				cp++;
			Buf_AddChar(&buf, *cp++);
		}

		string = Buf_Retrieve(&buf);

		if (DEBUG(COND))
			printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
			    lhs, string, op);
		/* Null-terminate rhs and perform the comparison.
		 * t is set to the result.  */
		if (*op == '=')
			t = strcmp(lhs, string) ? False : True;
		else
			t = strcmp(lhs, string) ? True : False;
		free(string);
		if (rhs == condExpr) {
			if (!qt && *cp == ')')
				condExpr = cp;
			else if (*cp == '\0')
				condExpr = cp;
			else
				condExpr = cp + 1;
		}
	} else {
		/* rhs is either a float or an integer. Convert both the
		 * lhs and the rhs to a double and compare the two.  */
		double left, right;
		char *string;

		if (!CondCvtArg(lhs, &left))
			goto do_string_compare;
		if (*rhs == '$') {
			size_t len;
			bool freeIt;

			string = Var_Parse(rhs, NULL, doEval,&len,&freeIt);
			if (string == var_Error)
				right = 0.0;
			else {
				if (!CondCvtArg(string, &right)) {
					if (freeIt)
						free(string);
					goto do_string_compare;
				}
				if (freeIt)
					free(string);
				if (rhs == condExpr)
					condExpr += len;
			}
		} else {
			if (!CondCvtArg(rhs, &right))
				goto do_string_compare;
			if (rhs == condExpr) {
				/* Skip over the right-hand side.  */
				while (!isspace(*condExpr) && *condExpr != '\0')
					condExpr++;
			}
		}

		if (DEBUG(COND))
			printf("left = %f, right = %f, op = %.2s\n", left,
			    right, op);
		switch (op[0]) {
		case '!':
			if (op[1] != '=') {
				Parse_Error(PARSE_WARNING, "Unknown operator");
				goto error;
			}
			t = left != right ? True : False;
			break;
		case '=':
			if (op[1] != '=') {
				Parse_Error(PARSE_WARNING, "Unknown operator");
				goto error;
			}
			t = left == right ? True : False;
			break;
		case '<':
			if (op[1] == '=')
				t = left <= right ? True : False;
			else
				t = left < right ? True : False;
			break;
		case '>':
			if (op[1] == '=')
				t = left >= right ? True : False;
			else
				t = left > right ? True : False;
			break;
		}
	}
error:
	if (doFree)
		free(lhs);
	return t;
}
コード例 #2
0
ファイル: cond.c プロジェクト: 0xffffffRabbit/NextBSD-1
/*-
 *-----------------------------------------------------------------------
 * CondToken --
 *	Return the next token from the input.
 *
 * Results:
 *	A Token for the next lexical token in the stream.
 *
 * Side Effects:
 *	condPushback will be set back to TOK_NONE if it is used.
 *
 *-----------------------------------------------------------------------
 */
static Token
compare_expression(Boolean doEval)
{
    Token	t;
    char	*lhs;
    char	*rhs;
    char	*op;
    void	*lhsFree;
    void	*rhsFree;
    Boolean lhsQuoted;
    Boolean rhsQuoted;
    double  	left, right;

    t = TOK_ERROR;
    rhs = NULL;
    lhsFree = rhsFree = FALSE;
    lhsQuoted = rhsQuoted = FALSE;
    
    /*
     * Parse the variable spec and skip over it, saving its
     * value in lhs.
     */
    lhs = CondGetString(doEval, &lhsQuoted, &lhsFree, lhsStrict);
    if (!lhs)
	goto done;

    /*
     * Skip whitespace to get to the operator
     */
    while (isspace((unsigned char) *condExpr))
	condExpr++;

    /*
     * Make sure the operator is a valid one. If it isn't a
     * known relational operator, pretend we got a
     * != 0 comparison.
     */
    op = condExpr;
    switch (*condExpr) {
	case '!':
	case '=':
	case '<':
	case '>':
	    if (condExpr[1] == '=') {
		condExpr += 2;
	    } else {
		condExpr += 1;
	    }
	    break;
	default:
	    if (!doEval) {
		t = TOK_FALSE;
		goto done;
	    }
	    /* For .ifxxx "..." check for non-empty string. */
	    if (lhsQuoted) {
		t = lhs[0] != 0;
		goto done;
	    }
	    /* For .ifxxx <number> compare against zero */
	    if (CondCvtArg(lhs, &left)) { 
		t = left != 0.0;
		goto done;
	    }
	    /* For .if ${...} check for non-empty string (defProc is ifdef). */
	    if (if_info->form[0] == 0) {
		t = lhs[0] != 0;
		goto done;
	    }
	    /* Otherwise action default test ... */
	    t = if_info->defProc(strlen(lhs), lhs) != if_info->doNot;
	    goto done;
    }

    while (isspace((unsigned char)*condExpr))
	condExpr++;

    if (*condExpr == '\0') {
	Parse_Error(PARSE_WARNING,
		    "Missing right-hand-side of operator");
	goto done;
    }

    rhs = CondGetString(doEval, &rhsQuoted, &rhsFree, FALSE);
    if (!rhs)
	goto done;

    if (rhsQuoted || lhsQuoted) {
do_string_compare:
	if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
	    Parse_Error(PARSE_WARNING,
    "String comparison operator should be either == or !=");
	    goto done;
	}

	if (DEBUG(COND)) {
	    fprintf(debug_file, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
		   lhs, rhs, op);
	}
	/*
	 * Null-terminate rhs and perform the comparison.
	 * t is set to the result.
	 */
	if (*op == '=') {
	    t = strcmp(lhs, rhs) == 0;
	} else {
	    t = strcmp(lhs, rhs) != 0;
	}
    } else {
	/*
	 * rhs is either a float or an integer. Convert both the
	 * lhs and the rhs to a double and compare the two.
	 */
    
	if (!CondCvtArg(lhs, &left) || !CondCvtArg(rhs, &right))
	    goto do_string_compare;

	if (DEBUG(COND)) {
	    fprintf(debug_file, "left = %f, right = %f, op = %.2s\n", left,
		   right, op);
	}
	switch(op[0]) {
	case '!':
	    if (op[1] != '=') {
		Parse_Error(PARSE_WARNING,
			    "Unknown operator");
		goto done;
	    }
	    t = (left != right);
	    break;
	case '=':
	    if (op[1] != '=') {
		Parse_Error(PARSE_WARNING,
			    "Unknown operator");
		goto done;
	    }
	    t = (left == right);
	    break;
	case '<':
	    if (op[1] == '=') {
		t = (left <= right);
	    } else {
		t = (left < right);
	    }
	    break;
	case '>':
	    if (op[1] == '=') {
		t = (left >= right);
	    } else {
		t = (left > right);
	    }
	    break;
	}
    }

done:
    free(lhsFree);
    free(rhsFree);
    return t;
}