Fix a bug where alias names could be defined twice

This could happen when configs are inherited, but aliases redefined
(a rare case so far).
This commit is contained in:
Thomas Jensen 2021-06-08 22:06:25 +02:00
parent d6433d3d41
commit 00153f8068
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
12 changed files with 227 additions and 14 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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: "

View File

@ -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

View File

@ -0,0 +1,15 @@
BOX designA, alias1, alias2
sample
A from parent config
ends
shapes {
w ("A")
}
elastic (
w
)
END designA

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,15 @@
BOX designA, alias1, alias2
sample
A from parent config
ends
shapes {
w ("A")
}
elastic (
w
)
END designA

View File

@ -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

View File

@ -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

View File

@ -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