X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/9385eb3d10ebe5eb398c52040ec3dbfba9b0cdcf..aa54d2fad3d9038b43475aa93c76795c5141a993:/gen/FreeBSD/err.c diff --git a/gen/FreeBSD/err.c b/gen/FreeBSD/err.c index aa0d306..f763764 100644 --- a/gen/FreeBSD/err.c +++ b/gen/FreeBSD/err.c @@ -10,10 +10,6 @@ * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -35,7 +31,7 @@ static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.13 2002/03/29 22:43:41 markm Exp $"); +__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.15 2008/04/03 20:36:44 imp Exp $"); #include "namespace.h" #include @@ -44,12 +40,107 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.13 2002/03/29 22:43:41 markm Exp #include #include #include +#include #include "un-namespace.h" +#ifdef __BLOCKS__ +#include +#endif /* __BLOCKS__ */ #include "libc_private.h" -static FILE *err_file; /* file to use for error output */ -static void (*err_exit)(int); +#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); +} /* * This is declared to take a `void *' so that the caller is not required @@ -60,17 +151,37 @@ void err_set_file(void *fp) { if (fp) - err_file = fp; + _e_err_file = fp; else - err_file = stderr; + _e_err_file = stderr; } void err_set_exit(void (*ef)(int)) { - err_exit = ef; +#ifdef __BLOCKS__ + if (_e_err_exit.type == ERR_EXIT_BLOCK) { + Block_release(_e_err_exit.block); + _e_err_exit.block = NULL; + } +#endif /* __BLOCKS__ */ + _e_err_exit.type = ef ? ERR_EXIT_FUNC : ERR_EXIT_UNDEF; + _e_err_exit.func = ef; } +#ifdef __BLOCKS__ +void +err_set_exit_b(void (^ef)(int)) +{ + if (_e_err_exit.type == ERR_EXIT_BLOCK) { + Block_release(_e_err_exit.block); + } + _e_err_exit.type = ef ? ERR_EXIT_BLOCK : ERR_EXIT_UNDEF; + _e_err_exit.block = Block_copy(ef); +} +#endif /* __BLOCKS__ */ +#endif /* !BUILDING_VARIANT */ + __weak_reference(_err, err); void @@ -101,22 +212,27 @@ errc(int eval, int code, const char *fmt, ...) } void -verrc(eval, code, fmt, ap) - int eval; - int code; - const char *fmt; - va_list ap; +verrc(int eval, int code, const char *fmt, va_list ap) { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, ": "); + } + fprintf(_e_err_file, "%s\n", strerror(code)); + if (_e_err_exit.type) { +#ifdef __BLOCKS__ + if (_e_err_exit.type == ERR_EXIT_BLOCK) { + _e_err_exit.block(eval); + } else { + _e_err_exit.func(eval); + } +#else + _e_err_exit.func(eval); +#endif /* __BLOCKS__ */ } - fprintf(err_file, "%s\n", strerror(code)); - if (err_exit) - err_exit(eval); exit(eval); } @@ -130,19 +246,25 @@ errx(int eval, const char *fmt, ...) } void -verrx(eval, fmt, ap) - int eval; - const char *fmt; - va_list ap; +verrx(int eval, const char *fmt, va_list ap) { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) - vfprintf(err_file, fmt, ap); - fprintf(err_file, "\n"); - if (err_exit) - err_exit(eval); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, "\n"); + if (_e_err_exit.type) { +#ifdef __BLOCKS__ + if (_e_err_exit.type == ERR_EXIT_BLOCK) { + _e_err_exit.block(eval); + } else { + _e_err_exit.func(eval); + } +#else + _e_err_exit.func(eval); +#endif /* __BLOCKS__ */ + } exit(eval); } @@ -158,9 +280,7 @@ _warn(const char *fmt, ...) } void -vwarn(fmt, ap) - const char *fmt; - va_list ap; +vwarn(const char *fmt, va_list ap) { vwarnc(errno, fmt, ap); } @@ -175,19 +295,16 @@ warnc(int code, const char *fmt, ...) } void -vwarnc(code, fmt, ap) - int code; - const char *fmt; - va_list ap; +vwarnc(int code, const char *fmt, va_list ap) { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, ": "); } - fprintf(err_file, "%s\n", strerror(code)); + fprintf(_e_err_file, "%s\n", strerror(code)); } void @@ -200,14 +317,12 @@ warnx(const char *fmt, ...) } void -vwarnx(fmt, ap) - const char *fmt; - va_list ap; +vwarnx(const char *fmt, va_list ap) { - if (err_file == 0) + if (_e_err_file == 0) err_set_file((FILE *)0); - fprintf(err_file, "%s: ", _getprogname()); + fprintf(_e_err_file, "%s: ", _getprogname()); if (fmt != NULL) - vfprintf(err_file, fmt, ap); - fprintf(err_file, "\n"); + _e_visprintf(_e_err_file, fmt, ap); + fprintf(_e_err_file, "\n"); }