static void random_setup() { randomize_queue = Var_Definedi("RANDOM_ORDER", NULL); if (Var_Definedi("RANDOM_DELAY", NULL)) random_delay = strtonum(Var_Value("RANDOM_DELAY"), 0, 1000, NULL) * 1000000; if (randomize_queue || random_delay) { unsigned int random_seed; char *t; t = Var_Value("RANDOM_SEED"); if (t != NULL) random_seed = strtonum(t, 0, UINT_MAX, NULL); else random_seed = time(NULL); fprintf(stderr, "RANDOM_SEED=%u\n", random_seed); srandom(random_seed); } }
static bool parse_variable_assignment(const char *line, int ctxt) { const char *arg; char *res1 = NULL, *res2 = NULL; #define VAR_INVALID -1 #define VAR_NORMAL 0 #define VAR_SUBST 1 #define VAR_APPEND 2 #define VAR_SHELL 4 #define VAR_OPT 8 int type; struct Name name; arg = VarName_Get(line, &name, NULL, true, FEATURES(FEATURE_SUNSHCMD) ? find_op1 : find_op2); while (isspace(*arg)) arg++; type = VAR_NORMAL; while (*arg != '=') { /* Check operator type. */ switch (*arg++) { case '+': if (type & (VAR_OPT|VAR_APPEND)) type = VAR_INVALID; else type |= VAR_APPEND; break; case '?': if (type & (VAR_OPT|VAR_APPEND)) type = VAR_INVALID; else type |= VAR_OPT; break; case ':': if (FEATURES(FEATURE_SUNSHCMD) && strncmp(arg, "sh", 2) == 0) { type = VAR_SHELL; arg += 2; while (*arg != '=' && *arg != '\0') arg++; } else { if (type & VAR_SUBST) type = VAR_INVALID; else type |= VAR_SUBST; } break; case '!': if (type & VAR_SHELL) type = VAR_INVALID; else type |= VAR_SHELL; break; default: type = VAR_INVALID; break; } if (type == VAR_INVALID) { VarName_Free(&name); return false; } } arg++; while (isspace(*arg)) arg++; /* If the variable already has a value, we don't do anything. */ if ((type & VAR_OPT) && Var_Definedi(name.s, name.e)) { VarName_Free(&name); return true; } if (type & VAR_SHELL) { char *err; if (strchr(arg, '$') != NULL) { char *sub; /* There's a dollar sign in the command, so perform * variable expansion on the whole thing. */ sub = Var_Subst(arg, NULL, true); res1 = Cmd_Exec(sub, &err); free(sub); } else res1 = Cmd_Exec(arg, &err); if (err) Parse_Error(PARSE_WARNING, err, arg); arg = res1; } if (type & VAR_SUBST) { /* * Allow variables in the old value to be undefined, but leave * their invocation alone -- this is done by forcing * errorIsOkay to be false. * XXX: This can cause recursive variables, but that's not * hard to do, and this allows someone to do something like * * CFLAGS = $(.INCLUDES) * CFLAGS := -I.. $(CFLAGS) * * And not get an error. */ bool saved = errorIsOkay; errorIsOkay = false; /* ensure the variable is set to something to avoid `variable * is recursive' errors. */ if (!Var_Definedi(name.s, name.e)) Var_Seti_with_ctxt(name.s, name.e, "", ctxt); res2 = Var_Subst(arg, NULL, false); errorIsOkay = saved; arg = res2; } if (type & VAR_APPEND) Var_Appendi_with_ctxt(name.s, name.e, arg, ctxt); else Var_Seti_with_ctxt(name.s, name.e, arg, ctxt); VarName_Free(&name); free(res2); free(res1); return true; }
/*- *----------------------------------------------------------------------- * CondDoDefined -- * Handle the 'defined' function for conditionals. * * Results: * true if the given variable is defined. *----------------------------------------------------------------------- */ static bool CondDoDefined(struct Name *arg) { return Var_Definedi(arg->s, arg->e); }