diff --git a/common/errors.c b/common/errors.c index 05bb7415..88f54dfb 100644 --- a/common/errors.c +++ b/common/errors.c @@ -4,6 +4,26 @@ #include "ui.h" #include "uipriv.h" +#define internalErrorPrefix "libui internal error" +// TODO add debugging advice? +#define internalErrorSuffix "This likely means there is a bug in libui itself. Contact the libui authors." + +void uiprivInternalError(const char *fmt, ...) +{ + va_list ap; + char buf[256]; + int n; + + va_start(ap, fmt); + n = vsnprintf(buf, 256, fmt, ap); + va_end(ap); + if (n < 0) + uiprivReportError(internalErrorPrefix, "internal error string has encoding error", internalErrorSuffix, true); + if (n >= 256) + uiprivReportError(internalErrorPrefix, "internal error string too long", internalErrorSuffix, true); + uiprivReportError(internalErrorPrefix, buf, internalErrorSuffix, true); +} + static const char *messages[] = { [uiprivProgrammerErrorWrongStructSize] = "wrong size %zu for %s", [uiprivProgrammerErrorIndexOutOfRange] = "index %d out of range in %s()", @@ -15,22 +35,19 @@ static void prepareProgrammerError(char *buf, int size, unsigned int which, va_l { int n; - if (which >= uiprivNumProgrammerErrors) { - // TODO - } + if (which >= uiprivNumProgrammerErrors) + uiprivInternalError("bad programmer error value %u", which); n = vsnprintf(buf, size, messages[which], ap); - if (n < 0) { - // TODO - } - if (n >= size) { - // TODO - buf[size - 4] = '.'; - buf[size - 3] = '.'; - buf[size - 2] = '.'; - buf[size - 1] = '\0'; - } + if (n < 0) + uiprivInternalError("programmer error string for %u has encoding error", which); + if (n >= size) + uiprivInternalError("programmer error string for %u too long (%d)", which, n); } +#define programmerErrorPrefix "libui programmer error" +// TODO add debugging advice? +#define programmerErrorSuffix "This likely means you are using libui incorrectly. Check your source code and try again. If you have received this warning in error, contact the libui authors." + void uiprivProgrammerError(unsigned int which, ...) { va_list ap; @@ -39,5 +56,5 @@ void uiprivProgrammerError(unsigned int which, ...) va_start(ap, which); prepareProgrammerError(buf, 256, which, ap); va_end(ap); - uiprivSysProgrammerError(buf); + uiprivReportError(programmerErrorPrefix, buf, programmerErrorSuffix, false); } diff --git a/common/uipriv.h b/common/uipriv.h index 9fde1a53..4090117f 100644 --- a/common/uipriv.h +++ b/common/uipriv.h @@ -11,6 +11,7 @@ extern int uiprivInitReturnError(uiInitError *err, const char *msg); extern int uiprivInitReturnErrorf(uiInitError *err, const char *msg, ...); // errors.c +extern void uiprivInternalError(const char *fmt, ...); enum { uiprivProgrammerErrorWrongStructSize, // arguments: size_t badSize, const char *structName uiprivProgrammerErrorIndexOutOfRange, // arguments: int badIndex, __func__ @@ -21,10 +22,7 @@ enum { uiprivNumProgrammerErrors, }; extern void uiprivProgrammerError(unsigned int which, ...); -extern void uiprivSysProgrammerError(const char *msg); -#define uiprivProgrammerErrorPrefix "libui programmer error" -// TODO add debugging advice? -#define uiprivProgrammerErrorAdvice "This likely means you are using libui incorrectly. Check your source code and try again. If you have received this warning in error, contact the libui authors." +extern void uiprivReportError(const char *prefix, const char *msg, const char *suffix, bool internal); #ifdef __cplusplus } diff --git a/darwin/main.m b/darwin/main.m index db44cb60..05a3c063 100644 --- a/darwin/main.m +++ b/darwin/main.m @@ -115,12 +115,17 @@ void uiQueueMain(void (*f)(void *data), void *data) // - possibly others, all on stackoverflow.com (and maybe once on Apple's own forums?); I forget now static void debugBreak(void); -void uiprivSysProgrammerError(const char *msg) +void uiprivReportError(const char *prefix, const char *msg, const char *suffix, bool internal) { - NSLog(@"*** %s: %s. %s", uiprivProgrammerErrorPrefix, msg, uiprivProgrammerErrorAdvice); - // TODO either find an appropriate exception for each message or use a custom exception name - [NSException raise:NSInvalidArgumentException - format:@"%s: %s", uiprivProgrammerErrorPrefix, msg]; + NSExceptionName exceptionName; + + NSLog(@"*** %s: %s. %s", prefix, msg, suffix); + exceptionName = NSInternalInconsistencyException; + if (!internal) + // TODO either find an appropriate exception for each possible message or use a custom exception name + exceptionName = NSInvalidArgumentException; + [NSException raise:exceptionName + format:@"%s: %s", prefix, msg]; debugBreak(); abort(); // we shouldn't reach here }