struct btp_thread * btp_thread_dup(struct btp_thread *thread, bool siblings) { struct btp_thread *result = btp_thread_new(); memcpy(result, thread, sizeof(struct btp_thread)); /* Handle siblings. */ if (siblings) { if (result->next) result->next = btp_thread_dup(result->next, true); } else result->next = NULL; /* Do not copy that. */ result->frames = btp_frame_dup(result->frames, true); return result; }
/* constructor */ PyObject *p_btp_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds) { ThreadObject *to = (ThreadObject *)PyObject_New(ThreadObject, &ThreadTypeObject); if (!to) return PyErr_NoMemory(); const char *str = NULL; int only_funs = 0; if (!PyArg_ParseTuple(args, "|si", &str, &only_funs)) return NULL; if (str) { if (!only_funs) { struct btp_location location; btp_location_init(&location); to->thread = btp_thread_parse(&str, &location); if (!to->thread) { PyErr_SetString(PyExc_ValueError, location.message); return NULL; } } else { to->thread = btp_thread_parse_funs(str); } to->frames = frame_linked_list_to_python_list(to->thread); if (!to->frames) return NULL; } else { to->frames = PyList_New(0); to->thread = btp_thread_new(); } return (PyObject *)to; }
struct btp_thread * btp_thread_parse(char **input, struct btp_location *location) { char *local_input = *input; /* Read the Thread keyword, which is mandatory. */ int chars = btp_skip_string(&local_input, "Thread"); location->column += chars; if (0 == chars) { location->message = "\"Thread\" header expected"; return NULL; } /* Skip spaces, at least one space is mandatory. */ int spaces = btp_skip_char_sequence(&local_input, ' '); location->column += spaces; if (0 == spaces) { location->message = "Space expected after the \"Thread\" keyword."; return NULL; } /* Read thread number. */ struct btp_thread *imthread = btp_thread_new(); int digits = btp_parse_unsigned_integer(&local_input, &imthread->number); location->column += digits; if (0 == digits) { location->message = "Thread number expected."; btp_thread_free(imthread); return NULL; } /* Skip spaces after the thread number and before parentheses. */ spaces = btp_skip_char_sequence(&local_input, ' '); location->column += spaces; if (0 == spaces) { location->message = "Space expected after the thread number."; btp_thread_free(imthread); return NULL; } /* Read the LWP section in parentheses, optional. */ location->column += btp_thread_skip_lwp(&local_input); /* Read the Thread keyword in parentheses, optional. */ chars = btp_skip_string(&local_input, "(Thread "); location->column += chars; if (0 != chars) { /* Read the thread identification number. It can be either in * decimal or hexadecimal form. * Examples: * "Thread 10 (Thread 2476):" * "Thread 8 (Thread 0xb07fdb70 (LWP 6357)):" */ digits = btp_skip_hexadecimal_number(&local_input); if (0 == digits) digits = btp_skip_unsigned_integer(&local_input); location->column += digits; if (0 == digits) { location->message = "The thread identification number expected."; btp_thread_free(imthread); return NULL; } /* Handle the optional " (LWP [0-9]+)" section. */ location->column += btp_skip_char_sequence(&local_input, ' '); location->column += btp_thread_skip_lwp(&local_input); /* Read the end of the parenthesis. */ if (!btp_skip_char(&local_input, ')')) { location->message = "Closing parenthesis for Thread expected."; btp_thread_free(imthread); return NULL; } } /* Read the end of the header line. */ chars = btp_skip_string(&local_input, ":\n"); if (0 == chars) { location->message = "Expected a colon followed by a newline ':\\n'."; btp_thread_free(imthread); return NULL; } /* Add the newline from the last btp_skip_string. */ btp_location_add(location, 2, 0); /* Read the frames. */ struct btp_frame *frame, *prevframe = NULL; struct btp_location frame_location; btp_location_init(&frame_location); while ((frame = btp_frame_parse(&local_input, &frame_location))) { if (prevframe) { btp_frame_add_sibling(prevframe, frame); prevframe = frame; } else imthread->frames = prevframe = frame; btp_location_add(location, frame_location.line, frame_location.column); } if (!imthread->frames) { location->message = frame_location.message; btp_thread_free(imthread); return NULL; } *input = local_input; return imthread; }