Add support of alias names for designs #30

This commit is contained in:
Thomas Jensen 2021-03-20 21:27:48 +01:00
parent 4dcd1322a7
commit 44f4c8adaa
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
3 changed files with 161 additions and 43 deletions

View File

@ -624,6 +624,7 @@ static int build_design(design_t **adesigns, const char *cld)
dp = *adesigns; /* for readability */
dp->name = "<Command Line Definition>";
dp->aliases = (char **) calloc(1, sizeof(char *));
dp->created = "now";
dp->revision = "1.0";
dp->sample = "n/a";
@ -718,6 +719,53 @@ static int style_sort(const void *p1, const void *p2)
/**
* Create a string listing all the names of a design, for example `"ada-cmt alias lua-cmt, sql-cmt"`.
* @param design pointer to the design
* @return the string of names, for which memory was allocated
*/
static char *names(design_t *design)
{
size_t siz = strlen(design->name);
size_t num_aliases = 0;
while(design->aliases[num_aliases] != NULL) {
siz += strlen(design->aliases[num_aliases]);
if (num_aliases > 0) {
siz += 2; // ", "
}
++num_aliases;
}
if (num_aliases > 0) {
siz += 7; // " alias "
}
char *result = (char *) malloc (siz + 1);
if (result == NULL) {
perror(PROJECT);
return NULL;
}
strcpy(result, design->name);
if (num_aliases > 0) {
char *p = result + strlen(design->name);
strcpy(p, " alias ");
p += 7;
for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) {
strcpy(p, design->aliases[aidx]);
p += strlen(design->aliases[aidx]);
if (aidx < num_aliases - 1) {
strcpy(p, ", ");
p += 2;
}
}
}
return result;
}
static int list_styles()
/*
* Generate sorted listing of available box styles.
@ -749,6 +797,17 @@ static int list_styles()
}
fprintf(opt.outfile, "\n");
fprintf(opt.outfile, "Alias Names: ");
size_t aidx = 0;
while(d->aliases[aidx] != NULL) {
fprintf(opt.outfile, "%s%s", aidx > 0 ? ", " : "", d->aliases[aidx]);
++aidx;
}
if (aidx == 0) {
fprintf(opt.outfile, "none");
}
fprintf(opt.outfile, "\n");
fprintf(opt.outfile, "Author: %s\n",
d->author ? d->author : "(unknown author)");
fprintf(opt.outfile, "Original Designer: %s\n",
@ -906,23 +965,27 @@ static int list_styles()
for (i = 0; i < anz_designs; ++i) {
if (opt.q) {
fprintf(opt.outfile, "%s\n", list[i]->name);
for (size_t aidx = 0; list[i]->aliases[aidx] != NULL; ++aidx) {
fprintf(opt.outfile, "%s (alias)\n", list[i]->aliases[aidx]);
}
}
else {
char *all_names = names(list[i]);
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
fprintf(opt.outfile, "%s\n%s, coded by %s:\n%s\n\n", list[i]->name,
fprintf(opt.outfile, "%s\n%s, coded by %s:\n%s\n\n", all_names,
list[i]->designer, list[i]->author, list[i]->sample);
}
else if (list[i]->designer) {
fprintf(opt.outfile, "%s\n%s:\n%s\n\n", list[i]->name,
list[i]->designer, list[i]->sample);
fprintf(opt.outfile, "%s\n%s:\n%s\n\n", all_names, list[i]->designer, list[i]->sample);
}
else if (list[i]->author) {
fprintf(opt.outfile, "%s\nunknown artist, coded by %s:\n%s\n\n", list[i]->name,
fprintf(opt.outfile, "%s\nunknown artist, coded by %s:\n%s\n\n", all_names,
list[i]->author, list[i]->sample);
}
else {
fprintf(opt.outfile, "%s:\n%s\n\n", list[i]->name, list[i]->sample);
fprintf(opt.outfile, "%s:\n%s\n\n", all_names, list[i]->sample);
}
BFREE(all_names);
}
}
BFREE (list);

View File

@ -92,6 +92,7 @@ typedef struct {
typedef struct {
char *name;
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 */

View File

@ -320,6 +320,16 @@ static void chg_strdelims (pass_to_bison *bison_args, const char asesc, const ch
static void init_design(pass_to_bison *bison_args, design_t *design)
{
memset (design, 0, sizeof(design_t));
design->aliases = (char **) calloc(1, sizeof(char *));
design->indentmode = DEF_INDENTMODE;
design->defined_in = bison_args->config_file;
}
static void recover(pass_to_bison *bison_args)
/*
* Reset parser to neutral state, so a new design can be parsed.
@ -337,41 +347,72 @@ static void recover(pass_to_bison *bison_args)
*/
BFREE (curdes.name);
BFREE (curdes.author);
BFREE (curdes.aliases);
BFREE (curdes.designer);
BFREE (curdes.created);
BFREE (curdes.revision);
BFREE (curdes.revdate);
BFREE (curdes.sample);
BFREE (curdes.tags);
memset (bison_args->designs + bison_args->design_idx, 0, sizeof(design_t));
curdes.indentmode = DEF_INDENTMODE;
curdes.defined_in = bison_args->config_file;
init_design(bison_args, &(curdes));
}
static int design_needed (const char *name, const int design_idx)
/*
* Return true if design of name name will be needed later on
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
static int design_has_name(design_t *design, char *name)
{
int result = 0;
if (strcasecmp(name, design->name) == 0) {
result = 1;
}
else {
for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) {
if (strcasecmp(name, design->aliases[aidx]) == 0) {
result = 1;
break;
}
}
}
return result;
}
/**
* Determine if the design currently being parsed is one that we will need.
* @param bison_args the bison state
* @return flag
*/
static int design_needed(pass_to_bison *bison_args)
{
if (opt.design_choice_by_user) {
return !strcasecmp (name, (char *) opt.design);
return design_has_name(&(curdes), (char *) opt.design);
}
else {
if (opt.r || opt.l) {
return 1;
}
if (design_idx == 0) {
if (bison_args->design_idx == 0) {
return 1;
}
}
return 0;
}
static int design_name_exists(pass_to_bison *bison_args, char *name)
{
int result = 0;
for (int i = 0; i < bison_args->design_idx; ++i) {
if (design_has_name(bison_args->designs + i, name)) {
result = 1;
break;
}
}
return result;
}
}
@ -437,9 +478,7 @@ first_rule:
YYABORT;
}
bison_args->num_designs = 1;
bison_args->designs->indentmode = DEF_INDENTMODE;
bison_args->designs->defined_in = bison_args->config_file;
init_design(bison_args, bison_args->designs);
}
config_file
@ -530,29 +569,55 @@ design_or_error: design | error
}
design: YBOX WORD
alias: WORD
{
if (design_name_exists(bison_args, $1)) {
yyerror(bison_args, "alias already in use -- %s", $1);
YYERROR;
}
size_t num_aliases = 0;
while (curdes.aliases[num_aliases] != NULL) {
++num_aliases;
}
curdes.aliases = (char **) realloc(curdes.aliases, (num_aliases + 2) * sizeof(char *));
curdes.aliases[num_aliases] = strdup($1);
curdes.aliases[num_aliases + 1] = NULL;
}
alias_list: alias | alias_list ',' alias;
design_id: WORD | WORD ',' alias_list
design: YBOX design_id
{
chg_strdelims(bison_args, '\\', '\"');
bison_args->speeding = 0;
bison_args->skipping = 0;
if (!design_needed ($2, bison_args->design_idx)) {
curdes.name = (char *) strdup($<s>2);
if (curdes.name == NULL) {
perror (PROJECT);
YYABORT;
}
if (!design_needed(bison_args)) {
bison_args->speeding = 1;
begin_speedmode(scanner);
init_design(bison_args, &(curdes));
YYERROR;
}
}
layout YEND WORD
{
char *design_primary_name = $<s>2;
design_t *tmp;
int i;
char *p;
#ifdef PARSER_DEBUG
fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", $2);
fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", design_primary_name);
#endif
if (strcasecmp ($2, $6)) {
if (strcasecmp (design_primary_name, $6)) {
yyerror(bison_args, "box design name differs at BOX and END");
YYERROR;
}
@ -560,29 +625,20 @@ layout YEND WORD
yyerror(bison_args, "entries SAMPLE, SHAPES, and ELASTIC are mandatory");
YYERROR;
}
for (i=0; i<bison_args->design_idx; ++i) {
if (strcasecmp ($2, bison_args->designs[i].name) == 0) {
yyerror(bison_args, "duplicate box design name -- %s", $2);
YYERROR;
}
if (design_name_exists(bison_args, design_primary_name)) {
yyerror(bison_args, "duplicate box design name -- %s", design_primary_name);
YYERROR;
}
p = $2;
p = design_primary_name;
while (*p) {
if (*p < 32 || *p > 126) {
yyerror(bison_args, "box design name must consist of printable standard "
"ASCII characters.");
yyerror(bison_args, "box design name must consist of printable standard ASCII characters.");
YYERROR;
}
++p;
}
curdes.name = (char *) strdup ($2);
if (curdes.name == NULL) {
perror (PROJECT);
YYABORT;
}
bison_args->num_mandatory = 0;
bison_args->time_for_se_check = 0;
bison_args->num_shapespec = 0;
@ -600,15 +656,13 @@ layout YEND WORD
* Allocate space for next design
*/
++(bison_args->design_idx);
tmp = (design_t *) realloc (bison_args->designs, (bison_args->design_idx+1)*sizeof(design_t));
tmp = (design_t *) realloc(bison_args->designs, (bison_args->design_idx + 1) * sizeof(design_t));
if (tmp == NULL) {
perror (PROJECT);
YYABORT;
}
bison_args->designs = tmp;
memset (&curdes, 0, sizeof(design_t));
curdes.indentmode = DEF_INDENTMODE;
curdes.defined_in = bison_args->config_file;
init_design(bison_args, &(curdes));
}
;