text: //     Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com
  //
  //     Part of "Nuitka", an optimizing Python compiler that is compatible and
  //     integrates with CPython, but also works on its own.
  //
  //     Licensed under the Apache License, Version 2.0 (the "License");
  //     you may not use this file except in compliance with the License.
  //     You may obtain a copy of the License at
  //
  //        http://www.apache.org/licenses/LICENSE-2.0
  //
  //     Unless required by applicable law or agreed to in writing, software
  //     distributed under the License is distributed on an "AS IS" BASIS,
  //     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  //     See the License for the specific language governing permissions and
  //     limitations under the License.
  //
  /* The main program for a compiled program.
   *
   * It needs to prepare the interpreter and then loads and executes
   * the "__main__" module.
   *
   */
  
  #if defined(_WIN32)
  #include <windows.h>
  #endif
  
  #include "nuitka/prelude.h"
  
  #ifndef __IDE_ONLY__
  // Generated during build with optional defines.
  #include "build_definitions.h"
  #else
  // For the IDE to know these exist.
  #define SYSFLAG_PY3K_WARNING 0
  #define SYSFLAG_DIVISION_WARNING 0
  #define SYSFLAG_UNICODE 0
  #define SYSFLAG_OPTIMIZE 0
  #define SYSFLAG_NO_SITE 0
  #define SYSFLAG_VERBOSE 0
  #define SYSFLAG_BYTES_WARNING 0
  #define SYSFLAG_UTF8 0
  #endif
  
  #include <osdefs.h>
  #include <structseq.h>
  
  extern PyCodeObject *codeobj_main;
  
  /* For later use in "Py_GetArgcArgv" */
  static char **orig_argv;
  static int orig_argc;
  #if PYTHON_VERSION >= 0x300
  static wchar_t **argv_unicode;
  #endif
  
  #ifdef _NUITKA_STANDALONE
  
  #if _NUITKA_FROZEN > 0
  extern void copyFrozenModulesTo(struct _frozen *destination);
  
  // The original frozen modules list.
  #if PYTHON_VERSION < 0x340
  static struct _frozen *old_frozen = NULL;
  #else
  static struct _frozen const *old_frozen = NULL;
  #endif
  #endif
  
  static void prepareStandaloneEnvironment() {
      // Tell the CPython library to use our pre-compiled modules as frozen
      // modules. This for those modules/packages like "encoding" that will be
      // loaded during "Py_Initialize" already, for the others they may be
      // compiled.
  
  #if _NUITKA_FROZEN > 0
      // The CPython library has some pre-existing frozen modules, we only append
      // to that.
      struct _frozen const *search = PyImport_FrozenModules;
      while (search->name) {
          search++;
      }
      int pre_existing_count = (int)(search - PyImport_FrozenModules);
  
      /* Allocate new memory and merge the tables. Keeping the old ones has
       * the advantage that e.g. "import this" is going to work well.
       */
      struct _frozen *merged =
          (struct _frozen *)malloc(sizeof(struct _frozen) * (_NUITKA_FROZEN + pre_existing_count + 1));
  
      memcpy(merged, PyImport_FrozenModules, pre_existing_count * sizeof(struct _frozen));
      copyFrozenModulesTo(merged + pre_existing_count);
      old_frozen = PyImport_FrozenModules;
      PyImport_FrozenModules = merged;
  #endif
  
      /* Setup environment variables to tell CPython that we would like it to use
       * the provided binary directory as the place to look for DLLs and for
       * extension modules.
       */
  #if defined(_WIN32)
      SetDllDirectoryW(getBinaryDirectoryWideChars());
  #endif
  
  #if PYTHON_VERSION < 0x300
      char *binary_directory = (char *)getBinaryDirectoryHostEncoded();
      NUITKA_PRINTF_TRACE("main(): Binary dir is %s\n", binary_directory);
  
      Py_SetPythonHome(binary_directory);
  #else
      wchar_t *binary_directory = (wchar_t *)getBinaryDirectoryWideChars();
      NUITKA_PRINTF_TRACE("main(): Binary dir is %S\n", binary_directory);
  
      Py_SetPythonHome(binary_directory);
  
  #endif
  }
  
  static void restoreStandaloneEnvironment() {
      /* Make sure to use the optimal value for standalone mode only. */
  #if PYTHON_VERSION < 0x300
      PySys_SetPath((char *)getBinaryDirectoryHostEncoded());
      // NUITKA_PRINTF_TRACE("Final PySys_GetPath is 's'.\n", PySys_GetPath());
  #else
      PySys_SetPath(getBinaryDirectoryWideChars());
      Py_SetPath(getBinaryDirectoryWideChars());
      NUITKA_PRINTF_TRACE("Final Py_GetPath is '%ls'.\n", Py_GetPath());
  #endif
  }
  
  #endif
  
  extern void _initCompiledCellType();
  extern void _initCompiledGeneratorType();
  extern void _initCompiledFunctionType();
  extern void _initCompiledMethodType();
  extern void _initCompiledFrameType();
  
  #include <locale.h>
  
  // Types of command line arguments are different between Python2/3.
  #if PYTHON_VERSION >= 0x300
  typedef wchar_t **argv_type_t;
  static argv_type_t convertCommandLineParameters(int argc, char **argv) {
  #if _WIN32
      int new_argc;
  
      argv_type_t result = CommandLineToArgvW(GetCommandLineW(), &new_argc);
      assert(new_argc == argc);
      return result;
  #else
      // Originally taken from CPython3: There seems to be no sane way to use
      static wchar_t **argv_copy;
      argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t *) * argc);
  
      // Temporarily disable locale for conversions to not use it.
      char *oldloc = strdup(setlocale(LC_ALL, NULL));
      setlocale(LC_ALL, "");
  
      for (int i = 0; i < argc; i++) {
  #if PYTHON_VERSION >= 0x350
          argv_copy[i] = Py_DecodeLocale(argv[i], NULL);
  #elif defined(__APPLE__) && PYTHON_VERSION >= 0x320
          argv_copy[i] = _Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i]));
  #else
          argv_copy[i] = _Py_char2wchar(argv[i], NULL);
  #endif
  
          assert(argv_copy[i]);
      }
  
      setlocale(LC_ALL, oldloc);
      free(oldloc);
  
      return argv_copy;
  #endif
  }
  #else
  typedef char **argv_type_t;
  #endif
  
  #ifdef _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED
  extern void SvcInstall();
  extern void SvcLaunchService();
  
  // Callback from Windows Service logic.
  DWORD WINAPI SvcStartPython(LPVOID lpParam) {
      if (lpParam == NULL) {
          IMPORT_EMBEDDED_MODULE("__main__");
  
          // TODO: Log exception and call ReportSvcStatus
          if (ERROR_OCCURRED()) {
              return 1;
          } else {
              return 0;
          }
      } else {
          PyErr_SetInterrupt();
          return 0;
      }
  }
  #endif
  
  // This is a multiprocessing fork
  static bool is_multiprocessing_fork = false;
  // This is a multiprocessing resource tracker.
  static PyObject *multiprocessing_resource_tracker_arg = NULL;
  
  // Platform compat
  #if !defined(_WIN32) && PYTHON_VERSION >= 0x300
  static long _wtoi(const wchar_t *value) { return wcstol(value, 0, 10); }
  #endif
  
  // Parse the command line parameters and provide it to "sys" built-in module,
  // as well as decide if it's a multiprocessing usage.
  static void setCommandLineParameters(int argc, argv_type_t argv, bool initial) {
      if (initial) {
          /* We might need to handle special parameters from plugins that are
             very deeply woven into command line handling. These are right now
             multiprocessing, which indicates that it's forking via extra
             command line argument. And Windows Service indicates need to
             install and exit here too.
           */
          for (int i = 1; i < argc; i++) {
  #if PYTHON_VERSION < 0x300
              if ((strcmp(argv[i], "--multiprocessing-fork")) == 0 && (i + 1 < argc))
  #else
              if ((wcscmp(argv[i], L"--multiprocessing-fork")) == 0 && (i + 1 < argc))
  #endif
              {
                  is_multiprocessing_fork = true;
                  break;
              }
  
  #if PYTHON_VERSION < 0x300
              if ((strcmp(argv[i], "--multiprocessing-resource-tracker")) == 0 && (i + 1 < argc))
  #else
              if ((wcscmp(argv[i], L"--multiprocessing-resource-tracker")) == 0 && (i + 1 < argc))
  #endif
              {
  #if PYTHON_VERSION < 0x300
                  multiprocessing_resource_tracker_arg = PyInt_FromLong(atoi(argv[i + 1]));
  #else
                  multiprocessing_resource_tracker_arg = PyLong_FromLong(_wtoi(argv[i + 1]));
  #endif
                  break;
              }
  
  #ifdef _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED
              if (i == 1) {
  #if PYTHON_VERSION < 0x300
                  if (strcmp(argv[i], "install") == 0)
  #else
                  if (wcscmp(argv[i], L"install") == 0)
  #endif
                  {
                      NUITKA_PRINT_TRACE("main(): Calling plugin SvcInstall().");
  
                      SvcInstall();
                      NUITKA_CANNOT_GET_HERE("SvcInstall must not return");
                  }
              }
  #endif
          }
      }
  
      if (initial) {
          // Py_SetProgramName(argv[0]);
      } else {
          PySys_SetArgv(argc, argv);
      }
  }
  
  #if defined(_WIN32) && PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1
  static void setenv(char const *name, char const *value, int overwrite) {
      assert(overwrite);
  
      SetEnvironmentVariableA(name, value);
  }
  
  static void unsetenv(char const *name) { SetEnvironmentVariableA(name, NULL); }
  #endif
  
  #if _DEBUG_REFCOUNTS
  static void PRINT_REFCOUNTS() {
      PRINT_STRING("REFERENCE counts at program end:\n");
      PRINT_STRING("active | allocated | released\n");
      PRINT_FORMAT("Compiled Coroutines: %d | %d | %d\n", count_active_Nuitka_Coroutine_Type,
                   count_allocated_Nuitka_Coroutine_Type, count_released_Nuitka_Coroutine_Type);
      PRINT_FORMAT("Compiled Coroutines Wrappers: %d | %d | %d\n", count_active_Nuitka_CoroutineWrapper_Type,
                   count_allocated_Nuitka_CoroutineWrapper_Type, count_released_Nuitka_CoroutineWrapper_Type);
  
      PRINT_FORMAT("Compiled Coroutines AIter Wrappers: %d | %d | %d\n", count_active_Nuitka_AIterWrapper_Type,
                   count_allocated_Nuitka_AIterWrapper_Type, count_released_Nuitka_AIterWrapper_Type);
  #if PYTHON_VERSION >= 0x360
      PRINT_FORMAT("Compiled Asyncgen: %d | %d | %d\n", count_active_Nuitka_Asyncgen_Type,
                   count_allocated_Nuitka_Asyncgen_Type, count_released_Nuitka_Asyncgen_Type);
      PRINT_FORMAT("Compiled Asyncgen Wrappers: %d | %d | %d\n", count_active_Nuitka_AsyncgenValueWrapper_Type,
                   count_allocated_Nuitka_AsyncgenValueWrapper_Type, count_released_Nuitka_AsyncgenValueWrapper_Type);
      PRINT_FORMAT("Compiled Asyncgen Asend: %d | %d | %d\n", count_active_Nuitka_AsyncgenAsend_Type,
                   count_allocated_Nuitka_AsyncgenAsend_Type, count_released_Nuitka_AsyncgenAsend_Type);
      PRINT_FORMAT("Compiled Asyncgen Athrow: %d | %d | %d\n", count_active_Nuitka_AsyncgenAthrow_Type,
                   count_allocated_Nuitka_AsyncgenAthrow_Type, count_released_Nuitka_AsyncgenAthrow_Type);
  #endif
  
      PRINT_FORMAT("Compiled Frames: %d | %d | %d (cache usage may occur)\n", count_active_Nuitka_Frame_Type,
                   count_allocated_Nuitka_Frame_Type, count_released_Nuitka_Frame_Type);
      PRINT_STRING("CACHED counts at program end:\n");
      PRINT_STRING("active | allocated | released | hits\n");
      PRINT_FORMAT("Cached Frames: %d | %d | %d | %d\n", count_active_frame_cache_instances,
                   count_allocated_frame_cache_instances, count_released_frame_cache_instances,
                   count_hit_frame_cache_instances);
  }
  #endif
  
  // Small helper to open files with few arguments.
  static PyObject *BUILTIN_OPEN_SIMPLE(PyObject *filename, char const *mode, PyObject *buffering) {
  #if PYTHON_VERSION < 0x300
      return BUILTIN_OPEN(filename, Nuitka_String_FromString(mode), buffering);
  #else
      return BUILTIN_OPEN(filename, Nuitka_String_FromString(mode), buffering, NULL, NULL, NULL, NULL, NULL);
  #endif
  }
  
  #if defined(_NUITKA_ONEFILE) && defined(_WIN32)
  
  static long onefile_ppid;
  
  DWORD WINAPI doOnefileParentMonitoring(LPVOID lpParam) {
      for (;;) {
          Sleep(1000);
  
          HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, onefile_ppid);
  
          if (handle == NULL) {
              if (GetLastError() == ERROR_INVALID_PARAMETER) {
                  break;
              } else {
                  continue;
              }
          } else {
              DWORD ret = WaitForSingleObject(handle, 0);
  
              CloseHandle(handle);
  
              if (ret == WAIT_OBJECT_0) {
                  break;
              }
          }
      }
  
      // puts("Onefile parent monitoring kicks in.");
  
      PyErr_SetInterrupt();
  
      return 0;
  }
  #endif
  
  static int HANDLE_PROGRAM_EXIT() {
      int exit_code;
  
      if (ERROR_OCCURRED()) {
  #if PYTHON_VERSION >= 0x300
          /* Remove the frozen importlib traceback part, which would not be compatible. */
          PyThreadState *thread_state = PyThreadState_GET();
  
          while (thread_state->curexc_traceback) {
              PyTracebackObject *tb = (PyTracebackObject *)thread_state->curexc_traceback;
              PyFrameObject *frame = tb->tb_frame;
  
              if (0 == strcmp(PyUnicode_AsUTF8(frame->f_code->co_filename), "<frozen importlib._bootstrap>")) {
                  thread_state->curexc_traceback = (PyObject *)tb->tb_next;
                  Py_INCREF(tb->tb_next);
  
                  continue;
              }
  
              break;
          }
  #endif
  
          PyErr_PrintEx(0);
  
          exit_code = 1;
      } else {
          exit_code = 0;
      }
  
      return exit_code;
  }
  
  #ifdef _NUITKA_WINMAIN_ENTRY_POINT
  int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpCmdLine, int nCmdShow) {
  #if defined(__MINGW32__) && !defined(_W64)
      /* MINGW32 */
      int argc = _argc;
      char **argv = _argv;
  #else
      /* MSVC, MINGW64 */
      int argc = __argc;
      char **argv = __argv;
  #endif
  #else
  int main(int argc, char **argv) {
  #endif
      NUITKA_PRINT_TIMING("main(): Entered.");
  
      orig_argv = argv;
      orig_argc = argc;
  
  #ifdef __FreeBSD__
      /* 754 requires that FP exceptions run in "no stop" mode by default, and
       *
       *    until C vendors implement C99's ways to control FP exceptions, Python
       *    requires non-stop mode.  Alas, some platforms enable FP exceptions by
       *    default.  Here we disable them.
       */
  
      fp_except_t m;
  
      m = fpgetmask();
      fpsetmask(m & ~FP_X_OFL);
  #endif
  
  #ifdef _NUITKA_STANDALONE
      NUITKA_PRINT_TIMING("main(): Prepare standalone environment.");
      prepareStandaloneEnvironment();
  #else
  
  #if PYTHON_VERSION >= 0x350 && defined(DLL_EXTRA_PATH)
      NUITKA_PRINT_TIMING("main(): Prepare DLL extra path.");
      SetDllDirectory(DLL_EXTRA_PATH);
  #endif
  
  #endif
  
      /* Initialize CPython library environment. */
      Py_DebugFlag = 0;
  #if PYTHON_VERSION < 0x300
      Py_Py3kWarningFlag = SYSFLAG_PY3K_WARNING;
      Py_DivisionWarningFlag = SYSFLAG_DIVISION_WARNING;
      Py_UnicodeFlag = SYSFLAG_UNICODE;
      Py_TabcheckFlag = 0;
  #endif
      Py_InspectFlag = 0;
      Py_InteractiveFlag = 0;
      Py_OptimizeFlag = SYSFLAG_OPTIMIZE;
      Py_DontWriteBytecodeFlag = 0;
      Py_NoUserSiteDirectory = SYSFLAG_NO_SITE;
      Py_IgnoreEnvironmentFlag = 0;
      Py_VerboseFlag = SYSFLAG_VERBOSE;
      Py_BytesWarningFlag = SYSFLAG_BYTES_WARNING;
  #if SYSFLAG_NO_RANDOMIZATION == 1
      Py_HashRandomizationFlag = 0;
  #if PYTHON_VERSION < 0x300
      // For Python2 this is all it takes to have static hashes.
      _PyRandom_Init();
  #endif
  #endif
  #if PYTHON_VERSION >= 0x370
      Py_UTF8Mode = SYSFLAG_UTF8;
  #endif
  
  #ifdef NUITKA_PYTHON_STATIC
      Py_InitStaticModules();
  #endif
  
      /* This suppresses warnings from getpath.c */
      Py_FrozenFlag = 1;
  
      /* We want to import the site module, but only after we finished our own
       * setup. The site module import will be the first thing, the main module
       * does.
       */
      Py_NoSiteFlag = 1;
  
      /* Initial command line handling only. */
  
  #if PYTHON_VERSION >= 0x300
      NUITKA_PRINT_TRACE("main(): Calling convertCommandLineParameters.");
      argv_unicode = convertCommandLineParameters(argc, argv);
  #endif
  
      NUITKA_PRINT_TRACE("main(): Calling setCommandLineParameters.");
  
  #if PYTHON_VERSION < 0x300
      setCommandLineParameters(argc, argv, true);
  #else
      setCommandLineParameters(argc, argv_unicode, true);
  #endif
  
      /* For Python installations that need the home set, we inject it back here. */
  #if defined(PYTHON_HOME_PATH)
  #if PYTHON_VERSION < 0x300
      NUITKA_PRINT_TRACE("main(): Prepare run environment '" PYTHON_HOME_PATH "'.");
      Py_SetPythonHome(PYTHON_HOME_PATH);
  #else
      NUITKA_PRINTF_TRACE("main(): Prepare run environment '%S'.\n", L"" PYTHON_HOME_PATH);
      Py_SetPythonHome(L"" PYTHON_HOME_PATH);
      // Make sure the above Py_SetPythonHome call has effect already.
      Py_GetPath();
  #endif
  #endif
  
  #if PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1
      char const *old_env = getenv("PYTHONHASHSEED");
      setenv("PYTHONHASHSEED", "0", 1);
  #endif
  
      /* Disable CPython warnings if requested to. */
  #if NO_PYTHON_WARNINGS
      {
  #if PYTHON_VERSION >= 0x300
          wchar_t ignore[] = L"ignore";
  #else
          char ignore[] = "ignore";
  #endif
  
          PySys_ResetWarnOptions();
          PySys_AddWarnOption(ignore);
      }
  #endif
  
      /* Initialize the embedded CPython interpreter. */
      NUITKA_PRINT_TIMING("main(): Calling Py_Initialize to initialize interpreter.");
      Py_Initialize();
  
  #if PYTHON_VERSION >= 0x300 && SYSFLAG_NO_RANDOMIZATION == 1
      if (old_env) {
          setenv("PYTHONHASHSEED", old_env, 1);
  
          PyObject *env_value = PyUnicode_FromString(old_env);
          PyObject *hashseed_str = PyUnicode_FromString("PYTHONHASHSEED");
  
          int res =
              PyObject_SetItem(PyObject_GetAttrString(PyImport_ImportModule("os"), "environ"), hashseed_str, env_value);
          assert(res == 0);
  
          Py_DECREF(env_value);
          Py_DECREF(hashseed_str);
      } else {
          unsetenv("PYTHONHASHSEED");
  
          int res =
              PyObject_DelItemString(PyObject_GetAttrString(PyImport_ImportModule("os"), "environ"), "PYTHONHASHSEED");
          assert(res == 0);
      }
  #endif
  
  #ifdef _NUITKA_STANDALONE
      NUITKA_PRINT_TRACE("main(): Restore standalone environment.");
      restoreStandaloneEnvironment();
  #endif
  
      /* Lie about it, believe it or not, there are "site" files, that check
       * against later imports, see below.
       */
      Py_NoSiteFlag = SYSFLAG_NO_SITE;
  
      /* Set the command line parameters for run time usage. */
      NUITKA_PRINT_TRACE("main(): Calling setCommandLineParameters.");
  
  #if PYTHON_VERSION < 0x300
      setCommandLineParameters(argc, argv, false);
  #else
      setCommandLineParameters(argc, argv_unicode, false);
  #endif
  
      /* Initialize the built-in module tricks used. */
      NUITKA_PRINT_TRACE("main(): Calling _initBuiltinModule().");
      _initBuiltinModule();
  
      /* Initialize the Python constant values used. This also sets
       * "sys.executable" while at it.
       */
      NUITKA_PRINT_TIMING("main(): Calling createGlobalConstants().");
      createGlobalConstants();
      NUITKA_PRINT_TIMING("main(): Returned createGlobalConstants().");
  
      /* Complex call helpers need "__main__" constants, even if we only
       * go into "__parents__main__" module as a start point.
       */
  #if _NUITKA_PLUGIN_MULTIPROCESSING_ENABLED || _NUITKA_PLUGIN_TRACEBACK_ENCRYPTION_ENABLED
      NUITKA_PRINT_TIMING("main(): Calling createMainModuleConstants().");
      createMainModuleConstants();
      NUITKA_PRINT_TIMING("main(): Returned createMainModuleConstants().");
  #endif
  
      NUITKA_PRINT_TRACE("main(): Calling _initBuiltinOriginalValues().");
      _initBuiltinOriginalValues();
  
      /* Revert the wrong "sys.flags" value, it's used by "site" on at least
       * Debian for Python 3.3, more uses may exist.
       */
  #if SYSFLAG_NO_SITE == 0
  #if PYTHON_VERSION < 0x300
      PyStructSequence_SET_ITEM(PySys_GetObject((char *)"flags"), 9, const_int_0);
  #else
      PyStructSequence_SetItem(PySys_GetObject("flags"), 6, const_int_0);
  #endif
  #endif
  
      /* Initialize the compiled types of Nuitka. */
      _initCompiledCellType();
      _initCompiledGeneratorType();
      _initCompiledFunctionType();
      _initCompiledMethodType();
      _initCompiledFrameType();
  
      _initSlotCompare();
  #if PYTHON_VERSION >= 0x270
      _initSlotIternext();
  #endif
  
      NUITKA_PRINT_TRACE("main(): Calling enhancePythonTypes().");
      enhancePythonTypes();
  
      NUITKA_PRINT_TRACE("main(): Calling patchBuiltinModule().");
      patchBuiltinModule();
  
      NUITKA_PRINT_TRACE("main(): Calling patchTypeComparison().");
      patchTypeComparison();
  
      NUITKA_PRINT_TRACE("main(): Calling patchTracebackDealloc().");
      patchTracebackDealloc();
  
  #ifndef NUITKA_USE_PYCORE_THREADSTATE
      /* Allow to override the ticker value, to remove checks for threads in
       * CPython core from impact on benchmarks. */
      char const *ticker_value = getenv("NUITKA_TICKER");
      if (ticker_value != NULL) {
          _Py_Ticker = atoi(ticker_value);
          assert(_Py_Ticker >= 20);
      }
  #endif
  
      /* At least on Windows, we support disabling the console via linker flag, but now
         need to provide the NUL standard file handles manually in this case. */
      {
          PyObject *nul_filename = Nuitka_String_FromString("NUL:");
  
          if (PySys_GetObject((char *)"stdin") == NULL) {
              PyObject *stdin_file = BUILTIN_OPEN_SIMPLE(nul_filename, "r", NULL);
  
              CHECK_OBJECT(stdin_file);
              PySys_SetObject((char *)"stdin", stdin_file);
          }
  
          if (PySys_GetObject((char *)"stdout") == NULL) {
              PyObject *stdout_file = BUILTIN_OPEN_SIMPLE(nul_filename, "w", NULL);
  
              CHECK_OBJECT(stdout_file);
              PySys_SetObject((char *)"stdout", stdout_file);
          }
  
          if (PySys_GetObject((char *)"stderr") == NULL) {
              PyObject *stderr_file = BUILTIN_OPEN_SIMPLE(nul_filename, "w", NULL);
  
              CHECK_OBJECT(stderr_file);
  
              PySys_SetObject((char *)"stderr", stderr_file);
          }
  
          Py_DECREF(nul_filename);
      }
  
  #if defined(NUITKA_FORCED_STDOUT_PATH)
      {
          wchar_t filename_buffer[1024];
          wchar_t const *pattern = L"" NUITKA_FORCED_STDOUT_PATH;
  
          bool res = expandTemplatePathW(filename_buffer, pattern, sizeof(filename_buffer) / sizeof(wchar_t));
  
          if (res == false) {
              puts("Error, couldn't expand pattern:");
              _putws(pattern);
              abort();
          }
  
          PyObject *filename = PyUnicode_FromWideChar(filename_buffer, wcslen(filename_buffer));
  
          PyObject *stdout_file = BUILTIN_OPEN_SIMPLE(filename, "w", const_int_pos_1);
          if (unlikely(stdout_file == NULL)) {
              PyErr_PrintEx(1);
              Py_Exit(1);
          }
  
          PySys_SetObject((char *)"stdout", stdout_file);
      }
  #endif
  
  #if defined(NUITKA_FORCED_STDERR_PATH)
      {
          wchar_t filename_buffer[1024];
          wchar_t const *pattern = L"" NUITKA_FORCED_STDERR_PATH;
  
          bool res = expandTemplatePathW(filename_buffer, pattern, sizeof(filename_buffer) / sizeof(wchar_t));
  
          if (res == false) {
              puts("Error, couldn't expand pattern:");
              _putws(pattern);
              abort();
          }
  
          PyObject *filename = PyUnicode_FromWideChar(filename_buffer, wcslen(filename_buffer));
  
          PyObject *stderr_file = BUILTIN_OPEN_SIMPLE(filename, "w", const_int_pos_1);
          if (unlikely(stderr_file == NULL)) {
              PyErr_PrintEx(1);
              Py_Exit(1);
          }
  
          PySys_SetObject((char *)"stderr", stderr_file);
      }
  #endif
  
  #ifdef _NUITKA_STANDALONE
      NUITKA_PRINT_TRACE("main(): Calling setEarlyFrozenModulesFileAttribute().");
  
      setEarlyFrozenModulesFileAttribute();
  #endif
  
  #if _NUITKA_FROZEN > 0
      NUITKA_PRINT_TRACE("main(): Removing early frozen module table again.");
      PyImport_FrozenModules = old_frozen;
      assert(old_frozen != NULL);
  #endif
  
      NUITKA_PRINT_TRACE("main(): Calling setupMetaPathBasedLoader().");
      /* Enable meta path based loader. */
      setupMetaPathBasedLoader();
  
      /* Initialize warnings module. */
      _PyWarnings_Init();
  
  #if NO_PYTHON_WARNINGS && PYTHON_VERSION >= 0x342 && defined(_NUITKA_FULL_COMPAT)
      // For full compatibility bump the warnings registry version,
      // otherwise modules "__warningsregistry__" will mismatch.
      PyObject *warnings_module = PyImport_ImportModule("warnings");
      PyObject *meth = PyObject_GetAttrString(warnings_module, "_filters_mutated");
  
      CALL_FUNCTION_NO_ARGS(meth);
  #if PYTHON_VERSION < 0x380
      // Two times, so "__warningregistry__" version matches.
      CALL_FUNCTION_NO_ARGS(meth);
  #endif
  #endif
  
  #if PYTHON_VERSION >= 0x300
      NUITKA_PRINT_TRACE("main(): Calling patchInspectModule().");
      patchInspectModule();
  #endif
  
  #if _NUITKA_PROFILE
      startProfiling();
  #endif
  
      /* Execute the main module unless plugins want to do something else. In case of
         multiprocessing making a fork on Windows, we should execute "__parents_main__"
         instead. And for Windows Service we call the plugin C code to call us back
         to launch main code in a callback. */
  #ifdef _NUITKA_PLUGIN_MULTIPROCESSING_ENABLED
      if (unlikely(is_multiprocessing_fork)) {
          NUITKA_PRINT_TRACE("main(): Calling __parents_main__.");
          IMPORT_EMBEDDED_MODULE("__parents_main__");
  
          int exit_code = HANDLE_PROGRAM_EXIT();
  
          NUITKA_PRINT_TRACE("main(): Calling __parents_main__ Py_Exit.");
  
          // TODO: Should maybe call Py_Exit here, but there were issues with that.
          exit(exit_code);
      } else if (unlikely(multiprocessing_resource_tracker_arg != NULL)) {
          NUITKA_PRINT_TRACE("main(): Calling resource_tracker.");
          PyObject *resource_tracker_module = IMPORT_EMBEDDED_MODULE("multiprocessing.resource_tracker");
  
          PyObject *main_function = PyObject_GetAttrString(resource_tracker_module, "main");
  
          CALL_FUNCTION_WITH_SINGLE_ARG(main_function, multiprocessing_resource_tracker_arg);
  
          int exit_code = HANDLE_PROGRAM_EXIT();
  
          NUITKA_PRINT_TRACE("main(): Calling resource_tracker Py_Exit.");
          // TODO: Should maybe call Py_Exit here, but there were issues with that.
          exit(exit_code);
      } else {
  #endif
  #if defined(_NUITKA_ONEFILE) && defined(_WIN32)
          {
              char buffer[128] = {0};
              DWORD size = GetEnvironmentVariableA("NUITKA_ONEFILE_PARENT", buffer, sizeof(buffer));
  
              if (size > 0 && size < 127) {
                  onefile_ppid = atol(buffer);
  
                  CreateThread(NULL, 0, doOnefileParentMonitoring, NULL, 0, NULL);
              }
          }
  #endif
          PyDict_DelItem(PyImport_GetModuleDict(), const_str_plain___main__);
  
  #if _NUITKA_PLUGIN_WINDOWS_SERVICE_ENABLED
          NUITKA_PRINT_TRACE("main(): Calling plugin SvcLaunchService() entry point.");
          SvcLaunchService();
  #else
      /* Execute the "__main__" module. */
      NUITKA_PRINT_TIMING("main(): Calling __main__.");
      IMPORT_EMBEDDED_MODULE("__main__");
      NUITKA_PRINT_TIMING("main(): Exited from __main__.");
  
  #endif
  #ifdef _NUITKA_PLUGIN_MULTIPROCESSING_ENABLED
      }
  #endif
  
  #if _NUITKA_PROFILE
      stopProfiling();
  #endif
  
  #ifndef __NUITKA_NO_ASSERT__
      checkGlobalConstants();
  
      /* TODO: Walk over all loaded compiled modules, and make this kind of checks. */
      checkModuleConstants___main__();
  
  #endif
  
      int exit_code = HANDLE_PROGRAM_EXIT();
  
  #if _DEBUG_REFCOUNTS
      PRINT_REFCOUNTS();
  #endif
  
      NUITKA_PRINT_TIMING("main(): Calling Py_Exit.");
      Py_Exit(exit_code);
  
      // The "Py_Exit()" calls is not supposed to return.
      NUITKA_CANNOT_GET_HERE("Py_Exit does not return");
  }
  
  /* This is an unofficial API, not available on Windows, but on Linux and others
   * it is exported, and has been used by some code.
   */
  #ifndef _WIN32
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #if PYTHON_VERSION >= 0x300
  #if defined(__GNUC__)
  __attribute__((weak))
  __attribute__((visibility("default")))
  #endif
  void Py_GetArgcArgv(int *argc, wchar_t ***argv) {
      *argc = orig_argc;
      *argv = argv_unicode;
  }
  
  #else
  #if defined(__GNUC__)
  __attribute__((weak))
  __attribute__((visibility("default")))
  #endif
  void Py_GetArgcArgv(int *argc, char ***argv) {
      *argc = orig_argc;
      *argv = orig_argv;
  }
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  #endif
  