commit ed845e75a1e73877454fb70958bb06a437f23825
parent 9ec1d5d00ac60396aedb12f15213b61406c716ab
Author: nibo <nibo@relim.de>
Date: Wed, 19 Feb 2025 20:02:26 +0100
Start refactoring 'cho_songs_parse'
First refactor by creating 'struct ChoContext'
and after that I can continue with the metadata
substitution.
Diffstat:
3 files changed, 872 insertions(+), 819 deletions(-)
diff --git a/src/chordpro.c b/src/chordpro.c
@@ -149,8 +149,8 @@ static enum TextType g_current_ttype = TT_TEXT;
static enum TextType g_prev_ttype = TT_TEXT;
static struct Config *g_config = NULL;
static const char *g_chordpro_filepath = NULL;
-static int *g_transpose_history = NULL;
-static int *g_transpose = NULL;
+// static int *g_transpose_history = NULL;
+// static int *g_transpose = NULL;
static size_t g_line_number = 1;
struct ChoImage **g_image_assets = NULL;
static int g_ia = 0;
@@ -1802,9 +1802,9 @@ transposition_parse(const char *str, int *transpose)
}
static char *
-transposition_calc_chord_root(int index, enum NoteType type)
+transposition_calc_chord_root(struct ChoContext *ctx, int index, enum NoteType type)
{
- int transpose = *g_transpose;
+ int transpose = *ctx->transpose;
if (transpose == 0) {
switch (type) {
case NT_NOTE:
@@ -2008,7 +2008,7 @@ cho_chords_free(struct ChoChord **chords)
/* returns how many bytes make up the root; returns 0 if no root was found */
static int
-cho_chord_root_parse(const char *str, struct ChoChord *chord)
+cho_chord_root_parse(struct ChoContext *ctx, const char *str, struct ChoChord *chord)
{
const char *note = NULL;
const char *sharp = NULL;
@@ -2018,7 +2018,7 @@ cho_chord_root_parse(const char *str, struct ChoChord *chord)
for (i = 0; i<7; i++) {
sharp = g_config->parser->notes[i]->sharp;
if (sharp && str_starts_with(str, sharp)) {
- transposed_root = transposition_calc_chord_root(i, NT_SHARP);
+ transposed_root = transposition_calc_chord_root(ctx, i, NT_SHARP);
if (!transposed_root) {
LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
@@ -2028,7 +2028,7 @@ cho_chord_root_parse(const char *str, struct ChoChord *chord)
}
flat = g_config->parser->notes[i]->flat;
if (flat && str_starts_with(str, flat)) {
- transposed_root = transposition_calc_chord_root(i, NT_FLAT);
+ transposed_root = transposition_calc_chord_root(ctx, i, NT_FLAT);
if (!transposed_root) {
LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
@@ -2038,7 +2038,7 @@ cho_chord_root_parse(const char *str, struct ChoChord *chord)
}
note = g_config->parser->notes[i]->note;
if (str_starts_with(str, note)) {
- transposed_root = transposition_calc_chord_root(i, NT_NOTE);
+ transposed_root = transposition_calc_chord_root(ctx, i, NT_NOTE);
if (!transposed_root) {
LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
@@ -2138,14 +2138,14 @@ cho_chord_bass_parse(const char *str, struct ChoChord *chord)
}
static struct ChoChord *
-cho_chord_parse(const char *str)
+cho_chord_parse(struct ChoContext *ctx, const char *str)
{
struct ChoChord *chord = cho_chord_new();
size_t str_len = strlen(str);
size_t bytes_parsed = 0;
int ret;
chord->name = strdup(str);
- ret = cho_chord_root_parse(str, chord);
+ ret = cho_chord_root_parse(ctx, str, chord);
if (ret == 0) {
return chord;
}
@@ -4026,16 +4026,72 @@ cho_directive_label_parse(const char *directive_name, const char *str)
return label_name;
}
+static bool
+cho_context_init(struct ChoContext *ctx)
+{
+ ctx->is_chord_already_initialized = false;
+ ctx->is_maybe_end_of_tab_directive = false;
+ ctx->directive_has_tag = false;
+ ctx->state = STATE_LYRICS;
+ ctx->state_before_comment = STATE_LYRICS;
+ ctx->state_before_tag = STATE_LYRICS;
+ ctx->state_before_backslash = STATE_LYRICS;
+ ctx->state_before_metadata_substitution = STATE_LYRICS;
+ ctx->ann = 0;
+ ctx->at = 0;
+ ctx->atn = 0;
+ ctx->atv = 0;
+ ctx->ch = 0;
+ ctx->dia = 0;
+ ctx->dn = 0;
+ ctx->dv = 0;
+ ctx->li = 0;
+ ctx->lia = 0;
+ ctx->lii = 0;
+ ctx->m = 11;
+ ctx->ms = 0;
+ ctx->se = 0;
+ ctx->so = 0;
+ ctx->t = 0;
+ ctx->ta = -1;
+ ctx->te = 0;
+ ctx->th = 0;
+ ctx->nested_level = 0;
+ ctx->tags = NULL;
+
+ ctx->transpose_history = emalloc((ctx->th+1) * sizeof(int *));
+ ctx->transpose_history[ctx->th] = 0;
+ ctx->transpose = &ctx->transpose_history[ctx->th];
+ ctx->th++;
+
+ ctx->songs = emalloc(sizeof(struct ChoSong *));
+ ctx->songs[ctx->so] = cho_song_new();
+ if (!ctx->songs[ctx->so]) {
+ LOG_DEBUG("cho_song_new failed.");
+ return false;
+ }
+ ctx->songs[ctx->so]->sections = emalloc((ctx->se+1) * sizeof(struct ChoSection *));
+ ctx->songs[ctx->so]->sections[ctx->se] = cho_section_new();
+ ctx->songs[ctx->so]->sections[ctx->se]->lines = emalloc(sizeof(struct ChoLine *));
+ ctx->songs[ctx->so]->sections[ctx->se]->lines[ctx->li] = cho_line_new();
+ return true;
+}
+
struct ChoSong **
cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
{
- g_config = config;
- g_chordpro_filepath = chordpro_filepath;
- bool is_chord_already_initialized = false;
- bool is_maybe_end_of_tab_directive = false;
- bool directive_has_tag = false;
- char buf = 0;
- char prev_buf = '\n';
+ enum AttrValueSyntax avs = -1;
+ struct ChoStyle *tag_style;
+ struct StyleProperty sprop;
+ struct ChoChord *tmp_chord;
+ struct ChoSection *chorus;
+ struct ChoImage *image;
+ struct ChordDiagram *diagram;
+ struct ChoDirective *directive;
+ struct ChoMetadata *metadata;
+ struct ChoLine ***lines;
+ struct ChoContext ctx;
+ char *label, *metadata_value, *stripped_directive_value;
char directive_name[128];
char directive_value[4096];
char chord[15];
@@ -4043,184 +4099,142 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
char tag_end[6];
char custom_directive[64];
char metadata_substitution[4096];
- char *label, *metadata_value, *stripped_directive_value;
- enum State state = STATE_LYRICS;
- enum State state_before_comment = STATE_LYRICS;
- enum State state_before_tag = STATE_LYRICS;
- enum State state_before_backslash = STATE_LYRICS;
- enum State state_before_metadata_substitution = STATE_LYRICS;
- int dn = 0;
- int dv = 0;
- int ch = 0;
- int c = 0;
- // Not zero by default because there are default metadata entries
- int m = 11;
- int ly = 0;
- int t = 0;
- int so = 0;
- int se = 0;
- int li = 0;
- int ta = -1;
- int te = 0;
- int at = 0;
- int atn = 0;
- int atv = 0;
- int ann = 0;
- int text_above_pos;
+ char c = 0;
+ char prev_c = '\n';
int transpose;
- int th = 0;
- int dia = 0;
- int ms = 0;
- int nested_level = 0;
size_t read;
- g_transpose_history = erealloc(g_transpose_history, (th+1) * sizeof(int *));
- g_transpose_history[th] = 0;
- g_transpose = &g_transpose_history[th];
- th++;
- enum AttrValueSyntax avs = -1;
- struct ChoDirective *directive = NULL;
- struct ChoMetadata *metadata = NULL;
- struct ChoLine ***lines;
- struct ChoSong **songs = emalloc(sizeof(struct ChoSong *));
- songs[so] = cho_song_new();
- if (!songs[so]) {
- LOG_DEBUG("cho_song_new failed.");
+
+ g_config = config;
+ g_chordpro_filepath = chordpro_filepath;
+
+ if (!cho_context_init(&ctx)) {
+ LOG_DEBUG("cho_context_init failed.");
return NULL;
}
- songs[so]->sections = emalloc((se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *));
- songs[so]->sections[se]->lines[li] = cho_line_new();
- lines = &songs[so]->sections[se]->lines;
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- songs[so]->present_text_types[TT_TOC] = config->output->toc->show;
- struct Tag **tags = NULL;
- struct ChoStyle *tag_style;
- struct StyleProperty sprop;
- struct ChoChord *tmp_chord;
- struct ChoSection *chorus;
- struct ChoImage *image;
- struct ChordDiagram *diagram;
+
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ ctx.songs[ctx.so]->present_text_types[TT_TOC] = config->output->toc->show;
while (feof(fp) == 0) {
- read = fread(&buf, 1, 1, fp);
+ read = fread(&c, 1, 1, fp);
if (read == 1) {
- if (buf == '\n') {
+ if (c == '\n') {
g_line_number++;
}
// printf("state: %s, buf: %c\n", state_enums[state], buf);
- if (buf == '\r') {
+ if (c == '\r') {
continue;
}
- switch (state) {
+ switch (ctx.state) {
case STATE_LYRICS: {
- if (prev_buf == '\n' && buf == '#') {
- state_before_comment = STATE_LYRICS;
- state = STATE_COMMENT;
+ if (prev_c == '\n' && c == '#') {
+ ctx.state_before_comment = STATE_LYRICS;
+ ctx.state = STATE_COMMENT;
break;
}
- if (prev_buf == '\n' && buf == '{') {
- state = STATE_DIRECTIVE_NAME;
+ if (prev_c == '\n' && c == '{') {
+ ctx.state = STATE_DIRECTIVE_NAME;
break;
}
- if (buf == '[') {
- state = STATE_CHORD;
+ if (c == '[') {
+ ctx.state = STATE_CHORD;
break;
}
- if (buf == '<') {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if (c == '<') {
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- te = 0;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- state_before_tag = STATE_LYRICS;
- state = STATE_MARKUP_TAG;
+ ctx.te = 0;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ ctx.state_before_tag = STATE_LYRICS;
+ ctx.state = STATE_MARKUP_TAG;
break;
}
- if (buf == '%') {
- state_before_metadata_substitution = STATE_LYRICS;
- state = STATE_MAYBE_METADATA_SUBSTITUTION;
+ if (c == '%') {
+ ctx.state_before_metadata_substitution = STATE_LYRICS;
+ ctx.state = STATE_MAYBE_METADATA_SUBSTITUTION;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_LYRICS;
- state = STATE_BACKSLASH;
- te--; // INFO: This will later overwrite the backslash
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_LYRICS;
+ ctx.state = STATE_BACKSLASH;
+ ctx.te--; // INFO: This will later overwrite the backslash
break;
}
- if (ta > -1 && !tags[ta]->is_closed && strcmp(tags[ta]->name, "img")) {
+ if (ctx.ta > -1 && !ctx.tags[ctx.ta]->is_closed && strcmp(ctx.tags[ctx.ta]->name, "img")) {
cho_log(LOG_ERR, "Tag has to be closed on same line.");
return NULL;
}
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
- if (ly == 0) {
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ if (ctx.lii == 0) {
if (
- !(*lines)[li]->text_above &&
- (*lines)[li]->btype == BT_LINE
+ !(*lines)[ctx.li]->text_above &&
+ (*lines)[ctx.li]->btype == BT_LINE
) {
- free((*lines)[li]->items);
- free((*lines)[li]);
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ free((*lines)[ctx.li]->items);
+ free((*lines)[ctx.li]);
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
break;
}
}
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = NULL;
- ly = 0;
- te = 0;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = NULL;
- c = 0;
- li++;
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = NULL;
+ ctx.lii = 0;
+ ctx.te = 0;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = NULL;
+ ctx.lia = 0;
+ ctx.li++;
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
break;
}
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = buf;
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = c;
+ ctx.te++;
break;
}
case STATE_BACKSLASH: {
- if (!is_whitespace(buf)) {
+ if (!is_whitespace(c)) {
if (fseek(fp, -1, SEEK_CUR)) {
LOG_DEBUG("fseek failed.");
return NULL;
}
- state = state_before_backslash;
+ ctx.state = ctx.state_before_backslash;
break;
}
break;
}
case STATE_DIRECTIVE_NAME: {
- if (buf == '}') {
- directive_name[dn] = 0;
- dn = 0;
+ if (c == '}') {
+ directive_name[ctx.dn] = 0;
+ ctx.dn = 0;
directive = cho_directive_parse(directive_name);
/* printf(
"directive: '%s'\ndtype: %s, stype: %s, position: %s\n",
@@ -4235,127 +4249,127 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
memset(custom_directive, 0, sizeof(custom_directive));
strcpy(custom_directive, &directive_name[9]);
}
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- ly = 0;
- free((*lines)[li]);
- (*lines)[li] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- songs[so]->sections[se]->type = directive->stype;
- li = 0;
- lines = &songs[so]->sections[se]->lines;
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ ctx.lii = 0;
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ ctx.songs[ctx.so]->sections[ctx.se]->type = directive->stype;
+ ctx.li = 0;
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- songs[so]->present_text_types[directive->ttype] = true;
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ ctx.songs[ctx.so]->present_text_types[directive->ttype] = true;
break;
}
case POS_END: {
- if (directive->stype == songs[so]->sections[se]->type) {
+ if (directive->stype == ctx.songs[ctx.so]->sections[ctx.se]->type) {
if (directive->stype == ST_CUSTOM) {
if (strcmp(custom_directive, &directive_name[7]) != 0) {
break;
}
}
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- ly = 0;
- free((*lines)[li]);
- (*lines)[li] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- li = 0;
- lines = &songs[so]->sections[se]->lines;
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ ctx.lii = 0;
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ ctx.li = 0;
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
}
break;
}
case POS_NO: {
/* INFO: {chorus} */
- chorus = cho_find_previous_chorus(songs[so]->sections, se);
+ chorus = cho_find_previous_chorus(ctx.songs[ctx.so]->sections, ctx.se);
if (chorus) {
if (config->output->chorus->quote) {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
}
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = NULL;
- ly = 0;
- te = 0;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = NULL;
- c = 0;
- cho_line_free((*lines)[li]);
- (*lines)[li] = NULL;
- li = 0;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_copy(chorus);
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- lines = &songs[so]->sections[se]->lines;
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = NULL;
+ ctx.lii = 0;
+ ctx.te = 0;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = NULL;
+ ctx.lia = 0;
+ cho_line_free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.li = 0;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_copy(chorus);
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
} else {
if (chorus->label) {
label = strdup(chorus->label->text);
} else {
label = strdup(config->output->chorus->label);
}
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
g_current_ttype = TT_LABEL;
- (*lines)[li]->items[ly]->u.text->style = cho_style_new_default();
- (*lines)[li]->items[ly]->u.text->text = label;
- te += strlen(label);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = label;
+ ctx.te += strlen(label);
}
} else {
if (config->output->chorus->quote) {
cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously.");
}
label = strdup(config->output->chorus->label);
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
g_current_ttype = TT_LABEL;
- (*lines)[li]->items[ly]->u.text->style = cho_style_new_default();
- (*lines)[li]->items[ly]->u.text->text = label;
- te += strlen(label);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = label;
+ ctx.te += strlen(label);
}
break;
}
@@ -4376,40 +4390,40 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
return NULL;
case DT_PREAMBLE: {
// INFO: The only preamble directive is 'new_song'
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- free((*lines)[li]);
- (*lines)[li] = NULL;
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = NULL;
- songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *));
- songs[so]->diagrams[dia] = NULL;
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = NULL;
+ ctx.songs[ctx.so]->diagrams = erealloc(ctx.songs[ctx.so]->diagrams, (ctx.dia+1) * sizeof(struct ChordDiagram *));
+ ctx.songs[ctx.so]->diagrams[ctx.dia] = NULL;
if (!cho_style_reset_default()) {
LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
- so++;
- songs = erealloc(songs, (so+1) * sizeof(struct ChoSong *));
- songs[so] = cho_song_new();
- if (!songs[so]) {
+ ctx.so++;
+ ctx.songs = erealloc(ctx.songs, (ctx.so+1) * sizeof(struct ChoSong *));
+ ctx.songs[ctx.so] = cho_song_new();
+ if (!ctx.songs[ctx.so]) {
LOG_DEBUG("cho_song_new failed.");
return NULL;
}
- se = 0;
- li = 0;
- ly = 0;
- m = 11;
- dia = 0;
- songs[so]->sections = emalloc((se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- lines = &songs[so]->sections[se]->lines;
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ ctx.se = 0;
+ ctx.li = 0;
+ ctx.lii = 0;
+ ctx.m = 11;
+ ctx.dia = 0;
+ ctx.songs[ctx.so]->sections = emalloc((ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
break;
}
case DT_FONT: {
@@ -4438,8 +4452,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case DT_CHORD: {
switch (directive->ctype) {
case TRANSPOSE:
- g_transpose--;
- th--;
+ ctx.transpose--;
+ ctx.th--;
break;
case DEFINE:
cho_log(LOG_WARN, "Ignoring chord directive '%s' because it has no value.", directive_name);
@@ -4449,7 +4463,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
case DT_OUTPUT:
if (directive->btype != -1) {
- (*lines)[li]->btype = directive->btype;
+ (*lines)[ctx.li]->btype = directive->btype;
}
break;
case DT_EXTENSION:
@@ -4463,42 +4477,42 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
return NULL;
}
if (directive->stype == ST_TAB) {
- state = STATE_TAB;
+ ctx.state = STATE_TAB;
} else {
- state = STATE_LYRICS;
+ ctx.state = STATE_LYRICS;
}
cho_directive_free(directive);
directive = NULL;
break;
}
- if (buf == '{') {
+ if (c == '{') {
cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_DIRECTIVE_NAME;
- state = STATE_BACKSLASH;
- dn--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_DIRECTIVE_NAME;
+ ctx.state = STATE_BACKSLASH;
+ ctx.dn--;
break;
}
cho_log(LOG_ERR, "Can't have a newline in a directive name.");
return NULL;
}
- if (buf == ':' || buf == ' ') {
- directive_name[dn] = 0;
- dn = 0;
- state = STATE_DIRECTIVE_VALUE;
+ if (c == ':' || c == ' ') {
+ directive_name[ctx.dn] = 0;
+ ctx.dn = 0;
+ ctx.state = STATE_DIRECTIVE_VALUE;
break;
}
- directive_name[dn] = buf;
- dn++;
+ directive_name[ctx.dn] = c;
+ ctx.dn++;
break;
}
case STATE_DIRECTIVE_VALUE: {
- if (buf == '}') {
- directive_value[dv] = 0;
- dv = 0;
+ if (c == '}') {
+ directive_value[ctx.dv] = 0;
+ ctx.dv = 0;
stripped_directive_value = str_remove_leading_whitespace(directive_value);
directive = cho_directive_parse(directive_name);
/* printf(
@@ -4508,7 +4522,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
switch (directive->dtype) {
case DT_ENVIRONMENT: {
if (strlen(stripped_directive_value) > 0) {
- songs[so]->present_text_types[TT_LABEL] = true;
+ ctx.songs[ctx.so]->present_text_types[TT_LABEL] = true;
}
g_current_ttype = directive->ttype;
switch (directive->position) {
@@ -4517,16 +4531,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
memset(custom_directive, 0, sizeof(custom_directive));
strcpy(custom_directive, &directive_name[9]);
}
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- ly = 0;
- free((*lines)[li]);
- (*lines)[li] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- songs[so]->sections[se]->type = directive->stype;
- songs[so]->sections[se]->label = emalloc(sizeof(struct ChoText));
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ ctx.lii = 0;
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ ctx.songs[ctx.so]->sections[ctx.se]->type = directive->stype;
+ ctx.songs[ctx.so]->sections[ctx.se]->label = emalloc(sizeof(struct ChoText));
if (strstr(directive_value, "=")) {
label = cho_directive_label_parse(directive_name, directive_value);
if (!label) {
@@ -4534,137 +4548,137 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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->text = label;
+ ctx.songs[ctx.so]->sections[ctx.se]->label->text = label;
} else {
- songs[so]->sections[se]->label->text = strdup(stripped_directive_value);
+ ctx.songs[ctx.so]->sections[ctx.se]->label->text = strdup(stripped_directive_value);
}
- songs[so]->sections[se]->label->style = cho_style_new_from_config(TT_LABEL);
- if (directive_has_tag) {
- cho_style_complement(songs[so]->sections[se]->label->style, tags[ta]->style, &tags[ta]->style_presence);
- directive_has_tag = false;
+ ctx.songs[ctx.so]->sections[ctx.se]->label->style = cho_style_new_from_config(TT_LABEL);
+ if (ctx.directive_has_tag) {
+ cho_style_complement(ctx.songs[ctx.so]->sections[ctx.se]->label->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
+ ctx.directive_has_tag = false;
}
- li = 0;
- lines = &songs[so]->sections[se]->lines;
+ ctx.li = 0;
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- songs[so]->present_text_types[directive->ttype] = true;
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ ctx.songs[ctx.so]->present_text_types[directive->ttype] = true;
break;
}
case POS_END: {
- if (directive->stype == songs[so]->sections[se]->type) {
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- ly = 0;
- free((*lines)[li]);
- (*lines)[li] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- li = 0;
- lines = &songs[so]->sections[se]->lines;
+ if (directive->stype == ctx.songs[ctx.so]->sections[ctx.se]->type) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ ctx.lii = 0;
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ ctx.li = 0;
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
}
break;
}
case POS_NO: {
/* INFO: {chorus: ...} */
label = strdup(stripped_directive_value);
- chorus = cho_find_previous_chorus(songs[so]->sections, se);
+ chorus = cho_find_previous_chorus(ctx.songs[ctx.so]->sections, ctx.se);
if (chorus) {
if (config->output->chorus->quote) {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
}
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = NULL;
- ly = 0;
- te = 0;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = NULL;
- c = 0;
- cho_line_free((*lines)[li]);
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = NULL;
+ ctx.lii = 0;
+ ctx.te = 0;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = NULL;
+ ctx.lia = 0;
+ cho_line_free((*lines)[ctx.li]);
// songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = NULL;
- li = 0;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_copy(chorus);
- if (songs[so]->sections[se]->label) {
- free(songs[so]->sections[se]->label->text);
- songs[so]->sections[se]->label->text = label;
+ (*lines)[ctx.li] = NULL;
+ ctx.li = 0;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_copy(chorus);
+ if (ctx.songs[ctx.so]->sections[ctx.se]->label) {
+ free(ctx.songs[ctx.so]->sections[ctx.se]->label->text);
+ ctx.songs[ctx.so]->sections[ctx.se]->label->text = label;
} else {
g_current_ttype = TT_LABEL;
- songs[so]->sections[se]->label = cho_text_new();
- songs[so]->sections[se]->label->text = label;
+ ctx.songs[ctx.so]->sections[ctx.se]->label = cho_text_new();
+ ctx.songs[ctx.so]->sections[ctx.se]->label->text = label;
}
- if (directive_has_tag) {
- cho_style_complement(songs[so]->sections[se]->label->style, tags[ta]->style, &tags[ta]->style_presence);
- directive_has_tag = false;
+ if (ctx.directive_has_tag) {
+ cho_style_complement(ctx.songs[ctx.so]->sections[ctx.se]->label->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
+ ctx.directive_has_tag = false;
}
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- lines = &songs[so]->sections[se]->lines;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
} else {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
g_current_ttype = TT_LABEL;
- (*lines)[li]->items[ly]->u.text->style = cho_style_new_default();
- (*lines)[li]->items[ly]->u.text->text = label;
- if (directive_has_tag) {
- cho_style_complement((*lines)[li]->items[ly]->u.text->style, tags[ta]->style, &tags[ta]->style_presence);
- directive_has_tag = false;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = label;
+ if (ctx.directive_has_tag) {
+ cho_style_complement((*lines)[ctx.li]->items[ctx.lii]->u.text->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
+ ctx.directive_has_tag = false;
}
- te += strlen(label);
+ ctx.te += strlen(label);
}
} else {
if (config->output->chorus->quote) {
cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously.");
}
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
g_current_ttype = TT_LABEL;
- (*lines)[li]->items[ly]->u.text->style = cho_style_new_default();
- (*lines)[li]->items[ly]->u.text->text = label;
- if (directive_has_tag) {
- cho_style_complement((*lines)[li]->items[ly]->u.text->style, tags[ta]->style, &tags[ta]->style_presence);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = label;
+ if (ctx.directive_has_tag) {
+ cho_style_complement((*lines)[ctx.li]->items[ctx.lii]->u.text->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
}
- te += strlen(label);
+ ctx.te += strlen(label);
}
break;
}
@@ -4683,22 +4697,22 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
switch (directive->meta) {
case TITLE:
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = cho_metadata_new();
- songs[so]->metadata[m]->name = strdup("title");
- songs[so]->metadata[m]->value = metadata_value;
- cho_style_free(songs[so]->metadata[m]->style);
- songs[so]->metadata[m]->style = cho_style_copy(directive->style);
- songs[so]->present_text_types[TT_TITLE] = true;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = cho_metadata_new();
+ ctx.songs[ctx.so]->metadata[ctx.m]->name = strdup("title");
+ ctx.songs[ctx.so]->metadata[ctx.m]->value = metadata_value;
+ cho_style_free(ctx.songs[ctx.so]->metadata[ctx.m]->style);
+ ctx.songs[ctx.so]->metadata[ctx.m]->style = cho_style_copy(directive->style);
+ ctx.songs[ctx.so]->present_text_types[TT_TITLE] = true;
break;
case SUBTITLE:
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = cho_metadata_new();
- songs[so]->metadata[m]->name = strdup("subtitle");
- songs[so]->metadata[m]->value = metadata_value;
- cho_style_free(songs[so]->metadata[m]->style);
- songs[so]->metadata[m]->style = cho_style_copy(directive->style);
- songs[so]->present_text_types[TT_SUBTITLE] = true;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = cho_metadata_new();
+ ctx.songs[ctx.so]->metadata[ctx.m]->name = strdup("subtitle");
+ ctx.songs[ctx.so]->metadata[ctx.m]->value = metadata_value;
+ cho_style_free(ctx.songs[ctx.so]->metadata[ctx.m]->style);
+ ctx.songs[ctx.so]->metadata[ctx.m]->style = cho_style_copy(directive->style);
+ ctx.songs[ctx.so]->present_text_types[TT_SUBTITLE] = true;
break;
default:
if (!strcmp(directive_name, "meta")) {
@@ -4707,46 +4721,46 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
LOG_DEBUG("cho_metadata_split failed.");
return NULL;
}
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = metadata;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = metadata;
free(metadata_value);
} else {
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = cho_metadata_new();
- songs[so]->metadata[m]->name = strdup(directive_name);
- songs[so]->metadata[m]->value = metadata_value;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = cho_metadata_new();
+ ctx.songs[ctx.so]->metadata[ctx.m]->name = strdup(directive_name);
+ ctx.songs[ctx.so]->metadata[ctx.m]->value = metadata_value;
}
}
- if (directive_has_tag) {
- cho_style_complement(songs[so]->metadata[m]->style, tags[ta]->style, &tags[ta]->style_presence);
- directive_has_tag = false;
+ if (ctx.directive_has_tag) {
+ cho_style_complement(ctx.songs[ctx.so]->metadata[ctx.m]->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
+ ctx.directive_has_tag = false;
}
- m++;
+ ctx.m++;
break;
}
case DT_FORMATTING: {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
- (*lines)[li]->items[ly]->u.text->style = cho_style_copy(directive->style);
- (*lines)[li]->items[ly]->u.text->text = strdup(stripped_directive_value);
- if (directive_has_tag) {
- cho_style_complement((*lines)[li]->items[ly]->u.text->style, tags[ta]->style, &tags[ta]->style_presence);
- directive_has_tag = false;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_copy(directive->style);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = strdup(stripped_directive_value);
+ if (ctx.directive_has_tag) {
+ cho_style_complement((*lines)[ctx.li]->items[ctx.lii]->u.text->style, ctx.tags[ctx.ta]->style, &ctx.tags[ctx.ta]->style_presence);
+ ctx.directive_has_tag = false;
}
- te += strlen(stripped_directive_value);
- songs[so]->present_text_types[directive->ttype] = true;
+ ctx.te += strlen(stripped_directive_value);
+ ctx.songs[ctx.so]->present_text_types[directive->ttype] = true;
break;
}
case DT_IMAGE: {
@@ -4765,17 +4779,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
g_image_assets[g_ia] = image;
g_ia++;
} else {
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- te = 0;
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ ctx.te = 0;
}
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
- cho_text_free((*lines)[li]->items[ly]->u.text);
- (*lines)[li]->items[ly]->is_text = false;
- (*lines)[li]->items[ly]->u.image = image;
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
+ cho_text_free((*lines)[ctx.li]->items[ctx.lii]->u.text);
+ (*lines)[ctx.li]->items[ctx.lii]->is_text = false;
+ (*lines)[ctx.li]->items[ctx.lii]->u.image = image;
}
break;
}
@@ -4831,20 +4845,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
cho_log(LOG_ERR, "Directive 'transpose' has an invalid value.");
return NULL;
}
- g_transpose_history = erealloc(g_transpose_history, (th+1) * sizeof(int *));
- g_transpose_history[th] = g_transpose_history[th-1] + transpose;
- g_transpose = &g_transpose_history[th];
- th++;
+ ctx.transpose_history = erealloc(ctx.transpose_history, (ctx.th+1) * sizeof(int *));
+ ctx.transpose_history[ctx.th] = ctx.transpose_history[ctx.th-1] + transpose;
+ ctx.transpose = &ctx.transpose_history[ctx.th];
+ ctx.th++;
break;
case DEFINE:
- diagram = cho_chord_diagram_parse(directive_value, songs[so]->diagrams, dia);
+ diagram = cho_chord_diagram_parse(directive_value, ctx.songs[ctx.so]->diagrams, ctx.dia);
if (!diagram) {
LOG_DEBUG("cho_chord_diagram_parse failed.");
return NULL;
}
- songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *));
- songs[so]->diagrams[dia] = diagram;
- dia++;
+ ctx.songs[ctx.so]->diagrams = erealloc(ctx.songs[ctx.so]->diagrams, (ctx.dia+1) * sizeof(struct ChordDiagram *));
+ ctx.songs[ctx.so]->diagrams[ctx.dia] = diagram;
+ ctx.dia++;
break;
}
break;
@@ -4866,278 +4880,278 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
free(stripped_directive_value);
cho_directive_free(directive);
directive = NULL;
- state = STATE_LYRICS;
+ ctx.state = STATE_LYRICS;
break;
}
- if (buf == '<') {
- state_before_tag = STATE_DIRECTIVE_VALUE;
- state = STATE_MARKUP_TAG;
+ if (c == '<') {
+ ctx.state_before_tag = STATE_DIRECTIVE_VALUE;
+ ctx.state = STATE_MARKUP_TAG;
break;
}
- if (buf == '{') {
+ if (c == '{') {
cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_DIRECTIVE_VALUE;
- state = STATE_BACKSLASH;
- dv--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_DIRECTIVE_VALUE;
+ ctx.state = STATE_BACKSLASH;
+ ctx.dv--;
break;
}
cho_log(LOG_ERR, "Newline character inside a directive value is invalid.");
return NULL;
}
- if (dv > 4094) {
+ if (ctx.dv > 4094) {
cho_log(LOG_ERR, "Directive value can't be greater than 4095 bytes.");
return NULL;
}
- directive_value[dv] = buf;
- dv++;
+ directive_value[ctx.dv] = c;
+ ctx.dv++;
break;
}
case STATE_CHORD: {
- if (buf == ']') {
- chord[ch] = 0;
- ch = 0;
+ if (c == ']') {
+ chord[ctx.ch] = 0;
+ ctx.ch = 0;
g_prev_ttype = g_current_ttype;
g_current_ttype = TT_CHORD;
- if (is_chord_already_initialized) {
- text_above_pos = cho_line_compute_text_above_position(songs[so]->sections[se]->lines[li], ly, te);
- (*lines)[li]->text_above[c]->position = text_above_pos;
- tmp_chord = cho_chord_parse(chord);
- cho_chord_complete((*lines)[li]->text_above[c]->u.chord, tmp_chord);
- if (!(*lines)[li]->text_above[c]->u.chord->is_canonical) {
- cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[li]->text_above[c]->u.chord->name);
+ if (ctx.is_chord_already_initialized) {
+ ctx.text_above_pos = cho_line_compute_text_above_position(ctx.songs[ctx.so]->sections[ctx.se]->lines[ctx.li], ctx.lii, ctx.te);
+ (*lines)[ctx.li]->text_above[ctx.lia]->position = ctx.text_above_pos;
+ tmp_chord = cho_chord_parse(&ctx, chord);
+ cho_chord_complete((*lines)[ctx.li]->text_above[ctx.lia]->u.chord, tmp_chord);
+ if (!(*lines)[ctx.li]->text_above[ctx.lia]->u.chord->is_canonical) {
+ cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->name);
}
cho_chord_free(tmp_chord);
- is_chord_already_initialized = false;
+ ctx.is_chord_already_initialized = false;
} else {
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove));
- (*lines)[li]->text_above[c]->is_chord = true;
- text_above_pos = cho_line_compute_text_above_position((*lines)[li], ly, te);
- (*lines)[li]->text_above[c]->position = text_above_pos;
- (*lines)[li]->text_above[c]->u.chord = cho_chord_parse(chord);
- if (!(*lines)[li]->text_above[c]->u.chord->is_canonical) {
- cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[li]->text_above[c]->u.chord->name);
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = emalloc(sizeof(struct ChoLineItemAbove));
+ (*lines)[ctx.li]->text_above[ctx.lia]->is_chord = true;
+ ctx.text_above_pos = cho_line_compute_text_above_position((*lines)[ctx.li], ctx.lii, ctx.te);
+ (*lines)[ctx.li]->text_above[ctx.lia]->position = ctx.text_above_pos;
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord = cho_chord_parse(&ctx, chord);
+ if (!(*lines)[ctx.li]->text_above[ctx.lia]->u.chord->is_canonical) {
+ cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->name);
}
}
- songs[so]->present_text_types[TT_CHORD] = true;
+ ctx.songs[ctx.so]->present_text_types[TT_CHORD] = true;
memset(chord, 0, strlen(chord));
- c++;
+ ctx.lia++;
g_current_ttype = g_prev_ttype;
- state = STATE_LYRICS;
+ ctx.state = STATE_LYRICS;
break;
}
- if (prev_buf == '[' && buf == '*') {
+ if (prev_c == '[' && c == '*') {
g_prev_ttype = g_current_ttype;
g_current_ttype = TT_ANNOT;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove));
- (*lines)[li]->text_above[c]->is_chord = false;
- text_above_pos = cho_line_compute_text_above_position((*lines)[li], ly, te);
- (*lines)[li]->text_above[c]->position = text_above_pos;
- (*lines)[li]->text_above[c]->u.annot = cho_text_new();
- state = STATE_ANNOTATION;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = emalloc(sizeof(struct ChoLineItemAbove));
+ (*lines)[ctx.li]->text_above[ctx.lia]->is_chord = false;
+ ctx.text_above_pos = cho_line_compute_text_above_position((*lines)[ctx.li], ctx.lii, ctx.te);
+ (*lines)[ctx.li]->text_above[ctx.lia]->position = ctx.text_above_pos;
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot = cho_text_new();
+ ctx.state = STATE_ANNOTATION;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_CHORD;
- state = STATE_BACKSLASH;
- ch--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_CHORD;
+ ctx.state = STATE_BACKSLASH;
+ ctx.ch--;
break;
}
cho_log(LOG_ERR, "Newline character inside a chord is invalid.");
return NULL;
}
- if (buf == '[') {
+ if (c == '[') {
cho_log(LOG_ERR, "Can't start a new chord/annotation if the previous one is not yet closed.");
return NULL;
}
- if (buf == '<') {
- if (prev_buf == '[') {
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove));
- (*lines)[li]->text_above[c]->is_chord = true;
- (*lines)[li]->text_above[c]->u.chord = cho_chord_new();
- is_chord_already_initialized = true;
+ if (c == '<') {
+ if (prev_c == '[') {
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = emalloc(sizeof(struct ChoLineItemAbove));
+ (*lines)[ctx.li]->text_above[ctx.lia]->is_chord = true;
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord = cho_chord_new();
+ ctx.is_chord_already_initialized = true;
}
- state_before_tag = STATE_CHORD;
- state = STATE_MARKUP_TAG;
+ ctx.state_before_tag = STATE_CHORD;
+ ctx.state = STATE_MARKUP_TAG;
break;
}
- chord[ch] = buf;
- ch++;
+ chord[ctx.ch] = c;
+ ctx.ch++;
break;
}
case STATE_ANNOTATION: {
- if (buf == ']') {
- (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
- (*lines)[li]->text_above[c]->u.annot->text[ann] = 0;
- songs[so]->present_text_types[TT_ANNOT] = true;
- ann = 0;
- c++;
+ if (c == ']') {
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text = erealloc((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text, (ctx.ann+1) * sizeof(char));
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text[ctx.ann] = 0;
+ ctx.songs[ctx.so]->present_text_types[TT_ANNOT] = true;
+ ctx.ann = 0;
+ ctx.lia++;
g_current_ttype = g_prev_ttype;
- state = STATE_LYRICS;
+ ctx.state = STATE_LYRICS;
break;
}
- if (buf == '<') {
- state_before_tag = STATE_ANNOTATION;
- state = STATE_MARKUP_TAG;
+ if (c == '<') {
+ ctx.state_before_tag = STATE_ANNOTATION;
+ ctx.state = STATE_MARKUP_TAG;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_ANNOTATION;
- state = STATE_BACKSLASH;
- ann--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_ANNOTATION;
+ ctx.state = STATE_BACKSLASH;
+ ctx.ann--;
break;
}
cho_log(LOG_ERR, "Newline character inside an annotation is invalid.");
return NULL;
}
- (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
- (*lines)[li]->text_above[c]->u.annot->text[ann] = buf;
- ann++;
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text = erealloc((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text, (ctx.ann+1) * sizeof(char));
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text[ctx.ann] = c;
+ ctx.ann++;
break;
}
case STATE_TAB: {
// INFO: similar to STATE_LYRICS but without markup and directives
- if (prev_buf == '\n' && buf == '#') {
- state_before_comment = STATE_TAB;
- state = STATE_COMMENT;
+ if (prev_c == '\n' && c == '#') {
+ ctx.state_before_comment = STATE_TAB;
+ ctx.state = STATE_COMMENT;
break;
}
- if (is_maybe_end_of_tab_directive) {
- if (buf == '}') {
- directive_name[dn] = 0;
- dn = 0;
- is_maybe_end_of_tab_directive = false;
+ if (ctx.is_maybe_end_of_tab_directive) {
+ if (c == '}') {
+ directive_name[ctx.dn] = 0;
+ ctx.dn = 0;
+ ctx.is_maybe_end_of_tab_directive = false;
if (!strcmp(directive_name, "end_of_tab") || !strcmp(directive_name, "eot")) {
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- ly = 0;
- free((*lines)[li]);
- (*lines)[li] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = cho_section_new();
- li = 0;
- lines = &songs[so]->sections[se]->lines;
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ ctx.lii = 0;
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = cho_section_new();
+ ctx.li = 0;
+ lines = &ctx.songs[ctx.so]->sections[ctx.se]->lines;
*lines = emalloc(sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = emalloc(sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
g_current_ttype = TT_TEXT;
- state = STATE_LYRICS;
+ ctx.state = STATE_LYRICS;
break;
} else {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = '{';
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = '{';
+ ctx.te++;
char *k;
- for (k = (char *)&directive_name; *k; k++, te++) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = *k;
+ for (k = (char *)&directive_name; *k; k++, ctx.te++) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = *k;
}
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = '}';
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = '}';
+ ctx.te++;
}
break;
}
- if (buf == ' ' || buf == ':') {
- directive_name[dn] = 0;
- dn = 0;
- is_maybe_end_of_tab_directive = false;
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = '{';
- te++;
+ if (c == ' ' || c == ':') {
+ directive_name[ctx.dn] = 0;
+ ctx.dn = 0;
+ ctx.is_maybe_end_of_tab_directive = false;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = '{';
+ ctx.te++;
char *k;
- for (k = (char *)&directive_name; *k; k++, te++) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = *k;
+ for (k = (char *)&directive_name; *k; k++, ctx.te++) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = *k;
}
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = buf;
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = c;
+ ctx.te++;
break;
}
- directive_name[dn] = buf;
- dn++;
+ directive_name[ctx.dn] = c;
+ ctx.dn++;
break;
}
- if (prev_buf == '\n' && buf == '{') {
- is_maybe_end_of_tab_directive = true;
+ if (prev_c == '\n' && c == '{') {
+ ctx.is_maybe_end_of_tab_directive = true;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_TAB;
- state = STATE_BACKSLASH;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_TAB;
+ ctx.state = STATE_BACKSLASH;
// INFO: This will later overwrite the backslash
- te--;
+ ctx.te--;
break;
}
- if (ta > -1 && !tags[ta]->is_closed && strcmp(tags[ta]->name, "img")) {
+ if (ctx.ta > -1 && !ctx.tags[ctx.ta]->is_closed && strcmp(ctx.tags[ctx.ta]->name, "img")) {
cho_log(LOG_ERR, "Tag has to be closed on same line.");
return NULL;
}
- if ((*lines)[li]->items[ly]->is_text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) {
- cho_line_item_free((*lines)[li]->items[ly]);
- if (ly == 0) {
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ if (strlen((*lines)[ctx.li]->items[ctx.lii]->u.text->text) == 0) {
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ if (ctx.lii == 0) {
if (
- !(*lines)[li]->text_above &&
- (*lines)[li]->btype == BT_LINE
+ !(*lines)[ctx.li]->text_above &&
+ (*lines)[ctx.li]->btype == BT_LINE
) {
- free((*lines)[li]->items);
- free((*lines)[li]);
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ free((*lines)[ctx.li]->items);
+ free((*lines)[ctx.li]);
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
break;
}
}
} else {
- ly++;
+ ctx.lii++;
}
} else {
- ly++;
+ ctx.lii++;
}
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = NULL;
- ly = 0;
- te = 0;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = NULL;
- c = 0;
- li++;
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = cho_line_new();
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = NULL;
+ ctx.lii = 0;
+ ctx.te = 0;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = NULL;
+ ctx.lia = 0;
+ ctx.li++;
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = cho_line_new();
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
break;
}
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = buf;
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = c;
+ ctx.te++;
break;
}
case STATE_MARKUP_TAG: {
- if (buf == '/') {
- state = STATE_MARKUP_TAG_END;
+ if (c == '/') {
+ ctx.state = STATE_MARKUP_TAG_END;
break;
}
- ta++;
- tags = erealloc(tags, (ta+1) * sizeof(struct Tag *));
- tags[ta] = cho_tag_new();
- state = STATE_MARKUP_TAG_START;
+ ctx.ta++;
+ ctx.tags = erealloc(ctx.tags, (ctx.ta+1) * sizeof(struct Tag *));
+ ctx.tags[ctx.ta] = cho_tag_new();
+ ctx.state = STATE_MARKUP_TAG_START;
if (fseek(fp, -1, SEEK_CUR)) {
LOG_DEBUG("fseek failed.");
return NULL;
@@ -5145,340 +5159,340 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
case STATE_MARKUP_TAG_START: {
- if (buf == '>') {
- tag_start[t] = 0;
- t = 0;
+ if (c == '>') {
+ tag_start[ctx.t] = 0;
+ ctx.t = 0;
if (!strcmp(tag_start, "img")) {
cho_log(LOG_ERR, "'img' tag has to have at least the 'src' attribute.");
return NULL;
}
- tags[ta]->name = strdup(tag_start);
- tag_style = cho_style_parse(tag_start, NULL, cho_tag_style_inherit(tags, ta-1), &tags[ta]->style_presence);
+ ctx.tags[ctx.ta]->name = strdup(tag_start);
+ tag_style = cho_style_parse(tag_start, NULL, cho_tag_style_inherit(ctx.tags, ctx.ta-1), &ctx.tags[ctx.ta]->style_presence);
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
- tags[ta]->style = tag_style;
- switch (state_before_tag) {
+ ctx.tags[ctx.ta]->style = tag_style;
+ switch (ctx.state_before_tag) {
case STATE_LYRICS:
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
- (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_copy(tag_style);
break;
case STATE_CHORD:
- cho_style_free((*lines)[li]->text_above[c]->u.chord->style);
- (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style = cho_style_copy(tag_style);
break;
case STATE_ANNOTATION:
- if (ann > 0) {
- (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
- (*lines)[li]->text_above[c]->u.annot->text[ann] = 0;
- ann = 0;
- c++;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove));
- (*lines)[li]->text_above[c]->is_chord = false;
- (*lines)[li]->text_above[c]->position = text_above_pos;
- (*lines)[li]->text_above[c]->u.annot = cho_text_new();
+ if (ctx.ann > 0) {
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text = erealloc((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text, (ctx.ann+1) * sizeof(char));
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->text[ctx.ann] = 0;
+ ctx.ann = 0;
+ ctx.lia++;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = emalloc(sizeof(struct ChoLineItemAbove));
+ (*lines)[ctx.li]->text_above[ctx.lia]->is_chord = false;
+ (*lines)[ctx.li]->text_above[ctx.lia]->position = ctx.text_above_pos;
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot = cho_text_new();
}
- cho_style_free((*lines)[li]->text_above[c]->u.annot->style);
- (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style = cho_style_copy(tag_style);
break;
case STATE_DIRECTIVE_VALUE:
- directive_has_tag = true;
+ ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[state_before_tag]);
+ cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
memset(tag_start, 0, strlen(tag_start));
- state = state_before_tag;
+ ctx.state = ctx.state_before_tag;
break;
}
- if (is_whitespace(buf)) {
- tag_start[t] = 0;
- t = 0;
- tags[ta]->name = strdup(tag_start);
- tags[ta]->attrs = erealloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *));
- tags[ta]->attrs[at] = cho_tag_attr_new();
- state = STATE_MARKUP_ATTR_NAME;
+ if (is_whitespace(c)) {
+ tag_start[ctx.t] = 0;
+ ctx.t = 0;
+ ctx.tags[ctx.ta]->name = strdup(tag_start);
+ ctx.tags[ctx.ta]->attrs = erealloc(ctx.tags[ctx.ta]->attrs, (ctx.at+1) * sizeof(struct Attr *));
+ ctx.tags[ctx.ta]->attrs[ctx.at] = cho_tag_attr_new();
+ ctx.state = STATE_MARKUP_ATTR_NAME;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_MARKUP_TAG_START;
- state = STATE_BACKSLASH;
- t--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_MARKUP_TAG_START;
+ ctx.state = STATE_BACKSLASH;
+ ctx.t--;
break;
}
cho_log(LOG_ERR, "Newline character inside a tag name is invalid.");
return NULL;
}
- if (t == 5) {
+ if (ctx.t == 5) {
cho_log(LOG_ERR, "Start tag name is too long.");
return NULL;
}
- tag_start[t] = buf;
- t++;
+ tag_start[ctx.t] = c;
+ ctx.t++;
break;
}
case STATE_MARKUP_TAG_END: {
- if (buf == '>') {
- tag_end[t] = 0;
- t = 0;
- if (!cho_tag_close_last_unclosed(tag_end, tags, ta)) {
+ if (c == '>') {
+ tag_end[ctx.t] = 0;
+ ctx.t = 0;
+ if (!cho_tag_close_last_unclosed(tag_end, ctx.tags, ctx.ta)) {
LOG_DEBUG("cho_tag_close_last_unclosed failed.");
return NULL;
}
memset(tag_end, 0, strlen(tag_end));
- state = state_before_tag;
+ ctx.state = ctx.state_before_tag;
break;
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_MARKUP_TAG_END;
- state = STATE_BACKSLASH;
- t--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_MARKUP_TAG_END;
+ ctx.state = STATE_BACKSLASH;
+ ctx.t--;
break;
}
cho_log(LOG_ERR, "Newline character inside a tag name is invalid.");
return NULL;
}
- if (t == 5) {
+ if (ctx.t == 5) {
cho_log(LOG_ERR, "End tag name is too long.");
return NULL;
}
- tag_end[t] = buf;
- t++;
+ tag_end[ctx.t] = c;
+ ctx.t++;
break;
}
case STATE_MARKUP_ATTR_NAME: {
- if (buf == '=') {
- tags[ta]->attrs[at]->name = erealloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
- tags[ta]->attrs[at]->name[atn] = 0;
- atn = 0;
- state = STATE_MARKUP_ATTR_VALUE;
+ if (c == '=') {
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name[ctx.atn] = 0;
+ ctx.atn = 0;
+ ctx.state = STATE_MARKUP_ATTR_VALUE;
break;
}
- if (is_whitespace(buf)) {
- if (at == 0) {
- if (!tags[ta]->attrs[at]->name) {
+ if (is_whitespace(c)) {
+ if (ctx.at == 0) {
+ if (!ctx.tags[ctx.ta]->attrs[ctx.at]->name) {
break;
} else {
- tags[ta]->attrs[at]->name = erealloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
- tags[ta]->attrs[at]->name[atn] = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name[ctx.atn] = 0;
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
}
- if (tags[ta]->attrs[at-1]->name && tags[ta]->attrs[at-1]->value) {
+ if (ctx.tags[ctx.ta]->attrs[ctx.at-1]->name && ctx.tags[ctx.ta]->attrs[ctx.at-1]->value) {
break;
}
- if (!tags[ta]->attrs[at-1]->name && !tags[ta]->attrs[at-1]->value) {
+ if (!ctx.tags[ctx.ta]->attrs[ctx.at-1]->name && !ctx.tags[ctx.ta]->attrs[ctx.at-1]->value) {
break;
}
- tags[ta]->attrs[at]->name = erealloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
- tags[ta]->attrs[at]->name[atn] = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name[ctx.atn] = 0;
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
- if (buf == '>') {
- if (tags[ta]->attrs[at-1]->value) {
- cho_tag_attr_free(tags[ta]->attrs[at]);
- tags[ta]->attrs[at] = NULL;
- atn = 0;
- if (!strcmp(tags[ta]->name, "img")) {
- cho_text_free((*lines)[li]->items[ly]->u.text);
- (*lines)[li]->items[ly]->is_text = false;
- image = cho_image_tag_parse(tags[ta]->attrs);
+ if (c == '>') {
+ if (ctx.tags[ctx.ta]->attrs[ctx.at-1]->value) {
+ cho_tag_attr_free(ctx.tags[ctx.ta]->attrs[ctx.at]);
+ ctx.tags[ctx.ta]->attrs[ctx.at] = NULL;
+ ctx.atn = 0;
+ if (!strcmp(ctx.tags[ctx.ta]->name, "img")) {
+ cho_text_free((*lines)[ctx.li]->items[ctx.lii]->u.text);
+ (*lines)[ctx.li]->items[ctx.lii]->is_text = false;
+ image = cho_image_tag_parse(ctx.tags[ctx.ta]->attrs);
if (!image) {
LOG_DEBUG("cho_image_tag_parse failed.");
return NULL;
}
- (*lines)[li]->items[ly]->u.image = image;
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li]->items[ctx.lii]->u.image = image;
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
} else {
- tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1), &tags[ta]->style_presence);
+ tag_style = cho_style_parse(tag_start, ctx.tags[ctx.ta]->attrs, cho_tag_style_inherit(ctx.tags, ctx.ta-1), &ctx.tags[ctx.ta]->style_presence);
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
- tags[ta]->style = tag_style;
- switch (state_before_tag) {
+ ctx.tags[ctx.ta]->style = tag_style;
+ switch (ctx.state_before_tag) {
case STATE_LYRICS:
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
- (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_copy(tag_style);
break;
case STATE_CHORD:
- cho_style_free((*lines)[li]->text_above[c]->u.chord->style);
- (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style = cho_style_copy(tag_style);
break;
case STATE_ANNOTATION:
- cho_style_free((*lines)[li]->text_above[c]->u.annot->style);
- (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style = cho_style_copy(tag_style);
break;
case STATE_DIRECTIVE_VALUE:
- directive_has_tag = true;
+ ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[state_before_tag]);
+ cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
}
- at = 0;
+ ctx.at = 0;
memset(tag_start, 0, strlen(tag_start));
- state = state_before_tag;
+ ctx.state = ctx.state_before_tag;
break;
} else {
- tags[ta]->attrs[at]->name = erealloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
- tags[ta]->attrs[at]->name[atn] = 0;
- atn = 0;
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name[ctx.atn] = 0;
+ ctx.atn = 0;
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
}
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_MARKUP_ATTR_NAME;
- state = STATE_BACKSLASH;
- atn--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_MARKUP_ATTR_NAME;
+ ctx.state = STATE_BACKSLASH;
+ ctx.atn--;
break;
}
cho_log(LOG_ERR, "Newline character inside an tag attribute name is invalid.");
return NULL;
}
- tags[ta]->attrs[at]->name = erealloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
- tags[ta]->attrs[at]->name[atn] = buf;
- atn++;
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->name[ctx.atn] = c;
+ ctx.atn++;
break;
}
case STATE_MARKUP_ATTR_VALUE: {
- if (buf == '\n') {
- if (prev_buf == '\\') {
- state_before_backslash = STATE_MARKUP_ATTR_VALUE;
- state = STATE_BACKSLASH;
- atv--;
+ if (c == '\n') {
+ if (prev_c == '\\') {
+ ctx.state_before_backslash = STATE_MARKUP_ATTR_VALUE;
+ ctx.state = STATE_BACKSLASH;
+ ctx.atv--;
break;
}
cho_log(LOG_ERR, "Newline character inside an attribute value is invalid.");
return NULL;
}
if (avs == -1) {
- if (is_whitespace(buf)) {
+ if (is_whitespace(c)) {
cho_log(LOG_ERR, "Whitespace character after equals sign is invalid.");
return NULL;
}
- if (buf == '>') {
- cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_start);
+ if (c == '>') {
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
- if (buf == '\'') {
+ if (c == '\'') {
avs = AVS_APOSTROPHE;
- } else if (buf == '"') {
+ } else if (c == '"') {
avs = AVS_QUOTATION_MARK;
} else {
avs = AVS_UNQUOTED;
- tags[ta]->attrs[at]->value = erealloc(tags[ta]->attrs[at]->value, (atv+1) * sizeof(char));
- tags[ta]->attrs[at]->value[atv] = buf;
- atv++;
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->value, (ctx.atv+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value[ctx.atv] = c;
+ ctx.atv++;
}
break;
}
- if (avs == AVS_UNQUOTED && buf == '>') {
- tags[ta]->attrs[at]->value = erealloc(tags[ta]->attrs[at]->value, (atv+1) * sizeof(char));
- tags[ta]->attrs[at]->value[atv] = 0;
- atv = 0;
- at++;
- tags[ta]->attrs = erealloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *));
- tags[ta]->attrs[at] = NULL;
- if (!strcmp(tags[ta]->name, "img")) {
- cho_text_free((*lines)[li]->items[ly]->u.text);
- (*lines)[li]->items[ly]->is_text = false;
- image = cho_image_tag_parse(tags[ta]->attrs);
+ if (avs == AVS_UNQUOTED && c == '>') {
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->value, (ctx.atv+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value[ctx.atv] = 0;
+ ctx.atv = 0;
+ ctx.at++;
+ ctx.tags[ctx.ta]->attrs = erealloc(ctx.tags[ctx.ta]->attrs, (ctx.at+1) * sizeof(struct Attr *));
+ ctx.tags[ctx.ta]->attrs[ctx.at] = NULL;
+ if (!strcmp(ctx.tags[ctx.ta]->name, "img")) {
+ cho_text_free((*lines)[ctx.li]->items[ctx.lii]->u.text);
+ (*lines)[ctx.li]->items[ctx.lii]->is_text = false;
+ image = cho_image_tag_parse(ctx.tags[ctx.ta]->attrs);
if (!image) {
LOG_DEBUG("cho_image_tag_parse failed.");
return NULL;
}
- (*lines)[li]->items[ly]->u.image = image;
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = cho_line_item_new();
+ (*lines)[ctx.li]->items[ctx.lii]->u.image = image;
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new();
} else {
- tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1), &tags[ta]->style_presence);
+ tag_style = cho_style_parse(tag_start, ctx.tags[ctx.ta]->attrs, cho_tag_style_inherit(ctx.tags, ctx.ta-1), &ctx.tags[ctx.ta]->style_presence);
if (!tag_style) {
LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
- tags[ta]->style = tag_style;
- switch (state_before_tag) {
+ ctx.tags[ctx.ta]->style = tag_style;
+ switch (ctx.state_before_tag) {
case STATE_LYRICS:
- cho_style_free((*lines)[li]->items[ly]->u.text->style);
- (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_copy(tag_style);
break;
case STATE_CHORD:
- cho_style_free((*lines)[li]->text_above[c]->u.chord->style);
- (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->style = cho_style_copy(tag_style);
break;
case STATE_ANNOTATION:
- cho_style_free((*lines)[li]->text_above[c]->u.annot->style);
- (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style);
+ cho_style_free((*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style);
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot->style = cho_style_copy(tag_style);
break;
case STATE_DIRECTIVE_VALUE:
- directive_has_tag = true;
+ ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[state_before_tag]);
+ cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
}
- at = 0;
+ ctx.at = 0;
avs = -1;
memset(tag_start, 0, strlen(tag_start));
- state = state_before_tag;
+ ctx.state = ctx.state_before_tag;
break;
}
if (
- (avs == AVS_APOSTROPHE && buf == '\'') ||
- (avs == AVS_QUOTATION_MARK && buf == '"') ||
- (avs == AVS_UNQUOTED && (buf == ' ' || buf == '\t'))
+ (avs == AVS_APOSTROPHE && c == '\'') ||
+ (avs == AVS_QUOTATION_MARK && c == '"') ||
+ (avs == AVS_UNQUOTED && (c == ' ' || c == '\t'))
) {
- tags[ta]->attrs[at]->value = erealloc(tags[ta]->attrs[at]->value, (atv+1) * sizeof(char));
- tags[ta]->attrs[at]->value[atv] = 0;
- atv = 0;
- at++;
- tags[ta]->attrs = erealloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *));
- tags[ta]->attrs[at] = cho_tag_attr_new();
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->value, (ctx.atv+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value[ctx.atv] = 0;
+ ctx.atv = 0;
+ ctx.at++;
+ ctx.tags[ctx.ta]->attrs = erealloc(ctx.tags[ctx.ta]->attrs, (ctx.at+1) * sizeof(struct Attr *));
+ ctx.tags[ctx.ta]->attrs[ctx.at] = cho_tag_attr_new();
avs = -1;
- state = STATE_MARKUP_ATTR_NAME;
+ ctx.state = STATE_MARKUP_ATTR_NAME;
break;
}
- tags[ta]->attrs[at]->value = erealloc(tags[ta]->attrs[at]->value, (atv+1) * sizeof(char));
- tags[ta]->attrs[at]->value[atv] = buf;
- atv++;
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->value, (ctx.atv+1) * sizeof(char));
+ ctx.tags[ctx.ta]->attrs[ctx.at]->value[ctx.atv] = c;
+ ctx.atv++;
break;
}
case STATE_COMMENT: {
- if (buf == '\n') {
- state = state_before_comment;
+ if (c == '\n') {
+ ctx.state = ctx.state_before_comment;
break;
}
break;
}
case STATE_MAYBE_METADATA_SUBSTITUTION: {
- if (buf == '{') {
- state = STATE_METADATA_SUBSTITUTION;
+ if (c == '{') {
+ ctx.state = STATE_METADATA_SUBSTITUTION;
break;
}
- switch (state_before_metadata_substitution) {
+ switch (ctx.state_before_metadata_substitution) {
case STATE_LYRICS:
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = '%';
- te++;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = '%';
+ ctx.te++;
break;
default:
}
- state = state_before_metadata_substitution;
+ ctx.state = ctx.state_before_metadata_substitution;
if (fseek(fp, -1, SEEK_CUR)) {
LOG_DEBUG("fseek failed.");
perror("fseek");
@@ -5487,10 +5501,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
case STATE_METADATA_SUBSTITUTION: {
- if (buf == '}') {
- if (nested_level == 0) {
- metadata_substitution[ms] = 0;
- ms = 0;
+ if (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(
metadata_substitution,
@@ -5498,75 +5512,75 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
state_before_metadata_substitution
); */
// Append 'substituted' to whatever text
- state = state_before_metadata_substitution;
+ ctx.state = ctx.state_before_metadata_substitution;
break;
}
- nested_level--;
+ ctx.nested_level--;
}
- if (prev_buf == '%' && buf == '{') {
- nested_level++;
+ if (prev_c == '%' && c == '{') {
+ ctx.nested_level++;
}
- if (ms > 4094) {
+ if (ctx.ms > 4094) {
cho_log(LOG_ERR, "Metadata substitution can't be greater than 4095 bytes.");
return NULL;
}
- metadata_substitution[ms] = buf;
- ms++;
+ metadata_substitution[ctx.ms] = c;
+ ctx.ms++;
break;
}
}
- prev_buf = buf;
+ prev_c = c;
} else {
break;
}
}
int e = 0;
- while (e <= ta) {
- cho_tag_free(tags[e]);
+ while (e <= ctx.ta) {
+ cho_tag_free(ctx.tags[e]);
e++;
}
- free(tags);
- if ((*lines)[li]->items[ly]->is_text) {
- if ((*lines)[li]->items[ly]->u.text->text) {
- (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char));
- (*lines)[li]->items[ly]->u.text->text[te] = 0;
- ly++;
- (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
- (*lines)[li]->items[ly] = NULL;
- (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- (*lines)[li]->text_above[c] = NULL;
- li++;
- *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *));
- (*lines)[li] = NULL;
+ free(ctx.tags);
+ if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
+ if ((*lines)[ctx.li]->items[ctx.lii]->u.text->text) {
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->text[ctx.te] = 0;
+ ctx.lii++;
+ (*lines)[ctx.li]->items = erealloc((*lines)[ctx.li]->items, (ctx.lii+1) * sizeof(struct ChoLineItem *));
+ (*lines)[ctx.li]->items[ctx.lii] = NULL;
+ (*lines)[ctx.li]->text_above = erealloc((*lines)[ctx.li]->text_above, (ctx.lia+1) * sizeof(struct ChoLineItemAbove *));
+ (*lines)[ctx.li]->text_above[ctx.lia] = NULL;
+ ctx.li++;
+ *lines = erealloc(*lines, (ctx.li+1) * sizeof(struct ChoLine *));
+ (*lines)[ctx.li] = NULL;
} else {
- cho_line_item_free((*lines)[li]->items[ly]);
- free((*lines)[li]->items);
- free((*lines)[li]->text_above);
- free((*lines)[li]);
- (*lines)[li] = NULL;
+ cho_line_item_free((*lines)[ctx.li]->items[ctx.lii]);
+ free((*lines)[ctx.li]->items);
+ free((*lines)[ctx.li]->text_above);
+ free((*lines)[ctx.li]);
+ (*lines)[ctx.li] = NULL;
}
}
if (!cho_style_reset_default()) {
LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = NULL;
- se++;
- songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
- songs[so]->sections[se] = NULL;
- songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *));
- songs[so]->diagrams[dia] = NULL;
- so++;
- songs = erealloc(songs, (so+1) * sizeof(struct ChoSong *));
- songs[so] = NULL;
+ ctx.songs[ctx.so]->metadata = erealloc(ctx.songs[ctx.so]->metadata, (ctx.m+1) * sizeof(struct ChoMetadata *));
+ ctx.songs[ctx.so]->metadata[ctx.m] = NULL;
+ ctx.se++;
+ ctx.songs[ctx.so]->sections = erealloc(ctx.songs[ctx.so]->sections, (ctx.se+1) * sizeof(struct ChoSection *));
+ ctx.songs[ctx.so]->sections[ctx.se] = NULL;
+ ctx.songs[ctx.so]->diagrams = erealloc(ctx.songs[ctx.so]->diagrams, (ctx.dia+1) * sizeof(struct ChordDiagram *));
+ ctx.songs[ctx.so]->diagrams[ctx.dia] = NULL;
+ ctx.so++;
+ ctx.songs = erealloc(ctx.songs, (ctx.so+1) * sizeof(struct ChoSong *));
+ ctx.songs[ctx.so] = NULL;
g_current_ttype = TT_TEXT;
g_prev_ttype = TT_TEXT;
g_config = NULL;
g_chordpro_filepath = NULL;
- free(g_transpose_history);
- g_transpose_history = NULL;
- g_transpose = NULL;
+ free(ctx.transpose_history);
+ ctx.transpose_history = NULL;
+ ctx.transpose = NULL;
g_line_number = 1;
for (e = 0; e<g_ia; e++) {
cho_image_free(g_image_assets[e]);
@@ -5575,12 +5589,12 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
g_image_assets = NULL;
g_ia = 0;
bool exist_title = false;
- for (so = 0; songs[so]; so++) {
- for (m = 0; songs[so]->metadata[m]; m++) {
+ for (ctx.so = 0; ctx.songs[ctx.so]; ctx.so++) {
+ for (ctx.m = 0; ctx.songs[ctx.so]->metadata[ctx.m]; ctx.m++) {
if (
- !strcmp(songs[so]->metadata[m]->name, "title") &&
- songs[so]->metadata[m]->value &&
- strcmp(songs[so]->metadata[m]->value, "") != 0
+ !strcmp(ctx.songs[ctx.so]->metadata[ctx.m]->name, "title") &&
+ ctx.songs[ctx.so]->metadata[ctx.m]->value &&
+ strcmp(ctx.songs[ctx.so]->metadata[ctx.m]->value, "") != 0
) {
exist_title = true;
}
@@ -5593,7 +5607,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
exist_title = false;
}
- return songs;
+ return ctx.songs;
}
#ifdef DEBUG
diff --git a/src/chordpro.h b/src/chordpro.h
@@ -129,6 +129,42 @@ struct Tag {
bool is_closed;
};
+struct ChoContext {
+ bool is_chord_already_initialized;
+ bool is_maybe_end_of_tab_directive;
+ bool directive_has_tag;
+ enum State state;
+ enum State state_before_comment;
+ enum State state_before_tag;
+ enum State state_before_backslash;
+ enum State state_before_metadata_substitution;
+ index_t ann; // annotation
+ index_t at; // struct Attr
+ index_t atn; // struct Attr.name
+ index_t atv; // struct Attr.value
+ index_t ch; // struct ChoChord
+ index_t dia; // struct ChordDiagram
+ index_t dn; // char directive_name
+ index_t dv; // char directive_value
+ index_t li; // struct ChoLine
+ index_t lia; // struct ChoLineItemAbove
+ index_t lii; // struct ChoLineItem
+ index_t m; // struct ChoMetadata
+ index_t ms; // metadata_substitution
+ index_t se; // struct ChoSection
+ index_t so; // struct ChoSong
+ index_t t; // char tag_start/tag_end
+ index_t ta; // struct Tag
+ index_t te; // struct ChoText
+ index_t th; // transpose_history
+ int text_above_pos;
+ int nested_level;
+ int *transpose_history;
+ int *transpose;
+ struct ChoSong **songs;
+ struct Tag **tags;
+};
+
void cho_log_enable_info_logs(void);
struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config);
diff --git a/src/types.h b/src/types.h
@@ -3,6 +3,9 @@
#ifndef _TYPES_H_
#define _TYPES_H_
+// used as an index in an array
+typedef int index_t;
+
enum TextType : int8_t {
TT_CHORD,
TT_ANNOT,