lorid

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

commit 6a82b74428043892a4985915ba79a8016a20be9b
parent a8b9e551d166e28462ffde23b465625453aad37d
Author: nibo <nibo@relim.de>
Date:   Thu, 17 Jul 2025 15:48:03 +0200

Add missing NULL pointer check

Also use pointer arithmetic instead of index accesses

Diffstat:
Msrc/chordpro.c | 497++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 252 insertions(+), 245 deletions(-)

diff --git a/src/chordpro.c b/src/chordpro.c @@ -1098,289 +1098,294 @@ cho_style_parse( struct RGBColor *rgb_color; struct ChoStyle *style; struct Font *font; + struct Attr **a; + if (inherited_style) { style = cho_style_copy(inherited_style); } else { style = cho_style_new_default(ctx); } if (!strcmp(tag_name, "span")) { - int a; - for (a = 0; attrs[a]; a++) { - if (!strcmp(attrs[a]->name, "font_desc")) { - font = cho_style_font_desc_parse(attrs[a]->value, presence); - if (font) { - if (!font->name) { - font->name = strdup(style->font->name); + if (attrs) { + for (a = attrs; *a; a++) { + if (!strcmp((*a)->name, "font_desc")) { + font = cho_style_font_desc_parse((*a)->value, presence); + if (font) { + if (!font->name) { + font->name = strdup(style->font->name); + } + cho_font_free(style->font); + style->font = font; } - cho_font_free(style->font); - style->font = font; - } - } else if ( - !strcmp(attrs[a]->name, "font_family") || - !strcmp(attrs[a]->name, "face") - ) { - if (!strcmp(attrs[a]->value, "normal")) { - style->font->family = FONT_FAMILY_NORMAL; - presence->font.family = true; - } else if (!strcmp(attrs[a]->value, "sans")) { - style->font->family = FONT_FAMILY_SANS; - presence->font.family = true; - } else if (!strcmp(attrs[a]->value, "serif")) { - style->font->family = FONT_FAMILY_SERIF; - presence->font.family = true; - } else if (!strcmp(attrs[a]->value, "monospace")) { - style->font->family = FONT_FAMILY_MONOSPACE; - presence->font.family = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'font_family/face' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "size")) { - value_len = strlen(attrs[a]->value); - last_char = value_len - 1; - if (attrs[a]->value[last_char] == '%') { - if (value_len < 5) { - attrs[a]->value[last_char] = 0; - int percentage = atoi(attrs[a]->value); - if (percentage != 0 && percentage <= 100) { - style->font->size *= percentage / 100.0; + } else if ( + !strcmp((*a)->name, "font_family") || + !strcmp((*a)->name, "face") + ) { + if (!strcmp((*a)->value, "normal")) { + style->font->family = FONT_FAMILY_NORMAL; + presence->font.family = true; + } else if (!strcmp((*a)->value, "sans")) { + style->font->family = FONT_FAMILY_SANS; + presence->font.family = true; + } else if (!strcmp((*a)->value, "serif")) { + style->font->family = FONT_FAMILY_SERIF; + presence->font.family = true; + } else if (!strcmp((*a)->value, "monospace")) { + style->font->family = FONT_FAMILY_MONOSPACE; + presence->font.family = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'font_family/face' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } + } else if (!strcmp((*a)->name, "size")) { + value_len = strlen((*a)->value); + last_char = value_len - 1; + if ((*a)->value[last_char] == '%') { + if (value_len < 5) { + (*a)->value[last_char] = 0; + int percentage = atoi((*a)->value); + if (percentage != 0 && percentage <= 100) { + style->font->size *= percentage / 100.0; + presence->font.size = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + goto ERR; + } + } else { + cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid percentage '%s'.", tag_name, (*a)->value); + goto ERR; + } + } else if (isdigit((*a)->value[0]) != 0) { + double size = strtod((*a)->value, NULL); + if (size != 0.0) { + style->font->size = size; presence->font.size = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid number '%.1f'.", tag_name, size); goto ERR; } + } else if (!strcmp((*a)->value, "xx-small")) { + style->font->size *= 0.8; + style->font->size *= 0.8; + style->font->size *= 0.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "x-small")) { + style->font->size *= 0.8; + style->font->size *= 0.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "small")) { + style->font->size *= 0.8; + presence->font.size = true; + // } else if (!strcmp((*a)->value, "medium")) { + } else if (!strcmp((*a)->value, "large")) { + style->font->size *= 1.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "x-large")) { + style->font->size *= 1.8; + style->font->size *= 1.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "xx-large")) { + style->font->size *= 1.8; + style->font->size *= 1.8; + style->font->size *= 1.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "larger")) { + style->font->size *= 1.8; + presence->font.size = true; + } else if (!strcmp((*a)->value, "smaller")) { + style->font->size *= 0.8; + presence->font.size = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid percentage '%s'.", tag_name, attrs[a]->value); + cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); goto ERR; } - } else if (isdigit(attrs[a]->value[0]) != 0) { - double size = strtod(attrs[a]->value, NULL); - if (size != 0.0) { - style->font->size = size; - presence->font.size = true; + } else if (!strcmp((*a)->name, "style")) { + if (!strcmp((*a)->value, "normal")) { + style->font->style = FONT_STYLE_ROMAN; + presence->font.style = true; + } else if (!strcmp((*a)->value, "oblique")) { + style->font->style = FONT_STYLE_OBLIQUE; + presence->font.style = true; + } else if (!strcmp((*a)->value, "italic")) { + style->font->style = FONT_STYLE_ITALIC; + presence->font.style = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid number '%.1f'.", tag_name, size); + cho_log(ctx, LOG_ERR, "Attribute 'style' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); goto ERR; } - } else if (!strcmp(attrs[a]->value, "xx-small")) { - style->font->size *= 0.8; - style->font->size *= 0.8; - style->font->size *= 0.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "x-small")) { - style->font->size *= 0.8; - style->font->size *= 0.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "small")) { - style->font->size *= 0.8; - presence->font.size = true; - // } else if (!strcmp(attrs[a]->value, "medium")) { - } else if (!strcmp(attrs[a]->value, "large")) { - style->font->size *= 1.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "x-large")) { - style->font->size *= 1.8; - style->font->size *= 1.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "xx-large")) { - style->font->size *= 1.8; - style->font->size *= 1.8; - style->font->size *= 1.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "larger")) { - style->font->size *= 1.8; - presence->font.size = true; - } else if (!strcmp(attrs[a]->value, "smaller")) { - style->font->size *= 0.8; - presence->font.size = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'size' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "style")) { - if (!strcmp(attrs[a]->value, "normal")) { - style->font->style = FONT_STYLE_ROMAN; - presence->font.style = true; - } else if (!strcmp(attrs[a]->value, "oblique")) { - style->font->style = FONT_STYLE_OBLIQUE; - presence->font.style = true; - } else if (!strcmp(attrs[a]->value, "italic")) { - style->font->style = FONT_STYLE_ITALIC; - presence->font.style = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'style' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "weight")) { - if (!strcmp(attrs[a]->value, "normal")) { - style->font->weight = FONT_WEIGHT_REGULAR; - presence->font.weight = true; - } else if (!strcmp(attrs[a]->value, "bold")) { - style->font->weight = FONT_WEIGHT_BOLD; - presence->font.weight = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'weight' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "foreground")) { - rgb_color = cho_color_parse(attrs[a]->value); - if (!rgb_color) { - LOG_DEBUG("cho_color_parse failed."); - cho_log(ctx, LOG_ERR, "Attribute 'foreground' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } else { - free(style->foreground_color); - style->foreground_color = rgb_color; - presence->foreground_color = true; - } - } else if (!strcmp(attrs[a]->name, "background")) { - rgb_color = cho_color_parse(attrs[a]->value); - if (!rgb_color) { - LOG_DEBUG("cho_color_parse failed."); - cho_log(ctx, LOG_ERR, "Attribute 'background' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } else { - free(style->background_color); - style->background_color = rgb_color; - presence->background_color = true; - } - } else if (!strcmp(attrs[a]->name, "underline")) { - if (!strcmp(attrs[a]->value, "single")) { - style->underline_style = LINE_STYLE_SINGLE; - presence->underline_style = true; - } else if (!strcmp(attrs[a]->value, "double")) { - style->underline_style = LINE_STYLE_DOUBLE; - presence->underline_style = true; - } else if (!strcmp(attrs[a]->value, "none")) { - style->underline_style = LINE_STYLE_NONE; - presence->underline_style = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'underline' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "underline_colour")) { - rgb_color = cho_color_parse(attrs[a]->value); - if (!rgb_color) { - LOG_DEBUG("cho_color_parse failed."); - cho_log(ctx, LOG_ERR, "Attribute 'underline_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } else { - free(style->underline_color); - style->underline_color = rgb_color; - presence->underline_color = true; - } - } else if (!strcmp(attrs[a]->name, "overline")) { - if (!strcmp(attrs[a]->value, "single")) { - style->overline_style = LINE_STYLE_SINGLE; - presence->overline_style = true; - } else if (!strcmp(attrs[a]->value, "double")) { - style->overline_style = LINE_STYLE_DOUBLE; - presence->overline_style = true; - } else if (!strcmp(attrs[a]->value, "none")) { - style->overline_style = LINE_STYLE_NONE; - presence->overline_style = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute 'overline' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else if (!strcmp(attrs[a]->name, "overline_colour")) { - rgb_color = cho_color_parse(attrs[a]->value); - if (!rgb_color) { - LOG_DEBUG("cho_color_parse failed."); - cho_log(ctx, LOG_ERR, "Attribute 'overline_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } else { - free(style->overline_color); - style->overline_color = rgb_color; - presence->overline_color = true; - } - } else if (!strcmp(attrs[a]->name, "rise")) { - value_len = strlen(attrs[a]->value); - last_char = value_len - 1; - if (attrs[a]->value[0] == '-') { - if (attrs[a]->value[last_char] == '%') { - if (value_len < 6) { - attrs[a]->value[last_char] = 0; - int percentage = atoi(&attrs[a]->value[1]); - if (percentage != 0 && percentage <= 100) { - style->rise = (style->font->size / 2) * percentage / 100.0; + } else if (!strcmp((*a)->name, "weight")) { + if (!strcmp((*a)->value, "normal")) { + style->font->weight = FONT_WEIGHT_REGULAR; + presence->font.weight = true; + } else if (!strcmp((*a)->value, "bold")) { + style->font->weight = FONT_WEIGHT_BOLD; + presence->font.weight = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'weight' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } + } else if (!strcmp((*a)->name, "foreground")) { + rgb_color = cho_color_parse((*a)->value); + if (!rgb_color) { + LOG_DEBUG("cho_color_parse failed."); + cho_log(ctx, LOG_ERR, "Attribute 'foreground' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } else { + free(style->foreground_color); + style->foreground_color = rgb_color; + presence->foreground_color = true; + } + } else if (!strcmp((*a)->name, "background")) { + rgb_color = cho_color_parse((*a)->value); + if (!rgb_color) { + LOG_DEBUG("cho_color_parse failed."); + cho_log(ctx, LOG_ERR, "Attribute 'background' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } else { + free(style->background_color); + style->background_color = rgb_color; + presence->background_color = true; + } + } else if (!strcmp((*a)->name, "underline")) { + if (!strcmp((*a)->value, "single")) { + style->underline_style = LINE_STYLE_SINGLE; + presence->underline_style = true; + } else if (!strcmp((*a)->value, "double")) { + style->underline_style = LINE_STYLE_DOUBLE; + presence->underline_style = true; + } else if (!strcmp((*a)->value, "none")) { + style->underline_style = LINE_STYLE_NONE; + presence->underline_style = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'underline' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } + } else if (!strcmp((*a)->name, "underline_colour")) { + rgb_color = cho_color_parse((*a)->value); + if (!rgb_color) { + LOG_DEBUG("cho_color_parse failed."); + cho_log(ctx, LOG_ERR, "Attribute 'underline_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } else { + free(style->underline_color); + style->underline_color = rgb_color; + presence->underline_color = true; + } + } else if (!strcmp((*a)->name, "overline")) { + if (!strcmp((*a)->value, "single")) { + style->overline_style = LINE_STYLE_SINGLE; + presence->overline_style = true; + } else if (!strcmp((*a)->value, "double")) { + style->overline_style = LINE_STYLE_DOUBLE; + presence->overline_style = true; + } else if (!strcmp((*a)->value, "none")) { + style->overline_style = LINE_STYLE_NONE; + presence->overline_style = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'overline' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } + } else if (!strcmp((*a)->name, "overline_colour")) { + rgb_color = cho_color_parse((*a)->value); + if (!rgb_color) { + LOG_DEBUG("cho_color_parse failed."); + cho_log(ctx, LOG_ERR, "Attribute 'overline_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } else { + free(style->overline_color); + style->overline_color = rgb_color; + presence->overline_color = true; + } + } else if (!strcmp((*a)->name, "rise")) { + value_len = strlen((*a)->value); + last_char = value_len - 1; + if ((*a)->value[0] == '-') { + if ((*a)->value[last_char] == '%') { + if (value_len < 6) { + (*a)->value[last_char] = 0; + int percentage = atoi(&(*a)->value[1]); + if (percentage != 0 && percentage <= 100) { + style->rise = (style->font->size / 2) * percentage / 100.0; + presence->rise = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + goto ERR; + } + } + } else if (isdigit((*a)->value[1]) != 0) { + double rise = strtod((*a)->value, NULL); + if (rise != 0.0) { + style->rise = rise; presence->rise = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid number '%d'.", tag_name, rise); goto ERR; } - } - } else if (isdigit(attrs[a]->value[1]) != 0) { - double rise = strtod(attrs[a]->value, NULL); - if (rise != 0.0) { - style->rise = rise; - presence->rise = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid number '%d'.", tag_name, rise); + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); goto ERR; } } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } - } else { - if (attrs[a]->value[last_char] == '%') { - if (value_len < 5) { - attrs[a]->value[last_char] = 0; - int percentage = atoi(attrs[a]->value); - if (percentage != 0 && percentage <= 100) { - // TODO: Test if that's right - double more = style->font->size / 2.0 * percentage / 100.0; - style->rise += more; + if ((*a)->value[last_char] == '%') { + if (value_len < 5) { + (*a)->value[last_char] = 0; + int percentage = atoi((*a)->value); + if (percentage != 0 && percentage <= 100) { + // TODO: Test if that's right + double more = style->font->size / 2.0 * percentage / 100.0; + style->rise += more; + presence->rise = true; + } else { + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + goto ERR; + } + } + } else if (isdigit((*a)->value[0]) != 0) { + double rise = strtod((*a)->value, NULL); + if (rise != 0.0) { + style->rise = rise; presence->rise = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid percentage '%d'.", tag_name, percentage); + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid number '%d'.", tag_name, rise); goto ERR; } - } - } else if (isdigit(attrs[a]->value[0]) != 0) { - double rise = strtod(attrs[a]->value, NULL); - if (rise != 0.0) { - style->rise = rise; - presence->rise = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid number '%d'.", tag_name, rise); + cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); goto ERR; } + } + } else if (!strcmp((*a)->name, "strikethrough")) { + if (!strcmp((*a)->value, "true")) { + style->strikethrough = true; + presence->strikethrough = true; + } else if (!strcmp((*a)->value, "false")) { + style->strikethrough = false; + presence->strikethrough = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'rise' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); + cho_log(ctx, LOG_ERR, "Attribute 'strikethrough' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); goto ERR; } - } - } else if (!strcmp(attrs[a]->name, "strikethrough")) { - if (!strcmp(attrs[a]->value, "true")) { - style->strikethrough = true; - presence->strikethrough = true; - } else if (!strcmp(attrs[a]->value, "false")) { - style->strikethrough = false; - presence->strikethrough = true; + } else if (!strcmp((*a)->name, "strikethrough_colour")) { + rgb_color = cho_color_parse((*a)->value); + if (!rgb_color) { + LOG_DEBUG("cho_color_parse failed."); + cho_log(ctx, LOG_ERR, "Attribute 'strikethrough_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, (*a)->value); + goto ERR; + } else { + free(style->strikethrough_color); + style->strikethrough_color = rgb_color; + presence->strikethrough_color = true; + } + } else if (!strcmp((*a)->name, "href")) { + style->href = strdup((*a)->value); + presence->href = true; } else { - cho_log(ctx, LOG_ERR, "Attribute 'strikethrough' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); + cho_log(ctx, LOG_ERR, "Attribute '%s' of markup tag '%s' is invalid.", (*a)->name, tag_name); goto ERR; } - } else if (!strcmp(attrs[a]->name, "strikethrough_colour")) { - rgb_color = cho_color_parse(attrs[a]->value); - if (!rgb_color) { - LOG_DEBUG("cho_color_parse failed."); - cho_log(ctx, LOG_ERR, "Attribute 'strikethrough_colour' of markup tag '%s' has an invalid value '%s'.", tag_name, attrs[a]->value); - goto ERR; - } else { - free(style->strikethrough_color); - style->strikethrough_color = rgb_color; - presence->strikethrough_color = true; - } - } else if (!strcmp(attrs[a]->name, "href")) { - style->href = strdup(attrs[a]->value); - presence->href = true; - } else { - cho_log(ctx, LOG_ERR, "Attribute '%s' of markup tag '%s' is invalid.", attrs[a]->name, tag_name); - goto ERR; } + } else { + cho_log(ctx, LOG_INFO, "'span' markup tag has no attributes and therefore no effect."); } } else if (!strcmp(tag_name, "b")) { style->font->weight = FONT_WEIGHT_BOLD; @@ -4910,7 +4915,8 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c struct ChoLine ***lines; struct ChoContext ctx; bool err; - char *metadata_value, *stripped_directive_value, *shape; + char *metadata_value, *shape; + char *stripped_directive_value = NULL; char *label = NULL; char directive_name[128]; char directive_value[4096]; @@ -6603,6 +6609,7 @@ cho_songs_parse(const char *str, const char *chordpro_filepath, struct Config *c cho_song_free(ctx.songs[e]); } free(ctx.songs); + free(stripped_directive_value); cho_directive_free(directive); cho_tag_attrs_free(directive_attrs); cho_metadata_free(metadata);