bpo-36142: Rework error reporting in pymain_main() (GH-12113)

Add a new _Py_INIT_EXIT() macro to be able to exit Python with an
exitcode using _PyInitError API. Rewrite function calls by
pymain_main() to use _PyInitError.

Changes:

* Remove _PyMain.err and _PyMain.status field
* Add _Py_INIT_EXIT() macro and _PyInitError.exitcode field.
* Rename _Py_FatalInitError() to _Py_ExitInitError().
diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h
index f7ac3f9..2ce99b2 100644
--- a/Include/cpython/coreconfig.h
+++ b/Include/cpython/coreconfig.h
@@ -11,6 +11,7 @@
     const char *prefix;
     const char *msg;
     int user_err;
+    int exitcode;
 } _PyInitError;
 
 /* Almost all errors causing Python initialization to fail */
@@ -22,16 +23,18 @@
 #endif
 
 #define _Py_INIT_OK() \
-    (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0}
+    (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = -1}
 #define _Py_INIT_ERR(MSG) \
-    (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0}
+    (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0, .exitcode = -1}
 /* Error that can be fixed by the user like invalid input parameter.
    Don't abort() the process on such error. */
 #define _Py_INIT_USER_ERR(MSG) \
-    (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1}
+    (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1, .exitcode = -1}
 #define _Py_INIT_NO_MEMORY() _Py_INIT_USER_ERR("memory allocation failed")
+#define _Py_INIT_EXIT(EXITCODE) \
+    (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = (EXITCODE)}
 #define _Py_INIT_FAILED(err) \
-    (err.msg != NULL)
+    (err.msg != NULL || err.exitcode != -1)
 
 /* _PyCoreConfig */
 
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index a3fdeef..3bffc80 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -39,7 +39,7 @@
 
 PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig(
     const _PyCoreConfig *config);
-PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalInitError(_PyInitError err);
+PyAPI_FUNC(void) _Py_NO_RETURN _Py_ExitInitError(_PyInitError err);
 
 /* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
  * exit functions.