commit 839d04eea6d10aa8b8396fde89bd48215a0898a4
parent ed845e75a1e73877454fb70958bb06a437f23825
Author: nibo <nibo@relim.de>
Date: Thu, 20 Feb 2025 11:54:09 +0100
Move global variables into 'struct ChoContext'
Diffstat:
2 files changed, 387 insertions(+), 373 deletions(-)
diff --git a/src/chordpro.c b/src/chordpro.c
@@ -145,15 +145,6 @@ static const char *chord_extensions_minor[] = {
};
static bool g_show_info_logs = false;
-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 size_t g_line_number = 1;
-struct ChoImage **g_image_assets = NULL;
-static int g_ia = 0;
#ifdef DEBUG
@@ -266,7 +257,7 @@ cho_log_enable_info_logs(void)
#if COLOR == 1
static void
-cho_log(enum LogLevel level, const char *msg, ...)
+cho_log(struct ChoContext *ctx, enum LogLevel level, const char *msg, ...)
{
if (level == LOG_INFO && !g_show_info_logs) {
return;
@@ -294,25 +285,25 @@ cho_log(enum LogLevel level, const char *msg, ...)
break;
}
if (isatty(2)) {
- if (g_chordpro_filepath) {
+ if (ctx->chordpro_filepath) {
fprintf(stderr, COLOR_BOLD_WHITE"%s:%ld:"COLOR_RESET" %s%s"COLOR_RESET": ",
- g_chordpro_filepath, g_line_number, color, log_level);
+ ctx->chordpro_filepath, ctx->line_number, color, log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
} else {
fprintf(stderr, "line "COLOR_BOLD_WHITE"%ld:"COLOR_RESET" %s%s"COLOR_RESET": ",
- g_line_number, color, log_level);
+ ctx->line_number, color, log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
}
} else {
- if (g_chordpro_filepath) {
- fprintf(stderr, "%s:%ld: %s: ", g_chordpro_filepath, g_line_number,
+ if (ctx->chordpro_filepath) {
+ fprintf(stderr, "%s:%ld: %s: ", ctx->chordpro_filepath, ctx->line_number,
log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
} else {
- fprintf(stderr, "line %ld: %s: ", g_line_number, log_level);
+ fprintf(stderr, "line %ld: %s: ", ctx->line_number, log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
}
@@ -320,7 +311,7 @@ cho_log(enum LogLevel level, const char *msg, ...)
}
#else
static void
-cho_log(enum LogLevel level, const char *msg, ...)
+cho_log(struct ChoContext *ctx, enum LogLevel level, const char *msg, ...)
{
if (level == LOG_INFO && !g_show_info_logs) {
return;
@@ -342,13 +333,13 @@ cho_log(enum LogLevel level, const char *msg, ...)
log_level = "TODO";
break;
}
- if (g_chordpro_filepath) {
- fprintf(stderr, "%s:%ld: %s: ", g_chordpro_filepath, g_line_number,
+ if (ctx->chordpro_filepath) {
+ fprintf(stderr, "%s:%ld: %s: ", ctx->chordpro_filepath, ctx->line_number,
log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
} else {
- fprintf(stderr, "line %ld: %s: ", g_line_number, log_level);
+ fprintf(stderr, "line %ld: %s: ", ctx->line_number, log_level);
vfprintf(stderr, msg, va);
fprintf(stderr, "\n");
}
@@ -409,7 +400,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[2];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -423,7 +414,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[4];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -437,7 +428,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[6];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -453,7 +444,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[1];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -467,7 +458,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[2];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -481,7 +472,7 @@ cho_rgbcolor_parse(const char *str)
tmp[1] = str[3];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- cho_log(LOG_ERR, "Invalid primary color in rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -489,7 +480,7 @@ cho_rgbcolor_parse(const char *str)
}
}
} else {
- cho_log(LOG_ERR, "Invalid rgb color.");
+ // cho_log(ctx, LOG_ERR, "Invalid rgb color.");
free(color);
return NULL;
}
@@ -547,7 +538,8 @@ cho_color_parse(const char *str)
color->green = 0;
color->blue = 0;
} else {
- cho_log(LOG_ERR, "Invalid color value '%s'.", str);
+ // TODO: If this is called by config.c what should 'ctx' have as value
+ // cho_log(ctx, LOG_ERR, "Invalid color value '%s'.", str);
free(color);
return NULL;
}
@@ -776,7 +768,12 @@ cho_debug_style_print(struct ChoStyle *style)
#endif /* DEBUG */
static bool
-cho_style_property_apply_default(enum TextType current_ttype, enum StylePropertyType ptype, struct ChoStyle *style)
+cho_style_property_apply_default(
+ struct ChoContext *ctx,
+ enum TextType current_ttype,
+ enum StylePropertyType ptype,
+ struct ChoStyle *style
+)
{
unsigned int i;
for (i = 0; i<LENGTH(default_style_properties); i++) {
@@ -812,7 +809,7 @@ cho_style_property_apply_default(enum TextType current_ttype, enum StyleProperty
}
break;
default:
- cho_log(LOG_WARN, "Invalid style property type '%d'.", ptype);
+ cho_log(ctx, LOG_WARN, "Invalid style property type '%d'.", ptype);
return false;
}
}
@@ -821,22 +818,22 @@ cho_style_property_apply_default(enum TextType current_ttype, enum StyleProperty
}
static void
-cho_style_apply_default(enum TextType current_ttype, struct ChoStyle *style)
+cho_style_apply_default(struct ChoContext *ctx, enum TextType current_ttype, struct ChoStyle *style)
{
if (current_ttype == TT_CHORUS) {
- if (!cho_style_property_apply_default(TT_CHORUS, SPT_FONT, style)) {
- cho_style_property_apply_default(TT_TEXT, SPT_FONT, style);
+ if (!cho_style_property_apply_default(ctx, TT_CHORUS, SPT_FONT, style)) {
+ cho_style_property_apply_default(ctx, TT_TEXT, SPT_FONT, style);
}
- if (!cho_style_property_apply_default(TT_CHORUS, SPT_SIZE, style)) {
- cho_style_property_apply_default(TT_TEXT, SPT_SIZE, style);
+ if (!cho_style_property_apply_default(ctx, TT_CHORUS, SPT_SIZE, style)) {
+ cho_style_property_apply_default(ctx, TT_TEXT, SPT_SIZE, style);
}
- if (!cho_style_property_apply_default(TT_CHORUS, SPT_COLOR, style)) {
- cho_style_property_apply_default(TT_TEXT, SPT_COLOR, style);
+ if (!cho_style_property_apply_default(ctx, TT_CHORUS, SPT_COLOR, style)) {
+ cho_style_property_apply_default(ctx, TT_TEXT, SPT_COLOR, style);
}
} else {
- cho_style_property_apply_default(current_ttype, SPT_FONT, style);
- cho_style_property_apply_default(current_ttype, SPT_SIZE, style);
- cho_style_property_apply_default(current_ttype, SPT_COLOR, style);
+ cho_style_property_apply_default(ctx, current_ttype, SPT_FONT, style);
+ cho_style_property_apply_default(ctx, current_ttype, SPT_SIZE, style);
+ cho_style_property_apply_default(ctx, current_ttype, SPT_COLOR, style);
}
}
@@ -949,20 +946,20 @@ cho_style_complement(
}
static struct ChoStyle *
-cho_style_new_from_config(enum TextType ttype)
+cho_style_new_from_config(struct ChoContext *ctx, enum TextType ttype)
{
- return cho_style_copy(g_config->output->styles[ttype]);
+ return cho_style_copy(ctx->config->output->styles[ttype]);
}
static struct ChoStyle *
-cho_style_new_default(void)
+cho_style_new_default(struct ChoContext *ctx)
{
- struct ChoStyle *style = cho_style_new_from_config(g_current_ttype);
+ struct ChoStyle *style = cho_style_new_from_config(ctx, ctx->current_ttype);
if (!style) {
LOG_DEBUG("cho_style_new_from_config failed.");
return NULL;
}
- cho_style_apply_default(g_current_ttype, style);
+ cho_style_apply_default(ctx, ctx->current_ttype, style);
return style;
}
@@ -1107,6 +1104,7 @@ cho_style_font_desc_parse(const char *str, struct ChoStylePresence *presence)
static struct ChoStyle *
cho_style_parse(
+ struct ChoContext *ctx,
const char *tag_name,
struct Attr **attrs,
struct ChoStyle *inherited_style,
@@ -1120,7 +1118,7 @@ cho_style_parse(
if (inherited_style) {
style = cho_style_copy(inherited_style);
} else {
- style = cho_style_new_default();
+ style = cho_style_new_default(ctx);
}
if (!strcmp(tag_name, "span")) {
int a;
@@ -1151,7 +1149,7 @@ cho_style_parse(
style->font->family = FF_MONOSPACE;
presence->font.family = true;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'font_family/face'.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'font_family/face'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "size")) {
@@ -1165,11 +1163,11 @@ cho_style_parse(
style->font->size *= percentage / 100.0;
presence->font.size = true;
} else {
- cho_log(LOG_ERR, "Invalid percentage in attribute 'size'.");
+ cho_log(ctx, LOG_ERR, "Invalid percentage in attribute 'size'.");
return NULL;
}
} else {
- cho_log(LOG_ERR, "Invalid percentage in attribute 'size'.");
+ cho_log(ctx, LOG_ERR, "Invalid percentage in attribute 'size'.");
return NULL;
}
} else if (isdigit(attrs[a]->value[0]) != 0) {
@@ -1178,7 +1176,7 @@ cho_style_parse(
style->font->size = size;
presence->font.size = true;
} else {
- cho_log(LOG_ERR, "Invalid number in attribute 'size'.");
+ cho_log(ctx, LOG_ERR, "Invalid number in attribute 'size'.");
return NULL;
}
} else if (!strcmp(attrs[a]->value, "xx-small")) {
@@ -1213,7 +1211,7 @@ cho_style_parse(
style->font->size *= 0.8;
presence->font.size = true;
} else {
- cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'size'.", attrs[a]->value);
+ cho_log(ctx, LOG_ERR, "Invalid value '%s' for the attribute 'size'.", attrs[a]->value);
return NULL;
}
} else if (!strcmp(attrs[a]->name, "style")) {
@@ -1227,7 +1225,7 @@ cho_style_parse(
style->font->style = FS_ITALIC;
presence->font.style = true;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'style'.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'style'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "weight")) {
@@ -1238,7 +1236,7 @@ cho_style_parse(
style->font->weight = FW_BOLD;
presence->font.weight = true;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'weight'.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'weight'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "foreground")) {
@@ -1272,7 +1270,7 @@ cho_style_parse(
style->underline_style = LS_NONE;
presence->underline_style = true;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'underline'.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'underline'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "underline_colour")) {
@@ -1296,7 +1294,7 @@ cho_style_parse(
style->overline_style = LS_NONE;
presence->overline_style = true;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'overline'.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'overline'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "overline_colour")) {
@@ -1321,7 +1319,7 @@ cho_style_parse(
style->rise = (style->font->size / 2) * percentage / 100.0;
presence->rise = true;
} else {
- cho_log(LOG_ERR, "Invalid percentage in attribute 'rise'.");
+ cho_log(ctx, LOG_ERR, "Invalid percentage in attribute 'rise'.");
return NULL;
}
}
@@ -1331,11 +1329,11 @@ cho_style_parse(
style->rise = rise;
presence->rise = true;
} else {
- cho_log(LOG_ERR, "Invalid number in attribute 'rise'.");
+ cho_log(ctx, LOG_ERR, "Invalid number in attribute 'rise'.");
return NULL;
}
} else {
- cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
+ cho_log(ctx, LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
return NULL;
}
} else {
@@ -1349,7 +1347,7 @@ cho_style_parse(
style->rise += more;
presence->rise = true;
} else {
- cho_log(LOG_ERR, "Invalid percentage in attribute 'rise'.");
+ cho_log(ctx, LOG_ERR, "Invalid percentage in attribute 'rise'.");
return NULL;
}
}
@@ -1359,11 +1357,11 @@ cho_style_parse(
style->rise = rise;
presence->rise = true;
} else {
- cho_log(LOG_ERR, "Invalid number in attribute 'rise'.");
+ cho_log(ctx, LOG_ERR, "Invalid number in attribute 'rise'.");
return NULL;
}
} else {
- cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
+ cho_log(ctx, LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
return NULL;
}
}
@@ -1375,7 +1373,7 @@ cho_style_parse(
style->strikethrough = false;
presence->strikethrough = true;
} else {
- cho_log(LOG_ERR, "Invalid value '%s' in attribute 'strikethrough'.", attrs[a]->value);
+ cho_log(ctx, LOG_ERR, "Invalid value '%s' in attribute 'strikethrough'.", attrs[a]->value);
return NULL;
}
} else if (!strcmp(attrs[a]->name, "strikethrough_colour")) {
@@ -1392,7 +1390,7 @@ cho_style_parse(
style->href = strdup(attrs[a]->value);
presence->href = true;
} else {
- cho_log(LOG_ERR, "Invalid attribute '%s'.", attrs[a]->name);
+ cho_log(ctx, LOG_ERR, "Invalid attribute '%s'.", attrs[a]->name);
return NULL;
}
}
@@ -1428,7 +1426,7 @@ cho_style_parse(
style->underline_style = LS_SINGLE;
presence->underline_style = true;
} else {
- cho_log(LOG_ERR, "Invalid tag name '%s'.", tag_name);
+ cho_log(ctx, LOG_ERR, "Invalid tag name '%s'.", tag_name);
cho_style_free(style);
return NULL;
}
@@ -1454,7 +1452,7 @@ cho_style_print_as_toml(struct ChoStyle *style, const char *section)
}
static bool
-cho_style_change_default(struct StyleProperty sprop)
+cho_style_change_default(struct ChoContext *ctx, struct StyleProperty sprop)
{
if (sprop.type == -1)
return false;
@@ -1485,7 +1483,7 @@ cho_style_change_default(struct StyleProperty sprop)
}
return true;
default:
- cho_log(LOG_ERR, "Invalid style property type '%d'.", sprop.type);
+ cho_log(ctx, LOG_ERR, "Invalid style property type '%d'.", sprop.type);
return false;
}
}
@@ -1494,7 +1492,7 @@ cho_style_change_default(struct StyleProperty sprop)
}
static bool
-cho_style_reset_default(void)
+cho_style_reset_default(struct ChoContext *ctx)
{
unsigned int i;
for (i = 0; i<LENGTH(default_style_properties); i++) {
@@ -1511,7 +1509,7 @@ cho_style_reset_default(void)
default_style_properties[i].u.foreground_color = NULL;
return true;
default:
- cho_log(LOG_ERR, "Invalid style property type '%d'.", default_style_properties[i].type);
+ cho_log(ctx, LOG_ERR, "Invalid style property type '%d'.", default_style_properties[i].type);
return false;
}
}
@@ -1578,7 +1576,7 @@ cho_tag_free(struct Tag *tag)
}
static bool
-cho_tag_close_last_unclosed(const char *tag_name, struct Tag **tags, int last_index)
+cho_tag_close_last_unclosed(struct ChoContext *ctx, const char *tag_name, struct Tag **tags, int last_index)
{
int i;
for (i = last_index; i >= 0; i--) {
@@ -1587,7 +1585,7 @@ cho_tag_close_last_unclosed(const char *tag_name, struct Tag **tags, int last_in
return true;
}
}
- cho_log(LOG_ERR, "Didn't find a start tag for the end tag '%s'.", tag_name);
+ cho_log(ctx, LOG_ERR, "Didn't find a start tag for the end tag '%s'.", tag_name);
return false;
}
@@ -1609,12 +1607,12 @@ cho_tag_style_inherit(struct Tag **tags, int prev_index)
}
static struct ChoMetadata *
-cho_metadata_new(void)
+cho_metadata_new(struct ChoContext *ctx)
{
struct ChoMetadata *meta = emalloc(sizeof(struct ChoMetadata));
meta->name = NULL;
meta->value = NULL;
- meta->style = cho_style_new_default();
+ meta->style = cho_style_new_default(ctx);
return meta;
}
@@ -1643,9 +1641,9 @@ cho_metadata_get(struct ChoMetadata **metadata, const char *name)
}
static struct ChoMetadata *
-cho_metadata_split(const char *directive_value)
+cho_metadata_split(struct ChoContext *ctx, const char *directive_value)
{
- struct ChoMetadata *meta = cho_metadata_new();
+ struct ChoMetadata *meta = cho_metadata_new(ctx);
bool is_name = true;
char *value = str_remove_leading_whitespace(directive_value);
int n = 0;
@@ -1677,13 +1675,13 @@ cho_metadata_split(const char *directive_value)
free(meta->name);
free(meta->value);
free(meta);
- cho_log(LOG_ERR, "Failed to parse directive 'meta'.");
+ cho_log(ctx, LOG_ERR, "Failed to parse directive 'meta'.");
return NULL;
}
}
static struct ChoMetadata **
-cho_metadata_load_default(void)
+cho_metadata_load_default(struct ChoContext *ctx)
{
struct ChoMetadata **meta = NULL;
char *filename;
@@ -1692,46 +1690,46 @@ cho_metadata_load_default(void)
LOG_DEBUG("getenv(USER) failed.");
return NULL;
}
- struct InstrumentInfo ins_info = config_instrument_get(g_config->output->diagram->instrument);
+ struct InstrumentInfo ins_info = config_instrument_get(ctx->config->output->diagram->instrument);
int i = 0;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("chordpro");
meta[i]->value = strdup("ChordPro");
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
- if (g_chordpro_filepath) {
- filename = filepath_basename(g_chordpro_filepath);
+ if (ctx->chordpro_filepath) {
+ filename = filepath_basename(ctx->chordpro_filepath);
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("chordpro.songsource");
meta[i]->value = filename;
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
}
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("chordpro.version");
meta[i]->value = strdup("6");
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("instrument");
meta[i]->value = strdup(ins_info.name);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("instrument.type");
meta[i]->value = strdup(ins_info.name);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("instrument.description");
meta[i]->value = strdup(ins_info.description);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
const time_t t = time(NULL);
struct tm *tt = localtime(&t);
@@ -1744,43 +1742,43 @@ cho_metadata_load_default(void)
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("today");
meta[i]->value = strdup(time_str);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("tuning");
meta[i]->value = strdup(ins_info.tuning);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("user");
meta[i]->value = strdup(logged_in_user);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("user.name");
meta[i]->value = strdup(logged_in_user);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
meta = erealloc(meta, (i+1) * sizeof(struct ChoMetadata *));
meta[i] = emalloc(sizeof(struct ChoMetadata));
meta[i]->name = strdup("user.fullname");
meta[i]->value = strdup(logged_in_user);
- meta[i]->style = cho_style_new_default();
+ meta[i]->style = cho_style_new_default(ctx);
i++;
return meta;
}
-static char *
+/* static char *
cho_metadata_substitution_parse(
const char *str,
struct ChoMetadata **metadata,
enum State state_before_substitution
)
{
-}
+} */
static bool
transposition_parse(const char *str, int *transpose)
@@ -1808,11 +1806,11 @@ transposition_calc_chord_root(struct ChoContext *ctx, int index, enum NoteType t
if (transpose == 0) {
switch (type) {
case NT_NOTE:
- return strdup(g_config->output->notes[index]->note);
+ return strdup(ctx->config->output->notes[index]->note);
case NT_SHARP:
- return strdup(g_config->output->notes[index]->sharp);
+ return strdup(ctx->config->output->notes[index]->sharp);
case NT_FLAT:
- return strdup(g_config->output->notes[index]->flat);
+ return strdup(ctx->config->output->notes[index]->flat);
}
}
int new_index = index;
@@ -1869,21 +1867,21 @@ transposition_calc_chord_root(struct ChoContext *ctx, int index, enum NoteType t
}
switch (note_type) {
case NT_NOTE:
- return strdup(g_config->output->notes[new_index]->note);
+ return strdup(ctx->config->output->notes[new_index]->note);
case NT_SHARP:
- return strdup(g_config->output->notes[new_index]->sharp);
+ return strdup(ctx->config->output->notes[new_index]->sharp);
case NT_FLAT:
- return strdup(g_config->output->notes[new_index]->flat);
+ return strdup(ctx->config->output->notes[new_index]->flat);
}
- cho_log(LOG_ERR, "Invalid NoteType '%d'.", note_type);
+ cho_log(ctx, LOG_ERR, "Invalid NoteType '%d'.", note_type);
return NULL;
}
static struct ChoChord *
-cho_chord_new(void)
+cho_chord_new(struct ChoContext *ctx)
{
struct ChoChord *chord = emalloc(sizeof(struct ChoChord));
- chord->style = cho_style_new_default();
+ chord->style = cho_style_new_default(ctx);
chord->name = NULL;
chord->is_canonical = false;
chord->root = NULL;
@@ -2016,7 +2014,7 @@ cho_chord_root_parse(struct ChoContext *ctx, const char *str, struct ChoChord *c
char *transposed_root;
int i;
for (i = 0; i<7; i++) {
- sharp = g_config->parser->notes[i]->sharp;
+ sharp = ctx->config->parser->notes[i]->sharp;
if (sharp && str_starts_with(str, sharp)) {
transposed_root = transposition_calc_chord_root(ctx, i, NT_SHARP);
if (!transposed_root) {
@@ -2026,7 +2024,7 @@ cho_chord_root_parse(struct ChoContext *ctx, const char *str, struct ChoChord *c
chord->root = transposed_root;
return strlen(sharp);
}
- flat = g_config->parser->notes[i]->flat;
+ flat = ctx->config->parser->notes[i]->flat;
if (flat && str_starts_with(str, flat)) {
transposed_root = transposition_calc_chord_root(ctx, i, NT_FLAT);
if (!transposed_root) {
@@ -2036,7 +2034,7 @@ cho_chord_root_parse(struct ChoContext *ctx, const char *str, struct ChoChord *c
chord->root = transposed_root;
return strlen(flat);
}
- note = g_config->parser->notes[i]->note;
+ note = ctx->config->parser->notes[i]->note;
if (str_starts_with(str, note)) {
transposed_root = transposition_calc_chord_root(ctx, i, NT_NOTE);
if (!transposed_root) {
@@ -2103,7 +2101,7 @@ cho_chord_qualifier_and_extension_parse(const char *str, struct ChoChord *chord)
}
static int
-cho_chord_bass_parse(const char *str, struct ChoChord *chord)
+cho_chord_bass_parse(struct ChoContext *ctx, const char *str, struct ChoChord *chord)
{
if (str[0] == '/') {
const char *note = NULL;
@@ -2114,20 +2112,20 @@ cho_chord_bass_parse(const char *str, struct ChoChord *chord)
const char *out_flat = NULL;
int i;
for (i = 0; i<7; i++) {
- sharp = g_config->parser->notes[i]->sharp;
- out_sharp = g_config->output->notes[i]->sharp;
+ sharp = ctx->config->parser->notes[i]->sharp;
+ out_sharp = ctx->config->output->notes[i]->sharp;
if (sharp && !strcmp((char *)&str[1], sharp)) {
chord->bass = strdup(out_sharp);
return strlen(sharp) + 1;
}
- flat = g_config->parser->notes[i]->flat;
- out_flat = g_config->output->notes[i]->flat;
+ flat = ctx->config->parser->notes[i]->flat;
+ out_flat = ctx->config->output->notes[i]->flat;
if (flat && !strcmp((char *)&str[1], flat)) {
chord->bass = strdup(out_flat);
return strlen(flat) + 1;
}
- note = g_config->parser->notes[i]->note;
- out_note = g_config->parser->notes[i]->note;
+ note = ctx->config->parser->notes[i]->note;
+ out_note = ctx->config->parser->notes[i]->note;
if (!strcmp((char *)&str[1], note)) {
chord->bass = strdup(out_note);
return strlen(note) + 1;
@@ -2140,7 +2138,7 @@ cho_chord_bass_parse(const char *str, struct ChoChord *chord)
static struct ChoChord *
cho_chord_parse(struct ChoContext *ctx, const char *str)
{
- struct ChoChord *chord = cho_chord_new();
+ struct ChoChord *chord = cho_chord_new(ctx);
size_t str_len = strlen(str);
size_t bytes_parsed = 0;
int ret;
@@ -2161,7 +2159,7 @@ cho_chord_parse(struct ChoContext *ctx, const char *str)
chord->is_canonical = true;
return chord;
}
- ret = cho_chord_bass_parse((const char *)&str[bytes_parsed], chord);
+ ret = cho_chord_bass_parse(ctx, (const char *)&str[bytes_parsed], chord);
bytes_parsed += ret;
if (bytes_parsed == str_len) {
chord->is_canonical = true;
@@ -2294,12 +2292,12 @@ cho_image_copy(struct ChoImage *image)
}
static struct ChoImage *
-cho_image_find_asset(const char *id)
+cho_image_find_asset(struct ChoContext *ctx, const char *id)
{
int i;
- for (i = 0; i<g_ia; i++) {
- if (!strcmp(g_image_assets[i]->id, id)) {
- return g_image_assets[i];
+ for (i = 0; i<ctx->ia; i++) {
+ if (!strcmp(ctx->image_assets[i]->id, id)) {
+ return ctx->image_assets[i];
}
}
return NULL;
@@ -2390,7 +2388,7 @@ cho_debug_image_print(struct ChoImage *image)
#endif /* DEBUG */
static bool
-cho_image_option_parse(struct ChoImage *image, const char *name, const char *value)
+cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const char *name, const char *value)
{
char *endptr;
struct Size *size;
@@ -2407,11 +2405,11 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(name, "width")) {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'width' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'width' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'width' in image directive. Allowed types are: points, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'width' in image directive. Allowed types are: points, percentage.");
return false;
}
image->width = size;
@@ -2419,11 +2417,11 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(name, "height")) {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'height' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'height' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'height' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'height' in image directive. Allowed types are: point, percentage.");
return false;
}
image->height = size;
@@ -2434,32 +2432,32 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
*comma = 0;
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'scale' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
return false;
}
image->width_scale = size;
size = size_create(++comma);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'scale' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
return false;
}
image->height_scale = size;
} else {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'scale' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
return false;
}
image->width_scale = size;
@@ -2476,7 +2474,7 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(value, "center")) {
image->align = A_CENTER;
} else {
- cho_log(LOG_ERR, "Invalid value in option 'align' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'align' in image directive.");
return false;
}
} else
@@ -2490,11 +2488,11 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(name, "spread")) {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'spread' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'spread' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'spread' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'spread' in image directive. Allowed types are: point, percentage.");
return false;
}
image->spread_space = size;
@@ -2505,11 +2503,11 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(name, "x")) {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'x' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'x' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'x' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'x' in image directive. Allowed types are: point, percentage.");
return false;
}
image->x = size;
@@ -2517,11 +2515,11 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(name, "y")) {
size = size_create(value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in option 'y' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'y' in image directive.");
return false;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in option 'y' in image directive. Allowed types are: point, percentage.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in option 'y' in image directive. Allowed types are: point, percentage.");
return false;
}
image->y = size;
@@ -2542,7 +2540,7 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
if (!strcmp(value, "float")) {
image->anchor = AN_FLOAT;
} else {
- cho_log(LOG_ERR, "Invalid value in option 'anchor' in image directive.");
+ cho_log(ctx, LOG_ERR, "Invalid value in option 'anchor' in image directive.");
return false;
}
}
@@ -2550,7 +2548,7 @@ cho_image_option_parse(struct ChoImage *image, const char *name, const char *val
}
static struct ChoImage *
-cho_image_directive_parse(const char *str)
+cho_image_directive_parse(struct ChoContext *ctx, const char *str)
{
struct ChoImage *image = cho_image_new();
struct ChoImage *asset;
@@ -2574,7 +2572,7 @@ cho_image_directive_parse(const char *str)
break;
} else {
name[n] = 0;
- cho_log(LOG_ERR, "Option with name '%s' in image directive has no value.", name);
+ cho_log(ctx, LOG_ERR, "Option with name '%s' in image directive has no value.", name);
return NULL;
}
}
@@ -2584,7 +2582,7 @@ cho_image_directive_parse(const char *str)
break;
}
if (n > 5) {
- cho_log(LOG_ERR, "Option name in image directive is too long.");
+ cho_log(ctx, LOG_ERR, "Option name in image directive is too long.");
return NULL;
}
name[n] = c;
@@ -2593,7 +2591,7 @@ cho_image_directive_parse(const char *str)
case OS_VALUE:
if (avs == -1) {
if (is_whitespace(c)) {
- cho_log(LOG_ERR, "Whitespace character after equals sign in image directive is invalid.");
+ cho_log(ctx, LOG_ERR, "Whitespace character after equals sign in image directive is invalid.");
return NULL;
}
if (c == '\'') {
@@ -2608,7 +2606,7 @@ cho_image_directive_parse(const char *str)
break;
}
if (c == '\n') {
- cho_log(LOG_ERR, "Newline character inside an option value in image directive is invalid.");
+ cho_log(ctx, LOG_ERR, "Newline character inside an option value in image directive is invalid.");
return NULL;
}
if (
@@ -2617,8 +2615,8 @@ cho_image_directive_parse(const char *str)
(avs == AVS_UNQUOTED && (c == ' ' || c == '\t'))
) {
value[v] = 0;
- if (!cho_image_option_parse(image, name, value)) {
- LOG_DEBUG("cho_image_option_check failed.");
+ if (!cho_image_option_parse(ctx, image, name, value)) {
+ LOG_DEBUG("cho_image_option_parse failed.");
return NULL;
}
option_count++;
@@ -2637,8 +2635,8 @@ cho_image_directive_parse(const char *str)
}
if (avs == AVS_UNQUOTED) {
value[v] = 0;
- if (!cho_image_option_parse(image, name, value)) {
- LOG_DEBUG("cho_image_option_check failed.");
+ if (!cho_image_option_parse(ctx, image, name, value)) {
+ LOG_DEBUG("cho_image_option_parse failed.");
return NULL;
}
option_count++;
@@ -2646,14 +2644,14 @@ cho_image_directive_parse(const char *str)
if (image->id) {
if (image->src) {
if (option_count > 2) {
- cho_log(LOG_ERR, "Defining an image asset disallows any options other than 'id' and 'src'.");
+ cho_log(ctx, LOG_ERR, "Defining an image asset disallows any options other than 'id' and 'src'.");
return NULL;
}
image->is_asset = true;
} else {
- asset = cho_image_find_asset(image->id);
+ asset = cho_image_find_asset(ctx, image->id);
if (!asset) {
- cho_log(LOG_ERR, "There is no image asset with the id '%s'.", image->id);
+ cho_log(ctx, LOG_ERR, "There is no image asset with the id '%s'.", image->id);
return NULL;
}
image->src = strdup(asset->src);
@@ -2663,7 +2661,7 @@ cho_image_directive_parse(const char *str)
}
static struct ChoImage *
-cho_image_tag_parse(struct Attr **attrs)
+cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
{
struct ChoImage *image = cho_image_new();
struct ChoImage *asset;
@@ -2683,11 +2681,11 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->name, "width")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'width' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'width' in 'img' tag.");
return NULL;
}
if (size->type == ST_PERCENT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'width' in 'img' tag. Allowed types are: point, em, ex.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'width' in 'img' tag. Allowed types are: point, em, ex.");
return NULL;
}
image->width = size;
@@ -2695,11 +2693,11 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->name, "height")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'height' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'height' in 'img' tag.");
return NULL;
}
if (size->type == ST_PERCENT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'height' in 'img' tag. Allowed types are: point, em, ex.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'height' in 'img' tag. Allowed types are: point, em, ex.");
return NULL;
}
image->height = size;
@@ -2707,11 +2705,11 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->name, "dx")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'dx' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'dx' in 'img' tag.");
return NULL;
}
if (size->type == ST_PERCENT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'dx' in 'img' tag. Allowed types are: point, em, ex.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'dx' in 'img' tag. Allowed types are: point, em, ex.");
return NULL;
}
image->dx = size;
@@ -2719,11 +2717,11 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->name, "dy")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'dy' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'dy' in 'img' tag.");
return NULL;
}
if (size->type == ST_PERCENT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'dy' in 'img' tag. Allowed types are: point, em, ex.");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'dy' in 'img' tag. Allowed types are: point, em, ex.");
return NULL;
}
image->dy = size;
@@ -2734,32 +2732,32 @@ cho_image_tag_parse(struct Attr **attrs)
*comma = 0;
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
return NULL;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
return NULL;
}
image->width_scale = size;
size = size_create(++comma);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
return NULL;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
return NULL;
}
image->height_scale = size;
} else {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
return NULL;
}
if (size->type == ST_EM || size->type == ST_EX) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
return NULL;
}
image->width_scale = size;
@@ -2776,7 +2774,7 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->value, "center")) {
image->align = A_CENTER;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'align' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'align' in 'img' tag.");
return NULL;
}
} else
@@ -2787,18 +2785,18 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->value, "0")) {
image->bbox = false;
} else {
- cho_log(LOG_ERR, "Invalid value in attribute 'bbox' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'bbox' in 'img' tag.");
return NULL;
}
} else
if (!strcmp(attrs[a]->name, "w")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'w' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'w' in 'img' tag.");
return NULL;
}
if (size->type != ST_POINT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'w' in 'img' tag. Allowed type is: point");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'w' in 'img' tag. Allowed type is: point");
return NULL;
}
image->w = size;
@@ -2806,34 +2804,34 @@ cho_image_tag_parse(struct Attr **attrs)
if (!strcmp(attrs[a]->name, "h")) {
size = size_create(attrs[a]->value);
if (!size) {
- cho_log(LOG_ERR, "Invalid value in attribute 'h' in 'img' tag.");
+ cho_log(ctx, LOG_ERR, "Invalid value in attribute 'h' in 'img' tag.");
return NULL;
}
if (size->type != ST_POINT) {
- cho_log(LOG_ERR, "Invalid type of value in attribute 'h' in 'img' tag. Allowed type is: point");
+ cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'h' in 'img' tag. Allowed type is: point");
return NULL;
}
image->h = size;
} else {
- cho_log(LOG_ERR, "Invalid attribute '%s' in 'img' tag.", attrs[a]->name);
+ cho_log(ctx, LOG_ERR, "Invalid attribute '%s' in 'img' tag.", attrs[a]->name);
return NULL;
}
}
if (image->id) {
if (image->src) {
- cho_log(LOG_ERR, "'img' tag can't have both attributes 'id' and 'src' at the same time.");
+ cho_log(ctx, LOG_ERR, "'img' tag can't have both attributes 'id' and 'src' at the same time.");
return NULL;
} else {
- asset = cho_image_find_asset(image->id);
+ asset = cho_image_find_asset(ctx, image->id);
if (!asset) {
- cho_log(LOG_ERR, "There is no image asset with the id '%s'.", image->id);
+ cho_log(ctx, LOG_ERR, "There is no image asset with the id '%s'.", image->id);
return NULL;
}
image->src = strdup(asset->src);
}
} else {
if (!image->src) {
- cho_log(LOG_ERR, "'img' tag has to have at least either the attribute 'id' or 'src'.");
+ cho_log(ctx, LOG_ERR, "'img' tag has to have at least either the attribute 'id' or 'src'.");
return NULL;
}
}
@@ -2866,6 +2864,7 @@ finger_to_int(char c)
static struct ChordDiagram *
cho_chord_diagram_parse(
+ struct ChoContext *ctx,
const char *str,
struct ChordDiagram **custom_diagrams,
int custom_diagrams_len
@@ -2903,7 +2902,7 @@ cho_chord_diagram_parse(
break;
}
if (i > 18) {
- cho_log(LOG_ERR, "Chord name in chord diagram is too long.");
+ cho_log(ctx, LOG_ERR, "Chord name in chord diagram is too long.");
return NULL;
}
name[i] = *c;
@@ -2939,7 +2938,7 @@ cho_chord_diagram_parse(
if (!strcmp(option, "copy")) {
state = CDS_COPY;
} else {
- cho_log(LOG_ERR, "Invalid option '%s' in define directive.", option);
+ cho_log(ctx, LOG_ERR, "Invalid option '%s' in define directive.", option);
return NULL;
}
memset(option, 0, i);
@@ -2958,13 +2957,13 @@ cho_chord_diagram_parse(
diagram->u.kd->name = strdup(name);
break;
default:
- cho_log(LOG_ERR, "'future_content' cannot be empty at this point.\n");
+ cho_log(ctx, LOG_ERR, "'future_content' cannot be empty at this point.\n");
}
}
break;
}
if (i > 8) {
- cho_log(LOG_ERR, "Option in chord diagram is too long.");
+ cho_log(ctx, LOG_ERR, "Option in chord diagram is too long.");
return NULL;
}
option[i] = *c;
@@ -2981,11 +2980,11 @@ cho_chord_diagram_parse(
l = str_to_number(base_fret);
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
- cho_log(LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
return NULL;
}
if (l == 0) {
- cho_log(LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
return NULL;
}
diagram->u.sd->base_fret = (int8_t)l;
@@ -2993,7 +2992,7 @@ cho_chord_diagram_parse(
break;
}
if (i > 1) {
- cho_log(LOG_ERR, "base-fret value is too long.");
+ cho_log(ctx, LOG_ERR, "base-fret value is too long.");
printf("c: %c\n", *c);
return NULL;
}
@@ -3015,7 +3014,7 @@ cho_chord_diagram_parse(
number = -1;
is_maybe_minus_one = false;
} else {
- cho_log(LOG_ERR, "Invalid frets value '-%c' in chord diagram.", *c);
+ cho_log(ctx, LOG_ERR, "Invalid frets value '-%c' in chord diagram.", *c);
return NULL;
}
}
@@ -3032,12 +3031,12 @@ cho_chord_diagram_parse(
number = char_to_positive_int(*c);
if (number == -1) {
LOG_DEBUG("char_to_positive_int failed.");
- cho_log(LOG_ERR, "Invalid frets value '%c' in chord diagram.", *c);
+ cho_log(ctx, LOG_ERR, "Invalid frets value '%c' in chord diagram.", *c);
return NULL;
}
}
if (f > 11) {
- cho_log(LOG_ERR, "Too many fret values in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Too many fret values in chord diagram.");
return NULL;
}
diagram->u.sd->frets[f] = number;
@@ -3057,11 +3056,11 @@ cho_chord_diagram_parse(
}
number = finger_to_int(*c);
if (number == -2) {
- cho_log(LOG_ERR, "Invalid fingers value '%c' in chord diagram.", *c);
+ cho_log(ctx, LOG_ERR, "Invalid fingers value '%c' in chord diagram.", *c);
return NULL;
}
if (f > 11) {
- cho_log(LOG_ERR, "Too many finger values in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Too many finger values in chord diagram.");
return NULL;
}
diagram->u.sd->fingers[f] = number;
@@ -3079,11 +3078,11 @@ cho_chord_diagram_parse(
l = str_to_number(key);
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
- cho_log(LOG_ERR, "Invalid number in keys in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Invalid number in keys in chord diagram.");
return NULL;
}
if (f > 23) {
- cho_log(LOG_ERR, "Too many key values in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Too many key values in chord diagram.");
return NULL;
}
diagram->u.kd->keys[f] = (int8_t)l;
@@ -3096,7 +3095,7 @@ cho_chord_diagram_parse(
break;
}
if (i > 1) {
- cho_log(LOG_ERR, "Too high key value in chord diagram. '%d'", i);
+ cho_log(ctx, LOG_ERR, "Too high key value in chord diagram. '%d'", i);
printf("key '%s'\n", key);
return NULL;
}
@@ -3138,13 +3137,13 @@ cho_chord_diagram_parse(
}
chord_to_copy[i] = 0;
if (current_content != -1) {
- cho_log(LOG_ERR, "The define options 'base-fret', 'frets', 'fingers' and 'keys' are not allowed before the 'copy' option.");
+ cho_log(ctx, LOG_ERR, "The define options 'base-fret', 'frets', 'fingers' and 'keys' are not allowed before the 'copy' option.");
return NULL;
}
- enum Instrument ins = g_config->output->diagram->instrument;
+ enum Instrument ins = ctx->config->output->diagram->instrument;
current_content = chord_diagram_duplicate(diagram, custom_diagrams, custom_diagrams_len, name, chord_to_copy, ins);
if (current_content == -1) {
- cho_log(LOG_ERR, "Can't copy the diagram for the chord '%s'"
+ cho_log(ctx, LOG_ERR, "Can't copy the diagram for the chord '%s'"
"because no previous definition was found and also"
"no predefined chord diagram for the instrument '%s'"
"was found.", chord_to_copy, instruments[ins]);
@@ -3167,11 +3166,11 @@ cho_chord_diagram_parse(
l = str_to_number(base_fret);
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
- cho_log(LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
return NULL;
}
if (l == 0) {
- cho_log(LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
return NULL;
}
diagram->u.sd->base_fret = (int8_t)l;
@@ -3183,11 +3182,11 @@ cho_chord_diagram_parse(
l = str_to_number(key);
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
- cho_log(LOG_ERR, "Invalid number in keys in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Invalid number in keys in chord diagram.");
return NULL;
}
if (f > 23) {
- cho_log(LOG_ERR, "Too many key values in chord diagram.");
+ cho_log(ctx, LOG_ERR, "Too many key values in chord diagram.");
return NULL;
}
diagram->u.kd->keys[f] = (int8_t)l;
@@ -3215,15 +3214,15 @@ cho_chord_diagram_parse(
case CDS_COPY: {
chord_to_copy[i] = 0;
if (current_content != -1) {
- cho_log(LOG_ERR, "The define options 'base-fret', 'frets',"
+ cho_log(ctx, LOG_ERR, "The define options 'base-fret', 'frets',"
"'fingers' and 'keys' are not allowed before the 'copy'"
"option.");
return NULL;
}
- enum Instrument ins = g_config->output->diagram->instrument;
+ enum Instrument ins = ctx->config->output->diagram->instrument;
current_content = chord_diagram_duplicate(diagram, custom_diagrams, custom_diagrams_len, name, chord_to_copy, ins);
if (current_content == -1) {
- cho_log(LOG_ERR, "Can't copy the diagram for the chord '%s' because"
+ cho_log(ctx, LOG_ERR, "Can't copy the diagram for the chord '%s' because"
"no previous definition was found and also no predefined"
"chord diagram for the instrument '%s' was found.",
chord_to_copy, instruments[ins]);
@@ -3239,17 +3238,17 @@ cho_chord_diagram_parse(
finger_count > 0 &&
fret_count != finger_count
) {
- cho_log(LOG_ERR, "The number of frets (%d) and fingers (%d) in the chord diagram must be equal.", fret_count, finger_count);
+ cho_log(ctx, LOG_ERR, "The number of frets (%d) and fingers (%d) in the chord diagram must be equal.", fret_count, finger_count);
return NULL;
}
return diagram;
}
static struct ChoText *
-cho_text_new(void)
+cho_text_new(struct ChoContext *ctx)
{
struct ChoText *text = emalloc(sizeof(struct ChoText));
- text->style = cho_style_new_default();
+ text->style = cho_style_new_default(ctx);
text->text = NULL;
return text;
}
@@ -3303,11 +3302,11 @@ cho_text_above_copy(struct ChoLineItemAbove *text_above)
}
static struct ChoLineItem *
-cho_line_item_new(void)
+cho_line_item_new(struct ChoContext *ctx)
{
struct ChoLineItem *item = emalloc(sizeof(struct ChoLineItem));
item->is_text = true;
- item->u.text = cho_text_new();
+ item->u.text = cho_text_new(ctx);
return item;
}
@@ -3448,10 +3447,10 @@ cho_section_copy(struct ChoSection *section)
}
static struct ChoSong *
-cho_song_new(void)
+cho_song_new(struct ChoContext *ctx)
{
struct ChoSong *song = emalloc(sizeof(struct ChoSong));
- song->metadata = cho_metadata_load_default();
+ song->metadata = cho_metadata_load_default(ctx);
if (!song->metadata) {
LOG_DEBUG("cho_metadata_load_default failed.");
return NULL;
@@ -3549,7 +3548,7 @@ cho_find_previous_chorus(struct ChoSection **sections, int se)
}
static struct ChoDirective *
-cho_directive_new(void)
+cho_directive_new(struct ChoContext *ctx)
{
struct ChoDirective *directive = emalloc(sizeof(struct ChoDirective));
directive->dtype = -1;
@@ -3560,7 +3559,7 @@ cho_directive_new(void)
directive->btype = -1;
directive->meta = -1;
directive->ctype = -1;
- directive->style = cho_style_new_default();
+ directive->style = cho_style_new_default(ctx);
return directive;
}
@@ -3575,9 +3574,9 @@ cho_directive_free(struct ChoDirective *directive)
}
static struct ChoDirective *
-cho_directive_parse(const char *name)
+cho_directive_parse(struct ChoContext *ctx, const char *name)
{
- struct ChoDirective *directive = cho_directive_new();
+ struct ChoDirective *directive = cho_directive_new(ctx);
if (
!strcmp(name, "start_of_chorus") ||
!strcmp(name, "soc")
@@ -3681,10 +3680,10 @@ cho_directive_parse(const char *name)
directive->dtype = DT_METADATA;
directive->meta = TITLE;
cho_style_free(directive->style);
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_TITLE;
- directive->style = cho_style_new_default();
- g_current_ttype = g_prev_ttype;
+ ctx->prev_ttype = ctx->current_ttype;
+ ctx->current_ttype = TT_TITLE;
+ directive->style = cho_style_new_default(ctx);
+ ctx->current_ttype = ctx->prev_ttype;
return directive;
} else if (
@@ -3694,10 +3693,10 @@ cho_directive_parse(const char *name)
directive->dtype = DT_METADATA;
directive->meta = SUBTITLE;
cho_style_free(directive->style);
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_SUBTITLE;
- directive->style = cho_style_new_default();
- g_current_ttype = g_prev_ttype;
+ ctx->prev_ttype = ctx->current_ttype;
+ ctx->current_ttype = TT_SUBTITLE;
+ directive->style = cho_style_new_default(ctx);
+ ctx->current_ttype = ctx->prev_ttype;
return directive;
}
if (
@@ -3725,11 +3724,11 @@ cho_directive_parse(const char *name)
!strcmp(name, "highlight")
) {
directive->dtype = DT_FORMATTING;
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_COMMENT;
+ ctx->prev_ttype = ctx->current_ttype;
+ ctx->current_ttype = TT_COMMENT;
cho_style_free(directive->style);
- directive->style = cho_style_new_default();
- g_current_ttype = g_prev_ttype;
+ directive->style = cho_style_new_default(ctx);
+ ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TT_COMMENT;
return directive;
} else if (
@@ -3737,11 +3736,11 @@ cho_directive_parse(const char *name)
!strcmp(name, "ci")
) {
directive->dtype = DT_FORMATTING;
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_COMMENT_ITALIC;
+ ctx->prev_ttype = ctx->current_ttype;
+ ctx->current_ttype = TT_COMMENT_ITALIC;
cho_style_free(directive->style);
- directive->style = cho_style_new_default();
- g_current_ttype = g_prev_ttype;
+ directive->style = cho_style_new_default(ctx);
+ ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TT_COMMENT_ITALIC;
return directive;
} else if (
@@ -3749,11 +3748,11 @@ cho_directive_parse(const char *name)
!strcmp(name, "cb")
) {
directive->dtype = DT_FORMATTING;
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_COMMENT_BOX;
+ ctx->prev_ttype = ctx->current_ttype;
+ ctx->current_ttype = TT_COMMENT_BOX;
cho_style_free(directive->style);
- directive->style = cho_style_new_default();
- g_current_ttype = g_prev_ttype;
+ directive->style = cho_style_new_default(ctx);
+ ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TT_COMMENT_BOX;
return directive;
}
@@ -3937,7 +3936,7 @@ cho_directive_parse(const char *name)
}
static char *
-cho_directive_label_parse(const char *directive_name, const char *str)
+cho_directive_label_parse(struct ChoContext *ctx, const char *directive_name, const char *str)
{
char *label_name = NULL;
char c;
@@ -3959,14 +3958,14 @@ cho_directive_label_parse(const char *directive_name, const char *str)
break;
} else {
name[n] = 0;
- cho_log(LOG_ERR, "Option with name '%s' in environment directive '%s' has no value.", name, directive_name);
+ cho_log(ctx, LOG_ERR, "Option with name '%s' in environment directive '%s' has no value.", name, directive_name);
return NULL;
}
}
if (c == '=') {
name[n] = 0;
if (strcmp(name, "label") != 0) {
- cho_log(LOG_ERR, "Invalid option name '%s' in environment directive '%s'.", name, directive_name);
+ cho_log(ctx, LOG_ERR, "Invalid option name '%s' in environment directive '%s'.", name, directive_name);
}
memset(name, 0, n);
n = 0;
@@ -3974,7 +3973,7 @@ cho_directive_label_parse(const char *directive_name, const char *str)
break;
}
if (n > 4) {
- cho_log(LOG_ERR, "Option name in environment directive '%s' is too long.", directive_name);
+ cho_log(ctx, LOG_ERR, "Option name in environment directive '%s' is too long.", directive_name);
return NULL;
}
name[n] = c;
@@ -3983,7 +3982,7 @@ cho_directive_label_parse(const char *directive_name, const char *str)
case OS_VALUE:
if (avs == -1) {
if (is_whitespace(c)) {
- cho_log(LOG_ERR, "Whitespace character after equals sign in environment directive '%s' is invalid.", directive_name);
+ cho_log(ctx, LOG_ERR, "Whitespace character after equals sign in environment directive '%s' is invalid.", directive_name);
return NULL;
}
if (c == '\'') {
@@ -3998,7 +3997,7 @@ cho_directive_label_parse(const char *directive_name, const char *str)
break;
}
if (c == '\n') {
- cho_log(LOG_ERR, "Newline character inside an option value in environment directive '%s' is invalid.", directive_name);
+ cho_log(ctx, LOG_ERR, "Newline character inside an option value in environment directive '%s' is invalid.", directive_name);
return NULL;
}
if (
@@ -4027,16 +4026,23 @@ cho_directive_label_parse(const char *directive_name, const char *str)
}
static bool
-cho_context_init(struct ChoContext *ctx)
+cho_context_init(
+ struct ChoContext *ctx,
+ struct Config *config,
+ const char *chordpro_filepath
+)
{
ctx->is_chord_already_initialized = false;
ctx->is_maybe_end_of_tab_directive = false;
ctx->directive_has_tag = false;
+ ctx->chordpro_filepath = chordpro_filepath;
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->current_ttype = TT_TEXT;
+ ctx->prev_ttype = TT_TEXT;
ctx->ann = 0;
ctx->at = 0;
ctx->atn = 0;
@@ -4045,6 +4051,7 @@ cho_context_init(struct ChoContext *ctx)
ctx->dia = 0;
ctx->dn = 0;
ctx->dv = 0;
+ ctx->ia = 0;
ctx->li = 0;
ctx->lia = 0;
ctx->lii = 0;
@@ -4057,15 +4064,18 @@ cho_context_init(struct ChoContext *ctx)
ctx->te = 0;
ctx->th = 0;
ctx->nested_level = 0;
+ ctx->line_number = 1;
ctx->tags = NULL;
+ ctx->image_assets = 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->config = config;
ctx->songs = emalloc(sizeof(struct ChoSong *));
- ctx->songs[ctx->so] = cho_song_new();
+ ctx->songs[ctx->so] = cho_song_new(ctx);
if (!ctx->songs[ctx->so]) {
LOG_DEBUG("cho_song_new failed.");
return false;
@@ -4104,23 +4114,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
int transpose;
size_t read;
- g_config = config;
- g_chordpro_filepath = chordpro_filepath;
-
- if (!cho_context_init(&ctx)) {
+ if (!cho_context_init(&ctx, config, chordpro_filepath)) {
LOG_DEBUG("cho_context_init failed.");
return NULL;
}
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
ctx.songs[ctx.so]->present_text_types[TT_TOC] = config->output->toc->show;
while (feof(fp) == 0) {
read = fread(&c, 1, 1, fp);
if (read == 1) {
if (c == '\n') {
- g_line_number++;
+ ctx.line_number++;
}
// printf("state: %s, buf: %c\n", state_enums[state], buf);
if (c == '\r') {
@@ -4155,7 +4162,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
ctx.state_before_tag = STATE_LYRICS;
ctx.state = STATE_MARKUP_TAG;
break;
@@ -4173,7 +4180,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
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.");
+ cho_log(&ctx, LOG_ERR, "Tag has to be closed on same line.");
return NULL;
}
if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
@@ -4191,7 +4198,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
break;
}
}
@@ -4212,7 +4219,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
break;
}
(*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
@@ -4235,14 +4242,14 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
if (c == '}') {
directive_name[ctx.dn] = 0;
ctx.dn = 0;
- directive = cho_directive_parse(directive_name);
+ directive = cho_directive_parse(&ctx, directive_name);
/* printf(
"directive: '%s'\ndtype: %s, stype: %s, position: %s\n",
directive_name, cho_debug_dtype(directive->dtype), cho_debug_the_stype(directive->stype), cho_debug_the_pos(directive->position)
); */
switch (directive->dtype) {
case DT_ENVIRONMENT: {
- g_current_ttype = directive->ttype;
+ ctx.current_ttype = directive->ttype;
switch (directive->position) {
case POS_START: {
if (directive->stype == ST_CUSTOM) {
@@ -4263,7 +4270,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
ctx.songs[ctx.so]->present_text_types[directive->ttype] = true;
break;
}
@@ -4287,7 +4294,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
}
break;
}
@@ -4321,7 +4328,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
} else {
if (chorus->label) {
label = strdup(chorus->label->text);
@@ -4340,16 +4347,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
- g_current_ttype = TT_LABEL;
- (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ ctx.current_ttype = TT_LABEL;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default(&ctx);
(*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.");
+ cho_log(&ctx, LOG_WARN, "Can't quote chorus because it's not defined previously.");
}
label = strdup(config->output->chorus->label);
if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
@@ -4364,29 +4371,29 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
- g_current_ttype = TT_LABEL;
- (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ ctx.current_ttype = TT_LABEL;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default(&ctx);
(*lines)[ctx.li]->items[ctx.lii]->u.text->text = label;
ctx.te += strlen(label);
}
break;
}
default:
- cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position);
+ cho_log(&ctx, LOG_ERR, "Invalid position value '%d'.", directive->position);
return NULL;
}
break;
}
case DT_METADATA:
- cho_log(LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
+ cho_log(&ctx, LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
break;
case DT_FORMATTING:
- cho_log(LOG_WARN, "Formatting directive '%s' has no value.", directive_name);
+ cho_log(&ctx, LOG_WARN, "Formatting directive '%s' has no value.", directive_name);
break;
case DT_IMAGE:
- cho_log(LOG_ERR, "Directive 'image' has no value.");
+ cho_log(&ctx, LOG_ERR, "Directive 'image' has no value.");
return NULL;
case DT_PREAMBLE: {
// INFO: The only preamble directive is 'new_song'
@@ -4401,13 +4408,13 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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()) {
+ if (!cho_style_reset_default(&ctx)) {
LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
ctx.so++;
ctx.songs = erealloc(ctx.songs, (ctx.so+1) * sizeof(struct ChoSong *));
- ctx.songs[ctx.so] = cho_song_new();
+ ctx.songs[ctx.so] = cho_song_new(&ctx);
if (!ctx.songs[ctx.so]) {
LOG_DEBUG("cho_song_new failed.");
return NULL;
@@ -4423,7 +4430,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
break;
}
case DT_FONT: {
@@ -4440,10 +4447,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
sprop.u.foreground_color = NULL;
break;
default:
- cho_log(LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
+ cho_log(&ctx, LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
return NULL;
}
- if (!cho_style_change_default(sprop)) {
+ if (!cho_style_change_default(&ctx, sprop)) {
LOG_DEBUG("cho_style_change_default failed.");
return NULL;
}
@@ -4456,7 +4463,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.th--;
break;
case DEFINE:
- cho_log(LOG_WARN, "Ignoring chord directive '%s' because it has no value.", directive_name);
+ cho_log(&ctx, LOG_WARN, "Ignoring chord directive '%s' because it has no value.", directive_name);
break;
}
break;
@@ -4470,10 +4477,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
// INFO: Such a directive should not be logged.
break;
case DT_CUSTOM:
- cho_log(LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
+ cho_log(&ctx, LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
break;
default:
- cho_log(LOG_ERR, "Invalid directive '%s'.", directive_name);
+ cho_log(&ctx, LOG_ERR, "Invalid directive '%s'.", directive_name);
return NULL;
}
if (directive->stype == ST_TAB) {
@@ -4486,7 +4493,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
if (c == '{') {
- cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
+ cho_log(&ctx, LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
if (c == '\n') {
@@ -4496,7 +4503,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.dn--;
break;
}
- cho_log(LOG_ERR, "Can't have a newline in a directive name.");
+ cho_log(&ctx, LOG_ERR, "Can't have a newline in a directive name.");
return NULL;
}
if (c == ':' || c == ' ') {
@@ -4514,7 +4521,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
directive_value[ctx.dv] = 0;
ctx.dv = 0;
stripped_directive_value = str_remove_leading_whitespace(directive_value);
- directive = cho_directive_parse(directive_name);
+ directive = cho_directive_parse(&ctx, directive_name);
/* printf(
"directive: '%s'\ndtype: %s, stype: %s, position: %s\n",
directive_name, dtype(directive->dtype), the_stype(directive->stype), pos(directive->position)
@@ -4524,7 +4531,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
if (strlen(stripped_directive_value) > 0) {
ctx.songs[ctx.so]->present_text_types[TT_LABEL] = true;
}
- g_current_ttype = directive->ttype;
+ ctx.current_ttype = directive->ttype;
switch (directive->position) {
case POS_START: {
if (directive->stype == ST_CUSTOM) {
@@ -4542,17 +4549,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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);
+ label = cho_directive_label_parse(&ctx, directive_name, directive_value);
if (!label) {
LOG_DEBUG("cho_directive_label_parse failed.");
- cho_log(LOG_ERR, "Failed to parse the section label. You have to ways of specifying a label:\n\t\t\t1. {start_of_*: label=\"Label name\"}\n\t\t\t2. {start_of*: Label name}");
+ cho_log(&ctx, 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;
}
ctx.songs[ctx.so]->sections[ctx.se]->label->text = label;
} else {
ctx.songs[ctx.so]->sections[ctx.se]->label->text = strdup(stripped_directive_value);
}
- ctx.songs[ctx.so]->sections[ctx.se]->label->style = cho_style_new_from_config(TT_LABEL);
+ ctx.songs[ctx.so]->sections[ctx.se]->label->style = cho_style_new_from_config(&ctx, 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;
@@ -4562,7 +4569,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
ctx.songs[ctx.so]->present_text_types[directive->ttype] = true;
break;
}
@@ -4581,7 +4588,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
}
break;
}
@@ -4614,8 +4621,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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;
- ctx.songs[ctx.so]->sections[ctx.se]->label = cho_text_new();
+ ctx.current_ttype = TT_LABEL;
+ ctx.songs[ctx.so]->sections[ctx.se]->label = cho_text_new(&ctx);
ctx.songs[ctx.so]->sections[ctx.se]->label->text = label;
}
if (ctx.directive_has_tag) {
@@ -4629,7 +4636,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
} else {
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));
@@ -4643,10 +4650,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
- g_current_ttype = TT_LABEL;
- (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ ctx.current_ttype = TT_LABEL;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default(&ctx);
(*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);
@@ -4656,7 +4663,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
} else {
if (config->output->chorus->quote) {
- cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously.");
+ cho_log(&ctx, LOG_WARN, "Can't quote chorus because it's not defined previously.");
}
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));
@@ -4670,10 +4677,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
cho_style_free((*lines)[ctx.li]->items[ctx.lii]->u.text->style);
- g_current_ttype = TT_LABEL;
- (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default();
+ ctx.current_ttype = TT_LABEL;
+ (*lines)[ctx.li]->items[ctx.lii]->u.text->style = cho_style_new_default(&ctx);
(*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);
@@ -4683,7 +4690,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
default:
- cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position);
+ cho_log(&ctx, LOG_ERR, "Invalid position value '%d'.", directive->position);
return NULL;
}
break;
@@ -4691,14 +4698,14 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case DT_METADATA: {
metadata_value = strdup(stripped_directive_value);
if (strlen(metadata_value) == 0) {
- cho_log(LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
+ cho_log(&ctx, LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
free(metadata_value);
break;
}
switch (directive->meta) {
case TITLE:
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] = cho_metadata_new(&ctx);
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);
@@ -4707,7 +4714,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
case SUBTITLE:
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] = cho_metadata_new(&ctx);
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);
@@ -4716,7 +4723,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
default:
if (!strcmp(directive_name, "meta")) {
- metadata = cho_metadata_split(directive_value);
+ metadata = cho_metadata_split(&ctx, directive_value);
if (!metadata) {
LOG_DEBUG("cho_metadata_split failed.");
return NULL;
@@ -4726,7 +4733,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
free(metadata_value);
} else {
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] = cho_metadata_new(&ctx);
ctx.songs[ctx.so]->metadata[ctx.m]->name = strdup(directive_name);
ctx.songs[ctx.so]->metadata[ctx.m]->value = metadata_value;
}
@@ -4751,7 +4758,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
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);
@@ -4765,7 +4772,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
case DT_IMAGE: {
if (strstr(directive_value, "=")) {
- image = cho_image_directive_parse(directive_value);
+ image = cho_image_directive_parse(&ctx, directive_value);
if (!image) {
LOG_DEBUG("cho_image_directive_parse failed.");
return NULL;
@@ -4775,9 +4782,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
image->src = strdup(stripped_directive_value);
}
if (image->is_asset) {
- g_image_assets = erealloc(g_image_assets, (g_ia+1) * sizeof(struct ChoImage *));
- g_image_assets[g_ia] = image;
- g_ia++;
+ ctx.image_assets = erealloc(ctx.image_assets, (ctx.ia+1) * sizeof(struct ChoImage *));
+ ctx.image_assets[ctx.ia] = image;
+ ctx.ia++;
} else {
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));
@@ -4786,7 +4793,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
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;
@@ -4794,7 +4801,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
case DT_PREAMBLE:
- cho_log(LOG_ERR, "Preamble directive '%s' can't have a value.", directive_name);
+ cho_log(&ctx, LOG_ERR, "Preamble directive '%s' can't have a value.", directive_name);
return NULL;
case DT_FONT: {
sprop.ttype = directive->ttype;
@@ -4808,7 +4815,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case SPT_SIZE:
sprop.u.font_size = strtod(dir_value, NULL);
if (sprop.u.font_size == 0.0) {
- cho_log(LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
+ cho_log(&ctx, LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
return NULL;
}
sprop.type = SPT_SIZE;
@@ -4816,16 +4823,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case SPT_COLOR:
sprop.u.foreground_color = cho_color_parse(dir_value);
if (sprop.u.foreground_color == NULL) {
- cho_log(LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
+ cho_log(&ctx, LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
return NULL;
}
sprop.type = SPT_COLOR;
break;
default:
- cho_log(LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
+ cho_log(&ctx, LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
return NULL;
}
- if (!cho_style_change_default(sprop)) {
+ if (!cho_style_change_default(&ctx, sprop)) {
LOG_DEBUG("cho_style_change_default failed.");
return NULL;
}
@@ -4842,7 +4849,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
case TRANSPOSE:
if (!transposition_parse(directive_value, &transpose)) {
LOG_DEBUG("transposition_parse failed.");
- cho_log(LOG_ERR, "Directive 'transpose' has an invalid value.");
+ cho_log(&ctx, LOG_ERR, "Directive 'transpose' has an invalid value.");
return NULL;
}
ctx.transpose_history = erealloc(ctx.transpose_history, (ctx.th+1) * sizeof(int *));
@@ -4851,7 +4858,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.th++;
break;
case DEFINE:
- diagram = cho_chord_diagram_parse(directive_value, ctx.songs[ctx.so]->diagrams, ctx.dia);
+ diagram = cho_chord_diagram_parse(&ctx, directive_value, ctx.songs[ctx.so]->diagrams, ctx.dia);
if (!diagram) {
LOG_DEBUG("cho_chord_diagram_parse failed.");
return NULL;
@@ -4864,16 +4871,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
case DT_OUTPUT:
- cho_log(LOG_ERR, "Directive '%s' can't have a value.", directive_name);
+ cho_log(&ctx, LOG_ERR, "Directive '%s' can't have a value.", directive_name);
return NULL;
case DT_EXTENSION:
// INFO: Such a directive should not be logged.
break;
case DT_CUSTOM:
- cho_log(LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
+ cho_log(&ctx, LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
break;
default:
- cho_log(LOG_ERR, "Invalid directive type '%d'.", directive->dtype);
+ cho_log(&ctx, LOG_ERR, "Invalid directive type '%d'.", directive->dtype);
return NULL;
}
memset(directive_value, 0, strlen(directive_value));
@@ -4889,7 +4896,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
if (c == '{') {
- cho_log(LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
+ cho_log(&ctx, LOG_ERR, "Can't start a new directive if the previous one is not yet closed.");
return NULL;
}
if (c == '\n') {
@@ -4899,11 +4906,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.dv--;
break;
}
- cho_log(LOG_ERR, "Newline character inside a directive value is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside a directive value is invalid.");
return NULL;
}
if (ctx.dv > 4094) {
- cho_log(LOG_ERR, "Directive value can't be greater than 4095 bytes.");
+ cho_log(&ctx, LOG_ERR, "Directive value can't be greater than 4095 bytes.");
return NULL;
}
directive_value[ctx.dv] = c;
@@ -4914,15 +4921,15 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
if (c == ']') {
chord[ctx.ch] = 0;
ctx.ch = 0;
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_CHORD;
+ ctx.prev_ttype = ctx.current_ttype;
+ ctx.current_ttype = TT_CHORD;
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_log(&ctx, LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->name);
}
cho_chord_free(tmp_chord);
ctx.is_chord_already_initialized = false;
@@ -4934,25 +4941,25 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*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);
+ cho_log(&ctx, LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[ctx.li]->text_above[ctx.lia]->u.chord->name);
}
}
ctx.songs[ctx.so]->present_text_types[TT_CHORD] = true;
memset(chord, 0, strlen(chord));
ctx.lia++;
- g_current_ttype = g_prev_ttype;
+ ctx.current_ttype = ctx.prev_ttype;
ctx.state = STATE_LYRICS;
break;
}
if (prev_c == '[' && c == '*') {
- g_prev_ttype = g_current_ttype;
- g_current_ttype = TT_ANNOT;
+ ctx.prev_ttype = ctx.current_ttype;
+ ctx.current_ttype = TT_ANNOT;
(*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();
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot = cho_text_new(&ctx);
ctx.state = STATE_ANNOTATION;
break;
}
@@ -4963,11 +4970,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.ch--;
break;
}
- cho_log(LOG_ERR, "Newline character inside a chord is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside a chord is invalid.");
return NULL;
}
if (c == '[') {
- cho_log(LOG_ERR, "Can't start a new chord/annotation if the previous one is not yet closed.");
+ cho_log(&ctx, LOG_ERR, "Can't start a new chord/annotation if the previous one is not yet closed.");
return NULL;
}
if (c == '<') {
@@ -4975,7 +4982,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*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();
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.chord = cho_chord_new(&ctx);
ctx.is_chord_already_initialized = true;
}
ctx.state_before_tag = STATE_CHORD;
@@ -4993,7 +5000,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.songs[ctx.so]->present_text_types[TT_ANNOT] = true;
ctx.ann = 0;
ctx.lia++;
- g_current_ttype = g_prev_ttype;
+ ctx.current_ttype = ctx.prev_ttype;
ctx.state = STATE_LYRICS;
break;
}
@@ -5009,7 +5016,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.ann--;
break;
}
- cho_log(LOG_ERR, "Newline character inside an annotation is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside an annotation is invalid.");
return NULL;
}
(*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));
@@ -5043,8 +5050,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*lines = emalloc(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();
- g_current_ttype = TT_TEXT;
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
+ ctx.current_ttype = TT_TEXT;
ctx.state = STATE_LYRICS;
break;
} else {
@@ -5096,7 +5103,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
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.");
+ cho_log(&ctx, LOG_ERR, "Tag has to be closed on same line.");
return NULL;
}
if ((*lines)[ctx.li]->items[ctx.lii]->is_text) {
@@ -5114,7 +5121,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
break;
}
}
@@ -5135,7 +5142,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
break;
}
(*lines)[ctx.li]->items[ctx.lii]->u.text->text = erealloc((*lines)[ctx.li]->items[ctx.lii]->u.text->text, (ctx.te+1) * sizeof(char));
@@ -5163,11 +5170,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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.");
+ cho_log(&ctx, LOG_ERR, "'img' tag has to have at least the 'src' attribute.");
return NULL;
}
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);
+ tag_style = cho_style_parse(&ctx, 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;
@@ -5192,7 +5199,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*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();
+ (*lines)[ctx.li]->text_above[ctx.lia]->u.annot = cho_text_new(&ctx);
}
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);
@@ -5201,7 +5208,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
+ cho_log(&ctx, LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
memset(tag_start, 0, strlen(tag_start));
@@ -5224,11 +5231,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.t--;
break;
}
- cho_log(LOG_ERR, "Newline character inside a tag name is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside a tag name is invalid.");
return NULL;
}
if (ctx.t == 5) {
- cho_log(LOG_ERR, "Start tag name is too long.");
+ cho_log(&ctx, LOG_ERR, "Start tag name is too long.");
return NULL;
}
tag_start[ctx.t] = c;
@@ -5239,7 +5246,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
if (c == '>') {
tag_end[ctx.t] = 0;
ctx.t = 0;
- if (!cho_tag_close_last_unclosed(tag_end, ctx.tags, ctx.ta)) {
+ if (!cho_tag_close_last_unclosed(&ctx, tag_end, ctx.tags, ctx.ta)) {
LOG_DEBUG("cho_tag_close_last_unclosed failed.");
return NULL;
}
@@ -5254,11 +5261,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.t--;
break;
}
- cho_log(LOG_ERR, "Newline character inside a tag name is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside a tag name is invalid.");
return NULL;
}
if (ctx.t == 5) {
- cho_log(LOG_ERR, "End tag name is too long.");
+ cho_log(&ctx, LOG_ERR, "End tag name is too long.");
return NULL;
}
tag_end[ctx.t] = c;
@@ -5280,7 +5287,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
} else {
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);
+ cho_log(&ctx, LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
}
@@ -5292,7 +5299,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
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);
+ cho_log(&ctx, 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 (c == '>') {
@@ -5303,7 +5310,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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);
+ image = cho_image_tag_parse(&ctx, ctx.tags[ctx.ta]->attrs);
if (!image) {
LOG_DEBUG("cho_image_tag_parse failed.");
return NULL;
@@ -5311,9 +5318,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
} else {
- 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);
+ tag_style = cho_style_parse(&ctx, 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;
@@ -5336,7 +5343,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
+ cho_log(&ctx, LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
}
@@ -5348,7 +5355,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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);
+ cho_log(&ctx, LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", ctx.tags[ctx.ta]->attrs[ctx.at]->name, tag_start);
return NULL;
}
}
@@ -5359,7 +5366,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.atn--;
break;
}
- cho_log(LOG_ERR, "Newline character inside an tag attribute name is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside an tag attribute name is invalid.");
return NULL;
}
ctx.tags[ctx.ta]->attrs[ctx.at]->name = erealloc(ctx.tags[ctx.ta]->attrs[ctx.at]->name, (ctx.atn+1) * sizeof(char));
@@ -5375,16 +5382,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.atv--;
break;
}
- cho_log(LOG_ERR, "Newline character inside an attribute value is invalid.");
+ cho_log(&ctx, LOG_ERR, "Newline character inside an attribute value is invalid.");
return NULL;
}
if (avs == -1) {
if (is_whitespace(c)) {
- cho_log(LOG_ERR, "Whitespace character after equals sign is invalid.");
+ cho_log(&ctx, LOG_ERR, "Whitespace character after equals sign is invalid.");
return NULL;
}
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);
+ cho_log(&ctx, 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 (c == '\'') {
@@ -5409,7 +5416,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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);
+ image = cho_image_tag_parse(&ctx, ctx.tags[ctx.ta]->attrs);
if (!image) {
LOG_DEBUG("cho_image_tag_parse failed.");
return NULL;
@@ -5417,9 +5424,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*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();
+ (*lines)[ctx.li]->items[ctx.lii] = cho_line_item_new(&ctx);
} else {
- 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);
+ tag_style = cho_style_parse(&ctx, 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;
@@ -5442,7 +5449,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.directive_has_tag = true;
break;
default:
- cho_log(LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
+ cho_log(&ctx, LOG_ERR, "Invalid state_before_tag '%s'.", state_enums[ctx.state_before_tag]);
return NULL;
}
}
@@ -5521,7 +5528,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
ctx.nested_level++;
}
if (ctx.ms > 4094) {
- cho_log(LOG_ERR, "Metadata substitution can't be greater than 4095 bytes.");
+ cho_log(&ctx, LOG_ERR, "Metadata substitution can't be greater than 4095 bytes.");
return NULL;
}
metadata_substitution[ctx.ms] = c;
@@ -5560,7 +5567,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
(*lines)[ctx.li] = NULL;
}
}
- if (!cho_style_reset_default()) {
+ if (!cho_style_reset_default(&ctx)) {
LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
@@ -5574,20 +5581,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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;
+ ctx.current_ttype = TT_TEXT;
+ ctx.prev_ttype = TT_TEXT;
+ ctx.config = NULL;
+ ctx.chordpro_filepath = 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]);
+ ctx.line_number = 1;
+ for (e = 0; e<ctx.ia; e++) {
+ cho_image_free(ctx.image_assets[e]);
}
- free(g_image_assets);
- g_image_assets = NULL;
- g_ia = 0;
+ free(ctx.image_assets);
+ ctx.image_assets = NULL;
+ ctx.ia = 0;
bool exist_title = false;
for (ctx.so = 0; ctx.songs[ctx.so]; ctx.so++) {
for (ctx.m = 0; ctx.songs[ctx.so]->metadata[ctx.m]; ctx.m++) {
@@ -5600,9 +5607,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
}
if (!exist_title) {
- g_line_number = 0;
- /* INFO: This cho_log() is not line specific. It's a workaround. */
- cho_log(LOG_ERR, "Song has no title.");
+ ctx.line_number = 0;
+ /* INFO: This cho_log(ctx, ) is not line specific. It's a workaround. */
+ cho_log(&ctx, LOG_ERR, "Song has no title.");
return NULL;
}
exist_title = false;
diff --git a/src/chordpro.h b/src/chordpro.h
@@ -133,11 +133,14 @@ struct ChoContext {
bool is_chord_already_initialized;
bool is_maybe_end_of_tab_directive;
bool directive_has_tag;
+ const char *chordpro_filepath;
enum State state;
enum State state_before_comment;
enum State state_before_tag;
enum State state_before_backslash;
enum State state_before_metadata_substitution;
+ enum TextType current_ttype;
+ enum TextType prev_ttype;
index_t ann; // annotation
index_t at; // struct Attr
index_t atn; // struct Attr.name
@@ -146,6 +149,7 @@ struct ChoContext {
index_t dia; // struct ChordDiagram
index_t dn; // char directive_name
index_t dv; // char directive_value
+ index_t ia; // struct ChoImage
index_t li; // struct ChoLine
index_t lia; // struct ChoLineItemAbove
index_t lii; // struct ChoLineItem
@@ -159,10 +163,13 @@ struct ChoContext {
index_t th; // transpose_history
int text_above_pos;
int nested_level;
+ size_t line_number;
int *transpose_history;
int *transpose;
struct ChoSong **songs;
struct Tag **tags;
+ struct Config *config;
+ struct ChoImage **image_assets;
};
void cho_log_enable_info_logs(void);