struct sr_java_frame * sr_java_frame_from_json(struct sr_json_value *root, char **error_message) { if (!JSON_CHECK_TYPE(root, SR_JSON_OBJECT, "frame")) return NULL; struct sr_java_frame *result = sr_java_frame_new(); bool success = JSON_READ_STRING(root, "name", &result->name) && JSON_READ_STRING(root, "file_name", &result->file_name) && JSON_READ_UINT32(root, "file_line", &result->file_line) && JSON_READ_STRING(root, "class_path", &result->class_path) && JSON_READ_BOOL(root, "is_native", &result->is_native) && JSON_READ_BOOL(root, "is_exception", &result->is_exception) && JSON_READ_STRING(root, "message", &result->message); if (!success) { sr_java_frame_free(result); return NULL; } return result; }
/* destructor */ void sr_py_java_frame_free(PyObject *object) { struct sr_py_java_frame *this = (struct sr_py_java_frame*)object; sr_java_frame_free(this->frame); PyObject_Del(object); }
void sr_java_frame_free_full(struct sr_java_frame *frame) { while(frame) { struct sr_java_frame *tmp = frame; frame = frame->next; sr_java_frame_free(tmp); } }
struct sr_java_frame * sr_java_frame_parse_exception(const char **input, struct sr_location *location) { /* java.lang.NullPointerException: foo */ const char *cursor = sr_skip_whitespace(*input); sr_location_add(location, 0, cursor - *input); const char *mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ": \t\n")); if (mark == cursor) { location->message = "Expected exception name"; return NULL; } struct sr_java_frame *exception = sr_java_frame_new_exception(); exception->name = sr_strndup(mark, cursor - mark); /* : foo */ if (*cursor == ':') { ++cursor; sr_location_add(location, 0, 1); mark = cursor; /* foo */ cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); mark = cursor; sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "\n")); if (mark != cursor) exception->message = sr_strndup(mark, cursor - mark); } else { /* just to be sure, that we skip white space behind exception name */ sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "\n")); } if (*cursor == '\n') { ++cursor; /* this adds one line */ sr_location_add(location, 2, 0); } /* else *cursor == '\0' */ mark = cursor; struct sr_java_frame *frame = NULL; /* iterate line by line best effort - continue on error */ while (*cursor != '\0') { cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); /* Each inner exception has '...' at its end */ if (strncmp("... ", cursor, strlen("... ")) == 0) goto current_exception_done; /* Suppressed exceptions follow after the end of current exception */ if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) goto current_exception_done; /* The top most exception does not have '...' at its end */ if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) goto parse_inner_exception; struct sr_java_frame *parsed = sr_java_frame_parse(&cursor, location); if (parsed == NULL) { sr_java_frame_free(exception); return NULL; } mark = cursor; if (exception->next == NULL) exception->next = parsed; else { assert(frame); frame->next = parsed; } frame = parsed; } /* We are done with the top most exception without inner exceptions */ /* because of no 'Caused by:' and no '...' */ goto exception_parsing_successful; current_exception_done: sr_skip_to_next_line_location(&cursor, &location->line, &location->column); mark = cursor; cursor = sr_skip_whitespace(mark); sr_location_add(location, 0, cursor - mark); if (strncmp("Suppressed: ", cursor, strlen("Suppressed: ")) == 0) { /* Skip all lines related to the suppressed exception. We can do * this by skipping all lines that begin with a whitespace - the * main exception chain always begins without preceding whitespace. */ sr_skip_to_next_line_location(&cursor, &location->line, &location->column); while (cursor && isspace(*cursor)) sr_skip_to_next_line_location(&cursor, &location->line, &location->column); } if (strncmp("Caused by: ", cursor, strlen("Caused by: ")) == 0) { parse_inner_exception: cursor += strlen("Caused by: "); sr_location_add(location, 0, strlen("Caused by: ")); struct sr_java_frame *inner = sr_java_frame_parse_exception(&cursor, location); if (inner == NULL) { sr_java_frame_free(exception); return NULL; } struct sr_java_frame *last_inner = sr_java_frame_get_last(inner); last_inner->next = exception; exception = inner; } exception_parsing_successful: *input = cursor; return exception; }