shithub: rgbds

Download patch

ref: d661b3a5329756fe334548bf8b23d65bd67de4be
parent: c0be5ddbb28f8e1826b5a9b1d72f1994f348c9d9
author: Anthony J. Bentley <[email protected]>
date: Tue Sep 23 22:50:39 EDT 2014

Now that we replace missing libc functions, switch back to err().

--- a/Makefile
+++ b/Makefile
@@ -23,12 +23,14 @@
 	src/asm/rpn.o \
 	src/asm/symbol.o \
 	src/asm/gameboy/locallex.o \
+	src/extern/err.o \
 	src/extern/strlcpy.o \
 	src/extern/strlcat.o
 
 rgblib_obj := \
 	src/lib/library.o \
-	src/lib/main.o
+	src/lib/main.o \
+	src/extern/err.o
 
 rgblink_obj := \
 	src/link/assign.o \
@@ -38,10 +40,12 @@
 	src/link/object.o \
 	src/link/output.o \
 	src/link/patch.o \
-	src/link/symbol.o
+	src/link/symbol.o \
+	src/extern/err.o
 
 rgbfix_obj := \
-	src/fix/main.o
+	src/fix/main.o \
+	src/extern/err.o
 
 all: rgbasm rgblib rgblink rgbfix
 
--- /dev/null
+++ b/include/extern/err.h
@@ -1,0 +1,63 @@
+/*
+ * Copyright © 2005-2013 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef EXTERN_ERR_H
+#define EXTERN_ERR_H
+
+#ifdef ERR_IN_LIBC
+#include <err.h>
+#else
+
+#include <stdarg.h>
+
+#define warn rgbds_warn
+#define vwarn rgbds_vwarn
+#define warnx rgbds_warnx
+#define vwarnx rgbds_vwarnx
+
+#define err rgbds_err
+#define verr rgbds_verr
+#define errx rgbds_errx
+#define verrx rgbds_verrx
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void warn(const char *, ...);
+void vwarn(const char *, va_list);
+void warnx(const char *, ...);
+void vwarnx(const char *, va_list);
+
+void err(int, const char *, ...);
+void verr(int, const char *, va_list);
+void errx(int, const char *, ...);
+void verrx(int, const char *, va_list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
--- /dev/null
+++ b/include/extern/strl.h
@@ -1,0 +1,13 @@
+#ifndef STRL_H
+#define STRL_H
+
+#ifdef STRL_IN_LIBC
+#include <string.h>
+#else
+#define strlcpy rgbds_strlcpy
+#define strlcat rgbds_strlcat
+size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
+#endif
+
+#endif
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -11,18 +11,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifndef STRL_IN_LIBC
-#define strlcpy rgbds_strlcpy
-#define strlcat rgbds_strlcat
-size_t strlcpy(char *, const char *, size_t);
-size_t strlcat(char *, const char *, size_t);
-#endif
-
 #include "asm/symbol.h"
 #include "asm/fstack.h"
 #include "asm/types.h"
 #include "asm/main.h"
 #include "asm/lexer.h"
+#include "extern/err.h"
+#include "extern/strl.h"
 
 /*
  * RGBAsm - FSTACK.C (FileStack routines)
@@ -245,10 +240,8 @@
 	f = fstk_FindFile(tzFileName);
 
 	if (f == NULL) {
-		fprintf(stderr, "Unable to open included file '%s': ",
+		err(1, "Unable to open included file '%s'",
 		    tzFileName);
-		perror(NULL);
-		exit(1);
 	}
 
 	pushcontext();
@@ -357,10 +350,7 @@
 	pFileStack = NULL;
 	pCurrentFile = fopen(tzFileName, "rb");
 	if (pCurrentFile == NULL) {
-		fprintf(stderr, "Unable to open file '%s': ",
-		    tzFileName);
-		perror(NULL);
-		exit(1);
+		err(1, "Unable to open file '%s'", tzFileName);
 	}
 
 	nMacroCount = 0;
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -4,6 +4,7 @@
 #include "asm/main.h"
 #include "asm/rpn.h"
 #include "asm/fstack.h"
+#include "extern/err.h"
 
 #include "asmy.h"
 
@@ -213,9 +214,8 @@
 lex_CheckCharacterRange(UWORD start, UWORD end)
 {
 	if (start > end || start < 1 || end > 127) {
-		fprintf(stderr, "Invalid character range (start: %u, end: %u)\n",
+		errx(1, "Invalid character range (start: %u, end: %u)",
 		        start, end);
-		exit(1);
 	}
 }
 
@@ -343,8 +343,6 @@
 		ppHash = &tLexHash[hash = lexcalchash(lex->tzName)];
 		while (*ppHash)
 			ppHash = &((*ppHash)->pNext);
-
-		//printf("%s has hashvalue %d\n", lex->tzName, hash);
 
 		if (((*ppHash) =
 			(struct sLexString *) malloc(sizeof(struct sLexString))) !=
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -19,6 +19,7 @@
 #include "asm/fstack.h"
 #include "asm/output.h"
 #include "asm/main.h"
+#include "extern/err.h"
 
 int yyparse(void);
 void setuplex(void);
@@ -133,9 +134,8 @@
 			newopt.gbgfx[2] = s[3];
 			newopt.gbgfx[3] = s[4];
 		} else {
-			fprintf(stderr, "Must specify exactly 4 characters "
-			    "for option 'g'\n");
-			exit(1);
+			errx(1, "Must specify exactly 4 characters for "
+			    "option 'g'");
 		}
 		break;
 	case 'b':
@@ -143,9 +143,8 @@
 			newopt.binary[0] = s[1];
 			newopt.binary[1] = s[2];
 		} else {
-			fprintf(stderr, "Must specify exactly 2 characters "
-			    "for option 'b'\n");
-			exit(1);
+			errx(1, "Must specify exactly 2 characters for option "
+			    "'b'");
 		}
 		break;
 	case 'z':
@@ -154,12 +153,10 @@
 
 			result = sscanf(&s[1], "%lx", &newopt.fillchar);
 			if (!((result == EOF) || (result == 1))) {
-				fprintf(stderr,
-				    "Invalid argument for option 'z'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'z'");
 			}
 		} else {
-			fprintf(stderr, "Invalid argument for option 'z'\n");
+			errx(1, "Invalid argument for option 'z'");
 			exit(1);
 		}
 		break;
@@ -295,9 +292,8 @@
 				newopt.binary[0] = optarg[1];
 				newopt.binary[1] = optarg[2];
 			} else {
-				fprintf(stderr, "Must specify exactly "
-				    "2 characters for option 'b'\n");
-				exit(1);
+				errx(1, "Must specify exactly 2 characters for "
+				    "option 'b'");
 			}
 			break;
 		case 'g':
@@ -307,9 +303,8 @@
 				newopt.gbgfx[2] = optarg[3];
 				newopt.gbgfx[3] = optarg[4];
 			} else {
-				fprintf(stderr, "Must specify exactly "
-				    "4 characters for option 'g'\n");
-				exit(1);
+				errx(1, "Must specify exactly 4 characters for "
+				    "option 'g'");
 			}
 			break;
 		case 'h':
@@ -324,14 +319,11 @@
 		case 'p':
 			newopt.fillchar = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'p'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'p'");
 			}
 			if (newopt.fillchar < 0 || newopt.fillchar > 0xFF) {
-				fprintf(stderr, "Argument for option 'p' "
-				    "must be between 0 and 0xFF\n");
-				exit(1);
+				errx(1, "Argument for option 'p' must be "
+				    "between 0 and 0xFF");
 			}
 			break;
 		case 'v':
@@ -420,16 +412,12 @@
 				exit(5);
 			}
 		} else {
-			fprintf(stderr,
-			    "Unterminated IF construct (%ld levels)!\n",
+			errx(1, "Unterminated IF construct (%ld levels)!",
 			    nIFDepth);
-			exit(1);
 		}
 	} else {
-		fprintf(stderr,
-		    "Assembly aborted in pass 1 (%ld errors)!\n",
+		errx(1, "Assembly aborted in pass 1 (%ld errors)!",
 		    nErrors);
-		exit(1);
 	}
 	return 0;
 }
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -17,6 +17,7 @@
 #include "asm/main.h"
 #include "asm/rpn.h"
 #include "asm/fstack.h"
+#include "extern/err.h"
 
 #define SECTIONCHUNK	0x4000
 
@@ -909,10 +910,7 @@
 
 	f = fstk_FindFile(s);
 	if (f == NULL) {
-		fprintf(stderr, "Unable to open incbin file '%s': ",
-		    s);
-		perror(NULL);
-		exit(1);
+		err(1, "Unable to open incbin file '%s'", s);
 	}
 
 	SLONG fsize;
@@ -949,10 +947,7 @@
 
 	f = fstk_FindFile(s);
 	if (f == NULL) {
-		fprintf(stderr, "Unable to open included file '%s': ",
-		    s);
-		perror(NULL);
-		exit(1);
+		err(1, "Unable to open included file '%s'", s);
 	}
 
 	SLONG fsize;
--- /dev/null
+++ b/src/extern/err.c
@@ -1,0 +1,90 @@
+/*
+ * Copyright © 2005-2013 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+extern char *__progname;
+
+void rgbds_vwarn(const char *fmt, va_list ap)
+{
+	fprintf (stderr, "%s: ", __progname);
+	if (fmt) {
+		vfprintf(stderr, fmt, ap);
+		fputs (": ", stderr);
+	}
+	perror(0);
+}
+
+void rgbds_vwarnx(const char *fmt, va_list ap)
+{
+	fprintf (stderr, "%s: ", __progname);
+	if (fmt) vfprintf(stderr, fmt, ap);
+	putc('\n', stderr);
+}
+
+void rgbds_verr(int status, const char *fmt, va_list ap)
+{
+	vwarn(fmt, ap);
+	exit(status);
+}
+
+void rgbds_verrx(int status, const char *fmt, va_list ap)
+{
+	vwarnx(fmt, ap);
+	exit(status);
+}
+
+void rgbds_warn(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vwarn(fmt, ap);
+	va_end(ap);
+}
+
+void rgbds_warnx(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vwarnx(fmt, ap);
+	va_end(ap);
+}
+
+void rgbds_err(int status, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verr(status, fmt, ap);
+	va_end(ap);
+}
+
+void rgbds_errx(int status, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verrx(status, fmt, ap);
+	va_end(ap);
+}
--- a/src/fix/main.c
+++ b/src/fix/main.c
@@ -22,6 +22,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "extern/err.h"
+
 static void
 usage(void)
 {
@@ -47,9 +49,7 @@
 		usage();
 
 	if ((rom = fopen(argv[argc - 1], "rb+")) == NULL) {
-		fprintf(stderr, "Error opening file %s: \n", argv[argc - 1]);
-		perror(NULL);
-		exit(1);
+		err(1, "Error opening file %s", argv[argc - 1]);
 	}
 
 	/*
@@ -93,9 +93,8 @@
 			setid = true;
 
 			if (strlen(optarg) != 4) {
-				fprintf(stderr, "Game ID %s must be exactly 4 "
-				    "characters\n", optarg);
-				exit(1);
+				errx(1, "Game ID %s must be exactly 4 "
+				    "characters", optarg);
 			}
 
 			id = optarg;
@@ -107,10 +106,8 @@
 			setnewlicensee = true;
 
 			if (strlen(optarg) != 2) {
-				fprintf(stderr,
-				    "New licensee code %s is not the correct "
-				    "length of 2 characters\n", optarg);
-				exit(1);
+				errx(1, "New licensee code %s is not the "
+				    "correct length of 2 characters", optarg);
 			}
 
 			newlicensee = optarg;
@@ -120,15 +117,11 @@
 
 			licensee = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'l'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'l'");
 			}
 			if (licensee < 0 || licensee > 0xFF) {
-				fprintf(stderr,
-				    "Argument for option 'l' must be "
-				    "between 0 and 255\n");
-				exit(1);
+				errx(1, "Argument for option 'l' must be "
+				    "between 0 and 255");
 			}
 			break;
 		case 'm':
@@ -136,15 +129,11 @@
 
 			cartridge = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'm'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'm'");
 			}
 			if (cartridge < 0 || cartridge > 0xFF) {
-				fprintf(stderr,
-				    "Argument for option 'm' must be "
-				    "between 0 and 255\n");
-				exit(1);
+				errx(1, "Argument for option 'm' must be "
+				    "between 0 and 255");
 			}
 			break;
 		case 'n':
@@ -152,15 +141,11 @@
 
 			version = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'n'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'n'");
 			}
 			if (version < 0 || version > 0xFF) {
-				fprintf(stderr,
-				    "Argument for option 'n' must be "
-				    "between 0 and 255\n");
-				exit(1);
+				errx(1, "Argument for option 'n' must be "
+				    "between 0 and 255");
 			}
 			break;
 		case 'p':
@@ -168,15 +153,11 @@
 
 			padvalue = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'p'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'p'");
 			}
 			if (padvalue < 0 || padvalue > 0xFF) {
-				fprintf(stderr,
-				    "Argument for option 'p' must be "
-				    "between 0 and 255\n");
-				exit(1);
+				errx(1, "Argument for option 'p' must be "
+				    "between 0 and 255");
 			}
 			break;
 		case 'r':
@@ -184,14 +165,11 @@
 
 			ramsize = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr,
-				    "Invalid argument for option 'r'\n");
+				errx(1, "Invalid argument for option 'r'");
 			}
 			if (ramsize < 0 || ramsize > 0xFF) {
-				fprintf(stderr,
-				    "Argument for option 'r' must be "
-				    "between 0 and 255\n");
-				exit(1);
+				errx(1, "Argument for option 'r' must be "
+				    "between 0 and 255");
 			}
 			break;
 		case 's':
@@ -201,15 +179,13 @@
 			settitle = true;
 
 			if (strlen(optarg) > 16) {
-				fprintf(stderr, "Title %s is greater than the "
-				    "maximum of 16 characters\n", optarg);
-				exit(1);
+				errx(1, "Title %s is greater than the "
+				    "maximum of 16 characters", optarg);
 			}
 
 			if (strlen(optarg) == 16)
-				fprintf(stderr,
-				    "Title %s is 16 chars, it is best "
-				    "to keep it to 15 or fewer\n", optarg);
+				warnx("Title %s is 16 chars, it is best to "
+				    "keep it to 15 or fewer", optarg);
 
 			title = optarg;
 			break;
@@ -313,8 +289,7 @@
 			byte |= 1 << 6;
 
 		if (byte & 0x3F)
-			fprintf(stderr,
-			    "Color flag conflicts with game title\n");
+			warnx("Color flag conflicts with game title");
 
 		fseek(rom, 0x143, SEEK_SET);
 		fputc(byte, rom);
@@ -351,9 +326,8 @@
 		 */
 
 		if (!setlicensee)
-			fprintf(stderr,
-			    "You should probably set both '-s' and "
-			    "'-l 0x33'\n");
+			warnx("You should probably set both '-s' and "
+			    "'-l 0x33'");
 
 		fseek(rom, 0x146, SEEK_SET);
 		fputc(3, rom);
@@ -390,7 +364,7 @@
 		}
 
 		if (newsize > 0x800000) /* ROM is bigger than 8MiB */
-			fprintf(stderr, "ROM size is bigger than 8MiB\n");
+			warnx("ROM size is bigger than 8MiB");
 
 		buf = malloc(newsize - romsize);
 		memset(buf, padvalue, newsize - romsize);
--- a/src/lib/library.c
+++ b/src/lib/library.c
@@ -88,8 +88,7 @@
 			if (l == NULL) {
 				l = malloc(sizeof *l);
 				if (!l) {
-					fprintf(stderr, "Out of memory\n");
-					exit(1);
+					err(1, NULL);
 				}
 
 				first = l;
@@ -96,8 +95,7 @@
 			} else {
 				l->pNext = malloc(sizeof *l->pNext);
 				if (!l->pNext) {
-					fprintf(stderr, "Out of memory\n");
-					exit(1);
+					err(1, NULL);
 				}
 
 				l = l->pNext;
@@ -115,8 +113,7 @@
 				    f);
 				size -= l->nByteLength;
 			} else {
-				fprintf(stderr, "Out of memory\n");
-				exit(1);
+				err(1, NULL);
 			}
 
 			l->pNext = NULL;
@@ -153,8 +150,7 @@
 			return (r);
 		} else {
 			fclose(f);
-			fprintf(stderr, "Not a valid xLib library\n");
-			exit(1);
+			errx(1, "Not a valid xLib library");
 		}
 	} else {
 		printf
@@ -191,8 +187,7 @@
 lib_Find(sLibrary * lib, char *filename)
 {
 	if (strlen(filename) >= MAXNAMELENGTH) {
-		fprintf(stderr, "Module name too long: %s\n", filename);
-		exit(1);
+		errx(1, "Module name too long: %s", filename);
 	}
 
 	while (lib) {
@@ -214,16 +209,13 @@
 		sLibrary *module;
 
 		if (strlen(filename) >= MAXNAMELENGTH) {
-			fprintf(stderr, "Module name too long: %s\n",
-			    filename);
-			exit(1);
+			errx(1, "Module name too long: %s\n", filename);
 		}
 
 		if ((module = lib_Find(lib, filename)) == NULL) {
 			module = malloc(sizeof *module);
 			if (!module) {
-				fprintf(stderr, "Out of memory\n");
-				exit(1);
+				err(1, NULL);
 			}
 
 			module->pNext = lib;
@@ -237,8 +229,7 @@
 		strcpy(module->tName, filename);
 		module->pData = malloc(module->nByteLength);
 		if (!module->pData) {
-			fprintf(stderr, "Out of memory\n");
-			exit(1);
+			err(1, NULL);
 		}
 
 		fread(module->pData, sizeof(UBYTE), module->nByteLength, f);
@@ -260,8 +251,7 @@
 	first = pp;
 
 	if (strlen(filename) >= MAXNAMELENGTH) {
-		fprintf(stderr, "Module name too long: %s\n", filename);
-		exit(1);
+		errx(1, "Module name too long: %s\n", filename);
 	}
 
 	while ((*pp) && (!found)) {
@@ -282,8 +272,7 @@
 	}
 
 	if (!found) {
-		fprintf(stderr, "Module not found\n");
-		exit(1);
+		errx(1, "Module not found\n");
 	} else
 		printf("Module '%s' deleted from library\n", filename);
 
--- a/src/lib/main.c
+++ b/src/lib/main.c
@@ -6,6 +6,7 @@
 
 #include "asmotor.h"
 
+#include "extern/err.h"
 #include "lib/types.h"
 #include "lib/library.h"
 
@@ -83,10 +84,8 @@
 						    ("Extracted module '%s'\n",
 						    argv[argn]);
 					} else {
-						fprintf(stderr,
-						    "Unable to write module '%s': ", argv[argn]);
-						perror(NULL);
-						exit(1);
+						err(1,
+						    "Unable to write module '%s'", argv[argn]);
 					}
 				} else {
 					fprintf(stderr, "Module not found\n");
--- a/src/link/assign.c
+++ b/src/link/assign.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "extern/err.h"
 #include "link/mylink.h"
 #include "link/main.h"
 #include "link/symbol.h"
@@ -77,9 +78,7 @@
 
 						return (org);
 					} else {
-						fprintf(stderr,
-						    "Out of memory!\n");
-						exit(1);
+						err(1, NULL);
 					}
 				}
 			}
@@ -310,9 +309,7 @@
 			pSection->oAssigned = 1;
 			DOMAXVBANK(pSection->nBank);
 		} else {
-			fprintf(stderr,
-			    "Unable to place VRAM section anywhere\n");
-			exit(1);
+			errx(1, "Unable to place VRAM section anywhere");
 		}
 	}
 }
@@ -331,9 +328,7 @@
 			pSection->oAssigned = 1;
 			DOMAXSBANK(pSection->nBank);
 		} else {
-			fprintf(stderr,
-			    "Unable to place SRAM section anywhere\n");
-			exit(1);
+			errx(1, "Unable to place SRAM section anywhere");
 		}
 	}
 }
@@ -352,9 +347,7 @@
 			pSection->oAssigned = 1;
 			DOMAXWBANK(pSection->nBank);
 		} else {
-			fprintf(stderr,
-			    "Unable to place WRAMX section anywhere\n");
-			exit(1);
+			errx(1, "Unable to place WRAMX section anywhere");
 		}
 	}
 }
@@ -373,9 +366,7 @@
 			pSection->oAssigned = 1;
 			DOMAXBANK(pSection->nBank);
 		} else {
-			fprintf(stderr,
-			    "Unable to place ROMX section anywhere\n");
-			exit(1);
+			errx(1, "Unable to place ROMX section anywhere");
 		}
 	}
 }
@@ -397,8 +388,7 @@
 		BankFree[i] = malloc(sizeof *BankFree[i]);
 
 		if (!BankFree[i]) {
-			fprintf(stderr, "Out of memory!\n");
-			exit(1);
+			err(1, NULL);
 		}
 
 		if (i == 0) {
@@ -472,10 +462,9 @@
 				if (area_AllocAbs
 				    (&BankFree[BANK_WRAM0], pSection->nOrg,
 					pSection->nByteSize) != pSection->nOrg) {
-					fprintf(stderr,
-					    "Unable to load fixed WRAM0 section "
-					    "at $%lX\n", pSection->nOrg);
-					exit(1);
+					errx(1,
+					    "Unable to load fixed WRAM0 "
+					    "section at $%lX", pSection->nOrg);
 				}
 				pSection->oAssigned = 1;
 				pSection->nBank = BANK_WRAM0;
@@ -484,10 +473,8 @@
 				if (area_AllocAbs
 				    (&BankFree[BANK_HRAM], pSection->nOrg,
 					pSection->nByteSize) != pSection->nOrg) {
-					fprintf(stderr, "Unable to load fixed "
-					    "HRAM section at $%lX\n",
-					    pSection->nOrg);
-					exit(1);
+					errx(1, "Unable to load fixed HRAM "
+					    "section at $%lX", pSection->nOrg);
 				}
 				pSection->oAssigned = 1;
 				pSection->nBank = BANK_HRAM;
@@ -530,17 +517,15 @@
 							    pSection->nOrg,
 							    pSection->nByteSize)
 							    != pSection->nOrg) {
-								fprintf(stderr,
-"Unable to load fixed SRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-								exit(1);
+								errx(1,
+"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 							}
 							DOMAXVBANK(pSection->
 							    nBank);
 							pSection->oAssigned = 1;
 						} else {
-							fprintf(stderr,
-"Unable to load fixed SRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-							exit(1);
+							errx(1,
+"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 						}
 					}
 				}
@@ -583,17 +568,15 @@
 							    pSection->nOrg,
 							    pSection->nByteSize)
 							    != pSection->nOrg) {
-								fprintf(stderr,
-"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-								exit(1);
+								errx(1,
+"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 							}
 							DOMAXWBANK(pSection->
 							    nBank);
 							pSection->oAssigned = 1;
 						} else {
-							fprintf(stderr,
-"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-							exit(1);
+							errx(1,
+"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 						}
 					}
 				}
@@ -636,17 +619,15 @@
 							    pSection->nOrg,
 							    pSection->nByteSize)
 							    != pSection->nOrg) {
-								fprintf(stderr,
-"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-								exit(1);
+								errx(1,
+"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 							}
 							DOMAXVBANK(pSection->
 							    nBank);
 							pSection->oAssigned = 1;
 						} else {
-							fprintf(stderr,
-"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-							exit(1);
+							errx(1,
+"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 						}
 					}
 				}
@@ -655,10 +636,8 @@
 				if (area_AllocAbs
 				    (&BankFree[BANK_ROM0], pSection->nOrg,
 					pSection->nByteSize) != pSection->nOrg) {
-					fprintf(stderr, "Unable to load fixed "
-					    "ROM0 section at $%lX\n",
-					    pSection->nOrg);
-					exit(1);
+					errx(1, "Unable to load fixed ROM0 "
+					    "section at $%lX", pSection->nOrg);
 				}
 				pSection->oAssigned = 1;
 				pSection->nBank = BANK_ROM0;
@@ -703,15 +682,15 @@
 								pSection->
 								nByteSize) !=
 							    pSection->nOrg) {
-								fprintf(stderr, "Unable to load fixed ROMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-								exit(1);
+								errx(1,
+								    "Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 							}
 							DOMAXBANK(pSection->
 							    nBank);
 							pSection->oAssigned = 1;
 						} else {
-							fprintf(stderr, "Unable to load fixed ROMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
-							exit(1);
+							errx(1,
+							"Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
 						}
 					}
 
@@ -737,14 +716,13 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[pSection->nBank],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "Unable to load fixed ROMX section into bank $%02lX\n", pSection->nBank);
-					exit(1);
+					errx(1,
+					"Unable to load fixed ROMX section into bank $%02lX", pSection->nBank);
 				}
 				pSection->oAssigned = 1;
 				DOMAXBANK(pSection->nBank);
 			} else {
-				fprintf(stderr, "Unable to load fixed ROMX section into bank $%02lX\n", pSection->nBank);
-				exit(1);
+				errx(1, "Unable to load fixed ROMX section into bank $%02lX", pSection->nBank);
 			}
 		} else if (pSection->oAssigned == 0
 		    && pSection->Type == SECT_SRAM
@@ -755,14 +733,12 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[pSection->nBank],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "Unable to load fixed SRAM section into bank $%02lX\n", pSection->nBank);
-					exit(1);
+					errx(1, "Unable to load fixed SRAM section into bank $%02lX", pSection->nBank);
 				}
 				pSection->oAssigned = 1;
 				DOMAXSBANK(pSection->nBank);
 			} else {
-				fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank);
-				exit(1);
+				errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
 			}
 		} else if (pSection->oAssigned == 0
 		    && pSection->Type == SECT_VRAM
@@ -773,14 +749,12 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[pSection->nBank],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank);
-					exit(1);
+					errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
 				}
 				pSection->oAssigned = 1;
 				DOMAXVBANK(pSection->nBank);
 			} else {
-				fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank);
-				exit(1);
+				errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
 			}
 		} else if (pSection->oAssigned == 0
 		    && pSection->Type == SECT_WRAMX
@@ -791,14 +765,12 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[pSection->nBank],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX);
-					exit(1);
+					errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX);
 				}
 				pSection->oAssigned = 1;
 				DOMAXWBANK(pSection->nBank);
 			} else {
-				fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX);
-				exit(1);
+				errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX);
 			}
 		}
 		pSection = pSection->pNext;
@@ -820,8 +792,7 @@
 				area_AllocAbsROMXAnyBank(pSection->nOrg,
 				    pSection->nByteSize)) ==
 			    -1) {
-				fprintf(stderr, "Unable to load fixed ROMX section at $%lX into any bank\n", pSection->nOrg);
-				exit(1);
+				errx(1, "Unable to load fixed ROMX section at $%lX into any bank", pSection->nOrg);
 			}
 			pSection->oAssigned = 1;
 			DOMAXBANK(pSection->nBank);
@@ -834,8 +805,7 @@
 				area_AllocAbsVRAMAnyBank(pSection->nOrg,
 				    pSection->nByteSize)) ==
 			    -1) {
-				fprintf(stderr, "Unable to load fixed VRAM section at $%lX into any bank\n", pSection->nOrg);
-				exit(1);
+				errx(1, "Unable to load fixed VRAM section at $%lX into any bank", pSection->nOrg);
 			}
 			pSection->oAssigned = 1;
 			DOMAXVBANK(pSection->nBank);
@@ -848,8 +818,7 @@
 				area_AllocAbsSRAMAnyBank(pSection->nOrg,
 				    pSection->nByteSize)) ==
 			    -1) {
-				fprintf(stderr, "Unable to load fixed SRAM section at $%lX into any bank\n", pSection->nOrg);
-				exit(1);
+				errx(1, "Unable to load fixed SRAM section at $%lX into any bank", pSection->nOrg);
 			}
 			pSection->oAssigned = 1;
 			DOMAXSBANK(pSection->nBank);
@@ -862,8 +831,7 @@
 				area_AllocAbsWRAMAnyBank(pSection->nOrg,
 				    pSection->nByteSize)) ==
 			    -1) {
-				fprintf(stderr, "Unable to load fixed WRAMX section at $%lX into any bank\n", pSection->nOrg);
-				exit(1);
+				errx(1, "Unable to load fixed WRAMX section at $%lX into any bank", pSection->nOrg);
 			}
 			pSection->oAssigned = 1;
 			DOMAXWBANK(pSection->nBank);
@@ -885,8 +853,7 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[BANK_WRAM0],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "WRAM0 section too large\n");
-					exit(1);
+					errx(1, "WRAM0 section too large");
 				}
 				pSection->nBank = BANK_WRAM0;
 				pSection->oAssigned = 1;
@@ -895,8 +862,7 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[BANK_HRAM],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "HRAM section too large\n");
-					exit(1);
+					errx(1, "HRAM section too large");
 				}
 				pSection->nBank = BANK_HRAM;
 				pSection->oAssigned = 1;
@@ -911,8 +877,7 @@
 				if ((pSection->nOrg =
 					area_Alloc(&BankFree[BANK_ROM0],
 					    pSection->nByteSize)) == -1) {
-					fprintf(stderr, "ROM0 section too large\n");
-					exit(1);
+					errx(1, "ROM0 section too large");
 				}
 				pSection->nBank = BANK_ROM0;
 				pSection->oAssigned = 1;
@@ -920,8 +885,7 @@
 			case SECT_ROMX:
 				break;
 			default:
-				fprintf(stderr, "(INTERNAL) Unknown section type!\n");
-				exit(1);
+				errx(1, "(INTERNAL) Unknown section type!");
 				break;
 			}
 		}
--- a/src/link/library.c
+++ b/src/link/library.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "extern/err.h"
 #include "link/types.h"
 #include "link/mylink.h"
 #include "link/main.h"
@@ -91,9 +92,8 @@
 	}
 	if (options & OPT_SMART_C_LINK) {
 		if (!addmodulecontaining(smartlinkstartsymbol)) {
-			fprintf(stderr, "Can't find start symbol '%s'\n",
+			errx(1, "Can't find start symbol '%s'",
 			    smartlinkstartsymbol);
-			exit(1);
 		} else
 			printf("Smart linking with symbol '%s'\n",
 			    smartlinkstartsymbol);
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -6,6 +6,7 @@
 
 #include "asmotor.h"
 
+#include "extern/err.h"
 #include "link/object.h"
 #include "link/output.h"
 #include "link/assign.h"
@@ -73,8 +74,7 @@
 		case 'p':
 			fillchar = strtoul(optarg, &ep, 0);
 			if (optarg[0] == '\0' || *ep != '\0') {
-				fprintf(stderr, "Invalid argument for option 'p'\n");
-				exit(1);
+				errx(1, "Invalid argument for option 'p'");
 			}
 			if (fillchar < 0 || fillchar > 0xFF) {
 				fprintf(stderr, "Argument for option 'p' must be between 0 and 0xFF");
--- a/src/link/mapfile.c
+++ b/src/link/mapfile.c
@@ -5,6 +5,7 @@
 
 #include "asmotor.h"
 
+#include "extern/err.h"
 #include "link/main.h"
 #include "link/mylink.h"
 #include "link/assign.h"
@@ -20,9 +21,7 @@
 	mf = fopen(name, "w");
 
 	if (mf == NULL) {
-		fprintf(stderr, "Cannot open mapfile '%s': ", name);
-		perror(NULL);
-		exit(1);
+		err(1, "Cannot open mapfile '%s'", name);
 	}
 }
 
@@ -32,8 +31,7 @@
 	sf = fopen(name, "w");
 
 	if (sf == NULL) {
-		fprintf(stderr, "Cannot open symfile '%s'\n", name);
-		exit(1);
+		err(1, "Cannot open symfile '%s'", name);
 	}
 
 	fprintf(sf, ";File generated by xLink v" LINK_VERSION "\n\n");
--- a/src/link/object.c
+++ b/src/link/object.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "extern/err.h"
 #include "link/mylink.h"
 #include "link/main.h"
 
@@ -80,8 +81,7 @@
 
 	*ppSections = malloc(sizeof **ppSections);
 	if (!*ppSections) {
-		fprintf(stderr, "Out of memory!\n");
-		exit(1);
+		err(1, NULL);
 	}
 	(*ppSections)->tSymbols = tSymbols;
 	(*ppSections)->pNext = NULL;
@@ -102,15 +102,13 @@
 
 	pSym = malloc(sizeof *pSym);
 	if (!pSym) {
-		fprintf(stderr, "Out of memory!\n");
-		exit(1);
+		err(1, NULL);
 	}
 
 	readasciiz(s, f);
 	pSym->pzName = malloc(strlen(s) + 1);
 	if (!pSym->pzName) {
-		fprintf(stderr, "Out of memory!\n");
-		exit(1);
+		err(1, NULL);
 	}
 
 	strcpy(pSym->pzName, s);
@@ -150,7 +148,7 @@
 		if (pSection->nByteSize) {
 			pSection->pData = malloc(pSection->nByteSize);
 			if (!pSection->pData) {
-				fprintf(stderr, "Out of memory!\n");
+				err(1, NULL);
 			}
 
 			SLONG nNumberOfPatches;
@@ -169,7 +167,7 @@
 			while (nNumberOfPatches--) {
 				pPatch = malloc(sizeof *pPatch);
 				if (!pPatch) {
-					fprintf(stderr, "Out of memory!\n");
+					err(1, NULL);
 				}
 
 				*ppPatch = pPatch;
@@ -177,7 +175,7 @@
 
 				pPatch->pzFilename = malloc(strlen(s) + 1);
 				if (!pPatch->pzFilename) {
-					fprintf(stderr, "Out of memory!\n");
+					err(1, NULL);
 				}
 
 				strcpy(pPatch->pzFilename, s);
@@ -193,8 +191,7 @@
 				if ((pPatch->nRPNSize = readlong(f)) > 0) {
 					pPatch->pRPN = malloc(pPatch->nRPNSize);
 					if (!pPatch->pRPN) {
-						fprintf(stderr, "Out of memory!\n");
-						exit(1);
+						err(1, NULL);
 					}
 
 					fread(pPatch->pRPN, sizeof(UBYTE),
@@ -228,8 +225,7 @@
 	if (nNumberOfSymbols) {
 		tSymbols = malloc(nNumberOfSymbols * sizeof(struct sSymbol *));
 		if (!tSymbols) {
-			fprintf(stderr, "Out of memory!\n");
-			exit(1);
+			err(1, NULL);
 		}
 
 		for (i = 0; i < nNumberOfSymbols; i += 1)
@@ -305,8 +301,7 @@
 		if (pSection->nByteSize) {
 			pSection->pData = malloc(pSection->nByteSize);
 			if (!pSection->pData) {
-				fprintf(stderr, "Out of memory!\n");
-				exit(1);
+				err(1, NULL);
 			}
 
 			SLONG nNumberOfPatches;
@@ -325,7 +320,7 @@
 			while (nNumberOfPatches--) {
 				pPatch = malloc(sizeof *pPatch);
 				if (!pPatch) {
-					fprintf(stderr, "Out of memory!\n");
+					err(1, NULL);
 				}
 
 				*ppPatch = pPatch;
@@ -332,7 +327,7 @@
 				readasciiz(s, f);
 				pPatch->pzFilename = malloc(strlen(s) + 1);
 				if (!pPatch->pzFilename) {
-					fprintf(stderr, "Out of memory!\n");
+					err(1, NULL);
 				}
 
 				strcpy(pPatch->pzFilename, s);
@@ -342,7 +337,7 @@
 				if ((pPatch->nRPNSize = readlong(f)) > 0) {
 					pPatch->pRPN = malloc(pPatch->nRPNSize);
 					if (!pPatch->pRPN) {
-						fprintf(stderr, "Out of memory!\n");
+						err(1, NULL);
 					}
 
 					fread(pPatch->pRPN, sizeof(UBYTE),
@@ -376,7 +371,7 @@
 	if (nNumberOfSymbols) {
 		tSymbols = malloc(nNumberOfSymbols * sizeof *tSymbols);
 		if (!tSymbols) {
-			fprintf(stderr, "Out of memory!\n");
+			err(1, NULL);
 		}
 
 		for (i = 0; i < nNumberOfSymbols; i += 1)
@@ -440,14 +435,10 @@
 			    obj_ReadRGB1(pObjfile);
 			break;
 		default:
-			fprintf(stderr, "'%s' is an unsupported version",
-			    tzObjectfile);
-			exit(1);
-			break;
+			errx(1, "'%s' is an unsupported version", tzObjectfile);
 		}
 	} else {
-		fprintf(stderr, "'%s' is not a valid object\n", tzObjectfile);
-		exit(1);
+		errx(1, "'%s' is not a valid object", tzObjectfile);
 	}
 }
 
@@ -463,10 +454,7 @@
 
 	pObjfile = fopen(tzObjectfile, "rb");
 	if (pObjfile == NULL) {
-		fprintf(stderr, "Unable to open object '%s': ",
-		    tzObjectfile);
-		perror(NULL);
-		exit(1);
+		err(1, "Unable to open object '%s'", tzObjectfile);
 	}
 	obj_ReadOpenFile(pObjfile, tzObjectfile);
 	fclose(pObjfile);
@@ -516,14 +504,8 @@
 
 	pObjfile = fopen(tzLibfile, "rb");
 	if (pObjfile == NULL) {
-		fprintf(stderr, "Unable to open object '%s': ", tzLibfile);
-		perror(NULL);
-		exit(1);
+		err(1, "Unable to open object '%s'", tzLibfile);
 	}
-	if (!pObjfile) {
-		fprintf(stderr, "Unable to open '%s'\n", tzLibfile);
-		exit(1);
-	}
 	char tzHeader[5];
 
 	fread(tzHeader, sizeof(char), 4, pObjfile);
@@ -531,9 +513,7 @@
 	if (strcmp(tzHeader, "XLB0") == 0)
 		lib_ReadXLB0(pObjfile);
 	else {
-		fprintf(stderr, "'%s' is an invalid library\n",
-		    tzLibfile);
-		exit(1);
+		errx(1, "'%s' is an invalid library", tzLibfile);
 	}
 	fclose(pObjfile);
 }
--- a/src/link/patch.c
+++ b/src/link/patch.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "extern/err.h"
 #include "link/mylink.h"
 #include "link/symbol.h"
 #include "link/main.h"
@@ -46,8 +47,7 @@
 	default:
 		break;
 	}
-	fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n");
-	exit(1);
+	errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
 }
 
 SLONG 
@@ -64,8 +64,7 @@
 	default:
 		break;
 	}
-	fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n");
-	exit(1);
+	errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
 }
 
 SLONG 
@@ -159,10 +158,9 @@
 			t = rpnpop();
 			rpnpush(t & 0xFF);
 			if (t < 0 || (t > 0xFF && t < 0xFF00) || t > 0xFFFF) {
-				fprintf(stderr,
-				    "%s(%ld) : Value must be in the HRAM area\n",
+				errx(1,
+				    "%s(%ld) : Value must be in the HRAM area",
 				    pPatch->pzFilename, pPatch->nLineNo);
-				exit(1);
 			}
 			break;
 		case RPN_PCEZP:
@@ -169,10 +167,9 @@
 			t = rpnpop();
 			rpnpush(t & 0xFF);
 			if (t < 0x2000 || t > 0x20FF) {
-				fprintf(stderr,
-				    "%s(%ld) : Value must be in the ZP area\n",
+				errx(1,
+				    "%s(%ld) : Value must be in the ZP area",
 				    pPatch->pzFilename, pPatch->nLineNo);
-				exit(1);
 			}
 			break;
 		case RPN_CONST:
@@ -217,11 +214,10 @@
 				high |= (*rpn++) << 24;
 				t = rpnpop();
 				if (t < low || t > high) {
-					fprintf(stderr,
-					    "%s(%ld) : Value must be in the range [%ld;%ld]\n",
+					errx(1,
+					    "%s(%ld) : Value must be in the range [%ld;%ld]",
 					    pPatch->pzFilename,
 					    pPatch->nLineNo, low, high);
-					exit(1);
 				}
 				rpnpush(t);
 				size -= 8;
@@ -255,11 +251,10 @@
 					pSect->pData[pPatch->nOffset] =
 					    (UBYTE) t;
 				} else {
-					fprintf(stderr,
-					    "%s(%ld) : Value must be 8-bit\n",
+					errx(1,
+					    "%s(%ld) : Value must be 8-bit",
 					    pPatch->pzFilename,
 					    pPatch->nLineNo);
-					exit(1);
 				}
 				break;
 			case PATCH_WORD_L:
@@ -280,11 +275,10 @@
 						    1] = t & 0xFF;
 					}
 				} else {
-					fprintf(stderr,
-					    "%s(%ld) : Value must be 16-bit\n",
+					errx(1,
+					    "%s(%ld) : Value must be 16-bit",
 					    pPatch->pzFilename,
 					    pPatch->nLineNo);
-					exit(1);
 				}
 				break;
 			case PATCH_LONG_L:
--- a/src/link/symbol.c
+++ b/src/link/symbol.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "extern/err.h"
 #include "link/main.h"
 #include "link/patch.h"
 #include "link/types.h"
@@ -53,8 +54,7 @@
 			}
 		}
 
-		fprintf(stderr, "Unknown symbol '%s'\n", tzName);
-		exit(1);
+		errx(1, "Unknown symbol '%s'", tzName);
 	}
 }
 
@@ -72,8 +72,7 @@
 		}
 	}
 
-	fprintf(stderr, "Unknown symbol '%s'\n", tzName);
-	exit(1);
+	errx(1, "Unknown symbol '%s'", tzName);
 }
 
 void 
@@ -93,10 +92,7 @@
 			if (nBank == -1)
 				return;
 
-			fprintf(stderr,
-			    "Symbol '%s' defined more than once\n",
-			    tzName);
-			exit(1);
+			errx(1, "Symbol '%s' defined more than once", tzName);
 		}
 	}