lorid

convert chordpro to pdf
git clone git://git.relim.de/lorid.git
Log | Files | Refs | README | LICENSE

commit 11ebd41a6c1db534165bf5eb2b22c87ea2c93f9e
parent 4953aaa9d1ffafa0b1abf79ee82da6c417144542
Author: nibo <nibo@relim.de>
Date:   Tue, 15 Oct 2024 09:16:59 +0200

Support this syntax: {start_of_*: label="..."}

Diffstat:
Mchordpro.c | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mtodo | 3++-
2 files changed, 103 insertions(+), 2 deletions(-)

diff --git a/chordpro.c b/chordpro.c @@ -2599,6 +2599,96 @@ END: return directive; } +static char * +cho_directive_label_parse(const char *directive_name, const char *str) +{ + char *label_name = NULL; + char c; + enum OptionState state = OS_NAME; + enum AttrValueSyntax avs = AVS_NO; + char name[5+1]; + char value[URL_MAX_LEN+1]; + int n = 0; + int v = 0; + memset(name, 0, sizeof(name)); + memset(value, 0, sizeof(value)); + int i; + for (i = 0; str[i] != 0; i++) { + c = str[i]; + switch (state) { + case OS_NAME: + if (is_whitespace(c)) { + if (n == 0) { + break; + } else { + name[n] = 0; + cho_log(LOG_ERR, "Option with name '%s' in environment directive '%s' has no value.", name, directive_name); + return NULL; + } + } + if (c == '=') { + name[n] = 0; + if (strcmp(name, "label") != 0) { + cho_log(LOG_ERR, "Invalid option name '%s' in environment directive '%s'.", name, directive_name); + } + memset(name, 0, n); + n = 0; + state = OS_VALUE; + break; + } + if (n > 4) { + cho_log(LOG_ERR, "Option name in environment directive '%s' is too long.", directive_name); + return NULL; + } + name[n] = c; + n++; + break; + case OS_VALUE: + if (avs == AVS_NO) { + if (is_whitespace(c)) { + cho_log(LOG_ERR, "Whitespace character after equals sign in environment directive '%s' is invalid.", directive_name); + return NULL; + } + if (c == '\'') { + avs = AVS_APOSTROPHE; + } else if (c == '"') { + avs = AVS_QUOTATION_MARK; + } else { + avs = AVS_UNQUOTED; + value[v] = c; + v++; + } + break; + } + if (c == '\n') { + cho_log(LOG_ERR, "Newline character inside an option value in environment directive '%s' is invalid.", directive_name); + return NULL; + } + if ( + (avs == AVS_APOSTROPHE && c == '\'') || + (avs == AVS_QUOTATION_MARK && c == '"') || + (avs == AVS_UNQUOTED && (c == ' ' || c == '\t')) + ) { + value[v] = 0; + label_name = strdup(value); + memset(value, 0, v); + v = 0; + avs = AVS_NO; + state = OS_NAME; + break; + } + value[v] = c; + v++; + break; + } + } + if (avs == AVS_UNQUOTED) { + value[v] = 0; + label_name = strdup(value); + } + return label_name; +} + struct ChoSong ** cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) { @@ -3009,7 +3099,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) songs[so]->sections[se] = cho_section_new(); songs[so]->sections[se]->type = directive->stype; songs[so]->sections[se]->label = malloc(sizeof(struct ChoLabel)); - songs[so]->sections[se]->label->name = str_remove_leading_whitespace(directive_value); + if (strstr(directive_value, "=")) { + label = cho_directive_label_parse(directive_name, directive_value); + if (!label) { + LOG_DEBUG("cho_directive_label_parse failed."); + cho_log(LOG_ERR, "Failed to parse the section label. You have to ways of specifying a label:\n\t\t\t1. {start_of_*: label=\"Label name\"}\n\t\t\t2. {start_of*: Label name}"); + return NULL; + } + songs[so]->sections[se]->label->name = label; + } else { + songs[so]->sections[se]->label->name = str_remove_leading_whitespace(directive_value); + } songs[so]->sections[se]->label->style = cho_style_new_from_config(SF_LABEL); li = 0; songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *)); diff --git a/todo b/todo @@ -1,16 +1,17 @@ +# parser 'image' directive https://chordpro.org/chordpro/directives-image/ metadata directives %{blabla} in lyrics, chords and annotations conditional metadata directives don't forget key, key_actual, key_from +grid chords define chords chord diagrams strict and relaxed parsing makes no difference!? make parser bulletproof try to detect invalid input as much as possible -parse environment directive value when: label="Verse 1" # pdf output break lines when too long