From f80d9fb9e12b9a2b88826e685b9f6ea576f1613c Mon Sep 17 00:00:00 2001 From: Attila Kovacs Date: Tue, 10 Sep 2024 21:39:46 +0200 Subject: [PATCH] More error tracing... --- include/xchange.h | 7 ++- src/xchange.c | 36 ++------------- src/xjson.c | 108 +++++++++++++++++++++++---------------------- src/xlookup.c | 28 +++++------- src/xstruct.c | 24 +++------- test/Makefile | 2 +- test/test-json.c | 3 ++ test/test-lookup.c | 2 + test/test-struct.c | 2 +- 9 files changed, 85 insertions(+), 127 deletions(-) diff --git a/include/xchange.h b/include/xchange.h index dcb67a9..ac03538 100644 --- a/include/xchange.h +++ b/include/xchange.h @@ -282,12 +282,11 @@ char *xStringCopyOf(const char *str); # endif # endif - -int x_trace(const char *loc, const char *op, int n); -void *x_trace_null(const char *loc, const char *op); -void x_set_errno(int en, const char *from, const char *desc, ...); int x_error(int ret, int en, const char *from, const char *desc, ...); int x_warn(const char *from, const char *desc, ...); +int x_trace(const char *loc, const char *op, int n); +void *x_trace_null(const char *loc, const char *op); + /** * Propagates an error (if any) with an offset. If the error is non-zero, it returns with the offset diff --git a/src/xchange.c b/src/xchange.c index 08d1981..b30057d 100644 --- a/src/xchange.c +++ b/src/xchange.c @@ -54,7 +54,7 @@ boolean xDebug = FALSE; * @return n */ int x_trace(const char *loc, const char *op, int n) { - if(n != 0 && xDebug) { + if(n < 0 && xDebug) { fprintf(stderr, " @ %s", loc); if(op) fprintf(stderr, " [%s]", op); fprintf(stderr, " [=> %d]\n", n); @@ -78,31 +78,6 @@ void *x_trace_null(const char *loc, const char *op) { return NULL; } -/** - * (for internal use) Sets an errno and report errors to the standard error, depending - * on the current debug mode. - * - * @param en {int} UNIX error number (see errno.h) - * @param from {string} Function (:location) where error originated - * @param desc {string} Description of error, with information to convey to user. - * - * @sa x_error() - * @sa x_debug() - */ -void x_set_errno(int en, const char *from, const char *desc, ...) { - va_list varg; - - va_start(varg, desc); - if(xDebug) { - fprintf(stderr, "\n ERROR! %s: ", from); - vfprintf(stderr, desc, varg); - fprintf(stderr, "\n"); - } - va_end(varg); - - errno = en; -} - /** * (for internal use) Sets errno and reports errors to the standard error, depending * on the current debug mode, before returning the supplied return code. @@ -256,7 +231,7 @@ int xElementSizeOf(XType type) { case X_STRUCT: return sizeof(XStructure); case X_STRING: return sizeof(char *); } - return x_warn("xElementSizeOf", "invalid type: %d", type); + return 0; } /** @@ -269,10 +244,7 @@ int xElementSizeOf(XType type) { */ char xTypeChar(XType type) { if(type < 0) return 'C'; - if(type < 0x20 || type > 0x7E) { - x_warn("xTypeChar", "invaid type: %d", type); - return '?'; - } + if(type < 0x20 || type > 0x7E) return (char) x_error('?', EINVAL, "xTypeChar", "invalid type: %d", type); return (char) (type & 0xff); } @@ -289,7 +261,7 @@ int xGetElementCount(int ndim, const int *sizes) { int i, N = 1; if(ndim > 0 && !sizes) - x_warn("xGetElementCount", "input 'sizes' is NULL (ndim = %d)", ndim); + return x_error(1, EINVAL, "xGetElementCount", "input 'sizes' is NULL (ndim = %d)", ndim); if(ndim > X_MAX_DIMS) ndim = X_MAX_DIMS; for(i = 0; i < ndim; i++) N *= sizes[i]; diff --git a/src/xjson.c b/src/xjson.c index b2eafdc..0582d28 100644 --- a/src/xjson.c +++ b/src/xjson.c @@ -489,7 +489,6 @@ static char UnescapedChar(char c) { return c; } - static char *ParseString(char **pos, int *lineNumber) { int isEscaped = 0; int i, k, l; @@ -553,9 +552,6 @@ static char *ParseString(char **pos, int *lineNumber) { return dst; } - - - static void *ParsePrimitive(char **pos, XType *type, int *lineNumber) { int l; long long ll; @@ -822,7 +818,7 @@ static int GetObjectStringSize(int prefixSize, const XStructure *s) { for(f = s->firstField; f != NULL; f = f->next) { int m = GetFieldStringSize(prefixSize + ilen, f); - if(m < 0) return m; + prop_error("GetObjectStringSize", m); n += m; } @@ -831,21 +827,20 @@ static int GetObjectStringSize(int prefixSize, const XStructure *s) { static int PrintObject(const char *prefix, const XStructure *s, char *str, boolean asArray) { + static const char *fn = "PrintObject"; + char *fieldPrefix; XField *f; int n = 0; if(!s) return X_SUCCESS; - if(!str) return X_NULL; - if(!prefix) return X_NULL; + if(!str) return x_error(X_NULL, EINVAL, fn, "output string buffer is NULL"); + if(!prefix) return x_error(X_NULL, EINVAL, fn, "prefix is NULL"); if(!s->firstField) return sprintf(&str[n], "{ }"); fieldPrefix = malloc(strlen(prefix) + ilen + 1); - if(!fieldPrefix) { - Error("Out of memory (field prefix).\n"); - return X_INCOMPLETE; - } + x_check_alloc(fieldPrefix); sprintf(fieldPrefix, "%s%s", prefix, indent); @@ -855,7 +850,7 @@ static int PrintObject(const char *prefix, const XStructure *s, char *str, boole int m = PrintField(fieldPrefix, f, &str[n]); if(m < 0) { free(fieldPrefix); - return m; // Error code; + return x_trace(fn, NULL, m); // Error code; } n += m; } @@ -868,17 +863,13 @@ static int PrintObject(const char *prefix, const XStructure *s, char *str, boole static int GetFieldStringSize(int prefixSize, const XField *f) { + static const char *fn = "GetFieldStringSize"; + int m; if(f == NULL) return 0; - if(f->name == NULL) { - Error("Field @0x%p name has no name.\n", f); - return X_NAME_INVALID; - } - if(*f->name == '\0') { - Error("Empty @0x%p field name.\n", f); - return X_NAME_INVALID; - } + if(f->name == NULL) return x_error(X_NAME_INVALID, EINVAL, fn, "field->name is NULL"); + if(*f->name == '\0') return x_error(X_NAME_INVALID, EINVAL, fn, "field->name is empty"); if(!f->value) m = 4; // "null" else if(f->ndim > 1) m = GetArrayStringSize(prefixSize, f->value, f->type, f->ndim, f->sizes); @@ -891,34 +882,33 @@ static int GetFieldStringSize(int prefixSize, const XField *f) { default: { if (xGetElementCount(f->ndim, f->sizes) == 0) return 0; m = xStringElementSizeOf(f->type); - if(m < 0) Error("Unrecognised type 0x%02x in field @0x%p.\n", f->type, f); } } - if(m < 0) return m; // Error code + prop_error(fn, m); return m + strlen(f->name) + 4; // name + " = " + value + "\n" } static int PrintField(const char *prefix, const XField *f, char *str) { + static const char *fn = "PrintField"; + int n = 0, m; - if(str == NULL) return X_NULL; + if(str == NULL) return x_error(X_NULL, EINVAL, fn, "output string buffer is NULL"); if(f == NULL) return 0; - if(f->name == NULL) return X_NAME_INVALID; - if(*f->name == '\0') return X_NAME_INVALID; - if(f->isSerialized) return X_PARSE_ERROR; // We don't know what format, so return an error + if(f->name == NULL) return x_error(X_NAME_INVALID, EINVAL, fn, "field->name is NULL"); + if(*f->name == '\0') return x_error(X_NAME_INVALID, EINVAL, fn, "field->name is empty"); + if(f->isSerialized) return x_error(X_PARSE_ERROR, ENOMSG, fn, "field is serialized (unknown format)"); // We don't know what format, so return an error n = sprintf(str, "%s%s : ", prefix, f->name); m = PrintArray(prefix, f->value, f->type, f->ndim, f->sizes, &str[n]); - if(m < 0) return m; + prop_error(fn, m); n += m; n += sprintf(&str[n], "\n"); - - return n; } @@ -934,12 +924,11 @@ static __inline__ int SizeOf(XType type, int ndim, const int *sizes) { static int GetArrayStringSize(int prefixSize, char *ptr, XType type, int ndim, const int *sizes) { - if(!ptr) return JSON_NULL_LEN; + static const char *fn = "GetArrayStringSize"; + + if(!ptr) return x_error(X_NULL, EINVAL, fn, "data pointer is NULL"); + if(ndim < 0) return x_error(X_SIZE_INVALID, EINVAL, fn, "invalid ndim: %d", ndim); - if(ndim < 0) { - Error("Invalid array dimension %d.\n", ndim); - return X_SIZE_INVALID; - } if(ndim == 0) { int m; @@ -947,10 +936,7 @@ static int GetArrayStringSize(int prefixSize, char *ptr, XType type, int ndim, c else if(type == X_STRING || type == X_RAW) m = GetJsonStringSize((char *) ptr, TERMINATED_STRING); else return m = xStringElementSizeOf(type); - if(m < 0) { - Error("Invalid type 0x%02x\n.", type); - return m; // Error code - } + prop_error(fn, m); return m; } else { @@ -964,7 +950,8 @@ static int GetArrayStringSize(int prefixSize, char *ptr, XType type, int ndim, c for(k = 0; k < N; k++, ptr += rowSize) { int m = GetArrayStringSize(prefixSize + ilen, ptr, type, ndim-1, &sizes[1]); - if(m < 0) return m; // Error code + prop_error(fn, m); + if(newLine) n += prefixSize + ilen; n += m + 3; // + " , " or " ,\n" } @@ -974,15 +961,20 @@ static int GetArrayStringSize(int prefixSize, char *ptr, XType type, int ndim, c static int PrintArray(const char *prefix, char *ptr, XType type, int ndim, const int *sizes, char *str) { - const char *str0 = str; + static const char *fn = "PrintArray"; - if(!str) return X_NULL; - if(!prefix) return X_NULL; + const char *str0 = str; - if(ndim < 0) return X_SIZE_INVALID; + if(!str) return x_error(X_NULL, EINVAL, fn, "output string buffer is NULL"); + if(!prefix) return x_error(X_NULL, EINVAL, fn, "prefix is NULL"); - if(ndim == 0) return (type == X_STRUCT) ? PrintObject(prefix, (XStructure *) ptr, str, FALSE) : PrintPrimitive(ptr, type, str); + if(ndim < 0) return x_error(X_SIZE_INVALID, ERANGE, fn, "invalid ndim: %d", ndim); + if(ndim == 0) { + int n = (type == X_STRUCT) ? PrintObject(prefix, (XStructure *) ptr, str, FALSE) : PrintPrimitive(ptr, type, str); + prop_error(fn, n); + return n; + } else { const int N = sizes[0]; const int rowSize = SizeOf(type, ndim-1, &sizes[1]); @@ -993,6 +985,8 @@ static int PrintArray(const char *prefix, char *ptr, XType type, int ndim, const // Indentation for elements... rowPrefix = malloc(strlen(prefix) + ilen + 1); + x_check_alloc(rowPrefix); + sprintf(rowPrefix, "%s%s", prefix, indent); // Special case: empty array @@ -1003,7 +997,6 @@ static int PrintArray(const char *prefix, char *ptr, XType type, int ndim, const return str - str0; } - *(str++) = '['; // Opening bracket at current position... // Print elements as required. @@ -1032,7 +1025,7 @@ static int PrintArray(const char *prefix, char *ptr, XType type, int ndim, const if(m < 0) { free(rowPrefix); - return m; // Error code + return x_trace(fn, NULL, m); // Error code } str += m; } @@ -1051,9 +1044,14 @@ static int PrintArray(const char *prefix, char *ptr, XType type, int ndim, const static int PrintPrimitive(const void *ptr, XType type, char *str) { + static const char *fn = "PrintPrimitive"; + if(!ptr) return sprintf(str, JSON_NULL); - if(xIsCharSequence(type)) return PrintString((char *) ptr, xElementSizeOf(type), str); + if(xIsCharSequence(type)) { + prop_error(fn, PrintString((char *) ptr, xElementSizeOf(type), str)); + return X_SUCCESS; + } switch(type) { case X_BOOLEAN: return sprintf(str, (*(boolean *)ptr ? JSON_TRUE : JSON_FALSE)); @@ -1069,7 +1067,7 @@ static int PrintPrimitive(const void *ptr, XType type, char *str) { case X_DOUBLE: return xPrintDouble(str, *(double *) ptr); case X_STRING: case X_RAW: return PrintString(*(char **) ptr, TERMINATED_STRING, str); - default: return X_TYPE_INVALID; + default: return x_error(X_TYPE_INVALID, EINVAL, fn, "invalid type: %d", type); } } @@ -1095,7 +1093,7 @@ static int GetJsonBytes(char c) { static int GetJsonStringSize(const char *src, int maxLength) { int i, n = 2; // "" - for(i=0; i < maxLength && src[i]; i++) n += GetJsonBytes(src[i]); + for(i = 0; i < maxLength && src[i]; i++) n += GetJsonBytes(src[i]); return n; } @@ -1152,21 +1150,27 @@ static int PrintString(const char *src, int maxLength, char *json) { * @sa xjsonUnescapeString() */ char *xjsonEscapeString(const char *src, int maxLength) { + static const char *fn = "xjsonEscapeString"; + int size; char *json; if(!src) { - x_error(0, EINVAL, "xjsonEscapeString", "input string is NULL"); + x_error(0, EINVAL, fn, "input string is NULL"); return NULL; } size = GetJsonStringSize(src, maxLength); + json = malloc(size + 1); - if(!json) return NULL; + if(!json) { + x_error(0, errno, fn, "malloc() error (%d bytes)", (size + 1)); + return NULL; + } if(PrintString(src, maxLength, json) != X_SUCCESS) { free(json); - return NULL; + return x_trace_null(fn, NULL); } return json; diff --git a/src/xlookup.c b/src/xlookup.c index 5a1fed8..3793caa 100644 --- a/src/xlookup.c +++ b/src/xlookup.c @@ -270,6 +270,7 @@ int xLookupPutAll(XLookupTable *tab, const char *prefix, const XStructure *s, bo n = xLookupPutAllAsync(tab, prefix, s, recursive); sem_post(&p->sem); + prop_error(fn, n); return n; } @@ -302,6 +303,7 @@ int xLookupRemoveAll(XLookupTable *tab, const char *prefix, const XStructure *s, n = xLookupRemoveAllAsync(tab, prefix, s, recursive); sem_post(&p->sem); + prop_error(fn, n); return n; } @@ -318,41 +320,29 @@ int xLookupRemoveAll(XLookupTable *tab, const char *prefix, const XStructure *s, * @sa xDestroyLookup() */ XLookupTable *xAllocLookup(unsigned int size) { - static const char *fn = "xAllocLookup"; - XLookupTable *tab; XLookupPrivate *p; unsigned int n = 2; if(size < 1) { - x_error(0, errno, fn, "invalid size: %d", size); + x_error(0, errno, "xAllocLookup", "invalid size: %d", size); return NULL; } while(n < size) n <<= 1; p = (XLookupPrivate *) calloc(1, sizeof(XLookupPrivate)); - if(!p) { - perror("ERROR! alloc error"); - exit(errno); - } + x_check_alloc(p) p->table = (XLookupEntry **) calloc(n, sizeof(XLookupEntry *)); - if(!p->table) { - x_error(0, errno, fn, "calloc() error (n = %d)", n); - free(p); - return NULL; - } + x_check_alloc(p->table); p->nBins = n; sem_init(&p->sem, FALSE, 1); tab = (XLookupTable *) calloc(1, sizeof(XLookupTable)); - if(!tab) { - perror("ERROR! alloc error"); - exit(errno); - } + x_check_alloc(tab); tab->priv = p; @@ -380,15 +370,17 @@ XLookupTable *xAllocLookup(unsigned int size) { * @sa xDestroyLookup() */ XLookupTable *xCreateLookup(const XStructure *s, boolean recursive) { + static const char *fn = "xCreateLookup"; + XLookupTable *l; if(s == NULL) { - errno = EINVAL; + x_error(0, EINVAL, fn, "input structure is NULL"); return NULL; } l = xAllocLookup(recursive ? xDeepCountFields(s) : xCountFields(s)); - if(!l) return x_trace_null("xCreateLookup", NULL); + if(!l) return x_trace_null(fn, NULL); xLookupPutAllAsync(l, NULL, s, recursive); diff --git a/src/xstruct.c b/src/xstruct.c index 42a9ca2..c3bf8f2 100644 --- a/src/xstruct.c +++ b/src/xstruct.c @@ -707,10 +707,7 @@ int xCountFields(const XStructure *s) { XField *f; int n = 0; - if(!s) { - x_warn("xCountFields", "input structure is NULL"); - return 0; - } + if(!s) return 0; for(f = s->firstField; f != NULL; f = f->next) n++; @@ -763,10 +760,7 @@ void xDestroyField(XField *f) { void xClearStruct(XStructure *s) { XField *f; - if(s == NULL) { - x_warn("xClearStruct", "input structure is NULL"); - return; - } + if(s == NULL) return; for(f = s->firstField; f != NULL; ) { XField *next = f->next; @@ -885,10 +879,7 @@ int xReduceAllDims(XStructure *s) { char *xNextIDToken(const char *id) { char *next; - if(!id) { - x_warn("xNextIDToken", "input is NULL"); - return NULL; - } + if(!id) return NULL; // Ignore leading separator. if(!strncmp(id, X_SEP, X_SEP_LENGTH)) id += X_SEP_LENGTH; @@ -904,16 +895,11 @@ char *xNextIDToken(const char *id) { * @return Pointer to the start of the next compound ID token, or NULL if there is no more components in the ID. */ char *xCopyIDToken(const char *id) { - static const char *fn = "xCopyIDToken"; - const char *next; char *token; int l; - if(!id) { - x_warn(fn, "input is NULL"); - return NULL; - } + if(!id) return NULL; // Ignore leading separator. if(!strncmp(id, X_SEP, X_SEP_LENGTH)) id += X_SEP_LENGTH; @@ -924,7 +910,7 @@ char *xCopyIDToken(const char *id) { token = malloc(l+1); if(!token) { - x_error(0, errno, fn, "malloc error"); + x_error(0, errno, "xCopyIDToken", "malloc error"); return NULL; } diff --git a/test/Makefile b/test/Makefile index 7340074..279d259 100644 --- a/test/Makefile +++ b/test/Makefile @@ -15,7 +15,7 @@ $(BIN)/test-%: $(OBJ)/test-%.o $(LIB)/libxchange.a | $(BIN) $(LIB)/libxchange.a: ../src ../include ../Makefile make -C .. static - + $(BIN): mkdir $(BIN) diff --git a/test/test-json.c b/test/test-json.c index 2dc96b1..42793ff 100644 --- a/test/test-json.c +++ b/test/test-json.c @@ -45,6 +45,7 @@ int main(int argc, char *argv[]) { char *str = xjsonToString(s), *next, *str1; printf("%s\n\n", str); + xSetDebug(TRUE); next = str; s1 = xjsonParseAt(&next, NULL); @@ -56,5 +57,7 @@ int main(int argc, char *argv[]) { return 1; } + printf("OK\n"); + return 0; } diff --git a/test/test-lookup.c b/test/test-lookup.c index bb6659b..6c20be2 100644 --- a/test/test-lookup.c +++ b/test/test-lookup.c @@ -88,5 +88,7 @@ int main(int argc, char *argv[]) { xDestroyLookup(l); + printf("OK\n"); + return 0; } diff --git a/test/test-struct.c b/test/test-struct.c index 1e60a53..4f21745 100644 --- a/test/test-struct.c +++ b/test/test-struct.c @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) { xDestroyStruct(s); - + printf("OK\n"); return 0; }