diff --git a/src/boxes.in.h b/src/boxes.in.h index 52fc94f..2842c41 100644 --- a/src/boxes.in.h +++ b/src/boxes.in.h @@ -76,14 +76,14 @@ typedef struct { typedef struct { - char *name; + char *name; /* primary name of the box design */ char **aliases; /* zero-terminated array of alias names of the design */ char *author; /* creator of the configuration file entry */ char *designer; /* creator of the original ASCII artwork */ char *created; /* date created, free format */ char *revision; /* revision number of design */ char *revdate; /* date of current revision */ - char *sample; + char *sample; /* the complete sample block in one string */ char indentmode; /* 'b', 't', or 'n' */ sentry_t shape[NUM_SHAPES]; size_t maxshapeheight; /* height of highest shape in design */ diff --git a/src/parsecode.c b/src/parsecode.c index 0780a70..3012e5f 100644 --- a/src/parsecode.c +++ b/src/parsecode.c @@ -323,6 +323,20 @@ void recover(pass_to_bison *bison_args) +static int design_has_alias(design_t *design, char *alias) +{ + int result = 0; + for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) { + if (strcasecmp(alias, design->aliases[aidx]) == 0) { + result = 1; + break; + } + } + return result; +} + + + static int design_has_name(design_t *design, char *name) { int result = 0; @@ -330,12 +344,7 @@ static int design_has_name(design_t *design, char *name) result = 1; } else { - for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) { - if (strcasecmp(name, design->aliases[aidx]) == 0) { - result = 1; - break; - } - } + result = design_has_alias(design, name); } return result; } @@ -390,6 +399,20 @@ static int design_name_exists(pass_to_bison *bison_args, char *name) +static int alias_exists_in_child_configs(pass_to_bison *bison_args, char *alias) +{ + int result = 0; + for (size_t i = 0; i < bison_args->num_child_configs; ++i) { + if (design_has_alias(bison_args->child_configs + i, alias)) { + result = 1; + break; + } + } + return result; +} + + + static int tag_add(pass_to_bison *bison_args, char *tag) { int rc = RC_SUCCESS; @@ -921,10 +944,17 @@ int action_add_alias(pass_to_bison *bison_args, char *alias_name) yyerror(bison_args, "alias already in use -- %s", alias_name); return RC_ERROR; } - size_t num_aliases = array_count0(curdes.aliases); - curdes.aliases = (char **) realloc(curdes.aliases, (num_aliases + 2) * sizeof(char *)); - curdes.aliases[num_aliases] = strdup(alias_name); - curdes.aliases[num_aliases + 1] = NULL; + if (alias_exists_in_child_configs(bison_args, alias_name)) { + #ifdef PARSER_DEBUG + fprintf (stderr, "alias already used by child config, dropping: %s\n", alias_name); + #endif + } + else { + size_t num_aliases = array_count0(curdes.aliases); + curdes.aliases = (char **) realloc(curdes.aliases, (num_aliases + 2) * sizeof(char *)); + curdes.aliases[num_aliases] = strdup(alias_name); + curdes.aliases[num_aliases + 1] = NULL; + } return RC_SUCCESS; } diff --git a/src/parser.y b/src/parser.y index cae5bc1..4950b2b 100644 --- a/src/parser.y +++ b/src/parser.y @@ -38,6 +38,12 @@ typedef struct { /** index into `*designs` */ int design_idx; + /** Box designs already parsed from child config files, if any. Else NULL */ + design_t *child_configs; + + /** the size of `*child_configs` */ + size_t num_child_configs; + /** the path to the config file we are parsing */ char *config_file; diff --git a/src/parsing.c b/src/parsing.c index 1fbc879..50d271a 100644 --- a/src/parsing.c +++ b/src/parsing.c @@ -161,13 +161,15 @@ static pass_to_flex new_flex_extra_data(pass_to_bison *bison_args) -static pass_to_bison parse_config_file(const char *config_file) +static pass_to_bison parse_config_file(const char *config_file, design_t *child_configs, size_t num_child_configs) { #ifdef DEBUG fprintf (stderr, "Parsing Config File %s ...\n", config_file); #endif pass_to_bison bison_args = new_bison_args(config_file); + bison_args.child_configs = child_configs; + bison_args.num_child_configs = num_child_configs; pass_to_flex flex_extra_data = new_flex_extra_data(&bison_args); current_bison_args = &bison_args; @@ -272,7 +274,7 @@ design_t *parse_config_files(const char *p_first_config_file, size_t *r_num_desi first_config_file = p_first_config_file; const char *config_file = p_first_config_file; do { - pass_to_bison bison_args = parse_config_file(config_file); + pass_to_bison bison_args = parse_config_file(config_file, result, *r_num_designs); ++parents_parsed; #ifdef DEBUG fprintf (stderr, "bison_args returned: " diff --git a/test/165_design_alias_parent_override.cfg b/test/165_design_alias_parent_override.cfg new file mode 100644 index 0000000..2c29275 --- /dev/null +++ b/test/165_design_alias_parent_override.cfg @@ -0,0 +1,18 @@ +parent 165_design_alias_parent_override.parent.cfg + +# the following designA will have these 2 alias names. alias2 will be gone +BOX designA, alias1, alias3 + +sample + A from regular config +ends + +shapes { + w ("Ab") +} + +elastic ( + w +) + +END designA diff --git a/test/165_design_alias_parent_override.parent.cfg b/test/165_design_alias_parent_override.parent.cfg new file mode 100644 index 0000000..bb21d43 --- /dev/null +++ b/test/165_design_alias_parent_override.parent.cfg @@ -0,0 +1,15 @@ +BOX designA, alias1, alias2 + +sample + A from parent config +ends + +shapes { + w ("A") +} + +elastic ( + w +) + +END designA diff --git a/test/165_design_alias_parent_override.txt b/test/165_design_alias_parent_override.txt new file mode 100644 index 0000000..4b0325b --- /dev/null +++ b/test/165_design_alias_parent_override.txt @@ -0,0 +1,27 @@ +:DESC +Test that when overriding a design that has alias names, the alias names in the child design do not cause a uniqueness +error, and properly override the parent alias names. + +:ARGS +-f 165_design_alias_parent_override.cfg -d designA -l +:INPUT +:OUTPUT-FILTER +:EXPECTED +Complete Design Information for "designA": +------------------------------------------ +Alias Names: alias1, alias3 +Author: (unknown author) +Original Designer: (unknown artist) +Creation Date: (unknown) +Current Revision: (unknown) +Configuration File: 165_design_alias_parent_override.cfg +Indentation Mode: box (indent box) +Replacement Rules: none +Reversion Rules: none +Minimum Box Dimensions: 4 x 3 (width x height) +Default Padding: none +Default Killblank: no +Tags: none +Elastic Shapes: N, E, S, W +Defined Shapes: W: "Ab" +:EOF diff --git a/test/166_design_alias_parent_clash.cfg b/test/166_design_alias_parent_clash.cfg new file mode 100644 index 0000000..6aa2331 --- /dev/null +++ b/test/166_design_alias_parent_clash.cfg @@ -0,0 +1,18 @@ +parent 166_design_alias_parent_clash.parent.cfg + +# the following designB claims alias1, which means designA from the parent config loses it +BOX designB, alias1 + +sample + B from regular config +ends + +shapes { + w ("B") +} + +elastic ( + w +) + +END designB diff --git a/test/166_design_alias_parent_clash.parent.cfg b/test/166_design_alias_parent_clash.parent.cfg new file mode 100644 index 0000000..bb21d43 --- /dev/null +++ b/test/166_design_alias_parent_clash.parent.cfg @@ -0,0 +1,15 @@ +BOX designA, alias1, alias2 + +sample + A from parent config +ends + +shapes { + w ("A") +} + +elastic ( + w +) + +END designA diff --git a/test/166_design_alias_parent_clash.txt b/test/166_design_alias_parent_clash.txt new file mode 100644 index 0000000..da9a284 --- /dev/null +++ b/test/166_design_alias_parent_clash.txt @@ -0,0 +1,28 @@ +:DESC +Test that when an alias is defined in a child config AND in a parent config, the child config wins. The parent design +loses the alias. + +:ARGS +-f 166_design_alias_parent_clash.cfg -l +:INPUT +:OUTPUT-FILTER +:EXPECTED +2 Available Styles: +------------------- + +Configuration Files: + - 166_design_alias_parent_clash.cfg + - 166_design_alias_parent_clash.parent.cfg (parent) + + +designA alias alias2: + + A from parent config + + +designB alias alias1: + + B from regular config + + +:EOF diff --git a/test/167_duplicate_primary_name.cfg b/test/167_duplicate_primary_name.cfg new file mode 100644 index 0000000..95c3b88 --- /dev/null +++ b/test/167_duplicate_primary_name.cfg @@ -0,0 +1,35 @@ + +BOX designA + +sample + designA +ends + +shapes { + w ("A") +} + +elastic ( + w +) + +END designA + + + + +BOX designA + +sample + designA (duplicate) +ends + +shapes { + w ("A-dup") +} + +elastic ( + w +) + +END designA diff --git a/test/167_duplicate_primary_name.txt b/test/167_duplicate_primary_name.txt new file mode 100644 index 0000000..e435958 --- /dev/null +++ b/test/167_duplicate_primary_name.txt @@ -0,0 +1,19 @@ +:DESC +Test that two designs in the same file may not have the same name. The second one is invalid and should be skipped. + +:ARGS +-f 167_duplicate_primary_name.cfg -l +:INPUT +:OUTPUT-FILTER +:EXPECTED +boxes: 167_duplicate_primary_name.cfg: line 35: duplicate box design name -- designA +boxes: 167_duplicate_primary_name.cfg: line 35: skipping to next design +1 Available Style in "167_duplicate_primary_name.cfg": +------------------------------------------------------ + +designA: + + designA + + +:EOF