mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-06-20 09:48:12 +02: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 = *adesigns; /* for readability */
|
||||||
|
|
||||||
dp->name = "<Command Line Definition>";
|
dp->name = "<Command Line Definition>";
|
||||||
|
dp->aliases = (char **) calloc(1, sizeof(char *));
|
||||||
dp->created = "now";
|
dp->created = "now";
|
||||||
dp->revision = "1.0";
|
dp->revision = "1.0";
|
||||||
dp->sample = "n/a";
|
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()
|
static int list_styles()
|
||||||
/*
|
/*
|
||||||
* Generate sorted listing of available box styles.
|
* Generate sorted listing of available box styles.
|
||||||
@ -749,6 +797,17 @@ static int list_styles()
|
|||||||
}
|
}
|
||||||
fprintf(opt.outfile, "\n");
|
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",
|
fprintf(opt.outfile, "Author: %s\n",
|
||||||
d->author ? d->author : "(unknown author)");
|
d->author ? d->author : "(unknown author)");
|
||||||
fprintf(opt.outfile, "Original Designer: %s\n",
|
fprintf(opt.outfile, "Original Designer: %s\n",
|
||||||
@ -906,23 +965,27 @@ static int list_styles()
|
|||||||
for (i = 0; i < anz_designs; ++i) {
|
for (i = 0; i < anz_designs; ++i) {
|
||||||
if (opt.q) {
|
if (opt.q) {
|
||||||
fprintf(opt.outfile, "%s\n", list[i]->name);
|
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 {
|
else {
|
||||||
|
char *all_names = names(list[i]);
|
||||||
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
|
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);
|
list[i]->designer, list[i]->author, list[i]->sample);
|
||||||
}
|
}
|
||||||
else if (list[i]->designer) {
|
else if (list[i]->designer) {
|
||||||
fprintf(opt.outfile, "%s\n%s:\n%s\n\n", list[i]->name,
|
fprintf(opt.outfile, "%s\n%s:\n%s\n\n", all_names, list[i]->designer, list[i]->sample);
|
||||||
list[i]->designer, list[i]->sample);
|
|
||||||
}
|
}
|
||||||
else if (list[i]->author) {
|
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);
|
list[i]->author, list[i]->sample);
|
||||||
}
|
}
|
||||||
else {
|
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);
|
BFREE (list);
|
||||||
|
@ -92,6 +92,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
|
char **aliases; /* zero-terminated array of alias names of the design */
|
||||||
char *author; /* creator of the configuration file entry */
|
char *author; /* creator of the configuration file entry */
|
||||||
char *designer; /* creator of the original ASCII artwork */
|
char *designer; /* creator of the original ASCII artwork */
|
||||||
char *created; /* date created, free format */
|
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)
|
static void recover(pass_to_bison *bison_args)
|
||||||
/*
|
/*
|
||||||
* Reset parser to neutral state, so a new design can be parsed.
|
* 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.name);
|
||||||
BFREE (curdes.author);
|
BFREE (curdes.author);
|
||||||
|
BFREE (curdes.aliases);
|
||||||
BFREE (curdes.designer);
|
BFREE (curdes.designer);
|
||||||
BFREE (curdes.created);
|
BFREE (curdes.created);
|
||||||
BFREE (curdes.revision);
|
BFREE (curdes.revision);
|
||||||
BFREE (curdes.revdate);
|
BFREE (curdes.revdate);
|
||||||
BFREE (curdes.sample);
|
BFREE (curdes.sample);
|
||||||
BFREE (curdes.tags);
|
BFREE (curdes.tags);
|
||||||
memset (bison_args->designs + bison_args->design_idx, 0, sizeof(design_t));
|
init_design(bison_args, &(curdes));
|
||||||
curdes.indentmode = DEF_INDENTMODE;
|
|
||||||
curdes.defined_in = bison_args->config_file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int design_needed (const char *name, const int design_idx)
|
static int design_has_name(design_t *design, char *name)
|
||||||
/*
|
{
|
||||||
* Return true if design of name name will be needed later on
|
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) {
|
if (opt.design_choice_by_user) {
|
||||||
return !strcasecmp (name, (char *) opt.design);
|
return design_has_name(&(curdes), (char *) opt.design);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (opt.r || opt.l) {
|
if (opt.r || opt.l) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (design_idx == 0) {
|
if (bison_args->design_idx == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
bison_args->num_designs = 1;
|
bison_args->num_designs = 1;
|
||||||
|
init_design(bison_args, bison_args->designs);
|
||||||
bison_args->designs->indentmode = DEF_INDENTMODE;
|
|
||||||
bison_args->designs->defined_in = bison_args->config_file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config_file
|
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, '\\', '\"');
|
chg_strdelims(bison_args, '\\', '\"');
|
||||||
bison_args->speeding = 0;
|
bison_args->speeding = 0;
|
||||||
bison_args->skipping = 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;
|
bison_args->speeding = 1;
|
||||||
begin_speedmode(scanner);
|
begin_speedmode(scanner);
|
||||||
|
init_design(bison_args, &(curdes));
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layout YEND WORD
|
layout YEND WORD
|
||||||
{
|
{
|
||||||
|
char *design_primary_name = $<s>2;
|
||||||
design_t *tmp;
|
design_t *tmp;
|
||||||
int i;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
#ifdef PARSER_DEBUG
|
#ifdef PARSER_DEBUG
|
||||||
fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", $2);
|
fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", design_primary_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strcasecmp ($2, $6)) {
|
if (strcasecmp (design_primary_name, $6)) {
|
||||||
yyerror(bison_args, "box design name differs at BOX and END");
|
yyerror(bison_args, "box design name differs at BOX and END");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -560,29 +625,20 @@ layout YEND WORD
|
|||||||
yyerror(bison_args, "entries SAMPLE, SHAPES, and ELASTIC are mandatory");
|
yyerror(bison_args, "entries SAMPLE, SHAPES, and ELASTIC are mandatory");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
|
if (design_name_exists(bison_args, design_primary_name)) {
|
||||||
for (i=0; i<bison_args->design_idx; ++i) {
|
yyerror(bison_args, "duplicate box design name -- %s", design_primary_name);
|
||||||
if (strcasecmp ($2, bison_args->designs[i].name) == 0) {
|
YYERROR;
|
||||||
yyerror(bison_args, "duplicate box design name -- %s", $2);
|
|
||||||
YYERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p = $2;
|
p = design_primary_name;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p < 32 || *p > 126) {
|
if (*p < 32 || *p > 126) {
|
||||||
yyerror(bison_args, "box design name must consist of printable standard "
|
yyerror(bison_args, "box design name must consist of printable standard ASCII characters.");
|
||||||
"ASCII characters.");
|
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
curdes.name = (char *) strdup ($2);
|
|
||||||
if (curdes.name == NULL) {
|
|
||||||
perror (PROJECT);
|
|
||||||
YYABORT;
|
|
||||||
}
|
|
||||||
bison_args->num_mandatory = 0;
|
bison_args->num_mandatory = 0;
|
||||||
bison_args->time_for_se_check = 0;
|
bison_args->time_for_se_check = 0;
|
||||||
bison_args->num_shapespec = 0;
|
bison_args->num_shapespec = 0;
|
||||||
@ -600,15 +656,13 @@ layout YEND WORD
|
|||||||
* Allocate space for next design
|
* Allocate space for next design
|
||||||
*/
|
*/
|
||||||
++(bison_args->design_idx);
|
++(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) {
|
if (tmp == NULL) {
|
||||||
perror (PROJECT);
|
perror (PROJECT);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
bison_args->designs = tmp;
|
bison_args->designs = tmp;
|
||||||
memset (&curdes, 0, sizeof(design_t));
|
init_design(bison_args, &(curdes));
|
||||||
curdes.indentmode = DEF_INDENTMODE;
|
|
||||||
curdes.defined_in = bison_args->config_file;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user