(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. (dup_parent_records): a function for distinquish variables in the same conditional line's depth but may have different parents sets. (print_value_records): a function to dump all value_records, parent_records, and other parents_records in depths belongs to this variable.
Signed-off-by: Macpaul Lin <macp...@gmail.com> --- Changes for v2: - simplify (free_parent_record). - simplify (free_variable_record). - add (dup_parent_records). - add depth support to (dup_parent_records). - add (print_value_records). - simplify (print_variable). variable.c | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 253 insertions(+), 5 deletions(-) diff --git a/variable.c b/variable.c index 3f57e7d..5ac2139 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') @@ -278,12 +279,42 @@ define_variable_in_set (const char *name, unsigned int length, does not need to be null-terminated. ORIGIN specifies the origin of the variable (makefile, command line or environment). */ +void +free_parent_record (struct parent_record *pr) +{ + if (pr != NULL) + { + if (pr->next != NULL) + free_parent_record (pr->next); + free (pr); + } +} + +static void +free_variable_record (struct value_record *vr) +{ + 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 +639,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 +1156,92 @@ shell_result (const char *p) return result; } +/* Given a destination pointer to a parent records, we duplicate the linking + list of source parent records to the destination pointer. */ +struct parent_record * +dup_parent_records (struct parent_record **dst_pr, struct parent_record *src_pr) +{ + /* Duplicate new parent_record and assign to this variable */ + struct parent_record *new_pr = NULL; + + if (src_pr != NULL) + { + *dst_pr = alloc_parent_record (src_pr->parent, src_pr->depth); + (*dst_pr)->next = NULL; + + if (src_pr->next != NULL) + { + dup_parent_records (&new_pr, src_pr->next); + (*dst_pr)->next = new_pr; + } + } + + return *dst_pr; +} +/* 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, unsigned int depth) +{ + struct parent_record *pr; + + pr = xmalloc(sizeof(struct parent_record)); + pr->parent = parent; + pr->depth = depth; + 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 +1483,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 +1711,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,13 +1726,68 @@ 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); return vp; } +/* Print information for variable_record variable VR, prefixing it with PREFIX. */ + +static void +print_value_records (struct value_record *src_vr) +{ + struct value_record *vr = src_vr; + struct parent_record *pr; + struct variable *temp_v; + + /* print the first depth of parent */ + while (vr != NULL) + { + printf("value: %s.", vr->value); + + /* Deal with multiple parent */ + pr = vr->p_records; + while (pr != NULL) + { + putchar (' '); + printf("parent: %s = %s;", pr->parent->name, pr->parent->value); + pr = pr->next; + } + /* Deal with multiple value */ + vr = vr->next; + if (vr) + putchar (' '); + } + + /* print the second depth of parent */ + vr = src_vr; + while (vr != NULL) + { + /* Deal with multiple parent */ + pr = vr->p_records; + while (pr != NULL) + { + /* if this parent has its own parent_records, dump them too. */ + temp_v = lookup_variable(pr->parent->name, + strlen(pr->parent->name)); + if (temp_v) + if (temp_v->v_records) + { + putchar ('\n'); + printf ("parent name: %s, ", pr->parent->name); + print_value_records (temp_v->v_records); + } + pr = pr->next; + } + /* Deal with multiple value */ + vr = vr->next; + } + +} + + /* Print information for variable V, prefixing it with PREFIX. */ static void @@ -1655,10 +1859,16 @@ print_variable (const void *item, void *arg) putchar (*p); } putchar ('\n'); + + /* Dump Dependency of variables. */ + if (v->v_records) + { + print_value_records (v->v_records); + putchar ('\n'); + } } } - static void print_auto_variable (const void *item, void *arg) { @@ -1694,6 +1904,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