/* Define variable named NAME with value VALUE in SET. VALUE is copied. LENGTH is the length of NAME, which does not need to be null-terminated. * ORIGIN specifies the origin of the variable (makefile, command line or environment). * If RECURSIVE is nonzero a flag is set in the variable saying that it should be recursively re-expanded. */ public static variable define_variable_in_set(string name, string value, variable_origin origin, bool recursive, Dictionary <string, variable> set) { Form1.UpdateVariablesTable(name, false); variable v; if (set == null) { set = current_variable_set_list; } if (set.ContainsKey(name)) { v = set[name]; } else { v = new variable(); v.name = name; set.Add(v.name, v); v.value = value; v.special = false; v.expanding = false; v.exp_count = 0; v.per_target = false; v.append = false; v.private_var = false; v.export = variable_export.v_default; v.exportable = true; if (name[0] != '_' && (name[0] < 'A' || name[0] > 'Z') && (name[0] < 'a' || name[0] > 'z')) { v.exportable = false; } else { int index = 1; int temp; for (; index < name.Length; index++) { if (name[index] != '_' && (name[index] < 'a' || name[index] > 'z') && (name[index] < 'A' || name[index] > 'Z') && !int.TryParse(name[index] + "", out temp)) { break; } } if (index != name.Length) { v.exportable = false; } } } v.value = value; v.origin = origin; v.recursive = recursive; v.unresolved = false; v.isvaluegraph = false; v.printed = false; return(v); }
/* Try to interpret LINE (a null-terminated string) as a variable definition. * ORIGIN may be o_file, o_override, o_env, o_env_override, or o_command specifying that the variable definition comes * from a makefile, an override directive, the environment with or without the -e switch, or the command line. * * See the comments for assign_variable_definition(). * If LINE was recognized as a variable definition, a pointer to its `struct variable' is returned. * If LINE is not a variable definition, NULL is returned. */ public static variable try_variable_definition(string line, variable_origin origin, int target_var) { variable v = new variable(); if (assign_variable_definition(ref v, line) == null) { return(null); } return(do_variable_definition(v.name, v.value, origin, v.flavor, target_var)); }
// Execute a `undefine' directive. The undefine line has already been read, and NAME is the name of the variable to be undefined. public static void do_undefine(string name, variable_origin origin) { string p = ""; string var = ""; // Expand the variable name and find the beginning (NAME) and end. var = ExpandString(name); name = Utils.next_token(var); if (name == null || name.Length == 0) { MessageBox.Show("Empty variable name at line(" + Read.LINENO + ")"); } p = name.TrimEnd(new char[] { ' ' }); undefine_variable(name, null); }
// Given a variable, a value, and a flavor, define the variable. See the try_variable_definition() function for details on the parameters. public static variable do_variable_definition(string varname, string value, variable_origin origin, variable_flavor flavor, int target_var) { string p = ""; string alloc_value = ""; variable v; bool append = false; bool conditional = false; // Calculate the variable's new value in VALUE. switch (flavor) { default: case variable_flavor.f_bogus: //Should not be possible. MessageBox.Show("Abort!"); break; case variable_flavor.f_simple: /* A simple variable definition "var := value". Expand the value. We have to allocate memory since otherwise it'll clobber the * variable buffer, and we may still need that if we're looking at a target-specific variable. */ p = alloc_value = ExpandString(value); break; case variable_flavor.f_conditional: // A conditional variable definition "var ?= value". The value is set IFF the variable is not defined yet. v = lookup_variable(varname); if (v != null) { return(v.special? set_special_var(v) : v); } conditional = true; flavor = variable_flavor.f_recursive; p = value; break; case variable_flavor.f_recursive: // A recursive variable definition "var = value". The value is used verbatim. p = value; break; case variable_flavor.f_append: { // If we have += but we're in a target variable context, we want to append only with other variables in the context of this target. if (target_var == 1) { append = true; v = lookup_variable_in_set(varname, varname.Length, current_variable_set_list); // Don't append from the global set if a previous non-appending target-specific variable definition exists. if (v != null && !v.append) { append = false; } } else { v = lookup_variable(varname); } if (v == null) { // There was no old value. This becomes a normal recursive definition. p = value; flavor = variable_flavor.f_recursive; } else { // Paste the old and new values together in VALUE. string val = ""; string tp = ""; val = value; if (v.recursive) { // The previous definition of the variable was recursive. The new value is the unexpanded old and new values. flavor = variable_flavor.f_recursive; } else { /* The previous definition of the variable was simple. The new value comes from the old value, which was expanded * when it was set; and from the expanded new value. Allocate memory for the expansion as we may still need the rest of the * buffer if we're looking at a target-specific variable. */ val = tp = ExpandString(val); } p = alloc_value = v.value + " " + val; } break; } } /* If we are defining variables inside an $(eval ...), we might have a * different variable context pushed, not the global context (maybe we're inside a $(call ...) or something. Since this function is only ever * invoked in places where we want to define globally visible variables, make sure we define this variable in the global set. */ v = define_variable_in_set(varname, p, origin, (flavor == variable_flavor.f_recursive), (target_var == 1 ? current_variable_set_list : null)); v.append = append; v.conditional = conditional; return(v.special ? set_special_var(v) : v); }