mirror of
https://github.com/ascii-boxes/boxes.git
synced 2024-12-04 22:11:07 +01:00
Add support of alias names for designs #30
This commit is contained in:
parent
4dcd1322a7
commit
44f4c8adaa
73
src/boxes.c
73
src/boxes.c
@ -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);
|
||||
|
@ -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 */
|
||||
|
130
src/parser.y
130
src/parser.y
@ -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));
|
||||
}
|
||||
;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user