From 16a45c31a9b5903461354a3c9e2c36ce913fe05e Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 12:35:55 +0000 Subject: [PATCH 01/42] Avoid exiting if the home directory isn't known. Just use / in this specific case which might already happen if the user's home directory is blank in the passwd(5) file. --- vitunes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vitunes.c b/vitunes.c index 7d1abbb..7f2a9f0 100644 --- a/vitunes.c +++ b/vitunes.c @@ -107,8 +107,9 @@ main(int argc, char *argv[]) /* get home dir */ if ((home = getenv("HOME")) == NULL || *home == '\0') { if ((pw = getpwuid(getuid())) == NULL) - errx(1, "Couldn't determine home directory. Can't find my config files."); - home = pw->pw_dir; + home = "/"; + else + home = pw->pw_dir; } /* build paths & other needed strings */ From 13792bcd5209843acf7a24aa94e2d48a8eb1b9f1 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 12:39:06 +0000 Subject: [PATCH 02/42] Don't destroy an uninitialised user interface. --- player.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/player.c b/player.c index 37bf637..3fa40f2 100644 --- a/player.c +++ b/player.c @@ -121,10 +121,8 @@ player_init(const char *backend) if (!found) errx(1, "media backend '%s' is unknown", backend); - if (player.dynamic) { - ui_destroy(); + if (player.dynamic) errx(1, "dynamically loaded backends not yet supported"); - } player.set_callback_playnext(callback_playnext); player.set_callback_notice(paint_message); From f0bbf50f01ff93f2b9a58735a9fb801aabf49ba3 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 19:34:44 +0000 Subject: [PATCH 03/42] Add functions to output a message to stderr. More to come. Namely, error context which changes throughout the program (ie output to either stderr or to the command/status window) and consolidating the debug code, as well. --- Makefile | 2 +- error.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error.h | 33 +++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 error.c create mode 100644 error.h diff --git a/Makefile b/Makefile index 27b1946..c6aa7b1 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ OBJS=commands.o compat.o ecmd.o \ ecmd_add.o ecmd_addurl.o ecmd_check.o \ ecmd_flush.o ecmd_help.o ecmd_init.o \ ecmd_rmfile.o ecmd_tag.o ecmd_update.o \ - keybindings.o medialib.o meta_info.o \ + error.o keybindings.o medialib.o meta_info.o \ mplayer.o paint.o player.o player_utils.o \ playlist.o socket.o str2argv.o \ uinterface.o vitunes.o \ diff --git a/error.c b/error.c new file mode 100644 index 0000000..c864ea1 --- /dev/null +++ b/error.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "error.h" + +/* + * Prints the provided error message to standard error and, if wanted, appends + * the errno message string. + */ +static void +error_print(bool errnoflag, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", progname); + vfprintf(stderr, fmt, ap); + + if (errnoflag) + fprintf(stderr, ": %s", strerror(errno)); + fputs("\n", stderr); +} + +/* + * Outputs a fatal message, appends the errno message string and terminates the + * process. + */ +void +fatal(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_print(true, fmt, ap); + va_end(ap); + exit(1); +} + +/* Outputs a fatal message and terminates the process. */ +void +fatalx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_print(false, fmt, ap); + va_end(ap); + exit(1); +} + +/* Outputs an informational message with the errno message string appended. */ +void +info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_print(true, fmt, ap); + va_end(ap); +} + +/* Outputs an informational message. */ +void +infox(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_print(false, fmt, ap); + va_end(ap); +} diff --git a/error.h b/error.h new file mode 100644 index 0000000..26db5e1 --- /dev/null +++ b/error.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ERROR_H +#define ERROR_H + +#include +#include +#include +#include +#include + +#include "vitunes.h" + +void fatal(const char *, ...); +void fatalx(const char *, ...); +void info(const char *, ...); +void infox(const char *, ...); + +#endif From beec982f5cc11d5c50ff64234756e93e4d5824ec Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 20:02:24 +0000 Subject: [PATCH 04/42] Use newly added functions. --- commands.c | 24 ++++++++++++------------ commands.h | 1 + ecmd.c | 2 +- ecmd_addurl.c | 9 +++++---- ecmd_check.c | 8 ++++---- ecmd_flush.c | 3 ++- ecmd_help.c | 5 +++-- ecmd_rmfile.c | 3 ++- ecmd_tag.c | 19 ++++++++++--------- keybindings.c | 40 ++++++++++++++++++++-------------------- keybindings.h | 1 + medialib.c | 46 +++++++++++++++++++++++----------------------- medialib.h | 1 + meta_info.c | 28 ++++++++++++++-------------- meta_info.h | 1 + paint.c | 4 ++-- paint.h | 1 + player.c | 8 ++++---- player.h | 1 + playlist.c | 50 +++++++++++++++++++++++++------------------------- playlist.h | 1 + str2argv.c | 12 ++++++------ str2argv.h | 1 + uinterface.c | 16 ++++++++-------- uinterface.h | 1 + vitunes.c | 42 +++++++++++++++++++++--------------------- vitunes.h | 1 + 27 files changed, 172 insertions(+), 157 deletions(-) diff --git a/commands.c b/commands.c index e310fca..c19b432 100644 --- a/commands.c +++ b/commands.c @@ -58,7 +58,7 @@ toggleset_init() { const int max_size = 52; /* since we only have registers a-z and A-Z */ if ((toggleset = calloc(max_size, sizeof(toggle_list*))) == NULL) - err(1, "%s: calloc(3) failed", __FUNCTION__); + fatal("%s: calloc(3) failed", __FUNCTION__); toggleset_size = 0; } @@ -83,14 +83,14 @@ toggle_list_add_command(toggle_list *t, char *cmd) /* resize array */ if (t->size == 0) { if ((t->commands = malloc(sizeof(char*))) == NULL) - err(1, "%s: malloc(3) failed", __FUNCTION__); + fatal("%s: malloc(3) failed", __FUNCTION__); idx = 0; t->size = 1; } else { int new_size = (t->size + 1) * sizeof(char*); if ((new_cmds = realloc(t->commands, new_size)) == NULL) - err(1, "%s: realloc(3) failed", __FUNCTION__); + fatal("%s: realloc(3) failed", __FUNCTION__); idx = t->size; t->commands = new_cmds; @@ -99,7 +99,7 @@ toggle_list_add_command(toggle_list *t, char *cmd) /* add command */ if ((t->commands[idx] = strdup(cmd)) == NULL) - err(1, "%s: strdup(3) failed", __FUNCTION__); + fatal("%s: strdup(3) failed", __FUNCTION__); } toggle_list* @@ -110,7 +110,7 @@ toggle_list_create(int registr, int argc, char *argv[]) int i, j; if ((t = malloc(sizeof(toggle_list))) == NULL) - err(1, "%s: malloc(3) failed", __FUNCTION__); + fatal("%s: malloc(3) failed", __FUNCTION__); t->commands = NULL; t->registr = registr; @@ -306,7 +306,7 @@ cmd_write(int argc, char *argv[]) /* build filename for playlist */ if (asprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, argv[1]) == -1) - err(1, "cmd_write: asprintf failed"); + fatal("cmd_write: asprintf failed"); /* check to see if playlist with that name already exists */ will_clobber = false; @@ -409,7 +409,7 @@ cmd_new(int argc, char *argv[]) name = argv[1]; if (asprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, name) == -1) - err(1, "cmd_new: asprintf failed"); + fatal("cmd_new: asprintf failed"); } /* create & setup playlist */ @@ -417,7 +417,7 @@ cmd_new(int argc, char *argv[]) p->needs_saving = true; p->filename = filename; if ((p->name = strdup(name)) == NULL) - err(1, "cmd_new: strdup(3) failed"); + fatal("cmd_new: strdup(3) failed"); /* add playlist to media library and update ui */ medialib_playlist_add(p); @@ -727,7 +727,7 @@ cmd_reload(int argc, char *argv[]) char *db_file = strdup(mdb.db_file); char *playlist_dir = strdup(mdb.playlist_dir); if (db_file == NULL || playlist_dir == NULL) - err(1, "cmd_reload: strdup(3) failed"); + fatal("cmd_reload: strdup(3) failed"); /* stop playback TODO investigate a nice way around this */ player_stop(); @@ -981,7 +981,7 @@ user_getstr(const char *prompt, char **response) /* allocate input space and clear */ if ((input = calloc(MAX_INPUT_SIZE, sizeof(char))) == NULL) - err(1, "user_getstr: calloc(3) failed for input string"); + fatal("user_getstr: calloc(3) failed for input string"); bzero(input, MAX_INPUT_SIZE); @@ -1039,7 +1039,7 @@ user_getstr(const char *prompt, char **response) /* see todo above - realloc input buffer here if position reaches max */ if (pos >= MAX_INPUT_SIZE) - errx(1, "user_getstr: shamefull limit reached"); + fatalx("user_getstr: shamefull limit reached"); } /* For lack of input, bail out */ @@ -1055,7 +1055,7 @@ user_getstr(const char *prompt, char **response) /* trim the fat */ if ((*response = calloc(strlen(input) + 1, sizeof(char))) == NULL) - err(1, "user_getstr: calloc(3) failed for result"); + fatal("user_getstr: calloc(3) failed for result"); snprintf(*response, strlen(input) + 1, "%s", input); diff --git a/commands.h b/commands.h index 521efe7..e520b03 100644 --- a/commands.h +++ b/commands.h @@ -25,6 +25,7 @@ #include "vitunes.h" #include "debug.h" #include "keybindings.h" +#include "error.h" /**************************************************************************** * Toggle-list handling stuff diff --git a/ecmd.c b/ecmd.c index eb0fbdb..a77c657 100644 --- a/ecmd.c +++ b/ecmd.c @@ -76,7 +76,7 @@ ecmd_exec(const char *ecmd, int argc, char **argv) } /* not found; bail out */ if (i == ecmdtab_size) { - warnx("Unknown e-command '%s'. See 'vitunes -e help' for list.", ecmd); + infox("Unknown e-command '%s'. See 'vitunes -e help' for list.", ecmd); return -1; } diff --git a/ecmd_addurl.c b/ecmd_addurl.c index bb58717..4cd0e32 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -20,6 +20,7 @@ #include #include "ecmd.h" +#include "error.h" #include "medialib.h" #include "meta_info.h" #include "playlist.h" @@ -38,14 +39,14 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) m = mi_new(); m->is_url = true; if ((m->filename = strdup(argv[0])) == NULL) - err(1, "%s: strdup failed (filename)", __FUNCTION__); + fatal("%s: strdup failed (filename)", __FUNCTION__); /* get fields from user */ for (field = 0; field < MI_NUM_CINFO; field++) { printf("%10.10s: ", MI_CINFO_NAMES[field]); if (fgets(input, sizeof(input), stdin) == NULL) { - warnx("Operation canceled. Database unchanged."); + infox("Operation canceled. Database unchanged."); mi_free(m); return; } @@ -54,7 +55,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) input[strlen(input) - 1] = '\0'; if ((m->cinfo[field] = strdup(input)) == NULL) - err(1, "%s: strdup failed (field)", __FUNCTION__); + fatal("%s: strdup failed (field)", __FUNCTION__); } /* load existing database and see if file/URL already exists */ @@ -76,7 +77,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) if (fgets(input, sizeof(input), stdin) == NULL || (strcasecmp(input, "yes\n") != 0 && strcasecmp(input, "y\n") != 0)) { - warnx("Operation Canceled. Database unchanged."); + infox("Operation Canceled. Database unchanged."); mi_free(m); medialib_destroy(); return; diff --git a/ecmd_check.c b/ecmd_check.c index dabfb49..3ee5281 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -39,7 +39,7 @@ ecmd_check_show_db(const char *path) if (show_database == false) return; if (realpath(path, realfile) == NULL) { - warn("realpath failed for %s: skipping", path); + info("realpath failed for %s: skipping", path); return; } @@ -55,7 +55,7 @@ ecmd_check_show_db(const char *path) } if (!found) - warnx("File '%s' does NOT exist in the database", path); + infox("File '%s' does NOT exist in the database", path); else { printf("\tThe meta-information in the DATABASE is:\n"); for (i = 0; i < MI_NUM_CINFO; i++) @@ -74,7 +74,7 @@ ecmd_check_show_raw(const char *path) if (show_raw == false) return; if ((mi = mi_extract(path)) == NULL) { - warnx("Failed to extract any meta-information from '%s'", path); + infox("Failed to extract any meta-information from '%s'", path); return; } @@ -92,7 +92,7 @@ ecmd_check_show_sanitized(const char *path) if (show_sanitized == false) return; if ((mi = mi_extract(path)) == NULL) { - warnx("Failed to extract any meta-information from '%s'", path); + infox("Failed to extract any meta-information from '%s'", path); return; } diff --git a/ecmd_flush.c b/ecmd_flush.c index 6eeb158..0d2da5d 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -20,6 +20,7 @@ #include #include "ecmd.h" +#include "error.h" #include "medialib.h" #include "vitunes.h" @@ -34,7 +35,7 @@ ecmd_flush_parse(int argc, char **argv) switch (ch) { case 't': if ((time_format = strdup(optarg)) == NULL) - err(1, "%s: strdup of time_format failed", argv[0]); + fatal("%s: strdup of time_format failed", argv[0]); break; case '?': case 'h': diff --git a/ecmd_help.c b/ecmd_help.c index ad85528..8886ff5 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -21,6 +21,7 @@ #include #include "ecmd.h" +#include "error.h" #include "vitunes.h" static void @@ -61,11 +62,11 @@ The list of available commands are:\n\n\ man_args[0] = "man"; if (asprintf(&man_args[1], "vitunes-%s", argv[0]) == -1) - err(1, "ecmd_help: asprintf failed"); + fatal("ecmd_help: asprintf failed"); man_args[2] = NULL; execvp("man", man_args); - err(1, "ecmd_help: execvp failed"); + fatal("ecmd_help: execvp failed"); } const struct ecmd ecmd_help = { diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index 39af3cf..4795d65 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -21,6 +21,7 @@ #include #include "ecmd.h" +#include "error.h" #include "medialib.h" #include "playlist.h" #include "vitunes.h" @@ -77,7 +78,7 @@ ecmd_rmfile_exec(UNUSED int argc, char **argv) printf("Are you sure you want to delete '%s'? [y/n] ", argv[0]); if (fgets(input, sizeof(input), stdin) == NULL || (strcasecmp(input, "yes\n") != 0 && strcasecmp(input, "y\n") != 0)) - errx(1, "Operation canceled. Database unchanged."); + fatalx("Operation canceled. Database unchanged."); } playlist_files_remove(mdb.library, found_idx, 1, false); diff --git a/ecmd_tag.c b/ecmd_tag.c index d17c7cd..16ec4c5 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -22,6 +22,7 @@ #include #include "ecmd.h" +#include "error.h" #include "meta_info.h" static char *artist; @@ -43,37 +44,37 @@ ecmd_tag_parse(int argc, char **argv) case 'A': free(album); if ((album = strdup(optarg)) == NULL) - err(1, "%s: strdup ALBUM failed", argv[0]); + fatal("%s: strdup ALBUM failed", argv[0]); break; case 'T': track = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) - errx(1, "invalid track '%s': %s", optarg, errstr); + fatalx("invalid track '%s': %s", optarg, errstr); break; case 'a': free(artist); if ((artist = strdup(optarg)) == NULL) - err(1, "%s: strdup ARTIST failed", argv[0]); + fatal("%s: strdup ARTIST failed", argv[0]); break; case 'c': free(comment); if ((comment = strdup(optarg)) == NULL) - err(1, "%s: strdup COMMENT failed", argv[0]); + fatal("%s: strdup COMMENT failed", argv[0]); break; case 'g': free(genre); if ((genre = strdup(optarg)) == NULL) - err(1, "%s: strdup GENRE failed", argv[0]); + fatal("%s: strdup GENRE failed", argv[0]); break; case 't': free(title); if ((title = strdup(optarg)) == NULL) - err(1, "%s: strdup TITLE failed", argv[0]); + fatal("%s: strdup TITLE failed", argv[0]); break; case 'y': year = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) - errx(1, "invalid year '%s': %s", optarg, errstr); + fatalx("invalid year '%s': %s", optarg, errstr); break; case 'h': case '?': @@ -119,8 +120,8 @@ ecmd_tag_exec(int argc, char **argv) /* extract taglib stuff */ if ((tag_file = taglib_file_new(argv[i])) == NULL) { - warnx("TagLib: failed to open file '%s': skipping.", argv[i]); - warnx(" => Causes: format not supported by TagLib or format doesn't support tags"); + infox("TagLib: failed to open file '%s': skipping.", argv[i]); + infox(" => Causes: format not supported by TagLib or format doesn't support tags"); continue; } diff --git a/keybindings.c b/keybindings.c index 242e868..c24cdfb 100644 --- a/keybindings.c +++ b/keybindings.c @@ -261,7 +261,7 @@ kb_increase_capacity() KeyBindingsCapacity += KEYBINDINGS_CHUNK_SIZE; nbytes = KeyBindingsCapacity * sizeof(KeyBinding); if ((new_buffer = realloc(KeyBindings, nbytes)) == NULL) - err(1, "%s: failed to realloc(3) keybindings", __FUNCTION__); + fatal("%s: failed to realloc(3) keybindings", __FUNCTION__); KeyBindings = new_buffer; } @@ -487,7 +487,7 @@ kba_scroll_row(KbaArgs a) ui.active->crow -= n; break; default: - errx(1, "%s: invalid direction", __FUNCTION__); + fatalx("%s: invalid direction", __FUNCTION__); } /* handle off-the-edge cases */ @@ -551,7 +551,7 @@ kba_scroll_page(KbaArgs a) maintain_row_idx = false; break; default: - errx(1, "scroll_page: invalid amount"); + fatalx("scroll_page: invalid amount"); } swindow_scroll(ui.active, a.direction, diff); @@ -647,11 +647,11 @@ kba_scroll_col(KbaArgs a) ui.active->hoffset = maxhoff; break; default: - errx(1, "scroll_col: invalid direction"); + fatalx("scroll_col: invalid direction"); } break; default: - errx(1, "scroll_col: invalid amount"); + fatalx("scroll_col: invalid amount"); } /* redraw */ @@ -690,7 +690,7 @@ kba_jumpto_screen(KbaArgs a) ui.active->crow = max_row - n + 1; break; default: - errx(1, "jumpto_page: invalid location"); + fatalx("jumpto_page: invalid location"); } /* sanitize current row */ @@ -753,7 +753,7 @@ kba_jumpto_file(KbaArgs a) break; default: - errx(1, "jumpto_file: NUMBER type with no num!"); + fatalx("jumpto_file: NUMBER type with no num!"); } break; @@ -767,7 +767,7 @@ kba_jumpto_file(KbaArgs a) break; default: - errx(1, "jumpto_file: invalid scale"); + fatalx("jumpto_file: invalid scale"); } /* jump */ @@ -821,7 +821,7 @@ kba_search(KbaArgs a) prompt = "?"; break; default: - errx(1, "search: invalid direction"); + fatalx("search: invalid direction"); } /* get search phrase from user */ @@ -878,7 +878,7 @@ kba_search_find(KbaArgs a) break; default: - errx(1, "search_find: invalid direction"); + fatalx("search_find: invalid direction"); } /* start looking from current row */ @@ -1029,7 +1029,7 @@ kba_cut(KbaArgs a UNUSED) } if (asprintf(&warning, "Are you sure you want to delete '%s'?", p->name) == -1) - err(1, "cut: asprintf failed"); + fatal("cut: asprintf failed"); /* make sure user wants this */ if (user_get_yesno(warning, &response) != 0) { @@ -1213,7 +1213,7 @@ kba_paste(KbaArgs a) start = p->nfiles; break; default: - errx(1, "paste: invalid placement [if]"); + fatalx("paste: invalid placement [if]"); } } else { @@ -1227,7 +1227,7 @@ kba_paste(KbaArgs a) if (start > p->nfiles) start = p->nfiles; break; default: - errx(1, "paste: invalid placement [else]"); + fatalx("paste: invalid placement [else]"); } } @@ -1491,7 +1491,7 @@ kba_volume(KbaArgs a) pcnt *= -1; break; default: - errx(1, "kba_volume: invalid direction"); + fatalx("kba_volume: invalid direction"); } player_volume_step(pcnt); @@ -1511,7 +1511,7 @@ kba_seek(KbaArgs a) secs = a.num * 60; break; default: - errx(1, "seek_playback: invalid scale"); + fatalx("seek_playback: invalid scale"); } /* adjust for direction */ @@ -1523,7 +1523,7 @@ kba_seek(KbaArgs a) secs *= -1; break; default: - errx(1, "seek_playback: invalid direction"); + fatalx("seek_playback: invalid direction"); } /* is there a multiplier? */ @@ -1588,7 +1588,7 @@ kba_toggle(KbaArgs a) } break; default: - errx(1, "%s: invalid direction", __FUNCTION__); + fatalx("%s: invalid direction", __FUNCTION__); } /* execute */ @@ -1659,7 +1659,7 @@ ybuffer_init() { _yank_buffer.files = calloc(YANK_BUFFER_CHUNK_SIZE, sizeof(meta_info*)); if (_yank_buffer.files == NULL) - err(1, "ybuffer_init: calloc(3) failed"); + fatal("ybuffer_init: calloc(3) failed"); _yank_buffer.capacity = YANK_BUFFER_CHUNK_SIZE; _yank_buffer.nfiles = 0; @@ -1689,7 +1689,7 @@ ybuffer_add(meta_info *f) _yank_buffer.capacity += YANK_BUFFER_CHUNK_SIZE; int new_capacity = _yank_buffer.capacity * sizeof(meta_info*); if ((new_buff = realloc(_yank_buffer.files, new_capacity)) == NULL) - err(1, "ybuffer_add: realloc(3) failed [%i]", new_capacity); + fatal("ybuffer_add: realloc(3) failed [%i]", new_capacity); _yank_buffer.files = new_buff; } @@ -1734,7 +1734,7 @@ match_command_name(const char *input, const char *cmd) /* check for '!' weirdness and abbreviations */ if ((icopy = strdup(input)) == NULL) - err(1, "match_command_name: strdup(3) failed"); + fatal("match_command_name: strdup(3) failed"); /* remove '!' from input, if present */ if (strstr(icopy, "!") != NULL) diff --git a/keybindings.h b/keybindings.h index 4ad5ccb..2132a9b 100644 --- a/keybindings.h +++ b/keybindings.h @@ -21,6 +21,7 @@ #include "debug.h" #include "enums.h" +#include "error.h" #include "paint.h" #include "vitunes.h" diff --git a/medialib.c b/medialib.c index 35cfd2e..c8271f1 100644 --- a/medialib.c +++ b/medialib.c @@ -35,7 +35,7 @@ medialib_load(const char *db_file, const char *playlist_dir) mdb.db_file = strdup(db_file); mdb.playlist_dir = strdup(playlist_dir); if (mdb.db_file == NULL || mdb.playlist_dir == NULL) - err(1, "failed to strdup db file and playlist dir in medialib_init"); + fatal("failed to strdup db file and playlist dir in medialib_init"); /* setup pseudo-playlists */ mdb.library = playlist_new(); @@ -47,7 +47,7 @@ medialib_load(const char *db_file, const char *playlist_dir) mdb.filter_results->name = strdup("--FILTER--"); if (mdb.library->name == NULL || mdb.filter_results->name == NULL) - err(1, "failed to strdup pseudo-names in medialib_load"); + fatal("failed to strdup pseudo-names in medialib_load"); /* load the actual database */ medialib_db_load(db_file); @@ -57,7 +57,7 @@ medialib_load(const char *db_file, const char *playlist_dir) mdb.playlists_capacity = 2; mdb.playlists = calloc(2, sizeof(playlist*)); if (mdb.playlists == NULL) - err(1, "medialib_load: failed to allocate initial playlists"); + fatal("medialib_load: failed to allocate initial playlists"); /* add library/filter pseudo-playlists */ medialib_playlist_add(mdb.library); @@ -113,7 +113,7 @@ medialib_playlist_add(playlist *p) mdb.playlists_capacity += MEDIALIB_PLAYLISTS_CHUNK_SIZE; int size = mdb.playlists_capacity * sizeof(playlist*); if ((new_playlists = realloc(mdb.playlists, size)) == NULL) - err(1, "medialib_playlist_add: realloc failed"); + fatal("medialib_playlist_add: realloc failed"); mdb.playlists = new_playlists; } @@ -131,7 +131,7 @@ medialib_playlist_remove(int pindex) int i; if (pindex < 0 || pindex >= mdb.nplaylists) - errx(1, "medialib_playlist_remove: index %d out of range", pindex); + fatalx("medialib_playlist_remove: index %d out of range", pindex); playlist_delete(mdb.playlists[pindex]); @@ -155,20 +155,20 @@ medialib_setup_files(const char *vitunes_dir, const char *db_file, /* create vitunes directory */ if (mkdir(vitunes_dir, S_IRWXU) == -1) { if (errno == EEXIST) - warnx("vitunes directory '%s' already exists (OK)", vitunes_dir); + infox("vitunes directory '%s' already exists (OK)", vitunes_dir); else - err(1, "unable to create vitunes directory '%s'", vitunes_dir); + fatal("unable to create vitunes directory '%s'", vitunes_dir); } else - warnx("vitunes directory '%s' created", vitunes_dir); + infox("vitunes directory '%s' created", vitunes_dir); /* create playlists directory */ if (mkdir(playlist_dir, S_IRWXU) == -1) { if (errno == EEXIST) - warnx("playlists directory '%s' already exists (OK)", playlist_dir); + infox("playlists directory '%s' already exists (OK)", playlist_dir); else - err(1, "unable to create playlists directory '%s'", playlist_dir); + fatal("unable to create playlists directory '%s'", playlist_dir); } else - warnx("playlists directory '%s' created", playlist_dir); + infox("playlists directory '%s' created", playlist_dir); /* create database file */ if (stat(db_file, &sb) < 0) { @@ -179,18 +179,18 @@ medialib_setup_files(const char *vitunes_dir, const char *db_file, /* open for writing */ if ((f = fopen(db_file, "w")) == NULL) - err(1, "failed to create database file '%s'", db_file); + fatal("failed to create database file '%s'", db_file); /* save header & version */ fwrite("vitunes", strlen("vitunes"), 1, f); fwrite(version, sizeof(version), 1, f); - warnx("empty database at '%s' created", db_file); + infox("empty database at '%s' created", db_file); fclose(f); } else - err(1, "database file '%s' exists, but cannot access it", db_file); + fatal("database file '%s' exists, but cannot access it", db_file); } else - warnx("database file '%s' already exists (OK)", db_file); + infox("database file '%s' already exists (OK)", db_file); } /* used to sort media db by filenames. */ @@ -214,12 +214,12 @@ medialib_db_load(const char *db_file) int version[3]; if ((fin = fopen(db_file, "r")) == NULL) - err(1, "Failed to open database file '%s'", db_file); + fatal("Failed to open database file '%s'", db_file); /* read and check header & version */ fread(header, strlen("vitunes"), 1, fin); if (strncmp(header, "vitunes", strlen("vitunes")) != 0) - errx(1, "Database file '%s' NOT a vitunes database", db_file); + fatalx("Database file '%s' NOT a vitunes database", db_file); fread(version, sizeof(version), 1, fin); if (version[0] != DB_VERSION_MAJOR || version[1] != DB_VERSION_MINOR @@ -244,7 +244,7 @@ medialib_db_load(const char *db_file) if (feof(fin)) mi_free(mi); else if (ferror(fin)) - err(1, "Error loading database file '%s'", db_file); + fatal("Error loading database file '%s'", db_file); else playlist_files_append(mdb.library, &mi, 1, false); } @@ -264,7 +264,7 @@ medialib_db_save(const char *db_file) int i; if ((fout = fopen(db_file, "w")) == NULL) - err(1, "medialib_db_save: failed to open database file '%s'", db_file); + fatal("medialib_db_save: failed to open database file '%s'", db_file); /* save header & version */ fwrite("vitunes", strlen("vitunes"), 1, fout); @@ -274,7 +274,7 @@ medialib_db_save(const char *db_file) for (i = 0; i < mdb.library->nfiles; i++) { mi_fwrite(mdb.library->files[i], fout); if (ferror(fout)) - err(1, "medialib_db_save: error saving database"); + fatal("medialib_db_save: error saving database"); } fclose(fout); @@ -449,7 +449,7 @@ medialib_db_scan_dirs(char *dirlist[]) fts = fts_open(dirlist, FTS_LOGICAL | FTS_NOCHDIR, NULL); if (fts == NULL) - err(1, "medialib_db_scan_dirs: fts_open failed"); + fatal("medialib_db_scan_dirs: fts_open failed"); while ((ftsent = fts_read(fts)) != NULL) { @@ -476,7 +476,7 @@ medialib_db_scan_dirs(char *dirlist[]) /* get the full name for the file */ if (realpath(ftsent->fts_accpath, fullname) == NULL) { - err(1, "medialib_db_scan_dirs: realpath failed for '%s'", + fatal("medialib_db_scan_dirs: realpath failed for '%s'", ftsent->fts_accpath); } @@ -536,7 +536,7 @@ medialib_db_scan_dirs(char *dirlist[]) } if (fts_close(fts) == -1) - err(1, "medialib_db_scan_dirs: failed to close file heirarchy"); + fatal("medialib_db_scan_dirs: failed to close file heirarchy"); /* save to file */ medialib_db_save(mdb.db_file); diff --git a/medialib.h b/medialib.h index 5f6e3af..7b6b8ab 100644 --- a/medialib.h +++ b/medialib.h @@ -37,6 +37,7 @@ #include #include "debug.h" +#include "error.h" #include "meta_info.h" #include "playlist.h" diff --git a/meta_info.c b/meta_info.c index b2c81d2..cc430ef 100644 --- a/meta_info.c +++ b/meta_info.c @@ -39,7 +39,7 @@ mi_new(void) int i; if ((mi = malloc(sizeof(meta_info))) == NULL) - err(1, "mi_new: meta_info malloc failed"); + fatal("mi_new: meta_info malloc failed"); mi->filename = NULL; mi->length = 0; @@ -112,14 +112,14 @@ mi_fread(meta_info *mi, FILE *fin) /* allocate all needed space in the meta_info struct, and zero */ if ((mi->filename = calloc(lengths[0] + 1, sizeof(char))) == NULL) - err(1, "mi_fread: calloc filename failed"); + fatal("mi_fread: calloc filename failed"); bzero(mi->filename, sizeof(char) * (lengths[0] + 1)); for (i = 0; i < MI_NUM_CINFO; i++) { if (lengths[i+1] > 0) { if ((mi->cinfo[i] = calloc(lengths[i+1] + 1, sizeof(char))) == NULL) - err(1, "mi_fread: failed to calloc cinfo"); + fatal("mi_fread: failed to calloc cinfo"); bzero(mi->cinfo[i], sizeof(char) * (lengths[i+1] + 1)); } @@ -181,10 +181,10 @@ mi_extract(const char *filename) /* store full filename in meta_info struct */ bzero(fullname, sizeof(fullname)); if (realpath(filename, fullname) == NULL) - err(1, "mi_extract: realpath failed to resolve '%s'", filename); + fatal("mi_extract: realpath failed to resolve '%s'", filename); if ((mi->filename = strdup(fullname)) == NULL) - errx(1, "mi_extract: strdup failed for '%s'", fullname); + fatalx("mi_extract: strdup failed for '%s'", fullname); /* start extracting fields using TagLib... */ @@ -221,25 +221,25 @@ mi_extract(const char *filename) || mi->cinfo[MI_CINFO_TITLE] == NULL || mi->cinfo[MI_CINFO_GENRE] == NULL || mi->cinfo[MI_CINFO_COMMENT] == NULL) - err(1, "mi_extract: strdup for CINFO failed"); + fatal("mi_extract: strdup for CINFO failed"); /* track number */ if (taglib_tag_track(tag) > 0) { if (asprintf(&(mi->cinfo[MI_CINFO_TRACK]), "%3i", taglib_tag_track(tag)) == -1) - err(1, "mi_extract: asprintf failed for CINFO_TRACK"); + fatal("mi_extract: asprintf failed for CINFO_TRACK"); } /* year */ if (taglib_tag_year(tag) > 0) { if (asprintf(&(mi->cinfo[MI_CINFO_YEAR]), "%i", taglib_tag_year(tag)) == -1) - err(1, "mi_extract: asprintf failed for CINFO_YEAR"); + fatal("mi_extract: asprintf failed for CINFO_YEAR"); } /* playlength in seconds (will be 0 if unavailable) */ mi->length = taglib_audioproperties_length(properties); if (mi->length > 0) { if ((mi->cinfo[MI_CINFO_LENGTH] = strdup(time2str(mi->length))) == NULL) - err(1, "mi_extract: strdup failed for CINO_LENGTH"); + fatal("mi_extract: strdup failed for CINO_LENGTH"); } /* record the time we extracted this info */ @@ -336,7 +336,7 @@ void mi_query_add_token(const char *token) { if (_mi_query.ntokens == MI_MAX_QUERY_TOKENS) - errx(1, "mi_query_add_token: reached shamefull limit"); + fatalx("mi_query_add_token: reached shamefull limit"); /* match or no? */ if (token[0] == '!') { @@ -347,7 +347,7 @@ mi_query_add_token(const char *token) /* copy token */ if ((_mi_query.tokens[_mi_query.ntokens++] = strdup(token)) == NULL) - err(1, "mi_query_add_token: strdup failed"); + fatal("mi_query_add_token: strdup failed"); } void @@ -357,7 +357,7 @@ mi_query_setraw(const char *query) free(_mi_query.raw); if ((_mi_query.raw = strdup(query)) == NULL) - err(1, "mi_query_setraw: query strdup failed"); + fatal("mi_query_setraw: query strdup failed"); } const char * @@ -492,7 +492,7 @@ mi_sort_set(const char *s, const char **errmsg) *errmsg = NULL; if ((line = strdup(s)) == NULL) - err(1, "mi_sort_set: sort strdup failed"); + fatal("mi_sort_set: sort strdup failed"); idx = 0; copy = line; @@ -700,7 +700,7 @@ mi_display_set(const char *display, const char **errmsg) new_display.nfields = 0; if ((s = strdup(display)) == NULL) - err(1, "mi_display_set: display strdup failed"); + fatal("mi_display_set: display strdup failed"); copy = s; idx = 0; diff --git a/meta_info.h b/meta_info.h index 19c04d7..4586ab5 100644 --- a/meta_info.h +++ b/meta_info.h @@ -36,6 +36,7 @@ #include "debug.h" #include "enums.h" +#include "error.h" /* the character-info fields. used for all meta-info that's shown */ #define MI_NUM_CINFO 8 diff --git a/paint.c b/paint.c index e0b4a8f..6bebdbf 100644 --- a/paint.c +++ b/paint.c @@ -67,7 +67,7 @@ num2fmt(int n, Direction d) if (n <= 0) { endwin(); - errx(1, "num2sfmt: invalid number %d provided", n); + fatalx("num2sfmt: invalid number %d provided", n); } if (d == LEFT) @@ -688,7 +688,7 @@ paint_str2color(const char *str) int number; if ((color = strdup(str)) == NULL) - err(1, "%s: strdup of '%s' failed.", __FUNCTION__, str); + fatal("%s: strdup of '%s' failed.", __FUNCTION__, str); if ((numberstr = strtok(color, "color")) == NULL) { free(color); diff --git a/paint.h b/paint.h index b8c8643..489297d 100644 --- a/paint.h +++ b/paint.h @@ -27,6 +27,7 @@ #include #include "enums.h" +#include "error.h" #include "meta_info.h" #include "player.h" #include "playlist.h" diff --git a/player.c b/player.c index 3fa40f2..e641525 100644 --- a/player.c +++ b/player.c @@ -119,10 +119,10 @@ player_init(const char *backend) } if (!found) - errx(1, "media backend '%s' is unknown", backend); + fatalx("media backend '%s' is unknown", backend); if (player.dynamic) - errx(1, "dynamically loaded backends not yet supported"); + fatalx("dynamically loaded backends not yet supported"); player.set_callback_playnext(callback_playnext); player.set_callback_notice(paint_message); @@ -148,10 +148,10 @@ void player_play() { if (player_info.queue == NULL) - errx(1, "player_play: bad queue/qidx"); + fatalx("player_play: bad queue/qidx"); if (player_info.qidx < 0 || player_info.qidx > player_info.queue->nfiles) - errx(1, "player_play: qidx %i out-of-range", player_info.qidx); + fatalx("player_play: qidx %i out-of-range", player_info.qidx); player.play(player_info.queue->files[player_info.qidx]->filename); diff --git a/player.h b/player.h index 029fb43..6c490b0 100644 --- a/player.h +++ b/player.h @@ -24,6 +24,7 @@ #include "playlist.h" #include "paint.h" #include "debug.h" +#include "error.h" /* "static" backends (those that aren't dynamically loaded) */ #include "players/mplayer.h" diff --git a/playlist.c b/playlist.c index ceac2fc..7b5e6c8 100644 --- a/playlist.c +++ b/playlist.c @@ -27,7 +27,7 @@ playlist_increase_capacity(playlist *p) p->capacity += PLAYLIST_CHUNK_SIZE; nbytes = p->capacity * sizeof(meta_info*); if ((new_files = realloc(p->files, nbytes)) == NULL) - err(1, "%s: failed to realloc(3) files", __FUNCTION__); + fatal("%s: failed to realloc(3) files", __FUNCTION__); p->files = new_files; } @@ -42,10 +42,10 @@ playlist_new(void) playlist *p; if ((p = malloc(sizeof(playlist))) == NULL) - err(1, "playlist_new: failed to allocate playlist"); + fatal("playlist_new: failed to allocate playlist"); if ((p->files = calloc(PLAYLIST_CHUNK_SIZE, sizeof(meta_info*))) == NULL) - err(1, "playlist_new: failed to allocate files"); + fatal("playlist_new: failed to allocate files"); p->capacity = PLAYLIST_CHUNK_SIZE; p->filename = NULL; @@ -87,17 +87,17 @@ playlist_dup(const playlist *original, const char *filename, if (name != NULL) { if ((newplist->name = strdup(name)) == NULL) - err(1, "playlist_dup: strdup name failed"); + fatal("playlist_dup: strdup name failed"); } if (filename != NULL) { if ((newplist->filename = strdup(filename)) == NULL) - err(1, "playlist_dup: strdup filename failed"); + fatal("playlist_dup: strdup filename failed"); } /* copy all of the files */ newplist->files = calloc(original->nfiles, sizeof(meta_info*)); if (newplist->files == NULL) - err(1, "playlist_dup: failed to allocate files"); + fatal("playlist_dup: failed to allocate files"); for (i = 0; i < original->nfiles; i++) newplist->files[i] = original->files[i]; @@ -115,7 +115,7 @@ playlist_files_add(playlist *p, meta_info **f, int start, int size, bool record) int i; if (start < 0 || start > p->nfiles) - errx(1, "playlist_file_add: index %d out of range", start); + fatalx("playlist_file_add: index %d out of range", start); while (p->capacity <= p->nfiles + size) playlist_increase_capacity(p); @@ -154,7 +154,7 @@ playlist_files_remove(playlist *p, int start, int size, bool record) int i; if (start < 0 || start >= p->nfiles) - errx(1, "playlist_remove_file: index %d out of range", start); + fatalx("playlist_remove_file: index %d out of range", start); if (record) { changes = changeset_create(CHANGE_REMOVE, size, &(p->files[start]), start); @@ -174,7 +174,7 @@ void playlist_file_replace(playlist *p, int index, meta_info *newEntry) { if (index < 0 || index >= p->nfiles) - errx(1, "playlist_file_replace: index %d out of range", index); + fatalx("playlist_file_replace: index %d out of range", index); p->files[index] = newEntry; } @@ -209,14 +209,14 @@ playlist_load(const char *filename, meta_info **db, int ndb) /* open file */ if ((fin = fopen(filename, "r")) == NULL) - err(1, "playlist_load: failed to open playlist '%s'", filename); + fatal("playlist_load: failed to open playlist '%s'", filename); /* create playlist and setup */ playlist *p = playlist_new(); p->filename = strdup(filename); p->name = strdup(basename(p->filename)); if (p->filename == NULL || p->name == NULL) - err(1, "playlist_load: failed to allocate info for playlist '%s'", filename); + fatal("playlist_load: failed to allocate info for playlist '%s'", filename); /* hack to remove '.playlist' from name */ period = strrchr(p->name, '.'); @@ -238,11 +238,11 @@ playlist_load(const char *filename, meta_info **db, int ndb) mi = mi_new(); mi->filename = strdup(entry); if (mi->filename == NULL) - err(1, "playlist_load: failed to strdup filename"); + fatal("playlist_load: failed to strdup filename"); /* add new record to the db and link it to the playlist */ playlist_files_append(p, &mi, 1, false); - warnx("playlist \"%s\", file \"%s\" is NOT in media database (added for now)", + infox("playlist \"%s\", file \"%s\" is NOT in media database (added for now)", p->name, entry); } } @@ -262,12 +262,12 @@ playlist_save(const playlist *p) int i; if ((fout = fopen(p->filename, "w")) == NULL) - err(1, "playlist_save: failed to open playlist \"%s\"", p->filename); + fatal("playlist_save: failed to open playlist \"%s\"", p->filename); /* write each song to file */ for (i = 0; i < p->nfiles; i++) { if (fprintf(fout, "%s\n", p->files[i]->filename) == -1) - err(1, "playlist_save: failed to record playlist \"%s\"", p->filename); + fatal("playlist_save: failed to record playlist \"%s\"", p->filename); } fclose(fout); @@ -282,7 +282,7 @@ playlist_delete(playlist *p) { /* delete file if the playlist is stored in a file */ if (p->filename != NULL && unlink(p->filename) != 0) - err(1, "playlist_delete: failed to delete playlist \"%s\"", p->filename); + fatal("playlist_delete: failed to delete playlist \"%s\"", p->filename); /* destroy/free() all memory */ playlist_free(p); @@ -354,20 +354,20 @@ retrieve_playlist_filenames(const char *dirname, char ***fnames) /* build the search pattern */ if (asprintf(&glob_pattern, "%s/*.playlist", dirname) == -1) - errx(1, "failed in building glob pattern"); + fatalx("failed in building glob pattern"); /* get the files */ globbed = glob(glob_pattern, 0, NULL, &files); if (globbed != 0 && globbed != GLOB_NOMATCH && errno != 0) - err(1, "failed to glob playlists directory"); + fatal("failed to glob playlists directory"); /* allocate & copy each of the filenames found into the filenames array */ if ((*fnames = calloc(files.gl_pathc, sizeof(char*))) == NULL) - err(1, "failed to allocate playlist filenames array"); + fatal("failed to allocate playlist filenames array"); for (fcount = 0; fcount < files.gl_pathc; fcount++) { if (asprintf(&((*fnames)[fcount]), "%s", files.gl_pathv[fcount]) == -1) - errx(1, "failed to allocate filename for playlist"); + fatalx("failed to allocate filename for playlist"); } /* cleanup */ @@ -385,10 +385,10 @@ changeset_create(short type, size_t size, meta_info **files, int loc) playlist_changeset *c; if ((c = malloc(sizeof(playlist_changeset))) == NULL) - err(1, "%s: malloc(3) failed", __FUNCTION__); + fatal("%s: malloc(3) failed", __FUNCTION__); if ((c->files = calloc(size, sizeof(meta_info*))) == NULL) - err(1, "%s: calloc(3) failed", __FUNCTION__); + fatal("%s: calloc(3) failed", __FUNCTION__); c->type = type; c->size = size; @@ -414,7 +414,7 @@ playlist_history_new(void) int i; if ((h = calloc(history_size, sizeof(playlist_changeset*))) == NULL) - err(1, "%s: calloc(3) failed", __FUNCTION__); + fatal("%s: calloc(3) failed", __FUNCTION__); for (i = 0; i < history_size; i++) h[i] = NULL; @@ -479,7 +479,7 @@ playlist_undo(playlist *p) playlist_files_add(p, c->files, c->location, c->size, false); break; default: - errx(1, "%s: invalid change type", __FUNCTION__); + fatalx("%s: invalid change type", __FUNCTION__); } p->hist_present--; @@ -506,7 +506,7 @@ playlist_redo(playlist *p) playlist_files_remove(p, c->location, c->size, false); break; default: - errx(1, "%s: invalid change type", __FUNCTION__); + fatalx("%s: invalid change type", __FUNCTION__); } p->hist_present++; diff --git a/playlist.h b/playlist.h index 60c06a0..61d685e 100644 --- a/playlist.h +++ b/playlist.h @@ -32,6 +32,7 @@ #include #include "debug.h" +#include "error.h" #include "meta_info.h" #define PLAYLIST_CHUNK_SIZE 100 diff --git a/str2argv.c b/str2argv.c index 5922ffb..2c71ca5 100644 --- a/str2argv.c +++ b/str2argv.c @@ -21,10 +21,10 @@ void argv_init(int *argc, char ***argv) { if ((*argv = calloc(ARGV_MAX_ENTRIES, sizeof(char*))) == NULL) - err(1, "argv_init: argv calloc fail"); + fatal("argv_init: argv calloc fail"); if (((*argv)[0] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) - err(1, "argv_init: argv[i] calloc fail"); + fatal("argv_init: argv[i] calloc fail"); bzero((*argv)[0], ARGV_MAX_TOKEN_LEN * sizeof(char)); *argc = 0; @@ -51,7 +51,7 @@ argv_addch(int argc, char **argv, int c) n = strlen(argv[argc]); if (n == ARGV_MAX_TOKEN_LEN - 1) - errx(1, "argv_addch: reached max token length (%d)", ARGV_MAX_TOKEN_LEN); + fatalx("argv_addch: reached max token length (%d)", ARGV_MAX_TOKEN_LEN); argv[argc][n] = c; } @@ -61,14 +61,14 @@ void argv_finish_token(int *argc, char ***argv) { if (*argc == ARGV_MAX_ENTRIES - 1) - errx(1, "argv_finish_token: reached max argv entries(%d)", ARGV_MAX_ENTRIES); + fatalx("argv_finish_token: reached max argv entries(%d)", ARGV_MAX_ENTRIES); if (strlen((*argv)[*argc]) == 0) return; *argc = *argc + 1; if (((*argv)[*argc] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) - err(1, "argv_finish_token: failed to calloc argv[i]"); + fatal("argv_finish_token: failed to calloc argv[i]"); bzero((*argv)[*argc], ARGV_MAX_TOKEN_LEN * sizeof(char)); } @@ -241,7 +241,7 @@ argv2str(int argc, char *argv[]) /* allocate result */ if ((result = calloc(len, sizeof(char))) == NULL) - err(1, "argv2str: calloc failed"); + fatal("argv2str: calloc failed"); bzero(result, len); /* build result */ diff --git a/str2argv.h b/str2argv.h index ab77c19..2d904ab 100644 --- a/str2argv.h +++ b/str2argv.h @@ -26,6 +26,7 @@ #include #include "debug.h" +#include "error.h" /* hard limits on the size of an argv and each entry/token w/in an argv */ #define ARGV_MAX_ENTRIES 255 diff --git a/uinterface.c b/uinterface.c index eef84e3..e50db71 100644 --- a/uinterface.c +++ b/uinterface.c @@ -28,7 +28,7 @@ swindow_new(int h, int w, int y, int x) { swindow *swin = malloc(sizeof(swindow)); if (swin == NULL) - err(1, "swindow_new failed to allocate swin"); + fatal("swindow_new failed to allocate swin"); swin->w = w; swin->h = h; @@ -38,7 +38,7 @@ swindow_new(int h, int w, int y, int x) swin->nrows = 0; swin->cwin = newwin(h, w, y, x); if (swin->cwin == NULL) - errx(1, "swindow_new: failed to create window"); + fatalx("swindow_new: failed to create window"); return swin; } @@ -95,7 +95,7 @@ swindow_scroll(swindow *win, Direction d, int n) break; default: - err(1, "swindow_scroll: bad direction"); + fatal("swindow_scroll: bad direction"); } } @@ -129,7 +129,7 @@ ui_init(int library_width) ui.player = newwin(1, cols, 0, 0); ui.command = newwin(1, cols, lines - 1, 0); if (ui.player == NULL || ui.command == NULL) - errx(1, "ui_init: failed to create player/command windows"); + fatalx("ui_init: failed to create player/command windows"); /* and the rest */ ui.library = swindow_new(lines - 3, ui.lwidth, 2, 0); @@ -172,16 +172,16 @@ ui_resize() /* get new dimensions and check for changes */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) - err(1, "ui_resize: ioctl failed"); + fatal("ui_resize: ioctl failed"); /* can we even handle the new display size? if not, just exit */ if (ws.ws_col < ui.lwidth + 2) { endwin(); - errx(1, "ui_resize: not enough columns to render vitunes nicely"); + fatalx("ui_resize: not enough columns to render vitunes nicely"); } if (ws.ws_row < 4) { endwin(); - errx(1, "ui_resize: not enough rows to render vitunes nicely"); + fatalx("ui_resize: not enough rows to render vitunes nicely"); } /* resize ncurses */ @@ -234,7 +234,7 @@ ui_unhide_library() /* create library window */ ui.library->cwin = newwin(h - 3, ui.lwidth, 2, 0); if (ui.library->cwin == NULL) - errx(1, "ui_unhide_library: failed to create newwin"); + fatalx("ui_unhide_library: failed to create newwin"); /* resize & move playlist window */ swindow_resize(ui.playlist, h - 3, w - ui.lwidth - 1, 2, ui.lwidth + 1); diff --git a/uinterface.h b/uinterface.h index e28e15a..a9bd54a 100644 --- a/uinterface.h +++ b/uinterface.h @@ -34,6 +34,7 @@ #include "debug.h" #include "enums.h" +#include "error.h" /* struct & methods for a scrollable window */ typedef struct diff --git a/vitunes.c b/vitunes.c index 7f2a9f0..04c1eb2 100644 --- a/vitunes.c +++ b/vitunes.c @@ -97,7 +97,7 @@ main(int argc, char *argv[]) #ifdef DEBUG if ((debug_log = fopen("vitunes-debug.log", "w")) == NULL) - err(1, "failed to open debug log"); + fatal("failed to open debug log"); #endif /*------------------------------------------------------------------------ @@ -114,15 +114,15 @@ main(int argc, char *argv[]) /* build paths & other needed strings */ if (asprintf(&vitunes_dir, VITUNES_DIR_FMT, home) == -1) - err(1, "main: asprintf failed"); + fatal("main: asprintf failed"); if (asprintf(&conf_file, CONF_FILE_FMT, home) == -1) - err(1, "main: asprintf failed"); + fatal("main: asprintf failed"); if (asprintf(&db_file, DB_FILE_FMT, home) == -1) - err(1, "main: asprintf failed"); + fatal("main: asprintf failed"); if (asprintf(&playlist_dir, PLAYLIST_DIR_FMT, home) == -1) - err(1, "main: asprintf failed"); + fatal("main: asprintf failed"); if (asprintf(&player_backend, "%s", DEFAULT_PLAYER_BACKEND) == -1) - err(1, "main: asprintf failed"); + fatal("main: asprintf failed"); /* handle command-line switches & e-commands */ handle_switches(argc, argv); @@ -131,7 +131,7 @@ main(int argc, char *argv[]) printf("Vitunes appears to be running already. Won't open socket."); } else { if((sock = sock_listen()) == -1) - errx(1, "failed to open socket."); + fatalx("failed to open socket."); } @@ -253,7 +253,7 @@ main(int argc, char *argv[]) if (QUIT_CAUSE != EXIT_NORMAL) { switch (QUIT_CAUSE) { case BAD_PLAYER: - warnx("It appears the media player is misbehaving. Apologies."); + infox("It appears the media player is misbehaving. Apologies."); break; } } @@ -365,12 +365,12 @@ setup_timer() /* create timer signal handler */ if (sigemptyset(&sig_act.sa_mask) < 0) - err(1, "setup_timer: sigemptyset failed"); + fatal("setup_timer: sigemptyset failed"); sig_act.sa_flags = 0; sig_act.sa_handler = signal_handler; if (sigaction(SIGALRM, &sig_act, NULL) < 0) - err(1, "setup_timer: sigaction failed"); + fatal("setup_timer: sigaction failed"); /* setup timer details */ timer.it_value.tv_sec = 0; @@ -380,7 +380,7 @@ setup_timer() /* register timer */ if (setitimer(ITIMER_REAL, &timer, NULL) < 0) - err(1, "setup_timer: setitimer failed"); + fatal("setup_timer: setitimer failed"); } /* @@ -411,7 +411,7 @@ load_config() /* get next line */ if ((line = fparseln(fin, &length, &linenum, NULL, 0)) == NULL) { if (ferror(fin)) - err(1, "error reading config file '%s'", conf_file); + fatal("error reading config file '%s'", conf_file); else break; } @@ -427,7 +427,7 @@ load_config() /* parse line into argc/argv */ if (str2argv(copy, &argc, &argv, &errmsg) != 0) { endwin(); - errx(1, "%s line %zd: parse error: %s", conf_file, linenum, errmsg); + fatalx("%s line %zd: parse error: %s", conf_file, linenum, errmsg); } /* run command */ @@ -444,16 +444,16 @@ load_config() if (found && num_matches == 1) { if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) { endwin(); - errx(1, "%s line %zd: error with command '%s' [%i]", + fatalx("%s line %zd: error with command '%s' [%i]", conf_file, linenum, argv[0], ret); } } else if (num_matches > 1) { endwin(); - errx(1, "%s line %zd: ambiguous abbreviation '%s'", + fatalx("%s line %zd: ambiguous abbreviation '%s'", conf_file, linenum, argv[0]); } else { endwin(); - errx(1, "%s line %zd: unknown command '%s'", + fatalx("%s line %zd: unknown command '%s'", conf_file, linenum, argv[0]); } @@ -477,13 +477,13 @@ handle_switches(int argc, char *argv[]) switch (ch) { case 'c': if(sock_send_msg(optarg) == -1) - errx(1, "Failed to send message. Vitunes not running?"); + fatalx("Failed to send message. Vitunes not running?"); exit(0); case 'd': free(db_file); if ((db_file = strdup(optarg)) == NULL) - err(1, "handle_switches: strdup db_file failed"); + fatal("handle_switches: strdup db_file failed"); break; case 'e': @@ -496,19 +496,19 @@ handle_switches(int argc, char *argv[]) case 'f': free(conf_file); if ((conf_file = strdup(optarg)) == NULL) - err(1, "handle_switches: strdup conf_file failed"); + fatal("handle_switches: strdup conf_file failed"); break; case 'm': free(player_backend); if ((player_backend = strdup(optarg)) == NULL) - err(1, "handle_switches: strdup player_backend failed"); + fatal("handle_switches: strdup player_backend failed"); break; case 'p': free(playlist_dir); if ((playlist_dir = strdup(optarg)) == NULL) - err(1, "handle_switches: strdup playlist_dir failed"); + fatal("handle_switches: strdup playlist_dir failed"); break; case 'h': diff --git a/vitunes.h b/vitunes.h index 8348da0..eeb8fdc 100644 --- a/vitunes.h +++ b/vitunes.h @@ -37,6 +37,7 @@ #include "player.h" #include "uinterface.h" #include "ecmd.h" +#include "error.h" /* for unused arguments */ #if defined(__GNUC__) || defined(__clang__) From 100fb96378dfeae771f66481ebe4151943e6f802 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 20:19:38 +0000 Subject: [PATCH 05/42] Remove includes from the header files. Specific "modules" should include what they really need and not rely on some other header including files. Obviously, now, headers need to be explicitly included. --- commands.c | 7 +++++++ commands.h | 10 ---------- ecmd.c | 6 ++++++ ecmd.h | 7 ------- error.c | 7 +++++++ error.h | 8 -------- keybindings.c | 7 ++++++- keybindings.h | 8 -------- medialib.c | 14 ++++++++++++++ medialib.h | 16 ---------------- meta_info.c | 19 +++++++++++++++++++ meta_info.h | 21 --------------------- paint.c | 15 +++++++++++++++ paint.h | 17 ----------------- player.c | 13 +++++++++++++ player.h | 15 --------------- players/mplayer.c | 21 +++++++++++++++++++++ players/mplayer.h | 22 ---------------------- players/player_utils.c | 8 ++++++++ players/player_utils.h | 9 --------- playlist.c | 16 ++++++++++++++++ playlist.h | 18 ------------------ socket.c | 9 +++++---- socket.h | 2 -- str2argv.c | 9 +++++++++ str2argv.h | 11 ----------- uinterface.c | 17 +++++++++++++++++ uinterface.h | 19 ------------------- vitunes.c | 22 +++++++++++++++++++++- vitunes.h | 22 ---------------------- 30 files changed, 184 insertions(+), 211 deletions(-) diff --git a/commands.c b/commands.c index c19b432..0c52532 100644 --- a/commands.c +++ b/commands.c @@ -15,6 +15,13 @@ */ #include "commands.h" +#include "debug.h" +#include "enums.h" +#include "error.h" +#include "keybindings.h" +#include "paint.h" +#include "str2argv.h" +#include "vitunes.h" bool sorts_need_saving = false; diff --git a/commands.h b/commands.h index e520b03..9253e12 100644 --- a/commands.h +++ b/commands.h @@ -17,16 +17,6 @@ #ifndef COMMANDS_H #define COMMANDS_H -#include "compat.h" - -#include "enums.h" -#include "paint.h" -#include "str2argv.h" -#include "vitunes.h" -#include "debug.h" -#include "keybindings.h" -#include "error.h" - /**************************************************************************** * Toggle-list handling stuff ***************************************************************************/ diff --git a/ecmd.c b/ecmd.c index a77c657..f266d16 100644 --- a/ecmd.c +++ b/ecmd.c @@ -15,7 +15,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include + #include "ecmd.h" +#include "vitunes.h" static int ecmd_parse(const struct ecmd *ecmd, int argc, char ***argv) diff --git a/ecmd.h b/ecmd.h index 95c4a31..4ae8e47 100644 --- a/ecmd.h +++ b/ecmd.h @@ -18,13 +18,6 @@ #ifndef ECMD_H #define ECMD_H -#include -#include -#include -#include - -#include "vitunes.h" - struct ecmd { const char *name; const char *alias; /* may be NULL */ diff --git a/error.c b/error.c index c864ea1..ff27a05 100644 --- a/error.c +++ b/error.c @@ -14,7 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include + #include "error.h" +#include "vitunes.h" /* * Prints the provided error message to standard error and, if wanted, appends diff --git a/error.h b/error.h index 26db5e1..fcdf2a7 100644 --- a/error.h +++ b/error.h @@ -17,14 +17,6 @@ #ifndef ERROR_H #define ERROR_H -#include -#include -#include -#include -#include - -#include "vitunes.h" - void fatal(const char *, ...); void fatalx(const char *, ...); void info(const char *, ...); diff --git a/keybindings.c b/keybindings.c index c24cdfb..cc72172 100644 --- a/keybindings.c +++ b/keybindings.c @@ -14,8 +14,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "compat.h" +#include "debug.h" +#include "enums.h" +#include "error.h" #include "keybindings.h" - +#include "paint.h" +#include "vitunes.h" /* This table maps KeyActions to their string representations */ typedef struct { diff --git a/keybindings.h b/keybindings.h index 2132a9b..0285c95 100644 --- a/keybindings.h +++ b/keybindings.h @@ -17,14 +17,6 @@ #ifndef KEYBINDINGS_H #define KEYBINDINGS_H -#include "compat.h" - -#include "debug.h" -#include "enums.h" -#include "error.h" -#include "paint.h" -#include "vitunes.h" - /* * List of all actions that can be bound by keybindings. * NOTE: Using "count" trick (see last element), so no enum should be defined. diff --git a/medialib.c b/medialib.c index c8271f1..a36ebea 100644 --- a/medialib.c +++ b/medialib.c @@ -14,7 +14,21 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include + +#include +#include +#include +#include + +#include "compat.h" +#include "debug.h" +#include "error.h" #include "medialib.h" +#include "meta_info.h" +#include "playlist.h" /* The global media library struct */ medialib mdb; diff --git a/medialib.h b/medialib.h index 7b6b8ab..5ba1dfe 100644 --- a/medialib.h +++ b/medialib.h @@ -25,22 +25,6 @@ #ifndef MEDIALIB_H #define MEDIALIB_H -#include "compat.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "debug.h" -#include "error.h" -#include "meta_info.h" -#include "playlist.h" - #define MEDIALIB_PLAYLISTS_CHUNK_SIZE 100 /* current database file-format version */ diff --git a/meta_info.c b/meta_info.c index cc430ef..3173927 100644 --- a/meta_info.c +++ b/meta_info.c @@ -14,6 +14,25 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* non-baes includes (just TagLib) */ +#include + +#include "compat.h" +#include "debug.h" +#include "enums.h" +#include "error.h" #include "meta_info.h" /* human-readable names of all of the string-type meta information values */ diff --git a/meta_info.h b/meta_info.h index 4586ab5..eba4f45 100644 --- a/meta_info.h +++ b/meta_info.h @@ -17,27 +17,6 @@ #ifndef META_INFO_H #define META_INFO_H -#include "compat.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* non-baes includes (just TagLib) */ -#include - -#include "debug.h" -#include "enums.h" -#include "error.h" - /* the character-info fields. used for all meta-info that's shown */ #define MI_NUM_CINFO 8 #define MI_CINFO_ARTIST 0 diff --git a/paint.c b/paint.c index 6bebdbf..9fb776f 100644 --- a/paint.c +++ b/paint.c @@ -14,7 +14,22 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "enums.h" +#include "error.h" +#include "meta_info.h" #include "paint.h" +#include "player.h" +#include "playlist.h" +#include "uinterface.h" +#include "vitunes.h" /* globals */ _colors colors; diff --git a/paint.h b/paint.h index 489297d..47ca5f5 100644 --- a/paint.h +++ b/paint.h @@ -17,23 +17,6 @@ #ifndef PAINT_H #define PAINT_H -#include "compat.h" - -#include -#include -#include -#include -#include -#include - -#include "enums.h" -#include "error.h" -#include "meta_info.h" -#include "player.h" -#include "playlist.h" -#include "uinterface.h" -#include "vitunes.h" - /* colors used by paint - each of these will be a number for a COLOR_PAIR */ typedef struct { /* visual dividers of windows */ diff --git a/player.c b/player.c index e641525..758bc4a 100644 --- a/player.c +++ b/player.c @@ -14,7 +14,20 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + +#include "compat.h" +#include "debug.h" +#include "error.h" +#include "paint.h" #include "player.h" +#include "playlist.h" + +/* "static" backends (those that aren't dynamically loaded) */ +#include "players/mplayer.h" +#if defined(ENABLE_GSTREAMER) +# include "players/gstplayer.h" +#endif /* globals */ player_backend_t player; diff --git a/player.h b/player.h index 6c490b0..09f6944 100644 --- a/player.h +++ b/player.h @@ -17,21 +17,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "compat.h" - -#include - -#include "playlist.h" -#include "paint.h" -#include "debug.h" -#include "error.h" - -/* "static" backends (those that aren't dynamically loaded) */ -#include "players/mplayer.h" -#if defined(ENABLE_GSTREAMER) -# include "players/gstplayer.h" -#endif - /* * Available play-modes. * Linear: Songs in the queue play in the order they appear diff --git a/players/mplayer.c b/players/mplayer.c index fcc8f71..d75cfdf 100644 --- a/players/mplayer.c +++ b/players/mplayer.c @@ -14,8 +14,29 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../compat.h" #include "mplayer.h" #include "mplayer_conf.h" +#include "player_utils.h" + +#ifdef DEBUG +# include "../debug.h" +#endif /* callback functions */ void (*mplayer_callback_playnext)(void) = NULL; diff --git a/players/mplayer.h b/players/mplayer.h index 03700cd..d8f3685 100644 --- a/players/mplayer.h +++ b/players/mplayer.h @@ -17,28 +17,6 @@ #ifndef MPLAYER_H #define MPLAYER_H -#include "../compat.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "player_utils.h" - -#ifdef DEBUG -# include "../debug.h" -#endif - void mplayer_start(); void mplayer_finish(); void mplayer_sigchld(); diff --git a/players/player_utils.c b/players/player_utils.c index 271774a..541eaf0 100644 --- a/players/player_utils.c +++ b/players/player_utils.c @@ -14,6 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include +#include + +#include "../compat.h" #include "player_utils.h" bool diff --git a/players/player_utils.h b/players/player_utils.h index f54b72e..d6ff969 100644 --- a/players/player_utils.h +++ b/players/player_utils.h @@ -17,15 +17,6 @@ #ifndef PLAYER_UTILS_H #define PLAYER_UTILS_H -#include "../compat.h" - -#include -#include -#include -#include -#include -#include - bool exe_in_path(const char *e); #endif diff --git a/playlist.c b/playlist.c index 7b5e6c8..e415dbe 100644 --- a/playlist.c +++ b/playlist.c @@ -14,6 +14,22 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "debug.h" +#include "error.h" +#include "meta_info.h" #include "playlist.h" int history_size = DEFAULT_HISTORY_SIZE; diff --git a/playlist.h b/playlist.h index 61d685e..aaf8613 100644 --- a/playlist.h +++ b/playlist.h @@ -17,24 +17,6 @@ #ifndef PLAYLIST_H #define PLAYLIST_H -#include "compat.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "error.h" -#include "meta_info.h" - #define PLAYLIST_CHUNK_SIZE 100 #define DEFAULT_HISTORY_SIZE 100 extern int history_size; diff --git a/socket.c b/socket.c index af4dcfb..174c555 100644 --- a/socket.c +++ b/socket.c @@ -13,19 +13,20 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include + #include #include #include + +#include +#include #include -#include "socket.h" #include "commands.h" +#include "socket.h" #define VITUNES_SOCK "/tmp/.vitunes" - int sock_send_msg(const char *msg) { diff --git a/socket.h b/socket.h index 155f3f0..056d2b1 100644 --- a/socket.h +++ b/socket.h @@ -16,8 +16,6 @@ #ifndef SOCKET_H #define SOCKET_H -#include - #define VITUNES_RUNNING "WHOWASPHONE?" /* diff --git a/str2argv.c b/str2argv.c index 2c71ca5..9c61de0 100644 --- a/str2argv.c +++ b/str2argv.c @@ -14,6 +14,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include + +#include "compat.h" +#include "debug.h" +#include "error.h" #include "str2argv.h" /* initialize empty argc/argv struct */ diff --git a/str2argv.h b/str2argv.h index 2d904ab..d826d07 100644 --- a/str2argv.h +++ b/str2argv.h @@ -17,17 +17,6 @@ #ifndef STR2ARGV_H #define STR2ARGV_H -#include "compat.h" - -#include -#include -#include -#include -#include - -#include "debug.h" -#include "error.h" - /* hard limits on the size of an argv and each entry/token w/in an argv */ #define ARGV_MAX_ENTRIES 255 #define ARGV_MAX_TOKEN_LEN 255 diff --git a/uinterface.c b/uinterface.c index e50db71..7ad6801 100644 --- a/uinterface.c +++ b/uinterface.c @@ -14,6 +14,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "debug.h" +#include "enums.h" +#include "error.h" #include "uinterface.h" /* the global user interface object */ diff --git a/uinterface.h b/uinterface.h index a9bd54a..acc2607 100644 --- a/uinterface.h +++ b/uinterface.h @@ -17,25 +17,6 @@ #ifndef UINTERFACE_H #define UINTERFACE_H -#include "compat.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "enums.h" -#include "error.h" - /* struct & methods for a scrollable window */ typedef struct { diff --git a/vitunes.c b/vitunes.c index 04c1eb2..3da5a28 100644 --- a/vitunes.c +++ b/vitunes.c @@ -14,9 +14,29 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "commands.h" +#include "compat.h" +#include "debug.h" +#include "ecmd.h" +#include "enums.h" +#include "error.h" +#include "keybindings.h" +#include "medialib.h" +#include "player.h" +#include "socket.h" +#include "uinterface.h" #include "vitunes.h" #include "config.h" /* NOTE: must be after vitunes.h */ -#include "socket.h" /***************************************************************************** * GLOBALS, EXPORTED diff --git a/vitunes.h b/vitunes.h index eeb8fdc..b4560d1 100644 --- a/vitunes.h +++ b/vitunes.h @@ -17,28 +17,6 @@ #ifndef VITUNES_H #define VITUNES_H -#include "compat.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "enums.h" -#include "commands.h" -#include "keybindings.h" -#include "medialib.h" -#include "player.h" -#include "uinterface.h" -#include "ecmd.h" -#include "error.h" - /* for unused arguments */ #if defined(__GNUC__) || defined(__clang__) # define UNUSED __attribute__((__unused__)) From 02805ac926606fef75e777b91432e8d05b46e545 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 21 Feb 2013 20:46:39 +0000 Subject: [PATCH 06/42] Add missing includes. --- commands.c | 6 ++++++ commands.h | 4 ++++ ecmd.c | 2 +- ecmd_addurl.c | 1 - ecmd_check.c | 4 +++- ecmd_flush.c | 1 - ecmd_help.c | 1 - ecmd_tag.c | 4 +++- error.c | 1 + keybindings.c | 9 +++++++++ keybindings.h | 4 ++++ medialib.c | 3 ++- medialib.h | 2 ++ meta_info.c | 1 - meta_info.h | 5 +++++ paint.c | 4 +++- paint.h | 2 ++ player.c | 6 +++++- player.h | 2 ++ players/gstplayer.c | 1 + playlist.c | 2 +- playlist.h | 2 ++ socket.c | 2 ++ str2argv.c | 1 - uinterface.c | 1 - uinterface.h | 2 ++ vitunes.c | 6 +++++- vitunes.h | 4 ++++ 28 files changed, 69 insertions(+), 14 deletions(-) diff --git a/commands.c b/commands.c index 0c52532..3979ecb 100644 --- a/commands.c +++ b/commands.c @@ -14,13 +14,19 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include + #include "commands.h" #include "debug.h" #include "enums.h" #include "error.h" #include "keybindings.h" +#include "medialib.h" #include "paint.h" +#include "player.h" #include "str2argv.h" +#include "uinterface.h" #include "vitunes.h" bool sorts_need_saving = false; diff --git a/commands.h b/commands.h index 9253e12..53b03b8 100644 --- a/commands.h +++ b/commands.h @@ -17,6 +17,10 @@ #ifndef COMMANDS_H #define COMMANDS_H +#include + +#include "playlist.h" + /**************************************************************************** * Toggle-list handling stuff ***************************************************************************/ diff --git a/ecmd.c b/ecmd.c index f266d16..3478426 100644 --- a/ecmd.c +++ b/ecmd.c @@ -15,12 +15,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include #include "ecmd.h" +#include "error.h" #include "vitunes.h" static int diff --git a/ecmd_addurl.c b/ecmd_addurl.c index 4cd0e32..d224986 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -15,7 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include diff --git a/ecmd_check.c b/ecmd_check.c index 3ee5281..8d6dfe7 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -15,12 +15,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include +#include #include #include #include "ecmd.h" +#include "error.h" #include "medialib.h" #include "vitunes.h" diff --git a/ecmd_flush.c b/ecmd_flush.c index 0d2da5d..a72db9d 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -15,7 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include diff --git a/ecmd_help.c b/ecmd_help.c index 8886ff5..086639f 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -15,7 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include diff --git a/ecmd_tag.c b/ecmd_tag.c index 16ec4c5..112981f 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -15,12 +15,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include #include #include #include +#include + #include "ecmd.h" #include "error.h" #include "meta_info.h" diff --git a/error.c b/error.c index ff27a05..1791cdd 100644 --- a/error.c +++ b/error.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "error.h" diff --git a/keybindings.c b/keybindings.c index cc72172..62c1698 100644 --- a/keybindings.c +++ b/keybindings.c @@ -14,12 +14,21 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include + +#include "commands.h" #include "compat.h" #include "debug.h" #include "enums.h" #include "error.h" #include "keybindings.h" +#include "medialib.h" #include "paint.h" +#include "player.h" +#include "str2argv.h" +#include "uinterface.h" #include "vitunes.h" /* This table maps KeyActions to their string representations */ diff --git a/keybindings.h b/keybindings.h index 0285c95..5df52d7 100644 --- a/keybindings.h +++ b/keybindings.h @@ -17,6 +17,10 @@ #ifndef KEYBINDINGS_H #define KEYBINDINGS_H +#include + +#include "meta_info.h" + /* * List of all actions that can be bound by keybindings. * NOTE: Using "count" trick (see last element), so no enum should be defined. diff --git a/medialib.c b/medialib.c index a36ebea..26f8a64 100644 --- a/medialib.c +++ b/medialib.c @@ -14,13 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include +#include #include #include #include +#include #include #include "compat.h" diff --git a/medialib.h b/medialib.h index 5ba1dfe..20e707d 100644 --- a/medialib.h +++ b/medialib.h @@ -25,6 +25,8 @@ #ifndef MEDIALIB_H #define MEDIALIB_H +#include "playlist.h" + #define MEDIALIB_PLAYLISTS_CHUNK_SIZE 100 /* current database file-format version */ diff --git a/meta_info.c b/meta_info.c index 3173927..cda0744 100644 --- a/meta_info.c +++ b/meta_info.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include diff --git a/meta_info.h b/meta_info.h index eba4f45..24fead9 100644 --- a/meta_info.h +++ b/meta_info.h @@ -17,6 +17,11 @@ #ifndef META_INFO_H #define META_INFO_H +#include +#include + +#include "enums.h" + /* the character-info fields. used for all meta-info that's shown */ #define MI_NUM_CINFO 8 #define MI_CINFO_ARTIST 0 diff --git a/paint.c b/paint.c index 9fb776f..c257857 100644 --- a/paint.c +++ b/paint.c @@ -14,16 +14,18 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include +#include #include #include +#include #include #include #include "compat.h" #include "enums.h" #include "error.h" +#include "medialib.h" #include "meta_info.h" #include "paint.h" #include "player.h" diff --git a/paint.h b/paint.h index 47ca5f5..8be6882 100644 --- a/paint.h +++ b/paint.h @@ -17,6 +17,8 @@ #ifndef PAINT_H #define PAINT_H +#include "meta_info.h" + /* colors used by paint - each of these will be a number for a COLOR_PAIR */ typedef struct { /* visual dividers of windows */ diff --git a/player.c b/player.c index 758bc4a..7419680 100644 --- a/player.c +++ b/player.c @@ -14,7 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include +#include +#include #include "compat.h" #include "debug.h" @@ -22,6 +24,8 @@ #include "paint.h" #include "player.h" #include "playlist.h" +#include "uinterface.h" +#include "vitunes.h" /* "static" backends (those that aren't dynamically loaded) */ #include "players/mplayer.h" diff --git a/player.h b/player.h index 09f6944..b4457cb 100644 --- a/player.h +++ b/player.h @@ -17,6 +17,8 @@ #ifndef PLAYER_H #define PLAYER_H +#include "playlist.h" + /* * Available play-modes. * Linear: Songs in the queue play in the order they appear diff --git a/players/gstplayer.c b/players/gstplayer.c index 01f77a7..e5a3c67 100644 --- a/players/gstplayer.c +++ b/players/gstplayer.c @@ -23,6 +23,7 @@ #include "gstplayer.h" #include "../player.h" +#include "../vitunes.h" /* player data */ static gst_player gplayer; diff --git a/playlist.c b/playlist.c index e415dbe..b2291b5 100644 --- a/playlist.c +++ b/playlist.c @@ -17,10 +17,10 @@ #include #include -#include #include #include #include +#include #include #include #include diff --git a/playlist.h b/playlist.h index aaf8613..a6d98f5 100644 --- a/playlist.h +++ b/playlist.h @@ -17,6 +17,8 @@ #ifndef PLAYLIST_H #define PLAYLIST_H +#include "meta_info.h" + #define PLAYLIST_CHUNK_SIZE 100 #define DEFAULT_HISTORY_SIZE 100 extern int history_size; diff --git a/socket.c b/socket.c index 174c555..8cacd5a 100644 --- a/socket.c +++ b/socket.c @@ -18,11 +18,13 @@ #include #include +#include #include #include #include #include "commands.h" +#include "keybindings.h" #include "socket.h" #define VITUNES_SOCK "/tmp/.vitunes" diff --git a/str2argv.c b/str2argv.c index 9c61de0..5457ac3 100644 --- a/str2argv.c +++ b/str2argv.c @@ -14,7 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include diff --git a/uinterface.c b/uinterface.c index 7ad6801..2a7cfdb 100644 --- a/uinterface.c +++ b/uinterface.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/uinterface.h b/uinterface.h index acc2607..2fb1560 100644 --- a/uinterface.h +++ b/uinterface.h @@ -17,6 +17,8 @@ #ifndef UINTERFACE_H #define UINTERFACE_H +#include + /* struct & methods for a scrollable window */ typedef struct { diff --git a/vitunes.c b/vitunes.c index 3da5a28..f195a4f 100644 --- a/vitunes.c +++ b/vitunes.c @@ -16,11 +16,13 @@ #include -#include +#include +#include #include #include #include #include +#include #include #include @@ -32,8 +34,10 @@ #include "error.h" #include "keybindings.h" #include "medialib.h" +#include "paint.h" #include "player.h" #include "socket.h" +#include "str2argv.h" #include "uinterface.h" #include "vitunes.h" #include "config.h" /* NOTE: must be after vitunes.h */ diff --git a/vitunes.h b/vitunes.h index b4560d1..68b417c 100644 --- a/vitunes.h +++ b/vitunes.h @@ -17,6 +17,10 @@ #ifndef VITUNES_H #define VITUNES_H +#include + +#include "playlist.h" + /* for unused arguments */ #if defined(__GNUC__) || defined(__clang__) # define UNUSED __attribute__((__unused__)) From 4135b871c7258804dcda6994cd7296a999f3b3b7 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 11:42:00 +0000 Subject: [PATCH 07/42] Replace special errx(3) call with new function. --- ecmd_rmfile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index 4795d65..ff49675 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -15,8 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include +#include #include #include @@ -70,7 +70,8 @@ ecmd_rmfile_exec(UNUSED int argc, char **argv) /* if not found then error */ if (!found) { i = (forced ? 0 : 1); - errx(i, "%s: %s: No such file or URL", argv[0], argv[0]); + infox("%s: No such file or URL", argv[0]); + exit(i); } /* if not forced, prompt user if they are sure */ From 0b5e57dc155987735862d12b0385a2efafda98de Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 14:32:52 +0000 Subject: [PATCH 08/42] Add missing format argument. Might be better, in the future, to append -Wformat=2 to CFLAGS and also use the printf format attribute. --- keybindings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keybindings.c b/keybindings.c index 62c1698..82adf78 100644 --- a/keybindings.c +++ b/keybindings.c @@ -925,7 +925,7 @@ kba_search_find(KbaArgs a) /* found one, jump to it */ if (matches) { if (msg != NULL) - paint_message(msg); + paint_message("%s", msg); gnum_set(idx + 1); foo = get_dummy_args(); From 8ab190258e91861633238fc130ddb0d27dce4eb6 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 15:00:55 +0000 Subject: [PATCH 09/42] Start adding support for error context. --- error.c | 31 +++++++++++++++++++++++++++---- error.h | 3 +++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/error.c b/error.c index 1791cdd..d236eff 100644 --- a/error.c +++ b/error.c @@ -24,6 +24,9 @@ #include "error.h" #include "vitunes.h" +/* error type which depends on the context */ +static int error_type; + /* * Prints the provided error message to standard error and, if wanted, appends * the errno message string. @@ -39,6 +42,26 @@ error_print(bool errnoflag, const char *fmt, va_list ap) fputs("\n", stderr); } +/* + * Check which context we are in and call the function responsible to output the + * error message. + */ +static void +error_doit(bool errnoflag, const char *fmt, va_list ap) +{ + switch (error_type) { + default: + error_print(errnoflag, fmt, ap); + break; + } +} + +void +error_init(int type) +{ + error_type = type; +} + /* * Outputs a fatal message, appends the errno message string and terminates the * process. @@ -49,7 +72,7 @@ fatal(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_print(true, fmt, ap); + error_doit(true, fmt, ap); va_end(ap); exit(1); } @@ -61,7 +84,7 @@ fatalx(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_print(false, fmt, ap); + error_doit(false, fmt, ap); va_end(ap); exit(1); } @@ -73,7 +96,7 @@ info(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_print(true, fmt, ap); + error_doit(true, fmt, ap); va_end(ap); } @@ -84,6 +107,6 @@ infox(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_print(false, fmt, ap); + error_doit(false, fmt, ap); va_end(ap); } diff --git a/error.h b/error.h index fcdf2a7..51afd21 100644 --- a/error.h +++ b/error.h @@ -17,6 +17,9 @@ #ifndef ERROR_H #define ERROR_H +#define ERROR_STDERR 0 + +void error_init(int); void fatal(const char *, ...); void fatalx(const char *, ...); void info(const char *, ...); From 8bdd03f8a6516073f56690ad1d0640497e408116 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:06:59 +0000 Subject: [PATCH 10/42] Add configuration file error context. --- error.c | 30 +++++++++++++++++++++++++----- error.h | 1 + vitunes.c | 21 ++++++++++----------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/error.c b/error.c index d236eff..d6b1109 100644 --- a/error.c +++ b/error.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include "error.h" +#include "uinterface.h" #include "vitunes.h" /* error type which depends on the context */ @@ -42,14 +44,32 @@ error_print(bool errnoflag, const char *fmt, va_list ap) fputs("\n", stderr); } +/* + * Prints a fatal message (informational messages are pointless in this context) + * and terminates the process. + */ +static void +error_cfg(bool errnoflag, bool iserr, const char *fmt, va_list ap) +{ + if (!iserr) + return; + + endwin(); + error_print(errnoflag, fmt, ap); + exit(1); +} + /* * Check which context we are in and call the function responsible to output the * error message. */ static void -error_doit(bool errnoflag, const char *fmt, va_list ap) +error_doit(bool errnoflag, bool iserr, const char *fmt, va_list ap) { switch (error_type) { + case ERROR_CFG: + error_cfg(errnoflag, iserr, fmt, ap); + break; default: error_print(errnoflag, fmt, ap); break; @@ -72,7 +92,7 @@ fatal(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_doit(true, fmt, ap); + error_doit(true, true, fmt, ap); va_end(ap); exit(1); } @@ -84,7 +104,7 @@ fatalx(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_doit(false, fmt, ap); + error_doit(false, true, fmt, ap); va_end(ap); exit(1); } @@ -96,7 +116,7 @@ info(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_doit(true, fmt, ap); + error_doit(true, false, fmt, ap); va_end(ap); } @@ -107,6 +127,6 @@ infox(const char *fmt, ...) va_list ap; va_start(ap, fmt); - error_doit(false, fmt, ap); + error_doit(false, false, fmt, ap); va_end(ap); } diff --git a/error.h b/error.h index 51afd21..49b9f32 100644 --- a/error.h +++ b/error.h @@ -18,6 +18,7 @@ #define ERROR_H #define ERROR_STDERR 0 +#define ERROR_CFG 1 void error_init(int); void fatal(const char *, ...); diff --git a/vitunes.c b/vitunes.c index f195a4f..2e7c1a0 100644 --- a/vitunes.c +++ b/vitunes.c @@ -119,6 +119,9 @@ main(int argc, char *argv[]) else progname++; + /* error messages go to stderr before the user interface is set up */ + error_init(ERROR_STDERR); + #ifdef DEBUG if ((debug_log = fopen("vitunes-debug.log", "w")) == NULL) fatal("failed to open debug log"); @@ -204,6 +207,9 @@ main(int argc, char *argv[]) /* setup user interface and default colors */ kb_init(); + + /* user interface being initialised; set context, accordingly */ + error_init(ERROR_CFG); ui_init(DEFAULT_LIBRARY_WINDOW_WIDTH); paint_setup_colors(); @@ -449,10 +455,8 @@ load_config() } /* parse line into argc/argv */ - if (str2argv(copy, &argc, &argv, &errmsg) != 0) { - endwin(); + if (str2argv(copy, &argc, &argv, &errmsg) != 0) fatalx("%s line %zd: parse error: %s", conf_file, linenum, errmsg); - } /* run command */ found = false; @@ -466,20 +470,15 @@ load_config() } if (found && num_matches == 1) { - if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) { - endwin(); + if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) fatalx("%s line %zd: error with command '%s' [%i]", conf_file, linenum, argv[0], ret); - } - } else if (num_matches > 1) { - endwin(); + } else if (num_matches > 1) fatalx("%s line %zd: ambiguous abbreviation '%s'", conf_file, linenum, argv[0]); - } else { - endwin(); + else fatalx("%s line %zd: unknown command '%s'", conf_file, linenum, argv[0]); - } argv_free(&argc, &argv); free(line); From 1553ab464249414c8b2ddb806d0c24aeabb3c1a5 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:13:06 +0000 Subject: [PATCH 11/42] Add paint error context. --- error.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-------- error.h | 1 + vitunes.c | 3 +++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/error.c b/error.c index d6b1109..fc9458c 100644 --- a/error.c +++ b/error.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010, 2011, 2012 Ryan Flannery * Copyright (c) 2013 Tiago Cunha * * Permission to use, copy, modify, and distribute this software for any @@ -23,12 +24,41 @@ #include #include "error.h" +#include "paint.h" #include "uinterface.h" #include "vitunes.h" /* error type which depends on the context */ static int error_type; +/* + * Starts by fetching the needed attributes that depend on the type of the + * message. It, then, paints it to the command/status window and, if wanted + * appends the errno message string. A beep is also issued if it's an error + * message. + */ +static void +error_paint(bool errnoflag, bool iserr, const char *fmt, va_list ap) +{ + int attrs, which; + + which = iserr ? colors.errors : colors.messages; + attrs = COLOR_PAIR(which); + + werase(ui.command); + wmove(ui.command, 0, 0); + wattron(ui.command, attrs); + vwprintw(ui.command, fmt, ap); + + if (errnoflag) + wprintw(ui.command, ": %s", strerror(errno)); + if (iserr) + beep(); + + wattroff(ui.command, attrs); + wrefresh(ui.command); +} + /* * Prints the provided error message to standard error and, if wanted, appends * the errno message string. @@ -59,6 +89,18 @@ error_cfg(bool errnoflag, bool iserr, const char *fmt, va_list ap) exit(1); } +/* + * Prints a message to standard error and terminates the process if it's an + * error. + */ +static void +error_stderr(bool errnoflag, bool iserr, const char *fmt, va_list ap) +{ + error_print(errnoflag, fmt, ap); + if (iserr) + exit(1); +} + /* * Check which context we are in and call the function responsible to output the * error message. @@ -70,8 +112,11 @@ error_doit(bool errnoflag, bool iserr, const char *fmt, va_list ap) case ERROR_CFG: error_cfg(errnoflag, iserr, fmt, ap); break; + case ERROR_PAINT: + error_paint(errnoflag, iserr, fmt, ap); + break; default: - error_print(errnoflag, fmt, ap); + error_stderr(errnoflag, iserr, fmt, ap); break; } } @@ -82,10 +127,7 @@ error_init(int type) error_type = type; } -/* - * Outputs a fatal message, appends the errno message string and terminates the - * process. - */ +/* Outputs a fatal message with the errno message string appended. */ void fatal(const char *fmt, ...) { @@ -94,10 +136,9 @@ fatal(const char *fmt, ...) va_start(ap, fmt); error_doit(true, true, fmt, ap); va_end(ap); - exit(1); } -/* Outputs a fatal message and terminates the process. */ +/* Outputs a fatal message. */ void fatalx(const char *fmt, ...) { @@ -106,7 +147,6 @@ fatalx(const char *fmt, ...) va_start(ap, fmt); error_doit(false, true, fmt, ap); va_end(ap); - exit(1); } /* Outputs an informational message with the errno message string appended. */ diff --git a/error.h b/error.h index 49b9f32..01eb7a8 100644 --- a/error.h +++ b/error.h @@ -19,6 +19,7 @@ #define ERROR_STDERR 0 #define ERROR_CFG 1 +#define ERROR_PAINT 2 void error_init(int); void fatal(const char *, ...); diff --git a/vitunes.c b/vitunes.c index 2e7c1a0..6604278 100644 --- a/vitunes.c +++ b/vitunes.c @@ -224,6 +224,9 @@ main(int argc, char *argv[]) /* initial painting of the display */ paint_all(); + /* configuration file ok; paint messages from now on */ + error_init(ERROR_PAINT); + /* ----------------------------------------------------------------------- * begin input loop * -------------------------------------------------------------------- */ From 4978fa2f566e0d096c996c8d7b14ff555d93bfcf Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:21:27 +0000 Subject: [PATCH 12/42] Add verbose command-line option. --- doc/vitunes.1 | 5 +++++ vitunes.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/vitunes.1 b/doc/vitunes.1 index 7495bef..17e0d49 100644 --- a/doc/vitunes.1 +++ b/doc/vitunes.1 @@ -21,6 +21,7 @@ .Sh SYNOPSIS .Nm vitunes .Bk -words +.Op Fl v .Op Fl c Ar command .Op Fl d Ar database-file .Op Fl e Ar command Op argument ... @@ -138,6 +139,10 @@ will be created here. .Pp The default location is .Pa ~/.vitunes/playlists/ . +.It Fl v +Turn verbose logging on. +Log messages will be saved in the vitunes-debug.log file in the current +directory. .El .Sh GETTING STARTED .Nm diff --git a/vitunes.c b/vitunes.c index 6604278..c9be9be 100644 --- a/vitunes.c +++ b/vitunes.c @@ -299,9 +299,8 @@ void usage(void) { fprintf(stderr,"\ -usage: %s [-f config-file] [-d database-file] [-p playlist-dir] [-m player-path] [-e COMMAND ...]\n\ -See \"%s -e help\" for information about what e-commands are available.\n\ -", +usage: %s [-v] [-f config-file] [-d database-file] [-p playlist-dir] [-m player-path]\n\ +\t[-e COMMAND ...]\nSee \"%s -e help\" for information about what e-commands are available.\n", progname, progname); exit(1); } @@ -499,7 +498,7 @@ handle_switches(int argc, char *argv[]) { int ch; - while ((ch = getopt(argc, argv, "he:f:d:p:m:c:")) != -1) { + while ((ch = getopt(argc, argv, "he:f:d:p:m:c:v")) != -1) { switch (ch) { case 'c': if(sock_send_msg(optarg) == -1) @@ -537,6 +536,9 @@ handle_switches(int argc, char *argv[]) fatal("handle_switches: strdup playlist_dir failed"); break; + case 'v': + break; + case 'h': case '?': default: From f49976a143208f1e709e134ca6f6eadf5a040589 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:22:41 +0000 Subject: [PATCH 13/42] Add functions to output a debug message. --- error.c | 41 ++++++++++++++++++++++++++++++++--------- error.h | 4 ++++ vitunes.c | 1 + 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/error.c b/error.c index fc9458c..ab7a801 100644 --- a/error.c +++ b/error.c @@ -28,8 +28,8 @@ #include "uinterface.h" #include "vitunes.h" -/* error type which depends on the context */ -static int error_type; +static FILE *error_fp; /* error debug file */ +static int error_type; /* error type which depends on the context */ /* * Starts by fetching the needed attributes that depend on the type of the @@ -64,14 +64,14 @@ error_paint(bool errnoflag, bool iserr, const char *fmt, va_list ap) * the errno message string. */ static void -error_print(bool errnoflag, const char *fmt, va_list ap) +error_file(FILE *fp, bool errnoflag, const char *fmt, va_list ap) { - fprintf(stderr, "%s: ", progname); - vfprintf(stderr, fmt, ap); + fprintf(fp, "%s: ", progname); + vfprintf(fp, fmt, ap); if (errnoflag) - fprintf(stderr, ": %s", strerror(errno)); - fputs("\n", stderr); + fprintf(fp, ": %s", strerror(errno)); + fputs("\n", fp); } /* @@ -85,7 +85,7 @@ error_cfg(bool errnoflag, bool iserr, const char *fmt, va_list ap) return; endwin(); - error_print(errnoflag, fmt, ap); + error_file(stderr, errnoflag, fmt, ap); exit(1); } @@ -96,7 +96,7 @@ error_cfg(bool errnoflag, bool iserr, const char *fmt, va_list ap) static void error_stderr(bool errnoflag, bool iserr, const char *fmt, va_list ap) { - error_print(errnoflag, fmt, ap); + error_file(stderr, errnoflag, fmt, ap); if (iserr) exit(1); } @@ -121,12 +121,35 @@ error_doit(bool errnoflag, bool iserr, const char *fmt, va_list ap) } } +/* Outputs a message if debugging is turned on. */ +void +debug(const char *fmt, ...) +{ + va_list ap; + + if (error_fp == NULL) + return; + + va_start(ap, fmt); + error_file(error_fp, false, fmt, ap); + va_end(ap); +} + void error_init(int type) { error_type = type; } +void +error_open(void) +{ + if (error_fp != NULL) + return; + if ((error_fp = fopen(ERROR_LOG_PATH, "w")) == NULL) + error_file(stderr, true, "%s: fopen", ERROR_LOG_PATH); +} + /* Outputs a fatal message with the errno message string appended. */ void fatal(const char *fmt, ...) diff --git a/error.h b/error.h index 01eb7a8..caa3716 100644 --- a/error.h +++ b/error.h @@ -17,11 +17,15 @@ #ifndef ERROR_H #define ERROR_H +#define ERROR_LOG_PATH "vitunes-debug.log" + #define ERROR_STDERR 0 #define ERROR_CFG 1 #define ERROR_PAINT 2 +void debug(const char *, ...); void error_init(int); +void error_open(void); void fatal(const char *, ...); void fatalx(const char *, ...); void info(const char *, ...); diff --git a/vitunes.c b/vitunes.c index c9be9be..b91b4a4 100644 --- a/vitunes.c +++ b/vitunes.c @@ -537,6 +537,7 @@ handle_switches(int argc, char *argv[]) break; case 'v': + error_open(); break; case 'h': From 14605edf72869b9b35b967c32f01e361a88711ec Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:25:39 +0000 Subject: [PATCH 14/42] Zap DEBUG macro. Which, in my opinion, is a good thing because, as a consequence, there's less pre-processor goo in the tree. --- Makefile | 2 +- commands.c | 1 - debug.h | 50 ----------------------------------------------- keybindings.c | 1 - medialib.c | 1 - meta_info.c | 1 - player.c | 1 - players/mplayer.c | 4 ---- playlist.c | 1 - str2argv.c | 1 - uinterface.c | 1 - vitunes.c | 9 --------- 12 files changed, 1 insertion(+), 72 deletions(-) delete mode 100644 debug.h diff --git a/Makefile b/Makefile index c6aa7b1..67ec861 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ vitunes: $(OBJS) $(CC) $(CFLAGS) $< debug: - make CDEBUG="-DDEBUG -g" + make CDEBUG="-g" clean: rm -f *.o diff --git a/commands.c b/commands.c index 3979ecb..57a4f26 100644 --- a/commands.c +++ b/commands.c @@ -18,7 +18,6 @@ #include #include "commands.h" -#include "debug.h" #include "enums.h" #include "error.h" #include "keybindings.h" diff --git a/debug.h b/debug.h deleted file mode 100644 index 45a9cd8..0000000 --- a/debug.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010, 2011 Ryan Flannery - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef DEBUG_H -#define DEBUG_H - -#include - -/* log file for debugging */ -extern FILE *debug_log; - -#ifdef DEBUG - -/* debug file logger that goes to the file opened in vitunes.c */ -#define DFLOG(format, args...) \ - fprintf(debug_log, "%s.%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ - fprintf(debug_log, format, ## args); \ - fprintf(debug_log, "\n"); \ - fflush(debug_log); - -/* console logger. goes to stdout. doesn't work well in curses */ -#define DCLOG(format, args...) \ - printf("%d: ", __LINE__); \ - printf(format, ## args); \ - printf("\n"); \ - fflush(stdout); - - -#else - -#define DFLOG(format, args...) 0; -#define DCLOG(format, args...) 0; - -#endif - - -#endif diff --git a/keybindings.c b/keybindings.c index 82adf78..e2a8d43 100644 --- a/keybindings.c +++ b/keybindings.c @@ -20,7 +20,6 @@ #include "commands.h" #include "compat.h" -#include "debug.h" #include "enums.h" #include "error.h" #include "keybindings.h" diff --git a/medialib.c b/medialib.c index 26f8a64..884848a 100644 --- a/medialib.c +++ b/medialib.c @@ -25,7 +25,6 @@ #include #include "compat.h" -#include "debug.h" #include "error.h" #include "medialib.h" #include "meta_info.h" diff --git a/meta_info.c b/meta_info.c index cda0744..6e08b6e 100644 --- a/meta_info.c +++ b/meta_info.c @@ -29,7 +29,6 @@ #include #include "compat.h" -#include "debug.h" #include "enums.h" #include "error.h" #include "meta_info.h" diff --git a/player.c b/player.c index 7419680..ff3a314 100644 --- a/player.c +++ b/player.c @@ -19,7 +19,6 @@ #include #include "compat.h" -#include "debug.h" #include "error.h" #include "paint.h" #include "player.h" diff --git a/players/mplayer.c b/players/mplayer.c index d75cfdf..2b345a8 100644 --- a/players/mplayer.c +++ b/players/mplayer.c @@ -34,10 +34,6 @@ #include "mplayer_conf.h" #include "player_utils.h" -#ifdef DEBUG -# include "../debug.h" -#endif - /* callback functions */ void (*mplayer_callback_playnext)(void) = NULL; void (*mplayer_callback_notice)(char *, ...) = NULL; diff --git a/playlist.c b/playlist.c index b2291b5..7791a62 100644 --- a/playlist.c +++ b/playlist.c @@ -27,7 +27,6 @@ #include #include "compat.h" -#include "debug.h" #include "error.h" #include "meta_info.h" #include "playlist.h" diff --git a/str2argv.c b/str2argv.c index 5457ac3..d6bc4aa 100644 --- a/str2argv.c +++ b/str2argv.c @@ -20,7 +20,6 @@ #include #include "compat.h" -#include "debug.h" #include "error.h" #include "str2argv.h" diff --git a/uinterface.c b/uinterface.c index 2a7cfdb..72b8a50 100644 --- a/uinterface.c +++ b/uinterface.c @@ -27,7 +27,6 @@ #include #include "compat.h" -#include "debug.h" #include "enums.h" #include "error.h" #include "uinterface.h" diff --git a/vitunes.c b/vitunes.c index b91b4a4..25293ae 100644 --- a/vitunes.c +++ b/vitunes.c @@ -28,7 +28,6 @@ #include "commands.h" #include "compat.h" -#include "debug.h" #include "ecmd.h" #include "enums.h" #include "error.h" @@ -67,9 +66,6 @@ volatile sig_atomic_t VSIG_PLAYER_MONITOR = 0; /* 1 = update player stats */ enum { EXIT_NORMAL, BAD_PLAYER }; volatile sig_atomic_t QUIT_CAUSE = EXIT_NORMAL; -/* used with -DDEBUG */ -FILE *debug_log; - /***************************************************************************** * GLOBALS, LOCAL @@ -122,11 +118,6 @@ main(int argc, char *argv[]) /* error messages go to stderr before the user interface is set up */ error_init(ERROR_STDERR); -#ifdef DEBUG - if ((debug_log = fopen("vitunes-debug.log", "w")) == NULL) - fatal("failed to open debug log"); -#endif - /*------------------------------------------------------------------------ * build paths names needed by vitunes & handle switches *----------------------------------------------------------------------*/ From 73c50968b683df2f21746d2efc9addc532a7da9a Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 17:56:52 +0000 Subject: [PATCH 15/42] Use new error functions. --- commands.c | 120 +++++++++++++++++++++++++------------------------- keybindings.c | 56 +++++++++++------------ vitunes.c | 2 +- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/commands.c b/commands.c index 57a4f26..2d5dc2f 100644 --- a/commands.c +++ b/commands.c @@ -255,7 +255,7 @@ cmd_quit(int argc, char *argv[]) bool forced; if (argc != 1) { - paint_error("usage: q[!]"); + fatalx("usage: q[!]"); return 1; } @@ -267,7 +267,7 @@ cmd_quit(int argc, char *argv[]) int i; for (i = 0; i < mdb.nplaylists; i++) { if (mdb.playlists[i]->needs_saving) { - paint_error("there are playlists with unsaved changes. use \"q!\" to force."); + fatalx("there are playlists with unsaved changes. use \"q!\" to force."); return 2; } } @@ -284,7 +284,7 @@ cmd_write(int argc, char *argv[]) bool forced; if (argc > 2) { - paint_error("usage: w[!] [name]"); + fatalx("usage: w[!] [name]"); return 1; } @@ -295,13 +295,13 @@ cmd_write(int argc, char *argv[]) /* can't save library or filter results */ if (viewing_playlist == mdb.library || viewing_playlist == mdb.filter_results) { - paint_error("use \"w name\" when saving pseudo-playlists like library/filter"); + fatalx("use \"w name\" when saving pseudo-playlists like library/filter"); return 2; } /* can't save a new playlist that has no name */ if (viewing_playlist->filename == NULL) { - paint_error("use \"w name\" for new playlists"); + fatalx("use \"w name\" for new playlists"); return 3; } @@ -309,7 +309,7 @@ cmd_write(int argc, char *argv[]) playlist_save(viewing_playlist); viewing_playlist->needs_saving = false; paint_library(); - paint_message("\"%s\" %d songs written", + infox("\"%s\" %d songs written", viewing_playlist->filename, viewing_playlist->nfiles); } else { /* "save as" */ @@ -332,7 +332,7 @@ cmd_write(int argc, char *argv[]) } if (will_clobber && !forced) { - paint_error("playlist with that name exists (use \"w!\" to overwrite)"); + fatalx("playlist with that name exists (use \"w!\" to overwrite)"); free(filename); return 4; } @@ -360,7 +360,7 @@ cmd_write(int argc, char *argv[]) viewing_playlist->needs_saving = false; paint_library(); - paint_message("\"%s\" %d songs written", + infox("\"%s\" %d songs written", filename, viewing_playlist->nfiles); free(filename); @@ -373,7 +373,7 @@ int cmd_mode(int argc, char *argv[]) { if (argc != 2) { - paint_error("usage: mode [ linear | loop | random ]"); + fatalx("usage: mode [ linear | loop | random ]"); return 1; } @@ -384,11 +384,11 @@ cmd_mode(int argc, char *argv[]) else if (strcasecmp(argv[1], "random") == 0) player_info.mode = MODE_RANDOM; else { - paint_error("invalid mode \"%s\". must be one of: linear, loop, or random", argv[1]); + fatalx("invalid mode \"%s\". must be one of: linear, loop, or random", argv[1]); return 2; } - paint_message("mode changed to: %s", argv[1]); + infox("mode changed to: %s", argv[1]); return 0; } @@ -400,7 +400,7 @@ cmd_new(int argc, char *argv[]) char *filename; if (argc > 2) { - paint_error("usage: new [name]"); + fatalx("usage: new [name]"); return 1; } @@ -414,7 +414,7 @@ cmd_new(int argc, char *argv[]) int i; for (i = 0; i < mdb.nplaylists; i++) { if (strcmp(mdb.playlists[i]->name, argv[1]) == 0) { - paint_error("playlist \"%s\" already exists.", argv[1]); + fatalx("playlist \"%s\" already exists.", argv[1]); return 2; } } @@ -439,7 +439,7 @@ cmd_new(int argc, char *argv[]) /* redraw */ paint_library(); - paint_message("playlist \"%s\" added", name); + infox("playlist \"%s\" added", name); return 0; } @@ -453,7 +453,7 @@ cmd_filter(int argc, char *argv[]) int i; if (argc == 1) { - paint_error("usage: filter[!] token [token2 ...]"); + fatalx("usage: filter[!] token [token2 ...]"); return 1; } @@ -493,13 +493,13 @@ cmd_sort(int argc, char *argv[]) const char *errmsg; if (argc != 2) { - paint_error("usage: sort "); + fatalx("usage: sort "); return 1; } /* setup global sort description */ if (mi_sort_set(argv[1], &errmsg) != 0) { - paint_error("%s: bad sort description: %s", argv[0], errmsg); + fatalx("%s: bad sort description: %s", argv[0], errmsg); return 2; } @@ -528,13 +528,13 @@ cmd_display(int argc, char *argv[]) const char *errmsg; if (argc != 2) { - paint_error("usage: display [ reset | show | ]"); + fatalx("usage: display [ reset | show | ]"); return 1; } /* show existng display? */ if (strcasecmp(argv[1], "show") == 0) { - paint_message(":display %s", mi_display_tostr()); + infox(":display %s", mi_display_tostr()); return 0; } @@ -550,7 +550,7 @@ cmd_display(int argc, char *argv[]) /* if reached here, setup global display description */ if (mi_display_set(argv[1], &errmsg) != 0) { - paint_error("%s: bad display description: %s", argv[0], errmsg); + fatalx("%s: bad display description: %s", argv[0], errmsg); return 1; } @@ -568,21 +568,21 @@ cmd_color(int argc, char *argv[]) int i_item, i_fg, i_bg, j; if (argc != 2) { - paint_error("usage: %s ITEM=FG,BG", argv[0]); + fatalx("usage: %s ITEM=FG,BG", argv[0]); return 1; } /* extract item and foreground/background colors */ item = argv[1]; if ((fg = strchr(item, '=')) == NULL) { - paint_error("usage: %s ITEM=FG,BG", argv[0]); + fatalx("usage: %s ITEM=FG,BG", argv[0]); return 2; } *fg = '\0'; fg++; if ((bg = strchr(fg, ',')) == NULL) { - paint_error("usage: %s ITEM=FG,BG", argv[0]); + fatalx("usage: %s ITEM=FG,BG", argv[0]); return 3; } *bg = '\0'; @@ -590,17 +590,17 @@ cmd_color(int argc, char *argv[]) /* convert all */ if ((i_item = paint_str2item(item)) < 0) { - paint_error("invalid item '%s'", item); + fatalx("invalid item '%s'", item); return 4; } if ((i_fg = paint_str2color(fg)) == -2) { - paint_error("invalid foreground color '%s'", fg); + fatalx("invalid foreground color '%s'", fg); return 5; } if ((i_bg = paint_str2color(bg)) == -2) { - paint_error("invalid background color '%s'", bg); + fatalx("invalid background color '%s'", bg); return 6; } @@ -632,7 +632,7 @@ cmd_set(int argc, char *argv[]) bool player_is_setup; if (argc != 2) { - paint_error("usage: %s =", argv[0]); + fatalx("usage: %s =", argv[0]); return 1; } @@ -643,7 +643,7 @@ cmd_set(int argc, char *argv[]) /* extract property and value */ property = argv[1]; if ((value = strchr(property, '=')) == NULL) { - paint_error("usage: %s =", argv[0]); + fatalx("usage: %s =", argv[0]); return 2; } *value = '\0'; @@ -659,7 +659,7 @@ cmd_set(int argc, char *argv[]) /* validate and convert width user provided */ new_width = (int)strtonum(value, 1, max_w, &err); if (err != NULL) { - paint_error("%s %s: bad width: '%s' %s", + fatalx("%s %s: bad width: '%s' %s", argv[0], property, value, err); return 3; } @@ -674,7 +674,7 @@ cmd_set(int argc, char *argv[]) } else if (strcasecmp(property, "lhide") == 0) { if (str2bool(value, &tf) < 0) { - paint_error("%s %s: value must be boolean", + fatalx("%s %s: value must be boolean", argv[0], property); return 4; } @@ -685,40 +685,40 @@ cmd_set(int argc, char *argv[]) if (player_is_setup && ui_is_init()) { ui_clear(); paint_all(); - paint_message("library window hidden"); + infox("library window hidden"); } } else { if (ui.library->cwin == NULL) ui_unhide_library(); if (player_is_setup && ui_is_init()) paint_all(); - paint_message("library window un-hidden"); + infox("library window un-hidden"); } } else if (strcasecmp(property, "match-fname") == 0) { if (str2bool(value, &tf) < 0) { - paint_error("%s %s: value must be boolean", + fatalx("%s %s: value must be boolean", argv[0], property); return 5; } mi_query_match_filename = tf; if (mi_query_match_filename) - paint_message("filenames will be matched against"); + infox("filenames will be matched against"); else - paint_message("filenames will NOT be matched against"); + infox("filenames will NOT be matched against"); } else if (strcasecmp(property, "save-sorts") == 0) { if (str2bool(value, &tf) < 0) { - paint_error("%s %s: value must be boolean", + fatalx("%s %s: value must be boolean", argv[0], property); return 6; } sorts_need_saving = tf; if (sorts_need_saving) - paint_message("changing sort will be prompted for saving"); + infox("changing sort will be prompted for saving"); else - paint_message("changing sort will NOT be prompted for saving"); + infox("changing sort will NOT be prompted for saving"); } else { - paint_error("%s: unknown property '%s'", argv[0], property); + fatalx("%s: unknown property '%s'", argv[0], property); return 7; } @@ -729,7 +729,7 @@ int cmd_reload(int argc, char *argv[]) { if (argc != 2) { - paint_error("usage: %s [ db | conf ]", argv[0]); + fatalx("usage: %s [ db | conf ]", argv[0]); return 1; } @@ -764,9 +764,9 @@ cmd_reload(int argc, char *argv[]) } else if (strcasecmp(argv[1], "conf") == 0) { load_config(); - paint_message("configuration reloaded"); + infox("configuration reloaded"); } else { - paint_error("usage: %s [ db | conf ]", argv[0]); + fatalx("usage: %s [ db | conf ]", argv[0]); return 2; } @@ -780,23 +780,23 @@ cmd_bind(int argc, char *argv[]) KeyCode code; if (argc < 3 || argc > 4) { - paint_error("usage: %s ", argv[0]); + fatalx("usage: %s ", argv[0]); return 1; } if (!kb_str2action(argv[1], &action)) { - paint_error("Unknown action '%s'", argv[1]); + fatalx("Unknown action '%s'", argv[1]); return 1; } if (argc == 3) { if ((code = kb_str2keycode(argv[2])) < 0) { - paint_error("Invalid keycode '%s'", argv[2]); + fatalx("Invalid keycode '%s'", argv[2]); return 1; } } else { if ((code = kb_str2keycode2(argv[2], argv[3])) < 0) { - paint_error("Invalid keycode '%s'", argv[2]); + fatalx("Invalid keycode '%s'", argv[2]); return 1; } } @@ -823,7 +823,7 @@ cmd_unbind(int argc, char *argv[]) kb_unbind_action(action); return 0; } else { - paint_error("Unknown action '%s'", argv[2]); + fatalx("Unknown action '%s'", argv[2]); return 1; } } @@ -831,7 +831,7 @@ cmd_unbind(int argc, char *argv[]) /* unbind key case, no control ("unbind key X") */ if (argc == 3 && strcasecmp(argv[1], "key") == 0) { if ((key = kb_str2keycode(argv[2])) < 0) { - paint_error("Invalid keycode '%s'", argv[2]); + fatalx("Invalid keycode '%s'", argv[2]); return 1; } @@ -842,7 +842,7 @@ cmd_unbind(int argc, char *argv[]) /* unbind key case, with control ("unbind key control X") */ if (argc == 4 && strcasecmp(argv[1], "key") == 0) { if ((key = kb_str2keycode2(argv[2], argv[3])) < 0) { - paint_error("Invalid keycode '%s %s'", argv[2], argv[3]); + fatalx("Invalid keycode '%s %s'", argv[2], argv[3]); return 1; } @@ -850,7 +850,7 @@ cmd_unbind(int argc, char *argv[]) return 0; } - paint_error("usage: unbind [* | action | key ]"); + fatalx("usage: unbind [* | action | key ]"); return 1; } @@ -863,12 +863,12 @@ cmd_toggle(int argc, char *argv[]) int registr; if (argc < 3) { - paint_error("usage: %s / ...", argv[0]); + fatalx("usage: %s / ...", argv[0]); return 1; } if (strlen(argv[1]) != 1) { - paint_error("error: register name must be a single letter (in [a-zA-Z])"); + fatalx("error: register name must be a single letter (in [a-zA-Z])"); return 1; } @@ -876,7 +876,7 @@ cmd_toggle(int argc, char *argv[]) if (!( ('a' <= registr && registr <= 'z') || ('A' <= registr && registr <= 'Z'))) { - paint_error("error: invalid register name. Must be one of [a-zA-Z]"); + fatalx("error: invalid register name. Must be one of [a-zA-Z]"); return 1; } @@ -894,7 +894,7 @@ cmd_playlist(int argc, char *argv[]) int idx = -1; if (argc != 2) { - paint_error("usage: playlist "); + fatalx("usage: playlist "); return 1; } @@ -914,17 +914,17 @@ cmd_playlist(int argc, char *argv[]) setup_viewing_playlist(mdb.playlists[idx]); ui.active = ui.playlist; paint_all(); - paint_message("jumped to playlist: %s", mdb.playlists[idx]->name); + infox("jumped to playlist: %s", mdb.playlists[idx]->name); return 0; } if(idx == -1) { - paint_error("no match for: %s", argv[1]); + fatalx("no match for: %s", argv[1]); return 0; } if(idx == -2) - paint_error("no unique match for: %s", argv[1]); + fatalx("no unique match for: %s", argv[1]); return 0; } @@ -941,7 +941,7 @@ cmd_execute(char *cmd) int i; if (str2argv(cmd, &argc, &argv, &errmsg) != 0) { - paint_error("parse error: %s in '%s'", errmsg, cmd); + fatalx("parse error: %s in '%s'", errmsg, cmd); return; } @@ -958,9 +958,9 @@ cmd_execute(char *cmd) if (found && num_matches == 1) (CommandPath[found_idx].func)(argc, argv); else if (num_matches > 1) - paint_error("Ambiguous abbreviation '%s'", argv[0]); + fatalx("Ambiguous abbreviation '%s'", argv[0]); else - paint_error("Unknown commands '%s'", argv[0]); + fatalx("Unknown commands '%s'", argv[0]); argv_free(&argc, &argv); } diff --git a/keybindings.c b/keybindings.c index e2a8d43..3529acf 100644 --- a/keybindings.c +++ b/keybindings.c @@ -845,7 +845,7 @@ kba_search(KbaArgs a) /* set the global query description and the search direction */ if (str2argv(search_phrase, &argc, &argv, &errmsg) != 0) { - paint_error("parse error: %s in '%s'", errmsg, search_phrase); + fatalx("parse error: %s in '%s'", errmsg, search_phrase); free(search_phrase); return; } @@ -924,7 +924,7 @@ kba_search_find(KbaArgs a) /* found one, jump to it */ if (matches) { if (msg != NULL) - paint_message("%s", msg); + infox("%s", msg); gnum_set(idx + 1); foo = get_dummy_args(); @@ -935,7 +935,7 @@ kba_search_find(KbaArgs a) } } - paint_error("Pattern not found: %s", mi_query_getraw()); + fatalx("Pattern not found: %s", mi_query_getraw()); } @@ -943,7 +943,7 @@ void kba_visual(KbaArgs a UNUSED) { if (ui.active == ui.library) { - paint_message("No visual mode in library window. Sorry."); + infox("No visual mode in library window. Sorry."); return; } @@ -1018,7 +1018,7 @@ kba_cut(KbaArgs a UNUSED) } if (start >= ui.active->nrows) { - paint_message("nothing to delete here!"); + infox("nothing to delete here!"); return; } @@ -1033,11 +1033,11 @@ kba_cut(KbaArgs a UNUSED) * while drunk. */ if (end != start + 1) { - paint_error("cannot delete multiple playlists"); + fatalx("cannot delete multiple playlists"); return; } if (p == mdb.library || p == mdb.filter_results) { - paint_error("cannot delete pseudo-playlists like LIBRARY or FILTER"); + fatalx("cannot delete pseudo-playlists like LIBRARY or FILTER"); return; } @@ -1046,12 +1046,12 @@ kba_cut(KbaArgs a UNUSED) /* make sure user wants this */ if (user_get_yesno(warning, &response) != 0) { - paint_message("delete of '%s' cancelled", p->name); + infox("delete of '%s' cancelled", p->name); free(warning); return; } if (response != 1) { - paint_message("playlist '%s' not deleted", p->name); + infox("playlist '%s' not deleted", p->name); free(warning); return; } @@ -1079,7 +1079,7 @@ kba_cut(KbaArgs a UNUSED) /* can't delete from library */ if (viewing_playlist == mdb.library) { - paint_error("cannot delete from library"); + fatalx("cannot delete from library"); return; } @@ -1105,7 +1105,7 @@ kba_cut(KbaArgs a UNUSED) /* redraw */ paint_playlist(); paint_library(); - paint_message("%d fewer files.", end - start); + infox("%d fewer files.", end - start); } void @@ -1117,12 +1117,12 @@ kba_yank(KbaArgs a UNUSED) int n; if (ui.active == ui.library) { - paint_error("cannot yank in library window"); + fatalx("cannot yank in library window"); return; } if (viewing_playlist->nfiles == 0) { - paint_error("nothing to yank!"); + fatalx("nothing to yank!"); return; } @@ -1188,7 +1188,7 @@ kba_yank(KbaArgs a UNUSED) paint_playlist(); /* notify user # of rows yanked */ - paint_message("Yanked %d files.", end - start); + infox("Yanked %d files.", end - start); } void @@ -1198,7 +1198,7 @@ kba_paste(KbaArgs a) int start = 0; if (_yank_buffer.nfiles == 0) { - paint_error("nothing to paste"); + fatalx("nothing to paste"); return; } @@ -1212,7 +1212,7 @@ kba_paste(KbaArgs a) /* can't alter library */ if (p == mdb.library) { - paint_error("Cannot alter %s pseudo-playlist", mdb.library->name); + fatalx("Cannot alter %s pseudo-playlist", mdb.library->name); return; } @@ -1256,9 +1256,9 @@ kba_paste(KbaArgs a) paint_library(); paint_playlist(); if (ui.active == ui.library) - paint_message("Pasted %d files to '%s'", _yank_buffer.nfiles, p->name); + infox("Pasted %d files to '%s'", _yank_buffer.nfiles, p->name); else - paint_message("Pasted %d files.", _yank_buffer.nfiles); + infox("Pasted %d files.", _yank_buffer.nfiles); } @@ -1266,14 +1266,14 @@ void kba_undo(KbaArgs a UNUSED) { if (ui.active == ui.library) { - paint_message("Cannot undo in library window."); + infox("Cannot undo in library window."); return; } if (playlist_undo(viewing_playlist) != 0) - paint_message("Nothing to undo."); + infox("Nothing to undo."); else - paint_message("Undo successfull."); + infox("Undo successfull."); /* TODO more informative message like in vim */ @@ -1288,14 +1288,14 @@ void kba_redo(KbaArgs a UNUSED) { if (ui.active == ui.library) { - paint_message("Cannot redo in library window."); + infox("Cannot redo in library window."); return; } if (playlist_redo(viewing_playlist) != 0) - paint_message("Nothing to redo."); + infox("Nothing to redo."); else - paint_message("Redo successfull."); + infox("Redo successfull."); /* TODO */ @@ -1381,7 +1381,7 @@ kba_show_file_info(KbaArgs a UNUSED) return; if (ui.active->crow >= ui.active->nrows) { - paint_message("no file here"); + infox("no file here"); return; } @@ -1411,7 +1411,7 @@ kba_load_playlist(KbaArgs a UNUSED) } else { /* play song */ if (ui.active->crow >= ui.active->nrows) { - paint_message("no file here"); + infox("no file here"); return; } player_set_queue(viewing_playlist, ui.active->voffset + ui.active->crow); @@ -1437,7 +1437,7 @@ kba_play(KbaArgs a UNUSED) } else { /* play song */ if (ui.active->crow >= ui.active->nrows) { - paint_message("no file here"); + infox("no file here"); return; } player_set_queue(viewing_playlist, ui.active->voffset + ui.active->crow); @@ -1581,7 +1581,7 @@ kba_toggle(KbaArgs a) /* get the command to execute */ if ((t = toggle_get(registr)) == NULL) { - paint_error("No toggle list in register %c (%i).", registr, registr); + fatalx("No toggle list in register %c (%i).", registr, registr); return; } diff --git a/vitunes.c b/vitunes.c index 25293ae..a812271 100644 --- a/vitunes.c +++ b/vitunes.c @@ -362,7 +362,7 @@ process_signals() paint_playlist(); } if (prev_volume != player.volume()) { - paint_message("volume: %3.0f%%", player.volume()); + infox("volume: %3.0f%%", player.volume()); prev_volume = player.volume(); } From 8e153b8e2397f8fcd7e0577bde49621d7b08e9ca Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 18:05:00 +0000 Subject: [PATCH 16/42] Sprinkle some const. --- paint.c | 4 ++-- paint.h | 4 ++-- player.c | 2 +- player.h | 6 +++--- players/gstplayer.c | 6 +++--- players/gstplayer.h | 14 +++++++------- players/mplayer.c | 12 ++++++------ players/mplayer.h | 6 +++--- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/paint.c b/paint.c index c257857..d343739 100644 --- a/paint.c +++ b/paint.c @@ -569,7 +569,7 @@ paint_all() * identical to that of printf(3) (vwprintw(3) actually). */ void -paint_error(char *fmt, ...) +paint_error(const char *fmt, ...) { va_list ap; @@ -591,7 +591,7 @@ paint_error(char *fmt, ...) * is identical to that of printf(3) (vwprintw(3) actually). */ void -paint_message(char *fmt, ...) +paint_message(const char *fmt, ...) { va_list ap; diff --git a/paint.h b/paint.h index 8be6882..c765891 100644 --- a/paint.h +++ b/paint.h @@ -67,8 +67,8 @@ extern bool showing_file_info; void paint_playlist_file_info(const meta_info *m); /* routines for painting errors/messages in the command/status window */ -void paint_error(char *fmt, ...); -void paint_message(char *fmt, ...); +void paint_error(const char *fmt, ...); +void paint_message(const char *fmt, ...); /* for setting up and working with the colors */ void paint_setup_colors(); diff --git a/player.c b/player.c index ff3a314..d0a5b05 100644 --- a/player.c +++ b/player.c @@ -41,7 +41,7 @@ player_info_t player_info; static void callback_playnext() { player_skip_song(1); } static void -callback_fatal(char *fmt, ...) +callback_fatal(const char *fmt, ...) { va_list ap; diff --git a/player.h b/player.h index b4457cb..e05a40b 100644 --- a/player.h +++ b/player.h @@ -86,9 +86,9 @@ typedef struct { /* callback functions */ void (*set_callback_playnext)(void (*f)(void)); - void (*set_callback_notice)(void (*f)(char *, ...)); - void (*set_callback_error)(void (*f)(char *, ...)); - void (*set_callback_fatal)(void (*f)(char *, ...)); + void (*set_callback_notice)(void (*f)(const char *, ...)); + void (*set_callback_error)(void (*f)(const char *, ...)); + void (*set_callback_fatal)(void (*f)(const char *, ...)); /* monitor function */ void (*monitor)(void); diff --git a/players/gstplayer.c b/players/gstplayer.c index e5a3c67..b29e615 100644 --- a/players/gstplayer.c +++ b/players/gstplayer.c @@ -270,17 +270,17 @@ gstplayer_set_callback_playnext(void (*f)(void)) gplayer.playnext_cb = f; } void -gstplayer_set_callback_notice(void (*f)(char *, ...)) +gstplayer_set_callback_notice(void (*f)(const char *, ...)) { gplayer.notice_cb = f; } void -gstplayer_set_callback_error(void (*f)(char *, ...)) +gstplayer_set_callback_error(void (*f)(const char *, ...)) { gplayer.error_cb = f; } void -gstplayer_set_callback_fatal(void (*f)(char *, ...)) +gstplayer_set_callback_fatal(void (*f)(const char *, ...)) { gplayer.fatal_cb = f; } diff --git a/players/gstplayer.h b/players/gstplayer.h index b23c8f7..0972644 100644 --- a/players/gstplayer.h +++ b/players/gstplayer.h @@ -34,10 +34,10 @@ typedef struct { bool paused; bool about_to_finish; /* callback functions */ - void (*playnext_cb)(void); - void (*notice_cb)(char *, ...); - void (*error_cb)(char *, ...); - void (*fatal_cb)(char *, ...); + void (*playnext_cb)(void); + void (*notice_cb)(const char *, ...); + void (*error_cb)(const char *, ...); + void (*fatal_cb)(const char *, ...); /* backend data */ GstElement *player; @@ -60,9 +60,9 @@ bool gstplayer_is_playing(); bool gstplayer_is_paused(); void gstplayer_set_callback_playnext(void (*f)(void)); -void gstplayer_set_callback_notice(void (*f)(char *, ...)); -void gstplayer_set_callback_error(void (*f)(char *, ...)); -void gstplayer_set_callback_fatal(void (*f)(char *, ...)); +void gstplayer_set_callback_notice(void (*f)(const char *, ...)); +void gstplayer_set_callback_error(void (*f)(const char *, ...)); +void gstplayer_set_callback_fatal(void (*f)(const char *, ...)); void gstplayer_monitor(); diff --git a/players/mplayer.c b/players/mplayer.c index 2b345a8..a2a3384 100644 --- a/players/mplayer.c +++ b/players/mplayer.c @@ -36,9 +36,9 @@ /* callback functions */ void (*mplayer_callback_playnext)(void) = NULL; -void (*mplayer_callback_notice)(char *, ...) = NULL; -void (*mplayer_callback_error)(char *, ...) = NULL; -void (*mplayer_callback_fatal)(char *, ...) = NULL; +void (*mplayer_callback_notice)(const char *, ...) = NULL; +void (*mplayer_callback_error)(const char *, ...) = NULL; +void (*mplayer_callback_fatal)(const char *, ...) = NULL; /* record keeping */ @@ -323,19 +323,19 @@ mplayer_set_callback_playnext(void (*f)(void)) } void -mplayer_set_callback_notice(void (*f)(char *, ...)) +mplayer_set_callback_notice(void (*f)(const char *, ...)) { mplayer_callback_notice = f; } void -mplayer_set_callback_error(void (*f)(char *, ...)) +mplayer_set_callback_error(void (*f)(const char *, ...)) { mplayer_callback_error = f; } void -mplayer_set_callback_fatal(void (*f)(char *, ...)) +mplayer_set_callback_fatal(void (*f)(const char *, ...)) { mplayer_callback_fatal = f; } diff --git a/players/mplayer.h b/players/mplayer.h index d8f3685..4d86fef 100644 --- a/players/mplayer.h +++ b/players/mplayer.h @@ -33,9 +33,9 @@ bool mplayer_is_playing(); bool mplayer_is_paused(); void mplayer_set_callback_playnext(void (*f)(void)); -void mplayer_set_callback_notice(void (*f)(char *, ...)); -void mplayer_set_callback_error(void (*f)(char *, ...)); -void mplayer_set_callback_fatal(void (*f)(char *, ...)); +void mplayer_set_callback_notice(void (*f)(const char *, ...)); +void mplayer_set_callback_error(void (*f)(const char *, ...)); +void mplayer_set_callback_fatal(void (*f)(const char *, ...)); void mplayer_monitor(); From 431a68d892a07e7bf99f34e9001221a41d50f46b Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 18:31:02 +0000 Subject: [PATCH 17/42] Take advantage of the -I compiler option. From now on, there's no need to specify the relative path of local header files. --- Makefile | 10 +++++----- compat.c | 6 +++--- player.c | 4 ++-- players/gstplayer.c | 4 ++-- players/mplayer.c | 2 +- players/player_utils.c | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 67ec861..155124d 100644 --- a/Makefile +++ b/Makefile @@ -11,9 +11,10 @@ LDEPS=$(TAGLIB_LIBS) $(GSTREAMER_LIBS) ODEPS=$(GSTREAMER_OBJS) # build variables -CC ?= /usr/bin/cc -CFLAGS += -c -std=c89 -Wall -Wextra -Wno-unused-value $(CDEBUG) $(CDEPS) -LIBS += -lm -lncurses -lutil $(LDEPS) +CC ?= /usr/bin/cc +CPPFLAGS += -I. -Icompat -Iplayers -iquote. +CFLAGS += -c -std=c89 -Wall -Wextra -Wno-unused-value $(CDEBUG) $(CDEPS) +LIBS += -lm -lncurses -lutil $(LDEPS) # object files OBJS=commands.o compat.o ecmd.o \ @@ -39,7 +40,7 @@ vitunes: $(OBJS) $(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) .c.o: - $(CC) $(CFLAGS) $< + $(CC) $(CPPFLAGS) $(CFLAGS) $< debug: make CDEBUG="-g" @@ -93,4 +94,3 @@ reports: report.mandoc report.cppcheck report.scan-build @figlet "Static Checks Complete" cat report.mandoc cat report.cppcheck - diff --git a/compat.c b/compat.c index 0e2d9f0..8cd144d 100644 --- a/compat.c +++ b/compat.c @@ -17,7 +17,7 @@ #include "compat.h" #ifdef COMPAT_NEED_FPARSELN -# include "compat/fparseln.c" +# include "fparseln.c" #endif #ifdef COMPAT_NEED_OPTRESET @@ -25,10 +25,10 @@ #endif #ifdef COMPAT_NEED_STRLCAT -# include "compat/strlcat.c" +# include "strlcat.c" #endif #ifdef COMPAT_NEED_STRTONUM -# include "compat/strtonum.c" +# include "strtonum.c" #endif diff --git a/player.c b/player.c index d0a5b05..e5a1685 100644 --- a/player.c +++ b/player.c @@ -27,9 +27,9 @@ #include "vitunes.h" /* "static" backends (those that aren't dynamically loaded) */ -#include "players/mplayer.h" +#include "mplayer.h" #if defined(ENABLE_GSTREAMER) -# include "players/gstplayer.h" +# include "gstplayer.h" #endif /* globals */ diff --git a/players/gstplayer.c b/players/gstplayer.c index b29e615..4d60c42 100644 --- a/players/gstplayer.c +++ b/players/gstplayer.c @@ -22,8 +22,8 @@ */ #include "gstplayer.h" -#include "../player.h" -#include "../vitunes.h" +#include "player.h" +#include "vitunes.h" /* player data */ static gst_player gplayer; diff --git a/players/mplayer.c b/players/mplayer.c index a2a3384..04d8540 100644 --- a/players/mplayer.c +++ b/players/mplayer.c @@ -29,7 +29,7 @@ #include #include -#include "../compat.h" +#include "compat.h" #include "mplayer.h" #include "mplayer_conf.h" #include "player_utils.h" diff --git a/players/player_utils.c b/players/player_utils.c index 541eaf0..78df94e 100644 --- a/players/player_utils.c +++ b/players/player_utils.c @@ -21,7 +21,7 @@ #include #include -#include "../compat.h" +#include "compat.h" #include "player_utils.h" bool From d2b6c3629e9af8a18927aefdc7244624406508b4 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 18:33:34 +0000 Subject: [PATCH 18/42] Remove last calls to the paint functions. --- paint.c | 43 ------------------------------------------- paint.h | 4 ---- player.c | 4 ++-- 3 files changed, 2 insertions(+), 49 deletions(-) diff --git a/paint.c b/paint.c index d343739..c55282d 100644 --- a/paint.c +++ b/paint.c @@ -564,49 +564,6 @@ paint_all() paint_playlist(); } -/* - * Paints an error message to the command/status window. The usage is - * identical to that of printf(3) (vwprintw(3) actually). - */ -void -paint_error(const char *fmt, ...) -{ - va_list ap; - - werase(ui.command); - wmove(ui.command, 0, 0); - wattron(ui.command, COLOR_PAIR(colors.errors)); - - va_start(ap, fmt); - vwprintw(ui.command, fmt, ap); - va_end(ap); - - beep(); - wattroff(ui.command, COLOR_PAIR(colors.errors)); - wrefresh(ui.command); -} - -/* - * Paints an informational message to the command/status window. The usage - * is identical to that of printf(3) (vwprintw(3) actually). - */ -void -paint_message(const char *fmt, ...) -{ - va_list ap; - - werase(ui.command); - wmove(ui.command, 0, 0); - wattron(ui.command, COLOR_PAIR(colors.messages)); - - va_start(ap, fmt); - vwprintw(ui.command, fmt, ap); - va_end(ap); - - wattroff(ui.command, COLOR_PAIR(colors.messages)); - wrefresh(ui.command); -} - /* * Each of these members of the global color object will be * run through init_pair(3) diff --git a/paint.h b/paint.h index c765891..d5078a1 100644 --- a/paint.h +++ b/paint.h @@ -66,10 +66,6 @@ void paint_all(); extern bool showing_file_info; void paint_playlist_file_info(const meta_info *m); -/* routines for painting errors/messages in the command/status window */ -void paint_error(const char *fmt, ...); -void paint_message(const char *fmt, ...); - /* for setting up and working with the colors */ void paint_setup_colors(); int paint_str2item(const char *str); diff --git a/player.c b/player.c index e5a1685..c1d5ffe 100644 --- a/player.c +++ b/player.c @@ -141,8 +141,8 @@ player_init(const char *backend) fatalx("dynamically loaded backends not yet supported"); player.set_callback_playnext(callback_playnext); - player.set_callback_notice(paint_message); - player.set_callback_error(paint_error); + player.set_callback_notice(infox); + player.set_callback_error(fatalx); player.set_callback_fatal(callback_fatal); player.start(); } From 1028a295e4033c0ed8e005057357f89efbe49ed2 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 19:35:36 +0000 Subject: [PATCH 19/42] Add functions that always exit when called. --- error.c | 27 +++++++++++++++++++++++++++ error.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/error.c b/error.c index ab7a801..a19304b 100644 --- a/error.c +++ b/error.c @@ -150,6 +150,33 @@ error_open(void) error_file(stderr, true, "%s: fopen", ERROR_LOG_PATH); } +/* + * Outputs a fatal message with the errno message string appended and terminates + * the process. + */ +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_file(stderr, true, fmt, ap); + va_end(ap); + exit(1); +} + +/* Outputs a fatal message and terminates the process. */ +void +diex(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_file(stderr, false, fmt, ap); + va_end(ap); + exit(1); +} + /* Outputs a fatal message with the errno message string appended. */ void fatal(const char *fmt, ...) diff --git a/error.h b/error.h index caa3716..27396b2 100644 --- a/error.h +++ b/error.h @@ -24,6 +24,8 @@ #define ERROR_PAINT 2 void debug(const char *, ...); +void die(const char *, ...); +void diex(const char *, ...); void error_init(int); void error_open(void); void fatal(const char *, ...); From 06216ad22a6f101d75fac0a5aa810e6a3912ca30 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 19:41:21 +0000 Subject: [PATCH 20/42] Add wrappers of functions that allocate memory. --- Makefile | 2 +- xmalloc.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ xmalloc.h | 29 ++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 xmalloc.c create mode 100644 xmalloc.h diff --git a/Makefile b/Makefile index 155124d..1e3b254 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ OBJS=commands.o compat.o ecmd.o \ error.o keybindings.o medialib.o meta_info.o \ mplayer.o paint.o player.o player_utils.o \ playlist.o socket.o str2argv.o \ - uinterface.o vitunes.o \ + uinterface.o vitunes.o xmalloc.o \ $(ODEPS) # subdirectories with code (.PATH for BSD make, VPATH for GNU make) diff --git a/xmalloc.c b/xmalloc.c new file mode 100644 index 0000000..2cf48ed --- /dev/null +++ b/xmalloc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "xmalloc.h" + +void +xasprintf(char **ret, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (vasprintf(ret, fmt, ap) == -1 || *ret == NULL) + diex("vasprintf"); + va_end(ap); +} + +void * +xcalloc(size_t nmemb, size_t size) +{ + void *ptr; + + if (nmemb == 0) + diex("xcalloc: zero objects"); + if (size == 0) + diex("xcalloc: zero size"); + if (nmemb > SIZE_MAX / size) { + errno = ENOMEM; + die("xcalloc: overflow"); + } + if ((ptr = calloc(nmemb, size)) == NULL) + die("calloc"); + + return (ptr); +} + +void * +xmalloc(size_t size) +{ + void *ptr; + + if (size == 0) + diex("xmalloc: zero size"); + if ((ptr = malloc(size)) == NULL) + die("malloc"); + + return (ptr); +} + +void * +xrealloc(void *ptr, size_t nmemb, size_t size) +{ + void *newptr; + + if (nmemb == 0) + diex("xrealloc: zero objects"); + if (size == 0) + diex("xrealloc: zero size"); + if (nmemb > SIZE_MAX / size) { + errno = ENOMEM; + die("xrealloc: overflow"); + } + if ((newptr = realloc(ptr, nmemb * size)) == NULL) + die("realloc"); + + return (newptr); +} + +char * +xstrdup(const char *s) +{ + char *ptr; + + if (s == NULL) + diex("xstrdup: null pointer"); + if ((ptr = strdup(s)) == NULL) + die("strdup"); + + return (ptr); +} diff --git a/xmalloc.h b/xmalloc.h new file mode 100644 index 0000000..cd41be4 --- /dev/null +++ b/xmalloc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef XMALLOC_H +#define XMALLOC_H + +#include +#include + +void xasprintf(char **, const char *, ...); +void *xcalloc(size_t, size_t); +void *xmalloc(size_t); +void *xrealloc(void *, size_t, size_t); +char *xstrdup(const char *); + +#endif From 07058a707e93231f11e4f20da16b22f54a0f0f04 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 22 Feb 2013 20:35:41 +0000 Subject: [PATCH 21/42] Remove superfluous bzero(3) calls. --- commands.c | 2 -- meta_info.c | 4 ---- str2argv.c | 4 ---- 3 files changed, 10 deletions(-) diff --git a/commands.c b/commands.c index 2d5dc2f..4d68db1 100644 --- a/commands.c +++ b/commands.c @@ -995,8 +995,6 @@ user_getstr(const char *prompt, char **response) if ((input = calloc(MAX_INPUT_SIZE, sizeof(char))) == NULL) fatal("user_getstr: calloc(3) failed for input string"); - bzero(input, MAX_INPUT_SIZE); - /* start getting input */ ret = 0; pos = 0; diff --git a/meta_info.c b/meta_info.c index 6e08b6e..f7bf074 100644 --- a/meta_info.c +++ b/meta_info.c @@ -131,14 +131,10 @@ mi_fread(meta_info *mi, FILE *fin) if ((mi->filename = calloc(lengths[0] + 1, sizeof(char))) == NULL) fatal("mi_fread: calloc filename failed"); - bzero(mi->filename, sizeof(char) * (lengths[0] + 1)); - for (i = 0; i < MI_NUM_CINFO; i++) { if (lengths[i+1] > 0) { if ((mi->cinfo[i] = calloc(lengths[i+1] + 1, sizeof(char))) == NULL) fatal("mi_fread: failed to calloc cinfo"); - - bzero(mi->cinfo[i], sizeof(char) * (lengths[i+1] + 1)); } } diff --git a/str2argv.c b/str2argv.c index d6bc4aa..f04eef7 100644 --- a/str2argv.c +++ b/str2argv.c @@ -33,7 +33,6 @@ argv_init(int *argc, char ***argv) if (((*argv)[0] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) fatal("argv_init: argv[i] calloc fail"); - bzero((*argv)[0], ARGV_MAX_TOKEN_LEN * sizeof(char)); *argc = 0; } @@ -76,8 +75,6 @@ argv_finish_token(int *argc, char ***argv) *argc = *argc + 1; if (((*argv)[*argc] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) fatal("argv_finish_token: failed to calloc argv[i]"); - - bzero((*argv)[*argc], ARGV_MAX_TOKEN_LEN * sizeof(char)); } /* @@ -249,7 +246,6 @@ argv2str(int argc, char *argv[]) /* allocate result */ if ((result = calloc(len, sizeof(char))) == NULL) fatal("argv2str: calloc failed"); - bzero(result, len); /* build result */ off = 0; From 071972476a5ddd6ecdb95e678f3e9011ea947e0f Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 23 Feb 2013 12:33:10 +0000 Subject: [PATCH 22/42] Use new wrapper functions. --- commands.c | 50 ++++++++------------------- ecmd_addurl.c | 7 ++-- ecmd_flush.c | 4 +-- ecmd_help.c | 4 +-- ecmd_tag.c | 16 ++++----- keybindings.c | 30 ++++------------ medialib.c | 27 +++++---------- meta_info.c | 66 ++++++++++++------------------------ paint.c | 4 +-- players/mplayer.c | 18 +++------- players/player_utils.c | 9 ++--- playlist.c | 77 +++++++++++------------------------------- str2argv.c | 15 +++----- uinterface.c | 8 ++--- vitunes.c | 28 ++++++--------- 15 files changed, 112 insertions(+), 251 deletions(-) diff --git a/commands.c b/commands.c index 4d68db1..df03fdb 100644 --- a/commands.c +++ b/commands.c @@ -27,6 +27,7 @@ #include "str2argv.h" #include "uinterface.h" #include "vitunes.h" +#include "xmalloc.h" bool sorts_need_saving = false; @@ -69,9 +70,8 @@ void toggleset_init() { const int max_size = 52; /* since we only have registers a-z and A-Z */ - if ((toggleset = calloc(max_size, sizeof(toggle_list*))) == NULL) - fatal("%s: calloc(3) failed", __FUNCTION__); + toggleset = xcalloc(max_size, sizeof(toggle_list*)); toggleset_size = 0; } @@ -89,29 +89,20 @@ toggleset_free() void toggle_list_add_command(toggle_list *t, char *cmd) { - char **new_cmds; - int idx; + int idx; /* resize array */ if (t->size == 0) { - if ((t->commands = malloc(sizeof(char*))) == NULL) - fatal("%s: malloc(3) failed", __FUNCTION__); - + t->commands = xmalloc(sizeof(char*)); idx = 0; t->size = 1; } else { - int new_size = (t->size + 1) * sizeof(char*); - if ((new_cmds = realloc(t->commands, new_size)) == NULL) - fatal("%s: realloc(3) failed", __FUNCTION__); - - idx = t->size; - t->commands = new_cmds; - t->size++; + t->commands = xrealloc(t->commands, t->size + 1, sizeof(char *)); + idx = t->size++; } /* add command */ - if ((t->commands[idx] = strdup(cmd)) == NULL) - fatal("%s: strdup(3) failed", __FUNCTION__); + t->commands[idx] = xstrdup(cmd); } toggle_list* @@ -121,9 +112,7 @@ toggle_list_create(int registr, int argc, char *argv[]) char *cmd = NULL; int i, j; - if ((t = malloc(sizeof(toggle_list))) == NULL) - fatal("%s: malloc(3) failed", __FUNCTION__); - + t = xmalloc(sizeof(toggle_list)); t->commands = NULL; t->registr = registr; t->size = 0; @@ -317,8 +306,7 @@ cmd_write(int argc, char *argv[]) bool will_clobber; /* build filename for playlist */ - if (asprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, argv[1]) == -1) - fatal("cmd_write: asprintf failed"); + xasprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, argv[1]); /* check to see if playlist with that name already exists */ will_clobber = false; @@ -420,16 +408,14 @@ cmd_new(int argc, char *argv[]) } name = argv[1]; - if (asprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, name) == -1) - fatal("cmd_new: asprintf failed"); + xasprintf(&filename, "%s/%s.playlist", mdb.playlist_dir, name); } /* create & setup playlist */ p = playlist_new(); p->needs_saving = true; p->filename = filename; - if ((p->name = strdup(name)) == NULL) - fatal("cmd_new: strdup(3) failed"); + p->name = xstrdup(name); /* add playlist to media library and update ui */ medialib_playlist_add(p); @@ -735,11 +721,8 @@ cmd_reload(int argc, char *argv[]) /* reload database or config file */ if (strcasecmp(argv[1], "db") == 0) { - - char *db_file = strdup(mdb.db_file); - char *playlist_dir = strdup(mdb.playlist_dir); - if (db_file == NULL || playlist_dir == NULL) - fatal("cmd_reload: strdup(3) failed"); + char *db_file = xstrdup(mdb.db_file); + char *playlist_dir = xstrdup(mdb.playlist_dir); /* stop playback TODO investigate a nice way around this */ player_stop(); @@ -992,8 +975,7 @@ user_getstr(const char *prompt, char **response) wrefresh(ui.command); /* allocate input space and clear */ - if ((input = calloc(MAX_INPUT_SIZE, sizeof(char))) == NULL) - fatal("user_getstr: calloc(3) failed for input string"); + input = xcalloc(MAX_INPUT_SIZE, sizeof(char)); /* start getting input */ ret = 0; @@ -1064,9 +1046,7 @@ user_getstr(const char *prompt, char **response) input[pos] = '\0'; /* trim the fat */ - if ((*response = calloc(strlen(input) + 1, sizeof(char))) == NULL) - fatal("user_getstr: calloc(3) failed for result"); - + *response = xcalloc(strlen(input) + 1, sizeof(char)); snprintf(*response, strlen(input) + 1, "%s", input); end: diff --git a/ecmd_addurl.c b/ecmd_addurl.c index d224986..3c06352 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -24,6 +24,7 @@ #include "meta_info.h" #include "playlist.h" #include "vitunes.h" +#include "xmalloc.h" static void ecmd_addurl_exec(UNUSED int argc, char **argv) @@ -37,8 +38,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) /* start new record, set filename */ m = mi_new(); m->is_url = true; - if ((m->filename = strdup(argv[0])) == NULL) - fatal("%s: strdup failed (filename)", __FUNCTION__); + m->filename = xstrdup(argv[0]); /* get fields from user */ for (field = 0; field < MI_NUM_CINFO; field++) { @@ -53,8 +53,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) if (input[strlen(input) - 1] == '\n') input[strlen(input) - 1] = '\0'; - if ((m->cinfo[field] = strdup(input)) == NULL) - fatal("%s: strdup failed (field)", __FUNCTION__); + m->cinfo[field] = xstrdup(input); } /* load existing database and see if file/URL already exists */ diff --git a/ecmd_flush.c b/ecmd_flush.c index a72db9d..66a1d68 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -22,6 +22,7 @@ #include "error.h" #include "medialib.h" #include "vitunes.h" +#include "xmalloc.h" static char *time_format = "%Y %m %d %H:%M:%S"; @@ -33,8 +34,7 @@ ecmd_flush_parse(int argc, char **argv) while ((ch = getopt(argc, argv, "t:")) != -1) { switch (ch) { case 't': - if ((time_format = strdup(optarg)) == NULL) - fatal("%s: strdup of time_format failed", argv[0]); + time_format = xstrdup(optarg); break; case '?': case 'h': diff --git a/ecmd_help.c b/ecmd_help.c index 086639f..15bb476 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -22,6 +22,7 @@ #include "ecmd.h" #include "error.h" #include "vitunes.h" +#include "xmalloc.h" static void ecmd_help_exec(UNUSED int argc, char **argv) @@ -60,8 +61,7 @@ The list of available commands are:\n\n\ } man_args[0] = "man"; - if (asprintf(&man_args[1], "vitunes-%s", argv[0]) == -1) - fatal("ecmd_help: asprintf failed"); + xasprintf(&man_args[1], "vitunes-%s", argv[0]); man_args[2] = NULL; execvp("man", man_args); diff --git a/ecmd_tag.c b/ecmd_tag.c index 112981f..b4f3c85 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -26,6 +26,7 @@ #include "ecmd.h" #include "error.h" #include "meta_info.h" +#include "xmalloc.h" static char *artist; static char *album; @@ -45,8 +46,7 @@ ecmd_tag_parse(int argc, char **argv) switch (ch) { case 'A': free(album); - if ((album = strdup(optarg)) == NULL) - fatal("%s: strdup ALBUM failed", argv[0]); + album = xstrdup(optarg); break; case 'T': track = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); @@ -55,23 +55,19 @@ ecmd_tag_parse(int argc, char **argv) break; case 'a': free(artist); - if ((artist = strdup(optarg)) == NULL) - fatal("%s: strdup ARTIST failed", argv[0]); + artist = xstrdup(optarg); break; case 'c': free(comment); - if ((comment = strdup(optarg)) == NULL) - fatal("%s: strdup COMMENT failed", argv[0]); + comment = xstrdup(optarg); break; case 'g': free(genre); - if ((genre = strdup(optarg)) == NULL) - fatal("%s: strdup GENRE failed", argv[0]); + genre = xstrdup(optarg); break; case 't': free(title); - if ((title = strdup(optarg)) == NULL) - fatal("%s: strdup TITLE failed", argv[0]); + title = xstrdup(optarg); break; case 'y': year = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); diff --git a/keybindings.c b/keybindings.c index 3529acf..320ad03 100644 --- a/keybindings.c +++ b/keybindings.c @@ -29,6 +29,7 @@ #include "str2argv.h" #include "uinterface.h" #include "vitunes.h" +#include "xmalloc.h" /* This table maps KeyActions to their string representations */ typedef struct { @@ -268,15 +269,8 @@ size_t KeyBindingsCapacity; void kb_increase_capacity() { - KeyBinding *new_buffer; - size_t nbytes; - KeyBindingsCapacity += KEYBINDINGS_CHUNK_SIZE; - nbytes = KeyBindingsCapacity * sizeof(KeyBinding); - if ((new_buffer = realloc(KeyBindings, nbytes)) == NULL) - fatal("%s: failed to realloc(3) keybindings", __FUNCTION__); - - KeyBindings = new_buffer; + KeyBindings = xrealloc(KeyBindings, KeyBindingsCapacity, sizeof(KeyBinding)); } @@ -1041,8 +1035,7 @@ kba_cut(KbaArgs a UNUSED) return; } - if (asprintf(&warning, "Are you sure you want to delete '%s'?", p->name) == -1) - fatal("cut: asprintf failed"); + xasprintf(&warning, "Are you sure you want to delete '%s'?", p->name); /* make sure user wants this */ if (user_get_yesno(warning, &response) != 0) { @@ -1670,10 +1663,7 @@ yank_buffer _yank_buffer; void ybuffer_init() { - _yank_buffer.files = calloc(YANK_BUFFER_CHUNK_SIZE, sizeof(meta_info*)); - if (_yank_buffer.files == NULL) - fatal("ybuffer_init: calloc(3) failed"); - + _yank_buffer.files = xcalloc(YANK_BUFFER_CHUNK_SIZE, sizeof(meta_info*)); _yank_buffer.capacity = YANK_BUFFER_CHUNK_SIZE; _yank_buffer.nfiles = 0; } @@ -1695,16 +1685,11 @@ ybuffer_free() void ybuffer_add(meta_info *f) { - meta_info **new_buff; - /* do we need to realloc()? */ if (_yank_buffer.nfiles == _yank_buffer.capacity) { _yank_buffer.capacity += YANK_BUFFER_CHUNK_SIZE; - int new_capacity = _yank_buffer.capacity * sizeof(meta_info*); - if ((new_buff = realloc(_yank_buffer.files, new_capacity)) == NULL) - fatal("ybuffer_add: realloc(3) failed [%i]", new_capacity); - - _yank_buffer.files = new_buff; + _yank_buffer.files = xrealloc(_yank_buffer.files, _yank_buffer.capacity, + sizeof(meta_info *)); } /* add the file */ @@ -1746,8 +1731,7 @@ match_command_name(const char *input, const char *cmd) /* check for '!' weirdness and abbreviations */ - if ((icopy = strdup(input)) == NULL) - fatal("match_command_name: strdup(3) failed"); + icopy = xstrdup(input); /* remove '!' from input, if present */ if (strstr(icopy, "!") != NULL) diff --git a/medialib.c b/medialib.c index 884848a..50bd8ba 100644 --- a/medialib.c +++ b/medialib.c @@ -29,6 +29,7 @@ #include "medialib.h" #include "meta_info.h" #include "playlist.h" +#include "xmalloc.h" /* The global media library struct */ medialib mdb; @@ -46,22 +47,17 @@ medialib_load(const char *db_file, const char *playlist_dir) int i; /* copy file/directory names */ - mdb.db_file = strdup(db_file); - mdb.playlist_dir = strdup(playlist_dir); - if (mdb.db_file == NULL || mdb.playlist_dir == NULL) - fatal("failed to strdup db file and playlist dir in medialib_init"); + mdb.db_file = xstrdup(db_file); + mdb.playlist_dir = xstrdup(playlist_dir); /* setup pseudo-playlists */ mdb.library = playlist_new(); mdb.library->filename = NULL; - mdb.library->name = strdup("--LIBRARY--"); + mdb.library->name = xstrdup("--LIBRARY--"); mdb.filter_results = playlist_new(); mdb.filter_results->filename = NULL; - mdb.filter_results->name = strdup("--FILTER--"); - - if (mdb.library->name == NULL || mdb.filter_results->name == NULL) - fatal("failed to strdup pseudo-names in medialib_load"); + mdb.filter_results->name = xstrdup("--FILTER--"); /* load the actual database */ medialib_db_load(db_file); @@ -69,9 +65,7 @@ medialib_load(const char *db_file, const char *playlist_dir) /* setup initial record keeping for playlists */ mdb.nplaylists = 0; mdb.playlists_capacity = 2; - mdb.playlists = calloc(2, sizeof(playlist*)); - if (mdb.playlists == NULL) - fatal("medialib_load: failed to allocate initial playlists"); + mdb.playlists = xcalloc(2, sizeof(playlist*)); /* add library/filter pseudo-playlists */ medialib_playlist_add(mdb.library); @@ -120,16 +114,11 @@ medialib_destroy() void medialib_playlist_add(playlist *p) { - playlist **new_playlists; - /* check to see if we need to resize the array */ if (mdb.nplaylists == mdb.playlists_capacity) { mdb.playlists_capacity += MEDIALIB_PLAYLISTS_CHUNK_SIZE; - int size = mdb.playlists_capacity * sizeof(playlist*); - if ((new_playlists = realloc(mdb.playlists, size)) == NULL) - fatal("medialib_playlist_add: realloc failed"); - - mdb.playlists = new_playlists; + mdb.playlists = xrealloc(mdb.playlists, mdb.playlists_capacity, + sizeof(playlist *)); } mdb.playlists[mdb.nplaylists++] = p; diff --git a/meta_info.c b/meta_info.c index f7bf074..be446c8 100644 --- a/meta_info.c +++ b/meta_info.c @@ -32,6 +32,7 @@ #include "enums.h" #include "error.h" #include "meta_info.h" +#include "xmalloc.h" /* human-readable names of all of the string-type meta information values */ const char *MI_CINFO_NAMES[] = { @@ -55,9 +56,7 @@ mi_new(void) meta_info *mi; int i; - if ((mi = malloc(sizeof(meta_info))) == NULL) - fatal("mi_new: meta_info malloc failed"); - + mi = xmalloc(sizeof(meta_info)); mi->filename = NULL; mi->length = 0; mi->last_updated = 0; @@ -128,14 +127,11 @@ mi_fread(meta_info *mi, FILE *fin) fread(lengths, sizeof(lengths), 1, fin); /* allocate all needed space in the meta_info struct, and zero */ - if ((mi->filename = calloc(lengths[0] + 1, sizeof(char))) == NULL) - fatal("mi_fread: calloc filename failed"); + mi->filename = xcalloc(lengths[0] + 1, sizeof(char)); for (i = 0; i < MI_NUM_CINFO; i++) { - if (lengths[i+1] > 0) { - if ((mi->cinfo[i] = calloc(lengths[i+1] + 1, sizeof(char))) == NULL) - fatal("mi_fread: failed to calloc cinfo"); - } + if (lengths[i+1] > 0) + mi->cinfo[i] = xcalloc(lengths[i+1] + 1, sizeof(char)); } /* read */ @@ -196,8 +192,7 @@ mi_extract(const char *filename) if (realpath(filename, fullname) == NULL) fatal("mi_extract: realpath failed to resolve '%s'", filename); - if ((mi->filename = strdup(fullname)) == NULL) - fatalx("mi_extract: strdup failed for '%s'", fullname); + mi->filename = xstrdup(fullname); /* start extracting fields using TagLib... */ @@ -215,45 +210,32 @@ mi_extract(const char *filename) /* artist/album/title/genre */ if ((str = taglib_tag_artist(tag)) != NULL) - mi->cinfo[MI_CINFO_ARTIST] = strdup(str); + mi->cinfo[MI_CINFO_ARTIST] = xstrdup(str); if ((str = taglib_tag_album(tag)) != NULL) - mi->cinfo[MI_CINFO_ALBUM] = strdup(str); + mi->cinfo[MI_CINFO_ALBUM] = xstrdup(str); if ((str = taglib_tag_title(tag)) != NULL) - mi->cinfo[MI_CINFO_TITLE] = strdup(str); + mi->cinfo[MI_CINFO_TITLE] = xstrdup(str); if ((str = taglib_tag_genre(tag)) != NULL) - mi->cinfo[MI_CINFO_GENRE] = strdup(str); + mi->cinfo[MI_CINFO_GENRE] = xstrdup(str); if ((str = taglib_tag_comment(tag)) != NULL) - mi->cinfo[MI_CINFO_COMMENT] = strdup(str); - - if (mi->cinfo[MI_CINFO_ARTIST] == NULL - || mi->cinfo[MI_CINFO_ALBUM] == NULL - || mi->cinfo[MI_CINFO_TITLE] == NULL - || mi->cinfo[MI_CINFO_GENRE] == NULL - || mi->cinfo[MI_CINFO_COMMENT] == NULL) - fatal("mi_extract: strdup for CINFO failed"); + mi->cinfo[MI_CINFO_COMMENT] = xstrdup(str); /* track number */ - if (taglib_tag_track(tag) > 0) { - if (asprintf(&(mi->cinfo[MI_CINFO_TRACK]), "%3i", taglib_tag_track(tag)) == -1) - fatal("mi_extract: asprintf failed for CINFO_TRACK"); - } + if (taglib_tag_track(tag) > 0) + xasprintf(&(mi->cinfo[MI_CINFO_TRACK]), "%3i", taglib_tag_track(tag)); /* year */ - if (taglib_tag_year(tag) > 0) { - if (asprintf(&(mi->cinfo[MI_CINFO_YEAR]), "%i", taglib_tag_year(tag)) == -1) - fatal("mi_extract: asprintf failed for CINFO_YEAR"); - } + if (taglib_tag_year(tag) > 0) + xasprintf(&(mi->cinfo[MI_CINFO_YEAR]), "%i", taglib_tag_year(tag)); /* playlength in seconds (will be 0 if unavailable) */ mi->length = taglib_audioproperties_length(properties); - if (mi->length > 0) { - if ((mi->cinfo[MI_CINFO_LENGTH] = strdup(time2str(mi->length))) == NULL) - fatal("mi_extract: strdup failed for CINO_LENGTH"); - } + if (mi->length > 0) + mi->cinfo[MI_CINFO_LENGTH] = xstrdup(time2str(mi->length)); /* record the time we extracted this info */ time(&mi->last_updated); @@ -359,8 +341,7 @@ mi_query_add_token(const char *token) _mi_query.match[_mi_query.ntokens] = true; /* copy token */ - if ((_mi_query.tokens[_mi_query.ntokens++] = strdup(token)) == NULL) - fatal("mi_query_add_token: strdup failed"); + _mi_query.tokens[_mi_query.ntokens++] = xstrdup(token); } void @@ -369,8 +350,7 @@ mi_query_setraw(const char *query) if (_mi_query.raw != NULL) free(_mi_query.raw); - if ((_mi_query.raw = strdup(query)) == NULL) - fatal("mi_query_setraw: query strdup failed"); + _mi_query.raw = xstrdup(query); } const char * @@ -504,9 +484,7 @@ mi_sort_set(const char *s, const char **errmsg) }; *errmsg = NULL; - if ((line = strdup(s)) == NULL) - fatal("mi_sort_set: sort strdup failed"); - + line = xstrdup(s); idx = 0; copy = line; @@ -712,9 +690,7 @@ mi_display_set(const char *display, const char **errmsg) *errmsg = NULL; new_display.nfields = 0; - if ((s = strdup(display)) == NULL) - fatal("mi_display_set: display strdup failed"); - + s = xstrdup(display); copy = s; idx = 0; diff --git a/paint.c b/paint.c index c55282d..aa2737d 100644 --- a/paint.c +++ b/paint.c @@ -32,6 +32,7 @@ #include "playlist.h" #include "uinterface.h" #include "vitunes.h" +#include "xmalloc.h" /* globals */ _colors colors; @@ -661,8 +662,7 @@ paint_str2color(const char *str) char *numberstr; int number; - if ((color = strdup(str)) == NULL) - fatal("%s: strdup of '%s' failed.", __FUNCTION__, str); + color = xstrdup(str); if ((numberstr = strtok(color, "color")) == NULL) { free(color); diff --git a/players/mplayer.c b/players/mplayer.c index 04d8540..4b468bb 100644 --- a/players/mplayer.c +++ b/players/mplayer.c @@ -33,6 +33,7 @@ #include "mplayer.h" #include "mplayer_conf.h" #include "player_utils.h" +#include "xmalloc.h" /* callback functions */ void (*mplayer_callback_playnext)(void) = NULL; @@ -195,9 +196,7 @@ mplayer_play(const char *file) static const char *cmd_fmt = "\nloadfile \"%s\" 0\nget_property time_pos\n"; char *cmd; - if (asprintf(&cmd, cmd_fmt, file) == -1) - err(1, "%s: asprintf failed", __FUNCTION__); - + xasprintf(&cmd, cmd_fmt, file); mplayer_send_cmd(cmd); free(cmd); @@ -239,9 +238,7 @@ mplayer_seek(int seconds) if (!mplayer_state.playing) return; - if (asprintf(&cmd, cmd_fmt, seconds) == -1) - err(1, "%s: asprintf failed", __FUNCTION__); - + xasprintf(&cmd, cmd_fmt, seconds); mplayer_send_cmd(cmd); free(cmd); @@ -267,9 +264,7 @@ mplayer_volume_step(float percent) return; } - if (asprintf(&cmd, cmd_fmt, percent) == -1) - err(1, "%s: asprintf failed", __FUNCTION__); - + xasprintf(&cmd, cmd_fmt, percent); mplayer_send_cmd(cmd); free(cmd); @@ -288,10 +283,7 @@ mplayer_volume_set(float percent) if (percent > 100) percent = 100; if (percent < 0) percent = 0; - if (asprintf(&cmd, cmd_fmt, percent) == -1) - err(1, "%s: asprintf failed", __FUNCTION__); - - + xasprintf(&cmd, cmd_fmt, percent); mplayer_send_cmd(cmd); free(cmd); diff --git a/players/player_utils.c b/players/player_utils.c index 78df94e..c2ac83d 100644 --- a/players/player_utils.c +++ b/players/player_utils.c @@ -23,6 +23,7 @@ #include "compat.h" #include "player_utils.h" +#include "xmalloc.h" bool exe_in_path(const char *e) @@ -30,17 +31,13 @@ exe_in_path(const char *e) char *path, *path_copy, *part, *test; bool found; - if ((path = strdup(getenv("PATH"))) == NULL) - err(1, "%s: strdup/getenv failed for $PATH", __FUNCTION__); - + path = xstrdup(getenv("PATH")); path_copy = path; found = false; while ((part = strsep(&path, ":")) != NULL && !found) { if (strlen(part) == 0) continue; - if (asprintf(&test, "%s/%s", part, e) == -1) - err(1, "%s: failed to build path", __FUNCTION__); - + xasprintf(&test, "%s/%s", part, e); if (access(test, X_OK) == 0) found = true; diff --git a/playlist.c b/playlist.c index 7791a62..29f1d95 100644 --- a/playlist.c +++ b/playlist.c @@ -30,21 +30,15 @@ #include "error.h" #include "meta_info.h" #include "playlist.h" +#include "xmalloc.h" int history_size = DEFAULT_HISTORY_SIZE; void playlist_increase_capacity(playlist *p) { - meta_info **new_files; - size_t nbytes; - p->capacity += PLAYLIST_CHUNK_SIZE; - nbytes = p->capacity * sizeof(meta_info*); - if ((new_files = realloc(p->files, nbytes)) == NULL) - fatal("%s: failed to realloc(3) files", __FUNCTION__); - - p->files = new_files; + p->files = xrealloc(p->files, p->capacity, sizeof(meta_info *)); } /* @@ -56,12 +50,8 @@ playlist_new(void) { playlist *p; - if ((p = malloc(sizeof(playlist))) == NULL) - fatal("playlist_new: failed to allocate playlist"); - - if ((p->files = calloc(PLAYLIST_CHUNK_SIZE, sizeof(meta_info*))) == NULL) - fatal("playlist_new: failed to allocate files"); - + p = xmalloc(sizeof(playlist)); + p->files = xcalloc(PLAYLIST_CHUNK_SIZE, sizeof(meta_info*)); p->capacity = PLAYLIST_CHUNK_SIZE; p->filename = NULL; p->name = NULL; @@ -100,20 +90,13 @@ playlist_dup(const playlist *original, const char *filename, newplist->nfiles = original->nfiles; newplist->capacity = original->nfiles; - if (name != NULL) { - if ((newplist->name = strdup(name)) == NULL) - fatal("playlist_dup: strdup name failed"); - } - if (filename != NULL) { - if ((newplist->filename = strdup(filename)) == NULL) - fatal("playlist_dup: strdup filename failed"); - } + if (name != NULL) + newplist->name = xstrdup(name); + if (filename != NULL) + newplist->filename = xstrdup(filename); /* copy all of the files */ - newplist->files = calloc(original->nfiles, sizeof(meta_info*)); - if (newplist->files == NULL) - fatal("playlist_dup: failed to allocate files"); - + newplist->files = xcalloc(original->nfiles, sizeof(meta_info*)); for (i = 0; i < original->nfiles; i++) newplist->files[i] = original->files[i]; @@ -228,10 +211,8 @@ playlist_load(const char *filename, meta_info **db, int ndb) /* create playlist and setup */ playlist *p = playlist_new(); - p->filename = strdup(filename); - p->name = strdup(basename(p->filename)); - if (p->filename == NULL || p->name == NULL) - fatal("playlist_load: failed to allocate info for playlist '%s'", filename); + p->filename = xstrdup(filename); + p->name = xstrdup(basename(p->filename)); /* hack to remove '.playlist' from name */ period = strrchr(p->name, '.'); @@ -251,9 +232,7 @@ playlist_load(const char *filename, meta_info **db, int ndb) } else { /* file does NOT exist in DB */ /* create empty meta-info object with just the file name */ mi = mi_new(); - mi->filename = strdup(entry); - if (mi->filename == NULL) - fatal("playlist_load: failed to strdup filename"); + mi->filename = xstrdup(entry); /* add new record to the db and link it to the playlist */ playlist_files_append(p, &mi, 1, false); @@ -368,8 +347,7 @@ retrieve_playlist_filenames(const char *dirname, char ***fnames) # endif /* build the search pattern */ - if (asprintf(&glob_pattern, "%s/*.playlist", dirname) == -1) - fatalx("failed in building glob pattern"); + xasprintf(&glob_pattern, "%s/*.playlist", dirname); /* get the files */ globbed = glob(glob_pattern, 0, NULL, &files); @@ -377,13 +355,10 @@ retrieve_playlist_filenames(const char *dirname, char ***fnames) fatal("failed to glob playlists directory"); /* allocate & copy each of the filenames found into the filenames array */ - if ((*fnames = calloc(files.gl_pathc, sizeof(char*))) == NULL) - fatal("failed to allocate playlist filenames array"); + *fnames = xcalloc(files.gl_pathc, sizeof(char*)); - for (fcount = 0; fcount < files.gl_pathc; fcount++) { - if (asprintf(&((*fnames)[fcount]), "%s", files.gl_pathv[fcount]) == -1) - fatalx("failed to allocate filename for playlist"); - } + for (fcount = 0; fcount < files.gl_pathc; fcount++) + xasprintf(&((*fnames)[fcount]), "%s", files.gl_pathv[fcount]); /* cleanup */ globfree(&files); @@ -396,15 +371,10 @@ playlist_changeset* changeset_create(short type, size_t size, meta_info **files, int loc) { size_t i; - playlist_changeset *c; - if ((c = malloc(sizeof(playlist_changeset))) == NULL) - fatal("%s: malloc(3) failed", __FUNCTION__); - - if ((c->files = calloc(size, sizeof(meta_info*))) == NULL) - fatal("%s: calloc(3) failed", __FUNCTION__); - + c = xmalloc(sizeof(playlist_changeset)); + c->files = xcalloc(size, sizeof(meta_info*)); c->type = type; c->size = size; c->location = loc; @@ -425,16 +395,7 @@ changeset_free(playlist_changeset *c) playlist_changeset** playlist_history_new(void) { - playlist_changeset **h; - int i; - - if ((h = calloc(history_size, sizeof(playlist_changeset*))) == NULL) - fatal("%s: calloc(3) failed", __FUNCTION__); - - for (i = 0; i < history_size; i++) - h[i] = NULL; - - return h; + return xcalloc(history_size, sizeof(playlist_changeset*)); } void diff --git a/str2argv.c b/str2argv.c index f04eef7..2ebc6fd 100644 --- a/str2argv.c +++ b/str2argv.c @@ -22,17 +22,14 @@ #include "compat.h" #include "error.h" #include "str2argv.h" +#include "xmalloc.h" /* initialize empty argc/argv struct */ void argv_init(int *argc, char ***argv) { - if ((*argv = calloc(ARGV_MAX_ENTRIES, sizeof(char*))) == NULL) - fatal("argv_init: argv calloc fail"); - - if (((*argv)[0] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) - fatal("argv_init: argv[i] calloc fail"); - + *argv = xcalloc(ARGV_MAX_ENTRIES, sizeof(char*)); + (*argv)[0] = xcalloc(ARGV_MAX_TOKEN_LEN, sizeof(char)); *argc = 0; } @@ -73,8 +70,7 @@ argv_finish_token(int *argc, char ***argv) return; *argc = *argc + 1; - if (((*argv)[*argc] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL) - fatal("argv_finish_token: failed to calloc argv[i]"); + (*argv)[*argc] = xcalloc(ARGV_MAX_TOKEN_LEN, sizeof(char)); } /* @@ -244,8 +240,7 @@ argv2str(int argc, char *argv[]) } /* allocate result */ - if ((result = calloc(len, sizeof(char))) == NULL) - fatal("argv2str: calloc failed"); + result = xcalloc(len, sizeof(char)); /* build result */ off = 0; diff --git a/uinterface.c b/uinterface.c index 72b8a50..24dbb73 100644 --- a/uinterface.c +++ b/uinterface.c @@ -30,6 +30,7 @@ #include "enums.h" #include "error.h" #include "uinterface.h" +#include "xmalloc.h" /* the global user interface object */ uinterface ui; @@ -41,10 +42,9 @@ uinterface ui; swindow* swindow_new(int h, int w, int y, int x) { - swindow *swin = malloc(sizeof(swindow)); - if (swin == NULL) - fatal("swindow_new failed to allocate swin"); - + swindow *swin; + + swin = xmalloc(sizeof(swindow)); swin->w = w; swin->h = h; swin->voffset = 0; diff --git a/vitunes.c b/vitunes.c index a812271..490a79b 100644 --- a/vitunes.c +++ b/vitunes.c @@ -39,6 +39,7 @@ #include "str2argv.h" #include "uinterface.h" #include "vitunes.h" +#include "xmalloc.h" #include "config.h" /* NOTE: must be after vitunes.h */ /***************************************************************************** @@ -131,16 +132,11 @@ main(int argc, char *argv[]) } /* build paths & other needed strings */ - if (asprintf(&vitunes_dir, VITUNES_DIR_FMT, home) == -1) - fatal("main: asprintf failed"); - if (asprintf(&conf_file, CONF_FILE_FMT, home) == -1) - fatal("main: asprintf failed"); - if (asprintf(&db_file, DB_FILE_FMT, home) == -1) - fatal("main: asprintf failed"); - if (asprintf(&playlist_dir, PLAYLIST_DIR_FMT, home) == -1) - fatal("main: asprintf failed"); - if (asprintf(&player_backend, "%s", DEFAULT_PLAYER_BACKEND) == -1) - fatal("main: asprintf failed"); + xasprintf(&vitunes_dir, VITUNES_DIR_FMT, home); + xasprintf(&conf_file, CONF_FILE_FMT, home); + xasprintf(&db_file, DB_FILE_FMT, home); + xasprintf(&playlist_dir, PLAYLIST_DIR_FMT, home); + xasprintf(&player_backend, "%s", DEFAULT_PLAYER_BACKEND); /* handle command-line switches & e-commands */ handle_switches(argc, argv); @@ -498,8 +494,7 @@ handle_switches(int argc, char *argv[]) case 'd': free(db_file); - if ((db_file = strdup(optarg)) == NULL) - fatal("handle_switches: strdup db_file failed"); + db_file = xstrdup(optarg); break; case 'e': @@ -511,20 +506,17 @@ handle_switches(int argc, char *argv[]) case 'f': free(conf_file); - if ((conf_file = strdup(optarg)) == NULL) - fatal("handle_switches: strdup conf_file failed"); + conf_file = xstrdup(optarg); break; case 'm': free(player_backend); - if ((player_backend = strdup(optarg)) == NULL) - fatal("handle_switches: strdup player_backend failed"); + player_backend = xstrdup(optarg); break; case 'p': free(playlist_dir); - if ((playlist_dir = strdup(optarg)) == NULL) - fatal("handle_switches: strdup playlist_dir failed"); + playlist_dir = xstrdup(optarg); break; case 'v': From e112d94e2b368a0b7f88650da0675fa596a54f38 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 23 Feb 2013 12:42:13 +0000 Subject: [PATCH 23/42] Do not allocate a zero size object. It might generate a SIGSEGV exception if it's accessed. Caught by the new wrapper function. --- medialib.c | 13 +++++++------ playlist.c | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/medialib.c b/medialib.c index 50bd8ba..f577743 100644 --- a/medialib.c +++ b/medialib.c @@ -73,17 +73,18 @@ medialib_load(const char *db_file, const char *playlist_dir) /* load the rest */ npfiles = retrieve_playlist_filenames(mdb.playlist_dir, &pfiles); - for (i = 0; i < npfiles; i++) { - p = playlist_load(pfiles[i], mdb.library->files, mdb.library->nfiles); - medialib_playlist_add(p); - free(pfiles[i]); + if (npfiles) { + for (i = 0; i < npfiles; i++) { + p = playlist_load(pfiles[i], mdb.library->files, mdb.library->nfiles); + medialib_playlist_add(p); + free(pfiles[i]); + } + free(pfiles); } /* set all playlists as saved initially */ for (i = 0; i < mdb.nplaylists; i++) mdb.playlists[i]->needs_saving = false; - - free(pfiles); } /* free() all memory associated with global media library */ diff --git a/playlist.c b/playlist.c index 29f1d95..080c357 100644 --- a/playlist.c +++ b/playlist.c @@ -350,9 +350,12 @@ retrieve_playlist_filenames(const char *dirname, char ***fnames) xasprintf(&glob_pattern, "%s/*.playlist", dirname); /* get the files */ + fcount = 0; globbed = glob(glob_pattern, 0, NULL, &files); if (globbed != 0 && globbed != GLOB_NOMATCH && errno != 0) fatal("failed to glob playlists directory"); + if (files.gl_pathc == 0) + goto out; /* allocate & copy each of the filenames found into the filenames array */ *fnames = xcalloc(files.gl_pathc, sizeof(char*)); @@ -361,6 +364,7 @@ retrieve_playlist_filenames(const char *dirname, char ***fnames) xasprintf(&((*fnames)[fcount]), "%s", files.gl_pathv[fcount]); /* cleanup */ +out: globfree(&files); free(glob_pattern); From e048f287ccc9fab3298db34c1d1b5df283566953 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 23 Feb 2013 14:43:25 +0000 Subject: [PATCH 24/42] Move example file to its own directory. --- add_urls.sh => examples/add_urls.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename add_urls.sh => examples/add_urls.sh (100%) diff --git a/add_urls.sh b/examples/add_urls.sh similarity index 100% rename from add_urls.sh rename to examples/add_urls.sh From 125db865d8de21c993fb48183375483681cf8bcb Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 23 Feb 2013 14:43:47 +0000 Subject: [PATCH 25/42] Remove extension for consistency. --- DEVELOPERS.txt => DEVELOPERS | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename DEVELOPERS.txt => DEVELOPERS (100%) diff --git a/DEVELOPERS.txt b/DEVELOPERS similarity index 100% rename from DEVELOPERS.txt rename to DEVELOPERS From e50cf675b6b6db8a0aefd4738788f2e7293629d2 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 23 Feb 2013 15:36:48 +0000 Subject: [PATCH 26/42] Do not use uninitialised variables. --- keybindings.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/keybindings.c b/keybindings.c index 320ad03..9744894 100644 --- a/keybindings.c +++ b/keybindings.c @@ -559,6 +559,7 @@ kba_scroll_page(KbaArgs a) break; default: fatalx("scroll_page: invalid amount"); + return; } swindow_scroll(ui.active, a.direction, diff); @@ -761,6 +762,7 @@ kba_jumpto_file(KbaArgs a) default: fatalx("jumpto_file: NUMBER type with no num!"); + return; } break; @@ -775,6 +777,7 @@ kba_jumpto_file(KbaArgs a) default: fatalx("jumpto_file: invalid scale"); + return; } /* jump */ @@ -886,6 +889,7 @@ kba_search_find(KbaArgs a) default: fatalx("search_find: invalid direction"); + return; } /* start looking from current row */ @@ -1518,6 +1522,7 @@ kba_seek(KbaArgs a) break; default: fatalx("seek_playback: invalid scale"); + return; } /* adjust for direction */ @@ -1530,6 +1535,7 @@ kba_seek(KbaArgs a) break; default: fatalx("seek_playback: invalid direction"); + return; } /* is there a multiplier? */ From 152362295de350c42fba5534ec13258dd82da22b Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 10 May 2013 20:05:13 +0100 Subject: [PATCH 27/42] Take advantage of the execute command function. Now, with error contexts, the execute function can, also, be called when parsing the configuration file, without having to worry about where to output its messages. That is, when parsing the configuration file, the messages are printed to standard error and, afterwards, they get painted to the command/status window. --- vitunes.c | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/vitunes.c b/vitunes.c index 490a79b..0b37d52 100644 --- a/vitunes.c +++ b/vitunes.c @@ -409,17 +409,10 @@ setup_timer() void load_config() { - const char *errmsg = NULL; size_t length, linenum; FILE *fin; char *line; char *copy; - char **argv; - int argc; - bool found; - int found_idx = 0; - int num_matches; - int i, ret; if ((fin = fopen(conf_file, "r")) == NULL) return; @@ -443,33 +436,7 @@ load_config() continue; } - /* parse line into argc/argv */ - if (str2argv(copy, &argc, &argv, &errmsg) != 0) - fatalx("%s line %zd: parse error: %s", conf_file, linenum, errmsg); - - /* run command */ - found = false; - num_matches = 0; - for (i = 0; i < CommandPathSize; i++) { - if (match_command_name(argv[0], CommandPath[i].name)) { - found = true; - found_idx = i; - num_matches++; - } - } - - if (found && num_matches == 1) { - if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) - fatalx("%s line %zd: error with command '%s' [%i]", - conf_file, linenum, argv[0], ret); - } else if (num_matches > 1) - fatalx("%s line %zd: ambiguous abbreviation '%s'", - conf_file, linenum, argv[0]); - else - fatalx("%s line %zd: unknown command '%s'", - conf_file, linenum, argv[0]); - - argv_free(&argc, &argv); + cmd_execute(line); free(line); } From 7f7f2658f3d005d3151038b423cf61b9618992c1 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Tue, 14 May 2013 17:48:15 +0100 Subject: [PATCH 28/42] Print the configuration file and line number. --- error.c | 6 +++++- vitunes.c | 8 +++++--- vitunes.h | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/error.c b/error.c index a19304b..0b7d4c9 100644 --- a/error.c +++ b/error.c @@ -66,7 +66,11 @@ error_paint(bool errnoflag, bool iserr, const char *fmt, va_list ap) static void error_file(FILE *fp, bool errnoflag, const char *fmt, va_list ap) { - fprintf(fp, "%s: ", progname); + fprintf(fp, "%s:", progname); + if (error_type == ERROR_CFG) + fprintf(fp, " %s line %zd:", conf_file, conf_linenum); + + fputs(" ", fp); vfprintf(fp, fmt, ap); if (errnoflag) diff --git a/vitunes.c b/vitunes.c index 0b37d52..f8d6a09 100644 --- a/vitunes.c +++ b/vitunes.c @@ -88,6 +88,9 @@ char *player_backend; /* program name with directories removed */ char *progname; +/* configuration file line number */ +size_t conf_linenum; + /***************************************************************************** * local functions @@ -409,7 +412,7 @@ setup_timer() void load_config() { - size_t length, linenum; + size_t length; FILE *fin; char *line; char *copy; @@ -417,11 +420,10 @@ load_config() if ((fin = fopen(conf_file, "r")) == NULL) return; - linenum = 0; while (!feof(fin)) { /* get next line */ - if ((line = fparseln(fin, &length, &linenum, NULL, 0)) == NULL) { + if ((line = fparseln(fin, &length, &conf_linenum, NULL, 0)) == NULL) { if (ferror(fin)) fatal("error reading config file '%s'", conf_file); else diff --git a/vitunes.h b/vitunes.h index 68b417c..0552e18 100644 --- a/vitunes.h +++ b/vitunes.h @@ -34,10 +34,12 @@ /* configurable paths */ extern char *vitunes_dir; +extern char *conf_file; extern char *playlist_dir; extern char *db_file; extern char *progname; +size_t conf_linenum; /* record keeping */ extern playlist *viewing_playlist; From 82414d422564b7e0e3df55ff07f9a9f57345f033 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Tue, 14 May 2013 17:49:18 +0100 Subject: [PATCH 29/42] While at it, simplify configuration file parsing. The fparseln(3) function already returns NULL on EOF. Check it and move the ferror(3) call outside the loop. --- vitunes.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/vitunes.c b/vitunes.c index f8d6a09..6d0c2ba 100644 --- a/vitunes.c +++ b/vitunes.c @@ -420,16 +420,8 @@ load_config() if ((fin = fopen(conf_file, "r")) == NULL) return; - while (!feof(fin)) { - - /* get next line */ - if ((line = fparseln(fin, &length, &conf_linenum, NULL, 0)) == NULL) { - if (ferror(fin)) - fatal("error reading config file '%s'", conf_file); - else - break; - } - + /* get next line */ + while ((line = fparseln(fin, &length, &conf_linenum, NULL, 0)) != NULL) { /* skip whitespace */ copy = line; copy += strspn(copy, " \t\n"); @@ -441,6 +433,8 @@ load_config() cmd_execute(line); free(line); } + if (ferror(fin)) + fatal("error reading config file '%s'", conf_file); fclose(fin); } From 00ba92f8cd6145ecc5ce739df1d3755b1a530610 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Tue, 14 May 2013 18:16:31 +0100 Subject: [PATCH 30/42] Do not output the path twice. It already gets printed by the error functions. --- vitunes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vitunes.c b/vitunes.c index 6d0c2ba..b09bc22 100644 --- a/vitunes.c +++ b/vitunes.c @@ -434,7 +434,7 @@ load_config() free(line); } if (ferror(fin)) - fatal("error reading config file '%s'", conf_file); + fatal("error reading config file"); fclose(fin); } From 9646532c8f8fe3e558f4c3b882c7bd00f040903e Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 31 May 2013 21:43:54 +0100 Subject: [PATCH 31/42] Add accepted character options to the structure. Not used, yet. However, it will allow to get rid of the e-command parse function. All e-commands (when applicable), will then use the generic parse function and the to be added arguments functions to check options and retrieve values. Idea taken from tmux. --- ecmd.h | 1 + ecmd_add.c | 1 + ecmd_addurl.c | 1 + ecmd_check.c | 1 + ecmd_flush.c | 1 + ecmd_help.c | 1 + ecmd_init.c | 1 + ecmd_rmfile.c | 1 + ecmd_tag.c | 1 + ecmd_update.c | 1 + 10 files changed, 10 insertions(+) diff --git a/ecmd.h b/ecmd.h index 4ae8e47..fae32ad 100644 --- a/ecmd.h +++ b/ecmd.h @@ -22,6 +22,7 @@ struct ecmd { const char *name; const char *alias; /* may be NULL */ const char *usage; /* may be NULL */ + const char *optstring; int args_lower; /* minimum number of arguments */ int args_upper; /* negative number means no limit */ int (*parse)(int argc, char **argv); /* may be NULL */ diff --git a/ecmd_add.c b/ecmd_add.c index 882d3d2..efb61b0 100644 --- a/ecmd_add.c +++ b/ecmd_add.c @@ -36,6 +36,7 @@ ecmd_add_exec(UNUSED int argc, char **argv) const struct ecmd ecmd_add = { "add", NULL, "path [...]", + NULL, 1, -1, NULL, NULL, diff --git a/ecmd_addurl.c b/ecmd_addurl.c index 3c06352..171b3a0 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -95,6 +95,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) const struct ecmd ecmd_addurl = { "addurl", NULL, "URL|path", + NULL, 1, 1, NULL, NULL, diff --git a/ecmd_check.c b/ecmd_check.c index 8d6dfe7..fac72a7 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -155,6 +155,7 @@ ecmd_check_exec(int argc, char **argv) const struct ecmd ecmd_check = { "check", NULL, "-d | -r | -s path [...]", + "drs", 1, -1, ecmd_check_parse, ecmd_check_check, diff --git a/ecmd_flush.c b/ecmd_flush.c index 66a1d68..4a892e6 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -57,6 +57,7 @@ ecmd_flush_exec(UNUSED int argc, UNUSED char **argv) const struct ecmd ecmd_flush = { "flush", NULL, "[-t format]", + "t:", 0, 0, ecmd_flush_parse, NULL, diff --git a/ecmd_help.c b/ecmd_help.c index 15bb476..bef12fc 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -71,6 +71,7 @@ The list of available commands are:\n\n\ const struct ecmd ecmd_help = { "help", NULL, "[command]", + NULL, 0, 1, NULL, NULL, diff --git a/ecmd_init.c b/ecmd_init.c index b0857dc..3de6c52 100644 --- a/ecmd_init.c +++ b/ecmd_init.c @@ -33,6 +33,7 @@ ecmd_init_exec(UNUSED int argc, UNUSED char **argv) const struct ecmd ecmd_init = { "init", NULL, NULL, + NULL, 0, 0, NULL, NULL, diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index ff49675..47b7753 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -90,6 +90,7 @@ ecmd_rmfile_exec(UNUSED int argc, char **argv) const struct ecmd ecmd_rmfile = { "rmfile", "rm", "[-f] URL|path", + "f", 1, 1, ecmd_rmfile_parse, NULL, diff --git a/ecmd_tag.c b/ecmd_tag.c index b4f3c85..ee305ee 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -146,6 +146,7 @@ const struct ecmd ecmd_tag = { "tag", NULL, "[-A album] [-T track] [-a artist] [-c comment] [-g genre] [-t title]\n\ \t[-y year] path [...]", + "A:T:a:c:g:t:y:", 1, -1, ecmd_tag_parse, ecmd_tag_check, diff --git a/ecmd_update.c b/ecmd_update.c index 877b1e6..cb1efb5 100644 --- a/ecmd_update.c +++ b/ecmd_update.c @@ -64,6 +64,7 @@ ecmd_update_exec(UNUSED int argc, UNUSED char **argv) const struct ecmd ecmd_update = { "update", NULL, "[-fs]", + "fs", 0, 0, ecmd_update_parse, NULL, From 952171b4155c8c59b07e3ea5c24efe09815b641f Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 31 May 2013 22:14:08 +0100 Subject: [PATCH 32/42] Add function that copies arguments. --- str2argv.c | 14 ++++++++++++++ str2argv.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/str2argv.c b/str2argv.c index 2ebc6fd..28e2113 100644 --- a/str2argv.c +++ b/str2argv.c @@ -59,6 +59,20 @@ argv_addch(int argc, char **argv, int c) argv[argc][n] = c; } +char ** +argv_copy(int argc, char **argv) +{ + char **new_argv; + int i; + + new_argv = xcalloc(argc + 1, sizeof *new_argv); + for (i = 0; i < argc; i++) + new_argv[i] = xstrdup(argv[i]); + new_argv[i] = NULL; + + return new_argv; +} + /* complete the current entry in the argc/argv and setup the next one */ void argv_finish_token(int *argc, char ***argv) diff --git a/str2argv.h b/str2argv.h index d826d07..1db0428 100644 --- a/str2argv.h +++ b/str2argv.h @@ -41,4 +41,9 @@ void argv_free(int *argc, char ***argv); */ char *argv2str(int argc, char *argv[]); +/* + * Duplicates the given argc/argv set of parameters. + */ +char **argv_copy(int argc, char **argv); + #endif From 08e77c34dbafdfeed4aac5a464b22768fdc14b0c Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 31 May 2013 22:15:05 +0100 Subject: [PATCH 33/42] Fix off-by-one. It would occur on zero arguments. --- str2argv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/str2argv.c b/str2argv.c index 28e2113..dc420a7 100644 --- a/str2argv.c +++ b/str2argv.c @@ -39,7 +39,7 @@ argv_free(int *argc, char ***argv) { int i; - for (i = 0; i <= *argc; i++) + for (i = 0; i < *argc; i++) free((*argv)[i]); free(*argv); From 7e915e8683a68e94ae0b4573766c97a3c53c6a3e Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 31 May 2013 22:18:15 +0100 Subject: [PATCH 34/42] Add e-command generic getopt arguments support. This uses the red-black tree implementation from OpenBSD. Other data structures should probably be converted in the future, accordingly, instead of rolling our own and sticking only to arrays. Not working for other operating systems, yet. --- Makefile | 2 +- compat.h | 1 + ecmd.c | 33 ++++++++++-------- ecmd_args.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ecmd_args.h | 40 ++++++++++++++++++++++ 5 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 ecmd_args.c create mode 100644 ecmd_args.h diff --git a/Makefile b/Makefile index 1e3b254..a1e4bbd 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ CFLAGS += -c -std=c89 -Wall -Wextra -Wno-unused-value $(CDEBUG) $(CDEPS) LIBS += -lm -lncurses -lutil $(LDEPS) # object files -OBJS=commands.o compat.o ecmd.o \ +OBJS=commands.o compat.o ecmd.o ecmd_args.o \ ecmd_add.o ecmd_addurl.o ecmd_check.o \ ecmd_flush.o ecmd_help.o ecmd_init.o \ ecmd_rmfile.o ecmd_tag.o ecmd_update.o \ diff --git a/compat.h b/compat.h index ac349c6..9ec0a55 100644 --- a/compat.h +++ b/compat.h @@ -38,6 +38,7 @@ /* OpenBSD has fparseln(3), but it must be included thusly */ #if defined(__OpenBSD__) +# include # include # include # include diff --git a/ecmd.c b/ecmd.c index 3478426..fd52d0b 100644 --- a/ecmd.c +++ b/ecmd.c @@ -20,23 +20,26 @@ #include #include "ecmd.h" +#include "ecmd_args.h" #include "error.h" #include "vitunes.h" -static int -ecmd_parse(const struct ecmd *ecmd, int argc, char ***argv) +static struct ecmd_args * +ecmd_parse(const struct ecmd *ecmd, int argc, char **argv) { - /* reset getopt(3) variables */ - optind = 0; - optreset = 1; + struct ecmd_args *args; + + /* generically parse command-line options */ + if ((args = ecmd_args_parse(ecmd->optstring, argc, argv)) == NULL) + return NULL; /* parse command line and if valid, skip parsed arguments */ if (ecmd->parse != NULL) { /* parse error */ - if (ecmd->parse(argc, *argv) == -1) - return -1; + if (ecmd->parse(argc, argv) == -1) + return NULL; if (ecmd->check != NULL && ecmd->check() == -1) - return -1; + return NULL; argc -= optind; *argv += optind; } else { @@ -47,12 +50,11 @@ ecmd_parse(const struct ecmd *ecmd, int argc, char ***argv) /* invalid number of arguments */ if (argc < ecmd->args_lower) - return -1; + return NULL; if (ecmd->args_upper >= 0 && argc > ecmd->args_upper) - return -1; + return NULL; - /* return updated (no name) number of arguments */ - return argc; + return args; } int @@ -70,8 +72,9 @@ ecmd_exec(const char *ecmd, int argc, char **argv) &ecmd_tag, &ecmd_update, }; - static const int ecmdtab_size = sizeof ecmdtab / sizeof ecmdtab[0]; - int i; + static const int ecmdtab_size = sizeof ecmdtab / sizeof ecmdtab[0]; + int i; + struct ecmd_args *args; /* search for e-command (first by name and then by alias) */ for (i = 0; i < ecmdtab_size; i++) { @@ -87,7 +90,7 @@ ecmd_exec(const char *ecmd, int argc, char **argv) } /* parse e-command arguments */ - if ((argc = ecmd_parse(ecmdtab[i], argc, &argv)) == -1) { + if ((args = ecmd_parse(ecmdtab[i], argc, argv)) == NULL) { fprintf(stderr, "usage: %s -e %s %s\n", progname, ecmdtab[i]->name, ecmdtab[i]->usage != NULL ? ecmdtab[i]->usage : ""); return 1; diff --git a/ecmd_args.c b/ecmd_args.c new file mode 100644 index 0000000..78c8705 --- /dev/null +++ b/ecmd_args.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "ecmd_args.h" +#include "str2argv.h" +#include "xmalloc.h" + +/* E-command arguments compare function. */ +static int +ecmd_args_cmp(struct ecmd_args_entry *entry1, struct ecmd_args_entry *entry2) +{ + return entry1->flag - entry2->flag; +} + +/* Tree prototypes and functions. */ +RB_PROTOTYPE_STATIC(ecmd_args_tree, ecmd_args_entry, entry, ecmd_args_cmp); +RB_GENERATE_STATIC(ecmd_args_tree, ecmd_args_entry, entry, ecmd_args_cmp); + +/* Find flag in the arguments tree. */ +static struct ecmd_args_entry * +ecmd_args_find(struct ecmd_args *args, int flag) +{ + struct ecmd_args_entry entry; + + entry.flag = flag; + return RB_FIND(ecmd_args_tree, &args->tree, &entry); +} + +/* Add a flag and value to the arguments tree. */ +void +ecmd_args_add(struct ecmd_args *args, int flag, const char *value) +{ + struct ecmd_args_entry *entry; + + /* Remove existing value. */ + if ((entry = ecmd_args_find(args, flag)) != NULL) { + free(entry->value); + if (value != NULL) + entry->value = xstrdup(value); + else + entry->value = NULL; + return; + } + + /* New value. */ + entry = xcalloc(1, sizeof *entry); + entry->flag = flag; + if (value != NULL) + entry->value = xstrdup(value); + RB_INSERT(ecmd_args_tree, &args->tree, entry); +} + +/* + * Generically parse function that adds the flags and, if applicable, its + * values to the arguments tree. It initialises the arguments structure, which + * isn't freed on purpose, because the program always quits on error. + */ +struct ecmd_args * +ecmd_args_parse(const char *optstring, int argc, char **argv) +{ + int ch; + struct ecmd_args *args; + + /* Initialise e-command arguments structure. */ + args = xcalloc(1, sizeof *args); + + /* Reset getopt(3) variables. */ + optind = 0; + optreset = 1; + while ((ch = getopt(argc, argv, optstring)) != -1) { + if (ch == '?') + return NULL; + ecmd_args_add(args, ch, optarg); + } + argc -= optind; + argv += optind; + + args->argc = argc; + args->argv = argv_copy(argc, argv); + + return args; +} diff --git a/ecmd_args.h b/ecmd_args.h new file mode 100644 index 0000000..d8462df --- /dev/null +++ b/ecmd_args.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Tiago Cunha + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ECMD_ARGS +#define ECMD_ARGS + +#include "compat.h" + +/* E-command arguments structure. */ +struct ecmd_args_entry { + int flag; /* Argument flag. */ + char *value; /* Argument value. */ + RB_ENTRY(ecmd_args_entry) entry; +}; +RB_HEAD(ecmd_args_tree, ecmd_args_entry); + +struct ecmd_args { + struct ecmd_args_tree tree; /* Tree of arguments. */ + int argc; + char **argv; +}; + +struct ecmd_args; +void ecmd_args_add(struct ecmd_args *, int, const char *); +struct ecmd_args *ecmd_args_parse(const char *, int, char **); + +#endif From 6418ee837b757a11195cb045ce70370d78b14158 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Fri, 31 May 2013 22:21:48 +0100 Subject: [PATCH 35/42] Simplify printing an e-command usage. --- ecmd.c | 2 +- ecmd.h | 2 +- ecmd_init.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ecmd.c b/ecmd.c index fd52d0b..528789c 100644 --- a/ecmd.c +++ b/ecmd.c @@ -92,7 +92,7 @@ ecmd_exec(const char *ecmd, int argc, char **argv) /* parse e-command arguments */ if ((args = ecmd_parse(ecmdtab[i], argc, argv)) == NULL) { fprintf(stderr, "usage: %s -e %s %s\n", progname, ecmdtab[i]->name, - ecmdtab[i]->usage != NULL ? ecmdtab[i]->usage : ""); + ecmdtab[i]->usage); return 1; } diff --git a/ecmd.h b/ecmd.h index fae32ad..8a27b2a 100644 --- a/ecmd.h +++ b/ecmd.h @@ -21,7 +21,7 @@ struct ecmd { const char *name; const char *alias; /* may be NULL */ - const char *usage; /* may be NULL */ + const char *usage; /* may be an empty string */ const char *optstring; int args_lower; /* minimum number of arguments */ int args_upper; /* negative number means no limit */ diff --git a/ecmd_init.c b/ecmd_init.c index 3de6c52..3b06567 100644 --- a/ecmd_init.c +++ b/ecmd_init.c @@ -32,7 +32,7 @@ ecmd_init_exec(UNUSED int argc, UNUSED char **argv) const struct ecmd ecmd_init = { "init", NULL, - NULL, + "", NULL, 0, 0, NULL, From db1891d8a819d7c61e225250ab75d95fde301f54 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 15:55:37 +0100 Subject: [PATCH 36/42] Skip e-command name. --- ecmd_args.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ecmd_args.c b/ecmd_args.c index 78c8705..bc9cea7 100644 --- a/ecmd_args.c +++ b/ecmd_args.c @@ -80,8 +80,8 @@ ecmd_args_parse(const char *optstring, int argc, char **argv) /* Initialise e-command arguments structure. */ args = xcalloc(1, sizeof *args); - /* Reset getopt(3) variables. */ - optind = 0; + /* Reset getopt(3) variables (skip e-command name). */ + optind = 1; optreset = 1; while ((ch = getopt(argc, argv, optstring)) != -1) { if (ch == '?') From 274e750dce2ba231e93e4a575117b0f2e5725466 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 15:45:44 +0100 Subject: [PATCH 37/42] Unhook parse function. --- ecmd.c | 21 ++++----------------- ecmd_args.c | 11 +++++++++++ ecmd_args.h | 1 + 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/ecmd.c b/ecmd.c index 528789c..5e41fe9 100644 --- a/ecmd.c +++ b/ecmd.c @@ -32,26 +32,13 @@ ecmd_parse(const struct ecmd *ecmd, int argc, char **argv) /* generically parse command-line options */ if ((args = ecmd_args_parse(ecmd->optstring, argc, argv)) == NULL) return NULL; + if (ecmd->check != NULL && ecmd->check() == -1) + return NULL; - /* parse command line and if valid, skip parsed arguments */ - if (ecmd->parse != NULL) { - /* parse error */ - if (ecmd->parse(argc, argv) == -1) - return NULL; - if (ecmd->check != NULL && ecmd->check() == -1) - return NULL; - argc -= optind; - *argv += optind; - } else { - /* no parse function; skip only its name */ - argc--; - (*argv)++; - } - /* invalid number of arguments */ - if (argc < ecmd->args_lower) + if (args->argc < ecmd->args_lower) return NULL; - if (ecmd->args_upper >= 0 && argc > ecmd->args_upper) + if (ecmd->args_upper >= 0 && args->argc > ecmd->args_upper) return NULL; return args; diff --git a/ecmd_args.c b/ecmd_args.c index bc9cea7..bad1673 100644 --- a/ecmd_args.c +++ b/ecmd_args.c @@ -66,6 +66,17 @@ ecmd_args_add(struct ecmd_args *args, int flag, const char *value) RB_INSERT(ecmd_args_tree, &args->tree, entry); } +/* Get e-command argument value. */ +const char * +ecmd_args_get(struct ecmd_args *args, int flag) +{ + struct ecmd_args_entry *entry; + + if ((entry = ecmd_args_find(args, flag)) == NULL) + return NULL; + return entry->value; +} + /* * Generically parse function that adds the flags and, if applicable, its * values to the arguments tree. It initialises the arguments structure, which diff --git a/ecmd_args.h b/ecmd_args.h index d8462df..b55749e 100644 --- a/ecmd_args.h +++ b/ecmd_args.h @@ -35,6 +35,7 @@ struct ecmd_args { struct ecmd_args; void ecmd_args_add(struct ecmd_args *, int, const char *); +const char *ecmd_args_get(struct ecmd_args *, int); struct ecmd_args *ecmd_args_parse(const char *, int, char **); #endif From 57249275059a6a80ad6995d5a304a4f95d8b5fc7 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 16:02:47 +0100 Subject: [PATCH 38/42] Functions should now use the arguments structure. --- ecmd.c | 5 ++--- ecmd.h | 8 +++++--- ecmd_add.c | 4 ++-- ecmd_addurl.c | 7 ++++--- ecmd_args.c | 10 ++++++++++ ecmd_args.h | 1 + ecmd_check.c | 14 +++++++------- ecmd_flush.c | 2 +- ecmd_help.c | 8 ++++---- ecmd_init.c | 2 +- ecmd_rmfile.c | 8 ++++---- ecmd_tag.c | 12 ++++++------ ecmd_update.c | 2 +- 13 files changed, 48 insertions(+), 35 deletions(-) diff --git a/ecmd.c b/ecmd.c index 5e41fe9..e961d1d 100644 --- a/ecmd.c +++ b/ecmd.c @@ -20,7 +20,6 @@ #include #include "ecmd.h" -#include "ecmd_args.h" #include "error.h" #include "vitunes.h" @@ -32,7 +31,7 @@ ecmd_parse(const struct ecmd *ecmd, int argc, char **argv) /* generically parse command-line options */ if ((args = ecmd_args_parse(ecmd->optstring, argc, argv)) == NULL) return NULL; - if (ecmd->check != NULL && ecmd->check() == -1) + if (ecmd->check != NULL && ecmd->check(args) == -1) return NULL; /* invalid number of arguments */ @@ -84,6 +83,6 @@ ecmd_exec(const char *ecmd, int argc, char **argv) } /* finally execute it */ - ecmdtab[i]->exec(argc, argv); + ecmdtab[i]->exec(args); return 0; } diff --git a/ecmd.h b/ecmd.h index 8a27b2a..e224aff 100644 --- a/ecmd.h +++ b/ecmd.h @@ -18,6 +18,8 @@ #ifndef ECMD_H #define ECMD_H +#include "ecmd_args.h" + struct ecmd { const char *name; const char *alias; /* may be NULL */ @@ -25,9 +27,9 @@ struct ecmd { const char *optstring; int args_lower; /* minimum number of arguments */ int args_upper; /* negative number means no limit */ - int (*parse)(int argc, char **argv); /* may be NULL */ - int (*check)(void); /* may be NULL */ - void (*exec)(int argc, char **argv); + int (*parse)(int argc, char **argv); /* may be NULL */ + int (*check)(struct ecmd_args *args); /* may be NULL */ + void (*exec)(struct ecmd_args *args); }; extern const struct ecmd ecmd_add; diff --git a/ecmd_add.c b/ecmd_add.c index efb61b0..d6693e1 100644 --- a/ecmd_add.c +++ b/ecmd_add.c @@ -22,13 +22,13 @@ #include "vitunes.h" static void -ecmd_add_exec(UNUSED int argc, char **argv) +ecmd_add_exec(struct ecmd_args *args) { printf("Loading existing database...\n"); medialib_load(db_file, playlist_dir); printf("Scanning directories for files to add to database...\n"); - medialib_db_scan_dirs(argv); + medialib_db_scan_dirs(args->argv); medialib_destroy(); } diff --git a/ecmd_addurl.c b/ecmd_addurl.c index 171b3a0..5c4f0de 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -27,7 +27,7 @@ #include "xmalloc.h" static void -ecmd_addurl_exec(UNUSED int argc, char **argv) +ecmd_addurl_exec(struct ecmd_args *args) { meta_info *m; bool found; @@ -38,7 +38,7 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) /* start new record, set filename */ m = mi_new(); m->is_url = true; - m->filename = xstrdup(argv[0]); + m->filename = xstrdup(args->argv[0]); /* get fields from user */ for (field = 0; field < MI_NUM_CINFO; field++) { @@ -70,7 +70,8 @@ ecmd_addurl_exec(UNUSED int argc, char **argv) } if (found) { - printf("Warning: file/URL '%s' already in the database.\n", argv[0]); + printf("Warning: file/URL '%s' already in the database.\n", + args->argv[0]); printf("Do you want to replace the existing record? [y/n] "); if (fgets(input, sizeof(input), stdin) == NULL diff --git a/ecmd_args.c b/ecmd_args.c index bad1673..c996763 100644 --- a/ecmd_args.c +++ b/ecmd_args.c @@ -66,6 +66,16 @@ ecmd_args_add(struct ecmd_args *args, int flag, const char *value) RB_INSERT(ecmd_args_tree, &args->tree, entry); } +/* + * Checks if the arguments tree is empty. Useful for those e-commands that need + * at least one flag. + */ +int +ecmd_args_empty(struct ecmd_args *args) +{ + return RB_EMPTY(&args->tree); +} + /* Get e-command argument value. */ const char * ecmd_args_get(struct ecmd_args *args, int flag) diff --git a/ecmd_args.h b/ecmd_args.h index b55749e..4509897 100644 --- a/ecmd_args.h +++ b/ecmd_args.h @@ -35,6 +35,7 @@ struct ecmd_args { struct ecmd_args; void ecmd_args_add(struct ecmd_args *, int, const char *); +int ecmd_args_empty(struct ecmd_args *); const char *ecmd_args_get(struct ecmd_args *, int); struct ecmd_args *ecmd_args_parse(const char *, int, char **); diff --git a/ecmd_check.c b/ecmd_check.c index fac72a7..2bdf95a 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -131,7 +131,7 @@ ecmd_check_parse(int argc, char **argv) } static int -ecmd_check_check(void) +ecmd_check_check(struct ecmd_args *args) { if (!show_raw && !show_sanitized && !show_database) return -1; @@ -139,16 +139,16 @@ ecmd_check_check(void) } static void -ecmd_check_exec(int argc, char **argv) +ecmd_check_exec(struct ecmd_args *args) { int i; /* scan through files... */ - for (i = 0; i < argc; i++) { - printf("Checking: '%s'\n", argv[i]); - ecmd_check_show_raw(argv[i]); - ecmd_check_show_sanitized(argv[i]); - ecmd_check_show_db(argv[i]); + for (i = 0; i < args->argc; i++) { + printf("Checking: '%s'\n", args->argv[i]); + ecmd_check_show_raw(args->argv[i]); + ecmd_check_show_sanitized(args->argv[i]); + ecmd_check_show_db(args->argv[i]); } } diff --git a/ecmd_flush.c b/ecmd_flush.c index 4a892e6..3c3e57a 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -47,7 +47,7 @@ ecmd_flush_parse(int argc, char **argv) } static void -ecmd_flush_exec(UNUSED int argc, UNUSED char **argv) +ecmd_flush_exec(UNUSED struct ecmd_args *args) { medialib_load(db_file, playlist_dir); medialib_db_flush(stdout, time_format); diff --git a/ecmd_help.c b/ecmd_help.c index bef12fc..542eb21 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -25,12 +25,12 @@ #include "xmalloc.h" static void -ecmd_help_exec(UNUSED int argc, char **argv) +ecmd_help_exec(struct ecmd_args *args) { char *man_args[3]; /* no help requested for a specific command, give a list of all e-cmds */ - if (argc == 0) { + if (args->argc == 0) { printf("\ The following is a list of e-commands supported by vitunes.\n\ Each command is executed by doing:\n\ @@ -55,13 +55,13 @@ The list of available commands are:\n\n\ } /* if reach here, help fora specific command was requested */ - if (strcmp(argv[0], "help") == 0) { + if (strcmp(args->argv[0], "help") == 0) { printf("You're a damn fool if you need help with help.\n"); return; } man_args[0] = "man"; - xasprintf(&man_args[1], "vitunes-%s", argv[0]); + xasprintf(&man_args[1], "vitunes-%s", args->argv[0]); man_args[2] = NULL; execvp("man", man_args); diff --git a/ecmd_init.c b/ecmd_init.c index 3b06567..d411407 100644 --- a/ecmd_init.c +++ b/ecmd_init.c @@ -22,7 +22,7 @@ #include "vitunes.h" static void -ecmd_init_exec(UNUSED int argc, UNUSED char **argv) +ecmd_init_exec(UNUSED struct ecmd_args *args) { printf("Creating all necessary files and directories for vitunes...\n"); medialib_setup_files(vitunes_dir, db_file, playlist_dir); diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index 47b7753..b094dc9 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -49,7 +49,7 @@ ecmd_rmfile_parse(int argc, char **argv) } static void -ecmd_rmfile_exec(UNUSED int argc, char **argv) +ecmd_rmfile_exec(struct ecmd_args *args) { char input[255]; bool found; @@ -61,7 +61,7 @@ ecmd_rmfile_exec(UNUSED int argc, char **argv) found = false; found_idx = -1; for (i = 0; i < mdb.library->nfiles && !found; i++) { - if (strcmp(argv[0], mdb.library->files[i]->filename) == 0) { + if (strcmp(args->argv[0], mdb.library->files[i]->filename) == 0) { found = true; found_idx = i; } @@ -70,13 +70,13 @@ ecmd_rmfile_exec(UNUSED int argc, char **argv) /* if not found then error */ if (!found) { i = (forced ? 0 : 1); - infox("%s: No such file or URL", argv[0]); + infox("%s: No such file or URL", args->argv[0]); exit(i); } /* if not forced, prompt user if they are sure */ if (!forced) { - printf("Are you sure you want to delete '%s'? [y/n] ", argv[0]); + printf("Are you sure you want to delete '%s'? [y/n] ", args->argv[0]); if (fgets(input, sizeof(input), stdin) == NULL || (strcasecmp(input, "yes\n") != 0 && strcasecmp(input, "y\n") != 0)) fatalx("Operation canceled. Database unchanged."); diff --git a/ecmd_tag.c b/ecmd_tag.c index ee305ee..9bb5d1b 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -85,7 +85,7 @@ ecmd_tag_parse(int argc, char **argv) } static int -ecmd_tag_check(void) +ecmd_tag_check(struct ecmd_args *args) { if (artist == NULL && album == NULL && title == NULL && genre == NULL && track == 0 && year == 0 && comment == NULL) @@ -95,7 +95,7 @@ ecmd_tag_check(void) } static void -ecmd_tag_exec(int argc, char **argv) +ecmd_tag_exec(struct ecmd_args *args) { TagLib_File *tag_file; TagLib_Tag *tag; @@ -113,12 +113,12 @@ ecmd_tag_exec(int argc, char **argv) /* tag files ... */ taglib_set_strings_unicode(false); - for (i = 0; i < argc; i++) { - printf("tagging: '%s'\n", argv[i]); + for (i = 0; i < args->argc; i++) { + printf("tagging: '%s'\n", args->argv[i]); /* extract taglib stuff */ - if ((tag_file = taglib_file_new(argv[i])) == NULL) { - infox("TagLib: failed to open file '%s': skipping.", argv[i]); + if ((tag_file = taglib_file_new(args->argv[i])) == NULL) { + infox("TagLib: failed to open file '%s': skipping.", args->argv[i]); infox(" => Causes: format not supported by TagLib or format doesn't support tags"); continue; } diff --git a/ecmd_update.c b/ecmd_update.c index cb1efb5..4a3c35a 100644 --- a/ecmd_update.c +++ b/ecmd_update.c @@ -50,7 +50,7 @@ ecmd_update_parse(int argc, char **argv) } static void -ecmd_update_exec(UNUSED int argc, UNUSED char **argv) +ecmd_update_exec(UNUSED struct ecmd_args *args) { printf("Loading existing database...\n"); medialib_load(db_file, playlist_dir); From 2225322d60ff0b811d2a082c0b4e931c0145cc9d Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 16:17:34 +0100 Subject: [PATCH 39/42] Use arguments empty function. --- ecmd_args.c | 30 ++++++++++++++++++++++++++++++ ecmd_args.h | 4 ++++ ecmd_check.c | 4 +--- ecmd_tag.c | 6 +----- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/ecmd_args.c b/ecmd_args.c index c996763..462cf2e 100644 --- a/ecmd_args.c +++ b/ecmd_args.c @@ -18,6 +18,7 @@ #include #include "ecmd_args.h" +#include "error.h" #include "str2argv.h" #include "xmalloc.h" @@ -66,6 +67,15 @@ ecmd_args_add(struct ecmd_args *args, int flag, const char *value) RB_INSERT(ecmd_args_tree, &args->tree, entry); } +/* Checks if the given flag was set an either return true or false. */ +bool +ecmd_args_bool(struct ecmd_args *args, int flag) +{ + if (ecmd_args_find(args, flag) == NULL) + return false; + return true; +} + /* * Checks if the arguments tree is empty. Useful for those e-commands that need * at least one flag. @@ -117,3 +127,23 @@ ecmd_args_parse(const char *optstring, int argc, char **argv) return args; } + +/* + * Convert the argument value to an integer. Since, no e-command (currently) + * expects a negative value, returns -1 if the flag wasn't set. + */ +int +ecmd_args_strtonum(struct ecmd_args *args, int flag, int minval, int maxval) +{ + const char *errstr, *value; + int n; + + if ((value = ecmd_args_get(args, flag)) == NULL) + return -1; + + n = strtonum(value, minval, maxval, &errstr); + if (errstr != NULL) + fatalx("number %s", errstr); + + return n; +} diff --git a/ecmd_args.h b/ecmd_args.h index 4509897..9d0a90d 100644 --- a/ecmd_args.h +++ b/ecmd_args.h @@ -17,6 +17,8 @@ #ifndef ECMD_ARGS #define ECMD_ARGS +#include + #include "compat.h" /* E-command arguments structure. */ @@ -35,8 +37,10 @@ struct ecmd_args { struct ecmd_args; void ecmd_args_add(struct ecmd_args *, int, const char *); +bool ecmd_args_bool(struct ecmd_args *, int); int ecmd_args_empty(struct ecmd_args *); const char *ecmd_args_get(struct ecmd_args *, int); struct ecmd_args *ecmd_args_parse(const char *, int, char **); +int ecmd_args_strtonum(struct ecmd_args *, int, int, int); #endif diff --git a/ecmd_check.c b/ecmd_check.c index 2bdf95a..c2d0642 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -133,9 +133,7 @@ ecmd_check_parse(int argc, char **argv) static int ecmd_check_check(struct ecmd_args *args) { - if (!show_raw && !show_sanitized && !show_database) - return -1; - return 0; + return ecmd_args_empty(args) == 0 ? 0 : -1; } static void diff --git a/ecmd_tag.c b/ecmd_tag.c index 9bb5d1b..89780d0 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -87,11 +87,7 @@ ecmd_tag_parse(int argc, char **argv) static int ecmd_tag_check(struct ecmd_args *args) { - if (artist == NULL && album == NULL && title == NULL && genre == NULL - && track == 0 && year == 0 && comment == NULL) - return -1; - - return 0; + return ecmd_args_empty(args) == 0 ? 0 : -1; } static void From 149a8dfe62565c93bf7466aab1adf8a2c821472c Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 16:48:04 +0100 Subject: [PATCH 40/42] Use new arguments functions. --- ecmd_check.c | 18 +++++++++--------- ecmd_flush.c | 7 ++++++- ecmd_rmfile.c | 6 +++--- ecmd_tag.c | 28 ++++++++++++++++++---------- ecmd_update.c | 6 +++++- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ecmd_check.c b/ecmd_check.c index c2d0642..86039d2 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -31,14 +31,14 @@ static bool show_sanitized; static bool show_database; static void -ecmd_check_show_db(const char *path) +ecmd_check_show_db(struct ecmd_args *args, const char *path) { bool found; char realfile[PATH_MAX]; int i; meta_info *mi; - if (show_database == false) + if (ecmd_args_bool(args, 'd') == false) return; if (realpath(path, realfile) == NULL) { info("realpath failed for %s: skipping", path); @@ -68,12 +68,12 @@ ecmd_check_show_db(const char *path) } static void -ecmd_check_show_raw(const char *path) +ecmd_check_show_raw(struct ecmd_args *args, const char *path) { int i; meta_info *mi; - if (show_raw == false) + if (ecmd_args_bool(args, 'r') == false) return; if ((mi = mi_extract(path)) == NULL) { infox("Failed to extract any meta-information from '%s'", path); @@ -86,12 +86,12 @@ ecmd_check_show_raw(const char *path) } static void -ecmd_check_show_sanitized(const char *path) +ecmd_check_show_sanitized(struct ecmd_args *args, const char *path) { int i; meta_info *mi; - if (show_sanitized == false) + if (ecmd_args_bool(args, 's') == false) return; if ((mi = mi_extract(path)) == NULL) { infox("Failed to extract any meta-information from '%s'", path); @@ -144,9 +144,9 @@ ecmd_check_exec(struct ecmd_args *args) /* scan through files... */ for (i = 0; i < args->argc; i++) { printf("Checking: '%s'\n", args->argv[i]); - ecmd_check_show_raw(args->argv[i]); - ecmd_check_show_sanitized(args->argv[i]); - ecmd_check_show_db(args->argv[i]); + ecmd_check_show_raw(args, args->argv[i]); + ecmd_check_show_sanitized(args, args->argv[i]); + ecmd_check_show_db(args, args->argv[i]); } } diff --git a/ecmd_flush.c b/ecmd_flush.c index 3c3e57a..f0a71e8 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -47,8 +47,13 @@ ecmd_flush_parse(int argc, char **argv) } static void -ecmd_flush_exec(UNUSED struct ecmd_args *args) +ecmd_flush_exec(struct ecmd_args *args) { + const char *timefmt; + + if ((timefmt = ecmd_args_get(args, 't')) == NULL) + timefmt = "%Y %m %d %H:%M:%S"; + medialib_load(db_file, playlist_dir); medialib_db_flush(stdout, time_format); medialib_destroy(); diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index b094dc9..bbe068f 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -52,9 +52,8 @@ static void ecmd_rmfile_exec(struct ecmd_args *args) { char input[255]; - bool found; - int found_idx; - int i; + bool forced, found; + int found_idx, i; /* load database and search for record */ medialib_load(db_file, playlist_dir); @@ -68,6 +67,7 @@ ecmd_rmfile_exec(struct ecmd_args *args) } /* if not found then error */ + forced = ecmd_args_bool(args, 'f'); if (!found) { i = (forced ? 0 : 1); infox("%s: No such file or URL", args->argv[0]); diff --git a/ecmd_tag.c b/ecmd_tag.c index 89780d0..b6f838e 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -95,17 +95,25 @@ ecmd_tag_exec(struct ecmd_args *args) { TagLib_File *tag_file; TagLib_Tag *tag; - int i; + const char *album, *artist, *comment, *genre, *title; + int i, track, year; /* be verbose, indicate what we're setting... */ printf("Setting the following tags to all files:\n"); - if (artist != NULL) printf("%10.10s => '%s'\n", "artist", artist); - if (album != NULL) printf("%10.10s => '%s'\n", "album", album); - if (title != NULL) printf("%10.10s => '%s'\n", "title", title); - if (genre != NULL ) printf("%10.10s => '%s'\n", "genre", genre); - if (track) printf("%10.10s => %u\n", "track", track); - if (year) printf("%10.10s => %u\n", "year", year); - if (comment != NULL) printf("%10.10s => '%s'\n", "comment", comment); + if ((artist = ecmd_args_get(args, 'a')) != NULL) + printf("%10.10s => '%s'\n", "artist", artist); + if ((album = ecmd_args_get(args, 'A')) != NULL) + printf("%10.10s => '%s'\n", "album", album); + if ((title = ecmd_args_get(args, 't')) != NULL) + printf("%10.10s => '%s'\n", "title", title); + if ((genre = ecmd_args_get(args, 'g')) != NULL) + printf("%10.10s => '%s'\n", "genre", genre); + if ((track = ecmd_args_strtonum(args, 'T', 0, INT_MAX)) != -1) + printf("%10.10s => %u\n", "track", track); + if ((year = ecmd_args_strtonum(args, 'y', 0, INT_MAX)) != -1) + printf("%10.10s => %u\n", "year", year); + if ((comment = ecmd_args_get(args, 'c')) != NULL) + printf("%10.10s => '%s'\n", "comment", comment); /* tag files ... */ taglib_set_strings_unicode(false); @@ -126,8 +134,8 @@ ecmd_tag_exec(struct ecmd_args *args) if (album != NULL) taglib_tag_set_album(tag, album); if (title != NULL) taglib_tag_set_title(tag, title); if (genre != NULL) taglib_tag_set_genre(tag, genre); - if (track) taglib_tag_set_track(tag, track); - if (year) taglib_tag_set_year(tag, year); + if (track != -1) taglib_tag_set_track(tag, track); + if (year != -1) taglib_tag_set_year(tag, year); if (comment != NULL) taglib_tag_set_comment(tag, comment); diff --git a/ecmd_update.c b/ecmd_update.c index 4a3c35a..0514b6c 100644 --- a/ecmd_update.c +++ b/ecmd_update.c @@ -50,11 +50,15 @@ ecmd_update_parse(int argc, char **argv) } static void -ecmd_update_exec(UNUSED struct ecmd_args *args) +ecmd_update_exec(struct ecmd_args *args) { + bool force_update, show_skipped; + printf("Loading existing database...\n"); medialib_load(db_file, playlist_dir); + force_update = ecmd_args_bool(args, 'f'); + show_skipped = ecmd_args_bool(args, 's'); printf("Updating existing database...\n"); medialib_db_update(show_skipped, force_update); From 06732af71e7205305d5bb8bc288185c34844aa74 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Sat, 1 Jun 2013 16:51:56 +0100 Subject: [PATCH 41/42] Remove parse functions. From now on, when implementing a new e-command, there's no need to duplicate code (ie call getopt, set flags and values). It's just a matter of calling the arguments functions. --- ecmd.h | 11 +++++----- ecmd_add.c | 1 - ecmd_addurl.c | 1 - ecmd_check.c | 32 --------------------------- ecmd_flush.c | 29 +----------------------- ecmd_help.c | 1 - ecmd_init.c | 1 - ecmd_rmfile.c | 24 -------------------- ecmd_tag.c | 61 --------------------------------------------------- ecmd_update.c | 28 ----------------------- 10 files changed, 6 insertions(+), 183 deletions(-) diff --git a/ecmd.h b/ecmd.h index e224aff..fa0ac10 100644 --- a/ecmd.h +++ b/ecmd.h @@ -22,12 +22,11 @@ struct ecmd { const char *name; - const char *alias; /* may be NULL */ - const char *usage; /* may be an empty string */ - const char *optstring; - int args_lower; /* minimum number of arguments */ - int args_upper; /* negative number means no limit */ - int (*parse)(int argc, char **argv); /* may be NULL */ + const char *alias; /* may be NULL */ + const char *usage; /* may be an empty string */ + const char *optstring; /* may be NULL */ + int args_lower; /* minimum number of arguments */ + int args_upper; /* negative number means no limit */ int (*check)(struct ecmd_args *args); /* may be NULL */ void (*exec)(struct ecmd_args *args); }; diff --git a/ecmd_add.c b/ecmd_add.c index d6693e1..f749263 100644 --- a/ecmd_add.c +++ b/ecmd_add.c @@ -39,6 +39,5 @@ const struct ecmd ecmd_add = { NULL, 1, -1, NULL, - NULL, ecmd_add_exec }; diff --git a/ecmd_addurl.c b/ecmd_addurl.c index 5c4f0de..14d9fdc 100644 --- a/ecmd_addurl.c +++ b/ecmd_addurl.c @@ -99,6 +99,5 @@ const struct ecmd ecmd_addurl = { NULL, 1, 1, NULL, - NULL, ecmd_addurl_exec }; diff --git a/ecmd_check.c b/ecmd_check.c index 86039d2..b011eae 100644 --- a/ecmd_check.c +++ b/ecmd_check.c @@ -19,17 +19,12 @@ #include #include #include -#include #include "ecmd.h" #include "error.h" #include "medialib.h" #include "vitunes.h" -static bool show_raw; -static bool show_sanitized; -static bool show_database; - static void ecmd_check_show_db(struct ecmd_args *args, const char *path) { @@ -104,32 +99,6 @@ ecmd_check_show_sanitized(struct ecmd_args *args, const char *path) printf("\t%10.10s: '%s'\n", MI_CINFO_NAMES[i], mi->cinfo[i]); } -static int -ecmd_check_parse(int argc, char **argv) -{ - int ch; - - while ((ch = getopt(argc, argv, "drs")) != -1) { - switch (ch) { - case 'd': - show_database = true; - break; - case 'r': - show_raw = true; - break; - case 's': - show_sanitized = true; - break; - case 'h': - case '?': - default: - return -1; - } - } - - return 0; -} - static int ecmd_check_check(struct ecmd_args *args) { @@ -155,7 +124,6 @@ const struct ecmd ecmd_check = { "-d | -r | -s path [...]", "drs", 1, -1, - ecmd_check_parse, ecmd_check_check, ecmd_check_exec }; diff --git a/ecmd_flush.c b/ecmd_flush.c index f0a71e8..4eb6914 100644 --- a/ecmd_flush.c +++ b/ecmd_flush.c @@ -15,37 +15,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include - #include "ecmd.h" -#include "error.h" #include "medialib.h" #include "vitunes.h" #include "xmalloc.h" -static char *time_format = "%Y %m %d %H:%M:%S"; - -static int -ecmd_flush_parse(int argc, char **argv) -{ - int ch; - - while ((ch = getopt(argc, argv, "t:")) != -1) { - switch (ch) { - case 't': - time_format = xstrdup(optarg); - break; - case '?': - case 'h': - default: - return -1; - } - } - - return 0; -} - static void ecmd_flush_exec(struct ecmd_args *args) { @@ -55,7 +29,7 @@ ecmd_flush_exec(struct ecmd_args *args) timefmt = "%Y %m %d %H:%M:%S"; medialib_load(db_file, playlist_dir); - medialib_db_flush(stdout, time_format); + medialib_db_flush(stdout, timefmt); medialib_destroy(); } @@ -64,7 +38,6 @@ const struct ecmd ecmd_flush = { "[-t format]", "t:", 0, 0, - ecmd_flush_parse, NULL, ecmd_flush_exec }; diff --git a/ecmd_help.c b/ecmd_help.c index 542eb21..65b1f16 100644 --- a/ecmd_help.c +++ b/ecmd_help.c @@ -74,6 +74,5 @@ const struct ecmd ecmd_help = { NULL, 0, 1, NULL, - NULL, ecmd_help_exec }; diff --git a/ecmd_init.c b/ecmd_init.c index d411407..96592d5 100644 --- a/ecmd_init.c +++ b/ecmd_init.c @@ -36,6 +36,5 @@ const struct ecmd ecmd_init = { NULL, 0, 0, NULL, - NULL, ecmd_init_exec }; diff --git a/ecmd_rmfile.c b/ecmd_rmfile.c index bbe068f..56a9f2f 100644 --- a/ecmd_rmfile.c +++ b/ecmd_rmfile.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "ecmd.h" #include "error.h" @@ -26,28 +25,6 @@ #include "playlist.h" #include "vitunes.h" -static bool forced; - -static int -ecmd_rmfile_parse(int argc, char **argv) -{ - int ch; - - while ((ch = getopt(argc, argv, "f")) != -1) { - switch (ch) { - case 'f': - forced = true; - break; - case 'h': - case '?': - default: - return -1; - } - } - - return 0; -} - static void ecmd_rmfile_exec(struct ecmd_args *args) { @@ -92,7 +69,6 @@ const struct ecmd ecmd_rmfile = { "[-f] URL|path", "f", 1, 1, - ecmd_rmfile_parse, NULL, ecmd_rmfile_exec }; diff --git a/ecmd_tag.c b/ecmd_tag.c index b6f838e..d49b3b7 100644 --- a/ecmd_tag.c +++ b/ecmd_tag.c @@ -17,10 +17,6 @@ #include #include -#include -#include -#include - #include #include "ecmd.h" @@ -28,62 +24,6 @@ #include "meta_info.h" #include "xmalloc.h" -static char *artist; -static char *album; -static char *title; -static char *genre; -static char *comment; -static unsigned int track; -static unsigned int year; - -static int -ecmd_tag_parse(int argc, char **argv) -{ - const char *errstr; - int ch; - - while ((ch = getopt(argc, argv, "A:T:a:c:g:t:y:")) != -1) { - switch (ch) { - case 'A': - free(album); - album = xstrdup(optarg); - break; - case 'T': - track = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); - if (errstr != NULL) - fatalx("invalid track '%s': %s", optarg, errstr); - break; - case 'a': - free(artist); - artist = xstrdup(optarg); - break; - case 'c': - free(comment); - comment = xstrdup(optarg); - break; - case 'g': - free(genre); - genre = xstrdup(optarg); - break; - case 't': - free(title); - title = xstrdup(optarg); - break; - case 'y': - year = (unsigned int) strtonum(optarg, 0, INT_MAX, &errstr); - if (errstr != NULL) - fatalx("invalid year '%s': %s", optarg, errstr); - break; - case 'h': - case '?': - default: - return -1; - } - } - - return 0; -} - static int ecmd_tag_check(struct ecmd_args *args) { @@ -152,7 +92,6 @@ const struct ecmd ecmd_tag = { \t[-y year] path [...]", "A:T:a:c:g:t:y:", 1, -1, - ecmd_tag_parse, ecmd_tag_check, ecmd_tag_exec }; diff --git a/ecmd_update.c b/ecmd_update.c index 0514b6c..20ca9f0 100644 --- a/ecmd_update.c +++ b/ecmd_update.c @@ -17,38 +17,11 @@ #include #include -#include #include "ecmd.h" #include "medialib.h" #include "vitunes.h" -static bool force_update; -static bool show_skipped; - -static int -ecmd_update_parse(int argc, char **argv) -{ - int ch; - - while ((ch = getopt(argc, argv, "fs")) != -1) { - switch (ch) { - case 'f': - force_update = true; - break; - case 's': - show_skipped = true; - break; - case 'h': - case '?': - default: - return -1; - } - } - - return 0; -} - static void ecmd_update_exec(struct ecmd_args *args) { @@ -70,7 +43,6 @@ const struct ecmd ecmd_update = { "[-fs]", "fs", 0, 0, - ecmd_update_parse, NULL, ecmd_update_exec }; From dfeb5f6d88fabd259e230bb68c5cef21d003471a Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Thu, 6 Jun 2013 18:28:06 +0100 Subject: [PATCH 42/42] Add tree header file from OpenBSD. On other operating systems, the local tree.h file is included. Not tested, though. The compat code probably needs some rework. --- compat.h | 4 + compat/tree.h | 748 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 752 insertions(+) create mode 100644 compat/tree.h diff --git a/compat.h b/compat.h index 9ec0a55..a8e89ab 100644 --- a/compat.h +++ b/compat.h @@ -50,24 +50,28 @@ # include # include # include +# include "tree.h" #endif /* Mac OS X has fparseln(3), but it must be included thusly */ #if defined(__MACH__) # include # include +# include "tree.h" #endif /* Mac OS X needs strtonum(3) */ #if defined(__APPLE__) && defined(__MACH__) # include # include +# include "tree.h" # define COMPAT_NEED_STRTONUM # define COMPAT_NEED_STRTOLL #endif /* Linux needs the following.. */ #if defined(__linux) +# include "tree.h" # define _GNU_SOURCE # define COMPAT_NEED_FPARSELN # define COMPAT_NEED_OPTRESET diff --git a/compat/tree.h b/compat/tree.h new file mode 100644 index 0000000..80d0f53 --- /dev/null +++ b/compat/tree.h @@ -0,0 +1,748 @@ +/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */ +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ + (x) = (y)) + +#endif /* _SYS_TREE_H_ */