commit cc5b9ee6387d48300815f184b5f21b8be583189c
parent b1413065e6893fb887be2de725dcfd50d259626b
Author: nibo <nibo@relim.de>
Date: Tue, 15 Jul 2025 13:55:36 +0200
Free memory in case of error in src/chordpro.c
Diffstat:
2 files changed, 283 insertions(+), 287 deletions(-)
diff --git a/DEVELOPMENT_NOTES b/DEVELOPMENT_NOTES
@@ -42,11 +42,6 @@ to pass a null pointer.
## memory leaks
-If the program encounters an ERR message memory doesn't have to be freed.
-Because of the convention that the program exits when there is an ERR
-message there is no need to free because the operating system takes
-care of that anyway.
-
There is one more case where memory leaks are tolerated. The library
fontconfig produces memory leaks according to valgrind. Fixing these
memory leaks is out of the scope of this project.
diff --git a/src/chordpro.c b/src/chordpro.c
@@ -1442,7 +1442,7 @@ cho_style_print_as_toml(struct ChoStyle *style, const char *section)
}
static bool
-cho_style_change_default(struct ChoContext *ctx, struct StyleProperty sprop)
+cho_style_change_default(struct StyleProperty sprop)
{
unsigned int i;
for (i = 0; i<LENGTH(default_style_properties); i++) {
@@ -1470,9 +1470,6 @@ cho_style_change_default(struct ChoContext *ctx, struct StyleProperty sprop)
default_style_properties[i].u.foreground_color = NULL;
}
return true;
- default:
- cho_log(ctx, LOG_ERR, "Invalid style property type '%d'.", sprop.type);
- return false;
}
}
}
@@ -1480,7 +1477,7 @@ cho_style_change_default(struct ChoContext *ctx, struct StyleProperty sprop)
}
static bool
-cho_style_reset_default(struct ChoContext *ctx)
+cho_style_reset_default(void)
{
unsigned int i;
for (i = 0; i<LENGTH(default_style_properties); i++) {
@@ -1496,9 +1493,6 @@ cho_style_reset_default(struct ChoContext *ctx)
free(default_style_properties[i].u.foreground_color);
default_style_properties[i].u.foreground_color = NULL;
return true;
- default:
- cho_log(ctx, LOG_ERR, "Invalid style property type '%d'.", default_style_properties[i].type);
- return false;
}
}
return false;
@@ -1587,7 +1581,7 @@ cho_tag_style_inherit(struct Tag **tags, int prev_index)
}
}
/*
- Doesn't mean there is an error.
+ INFO: Doesn't mean there is an error.
If no style can be inherited the
default style should be used.
*/
@@ -1684,9 +1678,7 @@ cho_metadata_split(struct ChoContext *ctx, const char *directive_value)
if (v > 1) {
return meta;
} else {
- free(meta->name);
- free(meta->value);
- free(meta);
+ cho_metadata_free(meta);
cho_log(ctx, LOG_ERR, "Failed to parse directive 'meta'.");
return NULL;
}
@@ -1980,7 +1972,7 @@ cho_metadata_substitution_parse(
break;
}
cho_log(ctx, LOG_ERR, "Invalid character after the dot.");
- return NULL;
+ goto ERR;
}
case METADATA_SUBSTITUTION_STATE_INDEX: {
if (c == '=') {
@@ -1998,7 +1990,7 @@ cho_metadata_substitution_parse(
if (!isdigit(c)) {
// TODO: Find a better term for 'metadata substitution name index'!
cho_log(ctx, LOG_ERR, "Specify a positive or negative number in metadata substitution name index.");
- return NULL;
+ goto ERR;
}
name_index[n] = c;
n++;
@@ -2008,11 +2000,11 @@ cho_metadata_substitution_parse(
if (avs == ATTRIBUTE_VALUE_SYNTAX_UNINITIALIZED) {
if (is_whitespace(c)) {
cho_log(ctx, LOG_ERR, "Whitespace character after equals sign is invalid.");
- return NULL;
+ goto ERR;
}
if (c == '|') {
cho_log(ctx, LOG_ERR, "If you specify an equals sign then you have to provide a value.");
- return NULL;
+ goto ERR;
}
if (c == '\'') {
avs = ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE;
@@ -2028,11 +2020,11 @@ cho_metadata_substitution_parse(
if (prev_c != '\\' && c == '|') {
if (avs == ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE) {
cho_log(ctx, LOG_ERR, "Can't find a matching \"\'\".");
- return NULL;
+ goto ERR;
}
if (avs == ATTRIBUTE_VALUE_SYNTAX_QUOTATION_MARK) {
cho_log(ctx, LOG_ERR, "Can't find a matching '\"'.");
- return NULL;
+ goto ERR;
}
if (avs == ATTRIBUTE_VALUE_SYNTAX_UNQUOTED) {
value[n] = 0;
@@ -2100,10 +2092,10 @@ cho_metadata_substitution_parse(
switch (avs) {
case ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE:
cho_log(ctx, LOG_ERR, "Can't find a matching \"\'\".");
- return NULL;
+ goto ERR;
case ATTRIBUTE_VALUE_SYNTAX_QUOTATION_MARK:
cho_log(ctx, LOG_ERR, "Can't find a matching '\"'.");
- return NULL;
+ goto ERR;
case ATTRIBUTE_VALUE_SYNTAX_UNQUOTED:
value[n] = 0;
break;
@@ -2124,7 +2116,7 @@ cho_metadata_substitution_parse(
index = atoi(name_index);
if (index == 0) {
LOG_DEBUG("atoi failed.");
- return NULL;
+ goto ERR;
}
}
if (name[0] != 0) {
@@ -2166,7 +2158,7 @@ cho_metadata_substitution_parse(
} else {
if (state_before_substitution != STATE_METADATA_SUBSTITUTION) {
cho_log(ctx, LOG_ERR, "An empty metadata substitution can only be used inside of another metadata substitution.");
- return NULL;
+ goto ERR;
}
if (substitution_exist) {
replaced = cho_metadata_substitution_replace(ctx, parent_name, "", 0);
@@ -2190,6 +2182,9 @@ cho_metadata_substitution_parse(
out = erealloc(out, (o+1) * sizeof(char));
out[o] = 0;
return out;
+ ERR:
+ free(out);
+ return NULL;
}
static bool
@@ -2399,7 +2394,8 @@ cho_chords_add(struct ChoChord ***chords, struct ChoChord *chord)
int i = 0;
if (*chords) {
struct ChoChord **c;
- for (c = *chords; *c; c++, i++);
+ for (c = *chords; *c; c++);
+ i = (int)(c - *chords);
}
*chords = erealloc(*chords, (i+2) * sizeof(struct ChoChord *));
(*chords)[i] = cho_chord_copy(chord);
@@ -2555,7 +2551,10 @@ cho_chord_parse(struct ChoContext *ctx, const char *str)
{
struct ChoChord *chord = cho_chord_new(ctx);
struct ChordDiagram *diagram;
- int i;
+ int i, ret;
+ size_t str_len = strlen(str);
+ size_t bytes_parsed = 0;
+
for (i = 0; i<ctx->dia; i++) {
diagram = ctx->songs[ctx->so]->diagrams[i];
if (
@@ -2565,9 +2564,6 @@ cho_chord_parse(struct ChoContext *ctx, const char *str)
chord->display = strdup(diagram->u.cm->display);
}
}
- size_t str_len = strlen(str);
- size_t bytes_parsed = 0;
- int ret;
chord->name = strdup(str);
ret = cho_chord_root_parse(ctx, str, chord);
if (ret == 0) {
@@ -2600,7 +2596,12 @@ cho_chord_name_generate_common(struct ChoChord *chord, struct Config *config)
struct Note **notes = config->output->notes;
struct Note *notes_common;
char *root = NULL;
+ char *name = NULL;
+ const char *qual;
int i;
+ int n = 0;
+ size_t name_len = 0;
+
if (chord->is_canonical) {
notes_common = config_notes_common();
for (i = 0; i<7; i++) {
@@ -2618,28 +2619,22 @@ cho_chord_name_generate_common(struct ChoChord *chord, struct Config *config)
}
}
free(notes_common);
- int n = 0;
- char *name = NULL;
- size_t name_len = 0;
name_len += strlen(root);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; root[i]; i++) {
+ for (i = 0; root[i]; i++, n++) {
name[n] = root[i];
- n++;
}
- const char *qual = chord_qualifiers[chord->qual];
+ qual = chord_qualifiers[chord->qual];
name_len += strlen(qual);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; qual[i]; i++) {
+ for (i = 0; qual[i]; i++, n++) {
name[n] = qual[i];
- n++;
}
if (chord->ext) {
name_len += strlen(chord->ext);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; chord->ext[i]; i++) {
+ for (i = 0; chord->ext[i]; i++, n++) {
name[n] = chord->ext[i];
- n++;
}
}
if (chord->bass) {
@@ -2648,9 +2643,8 @@ cho_chord_name_generate_common(struct ChoChord *chord, struct Config *config)
name = erealloc(name, name_len * sizeof(char));
name[n] = '/';
n++;
- for (i = 0; chord->bass[i]; i++) {
+ for (i = 0; chord->bass[i]; i++, n++) {
name[n] = chord->bass[i];
- n++;
}
}
name_len++;
@@ -2664,33 +2658,32 @@ cho_chord_name_generate_common(struct ChoChord *chord, struct Config *config)
char *
cho_chord_name_generate(struct ChoChord *chord)
{
+ int n = 0;
+ int i;
+ char *name = NULL;
+ const char *qual;
+ size_t name_len = 0;
+
if (chord->display) {
return strdup(chord->display);
}
if (chord->is_canonical) {
- int n = 0;
- int i;
- char *name = NULL;
- size_t name_len = 0;
name_len += strlen(chord->root);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; chord->root[i]; i++) {
+ for (i = 0; chord->root[i]; i++, n++) {
name[n] = chord->root[i];
- n++;
}
- const char *qual = chord_qualifiers[chord->qual];
+ qual = chord_qualifiers[chord->qual];
name_len += strlen(qual);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; qual[i]; i++) {
+ for (i = 0; qual[i]; i++, n++) {
name[n] = qual[i];
- n++;
}
if (chord->ext) {
name_len += strlen(chord->ext);
name = erealloc(name, name_len * sizeof(char));
- for (i = 0; chord->ext[i]; i++) {
+ for (i = 0; chord->ext[i]; i++, n++) {
name[n] = chord->ext[i];
- n++;
}
}
if (chord->bass) {
@@ -2699,9 +2692,8 @@ cho_chord_name_generate(struct ChoChord *chord)
name = erealloc(name, name_len * sizeof(char));
name[n] = '/';
n++;
- for (i = 0; chord->bass[i]; i++) {
+ for (i = 0; chord->bass[i]; i++, n++) {
name[n] = chord->bass[i];
- n++;
}
}
name_len++;
@@ -2791,6 +2783,7 @@ static struct ChoImage *
cho_image_find_asset(struct ChoContext *ctx, const char *id)
{
int i;
+
for (i = 0; i<ctx->ia; i++) {
if (!strcmp(ctx->image_assets[i]->id, id)) {
return ctx->image_assets[i];
@@ -2887,7 +2880,8 @@ static bool
cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const char *name, const char *value)
{
char *endptr;
- struct Size *size;
+ struct Size *size = NULL;
+
if (!strcmp(name, "id")) {
image->id = strdup(value);
} else
@@ -2895,18 +2889,18 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
image->src = filepath_resolve_tilde(value);
if (!image->src) {
LOG_DEBUG("filepath_resolve_tilde failed.");
- return false;
+ goto ERR;
}
} else
if (!strcmp(name, "width")) {
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'width' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'width' in image directive. Allowed types are: points, percentage.");
- return false;
+ goto ERR;
}
image->width = size;
} else
@@ -2914,11 +2908,11 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'height' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'height' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->height = size;
} else
@@ -2929,32 +2923,32 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->width_scale = size;
size = size_create(++comma);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->height_scale = size;
} else {
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'scale' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'scale' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->width_scale = size;
image->height_scale = size_copy(size);
@@ -2971,25 +2965,25 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
image->align = ALIGNMENT_CENTER;
} else {
cho_log(ctx, LOG_ERR, "Invalid value in option 'align' in image directive.");
- return false;
+ goto ERR;
}
} else
if (!strcmp(name, "border")) {
image->border = strtod(value, &endptr);
if (value == endptr || errno == ERANGE) {
LOG_DEBUG("strtod failed.");
- return false;
+ goto ERR;
}
} else
if (!strcmp(name, "spread")) {
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'spread' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'spread' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->spread_space = size;
} else
@@ -3000,11 +2994,11 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'x' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'x' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->x = size;
} else
@@ -3012,11 +3006,11 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
size = size_create(value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in option 'y' in image directive.");
- return false;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in option 'y' in image directive. Allowed types are: point, percentage.");
- return false;
+ goto ERR;
}
image->y = size;
} else
@@ -3037,10 +3031,13 @@ cho_image_option_parse(struct ChoContext *ctx, struct ChoImage *image, const cha
image->anchor = ANCHOR_FLOAT;
} else {
cho_log(ctx, LOG_ERR, "Invalid value in option 'anchor' in image directive.");
- return false;
+ goto ERR;
}
}
return true;
+ ERR:
+ free(size);
+ return false;
}
static struct ChoImage *
@@ -3048,17 +3045,18 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
{
struct ChoImage *image = cho_image_new();
struct ChoImage *asset;
- char c;
enum OptionState state = OPTION_STATE_NAME;
enum AttrValueSyntax avs = ATTRIBUTE_VALUE_SYNTAX_UNINITIALIZED;
+ char c;
char name[6+1];
char value[URL_MAX_LEN+1];
int n = 0;
int v = 0;
- memset(name, 0, sizeof(name));
- memset(value, 0, sizeof(value));
int option_count = 0;
int i;
+
+ memset(name, 0, sizeof(name));
+ memset(value, 0, sizeof(value));
for (i = 0; str[i]; i++) {
c = str[i];
switch (state) {
@@ -3069,7 +3067,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
} else {
name[n] = 0;
cho_log(ctx, LOG_ERR, "Option with name '%s' in image directive has no value.", name);
- return NULL;
+ goto ERR;
}
}
if (c == '=') {
@@ -3079,7 +3077,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
}
if (n > 5) {
cho_log(ctx, LOG_ERR, "Option name in image directive is too long.");
- return NULL;
+ goto ERR;
}
name[n] = c;
n++;
@@ -3088,7 +3086,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
if (avs == ATTRIBUTE_VALUE_SYNTAX_UNINITIALIZED) {
if (is_whitespace(c)) {
cho_log(ctx, LOG_ERR, "Whitespace character after equals sign in image directive is invalid.");
- return NULL;
+ goto ERR;
}
if (c == '\'') {
avs = ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE;
@@ -3103,7 +3101,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
}
if (c == '\n') {
cho_log(ctx, LOG_ERR, "Newline character inside an option value in image directive is invalid.");
- return NULL;
+ goto ERR;
}
if (
(avs == ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE && c == '\'') ||
@@ -3113,7 +3111,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
value[v] = 0;
if (!cho_image_option_parse(ctx, image, name, value)) {
LOG_DEBUG("cho_image_option_parse failed.");
- return NULL;
+ goto ERR;
}
option_count++;
memset(name, 0, n);
@@ -3133,7 +3131,7 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
value[v] = 0;
if (!cho_image_option_parse(ctx, image, name, value)) {
LOG_DEBUG("cho_image_option_parse failed.");
- return NULL;
+ goto ERR;
}
option_count++;
}
@@ -3141,19 +3139,22 @@ cho_image_directive_parse(struct ChoContext *ctx, const char *str)
if (image->src) {
if (option_count > 2) {
cho_log(ctx, LOG_ERR, "Defining an image asset disallows any options other than 'id' and 'src'.");
- return NULL;
+ goto ERR;
}
image->is_asset = true;
} else {
asset = cho_image_find_asset(ctx, image->id);
if (!asset) {
cho_log(ctx, LOG_ERR, "There is no image asset with the id '%s'.", image->id);
- return NULL;
+ goto ERR;
}
image->src = strdup(asset->src);
}
}
return image;
+ ERR:
+ cho_image_free(image);
+ return NULL;
}
static struct ChoImage *
@@ -3161,14 +3162,15 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
{
struct ChoImage *image = cho_image_new();
struct ChoImage *asset;
- struct Size *size;
+ struct Size *size = NULL;
int a;
+
for (a = 0; attrs[a]; a++) {
if (!strcmp(attrs[a]->name, "src")) {
image->src = filepath_resolve_tilde(attrs[a]->value);
if (!image->src) {
LOG_DEBUG("filepath_resolve_tilde failed.");
- return NULL;
+ goto ERR;
}
} else
if (!strcmp(attrs[a]->name, "id")) {
@@ -3178,11 +3180,11 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'width' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_PERCENT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'width' in 'img' tag. Allowed types are: point, em, ex.");
- return NULL;
+ goto ERR;
}
image->width = size;
} else
@@ -3190,11 +3192,11 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'height' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_PERCENT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'height' in 'img' tag. Allowed types are: point, em, ex.");
- return NULL;
+ goto ERR;
}
image->height = size;
} else
@@ -3202,11 +3204,11 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'dx' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_PERCENT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'dx' in 'img' tag. Allowed types are: point, em, ex.");
- return NULL;
+ goto ERR;
}
image->dx = size;
} else
@@ -3214,11 +3216,11 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'dy' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_PERCENT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'dy' in 'img' tag. Allowed types are: point, em, ex.");
- return NULL;
+ goto ERR;
}
image->dy = size;
} else
@@ -3229,32 +3231,32 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
- return NULL;
+ goto ERR;
}
image->width_scale = size;
size = size_create(++comma);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
- return NULL;
+ goto ERR;
}
image->height_scale = size;
} else {
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'scale' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type == SIZE_TYPE_EM || size->type == SIZE_TYPE_EX) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'scale' in 'img' tag. Allowed types are: point, percent");
- return NULL;
+ goto ERR;
}
image->width_scale = size;
image->height_scale = size_copy(size);
@@ -3271,7 +3273,7 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
image->align = ALIGNMENT_CENTER;
} else {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'align' in 'img' tag.");
- return NULL;
+ goto ERR;
}
} else
if (!strcmp(attrs[a]->name, "bbox")) {
@@ -3282,18 +3284,18 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
image->bbox = false;
} else {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'bbox' in 'img' tag.");
- return NULL;
+ goto ERR;
}
} else
if (!strcmp(attrs[a]->name, "w")) {
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'w' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type != SIZE_TYPE_POINT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'w' in 'img' tag. Allowed type is: point");
- return NULL;
+ goto ERR;
}
image->w = size;
} else
@@ -3301,37 +3303,41 @@ cho_image_tag_parse(struct ChoContext *ctx, struct Attr **attrs)
size = size_create(attrs[a]->value);
if (!size) {
cho_log(ctx, LOG_ERR, "Invalid value in attribute 'h' in 'img' tag.");
- return NULL;
+ goto ERR;
}
if (size->type != SIZE_TYPE_POINT) {
cho_log(ctx, LOG_ERR, "Invalid type of value in attribute 'h' in 'img' tag. Allowed type is: point");
- return NULL;
+ goto ERR;
}
image->h = size;
} else {
cho_log(ctx, LOG_ERR, "Invalid attribute '%s' in 'img' tag.", attrs[a]->name);
- return NULL;
+ goto ERR;
}
}
if (image->id) {
if (image->src) {
cho_log(ctx, LOG_ERR, "'img' tag can't have both attributes 'id' and 'src' at the same time.");
- return NULL;
+ goto ERR;
} else {
asset = cho_image_find_asset(ctx, image->id);
if (!asset) {
cho_log(ctx, LOG_ERR, "There is no image asset with the id '%s'.", image->id);
- return NULL;
+ goto ERR;
}
image->src = strdup(asset->src);
}
} else {
if (!image->src) {
cho_log(ctx, LOG_ERR, "'img' tag has to have at least either the attribute 'id' or 'src'.");
- return NULL;
+ goto ERR;
}
}
return image;
+ ERR:
+ cho_image_free(image);
+ free(size);
+ return NULL;
}
static int8_t
@@ -3385,6 +3391,7 @@ cho_chord_diagram_parse(
int8_t number = -2;
long l;
const char *c;
+
for (c = str; *c; c++){
// printf("c '%c' state '%d'\n", c, state);
switch (state) {
@@ -3400,7 +3407,7 @@ cho_chord_diagram_parse(
}
if (i > 18) {
cho_log(ctx, LOG_ERR, "Chord name in chord diagram is too long.");
- return NULL;
+ goto ERR;
}
name[i] = *c;
i++;
@@ -3440,7 +3447,7 @@ cho_chord_diagram_parse(
future_content = CHORD_DIAGRAM_CONTENT_CHORD_MAP;
} else {
cho_log(ctx, LOG_ERR, "Invalid option '%s' in define directive.", option);
- return NULL;
+ goto ERR;
}
memset(option, 0, i);
i = 0;
@@ -3466,14 +3473,15 @@ cho_chord_diagram_parse(
diagram->u.cm->name = strdup(name);
break;
default:
- cho_log(ctx, LOG_ERR, "'future_content' cannot be empty at this point.\n");
+ LOG_DEBUG("'future_content' cannot be empty at this point.\n");
+ goto ERR;
}
}
break;
}
if (i > 8) {
cho_log(ctx, LOG_ERR, "Option in chord diagram is too long.");
- return NULL;
+ goto ERR;
}
option[i] = *c;
i++;
@@ -3490,11 +3498,11 @@ cho_chord_diagram_parse(
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
- return NULL;
+ goto ERR;
}
if (l == 0) {
- cho_log(ctx, LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
- return NULL;
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
+ goto ERR;
}
diagram->u.sd->base_fret = (int8_t)l;
state = CHORD_DIAGRAM_STATE_OPTION_NAME;
@@ -3502,8 +3510,7 @@ cho_chord_diagram_parse(
}
if (i > 1) {
cho_log(ctx, LOG_ERR, "base-fret value is too long.");
- printf("c: %c\n", *c);
- return NULL;
+ goto ERR;
}
base_fret[i] = *c;
i++;
@@ -3524,7 +3531,7 @@ cho_chord_diagram_parse(
is_maybe_minus_one = false;
} else {
cho_log(ctx, LOG_ERR, "Invalid frets value '-%c' in chord diagram.", *c);
- return NULL;
+ goto ERR;
}
}
if (*c == 'N' || *c == 'x') {
@@ -3541,12 +3548,12 @@ cho_chord_diagram_parse(
if (number == -1) {
LOG_DEBUG("char_to_positive_int failed.");
cho_log(ctx, LOG_ERR, "Invalid frets value '%c' in chord diagram.", *c);
- return NULL;
+ goto ERR;
}
}
if (f > 11) {
cho_log(ctx, LOG_ERR, "Too many fret values in chord diagram.");
- return NULL;
+ goto ERR;
}
diagram->u.sd->frets[f] = number;
f++;
@@ -3566,11 +3573,11 @@ cho_chord_diagram_parse(
number = finger_to_int(*c);
if (number == -2) {
cho_log(ctx, LOG_ERR, "Invalid fingers value '%c' in chord diagram.", *c);
- return NULL;
+ goto ERR;
}
if (f > 11) {
cho_log(ctx, LOG_ERR, "Too many finger values in chord diagram.");
- return NULL;
+ goto ERR;
}
diagram->u.sd->fingers[f] = number;
f++;
@@ -3588,11 +3595,11 @@ cho_chord_diagram_parse(
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
cho_log(ctx, LOG_ERR, "Invalid number in keys in chord diagram.");
- return NULL;
+ goto ERR;
}
if (f > 23) {
cho_log(ctx, LOG_ERR, "Too many key values in chord diagram.");
- return NULL;
+ goto ERR;
}
diagram->u.kd->keys[f] = (int8_t)l;
f++;
@@ -3605,8 +3612,7 @@ cho_chord_diagram_parse(
}
if (i > 1) {
cho_log(ctx, LOG_ERR, "Too high key value in chord diagram. '%d'", i);
- printf("key '%s'\n", key);
- return NULL;
+ goto ERR;
}
key[i] = *c;
i++;
@@ -3629,7 +3635,7 @@ cho_chord_diagram_parse(
diagram->color = cho_color_parse(diagram_value);
if (!diagram->color) {
LOG_DEBUG("cho_color_parse failed.");
- return NULL;
+ goto ERR;
}
}
state = CHORD_DIAGRAM_STATE_OPTION_NAME;
@@ -3647,7 +3653,7 @@ cho_chord_diagram_parse(
chord_to_copy[i] = 0;
if (current_content != CHORD_DIAGRAM_CONTENT_UNINITIALIZED) {
cho_log(ctx, LOG_ERR, "The define options 'base-fret', 'frets', 'fingers' and 'keys' are not allowed before the 'copy' option.");
- return NULL;
+ goto ERR;
}
enum Instrument ins = ctx->config->output->diagram->instrument;
current_content = chord_diagram_duplicate(diagram, custom_diagrams, custom_diagrams_len, name, chord_to_copy, ins);
@@ -3656,7 +3662,7 @@ cho_chord_diagram_parse(
"because no previous definition was found and also"
"no predefined chord diagram for the instrument '%s'"
"was found.", chord_to_copy, instruments[ins].name);
- return NULL;
+ goto ERR;
}
i = 0;
state = CHORD_DIAGRAM_STATE_OPTION_NAME;
@@ -3687,11 +3693,11 @@ cho_chord_diagram_parse(
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
- return NULL;
+ goto ERR;
}
if (l == 0) {
- cho_log(ctx, LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", *c);
- return NULL;
+ cho_log(ctx, LOG_ERR, "Invalid base-fret value '%s' in chord diagram.", base_fret);
+ goto ERR;
}
diagram->u.sd->base_fret = (int8_t)l;
break;
@@ -3703,11 +3709,11 @@ cho_chord_diagram_parse(
if (l == -1) {
LOG_DEBUG("str_to_number failed.");
cho_log(ctx, LOG_ERR, "Invalid number in keys in chord diagram.");
- return NULL;
+ goto ERR;
}
if (f > 23) {
cho_log(ctx, LOG_ERR, "Too many key values in chord diagram.");
- return NULL;
+ goto ERR;
}
diagram->u.kd->keys[f] = (int8_t)l;
}
@@ -3726,7 +3732,7 @@ cho_chord_diagram_parse(
diagram->color = cho_color_parse(diagram_value);
if (!diagram->color) {
LOG_DEBUG("cho_color_parse failed.");
- return NULL;
+ goto ERR;
}
}
break;
@@ -3737,7 +3743,7 @@ cho_chord_diagram_parse(
cho_log(ctx, LOG_ERR, "The define options 'base-fret', 'frets',"
"'fingers' and 'keys' are not allowed before the 'copy'"
"option.");
- return NULL;
+ goto ERR;
}
enum Instrument ins = ctx->config->output->diagram->instrument;
current_content = chord_diagram_duplicate(diagram, custom_diagrams, custom_diagrams_len, name, chord_to_copy, ins);
@@ -3746,7 +3752,7 @@ cho_chord_diagram_parse(
"no previous definition was found and also no predefined"
"chord diagram for the instrument '%s' was found.",
chord_to_copy, instruments[ins].name);
- return NULL;
+ goto ERR;
}
break;
}
@@ -3764,13 +3770,16 @@ cho_chord_diagram_parse(
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;
+ goto ERR;
}
if (current_content == CHORD_DIAGRAM_CONTENT_UNINITIALIZED) {
cho_log(ctx, LOG_ERR, "The chord diagram is invalid.");
- return NULL;
+ goto ERR;
}
return diagram;
+ ERR:
+ chord_diagram_free(diagram);
+ return NULL;
}
static struct ChoText *
@@ -3946,11 +3955,13 @@ cho_section_free(struct ChoSection *section)
if (section->label) {
cho_text_free(section->label);
}
- struct ChoLine **li;
- for (li = section->lines; *li; li++) {
- cho_line_free(*li);
+ if (section->lines) {
+ struct ChoLine **li;
+ for (li = section->lines; *li; li++) {
+ cho_line_free(*li);
+ }
+ free(section->lines);
}
- free(section->lines);
free(section);
}
@@ -4034,6 +4045,7 @@ cho_song_compare(const void *a, const void *b)
{
struct ChoSong *song;
const char *a_title, *b_title;
+
song = *(struct ChoSong **)a;
a_title = cho_song_get_title(song);
song = *(struct ChoSong **)b;
@@ -4121,8 +4133,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_CHORUS;
directive->ttype = TEXT_TYPE_CHORUS;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "end_of_chorus") ||
!strcmp(name, "eoc")
) {
@@ -4130,13 +4142,13 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_END;
directive->stype = SECTION_TYPE_CHORUS;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (!strcmp(name, "chorus")) {
+ } else
+ if (!strcmp(name, "chorus")) {
directive->dtype = DIRECTIVE_TYPE_ENVIRONMENT;
directive->position = POSITION_NO;
directive->ttype = TEXT_TYPE_LABEL;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "start_of_verse") ||
!strcmp(name, "sov")
) {
@@ -4144,8 +4156,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_VERSE;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "end_of_verse") ||
!strcmp(name, "eov")
) {
@@ -4153,8 +4165,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_END;
directive->stype = SECTION_TYPE_VERSE;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "start_of_bridge") ||
!strcmp(name, "sob")
) {
@@ -4162,17 +4174,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_BRIDGE;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
- !strcmp(name, "end_of_bridge") ||
- !strcmp(name, "eob")
- ) {
- directive->dtype = DIRECTIVE_TYPE_ENVIRONMENT;
- directive->position = POSITION_END;
- directive->stype = SECTION_TYPE_BRIDGE;
- directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "start_of_tab") ||
!strcmp(name, "sot")
) {
@@ -4180,8 +4183,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_TAB;
directive->ttype = TEXT_TYPE_TAB;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "end_of_tab") ||
!strcmp(name, "eot")
) {
@@ -4189,8 +4192,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_END;
directive->stype = SECTION_TYPE_TAB;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "start_of_grid") ||
!strcmp(name, "sog")
) {
@@ -4198,8 +4201,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_GRID;
directive->ttype = TEXT_TYPE_GRID;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "end_of_grid") ||
!strcmp(name, "eog")
) {
@@ -4207,8 +4210,7 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->position = POSITION_END;
directive->stype = SECTION_TYPE_GRID;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- }
+ } else
if (
!strcmp(name, "title") ||
!strcmp(name, "t")
@@ -4220,9 +4222,9 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
ctx->current_ttype = TEXT_TYPE_TITLE;
directive->style = cho_style_new_default(ctx);
ctx->current_ttype = ctx->prev_ttype;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "subtitle") ||
!strcmp(name, "st")
) {
@@ -4233,8 +4235,7 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
ctx->current_ttype = TEXT_TYPE_SUBTITLE;
directive->style = cho_style_new_default(ctx);
ctx->current_ttype = ctx->prev_ttype;
- return directive;
- }
+ } else
if (
!strcmp(name, "sorttitle") ||
!strcmp(name, "artist") ||
@@ -4253,8 +4254,7 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
) {
directive->dtype = DIRECTIVE_TYPE_METADATA;
directive->meta = METADATA_DIRECTIVE_OTHER;
- return directive;
- }
+ } else
if (
!strcmp(name, "comment") ||
!strcmp(name, "c") ||
@@ -4267,8 +4267,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->style = cho_style_new_default(ctx);
ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TEXT_TYPE_COMMENT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "comment_italic") ||
!strcmp(name, "ci")
) {
@@ -4279,8 +4279,8 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->style = cho_style_new_default(ctx);
ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TEXT_TYPE_COMMENT_ITALIC;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "comment_box") ||
!strcmp(name, "cb")
) {
@@ -4291,20 +4291,17 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->style = cho_style_new_default(ctx);
ctx->current_ttype = ctx->prev_ttype;
directive->ttype = TEXT_TYPE_COMMENT_BOX;
- return directive;
- }
+ } else
if (!strcmp(name, "image")) {
directive->dtype = DIRECTIVE_TYPE_IMAGE;
- return directive;
- }
+ } else
if (
!strcmp(name, "new_song") ||
!strcmp(name, "ns")
) {
directive->dtype = DIRECTIVE_TYPE_PREAMBLE;
directive->stype = SECTION_TYPE_NEWSONG;
- return directive;
- }
+ } else
if (
!strcmp(name, "chordfont") ||
!strcmp(name, "cf")
@@ -4312,185 +4309,180 @@ cho_directive_parse(struct ChoContext *ctx, const char *name)
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_CHORD;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "chordsize") ||
!strcmp(name, "cs")
) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_CHORD;
- return directive;
- } else if (!strcmp(name, "chordcolour")) {
+ } else
+ if (!strcmp(name, "chordcolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_CHORD;
- return directive;
- } else if (!strcmp(name, "chorusfont")) {
+ } else
+ if (!strcmp(name, "chorusfont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_CHORUS;
- return directive;
- } else if (!strcmp(name, "chorussize")) {
+ } else
+ if (!strcmp(name, "chorussize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_CHORUS;
- return directive;
- } else if (!strcmp(name, "choruscolour")) {
+ } else
+ if (!strcmp(name, "choruscolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_CHORUS;
- return directive;
- } else if (!strcmp(name, "gridfont")) {
+ } else
+ if (!strcmp(name, "gridfont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_GRID;
- return directive;
- } else if (!strcmp(name, "gridsize")) {
+ } else
+ if (!strcmp(name, "gridsize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_GRID;
- return directive;
- } else if (!strcmp(name, "gridcolour")) {
+ } else
+ if (!strcmp(name, "gridcolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_GRID;
- return directive;
- } else if (!strcmp(name, "tabfont")) {
+ } else
+ if (!strcmp(name, "tabfont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_TAB;
- return directive;
- } else if (!strcmp(name, "tabsize")) {
+ } else
+ if (!strcmp(name, "tabsize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_TAB;
- return directive;
- } else if (!strcmp(name, "tabcolour")) {
+ } else
+ if (!strcmp(name, "tabcolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_TAB;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "textfont") ||
!strcmp(name, "tf")
) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "textsize") ||
!strcmp(name, "ts")
) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (!strcmp(name, "textcolour")) {
+ } else
+ if (!strcmp(name, "textcolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (!strcmp(name, "titlefont")) {
+ } else
+ if (!strcmp(name, "titlefont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_TITLE;
- return directive;
- } else if (!strcmp(name, "titlesize")) {
+ } else
+ if (!strcmp(name, "titlesize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_TITLE;
- return directive;
- } else if (!strcmp(name, "titlecolour")) {
+ } else
+ if (!strcmp(name, "titlecolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_TITLE;
- return directive;
- } else if (!strcmp(name, "tocfont")) {
+ } else
+ if (!strcmp(name, "tocfont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_TOC;
- return directive;
- } else if (!strcmp(name, "tocsize")) {
+ } else
+ if (!strcmp(name, "tocsize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_TOC;
- return directive;
- } else if (!strcmp(name, "toccolour")) {
+ } else
+ if (!strcmp(name, "toccolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_TOC;
- return directive;
/* } else if (!strcmp(name, "footerfont")) {
} else if (!strcmp(name, "footersize")) {
} else if (!strcmp(name, "footercolour")) { */
- } else if (!strcmp(name, "labelfont")) {
+ } else
+ if (!strcmp(name, "labelfont")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_FONT;
directive->ttype = TEXT_TYPE_LABEL;
- return directive;
- } else if (!strcmp(name, "labelsize")) {
+ } else
+ if (!strcmp(name, "labelsize")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_SIZE;
directive->ttype = TEXT_TYPE_LABEL;
- return directive;
- } else if (!strcmp(name, "labelcolour")) {
+ } else
+ if (!strcmp(name, "labelcolour")) {
directive->dtype = DIRECTIVE_TYPE_FONT;
directive->sprop = STYLE_PROPERTY_TYPE_COLOR;
directive->ttype = TEXT_TYPE_LABEL;
- return directive;
- }
+ } else
if (!strcmp(name, "transpose")) {
directive->dtype = DIRECTIVE_TYPE_CHORD;
directive->ctype = CHORD_DIRECTIVE_TRANSPOSE;
- return directive;
- } else if (!strcmp(name, "define")) {
+ } else
+ if (!strcmp(name, "define")) {
directive->dtype = DIRECTIVE_TYPE_CHORD;
directive->ctype = CHORD_DIRECTIVE_DEFINE;
- return directive;
- } /* else if (!strcmp(name, "chord")) {
- } */
+ /* } else if (!strcmp(name, "chord")) { */
+ } else
if (
!strcmp(name, "new_page") ||
!strcmp(name, "np")
) {
directive->dtype = DIRECTIVE_TYPE_OUTPUT;
directive->btype = BREAK_TYPE_PAGE;
- return directive;
- } else if (
+ } else
+ if (
!strcmp(name, "column_break") ||
!strcmp(name, "colb")
) {
directive->dtype = DIRECTIVE_TYPE_OUTPUT;
directive->btype = BREAK_TYPE_COLUMN;
- return directive;
- }
+ } else
if (str_starts_with(name, "start_of_")) {
directive->dtype = DIRECTIVE_TYPE_ENVIRONMENT;
directive->position = POSITION_START;
directive->stype = SECTION_TYPE_CUSTOM;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- } else if (str_starts_with(name, "end_of_")) {
+ } else
+ if (str_starts_with(name, "end_of_")) {
directive->dtype = DIRECTIVE_TYPE_ENVIRONMENT;
directive->position = POSITION_END;
directive->stype = SECTION_TYPE_CUSTOM;
directive->ttype = TEXT_TYPE_TEXT;
- return directive;
- }
+ } else
if (str_starts_with(name, "x_")) {
directive->dtype = DIRECTIVE_TYPE_EXTENSION;
- return directive;
+ } else {
+ directive->dtype = DIRECTIVE_TYPE_CUSTOM;
}
- directive->dtype = DIRECTIVE_TYPE_CUSTOM;
return directive;
}
static struct Attr **
-cho_attrs_parse(struct ChoContext *ctx, const char *str)
+cho_attrs_parse(struct ChoContext *ctx, const char *str, const char *directive_name)
{
- const char *directive_name = "something";
struct Attr **attrs = NULL;
int a = 0;
enum OptionState state = OPTION_STATE_NAME;
@@ -4511,7 +4503,7 @@ cho_attrs_parse(struct ChoContext *ctx, const char *str)
} else {
name[n] = 0;
cho_log(ctx, LOG_ERR, "Option with name '%s' in environment directive '%s' has no value.", name, directive_name);
- return NULL;
+ goto ERR;
}
}
if (*c == '=') {
@@ -4521,7 +4513,7 @@ cho_attrs_parse(struct ChoContext *ctx, const char *str)
}
if (n > 4) {
cho_log(ctx, LOG_ERR, "Option name in environment directive '%s' is too long.", directive_name);
- return NULL;
+ goto ERR;
}
name[n] = *c;
n++;
@@ -4530,7 +4522,7 @@ cho_attrs_parse(struct ChoContext *ctx, const char *str)
if (avs == ATTRIBUTE_VALUE_SYNTAX_UNINITIALIZED) {
if (is_whitespace(*c)) {
cho_log(ctx, LOG_ERR, "Whitespace character after equals sign in environment directive '%s' is invalid.", directive_name);
- return NULL;
+ goto ERR;
}
if (*c == '\'') {
avs = ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE;
@@ -4545,7 +4537,7 @@ cho_attrs_parse(struct ChoContext *ctx, const char *str)
}
if (*c == '\n') {
cho_log(ctx, LOG_ERR, "Newline character inside an option value in environment directive '%s' is invalid.", directive_name);
- return NULL;
+ goto ERR;
}
if (
(avs == ATTRIBUTE_VALUE_SYNTAX_APOSTROPHE && *c == '\'') ||
@@ -4582,6 +4574,12 @@ cho_attrs_parse(struct ChoContext *ctx, const char *str)
attrs = erealloc(attrs, (a+1) * sizeof(struct Attr *));
attrs[a] = NULL;
return attrs;
+ ERR:
+ for (n = 0; n<a; n++) {
+ cho_tag_attr_free(attrs[n]);
+ }
+ free(attrs);
+ return NULL;
}
static char *
@@ -4601,11 +4599,11 @@ static bool
cho_grid_shape_parse_and_set(struct ChoContext *ctx, const char *str)
{
enum {
- BEFORE_FIRSIZE_TYPE_PLUS,
- AFTER_FIRSIZE_TYPE_PLUS,
+ BEFORE_FIRST_PLUS,
+ AFTER_FIRST_PLUS,
AFTER_SECOND_PLUS,
AFTER_X
- } state = BEFORE_FIRSIZE_TYPE_PLUS;
+ } state = BEFORE_FIRST_PLUS;
const char *c;
char tmp[6+1];
int t = 0;
@@ -4614,7 +4612,7 @@ cho_grid_shape_parse_and_set(struct ChoContext *ctx, const char *str)
int i;
for (c = str; *c; c++) {
switch (state) {
- case BEFORE_FIRSIZE_TYPE_PLUS:
+ case BEFORE_FIRST_PLUS:
if (*c == '+') {
tmp[t] = 0;
i = atoi(tmp);
@@ -4625,7 +4623,7 @@ cho_grid_shape_parse_and_set(struct ChoContext *ctx, const char *str)
ctx->grid.left = i;
memset(tmp, 0, t);
t = 0;
- state = AFTER_FIRSIZE_TYPE_PLUS;
+ state = AFTER_FIRST_PLUS;
break;
}
if (*c == 'x') {
@@ -4648,7 +4646,7 @@ cho_grid_shape_parse_and_set(struct ChoContext *ctx, const char *str)
tmp[t] = *c;
t++;
break;
- case AFTER_FIRSIZE_TYPE_PLUS:
+ case AFTER_FIRST_PLUS:
if (*c == '+') {
tmp[t] = 0;
i = atoi(tmp);
@@ -4709,9 +4707,9 @@ cho_grid_shape_parse_and_set(struct ChoContext *ctx, const char *str)
return false;
}
switch (state) {
- case BEFORE_FIRSIZE_TYPE_PLUS:
+ case BEFORE_FIRST_PLUS:
/* fallthrough */
- case AFTER_FIRSIZE_TYPE_PLUS:
+ case AFTER_FIRST_PLUS:
ctx->grid.cells = i;
break;
case AFTER_SECOND_PLUS:
@@ -4766,13 +4764,19 @@ cho_grid_token_parse(struct ChoContext *ctx, const char *token, bool *err)
return GRID_TOKEN_CHORD;
}
*err = true;
- return GRID_TOKEN_CHORD;
+ return GRID_TOKEN_CHORD; // unused
}
static void
cho_songs_close(struct ChoContext *ctx, struct ChoLine ***lines)
{
- if ((*lines)[ctx->li]->items[ctx->lii]->is_text) {
+ if (
+ (*lines) &&
+ (*lines)[ctx->li] &&
+ (*lines)[ctx->li]->items &&
+ (*lines)[ctx->li]->items[ctx->lii] &&
+ (*lines)[ctx->li]->items[ctx->lii]->is_text
+ ) {
if ((*lines)[ctx->li]->items[ctx->lii]->u.text->text) {
(*lines)[ctx->li]->items[ctx->lii]->u.text->text = erealloc((*lines)[ctx->li]->items[ctx->lii]->u.text->text, (ctx->te+1) * sizeof(char));
(*lines)[ctx->li]->items[ctx->lii]->u.text->text[ctx->te] = 0;
@@ -4854,21 +4858,18 @@ cho_context_init(
ctx->grid.bar_line_symbol_in_line_count = 0;
ctx->grid.tokens_per_cell = 0;
ctx->grid.expected_tokens_per_cell = 0;
-
- 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);
if (!ctx->songs[ctx->so]) {
LOG_DEBUG("cho_song_new failed.");
- free(ctx->transpose_history);
free(ctx->songs);
return false;
}
+ 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[ctx->so]->sections = emalloc((ctx->se+1) * sizeof(struct ChoSection *));
ctx->songs[ctx->so]->sections[ctx->se] = cho_section_new();
ctx->songs[ctx->so]->sections[ctx->se]->lines = emalloc(sizeof(struct ChoLine *));
@@ -5233,7 +5234,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c
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(&ctx)) {
+ if (!cho_style_reset_default()) {
LOG_DEBUG("cho_style_reset_default failed.");
goto ERR;
}
@@ -5284,7 +5285,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c
sprop.u.foreground_color = NULL;
break;
}
- if (!cho_style_change_default(&ctx, sprop)) {
+ if (!cho_style_change_default(sprop)) {
LOG_DEBUG("cho_style_change_default failed.");
goto ERR;
}
@@ -5374,7 +5375,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c
ctx.songs[ctx.so]->sections[ctx.se]->type = directive->stype;
if (strchr(stripped_directive_value, '=')) {
- directive_attrs = cho_attrs_parse(&ctx, stripped_directive_value);
+ directive_attrs = cho_attrs_parse(&ctx, stripped_directive_value, directive_name);
if (!directive_attrs) {
LOG_DEBUG("cho_attrs_parse failed.");
goto ERR;
@@ -5670,7 +5671,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c
cho_log(&ctx, LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
goto ERR;
}
- if (!cho_style_change_default(&ctx, sprop)) {
+ if (!cho_style_change_default(sprop)) {
LOG_DEBUG("cho_style_change_default failed.");
goto ERR;
}
@@ -6569,7 +6570,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c
}
prev_c = c;
}
- if (!cho_style_reset_default(&ctx)) {
+ if (!cho_style_reset_default()) {
LOG_DEBUG("cho_style_reset_default failed.");
goto ERR;
}