+#define ERR_EXIT_UNDEF 0
+#ifdef __BLOCKS__
+#define ERR_EXIT_BLOCK 1
+#endif /* __BLOCKS__ */
+#define ERR_EXIT_FUNC 2
+struct _e_err_exit {
+ unsigned int type;
+#ifdef __BLOCKS__
+ union {
+#endif /* __BLOCKS__ */
+ void (*func)(int);
+#ifdef __BLOCKS__
+ void (^block)(int);
+ };
+#endif /* __BLOCKS__ */
+};
+
+#ifdef BUILDING_VARIANT
+
+__private_extern__ FILE *_e_err_file; /* file to use for error output */
+__private_extern__ struct _e_err_exit _e_err_exit;
+__private_extern__ void _e_visprintf(FILE * __restrict, const char * __restrict, va_list);
+
+#else /* !BUILDING_VARIANT */
+
+__private_extern__ FILE *_e_err_file = NULL; /* file to use for error output */
+__private_extern__ struct _e_err_exit _e_err_exit = {ERR_EXIT_UNDEF};
+
+/*
+ * zero means pass as is
+ * 255 means use \nnn (octal)
+ * otherwise use \x (x is value)
+ * (NUL isn't used)
+ */
+static const unsigned char escape[256] = {
+ /* NUL */
+ 0, /* Unused: strings can't contain nulls */
+ /* SOH STX ETX EOT ENQ ACK BEL */
+ 255, 255, 255, 255, 255, 255, 'a',
+ /* BS HT NL VT NP CR SO SI */
+ 'b', 0, 0, 'v', 'f', 'r', 255, 255,
+ /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ /* CAN EM SUB ESC FS GS RS US */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ /* the rest are zero */
+};
+
+/*
+ * Make characters visible. If we can't allocate enough
+ * memory, we fall back on vfprintf().
+ */
+__private_extern__ void
+_e_visprintf(FILE * __restrict stream, const char * __restrict format, va_list ap)
+{
+ int failed = 0;
+ char *str, *visstr;
+ va_list backup;
+
+ va_copy(backup, ap);
+ vasprintf(&str, format, ap);
+ if (str != NULL) {
+ if ((visstr = malloc(4 * strlen(str) + 1)) != NULL) {
+ unsigned char *fp = (unsigned char *)str;
+ unsigned char *tp = (unsigned char *)visstr;
+ while(*fp) {
+ switch(escape[*fp]) {
+ case 0:
+ *tp++ = *fp;
+ break;
+ case 255:
+ sprintf((char *)tp, "\\%03o", *fp);
+ tp += 4;
+ break;
+ default:
+ *tp++ = '\\';
+ *tp++ = escape[*fp];
+ break;
+ }
+ fp++;
+ }
+ *tp = 0;
+ fputs(visstr, stream);
+ free(visstr);
+ } else
+ failed = 1;
+ free(str);
+ } else
+ failed = 1;
+ if (failed)
+ vfprintf(stream, format, backup);
+ va_end(backup);
+}