Skip to content

Commit

Permalink
More error tracing...
Browse files Browse the repository at this point in the history
  • Loading branch information
attipaci committed Sep 10, 2024
1 parent a08bf12 commit f80d9fb
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 127 deletions.
7 changes: 3 additions & 4 deletions include/xchange.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 4 additions & 32 deletions src/xchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -78,31 +78,6 @@ void *x_trace_null(const char *loc, const char *op) {
return NULL;
}

/**
* (<i>for internal use</i>) 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;
}

/**
* (<i>for internal use</i>) Sets errno and reports errors to the standard error, depending
* on the current debug mode, before returning the supplied return code.
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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);
}

Expand All @@ -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];
Expand Down
108 changes: 56 additions & 52 deletions src/xjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);

Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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;
}

Expand All @@ -934,23 +924,19 @@ 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;

if(type == X_STRUCT) m = GetObjectStringSize(prefixSize, (XStructure *) ptr);
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 {
Expand All @@ -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"
}
Expand All @@ -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]);
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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;
}
Expand All @@ -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));
Expand All @@ -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);
}
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit f80d9fb

Please sign in to comment.