(define_variable_in_set): assign NULL as initial value of a pointer to value_record. (free_parent_record): free all parent_records which were assigned. (free_variable_record): free all value_records and related parent_records belongs to a variable. (free_variable_name_and_value): add free_variable_record to when variable is going to be destoryed. (initialize_file_variables): parameters change when do_variable_definition is called. (alloc_parent_record): allocate memory for a parent_record. (do_assign_parent_record): assign a parent_record to its value_record. (do_assign_value_record): assign a value_record to related variable. (do_variable_definition): add parent_record related processing to construct information for a variable. (assign_variable_definition): add parent_record as a parameter of this wrapper. (try_variable_definition): add parent_record as a parameter of do_variable_definition (print_variable): dump value_record and parent_record for a variable (print_variable_dep_set): dump dependency of value_record, parent_record of a variable from a set.
Signed-off-by: Macpaul Lin <macp...@gmail.com> --- variable.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 196 insertions(+), 5 deletions(-) diff --git a/variable.c b/variable.c index 3f57e7d..6ca5b56 100644 --- a/variable.c +++ b/variable.c @@ -254,6 +254,7 @@ define_variable_in_set (const char *name, unsigned int length, v->append = 0; v->private_var = 0; v->export = v_default; + v->v_records = NULL; v->exportable = 1; if (*name != '_' && (*name < 'A' || *name > 'Z') @@ -279,11 +280,47 @@ define_variable_in_set (const char *name, unsigned int length, variable (makefile, command line or environment). */ static void +free_parent_record (struct parent_record *record) +{ + struct parent_record *pr; + + pr = record; + if (pr != NULL) + { + if (pr->next != NULL) + free_parent_record (pr->next); + free (pr); + } +} + +static void +free_variable_record (struct value_record *record) +{ + struct value_record *vr; + + vr = record; + if (vr != NULL) + { + if (vr->next != NULL) + free_variable_record (vr->next); + + if (vr->p_records != NULL) + free_parent_record (vr->p_records); + + free (vr->value); + free (vr); + } +} + +static void free_variable_name_and_value (const void *item) { struct variable *v = (struct variable *) item; free (v->name); free (v->value); + + if (v->v_records) + free_variable_record(v->v_records); } void @@ -608,7 +645,7 @@ initialize_file_variables (struct file *file, int reading) v = do_variable_definition ( &p->variable.fileinfo, p->variable.name, p->variable.value, p->variable.origin, - p->variable.flavor, 1); + p->variable.flavor, 1, NULL); } /* Also mark it as a per-target and copy export status. */ @@ -1125,17 +1162,68 @@ shell_result (const char *p) return result; } +/* Given a variable as a "parent variable" which defines a value for another + variable. + This function will allocate a struct of parent_record to link these parents. */ +struct parent_record * +alloc_parent_record (struct variable *parent) +{ + struct parent_record *pr; + + pr = xmalloc(sizeof(struct parent_record)); + pr->parent = parent; + pr->next = NULL; + + return pr; +} +/* Given a defined value_record, and a parent_record, link the parents to this value_record. */ +void +do_assign_parent_record (struct value_record *vr, struct parent_record *parents) +{ + struct parent_record *pr; + + /* find the last parent_record */ + pr = vr->p_records; + + if (pr == NULL) + vr->p_records = parents; + else + { + while (pr->next != NULL) + pr = pr->next; + pr->next = parents; + } +} + +/* Given a value of variable, return a point to a valuei_record. */ +struct value_record * +do_assign_value_record (const char *value) +{ + struct value_record *vr; + + vr = xmalloc(sizeof(struct value_record)); + vr->value = xmalloc (strlen (value) + 1); + memcpy (vr->value, value, strlen (value)); + vr->value[strlen (value)] = '\0'; + vr->p_records = NULL; + vr->next = NULL; + + return vr; +} + /* Given a variable, a value, and a flavor, define the variable. See the try_variable_definition() function for details on the parameters. */ struct variable * do_variable_definition (const gmk_floc *flocp, const char *varname, const char *value, enum variable_origin origin, - enum variable_flavor flavor, int target_var) + enum variable_flavor flavor, int target_var, + struct parent_record *parents) { const char *p; char *alloc_value = NULL; struct variable *v; + struct value_record *temp_vr, *last_vr; int append = 0; int conditional = 0; @@ -1377,6 +1465,48 @@ do_variable_definition (const gmk_floc *flocp, const char *varname, v->append = append; v->conditional = conditional; + /* Check if this value was defined by parent variables (conditional line). + If there are parent_records (parents), create value_record (temp_vr) and + then link these parent_records with this value_record */ + if (parents != NULL) + { + /* check if this vr already exists */ + temp_vr = v->v_records; + + if (temp_vr == NULL) + { + temp_vr = do_assign_value_record (value); + do_assign_parent_record (temp_vr, parents); + v->v_records = temp_vr; + } + else + { + /* Deal with multiple parent for the same value */ + while (temp_vr != NULL) + { + if (strcmp (temp_vr->value, value)) + { + /* keep the pointer to the second-last */ + last_vr = temp_vr; + temp_vr = temp_vr->next; + } + else + { + do_assign_parent_record(temp_vr, parents); + break; + } + } + + /* this means this value is a new one. */ + if (temp_vr == NULL) + { + temp_vr = do_assign_value_record (value); + do_assign_parent_record (temp_vr, parents); + last_vr->next = temp_vr; + } + } + } + free (alloc_value); return v->special ? set_special_var (v) : v; @@ -1563,7 +1693,8 @@ assign_variable_definition (struct variable *v, const char *line) struct variable * try_variable_definition (const gmk_floc *flocp, const char *line, - enum variable_origin origin, int target_var) + enum variable_origin origin, int target_var, + struct parent_record *parents) { struct variable v; struct variable *vp; @@ -1577,7 +1708,7 @@ try_variable_definition (const gmk_floc *flocp, const char *line, return 0; vp = do_variable_definition (flocp, v.name, v.value, - origin, v.flavor, target_var); + origin, v.flavor, target_var, parents); free (v.name); @@ -1636,6 +1767,8 @@ print_variable (const void *item, void *arg) else { char *p; + struct value_record *vr; + struct parent_record *pr; printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); @@ -1655,10 +1788,30 @@ print_variable (const void *item, void *arg) putchar (*p); } putchar ('\n'); + + /* Dump Dependency of variables. */ + /* Check if the value is just whitespace. */ + vr = v->v_records; + while (vr != NULL) + { + printf(" value: %s", vr->value); + + /* Deal with multiple parent */ + pr = vr->p_records; + while (pr != NULL) + { + printf(" parent: %s, value: %s;", pr->parent->name, + pr->parent->value); + pr = pr->next; + } + /* Deal with multiple value */ + vr = vr->next; + putchar ('\n'); + } + } } - static void print_auto_variable (const void *item, void *arg) { @@ -1694,6 +1847,44 @@ print_variable_set (struct variable_set *set, const char *prefix, int pauto) putc ('\n', stdout); } +/* Print all the variables dependency in SET. PREFIX is printed before + the actual variable definitions (everything else is comments). */ + +void +print_variable_dep_set (struct variable_set *set, const char *prefix, int pauto) +{ + hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable), + (void *)prefix); +} + +/* Print the dependency of variables. */ + +void +print_variable_dependency (void) +{ + puts (_("\n# Variables\n")); + + print_variable_dep_set (&global_variable_set, "", 0); + + puts (_("\n# Pattern-specific Variable Values")); + + { + struct pattern_var *p; + int rules = 0; + + for (p = pattern_vars; p != 0; p = p->next) + { + ++rules; + printf ("\n%s :\n", p->target); + print_variable (&p->variable, (void *)"# "); + } + if (rules == 0) + puts (_("\n# No pattern-specific variable values.")); + else + printf (_("\n# %u pattern-specific variable values"), rules); + } +} + /* Print the data base of variables. */ void -- 1.9.1 _______________________________________________ Bug-make mailing list Bug-make@gnu.org https://lists.gnu.org/mailman/listinfo/bug-make