lorid

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

commit fbfb37c5440ea4d836d3742f89a32919d8e43349
parent 78d4be4302a623b81db0ccb4f09831964dc2a690
Author: nibo <nibo@relim.de>
Date:   Thu, 20 Feb 2025 20:20:59 +0100

Continue implementing metadata substitution

Diffstat:
Msrc/chordpro.c | 139++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/chordpro.h | 8++++++++
2 files changed, 139 insertions(+), 8 deletions(-)

diff --git a/src/chordpro.c b/src/chordpro.c @@ -1772,14 +1772,133 @@ cho_metadata_load_default(struct ChoContext *ctx) return meta; } -/* static char * +static char * cho_metadata_substitution_parse( + struct ChoContext *ctx, const char *str, struct ChoMetadata **metadata, enum State state_before_substitution ) { -} */ + enum MetadataSubstitutionState state = MSS_NAME; + enum AttrValueSyntax avs = -1; + char name[128]; + name[0] = 0; + char value[4096]; + value[0] = 0; + char prev_c = 0; + char c = 0; + int n = 0; + for (; *str; str++) { + c = *str; + switch (state) { + case MSS_NAME: { + if (c == '=') { + name[n] = 0; + n = 0; + state = MSS_VALUE; + break; + } + if (prev_c != '\\' && c == '|') { + name[n] = 0; + n = 0; + state = MSS_TRUE_TEXT; + break; + } + name[n] = c; + n++; + break; + } + case MSS_VALUE: { + if (avs == -1) { + if (is_whitespace(c)) { + cho_log(ctx, LOG_ERR, "Whitespace character after equals sign is invalid."); + return NULL; + } + if (c == '|') { + cho_log(ctx, LOG_ERR, "If you specify an equals sign then you have to provide a value."); + return NULL; + } + if (c == '\'') { + avs = AVS_APOSTROPHE; + } else if (c == '"') { + avs = AVS_QUOTATION_MARK; + } else { + avs = AVS_UNQUOTED; + value[n] = c; + n++; + } + break; + } + if (prev_c != '\\' && c == '|') { + if (avs == AVS_APOSTROPHE) { + cho_log(ctx, LOG_ERR, "Can't find a matching '\''."); + return NULL; + } + if (avs == AVS_QUOTATION_MARK) { + cho_log(ctx, LOG_ERR, "Can't find a matching '\"'."); + return NULL; + } + if (avs == AVS_UNQUOTED) { + value[n] = 0; + n = 0; + state = MSS_TRUE_TEXT; + break; + } + if (avs == -1) { + state = MSS_TRUE_TEXT; + break; + } + break; + } + if ( + (avs == AVS_APOSTROPHE && c == '\'') || + (avs == AVS_QUOTATION_MARK && c == '"') || + (avs == AVS_UNQUOTED && c == ' ') + ) { + value[n] = 0; + n = 0; + state = MSS_WAIT_FOR_PIPE; + break; + } + value[n] = c; + n++; + break; + } + case MSS_TRUE_TEXT: { + if (prev_c != '\\' && c == '|') { + state = MSS_FALSE_TEXT; + break; + } + break; + } + case MSS_FALSE_TEXT: { + break; + } + case MSS_WAIT_FOR_PIPE: { + if (is_whitespace(c)) { + break; + } + if (c == '|') { + state = MSS_TRUE_TEXT; + break; + } + break; + } + } + prev_c = c; + } + if (state == MSS_NAME) { + name[n] = 0; + } else if (state == MSS_VALUE && avs == AVS_UNQUOTED) { + value[n] = 0; + } + if (name[0] != 0) + printf("name '%s'\n", name); + if (value[0] != 0) + printf("value '%s'\n", value); + return ""; +} static bool transposition_parse(const char *str, int *transpose) @@ -5509,16 +5628,20 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c break; } case STATE_METADATA_SUBSTITUTION: { - if (c == '}') { + if (prev_c != '\\' && c == '}') { if (ctx.nested_level == 0) { metadata_substitution[ctx.ms] = 0; ctx.ms = 0; - printf("substitution: '%s'\n", metadata_substitution); - /* char *substituted = cho_metadata_substitution_parse( + char *substituted = cho_metadata_substitution_parse( + &ctx, metadata_substitution, - songs[so]->metadata, - state_before_metadata_substitution - ); */ + ctx.songs[ctx.so]->metadata, + ctx.state_before_metadata_substitution + ); + if (!substituted) { + LOG_DEBUG("cho_metadata_substitution_parse failed."); + return NULL; + } // Append 'substituted' to whatever text ctx.state = ctx.state_before_metadata_substitution; break; diff --git a/src/chordpro.h b/src/chordpro.h @@ -30,6 +30,14 @@ enum ChordDiagramState { CDS_COPY }; +enum MetadataSubstitutionState { + MSS_NAME, + MSS_VALUE, + MSS_TRUE_TEXT, + MSS_FALSE_TEXT, + MSS_WAIT_FOR_PIPE +}; + enum ChordDirective { TRANSPOSE, DEFINE /* , CHORD */ };