commit 5262593690217c8b6e06fe3537184ff48dc78ffd
parent 35ea8f898f3d437ecb47b5dde1e44a2e09c84f30
Author: nibo <nibo@relim.de>
Date: Wed, 9 Oct 2024 18:15:18 +0200
Improve logging
Diffstat:
| M | Makefile | | | 6 | ++++-- |
| M | chordpro.c | | | 247 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
| M | chordpro.h | | | 14 | +------------- |
| M | config.c | | | 10 | +++++----- |
| M | lorid.c | | | 16 | +++++++++------- |
| M | out_pdf.c | | | 132 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
| M | todo | | | 6 | +++++- |
| M | util.c | | | 68 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | util.h | | | 14 | ++++++++++++-- |
9 files changed, 326 insertions(+), 187 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,10 +4,12 @@ CFLAGS = -pedantic -Wall -Wextra -DVERSION=\"${VERSION}\"
LDFLAGS = -lpdfio -ltoml -lfontconfig
SRC = util.c fontconfig.c config.c chordpro.c out_pdf.c lorid.c
+COLOR = 0
+
all:
- $(CC) ${CFLAGS} -O2 ${SRC} -o lorid ${LDFLAGS}
+ $(CC) ${CFLAGS} -DCOLOR=${COLOR} -O2 ${SRC} -o lorid ${LDFLAGS}
debug:
- $(CC) ${CFLAGS} -DDEBUG=1 -g ${SRC} -o lorid ${LDFLAGS}
+ $(CC) ${CFLAGS} -DCOLOR=${COLOR} -DDEBUG -g ${SRC} -o lorid ${LDFLAGS}
clean:
rm *.o
rm lorid
diff --git a/chordpro.c b/chordpro.c
@@ -2,11 +2,11 @@
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
+#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-#include <math.h>
#include "chordpro.h"
#include "config.h"
#include "util.h"
@@ -177,6 +177,7 @@ static const char *chord_extensions_minor[] = {
static enum SongFragmentType g_current_ftype = SF_TEXT;
static enum SongFragmentType g_prev_ftype = SF_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;
@@ -269,6 +270,66 @@ static void cho_debug_chord_print(struct ChoChord *chord)
#endif /* DEBUG */
+static void cho_log(enum LogLevel level, const char *msg, ...)
+{
+ va_list va;
+ va_start(va, msg);
+#if COLOR == 1
+ const char *log_level;
+ const char *color;
+ switch (level) {
+ case LOG_INFO:
+ log_level = "INFO";
+ color = "37";
+ break;
+ case LOG_WARN:
+ log_level = "WARN";
+ color = "33";
+ break;
+ case LOG_ERR:
+ log_level = " ERR";
+ color = "31";
+ break;
+ }
+ if (g_chordpro_filepath) {
+ /* fprintf(stderr, "\033[1m%s:%ld:\033[0m \033[1m\033[%sm%s\033[0m: %s\n",
+ g_chordpro_filepath, g_line_number, color, log_level, msg); */
+ fprintf(stderr, "\033[1m%s:%ld:\033[0m \033[1m\033[%sm%s\033[0m: ",
+ g_chordpro_filepath, g_line_number, color, log_level);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+ } else {
+ fprintf(stderr, "line \033[1m%ld:\033[0m \033[1m\033[%sm%s\033[0m: ",
+ g_line_number, color, log_level);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+ }
+#else
+ const char *log_level;
+ switch (level) {
+ case LOG_INFO:
+ log_level = "INFO";
+ break;
+ case LOG_WARN:
+ log_level = "WARN";
+ break;
+ case LOG_ERR:
+ log_level = " ERR";
+ break;
+ }
+ if (g_chordpro_filepath) {
+ fprintf(stderr, "%s:%ld: %s: ", g_chordpro_filepath, g_line_number,
+ log_level);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+ } else {
+ fprintf(stderr, "line %ld: %s: ", g_line_number, log_level);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+ }
+#endif
+}
+
static inline bool is_whitespace(char c)
{
if (
@@ -323,7 +384,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[2];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -337,7 +398,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[4];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -351,7 +412,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[6];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -367,7 +428,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[1];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -381,7 +442,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[2];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -395,7 +456,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
tmp[1] = str[3];
primary_color = strtol((char *)&tmp, NULL, 16);
if (primary_color == 0) {
- fprintf(stderr, "ERR: Invalid primary color in rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid primary color in rgb color.");
free(color);
return NULL;
} else {
@@ -403,7 +464,7 @@ struct RGBColor *cho_rgbcolor_parse(const char *str)
}
}
} else {
- fprintf(stderr, "ERR: Invalid rgb color, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid rgb color.");
free(color);
return NULL;
}
@@ -420,7 +481,7 @@ struct RGBColor *cho_color_parse(const char *str)
color = rgb_color;
} else {
free(color);
- DEBUG_MSG("cho_rgbcolor_parse failed.");
+ LOG_DEBUG("cho_rgbcolor_parse failed.");
return NULL;
}
} else if (!strcmp(str, "red")) {
@@ -460,7 +521,7 @@ struct RGBColor *cho_color_parse(const char *str)
color->green = 0;
color->blue = 0;
} else {
- fprintf(stderr, "ERR: Invalid color value '%s', line '%ld'.\n", str, g_line_number);
+ cho_log(LOG_ERR, "Invalid color value '%s'.", str);
free(color);
return NULL;
}
@@ -699,7 +760,7 @@ static bool cho_style_property_apply_default(enum SongFragmentType current_ftype
}
break;
default:
- fprintf(stderr, "WARN: Invalid style property type '%d', line '%ld'.\n", ptype, g_line_number);
+ cho_log(LOG_WARN, "Invalid style property type '%d'.", ptype);
return false;
}
}
@@ -959,7 +1020,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "monospace")) {
style->font->family = FF_MONOSPACE;
} else {
- fprintf(stderr, "ERR: Invalid value in attribute 'font_family/face', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid value in attribute 'font_family/face'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "size")) {
@@ -972,11 +1033,11 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
if (percentage != 0 && percentage <= 100) {
style->font->size *= percentage / 100.0;
} else {
- fprintf(stderr, "ERR: Invalid percentage in attribute 'size', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid percentage in attribute 'size'.");
return NULL;
}
} else {
- fprintf(stderr, "ERR: Invalid percentage in attribute 'size', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid percentage in attribute 'size'.");
return NULL;
}
} else if (isdigit(attrs[a]->value[0]) != 0) {
@@ -984,7 +1045,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
if (size != 0.0) {
style->font->size = size;
} else {
- fprintf(stderr, "ERR: Invalid number in attribute 'size', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid number in attribute 'size'.");
return NULL;
}
} else if (!strcmp(attrs[a]->value, "xx-small")) {
@@ -1011,7 +1072,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "smaller")) {
style->font->size *= 0.8;
} else {
- fprintf(stderr, "ERR: Invalid value '%s' for the attribute 'size', line '%ld'.\n", attrs[a]->value, g_line_number);
+ cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'size'.", attrs[a]->value);
return NULL;
}
} else if (!strcmp(attrs[a]->name, "style")) {
@@ -1022,7 +1083,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "italic")) {
style->font->style = FS_ITALIC;
} else {
- fprintf(stderr, "ERR: Invalid value in attribute 'style', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid value in attribute 'style'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "weight")) {
@@ -1031,13 +1092,13 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "bold")) {
style->font->weight = FW_BOLD;
} else {
- fprintf(stderr, "ERR: Invalid value in attribute 'weight', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid value in attribute 'weight'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "foreground")) {
rgb_color = cho_color_parse(attrs[a]->value);
if (!rgb_color) {
- DEBUG_MSG("cho_color_parse failed.");
+ LOG_DEBUG("cho_color_parse failed.");
return NULL;
} else {
free(style->foreground_color);
@@ -1046,7 +1107,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->name, "background")) {
rgb_color = cho_color_parse(attrs[a]->value);
if (!rgb_color) {
- DEBUG_MSG("cho_color_parse failed.");
+ LOG_DEBUG("cho_color_parse failed.");
return NULL;
} else {
free(style->background_color);
@@ -1060,13 +1121,13 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "none")) {
style->underline_style = LS_NONE;
} else {
- fprintf(stderr, "ERR: Invalid value in attribute 'underline', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid value in attribute 'underline'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "underline_colour")) {
rgb_color = cho_color_parse(attrs[a]->value);
if (!rgb_color) {
- DEBUG_MSG("cho_color_parse failed.");
+ LOG_DEBUG("cho_color_parse failed.");
return NULL;
} else {
free(style->underline_color);
@@ -1080,13 +1141,13 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "none")) {
style->overline_style = LS_NONE;
} else {
- fprintf(stderr, "ERR: Invalid value in attribute 'overline', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid value in attribute 'overline'.");
return NULL;
}
} else if (!strcmp(attrs[a]->name, "overline_colour")) {
rgb_color = cho_color_parse(attrs[a]->value);
if (!rgb_color) {
- DEBUG_MSG("cho_color_parse failed.");
+ LOG_DEBUG("cho_color_parse failed.");
return NULL;
} else {
free(style->overline_color);
@@ -1103,7 +1164,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
if (percentage != 0 && percentage <= 100) {
style->rise = (style->font->size / 2) * percentage / 100.0;
} else {
- fprintf(stderr, "ERR: Invalid percentage in attribute 'rise', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid percentage in attribute 'rise'.");
return NULL;
}
}
@@ -1112,11 +1173,11 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
if (rise != 0.0) {
style->rise = rise;
} else {
- fprintf(stderr, "ERR: Invalid number in attribute 'rise', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid number in attribute 'rise'.");
return NULL;
}
} else {
- fprintf(stderr, "ERR: Invalid value '%s' for the attribute 'rise', line '%ld'.\n", attrs[a]->value, g_line_number);
+ cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
return NULL;
}
} else {
@@ -1129,7 +1190,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
double more = style->font->size / 2.0 * percentage / 100.0;
style->rise += more;
} else {
- fprintf(stderr, "ERR: Invalid percentage in attribute 'rise', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid percentage in attribute 'rise'.");
return NULL;
}
}
@@ -1138,11 +1199,11 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
if (rise != 0.0) {
style->rise = rise;
} else {
- fprintf(stderr, "ERR: Invalid number in attribute 'rise', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Invalid number in attribute 'rise'.");
return NULL;
}
} else {
- fprintf(stderr, "ERR: Invalid value '%s' for the attribute 'rise', line '%ld'.\n", attrs[a]->value, g_line_number);
+ cho_log(LOG_ERR, "Invalid value '%s' for the attribute 'rise'.", attrs[a]->value);
return NULL;
}
}
@@ -1152,13 +1213,13 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->value, "false")) {
style->strikethrough = false;
} else {
- fprintf(stderr, "ERR: Invalid value '%s' in attribute 'strikethrough', line '%ld'.\n", attrs[a]->value, g_line_number);
+ cho_log(LOG_ERR, "Invalid value '%s' in attribute 'strikethrough'.", attrs[a]->value);
return NULL;
}
} else if (!strcmp(attrs[a]->name, "strikethrough_colour")) {
rgb_color = cho_color_parse(attrs[a]->value);
if (!rgb_color) {
- DEBUG_MSG("cho_color_parse failed.");
+ LOG_DEBUG("cho_color_parse failed.");
return NULL;
} else {
free(style->strikethrough_color);
@@ -1167,7 +1228,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(attrs[a]->name, "href")) {
style->href = strdup(attrs[a]->value);
} else {
- fprintf(stderr, "ERR: Invalid attribute '%s', line '%ld'.\n", attrs[a]->name, g_line_number);
+ cho_log(LOG_ERR, "Invalid attribute '%s'.", attrs[a]->name);
return NULL;
}
a++;
@@ -1193,7 +1254,7 @@ struct Style *cho_style_parse(const char *tag_name, struct Attr **attrs, struct
} else if (!strcmp(tag_name, "u")) {
style->underline_style = LS_SINGLE;
} else {
- fprintf(stderr, "ERR: Invalid tag name '%s', line '%ld'.\n", tag_name, g_line_number);
+ cho_log(LOG_ERR, "Invalid tag name '%s'.", tag_name);
cho_style_free(style);
return NULL;
}
@@ -1249,7 +1310,7 @@ static bool cho_style_change_default(struct StyleProperty sprop)
}
return true;
default:
- fprintf(stderr, "ERR: Invalid style property type '%d', line '%ld'.\n", sprop.type, g_line_number);
+ cho_log(LOG_ERR, "Invalid style property type '%d'.", sprop.type);
return false;
}
}
@@ -1274,7 +1335,7 @@ static bool cho_style_reset_default(void)
default_style_properties[i].u.foreground_color = NULL;
return true;
default:
- fprintf(stderr, "ERR: Invalid style property type '%d', line '%ld'.\n", default_style_properties[i].type, g_line_number);
+ cho_log(LOG_ERR, "Invalid style property type '%d'.", default_style_properties[i].type);
return false;
}
}
@@ -1335,7 +1396,7 @@ static bool cho_tag_close_last_unclosed(const char *tag_name, struct Tag **tags,
}
i--;
}
- fprintf(stderr, "ERR: Didn't find a start tag for the end tag '%s', line '%ld'.\n", tag_name, g_line_number);
+ cho_log(LOG_ERR, "Didn't find a start tag for the end tag '%s'.", tag_name);
return false;
}
@@ -1411,7 +1472,7 @@ static struct ChoMetadata *cho_metadata_split(const char *directive_value)
free(meta->name);
free(meta->value);
free(meta);
- fprintf(stderr, "ERR: Failed to parse directive 'meta', line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Failed to parse directive 'meta'.");
return NULL;
}
}
@@ -1507,7 +1568,7 @@ static char *transposition_calc_chord_root(int index, enum NoteType type)
case NT_FLAT:
return strdup(g_config->output->notes[new_index]->flat);
}
- fprintf(stderr, "ERR: Invalid NoteType '%d', line '%ld'.\n", note_type, g_line_number);
+ cho_log(LOG_ERR, "Invalid NoteType '%d'.", note_type);
return NULL;
}
@@ -1565,7 +1626,7 @@ static int cho_chord_root_parse(const char *str, struct ChoChord *chord)
if (sharp && str_starts_with(str, sharp)) {
transposed_root = transposition_calc_chord_root(i, NT_SHARP);
if (!transposed_root) {
- DEBUG_MSG("transposition_calc_chord_root failed.");
+ LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
}
chord->root = transposed_root;
@@ -1575,7 +1636,7 @@ static int cho_chord_root_parse(const char *str, struct ChoChord *chord)
if (flat && str_starts_with(str, flat)) {
transposed_root = transposition_calc_chord_root(i, NT_FLAT);
if (!transposed_root) {
- DEBUG_MSG("transposition_calc_chord_root failed.");
+ LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
}
chord->root = transposed_root;
@@ -1585,7 +1646,7 @@ static int cho_chord_root_parse(const char *str, struct ChoChord *chord)
if (str_starts_with(str, note)) {
transposed_root = transposition_calc_chord_root(i, NT_NOTE);
if (!transposed_root) {
- DEBUG_MSG("transposition_calc_chord_root failed.");
+ LOG_DEBUG("transposition_calc_chord_root failed.");
return 0;
}
chord->root = transposed_root;
@@ -1997,7 +2058,7 @@ static struct ChoImage *cho_image_directive_parse(const char *str)
case OS_VALUE:
if (avs == AVS_NO) {
if (is_whitespace(c)) {
- fprintf(stderr, "ERR: Whitespace character after equals sign in image directive is invalid, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Whitespace character after equals sign in image directive is invalid.");
return NULL;
}
if (c == '\'') {
@@ -2012,7 +2073,7 @@ static struct ChoImage *cho_image_directive_parse(const char *str)
break;
}
if (c == '\n') {
- fprintf(stderr, "ERR: Newline character inside an option value in image directive is invalid, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Newline character inside an option value in image directive is invalid.");
return NULL;
}
if (
@@ -2339,9 +2400,10 @@ END:
return directive;
}
-struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
+struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
{
g_config = config;
+ g_chordpro_filepath = chordpro_filepath;
bool is_chord_already_initialized = false;
char buf = 0;
char prev_buf = '\n';
@@ -2396,6 +2458,9 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
while (feof(fp) == 0) {
read = fread(&buf, 1, 1, fp);
if (read == 1) {
+ if (buf == '\n') {
+ g_line_number++;
+ }
// printf("state: %s, prev_state: %s, prev_buf: %c, buf: %c\n", cho_state_to_string(state), cho_state_to_string(prev_state), prev_buf, buf);
if (buf == '\r') {
continue;
@@ -2530,12 +2595,12 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
}
break;
default:
- fprintf(stderr, "ERR: Invalid position value '%d', line '%ld'.\n", directive->position, g_line_number);
+ cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position);
return NULL;
}
break;
case DT_METADATA:
- fprintf(stderr, "INFO: Metadata directive '%s' has no value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_INFO, "Metadata directive '%s' has no value.", directive_name);
songs[so]->metadata = realloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
songs[so]->metadata[m] = cho_metadata_new();
songs[so]->metadata[m]->name = strdup(directive_name);
@@ -2543,10 +2608,10 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
memset(directive_name, 0, strlen(directive_name));
break;
case DT_FORMATTING:
- fprintf(stderr, "WARN: Formatting directive '%s' has no value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_WARN, "Formatting directive '%s' has no value.", directive_name);
break;
case DT_IMAGE:
- fprintf(stderr, "ERR: Directive 'image' has no value, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Directive 'image' has no value.");
return NULL;
case DT_PREAMBLE:
// INFO: The only preamble directive is 'new_song'
@@ -2560,7 +2625,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
songs[so]->sections[se] = NULL;
if (!cho_style_reset_default()) {
- DEBUG_MSG("cho_style_reset_default failed.");
+ LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
so++;
@@ -2591,11 +2656,11 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
sprop.u.foreground_color = NULL;
break;
default:
- fprintf(stderr, "ERR: Invalid style property type '%d', line '%ld'.\n", directive->sprop, g_line_number);
+ cho_log(LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
return NULL;
}
if (!cho_style_change_default(sprop)) {
- DEBUG_MSG("cho_style_change_default failed.");
+ LOG_DEBUG("cho_style_change_default failed.");
return NULL;
}
break;
@@ -2611,10 +2676,10 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
case DT_CUSTOM:
// TODO: Implement {start_of_*} and {end_of_*} custom directives
- fprintf(stderr, "INFO: Ignoring custom directive '%s', line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
break;
default:
- fprintf(stderr, "ERR: Invalid directive '%s', line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_ERR, "Invalid directive '%s'.", directive_name);
return NULL;
}
cho_directive_free(directive);
@@ -2685,7 +2750,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
}
break;
default:
- fprintf(stderr, "ERR: Invalid position value '%d', line '%ld'.\n", directive->position, g_line_number);
+ cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position);
return NULL;
}
break;
@@ -2697,7 +2762,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->metadata[m] = metadata;
m++;
} else {
- DEBUG_MSG("cho_metadata_split failed.");
+ LOG_DEBUG("cho_metadata_split failed.");
return NULL;
}
} else {
@@ -2738,13 +2803,13 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
case DT_IMAGE:
image = cho_image_directive_parse(directive_value);
if (!image) {
- DEBUG_MSG("cho_image_directive_parse failed.");
+ LOG_DEBUG("cho_image_directive_parse failed.");
return NULL;
}
cho_image_free(image);
break;
case DT_PREAMBLE:
- fprintf(stderr, "ERR: Preamble directive '%s' can't have a value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_ERR, "Preamble directive '%s' can't have a value.", directive_name);
return NULL;
case DT_FONT:
sprop.ftype = directive->ftype;
@@ -2758,7 +2823,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
case SPT_SIZE:
sprop.u.font_size = strtod(dir_value, NULL);
if (sprop.u.font_size == 0.0) {
- fprintf(stderr, "ERR: Font directive '%s' has an invalid value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
return NULL;
}
sprop.type = SPT_SIZE;
@@ -2766,17 +2831,17 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
case SPT_COLOR:
sprop.u.foreground_color = cho_color_parse(dir_value);
if (sprop.u.foreground_color == NULL) {
- fprintf(stderr, "ERR: Font directive '%s' has an invalid value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_ERR, "Font directive '%s' has an invalid value.", directive_name);
return NULL;
}
sprop.type = SPT_COLOR;
break;
default:
- fprintf(stderr, "ERR: Invalid style property type '%d', line '%ld'.\n", directive->sprop, g_line_number);
+ cho_log(LOG_ERR, "Invalid style property type '%d'.", directive->sprop);
return NULL;
}
if (!cho_style_change_default(sprop)) {
- DEBUG_MSG("cho_style_change_default failed.");
+ LOG_DEBUG("cho_style_change_default failed.");
return NULL;
}
if (sprop.type == SPT_FONT) {
@@ -2789,8 +2854,8 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
case DT_CHORD:
/* INFO: The only chord directive is currently 'transpose' */
if (!transposition_parse(directive_value, &transpose)) {
- DEBUG_MSG("transposition_parse failed.");
- fprintf(stderr, "ERR: Directive 'transpose' has an invalid value, line '%ld'.\n", g_line_number);
+ LOG_DEBUG("transposition_parse failed.");
+ cho_log(LOG_ERR, "Directive 'transpose' has an invalid value.");
return NULL;
}
g_transpose_history = realloc(g_transpose_history, (th+1) * sizeof(int *));
@@ -2799,13 +2864,13 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
th++;
break;
case DT_OUTPUT:
- fprintf(stderr, "ERR: Directive '%s' can't have a value, line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_ERR, "Directive '%s' can't have a value.", directive_name);
return NULL;
case DT_CUSTOM:
- fprintf(stderr, "INFO: Ignoring custom directive '%s', line '%ld'.\n", directive_name, g_line_number);
+ cho_log(LOG_INFO, "Ignoring custom directive '%s'.", directive_name);
break;
default:
- fprintf(stderr, "ERR: Invalid directive '%d', line '%ld'.\n", directive->dtype, g_line_number);
+ cho_log(LOG_ERR, "Invalid directive type '%d'.", directive->dtype);
return NULL;
}
memset(directive_value, 0, strlen(directive_value));
@@ -2829,7 +2894,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tmp_chord = cho_chord_parse(chord);
cho_chord_complete(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord, tmp_chord);
if (!songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->is_canonical) {
- fprintf(stderr, "INFO: Didn't recognize the chord '%s', line '%ld'.\n", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name, g_line_number);
+ cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name);
}
cho_chord_free(tmp_chord);
is_chord_already_initialized = false;
@@ -2842,7 +2907,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos;
songs[so]->sections[se]->lines[li]->text_above[c]->u.chord = cho_chord_parse(chord);
if (!songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->is_canonical) {
- fprintf(stderr, "INFO: Didn't recognize the chord '%s', line '%ld'.\n", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name, g_line_number);
+ cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name);
}
// cho_debug_chord_print(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord);
}
@@ -2917,7 +2982,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tags[ta]->name = strdup(tag_begin);
tag_style = cho_style_parse(tag_begin, NULL, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
- DEBUG_MSG("cho_style_parse failed.");
+ LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
tags[ta]->style = tag_style;
@@ -2935,7 +3000,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
- fprintf(stderr, "ERR: Invalid prev_state '%s', line '%ld'.\n", state_enums[prev_state], g_line_number);
+ cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]);
return NULL;
}
memset(tag_begin, 0, strlen(tag_begin));
@@ -2952,8 +3017,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
}
if (t == 5) {
- tag_begin[t] = 0;
- fprintf(stderr, "ERR: Begin tag name '%s' is too long, line '%ld'.\n", tag_begin, g_line_number);
+ cho_log(LOG_ERR, "Begin tag name is too long.");
return NULL;
}
tag_begin[t] = buf;
@@ -2975,7 +3039,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tag_end[t] = 0;
t = 0;
if (!cho_tag_close_last_unclosed(tag_end, tags, ta)) {
- DEBUG_MSG("cho_tag_close_last_unclosed failed.");
+ LOG_DEBUG("cho_tag_close_last_unclosed failed.");
return NULL;
}
memset(tag_end, 0, strlen(tag_end));
@@ -2983,8 +3047,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
}
if (t == 5) {
- tag_end[t] = 0;
- fprintf(stderr, "ERR: End tag name '%s' is too long, line '%ld'.\n", tag_end, g_line_number);
+ cho_log(LOG_ERR, "End tag name is too long.");
return NULL;
}
tag_end[t] = buf;
@@ -3005,7 +3068,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
} else {
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
- fprintf(stderr, "ERR: Attribute with name '%s' of tag '%s' has no value, line '%ld'.\n", tags[ta]->attrs[at]->name, tag_begin, g_line_number);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
return NULL;
}
}
@@ -3017,7 +3080,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
}
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
- fprintf(stderr, "ERR: Attribute with name '%s' of tag '%s' has no value, line '%ld'.\n", tags[ta]->attrs[at]->name, tag_begin, g_line_number);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
return NULL;
}
if (buf == '>') {
@@ -3026,7 +3089,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tags[ta]->attrs[at] = NULL;
tag_style = cho_style_parse(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
- DEBUG_MSG("cho_style_parse failed.");
+ LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
tags[ta]->style = tag_style;
@@ -3044,7 +3107,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
- fprintf(stderr, "ERR: Invalid prev_state '%s', line '%ld'.\n", state_enums[prev_state], g_line_number);
+ cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]);
return NULL;
}
at = 0;
@@ -3055,7 +3118,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tags[ta]->attrs[at]->name = realloc(tags[ta]->attrs[at]->name, (atn+1) * sizeof(char));
tags[ta]->attrs[at]->name[atn] = 0;
atn = 0;
- fprintf(stderr, "ERR: Attribute with name '%s' of tag '%s' has no value, line '%ld'.\n", tags[ta]->attrs[at]->name, tag_begin, g_line_number);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
return NULL;
}
}
@@ -3066,11 +3129,11 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
case STATE_MARKUP_ATTR_VALUE:
if (avs == AVS_NO) {
if (is_whitespace(buf)) {
- fprintf(stderr, "ERR: Whitespace character after equals sign is invalid, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Whitespace character after equals sign is invalid.");
return NULL;
}
if (buf == '>') {
- fprintf(stderr, "ERR: Attribute with name '%s' of tag '%s' has no value, line '%ld'.\n", tags[ta]->attrs[at]->name, tag_begin, g_line_number);
+ cho_log(LOG_ERR, "Attribute with name '%s' of tag '%s' has no value.", tags[ta]->attrs[at]->name, tag_begin);
return NULL;
}
if (buf == '\'') {
@@ -3086,7 +3149,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
}
if (buf == '\n') {
- fprintf(stderr, "ERR: Newline character inside an attribute value is invalid, line '%ld'.\n", g_line_number);
+ cho_log(LOG_ERR, "Newline character inside an attribute value is invalid.");
return NULL;
}
if (avs == AVS_UNQUOTED && buf == '>') {
@@ -3098,7 +3161,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
tags[ta]->attrs[at] = NULL;
tag_style = cho_style_parse(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1));
if (!tag_style) {
- DEBUG_MSG("cho_style_parse failed.");
+ LOG_DEBUG("cho_style_parse failed.");
return NULL;
}
tags[ta]->style = tag_style;
@@ -3116,7 +3179,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
- fprintf(stderr, "ERR: Invalid prev_state '%s', line '%ld'.\n", state_enums[prev_state], g_line_number);
+ cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]);
return NULL;
}
at = 0;
@@ -3153,12 +3216,12 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
}
prev_buf = buf;
} else if (ferror(fp) != 0) {
- DEBUG_MSG("fread failed.");
+ LOG_DEBUG("fread failed.");
return NULL;
}
- if (buf == '\n') {
+ /* if (buf == '\n') {
g_line_number++;
- }
+ } */
}
int e = 0;
while (e <= ta) {
@@ -3185,7 +3248,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li] = NULL;
}
if (!cho_style_reset_default()) {
- DEBUG_MSG("cho_style_reset_default failed.");
+ LOG_DEBUG("cho_style_reset_default failed.");
return NULL;
}
songs[so]->metadata = realloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
@@ -3209,7 +3272,9 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
}
}
if (!exist_title) {
- fprintf(stderr, "ERR: Song no. %d has no title.\n", so+1);
+ g_line_number = 0;
+ /* INFO: This cho_log() is not line specific. It's a workaround. */
+ cho_log(LOG_ERR, "Song has no title.");
return NULL;
}
exist_title = false;
diff --git a/chordpro.h b/chordpro.h
@@ -21,14 +21,6 @@ enum EnvironmentDirective {
};
-/* enum MetadataDirective {
- TITLE, SORTTITLE, SUBTITLE,
- ARTIST, COMPOSER, LYRICIST,
- COPYRIGHT, ALBUM, YEAR, KEY,
- TIME, TEMPO, DURATION, CAPO,
- META, ARRANGER
-}; */
-
enum FormattingDirective {
COMMENT, C, HIGHLIGHT, COMMENT_ITALIC, CI,
COMMENT_BOX, CB
@@ -38,10 +30,6 @@ enum ImageDirectve {
IMAGE
};
-/* enum PreabmleDirective {
- NEW_SONG, NS
-}; */
-
enum FontDirective {
CHORDFONT, CF, CHORDSIZE, CS, CHORDCOLOR,
CHORUSFONT, CHORUSSIZE, CHORUSCOLOR,
@@ -331,7 +319,7 @@ struct ChoSong {
struct ChoSection **sections;
};
-struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config);
+struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config);
int cho_song_count(struct ChoSong **songs);
void cho_songs_free(struct ChoSong **song);
diff --git a/config.c b/config.c
@@ -425,7 +425,7 @@ static bool config_load_style(struct Style *style, toml_table_t *table, const ch
toml_table_t *font_section = toml_table_table(table, "font");
if (font_section) {
if (!config_load_font(style->font, font_section, key_name)) {
- DEBUG_MSG("config_load_font failed.");
+ LOG_DEBUG("config_load_font failed.");
return false;
}
}
@@ -570,7 +570,7 @@ struct Config *config_load(const char *filepath)
char errbuf[200];
toml_table_t *table = toml_parse_file(fp, (char *)&errbuf, sizeof(errbuf));
if (!table) {
- DEBUG_MSG("toml_parse_file failed.");
+ LOG_DEBUG("toml_parse_file failed.");
fprintf(stderr, "ERR: Config file is not a valid toml file.\n");
fprintf(stderr, "%s\n", (char *)&errbuf);
return NULL;
@@ -595,7 +595,7 @@ struct Config *config_load(const char *filepath)
config_notes_free(config->output->notes);
config->output->notes = custom_notes;
} else {
- DEBUG_MSG("config_notes_load failed.");
+ LOG_DEBUG("config_notes_load failed.");
fprintf(stderr, "ERR: Couldn't load custom notes '%s' from [notes] section.\n", value.u.s);
return NULL;
}
@@ -619,7 +619,7 @@ struct Config *config_load(const char *filepath)
item = config_printable_item_get(config->output->printable_items, key_name);
if (item) {
if (!config_load_style(item->style, key, key_name)) {
- DEBUG_MSG("config_load_style failed.");
+ LOG_DEBUG("config_load_style failed.");
return NULL;
}
}
@@ -650,7 +650,7 @@ struct Config *config_load(const char *filepath)
config_notes_free(config->parser->notes);
config->parser->notes = custom_notes;
} else {
- DEBUG_MSG("config_notes_load failed.");
+ LOG_DEBUG("config_notes_load failed.");
fprintf(stderr, "ERR: Couldn't load custom notes '%s' from [notes] section.\n", value.u.s);
return NULL;
}
diff --git a/lorid.c b/lorid.c
@@ -20,6 +20,7 @@ int main(int argc, char *argv[])
{ 0, 0, 0, 0 }
};
int o, option_index;
+ const char *chordpro_filepath = NULL;
char *config_filepath = NULL;
char *output = NULL;
FILE *fp;
@@ -46,7 +47,7 @@ int main(int argc, char *argv[])
}
struct Config *config = config_load(config_filepath);
if (!config) {
- DEBUG_MSG("config_load failed.");
+ LOG_DEBUG("config_load failed.");
return 1;
}
free(config_filepath);
@@ -55,24 +56,25 @@ int main(int argc, char *argv[])
} else if (argc == optind+1) {
fp = fopen(argv[argc-1], "r");
if (!fp) {
- DEBUG_MSG("fopen failed.");
+ LOG_DEBUG("fopen failed.");
return 1;
}
+ chordpro_filepath = argv[argc-1];
} else {
- fprintf(stderr, "ERR: Provide only one file.\n");
+ util_log(LOG_ERR, "Provide only one file.");
return 1;
}
- struct ChoSong **songs = cho_songs_parse(fp, config);
+ struct ChoSong **songs = cho_songs_parse(fp, chordpro_filepath, config);
if (!songs) {
- DEBUG_MSG("cho_parse failed.");
+ LOG_DEBUG("cho_songs_parse failed.");
return 1;
}
char *pdf_filename = out_pdf_new(argc == optind+1 ? argv[argc-1] : NULL, output ? output : NULL, songs, config);
if (!pdf_filename) {
- DEBUG_MSG("out_pdf_new failed.");
+ LOG_DEBUG("out_pdf_new failed.");
return 1;
}
- fprintf(stderr, "INFO: Writing pdf to file: '%s'\n", pdf_filename);
+ util_log(LOG_INFO, "Writing pdf to file: '%s'.", pdf_filename);
free(pdf_filename);
free(output);
cho_songs_free(songs);
diff --git a/out_pdf.c b/out_pdf.c
@@ -181,7 +181,7 @@ static char *out_pdf_filename_create(struct ChoSong **songs, const char *cho_fil
} else {
pdf_filename = out_pdf_filename_generate_from_songs(songs);
if (!pdf_filename) {
- DEBUG_MSG("out_pdf_filename_generate_from_songs failed.");
+ LOG_DEBUG("out_pdf_filename_generate_from_songs failed.");
return NULL;
}
}
@@ -318,12 +318,12 @@ static bool out_pdf_font_set(pdfio_stream_t *stream, struct Font *font)
return true;
}
if (!pdfioContentSetTextFont(stream, name, font->size)) {
- DEBUG_MSG("pdfioContentSetTextFont failed.");
+ LOG_DEBUG("pdfioContentSetTextFont failed.");
return false;
}
pdfio_obj_t *font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return false;
}
strcpy(g_current_font_name, name);
@@ -371,7 +371,7 @@ static double text_width(struct TextLineItem *item)
char *name = out_pdf_fnt_name_create(item->style->font);
pdfio_obj_t *font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return -1.0;
}
free(name);
@@ -384,7 +384,7 @@ static enum Bool text_fits(const char *str, struct Style *style)
char *name = out_pdf_fnt_name_create(style->font);
pdfio_obj_t *font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return B_ERROR;
}
free(name);
@@ -423,7 +423,7 @@ static char *text_find_fitting(const char *str, struct Style *style)
tmp[i] = 0;
fits = text_fits((const char *)&tmp, style);
if (fits == B_ERROR) {
- DEBUG_MSG("text_fits failed.");
+ LOG_DEBUG("text_fits failed.");
return NULL;
}
start = i - 1;
@@ -445,7 +445,7 @@ static struct TextLine **text_split_by_whitespace(const char *str, struct Style
while (1) {
fits = text_fits(text, style);
if (fits == B_ERROR) {
- DEBUG_MSG("text_fits failed.");
+ LOG_DEBUG("text_fits failed.");
return NULL;
}
if (fits) {
@@ -461,7 +461,7 @@ static struct TextLine **text_split_by_whitespace(const char *str, struct Style
}
fitting = text_find_fitting(text, style);
if (!fitting) {
- DEBUG_MSG("text_find_fitting failed.");
+ LOG_DEBUG("text_find_fitting failed.");
return NULL;
}
line = text_line_create(fitting, style);
@@ -487,7 +487,7 @@ static enum Bool text_line_fits(struct TextLine *line)
}
width = text_width(line->items[i-1]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return B_ERROR;
}
if (line->items[i-1]->x + width > LINE_WIDTH) {
@@ -520,19 +520,19 @@ static bool out_pdf_draw_line(pdfio_stream_t *stream, struct TextLineItem *item,
break;
}
if (!pdfioContentPathMoveTo(stream, item->x, y)) {
- DEBUG_MSG("pdfioContentPathMoveTo failed.");
+ LOG_DEBUG("pdfioContentPathMoveTo failed.");
return false;
}
if (!pdfioContentPathLineTo(stream, item->x + width, y)) {
- DEBUG_MSG("pdfioContentPathLineTo failed.");
+ LOG_DEBUG("pdfioContentPathLineTo failed.");
return false;
}
if (!pdfioContentSetStrokeColorRGB(stream, red, green, blue)) {
- DEBUG_MSG("pdfioContentSetStrokeColorRGB failed.");
+ LOG_DEBUG("pdfioContentSetStrokeColorRGB failed.");
return false;
}
if (!pdfioContentStroke(stream)) {
- DEBUG_MSG("pdfioContentStroke failed.");
+ LOG_DEBUG("pdfioContentStroke failed.");
return false;
}
return true;
@@ -544,38 +544,38 @@ static bool out_pdf_text_show(pdfio_stream_t *stream, struct TextLineItem *item,
// TODO: Maybe store the width in TextLineItem
width = text_width(item);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return false;
}
if (!out_pdf_font_set(stream, item->style->font)) {
- DEBUG_MSG("out_pdf_font_set failed.");
+ LOG_DEBUG("out_pdf_font_set failed.");
return false;
}
red = item->style->foreground_color->red / 255.0;
green = item->style->foreground_color->green / 255.0;
blue = item->style->foreground_color->blue / 255.0;
if (!pdfioContentSetFillColorRGB(stream, red, green, blue)) {
- DEBUG_MSG("pdfioContentSetFillColorRGB failed.");
+ LOG_DEBUG("pdfioContentSetFillColorRGB failed.");
return false;
}
if (!pdfioContentTextBegin(stream)) {
- DEBUG_MSG("pdfioContentTextBegin failed.");
+ LOG_DEBUG("pdfioContentTextBegin failed.");
return false;
}
if (!pdfioContentTextMoveTo(stream, item->x, y)) {
- DEBUG_MSG("pdfioContentTextMoveTo failed.");
+ LOG_DEBUG("pdfioContentTextMoveTo failed.");
return false;
}
if (!pdfioContentSetTextRise(stream, item->style->rise)) {
- DEBUG_MSG("pdfioContentSetTextRise failed.");
+ LOG_DEBUG("pdfioContentSetTextRise failed.");
return false;
}
if (!pdfioContentTextShow(stream, true, item->text)) {
- DEBUG_MSG("pdfioContentTextShow failed.");
+ LOG_DEBUG("pdfioContentTextShow failed.");
return false;
}
if (!pdfioContentTextEnd(stream)) {
- DEBUG_MSG("pdfioContentTextEnd failed.");
+ LOG_DEBUG("pdfioContentTextEnd failed.");
return false;
}
if (item->style->underline_style == LS_SINGLE) {
@@ -598,15 +598,15 @@ static bool out_pdf_text_show(pdfio_stream_t *stream, struct TextLineItem *item,
green = item->style->boxed_color->green / 255.0;
blue = item->style->boxed_color->blue / 255.0;
if (!pdfioContentSetStrokeColorRGB(stream, red, green, blue)) {
- DEBUG_MSG("pdfioContentSetFillColorRGB failed.");
+ LOG_DEBUG("pdfioContentSetFillColorRGB failed.");
return false;
}
if (!pdfioContentPathRect(stream, item->x - 2.0, y - 2.0, width + 4.0, item->style->font->size * 0.8 + 4.0)) {
- DEBUG_MSG("pdfioContentPathRect failed.");
+ LOG_DEBUG("pdfioContentPathRect failed.");
return false;
}
if (!pdfioContentStroke(stream)) {
- DEBUG_MSG("pdfioContentStroke failed.");
+ LOG_DEBUG("pdfioContentStroke failed.");
return false;
}
}
@@ -644,7 +644,7 @@ static double line_width_until_chord(struct ChoLine *line, struct ChoLineItemAbo
name = out_pdf_fnt_name_create(line->lyrics[ly]->style->font);
font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return EMPTY;
}
if (ly == last_ly) {
@@ -678,7 +678,7 @@ static enum Bool out_pdf_text_above_is_enough_space(struct ChoLine *line, struct
name = out_pdf_fnt_name_create(prev_text_above->u.chord->style->font);
font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return B_ERROR;
}
free(name);
@@ -687,7 +687,7 @@ static enum Bool out_pdf_text_above_is_enough_space(struct ChoLine *line, struct
name = out_pdf_fnt_name_create(prev_text_above->u.annot->style->font);
font_obj = out_pdf_fnt_obj_get_by_name(name);
if (!font_obj) {
- DEBUG_MSG("out_pdf_fnt_obj_get_by_name failed.");
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
return B_ERROR;
}
free(name);
@@ -740,7 +740,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
if (!strcmp(songs[so]->metadata[m]->name, "title")) {
fits = text_fits(songs[so]->metadata[m]->value, songs[so]->metadata[m]->style);
if (fits == B_ERROR) {
- DEBUG_MSG("text_fits failed.");
+ LOG_DEBUG("text_fits failed.");
return NULL;
}
if (fits) {
@@ -752,7 +752,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[0]->style = cho_style_duplicate(songs[so]->metadata[m]->style);
width = text_width(text[t]->lines[tl]->items[0]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text[t]->lines[tl]->items[0]->x = MARGIN_HORIZONTAL + (LINE_WIDTH - width) / 2;
@@ -771,7 +771,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
for (int i = 0; text_lines[i]; i++) {
width = text_width(text_lines[i]->items[0]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text_lines[i]->items[0]->x = MARGIN_HORIZONTAL + (LINE_WIDTH - width) / 2;
@@ -787,13 +787,13 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
if (!strcmp(songs[so]->metadata[m]->name, "subtitle")) {
fits = text_fits(songs[so]->metadata[m]->value, songs[so]->metadata[m]->style);
if (fits == B_ERROR) {
- DEBUG_MSG("text_fits failed.");
+ LOG_DEBUG("text_fits failed.");
return NULL;
}
if (fits) {
printable_item = config_printable_item_get(config->output->printable_items, "subtitle");
if (!printable_item) {
- DEBUG_MSG("config_printable_item_get failed.");
+ LOG_DEBUG("config_printable_item_get failed.");
return NULL;
}
text[t]->lines = realloc(text[t]->lines, (tl+1) * sizeof(struct TextLine *));
@@ -804,7 +804,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[0]->style = cho_style_duplicate(printable_item->style);
width = text_width(text[t]->lines[tl]->items[0]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text[t]->lines[tl]->items[0]->x = MARGIN_HORIZONTAL + (LINE_WIDTH - width) / 2;
@@ -823,7 +823,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
for (int i = 0; text_lines[i]; i++) {
width = text_width(text_lines[i]->items[0]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text_lines[i]->items[0]->x = MARGIN_HORIZONTAL + (LINE_WIDTH - width) / 2;
@@ -845,7 +845,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
if (songs[so]->sections[se]->label) {
fits = text_fits(songs[so]->sections[se]->label->name, songs[so]->sections[se]->label->style);
if (fits == B_ERROR) {
- DEBUG_MSG("text_fits failed.");
+ LOG_DEBUG("text_fits failed.");
return NULL;
}
if (fits) {
@@ -871,7 +871,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
for (int i = 0; text_lines[i]; i++) {
width = text_width(text_lines[i]->items[0]);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
// text_lines[i]->items[0]->x = MARGIN_HORIZONTAL + (LINE_WIDTH - width) / 2;
@@ -904,7 +904,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli] = malloc(sizeof(struct TextLineItem));
double width_until = line_width_until_chord(lines[li], text_above[ch], NULL);
if (width_until == EMPTY) {
- DEBUG_MSG("line_width_until_chord failed.");
+ LOG_DEBUG("line_width_until_chord failed.");
return NULL;
}
if (tli == 0) {
@@ -925,7 +925,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
tmp.text = text_above[b]->u.annot->text;
width = text_width(&tmp);
if (width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text[t]->lines[tl]->items[tli]->x += width;
@@ -948,7 +948,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
}
enough_space = out_pdf_text_above_is_enough_space(songs[so]->sections[se]->lines[li], text_above[ch], text_above[ch+1], &space);
if (enough_space == B_ERROR) {
- DEBUG_MSG("out_pdf_text_above_is_enough_space failed.");
+ LOG_DEBUG("out_pdf_text_above_is_enough_space failed.");
return NULL;
}
if (!enough_space) {
@@ -968,7 +968,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli] = NULL;
fits = text_line_fits(text[t]->lines[tl]);
if (fits == B_ERROR) {
- DEBUG_MSG("text_line_fits failed.");
+ LOG_DEBUG("text_line_fits failed.");
return NULL;
}
if (!fits) {
@@ -1009,7 +1009,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
} else {
last_text_line_item_width = text_width(text[t]->lines[tl]->items[tli-1]);
if (last_text_line_item_width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text[t]->lines[tl]->items[tli]->x = text[t]->lines[tl]->items[tli-1]->x + last_text_line_item_width;
@@ -1030,7 +1030,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli]->style = cho_style_duplicate(lines[li]->lyrics[ly]->style);
last_text_line_item_width = text_width(text[t]->lines[tl]->items[tli-1]);
if (last_text_line_item_width == EMPTY) {
- DEBUG_MSG("text_width failed.");
+ LOG_DEBUG("text_width failed.");
return NULL;
}
text[t]->lines[tl]->items[tli]->x = text[t]->lines[tl]->items[tli-1]->x + last_text_line_item_width + sp->amount;
@@ -1048,7 +1048,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli] = NULL;
fits = text_line_fits(text[t]->lines[tl]);
if (fits == B_ERROR) {
- DEBUG_MSG("text_line_fits failed.");
+ LOG_DEBUG("text_line_fits failed.");
return NULL;
}
if (!fits) {
@@ -1119,24 +1119,24 @@ static pdfio_dict_t *annot_create(pdfio_file_t *pdf, const char *uri, pdfio_rect
{
pdfio_dict_t *annot = pdfioDictCreate(pdf);
if (!pdfioDictSetName(annot, "Subtype", "Link")) {
- DEBUG_MSG("pdfioDictSetName failed.");
+ LOG_DEBUG("pdfioDictSetName failed.");
return NULL;
}
if (!pdfioDictSetRect(annot, "Rect", rect)) {
- DEBUG_MSG("pdfioDictSetRect failed.");
+ LOG_DEBUG("pdfioDictSetRect failed.");
return NULL;
}
pdfio_dict_t *action = pdfioDictCreate(pdf);
if (!pdfioDictSetName(action, "S", "URI")) {
- DEBUG_MSG("pdfioDictSetName failed.");
+ LOG_DEBUG("pdfioDictSetName failed.");
return NULL;
}
if (!pdfioDictSetString(action, "URI", uri)) {
- DEBUG_MSG("pdfioDictSetString failed.");
+ LOG_DEBUG("pdfioDictSetString failed.");
return NULL;
}
if (!pdfioDictSetDict(annot, "A", action)) {
- DEBUG_MSG("pdfioDictSetDict failed.");
+ LOG_DEBUG("pdfioDictSetDict failed.");
return NULL;
}
return annot;
@@ -1152,7 +1152,7 @@ static bool annots_create(pdfio_file_t *pdf, pdfio_array_t *annots, struct Text
int t, tl, tli;
pdfio_array_t *page_annots = pdfioArrayCreate(pdf);
if (!page_annots) {
- DEBUG_MSG("pdfioArrayCreate failed.");
+ LOG_DEBUG("pdfioArrayCreate failed.");
return false;
}
for (t = 0; text[t]; t++) {
@@ -1168,11 +1168,11 @@ static bool annots_create(pdfio_file_t *pdf, pdfio_array_t *annots, struct Text
rect.y2 = y + item->style->font->size * 0.8;
annot = annot_create(pdf, item->style->href, &rect);
if (!annot) {
- DEBUG_MSG("annot_create failed.");
+ LOG_DEBUG("annot_create failed.");
return false;
}
if (!pdfioArrayAppendDict(page_annots, annot)) {
- DEBUG_MSG("pdfioArrayAppendDict failed.");
+ LOG_DEBUG("pdfioArrayAppendDict failed.");
return false;
}
}
@@ -1180,12 +1180,12 @@ static bool annots_create(pdfio_file_t *pdf, pdfio_array_t *annots, struct Text
}
if (text[t]->lines[tl]->btype == BT_PAGE) {
if (!pdfioArrayAppendArray(annots, page_annots)) {
- DEBUG_MSG("pdfioArrayAppendArray failed.");
+ LOG_DEBUG("pdfioArrayAppendArray failed.");
return false;
}
page_annots = pdfioArrayCreate(pdf);
if (!page_annots) {
- DEBUG_MSG("pdfioArrayCreate failed.");
+ LOG_DEBUG("pdfioArrayCreate failed.");
return false;
}
y = MEDIABOX_HEIGHT - MARGIN_TOP;
@@ -1195,7 +1195,7 @@ static bool annots_create(pdfio_file_t *pdf, pdfio_array_t *annots, struct Text
}
}
if (!pdfioArrayAppendArray(annots, page_annots)) {
- DEBUG_MSG("pdfioArrayAppendArray failed.");
+ LOG_DEBUG("pdfioArrayAppendArray failed.");
return false;
}
return true;
@@ -1225,27 +1225,27 @@ static pdfio_stream_t *out_pdf_page_create(pdfio_file_t *pdf, pdfio_array_t *ann
pdfio_array_t *color_array = pdfioArrayCreateColorFromStandard(pdf, 3, PDFIO_CS_ADOBE);
page_dict = pdfioDictCreate(pdf);
if (!pdfioPageDictAddColorSpace(page_dict, "rgbcolorspace", color_array)) {
- DEBUG_MSG("pdfioPageDictAddColorSpace failed.");
+ LOG_DEBUG("pdfioPageDictAddColorSpace failed.");
return false;
}
for (f = 0; g_fonts[f]; f++) {
if (!pdfioPageDictAddFont(page_dict, g_fonts[f]->name, g_fonts[f]->font)) {
- DEBUG_MSG("pdfioPageDictAddFont failed.");
+ LOG_DEBUG("pdfioPageDictAddFont failed.");
return false;
}
}
page_annots = pdfioArrayGetArray(annots, page_no);
if (!pdfioDictSetArray(page_dict, "Annots", page_annots)) {
- DEBUG_MSG("pdfioDictSetArray failed.");
+ LOG_DEBUG("pdfioDictSetArray failed.");
return false;
}
page_stream = pdfioFileCreatePage(pdf, page_dict);
if (!pdfioContentSetFillColorSpace(page_stream, "rgbcolorspace")) {
- DEBUG_MSG("pdfioContentSetFillColorSpace failed.");
+ LOG_DEBUG("pdfioContentSetFillColorSpace failed.");
return false;
}
if (!pdfioContentSetStrokeColorSpace(page_stream, "rgbcolorspace")) {
- DEBUG_MSG("pdfioContentSetStrokeColorSpace failed.");
+ LOG_DEBUG("pdfioContentSetStrokeColorSpace failed.");
return false;
}
return page_stream;
@@ -1256,14 +1256,14 @@ char *out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, s
memset(&g_current_font_name, 0, sizeof(g_current_font_name));
char *pdf_filename = out_pdf_filename_create(songs, cho_filepath, output_folder_or_file);
if (!pdf_filename) {
- DEBUG_MSG("out_pdf_filename_create failed.");
+ LOG_DEBUG("out_pdf_filename_create failed.");
return NULL;
}
pdfio_rect_t media_box_a4 = { 0.0, 0.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT };
pdfio_rect_t crop_box = { 36.0, 36.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT };
pdfio_file_t *pdf = pdfioFileCreate(pdf_filename, "2.0", &media_box_a4, &crop_box, NULL, NULL);
if (!out_pdf_set_title(pdf, songs)) {
- DEBUG_MSG("out_pdf_set_title failed.");
+ LOG_DEBUG("out_pdf_set_title failed.");
return NULL;
}
struct Font **needed_fonts = out_pdf_font_get_all(songs, config);
@@ -1297,12 +1297,12 @@ char *out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, s
cho_fonts_free(needed_fonts);
struct Text **text = text_create(songs, config);
if (!text) {
- DEBUG_MSG("text_create failed.");
+ LOG_DEBUG("text_create failed.");
return NULL;
}
pdfio_array_t *annots = pdfioArrayCreate(pdf);
if (!annots_create(pdf, annots, text)) {
- DEBUG_MSG("annotations_create failed.");
+ LOG_DEBUG("annotations_create failed.");
return NULL;
}
pdfio_stream_t *page_stream;
@@ -1319,7 +1319,7 @@ char *out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, s
}
if (text[t]->lines[tl]->btype == BT_PAGE) {
if (!pdfioStreamClose(page_stream)) {
- DEBUG_MSG("pdfioStreamClose failed.");
+ LOG_DEBUG("pdfioStreamClose failed.");
return NULL;
}
p++;
@@ -1331,11 +1331,11 @@ char *out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, s
}
}
if (!pdfioStreamClose(page_stream)) {
- DEBUG_MSG("pdfioStreamClose failed.");
+ LOG_DEBUG("pdfioStreamClose failed.");
return NULL;
}
if (!pdfioFileClose(pdf)) {
- DEBUG_MSG("pdfioFileClose failed.");
+ LOG_DEBUG("pdfioFileClose failed.");
return NULL;
}
text_free(text);
diff --git a/todo b/todo
@@ -22,4 +22,8 @@ render in two or more columns
find better name for PrintableItem, TextAbove
consider freeing memory in case of errors
-add line number to error, warning and info fprintf's.
+decide and then change consistent global variables prefix 'g_' or not
+change logging:
+ #define LOG_DEBUG
+ #define LOG_INFO
+ <filepath> <line_number> <log_level> <msg>
diff --git a/util.c b/util.c
@@ -1,10 +1,58 @@
+#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
+#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <sys/stat.h>
+#include <errno.h>
#include "util.h"
+void util_log(enum LogLevel level, const char *msg, ...)
+{
+#if COLOR == 1
+ const char *log_level = "";
+ const char *color = "";
+ switch (level) {
+ case LOG_INFO:
+ log_level = "INFO";
+ color = "37";
+ break;
+ case LOG_WARN:
+ log_level = "WARN";
+ color = "33";
+ break;
+ case LOG_ERR:
+ log_level = " ERR";
+ color = "31";
+ break;
+ }
+ fprintf(stderr, "\033[1m\033[%sm%s\033[0m: ", color, log_level);
+ va_list va;
+ va_start(va, msg);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+#else
+ const char *log_level = "";
+ switch (level) {
+ case LOG_INFO:
+ log_level = "INFO";
+ break;
+ case LOG_WARN:
+ log_level = "WARN";
+ break;
+ case LOG_ERR:
+ log_level = " ERR";
+ break;
+ }
+ fprintf(stderr, "%s: ", log_level);
+ va_list va;
+ va_start(va, msg);
+ vfprintf(stderr, msg, va);
+ fprintf(stderr, "\n");
+#endif
+}
+
bool str_starts_with(const char *str, const char *part)
{
unsigned int i;
@@ -93,6 +141,26 @@ char *str_remove_leading_whitespace(const char *str)
return strdup(&str[i]);
}
+short str_parse_as_percent(const char *str)
+{
+ if (strlen(str) > 4) {
+ return -1;
+ }
+ long l;
+ char *endptr;
+ l = strtol(str, &endptr, 10);
+ if (str == endptr) {
+ return -1;
+ }
+ if (errno == ERANGE) {
+ return -1;
+ }
+ if (l < 1 || l > 100) {
+ return -1;
+ }
+ return (short)l;
+}
+
enum FileType file_type(const char *path)
{
struct stat s;
diff --git a/util.h b/util.h
@@ -1,9 +1,15 @@
#ifdef DEBUG
-#define DEBUG_MSG(msg) fprintf(stderr, msg"\n")
+#define LOG_DEBUG(msg) fprintf(stderr, msg"\n")
#else
-#define DEBUG_MSG(msg)
+#define LOG_DEBUG(msg)
#endif
+enum LogLevel {
+ LOG_INFO,
+ LOG_WARN,
+ LOG_ERR
+};
+
enum FileType {
F_ERROR,
F_FOLDER,
@@ -11,10 +17,13 @@ enum FileType {
F_OTHER
};
+void util_log(enum LogLevel level, const char *msg, ...);
+
bool str_starts_with(const char *str, const char *part);
char *str_normalize(const char *str);
char *str_trim(const char *str);
char *str_remove_leading_whitespace(const char *str);
+short str_parse_as_percent(const char *str);
enum FileType file_type(const char *path);
char *file_extension_replace_or_add(const char *old, const char *extension);
@@ -22,3 +31,4 @@ char *file_extension_replace_or_add(const char *old, const char *extension);
char *filepath_add_ending_slash_if_missing(const char *path);
char *filepath_basename(const char *path);
char *filepath_dirname(const char *path);
+