]> Trent Huber's Code - xpmview.git/commitdiff
Use err.h for error messaging
authorTrent Huber <trentmhuber@gmail.com>
Tue, 6 May 2025 02:29:07 +0000 (22:29 -0400)
committerTrent Huber <trentmhuber@gmail.com>
Tue, 6 May 2025 02:29:07 +0000 (22:29 -0400)
16 files changed:
build.h
clean.c
external/build.c
external/cbs
src/build.c
src/cbs.h [new file with mode: 0644]
src/colors.h [new file with mode: 0644]
src/colors/build.c
src/colors/gencolors.c
src/font/build.c
src/font/genfont.c
src/main.c
src/options.c
src/utilities.c [deleted file]
src/utilities.h [deleted file]
src/xpm.c

diff --git a/build.h b/build.h
index 1a61d1071117284239c623c7682cbf661804fe95..c18406462a17f57ca3d26598f6ec830b290629f4 100644 (file)
--- a/build.h
+++ b/build.h
@@ -1,42 +1,32 @@
 /* Switch the following #define to change whether or not raylib is built as a
  * static or dynamic library; be sure to `clean' before you `build' again.
  */
-// #define RLDYNAMIC
+// #define DYNAMICLIBS
 
-#ifdef RLDYNAMIC
-#define RLEXT DYEXT
+#ifdef DYNAMICLIBS
+#define LIBEXT DYEXT
 #else
-#define RLEXT ".a"
+#define LIBEXT ".a"
 #endif
 
-#define CBSPATH ROOT "external/cbs/"
-#define CBS CBSPATH "cbs.c"
+#define CBSROOT ROOT "external/cbs/"
+#define CBSLIB CBSROOT "cbs" LIBEXT
 #define RLROOT ROOT "external/raylib/"
-#define RLLIB RLROOT "raylib" RLEXT
+#define RLLIB RLROOT "raylib" LIBEXT
 #define RLSRC RLROOT "src/"
 #define RLHDR RLSRC "raylib"
 #define SIMPLEXPM ROOT "bin/simplexpm"
 #define SRC ROOT "src/"
-#define UTILS SRC "utilities"
 
-#define CFCBS "-I" CBSPATH
 #define CFRAYLIB "-I" RLSRC
-#define CFSRC "-I" SRC
 
 #ifdef __APPLE__
-#define RLLFLAGS \
+#define LFRAYLIB \
    "-framework", "Cocoa", \
    "-framework", "CoreVideo", \
    "-framework", "GLUT", \
    "-framework", "IOKit", \
    "-framework", "OpenGL"
 #else
-#define RLLFLAGS "-lm"
-#endif
-#ifdef RLDYNAMIC
-#define LFEXTERNAL RLLFLAGS
-#define LFRAYLIB NULL
-#else
-#define LFEXTERNAL NULL
-#define LFRAYLIB RLLFLAGS
+#define LFRAYLIB "-lm"
 #endif
diff --git a/clean.c b/clean.c
index 1cce666483553fc67da5fc02b4275a94fc85b9a4..04a9da47725930392b504016f6caa52303472e47 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -15,7 +15,7 @@ int main(void) {
    size_t i;
    pid_t cpid;
 
-   what = "removal";
+   what = "remove";
 
    // Remove build executables and object files
    whos = (char *[2]){"{*/*build,*/*/*build}", "{*/*.o,*/*/*.o,*/*/*/*.o}"};
@@ -27,16 +27,16 @@ int main(void) {
        await(cpid, what, whos[i]);
    }
 
-   /* Remove raylib library, application executables,
+   /* Remove cbs and raylib libraries, application executables,
     * automatically generated source files, and ourself
     */
-   whos = (char *[4]){extend(RLLIB, RLEXT),
+   whos = (char *[5]){extend(CBSLIB, LIBEXT), extend(RLLIB, LIBEXT),
                       "{" GENCOLORS "," GENFONT "," SIMPLEXPM "}",
                       "{" COLORS "," FONT "}", "clean"};
-   rms = (char **[4]){(char *[3]){whos[0]},
+   rms = (char **[5]){(char *[3]){whos[0]}, (char *[3]){whos[1]},
                       (char *[3]){GENCOLORS, GENFONT, SIMPLEXPM},
-                      (char *[3]){COLORS, FONT}, (char *[3]){whos[3]}};
-   for (i = 0; i < 4; ++i) {
+                      (char *[3]){COLORS, FONT}, (char *[3]){whos[4]}};
+   for (i = 0; i < 5; ++i) {
        if ((cpid = fork()) == 0)
            run(RM, (char *[]){"rm", "-f", rms[i][0], rms[i][1], rms[i][2], NULL},
                what, whos[i]);
index f8e5d9ed3a0b1a4ed2adb05eef6cd44ca6863a6f..a3f4352ddc19f68d0d4daac02f2144a2a77ccc6f 100644 (file)
@@ -1,6 +1,9 @@
 #define ROOT "../"
 #include "../build.h"
 
+#include "cbs/cbs.c"
+
+#define CBSSRC CBSROOT "cbs"
 #define RLSRCS \
    RLSRC "raudio", RLSRC "rmodels", \
    RLSRC "rshapes", RLSRC "rtext", \
 #define CFGRAPHICS "-D_GLFW_X11"
 #endif
 #define CFGLFW "-I" RLSRC "external/glfw/include"
-#ifdef RLDYNAMIC
-#define CFGLOBALS "-DPLATFORM_DESKTOP", "-fPIC"
+#ifdef DYNAMICLIBS
+#define CFPIC "-fPIC"
 #else
-#define CFGLOBALS "-DPLATFORM_DESKTOP"
+#define CFPIC NULL
+#endif
+#define CFGLOBALS "-DPLATFORM_DESKTOP", CFPIC
+
+#ifndef DYNAMICLIBS
+#undef LFRAYLIB
+#define LFRAYLIB NULL
 #endif
 
-#ifdef RLDYNAMIC
+#ifdef DYNAMICLIBS
 #define LIBTYPE 'd'
 #else
 #define LIBTYPE 's'
 #endif
 
-#include "cbs/cbs.c"
+void cbs(void) {
+   cflags = (char *[]){CFPIC, NULL};
+   compile(CBSSRC, NULL);
+   load(LIBTYPE, CBSLIB, CBSSRC, NULL);
+}
 
-int main(void) {
+void raylib(void) {
    char **src;
    size_t i;
 
-   build(NULL);
-
    src = (char *[]){RLSRCS, NULL};
    cflags = (char *[]){CFGLOBALS, NULL};
    for (i = 0; i < 6; ++i) compile(src[i], NULL);
@@ -41,8 +52,15 @@ int main(void) {
    cflags = (char *[]){CFGRAPHICS, CFGLFW, CFGLOBALS, NULL};
    compile(src[7], NULL);
 
-   lflags = (char *[]){LFEXTERNAL, NULL};
+   lflags = (char *[]){LFRAYLIB, NULL};
    load(LIBTYPE, RLLIB, RLSRCS, NULL);
+}
+
+int main(void) {
+   build(NULL);
+
+   cbs();
+   raylib();
 
    return EXIT_SUCCESS;
 }
index 47c262dc02e5f6ed3dba9e092a5f750084bfad95..51d2489cfcf1c245db14c3a9e7c9e40e6a550f4c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 47c262dc02e5f6ed3dba9e092a5f750084bfad95
+Subproject commit 51d2489cfcf1c245db14c3a9e7c9e40e6a550f4c
index d828156c6494b780992e9253a30bc4e92a05c717..17341735f278026221d55929a2bcb5bb32d8f116 100644 (file)
@@ -3,23 +3,29 @@
 
 #include "../external/cbs/cbs.c"
 
+#define CFDYEXT "-DDYEXT=\"" DYEXT "\""
+
+#ifdef DYNAMICLIBS
+#undef LFRAYLIB
+#define LFRAYLIB NULL
+#endif
+
 int main(void) {
    build(NULL);
 
-   compile("utilities", NULL);
-
    build("colors/");
    build("font/");
 
+   compile("colors", "colors", NULL);
    cflags = (char *[]){CFRAYLIB, NULL};
-   compile("main", "utilities", "options", RLHDR, "xpm", "font.c", NULL);
+   compile("main", "cbs", "options", RLHDR, "xpm", "font.c", NULL);
    cflags = NULL;
-   compile("options", "utilities", NULL);
-   cflags = (char *[]){CFRAYLIB, CFCBS, NULL};
-   compile("xpm", "utilities", RLHDR, "xpm", CBS, "colors.c", NULL);
+   compile("options", "cbs", NULL);
+   cflags = (char *[]){CFDYEXT, CFRAYLIB, NULL};
+   compile("xpm", "cbs", "colors", RLHDR, "xpm", "colors.c", NULL);
 
    lflags = (char *[]){LFRAYLIB, NULL};
-   load('x', SIMPLEXPM, "utilities", "main", "options", "xpm", RLLIB, NULL);
+   load('x', SIMPLEXPM, "colors", "main", "options", "xpm", CBSLIB, RLLIB, NULL);
 
    return EXIT_SUCCESS;
 }
diff --git a/src/cbs.h b/src/cbs.h
new file mode 100644 (file)
index 0000000..c81e516
--- /dev/null
+++ b/src/cbs.h
@@ -0,0 +1,3 @@
+void *allocate(size_t s);
+void compile(char *src, ...);
+void load(char type, char *target, char *obj, ...);
diff --git a/src/colors.h b/src/colors.h
new file mode 100644 (file)
index 0000000..9acbf69
--- /dev/null
@@ -0,0 +1,7 @@
+struct color {
+   char *name;
+   unsigned int value;
+};
+
+extern struct color colors[];
+extern size_t numcolors;
index 7e83836dc9142b75f92225234ce42d7d240b27e7..98326c320ae10a326d384955fb950fc124316fa0 100644 (file)
@@ -1,20 +1,19 @@
 #define ROOT "../../"
 #include "../../build.h"
 
-#define COLORS SRC "colors.c"
-
 #include "../../external/cbs/cbs.c"
 
+#define COLORS SRC "colors.c"
+
 int main(void) {
    build(NULL);
 
-   cflags = (char *[]){CFSRC, NULL};
-   compile("gencolors", UTILS, NULL);
-   load('x', "gencolors", "gencolors", UTILS, NULL);
+   compile("gencolors", NULL);
+   load('x', "gencolors", "gencolors", NULL);
 
    if (modified(COLORS, "gencolors.c") || modified(COLORS, "rgb.txt"))
        run("gencolors", (char *[]){"./gencolors", "rgb.txt", COLORS, NULL},
-           "execution", "gencolors");
+           "run", "gencolors");
 
    return EXIT_SUCCESS;
 }
index b5dd82c07c957112f74433f6bcad0d1739a6399f..e5c48563aa050a4f435d818b2b7293621fd65d29 100644 (file)
@@ -1,14 +1,12 @@
+#include <err.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/errno.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "utilities.h"
-
 int main(int argc, char **argv) {
    int result, infd, outfd;
    struct stat instat;
@@ -18,37 +16,31 @@ int main(int argc, char **argv) {
    unsigned char r, g, b;
 
    result = EXIT_FAILURE;
-   if (argc != 3) {
-       xpmerror("Incorrect number of arguments: %s <input.txt> <output.c>", argv[0]);
-       return result;
-   }
-   if ((infd = open(argv[1], O_RDONLY)) == -1) {
-       xpmerror("Unable to open `%s' for reading", argv[1]);
-       return result;
-   }
+   if (argc != 3)
+       errx(EXIT_FAILURE, "Incorrect number of arguments: %s <input.txt> <output.c>",
+            argv[0]);
+   if ((infd = open(argv[1], O_RDONLY)) == -1)
+       err(EXIT_FAILURE, "Unable to open `%s' for reading", argv[1]);
    if (fstat(infd, &instat) == -1) {
-       xpmerror("Unable to stat `%s'", argv[1]);
+       warn("Unable to stat `%s'", argv[1]);
        goto closein;
    }
    l = instat.st_size;
    if ((p = map = mmap(NULL, l, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE, infd, 0)) == MAP_FAILED) {
-       xpmerror("Unable to map `%s' to memory", argv[1]);
+       warn("Unable to map `%s' to memory", argv[1]);
        goto closein;
    }
    if ((outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
-       xpmerror("Unable to open `%s' for writing", argv[2]);
+       warn("Unable to open `%s' for writing", argv[2]);
        goto munmap;
    }
 
-   result = EXIT_SUCCESS;
-   if (dprintf(outfd, "struct color {\n"
-               "\tchar *name;\n"
-               "\tunsigned int value;\n"
-               "};\n\n"
-               "static struct color colors[] = {\n"
+   if (dprintf(outfd, "#include <stddef.h>\n\n"
+               "#include \"colors.h\"\n\n"
+               "struct color colors[] = {\n"
                "\t{\"None\", 0x00ffffff},\n") == -1) {
-       xpmerror("Unable to write to `%s'", argv[2]);
+       warn("Unable to write to `%s'", argv[2]);
        goto closeout;
    }
    for (i = 1; p < (char *)map + l; ++i) {
@@ -57,24 +49,32 @@ int main(int argc, char **argv) {
        b = strtol(p, &p, 10);
        if (dprintf(outfd, "\t{\"%s\", 0x%02x%02x%02x},\n",
                    strsep(&p, "\n") + 2, r, g, b) == -1) {
-           xpmerror("Unable to write to `%s'", argv[2]);
+           warn("Unable to write to `%s'", argv[2]);
            goto closeout;
        }
    }
-   if (dprintf(outfd, "};\n\nstatic size_t numcolors = %zu;\n", i) == -1)
-       xpmerror("Unable to write to `%s'", argv[2]);
+   if (dprintf(outfd, "};\n\nsize_t numcolors = %zu;\n", i) == -1)
+       warn("Unable to write to `%s'", argv[2]);
+
+   result = EXIT_SUCCESS;
 
 closeout:
-   if (close(outfd) == -1)
-       xpmerror("Unable to close `%s'", argv[2]);
+   if (close(outfd) == -1) {
+       warn("Unable to close `%s'", argv[2]);
+       result = EXIT_FAILURE;
+   }
 
 munmap:
-   if (munmap(map, l) == -1)
-       xpmerror("Unable to unmap memory associated with `%s'", argv[1]);
+   if (munmap(map, l) == -1) {
+       warn("Unable to unmap memory associated with `%s'", argv[1]);
+       result = EXIT_FAILURE;
+   }
 
 closein:
-   if (close(infd) == -1)
-       xpmerror("Unable to close `%s'", argv[1]);
+   if (close(infd) == -1) {
+       warn("Unable to close `%s'", argv[1]);
+       result = EXIT_FAILURE;
+   }
 
    return result;
 }
index 989db8bdb1ba64f18cfc4aa6ec7a7e60fb4346a8..b596a60dcddc7cbce980eb02ed7ea61606e2a9b5 100644 (file)
@@ -1,22 +1,27 @@
 #define ROOT "../../"
 #include "../../build.h"
 
+#include "../../external/cbs/cbs.c"
+
 #define FONT SRC "font.c"
 
-#include "../../external/cbs/cbs.c"
+#ifdef DYNAMICLIBS
+#undef LFRAYLIB
+#define LFRAYLIB NULL
+#endif
 
 int main(void) {
    build(NULL);
 
-   cflags = (char *[]){CFRAYLIB, CFSRC, NULL};
-   compile("genfont", UTILS, RLHDR, NULL);
+   cflags = (char *[]){CFRAYLIB, NULL};
+   compile("genfont", RLHDR, NULL);
 
    lflags = (char *[]){LFRAYLIB, NULL};
-   load('x', "genfont", "genfont", UTILS, RLLIB, NULL);
+   load('x', "genfont", "genfont", RLLIB, NULL);
 
    if (modified(FONT, "genfont.c") || modified(FONT, "font.ttf"))
        run("genfont", (char *[]){"./genfont", "font.ttf", FONT, NULL},
-           "execution", "genfont");
+           "run", "genfont");
 
    return EXIT_SUCCESS;
 }
index 764916e7feda79d0e19a1a19b88a07f4ec7cc4d0..958e2710cd7a3ff76feefa861205c6fe87ad2a29 100644 (file)
@@ -1,24 +1,21 @@
+#include <err.h>
 #include <stdlib.h>
 
 #include "raylib.h"
-#include "utilities.h"
 
 int main(int argc, char **argv) {
    Font font;
 
-   if (argc != 3) {
-       xpmerror("Incorrect number of arguments: %s <input.ttf> <output.c>", argv[0]);
-       return EXIT_FAILURE;
-   }
+   if (argc != 3)
+       errx(EXIT_FAILURE, "Incorrect number of arguments: %s <input.ttf> <output.c>",
+            argv[0]);
 
    SetTraceLogLevel(LOG_WARNING);
    InitWindow(0, 0, "");
 
    font = LoadFontEx(argv[1], 48, NULL, 95);
-   if (!ExportFontAsCode(font, argv[2])) {
-       xpmerror("Unable to generate `%s' from `%s'", argv[2], argv[1]);
-       return EXIT_FAILURE;
-   }
+   if (!ExportFontAsCode(font, argv[2]))
+       errx(EXIT_FAILURE, "Unable to generate `%s' from `%s'", argv[2], argv[1]);
 
    UnloadFont(font);
 
index b0365088a0215ae3b042e99347a5746e63cc2e79..265fc30935d3873901903e3a11caba67dafc4fe9 100644 (file)
@@ -1,19 +1,13 @@
-#include <setjmp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <unistd.h>
 
+#include "cbs.h"
 #include "options.h"
 #define SUPPORT_IMAGE_EXPORT
 #include "raylib.h"
-#include "utilities.h"
 #include "xpm.h"
 
-extern bool isGpuReady;
-
 #include "font.c"
 
 static void getinput(char **xp, Texture2D *tp, Image *ip) {
@@ -25,7 +19,7 @@ static void getinput(char **xp, Texture2D *tp, Image *ip) {
    if (IsFileDropped()) {
        files = LoadDroppedFiles();
        if (*xp) RL_FREE(*xp);
-       *xp = xpmalloc(FILENAME_MAX);
+       *xp = allocate(FILENAME_MAX);
        strcpy(*xp, files.paths[0]);
        UnloadDroppedFiles(files);
        *tp = gettexture(*xp, ip, mode);
index 62966dc5eef4af51a920fef887b317cfa4552380..e985db6ecfe5e1dbfe99b560955a3ac0514bcf8f 100644 (file)
@@ -1,10 +1,11 @@
+#include <err.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include "utilities.h"
+#include "cbs.h"
 
 static void usage(char *prog, int fd) {
    dprintf(fd, "Usage: %s [-dh] [-f file]\n"
@@ -31,7 +32,7 @@ int options(int argc, char **argv, int *debug, char **xp) {
        *debug = 1;
        break;
    case 'f':
-       *xp = xpmalloc(FILENAME_MAX);
+       *xp = allocate(FILENAME_MAX);
        strcpy(*xp, optarg);
        break;
    case 'h':
@@ -46,18 +47,18 @@ int options(int argc, char **argv, int *debug, char **xp) {
    result = 1;
    if (!*debug) {
        if ((dnfd = open("/dev/null", O_WRONLY)) == -1) {
-           xpmerror("Unable to open `/dev/null'; showing debug messages");
-           return 0;
+           warn("Unable to open `/dev/null'; showing debug messages");
+           return result;
        }
        if (close(STDOUT_FILENO) == -1) {
-           xpmerror("Unable to close stdout");
+           warn("Unable to close stdout");
            result = 0;
        } else if (dup2(dnfd, STDOUT_FILENO) == -1) {
-           xpmerror("Unable to redirect stdout to `/dev/null'");
-           exit(EXIT_FAILURE);
+           warn("Unable to redirect stdout to `/dev/null'");
+           result = 0;
        }
        if (close(dnfd) == -1) {
-           xpmerror("Unable to close `/dev/null'");
+           warn("Unable to close `/dev/null'");
            result = 0;
        }
    }
diff --git a/src/utilities.c b/src/utilities.c
deleted file mode 100644 (file)
index 00d780f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/errno.h>
-#include <unistd.h>
-
-void xpmerror(char *fmt, ...) {
-   va_list args;
-
-   dprintf(STDERR_FILENO, "simplexpm: ");
-   va_start(args, fmt);
-   vdprintf(STDERR_FILENO, fmt, args);
-   va_end(args);
-   if (errno) {
-       dprintf(STDERR_FILENO, ": %s", strerror(errno));
-       errno = 0;
-   }
-   dprintf(STDERR_FILENO, "\n");
-}
-
-void *xpmalloc(size_t s) {
-   void *r;
-
-   if ((r = malloc(s))) return memset(r, 0, s);
-
-   xpmerror("Memory allocation");
-   exit(EXIT_FAILURE);
-}
diff --git a/src/utilities.h b/src/utilities.h
deleted file mode 100644 (file)
index d73b62c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-void xpmerror(char *fmt, ...);
-void *xpmalloc(size_t s);
index 9b83f631cf6be4e75486058df4f2ad9e63616235..fa048b2501c9fae25bc9cd96aa93891df03bea8d 100644 (file)
--- a/src/xpm.c
+++ b/src/xpm.c
@@ -1,18 +1,22 @@
 #include <dlfcn.h>
+#include <err.h>
 #include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
+#include "cbs.h"
+#include "colors.h"
 #include "raylib.h"
-#include "utilities.h"
 #include "xpm.h"
 
 #define TMP "/tmp/xpm"
 #define TMPSRC TMP ".c"
 #define TMPLIB "/tmp/libxpm" DYEXT
 
-#include "cbs.c"
-#include "colors.c"
-
 static char *strnsub(char *str, char *sub, size_t l) {
    size_t subl;
 
@@ -40,7 +44,7 @@ static char *arrname(char *p, size_t l) {
    start = p;
    for (; !space(*p) && *p != '['; ++p, --l) if (l == 0) return NULL;
    l = p - start;
-   r = xpmalloc(l + 1);
+   r = allocate(l + 1);
    strncpy(r, start, l);
 
    return r;
@@ -76,7 +80,7 @@ static int key2mode(char **strp) {
        r = MODEC;
        break;
    default:
-       xpmerror("Unknown key `%c'", *(*strp - 1));
+       warnx("Unknown key `%c'", *(*strp - 1));
        r = NUMMODES;
        break;
    case 's':
@@ -116,12 +120,12 @@ static unsigned int str2color(char **strp) {
        }
    }
    if (i == numcolors) {
-       xpmerror("`%s' is not a valid color name", *strp);
+       warnx("`%s' is not a valid color name", *strp);
        return 0;
    }
 
    if (r > 0xffffff) {
-       xpmerror("`0x%06x' is not a valid RGB color", r);
+       warnx("`0x%06x' is not a valid RGB color", r);
        return 0;
    }
    if (lendian()) r = (r >> 16 & 0xff) | (r & 0xff00) | (r & 0xff) << 16;
@@ -148,13 +152,13 @@ static Image parse(char **data, long *sizep) {
    ncolors = strtol(p, &p, 10);
    cpp = strtol(p, &p, 10);
    if (1 + ncolors + height > *sizep) {
-       xpmerror("Actual image height too short");
+       warnx("Actual image height too short");
        return result;
    }
 
    // Colors
-   chars = xpmalloc(ncolors * cpp * sizeof*chars);
-   colors = xpmalloc(NUMMODES * ncolors * sizeof*colors);
+   chars = allocate(ncolors * cpp * sizeof*chars);
+   colors = allocate(NUMMODES * ncolors * sizeof*colors);
    for (i = 0; i < ncolors; ++i) {
        p = data[1 + i];
        strncpy(chars + i * cpp, p, cpp);
@@ -174,7 +178,7 @@ static Image parse(char **data, long *sizep) {
    }
 
    // Pixels
-   pixels = xpmalloc(NUMMODES * height * width * sizeof*pixels);
+   pixels = allocate(NUMMODES * height * width * sizeof*pixels);
    j = width;
    l = 0;
    for (i = 0, pp = &data[1 + ncolors];
@@ -188,7 +192,7 @@ static Image parse(char **data, long *sizep) {
                    for (m = 0; m < NUMMODES; ++m)
                        pixels[m * width * height + i * width + j] = colors[m * ncolors + k];
    if (j != width || l != 0) {
-       xpmerror("Actual image width too narrow");
+       warnx("Actual image width too narrow");
        goto free;
    }
 
@@ -216,44 +220,43 @@ static Image process(char *xpm) {
    void *d;
    long *sizep;
 
-   errno = 0;
    result = (Image){0};
    if ((xpmfd = open(xpm, O_RDONLY)) == -1) {
-       xpmerror("Unable to open `%s'", xpm);
+       warn("Unable to open `%s'", xpm);
        return result;
    }
    if (stat(xpm, &xstat) == -1) {
-       xpmerror("Unable to stat `%s'", xpm);
+       warn("Unable to stat `%s'", xpm);
        goto close;
    }
    l = xstat.st_size;
    if ((map = mmap(NULL, l, PROT_READ, MAP_PRIVATE, xpmfd, 0)) == MAP_FAILED) {
-       xpmerror("Unable to map `%s' to memory", xpm);
+       warn("Unable to map `%s' to memory", xpm);
        goto close;
    }
 
    if ((p = strnsub(map, "char", l)) == NULL) { // Skip "static" keyword
-       xpmerror("`%s' improperly formatted", xpm);
+       warnx("`%s' improperly formatted", xpm);
        goto munmap;
    }
    offset = p - map;
    if ((a = arrname(p + 4, l - offset - 4)) == NULL) {
-       xpmerror("`%s' improperly formatted", xpm);
+       warnx("`%s' improperly formatted", xpm);
        goto munmap;
    }
 
    if ((srcfd = open(TMPSRC, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
-       xpmerror("Unable to open `" TMPSRC "'");
+       warn("Unable to open `" TMPSRC "'");
        goto munmap;
    }
    e = !writeall(srcfd, p, l - offset)
        || dprintf(srcfd, "\n\nlong size = sizeof %s / sizeof*%s;\n", a, a) < 0;
    if (close(srcfd) == -1) {
-       xpmerror("Unable to close `" TMPSRC "'");
+       warn("Unable to close `" TMPSRC "'");
        goto munmap;
    }
    if (e) {
-       xpmerror("Unable to write to `" TMPSRC "'");
+       warn("Unable to write to `" TMPSRC "'");
        goto munmap;
    }
 
@@ -262,35 +265,49 @@ static Image process(char *xpm) {
        load('d', TMP, TMP, NULL);
        exit(EXIT_SUCCESS);
    }
-   if (cpid == -1 || waitpid(cpid, &status, 0) == -1
-       || !WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) {
-       xpmerror("Unable to create `" TMPLIB "'");
+   if (cpid == -1 || waitpid(cpid, &status, 0) == -1) {
+       warn("Unable to create `" TMPLIB "'");
        goto munmap;
    }
+   if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) goto munmap;
 
    if ((d = dlopen(TMPLIB, RTLD_LAZY)) == NULL) {
-       xpmerror("Unable to load `" TMPLIB "': %s", dlerror());
+       warnx("Unable to load `" TMPLIB "': %s", dlerror());
        goto munmap;
    }
    if ((data = (char **)dlsym(d, a)) == NULL) {
-       xpmerror("Unable to load image data from `" TMPLIB "': `%s'", dlerror());
+       warnx("Unable to load image data from `" TMPLIB "': `%s'", dlerror());
        goto dlclose;
    }
    if ((sizep = (long *)dlsym(d, "size")) == NULL) {
-       xpmerror("Unable to load image length from `" TMPLIB "': `%s'", dlerror());
+       warnx("Unable to load image size from `" TMPLIB "': `%s'", dlerror());
        goto dlclose;
    }
 
    result = parse(data, sizep);
 
 dlclose:
-   if (dlclose(d)) xpmerror("Unable to unload `" TMPLIB "': %s", dlerror());
+   if (dlclose(d)) {
+       warnx("Unable to unload `" TMPLIB "': %s", dlerror());
+       result.mipmaps = 0;
+   }
 
 munmap:
-   if (munmap(map, l) == -1) xpmerror("Unable to unmap `%s' from memory", xpm);
+   if (munmap(map, l) == -1) {
+       warn("Unable to unmap `%s' from memory", xpm);
+       result.mipmaps = 0;
+   }
 
 close:
-   if (close(xpmfd) == -1) xpmerror("Unable to close `%s'", xpm);
+   if (close(xpmfd) == -1) {
+       warn("Unable to close `%s'", xpm);
+       result.mipmaps = 0;
+   }
+
+   if (result.data && !result.mipmaps) {
+       free(result.data);
+       result = (Image){0};
+   }
 
    return result;
 }