PY_EXPORT int Py_BytesMain()

in ext/Modules/main.cpp [138:342]


PY_EXPORT int Py_BytesMain(int argc, char** argv) {
  int print_version = 0;
  bool print_help = false;
  const char* command = nullptr;
  const char* module = nullptr;

  optind = 1;

  DCHECK(warn_options.empty(), "warn options should be empty");
  int option;
  while ((option = getopt_long(argc, argv, kSupportedOpts, kSupportedLongOpts,
                               nullptr)) != -1) {
    // -c and -m mark the end of interpreter options - all further
    // arguments are passed to the script
    if (option == 'c') {
      command = optarg;
      break;
    }
    if (option == 'm') {
      module = optarg;
      break;
    }

    wchar_t* woptarg;
    switch (option) {
      case 'b':
        Py_BytesWarningFlag++;
        break;
      case 'd':
        Py_DebugFlag++;
        break;
      case 'i':
        Py_InspectFlag++;
        Py_InteractiveFlag++;
        break;
      case 'I':
        Py_IsolatedFlag++;
        Py_NoUserSiteDirectory++;
        Py_IgnoreEnvironmentFlag++;
        break;
      case 'O':
        Py_OptimizeFlag++;
        break;
      case 'B':
        Py_DontWriteBytecodeFlag++;
        break;
      case 's':
        Py_NoUserSiteDirectory++;
        break;
      case 'S':
        Py_NoSiteFlag++;
        break;
      case 'E':
        Py_IgnoreEnvironmentFlag++;
        break;
      case 't':
        // ignored for backwards compatibility.
        break;
      case 'u':
        Py_UnbufferedStdioFlag = 1;
        break;
      case 'v':
        Py_VerboseFlag++;
        break;
      case 'x':
        UNIMPLEMENTED("skip first line");
        break;
      case 'h':
      case '?':
        print_help = true;
        break;
      case 'V':
        print_version++;
        break;
      case 'W':
        warn_options.push_back(optarg);
        break;
      case 'X':
        woptarg = Py_DecodeLocale(optarg, nullptr);
        PySys_AddXOption(woptarg);
        PyMem_RawFree(woptarg);
        woptarg = nullptr;
        break;
      case 'q':
        Py_QuietFlag++;
        break;
      default:
        UNREACHABLE("Unexpected value returned from getopt_long()");
    }
  }

  if (print_help) {
    UNIMPLEMENTED("command line help");
  }

  if (print_version) {
    std::printf("Python %s\n", print_version >= 2 ? Py_GetVersion() : kVersion);
    return 0;
  }

  char* filename = nullptr;
  if (command == nullptr && module == nullptr && optind < argc &&
      std::strcmp(argv[optind], "-") != 0) {
    filename = argv[optind];
  }

  bool is_interactive = Py_FdIsInteractive(stdin, nullptr);

  wchar_t* prog_name = Py_DecodeLocale(argv[0], nullptr);
  if (prog_name == nullptr) {
    failArgConversion("unable to decode the program name", 0);
  }
  Py_SetProgramName(prog_name);
  PyMem_RawFree(prog_name);

  Py_Initialize();

  if (!Py_QuietFlag &&
      (Py_VerboseFlag || (command == nullptr && filename == nullptr &&
                          module == nullptr && is_interactive))) {
    std::fprintf(stderr, "Python %s on %s\n", Py_GetVersion(),
                 Py_GetPlatform());
    if (!Py_NoSiteFlag) {
      std::fprintf(stderr, "%s\n", kInteractiveHelp);
    }
  }

  int wargc;
  wchar_t** wargv;
  if (command != nullptr || module != nullptr) {
    // Start arg list with "-c" or "-m" and omit command/module arg
    wargc = argc - optind + 1;
    const char** argv_copy =
        static_cast<const char**>(PyMem_RawCalloc(wargc, sizeof(*argv_copy)));
    argv_copy[0] = command != nullptr ? "-c" : "-m";
    for (int i = optind; i < argc; i++) {
      argv_copy[i - optind + 1] = argv[i];
    }
    wargv = static_cast<wchar_t**>(PyMem_RawCalloc(wargc, sizeof(*wargv)));
    decodeArgv(wargc, argv_copy, wargv);
    PyMem_RawFree(argv_copy);
  } else {
    wargc = argc - optind;
    wargv = static_cast<wchar_t**>(PyMem_RawCalloc(wargc, sizeof(*wargv)));
    decodeArgv(wargc, argv + optind, wargv);
  }
  PySys_SetArgv(wargc, wargv);
  for (int i = 0; i < wargc; i++) {
    PyMem_RawFree(wargv[i]);
  }
  PyMem_RawFree(wargv);

  PyCompilerFlags flags = _PyCompilerFlags_INIT;

  int returncode;
  if (command != nullptr) {
    returncode = PyRun_SimpleStringFlags(command, &flags) == 0 ? EXIT_SUCCESS
                                                               : EXIT_FAILURE;
  } else if (module != nullptr) {
    returncode = runModule(module, true) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
  } else if (filename != nullptr) {
    Thread* thread = Thread::current();
    int run_package_result = tryRunPackage(thread, filename);
    if (run_package_result == 1) {
      returncode = EXIT_SUCCESS;
    } else if (run_package_result < 0) {
      returncode = EXIT_FAILURE;
    } else {
      // `filename` was not a package, run as single file.
      FILE* fp = std::fopen(filename, "r");
      if (fp == nullptr) {
        std::fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
                     argv[0], filename, errno, std::strerror(errno));
        return 2;
      }
      returncode =
          PyRun_AnyFileExFlags(fp, filename, /*closeit=*/1, &flags) == 0
              ? EXIT_SUCCESS
              : EXIT_FAILURE;
    }
  } else {
    // filename == nullptr: read input from stdin
    if (is_interactive) {
      Py_InspectFlag = 0;  // do exit on SystemExit
      runStartupFile(&flags);
      runInteractiveHook();
    }
    returncode =
        PyRun_AnyFileExFlags(stdin, "<stdin>", /*closeit=*/0, &flags) == 0
            ? EXIT_SUCCESS
            : EXIT_FAILURE;
  }

  if (Py_InspectFlag && is_interactive) {
    Py_InspectFlag = 0;
    runInteractiveHook();
    returncode = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &flags) == 0
                     ? EXIT_SUCCESS
                     : EXIT_FAILURE;
  }

  Py_Finalize();

  return returncode;
}