/* Delete a variable and all the space associated with it. */ static void delete_var(Var *v) { if ((v->flags & VAR_DUMMY) == 0) Buf_Destroy(&(v->val)); free(v); }
/* 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); }
void Var_DeleteLoopVar(struct LoopVar *l) { if ((l->me->flags & VAR_DUMMY) == 0) Buf_Destroy(&(l->me->val)); *(l->me) = l->old; free(l); }
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); }
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); }
/* coverity:[+alloc : arg-*2] */ static char * CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS) { Buffer buf; char *cp; char *str; int len; int qt; char *start; Buf_Init(&buf, 0); str = NULL; *freeIt = NULL; *quoted = qt = *condExpr == '"' ? 1 : 0; if (qt) condExpr++; for (start = condExpr; *condExpr && str == NULL; condExpr++) { switch (*condExpr) { case '\\': if (condExpr[1] != '\0') { condExpr++; Buf_AddByte(&buf, *condExpr); } break; case '"': if (qt) { condExpr++; /* we don't want the quotes */ goto got_str; } else Buf_AddByte(&buf, *condExpr); /* likely? */ break; case ')': case '!': case '=': case '>': case '<': case ' ': case '\t': if (!qt) goto got_str; else Buf_AddByte(&buf, *condExpr); break; case '$': /* if we are in quotes, then an undefined variable is ok */ str = Var_Parse(condExpr, VAR_CMD, ((!qt && doEval) ? VARF_UNDEFERR : 0) | VARF_WANTRES, &len, freeIt); if (str == var_Error) { if (*freeIt) { free(*freeIt); *freeIt = NULL; } /* * Even if !doEval, we still report syntax errors, which * is what getting var_Error back with !doEval means. */ str = NULL; goto cleanup; } condExpr += len; /* * If the '$' was first char (no quotes), and we are * followed by space, the operator or end of expression, * we are done. */ if ((condExpr == start + len) && (*condExpr == '\0' || isspace((unsigned char) *condExpr) || strchr("!=><)", *condExpr))) { goto cleanup; } /* * Nope, we better copy str to buf */ for (cp = str; *cp; cp++) { Buf_AddByte(&buf, *cp); } if (*freeIt) { free(*freeIt); *freeIt = NULL; } str = NULL; /* not finished yet */ condExpr--; /* don't skip over next char */ break; default: if (strictLHS && !qt && *start != '$' && !isdigit((unsigned char) *start)) { /* lhs must be quoted, a variable reference or number */ if (*freeIt) { free(*freeIt); *freeIt = NULL; } str = NULL; goto cleanup; } Buf_AddByte(&buf, *condExpr); break; } } got_str: str = Buf_GetAll(&buf, NULL); *freeIt = str; cleanup: Buf_Destroy(&buf, FALSE); return str; }
/*- *----------------------------------------------------------------------- * CondGetArg -- * Find the argument of a built-in function. * * Input: * parens TRUE if arg should be bounded by parens * * Results: * The length of the argument and the address of the argument. * * Side Effects: * The pointer is set to point to the closing parenthesis of the * function call. * *----------------------------------------------------------------------- */ static int CondGetArg(char **linePtr, char **argPtr, const char *func) { char *cp; int argLen; Buffer buf; int paren_depth; char ch; cp = *linePtr; if (func != NULL) /* Skip opening '(' - verfied by caller */ cp++; if (*cp == '\0') { /* * No arguments whatsoever. Because 'make' and 'defined' aren't really * "reserved words", we don't print a message. I think this is better * than hitting the user with a warning message every time s/he uses * the word 'make' or 'defined' at the beginning of a symbol... */ *argPtr = NULL; return (0); } while (*cp == ' ' || *cp == '\t') { cp++; } /* * Create a buffer for the argument and start it out at 16 characters * long. Why 16? Why not? */ Buf_Init(&buf, 16); paren_depth = 0; for (;;) { ch = *cp; if (ch == 0 || ch == ' ' || ch == '\t') break; if ((ch == '&' || ch == '|') && paren_depth == 0) break; if (*cp == '$') { /* * Parse the variable spec and install it as part of the argument * if it's valid. We tell Var_Parse to complain on an undefined * variable, so we don't do it too. Nor do we return an error, * though perhaps we should... */ char *cp2; int len; void *freeIt; cp2 = Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES, &len, &freeIt); Buf_AddBytes(&buf, strlen(cp2), cp2); free(freeIt); cp += len; continue; } if (ch == '(') paren_depth++; else if (ch == ')' && --paren_depth < 0) break; Buf_AddByte(&buf, *cp); cp++; } *argPtr = Buf_GetAll(&buf, &argLen); Buf_Destroy(&buf, FALSE); while (*cp == ' ' || *cp == '\t') { cp++; } if (func != NULL && *cp++ != ')') { Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", func); return (0); } *linePtr = cp; return (argLen); }
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); }