X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/268a13a5a3f7c6b9b6ffc5ac2d1b24eb41f3fbdc..82fc57fd6b0aff85d86c47b5892f91c04fd58f0f:/gdb/python/python.c diff --git a/gdb/python/python.c b/gdb/python/python.c index 96bee7c3b0..bf3abdbbbe 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1,6 +1,6 @@ /* General python/gdb code - Copyright (C) 2008-2019 Free Software Foundation, Inc. + Copyright (C) 2008-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -27,15 +27,14 @@ #include "objfiles.h" #include "value.h" #include "language.h" -#include "event-loop.h" -#include "serial.h" +#include "gdbsupport/event-loop.h" #include "readline/tilde.h" #include "python.h" #include "extension-priv.h" #include "cli/cli-utils.h" #include #include "location.h" -#include "ser-event.h" +#include "run-on-main-thread.h" /* Declared constants and enum for python stack printing. */ static const char python_excp_none[] = "none"; @@ -107,10 +106,6 @@ int gdb_python_initialized; extern PyMethodDef python_GdbMethods[]; -#ifdef IS_PY3K -extern struct PyModuleDef python_GdbModuleDef; -#endif - PyObject *gdb_module; PyObject *gdb_python_module; @@ -150,6 +145,8 @@ static void gdbpy_set_quit_flag (const struct extension_language_defn *); static int gdbpy_check_quit_flag (const struct extension_language_defn *); static enum ext_lang_rc gdbpy_before_prompt_hook (const struct extension_language_defn *, const char *current_gdb_prompt); +static gdb::optional gdbpy_colorize + (const std::string &filename, const std::string &contents); /* The interface between gdb proper and loading of python scripts. */ @@ -189,6 +186,8 @@ const struct extension_language_ops python_extension_ops = gdbpy_before_prompt_hook, gdbpy_get_matching_xmethod_workers, + + gdbpy_colorize, }; /* Architecture and language to be used in callbacks from @@ -228,13 +227,37 @@ gdbpy_enter::~gdbpy_enter () m_error->restore (); - PyGILState_Release (m_state); python_gdbarch = m_gdbarch; python_language = m_language; restore_active_ext_lang (m_previous_active); + PyGILState_Release (m_state); } +/* A helper class to save and restore the GIL, but without touching + the other globals that are handled by gdbpy_enter. */ + +class gdbpy_gil +{ +public: + + gdbpy_gil () + : m_state (PyGILState_Ensure ()) + { + } + + ~gdbpy_gil () + { + PyGILState_Release (m_state); + } + + DISABLE_COPY_AND_ASSIGN (gdbpy_gil); + +private: + + PyGILState_STATE m_state; +}; + /* Set the quit flag. */ static void @@ -248,6 +271,10 @@ gdbpy_set_quit_flag (const struct extension_language_defn *extlang) static int gdbpy_check_quit_flag (const struct extension_language_defn *extlang) { + if (!gdb_python_initialized) + return 0; + + gdbpy_gil gil; return PyOS_InterruptOccurred (); } @@ -323,9 +350,8 @@ python_interactive_command (const char *arg, int from_tty) A FILE * from one runtime does not necessarily operate correctly in the other runtime. - To work around this potential issue, we create on Windows hosts the - FILE object using Python routines, thus making sure that it is - compatible with the Python library. */ + To work around this potential issue, we run code in Python to load + the script. */ static void python_run_simple_file (FILE *file, const char *filename) @@ -339,15 +365,21 @@ python_run_simple_file (FILE *file, const char *filename) /* Because we have a string for a filename, and are using Python to open the file, we need to expand any tilde in the path first. */ gdb::unique_xmalloc_ptr full_path (tilde_expand (filename)); - gdbpy_ref<> python_file (PyFile_FromString (full_path.get (), (char *) "r")); - if (python_file == NULL) + + if (gdb_python_module == nullptr + || ! PyObject_HasAttrString (gdb_python_module, "_execute_file")) + error (_("Installation error: gdb._execute_file function is missing")); + + gdbpy_ref<> return_value + (PyObject_CallMethod (gdb_python_module, "_execute_file", "s", + full_path.get ())); + if (return_value == nullptr) { - gdbpy_print_stack (); - error (_("Error while opening file: %s"), full_path.get ()); + /* Use PyErr_PrintEx instead of gdbpy_print_stack to better match the + behavior of the non-Windows codepath. */ + PyErr_PrintEx(0); } - PyRun_SimpleFile (PyFile_AsFile (python_file.get ()), filename); - #endif /* _WIN32 */ } @@ -436,7 +468,7 @@ gdbpy_parameter_value (enum var_types type, void *var) case var_boolean: { - if (* (int *) var) + if (* (bool *) var) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -460,7 +492,7 @@ gdbpy_parameter_value (enum var_types type, void *var) /* Fall through. */ case var_zinteger: case var_zuinteger_unlimited: - return PyLong_FromLong (* (int *) var); + return gdb_py_object_from_longest (* (int *) var).release (); case var_uinteger: { @@ -468,13 +500,13 @@ gdbpy_parameter_value (enum var_types type, void *var) if (val == UINT_MAX) Py_RETURN_NONE; - return PyLong_FromUnsignedLong (val); + return gdb_py_object_from_ulongest (val).release (); } case var_zuinteger: { unsigned int val = * (unsigned int *) var; - return PyLong_FromUnsignedLong (val); + return gdb_py_object_from_ulongest (val).release (); } } @@ -616,6 +648,12 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) } catch (const gdb_exception &except) { + /* If an exception occurred then we won't hit normal_stop (), or have + an exception reach the top level of the event loop, which are the + two usual places in which stdin would be re-enabled. So, before we + convert the exception and continue back in Python, we should + re-enable stdin here. */ + async_enable_stdin (); GDB_PY_HANDLE_EXCEPTION (except); } @@ -640,19 +678,6 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) static PyObject * gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) { - /* A simple type to ensure clean up of a vector of allocated strings - when a C interface demands a const char *array[] type - interface. */ - struct symtab_list_type - { - ~symtab_list_type () - { - for (const char *elem: vec) - xfree ((void *) elem); - } - std::vector vec; - }; - char *regex = NULL; std::vector symbols; unsigned long count = 0; @@ -662,7 +687,6 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) unsigned int throttle = 0; static const char *keywords[] = {"regex","minsyms", "throttle", "symtabs", NULL}; - symtab_list_type symtab_paths; if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!IO", keywords, ®ex, &PyBool_Type, @@ -679,6 +703,12 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) minsyms_p = cmp; } + global_symbol_searcher spec (FUNCTIONS_DOMAIN, regex); + SCOPE_EXIT { + for (const char *elem : spec.filenames) + xfree ((void *) elem); + }; + /* The "symtabs" keyword is any Python iterable object that returns a gdb.Symtab on each iteration. If specified, iterate through the provided gdb.Symtabs and extract their full path. As @@ -724,20 +754,13 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) /* Make sure there is a definite place to store the value of filename before it is released. */ - symtab_paths.vec.push_back (nullptr); - symtab_paths.vec.back () = filename.release (); + spec.filenames.push_back (nullptr); + spec.filenames.back () = filename.release (); } } - if (symtab_list) - { - const char **files = symtab_paths.vec.data (); - - symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, - symtab_paths.vec.size (), files); - } - else - symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, 0, NULL); + /* The search spec. */ + symbols = spec.search (); /* Count the number of symbols (both symbols and optionally minimal symbols) so we can correctly check the throttle limit. */ @@ -786,10 +809,10 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) symbol_name = fullname; symbol_name += ":"; - symbol_name += SYMBOL_LINKAGE_NAME (p.symbol); + symbol_name += p.symbol->linkage_name (); } else - symbol_name = MSYMBOL_LINKAGE_NAME (p.msymbol.minsym); + symbol_name = p.msymbol.minsym->linkage_name (); gdbpy_ref<> argList (Py_BuildValue("(s)", symbol_name.c_str ())); gdbpy_ref<> obj (PyObject_CallObject ((PyObject *) @@ -821,6 +844,15 @@ gdbpy_decode_line (PyObject *self, PyObject *args) if (! PyArg_ParseTuple (args, "|s", &arg)) return NULL; + /* Treat a string consisting of just whitespace the same as + NULL. */ + if (arg != NULL) + { + arg = skip_spaces (arg); + if (*arg == '\0') + arg = NULL; + } + if (arg != NULL) location = string_to_event_location_basic (&arg, python_language, symbol_name_match_type::WILD); @@ -938,60 +970,54 @@ gdbpy_source_script (const struct extension_language_defn *extlang, /* A single event. */ struct gdbpy_event { - /* The Python event. This is just a callable object. */ - PyObject *event; - /* The next event. */ - struct gdbpy_event *next; -}; + gdbpy_event (gdbpy_ref<> &&func) + : m_func (func.release ()) + { + } -/* All pending events. */ -static struct gdbpy_event *gdbpy_event_list; -/* The final link of the event list. */ -static struct gdbpy_event **gdbpy_event_list_end; + gdbpy_event (gdbpy_event &&other) noexcept + : m_func (other.m_func) + { + other.m_func = nullptr; + } -/* So that we can wake up the main thread even when it is blocked in - poll(). */ -static struct serial_event *gdbpy_serial_event; + gdbpy_event (const gdbpy_event &other) + : m_func (other.m_func) + { + gdbpy_gil gil; + Py_XINCREF (m_func); + } -/* The file handler callback. This reads from the internal pipe, and - then processes the Python event queue. This will always be run in - the main gdb thread. */ + ~gdbpy_event () + { + gdbpy_gil gil; + Py_XDECREF (m_func); + } -static void -gdbpy_run_events (int error, gdb_client_data client_data) -{ - gdbpy_enter enter_py (get_current_arch (), current_language); + gdbpy_event &operator= (const gdbpy_event &other) = delete; - /* Clear the event fd. Do this before flushing the events list, so - that any new event post afterwards is sure to re-awake the event - loop. */ - serial_event_clear (gdbpy_serial_event); + void operator() () + { + gdbpy_enter enter_py (get_current_arch (), current_language); - while (gdbpy_event_list) - { - /* Dispatching the event might push a new element onto the event - loop, so we update here "atomically enough". */ - struct gdbpy_event *item = gdbpy_event_list; - gdbpy_event_list = gdbpy_event_list->next; - if (gdbpy_event_list == NULL) - gdbpy_event_list_end = &gdbpy_event_list; - - gdbpy_ref<> call_result (PyObject_CallObject (item->event, NULL)); - if (call_result == NULL) - gdbpy_print_stack (); + gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL)); + if (call_result == NULL) + gdbpy_print_stack (); + } - Py_DECREF (item->event); - xfree (item); - } -} +private: + + /* The Python event. This is just a callable object. Note that + this is not a gdbpy_ref<>, because we have to take particular + care to only destroy the reference when holding the GIL. */ + PyObject *m_func; +}; /* Submit an event to the gdb thread. */ static PyObject * gdbpy_post_event (PyObject *self, PyObject *args) { - struct gdbpy_event *event; PyObject *func; - int wakeup; if (!PyArg_ParseTuple (args, "O", &func)) return NULL; @@ -1003,38 +1029,13 @@ gdbpy_post_event (PyObject *self, PyObject *args) return NULL; } - Py_INCREF (func); - - /* From here until the end of the function, we have the GIL, so we - can operate on our global data structures without worrying. */ - wakeup = gdbpy_event_list == NULL; - - event = XNEW (struct gdbpy_event); - event->event = func; - event->next = NULL; - *gdbpy_event_list_end = event; - gdbpy_event_list_end = &event->next; - - /* Wake up gdb when needed. */ - if (wakeup) - serial_event_set (gdbpy_serial_event); + gdbpy_ref<> func_ref = gdbpy_ref<>::new_reference (func); + gdbpy_event event (std::move (func_ref)); + run_on_main_thread (event); Py_RETURN_NONE; } -/* Initialize the Python event handler. */ -static int -gdbpy_initialize_events (void) -{ - gdbpy_event_list_end = &gdbpy_event_list; - - gdbpy_serial_event = make_serial_event (); - add_file_handler (serial_event_fd (gdbpy_serial_event), - gdbpy_run_events, NULL); - - return 0; -} - /* This is the extension_language_ops.before_prompt "method". */ @@ -1113,6 +1114,74 @@ gdbpy_before_prompt_hook (const struct extension_language_defn *extlang, return EXT_LANG_RC_NOP; } +/* This is the extension_language_ops.colorize "method". */ + +static gdb::optional +gdbpy_colorize (const std::string &filename, const std::string &contents) +{ + if (!gdb_python_initialized) + return {}; + + gdbpy_enter enter_py (get_current_arch (), current_language); + + if (gdb_python_module == nullptr + || !PyObject_HasAttrString (gdb_python_module, "colorize")) + return {}; + + gdbpy_ref<> hook (PyObject_GetAttrString (gdb_python_module, "colorize")); + if (hook == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + if (!PyCallable_Check (hook.get ())) + return {}; + + gdbpy_ref<> fname_arg (PyString_FromString (filename.c_str ())); + if (fname_arg == nullptr) + { + gdbpy_print_stack (); + return {}; + } + gdbpy_ref<> contents_arg (PyString_FromString (contents.c_str ())); + if (contents_arg == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (), + fname_arg.get (), + contents_arg.get (), + nullptr)); + if (result == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + if (!gdbpy_is_string (result.get ())) + return {}; + + gdbpy_ref<> unic = python_string_to_unicode (result.get ()); + if (unic == nullptr) + { + gdbpy_print_stack (); + return {}; + } + gdbpy_ref<> host_str (PyUnicode_AsEncodedString (unic.get (), + host_charset (), + nullptr)); + if (host_str == nullptr) + { + gdbpy_print_stack (); + return {}; + } + + return std::string (PyBytes_AsString (host_str.get ())); +} + /* Printing. */ @@ -1135,20 +1204,20 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) try { switch (stream_type) - { - case 1: - { + { + case 1: + { fprintf_filtered (gdb_stderr, "%s", arg); break; - } - case 2: - { + } + case 2: + { fprintf_filtered (gdb_stdlog, "%s", arg); break; - } - default: - fprintf_filtered (gdb_stdout, "%s", arg); - } + } + default: + fprintf_filtered (gdb_stdout, "%s", arg); + } } catch (const gdb_exception &except) { @@ -1281,19 +1350,17 @@ gdbpy_print_stack_or_quit () static PyObject * gdbpy_progspaces (PyObject *unused1, PyObject *unused2) { - struct program_space *ps; - gdbpy_ref<> list (PyList_New (0)); if (list == NULL) return NULL; - ALL_PSPACES (ps) - { - gdbpy_ref<> item = pspace_to_pspace_object (ps); + for (struct program_space *ps : program_spaces) + { + gdbpy_ref<> item = pspace_to_pspace_object (ps); - if (item == NULL || PyList_Append (list.get (), item.get ()) == -1) - return NULL; - } + if (item == NULL || PyList_Append (list.get (), item.get ()) == -1) + return NULL; + } return list.release (); } @@ -1320,7 +1387,7 @@ gdbpy_source_objfile_script (const struct extension_language_defn *extlang, if (!gdb_python_initialized) return; - gdbpy_enter enter_py (get_objfile_arch (objfile), current_language); + gdbpy_enter enter_py (objfile->arch (), current_language); gdbpy_current_objfile = objfile; python_run_simple_file (file, filename); @@ -1342,7 +1409,7 @@ gdbpy_execute_objfile_script (const struct extension_language_defn *extlang, if (!gdb_python_initialized) return; - gdbpy_enter enter_py (get_objfile_arch (objfile), current_language); + gdbpy_enter enter_py (objfile->arch (), current_language); gdbpy_current_objfile = objfile; PyRun_SimpleString (script); @@ -1521,23 +1588,6 @@ python_command (const char *arg, int from_tty) static struct cmd_list_element *user_set_python_list; static struct cmd_list_element *user_show_python_list; -/* Function for use by 'set python' prefix command. */ - -static void -user_set_python (const char *args, int from_tty) -{ - help_list (user_set_python_list, "set python ", all_commands, - gdb_stdout); -} - -/* Function for use by 'show python' prefix command. */ - -static void -user_show_python (const char *args, int from_tty) -{ - cmd_show_list (user_show_python_list, from_tty, ""); -} - /* Initialize the Python code. */ #ifdef HAVE_PYTHON @@ -1566,13 +1616,28 @@ finalize_python (void *ignore) Py_Finalize (); + gdb_python_initialized = false; restore_active_ext_lang (previous_active); } #ifdef IS_PY3K +static struct PyModuleDef python_GdbModuleDef = +{ + PyModuleDef_HEAD_INIT, + "_gdb", + NULL, + -1, + python_GdbMethods, + NULL, + NULL, + NULL, + NULL +}; + /* This is called via the PyImport_AppendInittab mechanism called during initialization, to make the built-in _gdb module known to Python. */ +PyMODINIT_FUNC init__gdb_module (void); PyMODINIT_FUNC init__gdb_module (void) { @@ -1583,11 +1648,6 @@ init__gdb_module (void) static bool do_start_initialization () { -#ifdef IS_PY3K - size_t progsize, count; - wchar_t *progname_copy; -#endif - #ifdef WITH_PYTHON_PATH /* Work around problem where python gets confused about where it is, and then can't find its libraries, etc. @@ -1596,19 +1656,23 @@ do_start_initialization () /foo/lib/pythonX.Y/... This must be done before calling Py_Initialize. */ gdb::unique_xmalloc_ptr progname - (concat (ldirname (python_libdir).c_str (), SLASH_STRING, "bin", + (concat (ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin", SLASH_STRING, "python", (char *) NULL)); #ifdef IS_PY3K + /* Python documentation indicates that the memory given + to Py_SetProgramName cannot be freed. However, it seems that + at least Python 3.7.4 Py_SetProgramName takes a copy of the + given program_name. Making progname_copy static and not release + the memory avoids a leak report for Python versions that duplicate + program_name, and respect the requirement of Py_SetProgramName + for Python versions that do not duplicate program_name. */ + static wchar_t *progname_copy; + std::string oldloc = setlocale (LC_ALL, NULL); setlocale (LC_ALL, ""); - progsize = strlen (progname.get ()); - progname_copy = (wchar_t *) xmalloc ((progsize + 1) * sizeof (wchar_t)); - if (!progname_copy) - { - fprintf (stderr, "out of memory\n"); - return false; - } - count = mbstowcs (progname_copy, progname.get (), progsize + 1); + size_t progsize = strlen (progname.get ()); + progname_copy = XNEWVEC (wchar_t, progsize + 1); + size_t count = mbstowcs (progname_copy, progname.get (), progsize + 1); if (count == (size_t) -1) { fprintf (stderr, "Could not convert python path to string\n"); @@ -1629,7 +1693,12 @@ do_start_initialization () #endif Py_Initialize (); +#if PY_VERSION_HEX < 0x03090000 + /* PyEval_InitThreads became deprecated in Python 3.9 and will + be removed in Python 3.11. Prior to Python 3.7, this call was + required to initialize the GIL. */ PyEval_InitThreads (); +#endif #ifdef IS_PY3K gdb_module = PyImport_ImportModule ("_gdb"); @@ -1692,13 +1761,14 @@ do_start_initialization () || gdbpy_initialize_linetable () < 0 || gdbpy_initialize_thread () < 0 || gdbpy_initialize_inferior () < 0 - || gdbpy_initialize_events () < 0 || gdbpy_initialize_eventregistry () < 0 || gdbpy_initialize_py_events () < 0 || gdbpy_initialize_event () < 0 || gdbpy_initialize_arch () < 0 + || gdbpy_initialize_registers () < 0 || gdbpy_initialize_xmethods () < 0 - || gdbpy_initialize_unwind () < 0) + || gdbpy_initialize_unwind () < 0 + || gdbpy_initialize_tui () < 0) return false; #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ @@ -1727,8 +1797,7 @@ do_start_initialization () return false; /* Release the GIL while gdb runs. */ - PyThreadState_Swap (NULL); - PyEval_ReleaseLock (); + PyEval_SaveThread (); make_final_cleanup (finalize_python, NULL); @@ -1742,8 +1811,9 @@ do_start_initialization () /* See python.h. */ cmd_list_element *python_cmd_element = nullptr; +void _initialize_python (); void -_initialize_python (void) +_initialize_python () { add_com ("python-interactive", class_obscure, python_interactive_command, @@ -1793,15 +1863,15 @@ This command is only a placeholder.") add_com_alias ("py", "python", class_obscure, 1); /* Add set/show python print-stack. */ - add_prefix_cmd ("python", no_class, user_show_python, - _("Prefix command for python preference settings."), - &user_show_python_list, "show python ", 0, - &showlist); + add_basic_prefix_cmd ("python", no_class, + _("Prefix command for python preference settings."), + &user_show_python_list, "show python ", 0, + &showlist); - add_prefix_cmd ("python", no_class, user_set_python, - _("Prefix command for python preference settings."), - &user_set_python_list, "set python ", 0, - &setlist); + add_show_prefix_cmd ("python", no_class, + _("Prefix command for python preference settings."), + &user_set_python_list, "set python ", 0, + &setlist); add_setshow_enum_cmd ("print-stack", no_class, python_excp_enums, &gdbpy_should_print_stack, _("\ @@ -1912,12 +1982,6 @@ gdbpy_initialized (const struct extension_language_defn *extlang) return gdb_python_initialized; } -#endif /* HAVE_PYTHON */ - - - -#ifdef HAVE_PYTHON - PyMethodDef python_GdbMethods[] = { { "history", gdbpy_history, METH_VARARGS, @@ -1978,6 +2042,14 @@ a boolean indicating if name is a field of the current implied argument\n\ METH_VARARGS | METH_KEYWORDS, "lookup_global_symbol (name [, domain]) -> symbol\n\ Return the symbol corresponding to the given name (or None)." }, + { "lookup_static_symbol", (PyCFunction) gdbpy_lookup_static_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_static_symbol (name [, domain]) -> symbol\n\ +Return the static-linkage symbol corresponding to the given name (or None)." }, + { "lookup_static_symbols", (PyCFunction) gdbpy_lookup_static_symbols, + METH_VARARGS | METH_KEYWORDS, + "lookup_static_symbols (name [, domain]) -> symbol\n\ +Return a list of all static-linkage symbols corresponding to the given name." }, { "lookup_objfile", (PyCFunction) gdbpy_lookup_objfile, METH_VARARGS | METH_KEYWORDS, @@ -2042,28 +2114,20 @@ or None if not set." }, "convenience_variable (NAME, VALUE) -> None.\n\ Set the value of the convenience variable $NAME." }, - {NULL, NULL, 0, NULL} -}; +#ifdef TUI + { "register_window_type", (PyCFunction) gdbpy_register_tui_window, + METH_VARARGS | METH_KEYWORDS, + "register_window_type (NAME, CONSTRUCSTOR) -> None\n\ +Register a TUI window constructor." }, +#endif /* TUI */ -#ifdef IS_PY3K -struct PyModuleDef python_GdbModuleDef = -{ - PyModuleDef_HEAD_INIT, - "_gdb", - NULL, - -1, - python_GdbMethods, - NULL, - NULL, - NULL, - NULL + {NULL, NULL, 0, NULL} }; -#endif /* Define all the event objects. */ #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ PyTypeObject name##_event_object_type \ - CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object") \ + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object") \ = { \ PyVarObject_HEAD_INIT (NULL, 0) \ "gdb." py_name, /* tp_name */ \