Пример #1
0
static void
ForExec(void *valuep, void *argp)
{
	char *value = (char *)valuep;
	For *arg = (For *)argp;
	BUFFER buf;

	/* Parse_FromString pushes stuff back, so we need to go over vars in
	   reverse.  */
	if (arg->var == NULL) {
		arg->var = Lst_Last(&arg->vars);
		arg->text = Buf_Retrieve(&arg->buf);
		arg->freeold = false;
	}

	if (DEBUG(FOR))
		(void)fprintf(stderr, "--- %s = %s\n",
		    Var_LoopVarName(Lst_Datum(arg->var)), value);
	Buf_Init(&buf, arg->guess);
	Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), value);
	if (arg->freeold)
		free(arg->text);
	arg->text = Buf_Retrieve(&buf);
	arg->freeold = true;
	arg->var = Lst_Rev(arg->var);
	if (arg->var == NULL)
		Parse_FromString(arg->text, arg->lineno);
}
Пример #2
0
Файл: var.c Проект: aharri/base
/* POSIX says that variable assignments passed on the command line should be
 * propagated to sub makes through MAKEFLAGS.
 */
void
Var_AddCmdline(const char *name)
{
	Var *v;
	unsigned int i;
	BUFFER buf;
	char *s;

	Buf_Init(&buf, MAKE_BSIZE);

	for (v = ohash_first(&global_variables, &i); v != NULL;
	    v = ohash_next(&global_variables, &i)) {
		/* This is not as expensive as it looks: this function is
		 * called before parsing Makefiles, so there are just a
		 * few non cmdling variables in there.
		 */
		if (!(v->flags & VAR_FROM_CMD)) {
			continue;
		}
		/* We assume variable names don't need quoting */
		Buf_AddString(&buf, v->name);
		Buf_AddChar(&buf, '=');
		for (s = var_get_value(v); *s != '\0'; s++) {
			if (strchr(quotable, *s))
				Buf_AddChar(&buf, '\\');
			Buf_AddChar(&buf, *s);
		}
		Buf_AddSpace(&buf);
	}
	Var_Append(name, Buf_Retrieve(&buf));
	Buf_Destroy(&buf);
}
Пример #3
0
char *
Parse_ReadUnparsedLine(Buffer linebuf, const char *type)
{
	int c;

	Buf_Reset(linebuf);
	c = read_char();
	if (c == EOF) {
		Parse_Error(PARSE_FATAL, "Unclosed %s", type);
		return NULL;
	}

	/* Handle '\' at beginning of line, since \\n needs special treatment */
	while (c == '\\') {
		c = read_char();
		if (c == '\n') {
			current->lineno++;
			do {
				c = read_char();
			} while (c == ' ' || c == '\t');
		} else {
			Buf_AddChar(linebuf, '\\');
			if (c == '\\') {
				Buf_AddChar(linebuf, '\\');
				c = read_char();
			}
			break;
		}
	}
	read_logical_line(linebuf, c);

	return Buf_Retrieve(linebuf);
}
Пример #4
0
Файл: var.c Проект: aharri/base
/* we would like to subst on intervals, but it's complicated, so we cheat
 * by storing the interval in a static buffer.
 */
char *
Var_Substi(const char *str, const char *estr, SymTable *ctxt, bool undefErr)
{
	/* delimited string: no need to copy */
	if (estr == NULL || *estr == '\0')
		return Var_Subst(str, ctxt, undefErr);

	Buf_Reset(&subst_buffer);
	Buf_Addi(&subst_buffer, str, estr);
	return Var_Subst(Buf_Retrieve(&subst_buffer), ctxt, undefErr);
}
Пример #5
0
/* Parse_ReadNormalLine removes beginning and trailing blanks (but keeps
 * the first tab), handles escaped newlines, and skips over uninteresting
 * lines.
 *
 * The line number is incremented, which implies that continuation
 * lines are numbered with the last line number (we could do better, at a
 * price).
 *
 * Trivial comments are also removed, but we can't do more, as
 * we don't know which lines are shell commands or not.  */
char *
Parse_ReadNormalLine(Buffer linebuf)
{
	int c;		/* the current character */

	c = skip_empty_lines_and_read_char(linebuf);

	if (c == EOF)
		return NULL;
	else {
		read_logical_line(linebuf, c);
		Buf_KillTrailingSpaces(linebuf);
		return Buf_Retrieve(linebuf);
	}
}
Пример #6
0
static Token
CondHandleString(bool doEval)
{
	char *lhs;
	const char *begin;
	BUFFER buf;

	/* find the extent of the string */
	begin = ++condExpr;
	while (*condExpr && *condExpr != '"') {
		condExpr++;
	}

	Buf_Init(&buf, 0);
	Buf_Addi(&buf, begin, condExpr);
	if (*condExpr == '"')
		condExpr++;
	lhs = Var_Subst(Buf_Retrieve(&buf), NULL, doEval);
	Buf_Destroy(&buf);
	return CondHandleComparison(lhs, true, doEval);
}
Пример #7
0
static Token
CondHandleVarSpec(bool doEval)
{
	char *lhs;
	size_t varSpecLen;
	bool doFree;

	/* Parse the variable spec and skip over it, saving its
	 * value in lhs.  */
	lhs = Var_Parse(condExpr, NULL, doEval,&varSpecLen,&doFree);
	if (lhs == var_Error)
		/* Even if !doEval, we still report syntax errors, which
		 * is what getting var_Error back with !doEval means.  */
		return Err;
	condExpr += varSpecLen;

	if (!isspace(*condExpr) &&
		strchr("!=><", *condExpr) == NULL) {
		BUFFER buf;

		Buf_Init(&buf, 0);

		Buf_AddString(&buf, lhs);

		if (doFree)
			free(lhs);

		for (;*condExpr && !isspace(*condExpr); condExpr++)
			Buf_AddChar(&buf, *condExpr);

		lhs = Var_Subst(Buf_Retrieve(&buf), NULL, doEval);
		Buf_Destroy(&buf);
		doFree = true;
	}

	return CondHandleComparison(lhs, doFree, doEval);
}
Пример #8
0
Файл: var.c Проект: aharri/base
char *
Var_Subst(const char *str,	/* the string in which to substitute */
    SymTable *ctxt,		/* the context wherein to find variables */
    bool undefErr)		/* true if undefineds are an error */
{
	BUFFER buf;		/* Buffer for forming things */
	static bool errorReported;

	Buf_Init(&buf, MAKE_BSIZE);
	errorReported = false;

	for (;;) {
		char *val;	/* Value to substitute for a variable */
		size_t length;	/* Length of the variable invocation */
		bool doFree;	/* Set true if val should be freed */
		const char *cp;

		/* copy uninteresting stuff */
		for (cp = str; *str != '\0' && *str != '$'; str++)
			;
		Buf_Addi(&buf, cp, str);
		if (*str == '\0')
			break;
		if (str[1] == '$') {
			/* A $ may be escaped with another $. */
			Buf_AddChar(&buf, '$');
			str += 2;
			continue;
		}
		val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
		/* When we come down here, val should either point to the
		 * value of this variable, suitably modified, or be NULL.
		 * Length should be the total length of the potential
		 * variable invocation (from $ to end character...) */
		if (val == var_Error || val == varNoError) {
			/* If errors are not an issue, skip over the variable
			 * and continue with the substitution. Otherwise, store
			 * the dollar sign and advance str so we continue with
			 * the string...  */
			if (errorIsOkay)
				str += length;
			else if (undefErr) {
				/* If variable is undefined, complain and
				 * skip the variable name. The complaint
				 * will stop us from doing anything when
				 * the file is parsed.  */
				if (!errorReported)
					Parse_Error(PARSE_FATAL,
					     "Undefined variable \"%.*s\"",
					     length, str);
				str += length;
				errorReported = true;
			} else {
				Buf_AddChar(&buf, *str);
				str++;
			}
		} else {
			/* We've now got a variable structure to store in.
			 * But first, advance the string pointer.  */
			str += length;

			/* Copy all the characters from the variable value
			 * straight into the new string.  */
			Buf_AddString(&buf, val);
			if (doFree)
				free(val);
		}
	}
	return  Buf_Retrieve(&buf);
}
Пример #9
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;
}
Пример #10
0
void
Make_DoAllVar(GNode *gn)
{
    GNode *child;
    LstNode ln;
    BUFFER allsrc, oodate;
    char *target;
    bool do_oodate;
    int oodate_count, allsrc_count = 0;

    oodate_count = 0;
    allsrc_count = 0;

    for (ln = Lst_First(&gn->children); ln != NULL; ln = Lst_Adv(ln)) {
        child = (GNode *)Lst_Datum(ln);
        if ((child->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) != 0)
            continue;
        if (OP_NOP(child->type) ||
                (target = Var(TARGET_INDEX, child)) == NULL) {
            /*
             * this node is only source; use the specific pathname
             * for it
             */
            target = child->path != NULL ? child->path :
                     child->name;
        }

        /*
         * It goes in the OODATE variable if the parent is younger than
         * the child or if the child has been modified more recently
         * than the start of the make.  This is to keep make from
         * getting confused if something else updates the parent after
         * the make starts (shouldn't happen, I know, but sometimes it
         * does). In such a case, if we've updated the kid, the parent
         * is likely to have a modification time later than that of the
         * kid and anything that relies on the OODATE variable will be
         * hosed.
         */
        do_oodate = false;
        if (gn->type & OP_JOIN) {
            if (child->built_status == MADE)
                do_oodate = true;
        } else if (is_strictly_before(gn->mtime, child->mtime) ||
                   (!is_strictly_before(child->mtime, now) &&
                    child->built_status == MADE))
            do_oodate = true;
        if (do_oodate) {
            oodate_count++;
            if (oodate_count == 1)
                Var(OODATE_INDEX, gn) = target;
            else {
                if (oodate_count == 2) {
                    Buf_Init(&oodate, 0);
                    Buf_AddString(&oodate,
                                  Var(OODATE_INDEX, gn));
                }
                Buf_AddSpace(&oodate);
                Buf_AddString(&oodate, target);
            }
        }
        allsrc_count++;
        if (allsrc_count == 1)
            Var(ALLSRC_INDEX, gn) = target;
        else {
            if (allsrc_count == 2) {
                Buf_Init(&allsrc, 0);
                Buf_AddString(&allsrc,
                              Var(ALLSRC_INDEX, gn));
            }
            Buf_AddSpace(&allsrc);
            Buf_AddString(&allsrc, target);
        }
    }

    if (allsrc_count > 1)
        Var(ALLSRC_INDEX, gn) = Buf_Retrieve(&allsrc);
    if (oodate_count > 1)
        Var(OODATE_INDEX, gn) = Buf_Retrieve(&oodate);

    if (gn->impliedsrc)
        Var(IMPSRC_INDEX, gn) = Var(TARGET_INDEX, gn->impliedsrc);

    if (gn->type & OP_JOIN)
        Var(TARGET_INDEX, gn) = Var(ALLSRC_INDEX, gn);
}
Пример #11
-1
void
For_Run(For *arg)
{
	arg->text = Buf_Retrieve(&arg->buf);
	arg->guess = Buf_Size(&arg->buf) + GUESS_EXPANSION;

	arg->var = NULL;
	Lst_ForEach(&arg->lst, ForExec, arg);
	Buf_Destroy(&arg->buf);
	Lst_Destroy(&arg->vars, (SimpleProc)Var_DeleteLoopVar);
	Lst_Destroy(&arg->lst, (SimpleProc)free);
	free(arg);
}