Esempio n. 1
0
static Token
CondHandleDefault(bool doEval)
{
	bool t;
	bool (*evalProc)(struct Name *);
	bool invert = false;
	struct Name arg;
	size_t arglen;

	evalProc = NULL;
	if (strncmp(condExpr, "empty", 5) == 0) {
		/* Use Var_Parse to parse the spec in parens and return
		 * True if the resulting string is empty.  */
		size_t length;
		bool doFree;
		char *val;

		condExpr += 5;

		for (arglen = 0; condExpr[arglen] != '(' &&
		    condExpr[arglen] != '\0';)
			arglen++;

		if (condExpr[arglen] != '\0') {
			val = Var_Parse(&condExpr[arglen - 1], NULL,
			    doEval, &length, &doFree);
			if (val == var_Error)
				t = Err;
			else {
				/* A variable is empty when it just contains
				 * spaces... 4/15/92, christos */
				char *p;
				for (p = val; isspace(*p); p++)
					continue;
				t = *p == '\0' ? True : False;
			}
			if (doFree)
				free(val);
			/* Advance condExpr to beyond the closing ). Note that
			 * we subtract one from arglen + length b/c length
			 * is calculated from condExpr[arglen - 1].  */
			condExpr += arglen + length - 1;
			return t;
		} else
			condExpr -= 5;
	} else {
		struct operator *op;

		for (op = ops; op != NULL; op++)
			if (strncmp(condExpr, op->s, op->len) == 0) {
				condExpr += op->len;
				if (CondGetArg(&condExpr, &arg, op->s, true))
					evalProc = op->proc;
				else
					condExpr -= op->len;
				break;
			}
	}
	if (evalProc == NULL) {
		/* The symbol is itself the argument to the default
		 * function. We advance condExpr to the end of the symbol
		 * by hand (the next whitespace, closing paren or
		 * binary operator) and set to invert the evaluation
		 * function if condInvert is true.  */
		invert = condInvert;
		evalProc = condDefProc;
		/* XXX should we ignore problems now ? */
		CondGetArg(&condExpr, &arg, "", false);
	}

	/* Evaluate the argument using the set function. If invert
	 * is true, we invert the sense of the function.  */
	t = (!doEval || (*evalProc)(&arg) ?
	     (invert ? False : True) :
	     (invert ? True : False));
	VarName_Free(&arg);
	return t;
}
Esempio n. 2
0
static Token
compare_function(Boolean doEval)
{
    static const struct fn_def {
	const char  *fn_name;
	int         fn_name_len;
        int         (*fn_getarg)(char **, char **, const char *);
	Boolean     (*fn_proc)(int, const char *);
    } fn_defs[] = {
	{ "defined",   7, CondGetArg, CondDoDefined },
	{ "make",      4, CondGetArg, CondDoMake },
	{ "exists",    6, CondGetArg, CondDoExists },
	{ "empty",     5, get_mpt_arg, CondDoEmpty },
	{ "target",    6, CondGetArg, CondDoTarget },
	{ "commands",  8, CondGetArg, CondDoCommands },
	{ NULL,        0, NULL, NULL },
    };
    const struct fn_def *fn_def;
    Token	t;
    char	*arg = NULL;
    int	arglen;
    char *cp = condExpr;
    char *cp1;

    for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) {
	if (!istoken(cp, fn_def->fn_name, fn_def->fn_name_len))
	    continue;
	cp += fn_def->fn_name_len;
	/* There can only be whitespace before the '(' */
	while (isspace(*(unsigned char *)cp))
	    cp++;
	if (*cp != '(')
	    break;

	arglen = fn_def->fn_getarg(&cp, &arg, fn_def->fn_name);
	if (arglen <= 0) {
	    condExpr = cp;
	    return arglen < 0 ? TOK_ERROR : TOK_FALSE;
	}
	/* Evaluate the argument using the required function. */
	t = !doEval || fn_def->fn_proc(arglen, arg);
	if (arg)
	    free(arg);
	condExpr = cp;
	return t;
    }

    /* Push anything numeric through the compare expression */
    cp = condExpr;
    if (isdigit((unsigned char)cp[0]) || strchr("+-", cp[0]))
	return compare_expression(doEval);

    /*
     * Most likely we have a naked token to apply the default function to.
     * However ".if a == b" gets here when the "a" is unquoted and doesn't
     * start with a '$'. This surprises people.
     * If what follows the function argument is a '=' or '!' then the syntax
     * would be invalid if we did "defined(a)" - so instead treat as an
     * expression.
     */
    arglen = CondGetArg(&cp, &arg, NULL);
    for (cp1 = cp; isspace(*(unsigned char *)cp1); cp1++)
	continue;
    if (*cp1 == '=' || *cp1 == '!')
	return compare_expression(doEval);
    condExpr = cp;

    /*
     * Evaluate the argument using the default function.
     * This path always treats .if as .ifdef. To get here the character
     * after .if must have been taken literally, so the argument cannot
     * be empty - even if it contained a variable expansion.
     */
    t = !doEval || if_info->defProc(arglen, arg) != if_info->doNot;
    if (arg)
	free(arg);
    return t;
}