Home | History | Annotate | Download | only in Modules
      1 /** @file
      2   Python interpreter main program.
      3 
      4   Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR>
      5 **/
      6 
      7 #include "Python.h"
      8 #include "osdefs.h"
      9 #include "code.h" /* For CO_FUTURE_DIVISION */
     10 #include "import.h"
     11 
     12 #ifdef __VMS
     13 #include <unixlib.h>
     14 #endif
     15 
     16 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
     17 #ifdef HAVE_FCNTL_H
     18 #include <fcntl.h>
     19 #endif
     20 #endif
     21 
     22 #if (defined(PYOS_OS2) && !defined(PYCC_GCC)) || defined(MS_WINDOWS)
     23 #define PYTHONHOMEHELP "<prefix>\\lib"
     24 #else
     25 #if defined(PYOS_OS2) && defined(PYCC_GCC)
     26 #define PYTHONHOMEHELP "<prefix>/Lib"
     27 #else
     28 #define PYTHONHOMEHELP "<prefix>/pythonX.X"
     29 #endif
     30 #endif
     31 
     32 #include "pygetopt.h"
     33 
     34 #define COPYRIGHT \
     35     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
     36     "for more information."
     37 
     38 #ifdef __cplusplus
     39 extern "C" {
     40 #endif
     41 
     42 /* For Py_GetArgcArgv(); set by main() */
     43 static char **orig_argv;
     44 static int  orig_argc;
     45 
     46 /* command line options */
     47 #define BASE_OPTS "#3bBc:dEhiJm:OQ:sStuUvVW:xX?"
     48 
     49 #ifndef RISCOS
     50 #define PROGRAM_OPTS BASE_OPTS
     51 #else /*RISCOS*/
     52 /* extra option saying that we are running under a special task window
     53    frontend; especially my_readline will behave different */
     54 #define PROGRAM_OPTS BASE_OPTS "w"
     55 /* corresponding flag */
     56 extern int Py_RISCOSWimpFlag;
     57 #endif /*RISCOS*/
     58 
     59 /* Short usage message (with %s for argv0) */
     60 static char *usage_line =
     61 "usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
     62 
     63 /* Long usage message, split into parts < 512 bytes */
     64 static char *usage_1 = "\
     65 Options and arguments (and corresponding environment variables):\n\
     66 -#     : alias stderr to stdout for platforms without STDERR output.\n\
     67 -B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x\n\
     68 -c cmd : program passed in as string (terminates option list)\n\
     69 -d     : debug output from parser; also PYTHONDEBUG=x\n\
     70 -E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
     71 -h     : print this help message and exit (also --help)\n\
     72 -i     : inspect interactively after running script; forces a prompt even\n\
     73 ";
     74 static char *usage_2 = "\
     75          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
     76 -m mod : run library module as a script (terminates option list)\n\
     77 -O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
     78 -OO    : remove doc-strings in addition to the -O optimizations\n\
     79 -Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
     80 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
     81 -S     : don't imply 'import site' on initialization\n\
     82 -t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
     83 ";
     84 static char *usage_3 = "\
     85 -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\
     86          see man page for details on internal buffering relating to '-u'\n\
     87 -v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
     88          can be supplied multiple times to increase verbosity\n\
     89 -V     : print the Python version number and exit (also --version)\n\
     90 -W arg : warning control; arg is action:message:category:module:lineno\n\
     91          also PYTHONWARNINGS=arg\n\
     92 -x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
     93 ";
     94 static char *usage_4 = "\
     95 -3     : warn about Python 3.x incompatibilities that 2to3 cannot trivially fix\n\
     96 file   : program read from script file\n\
     97 -      : program read from stdin (default; interactive mode if a tty)\n\
     98 arg ...: arguments passed to program in sys.argv[1:]\n\n\
     99 Other environment variables:\n\
    100 PYTHONSTARTUP: file executed on interactive startup (no default)\n\
    101 PYTHONPATH   : '%c'-separated list of directories prefixed to the\n\
    102                default module search path.  The result is sys.path.\n\
    103 ";
    104 static char *usage_5 = "\
    105 PYTHONHOME   : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\
    106                The default module search path uses %s.\n\
    107 PYTHONCASEOK : ignore case in 'import' statements (UEFI default).\n\
    108 PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\
    109 ";
    110 
    111 
    112 static int
    113 usage(int exitcode, char* program)
    114 {
    115     FILE *f = exitcode ? stderr : stdout;
    116 
    117     fprintf(f, usage_line, program);
    118     if (exitcode)
    119         fprintf(f, "Try `python -h' for more information.\n");
    120     else {
    121         fputs(usage_1, f);
    122         fputs(usage_2, f);
    123         fputs(usage_3, f);
    124         fprintf(f, usage_4, DELIM);
    125         fprintf(f, usage_5, DELIM, PYTHONHOMEHELP);
    126     }
    127 #if defined(__VMS)
    128     if (exitcode == 0) {
    129         /* suppress 'error' message */
    130         return 1;
    131     }
    132     else {
    133         /* STS$M_INHIB_MSG + SS$_ABORT */
    134         return 0x1000002c;
    135     }
    136 #else
    137     return exitcode;
    138 #endif
    139     /*NOTREACHED*/
    140 }
    141 
    142 static void RunStartupFile(PyCompilerFlags *cf)
    143 {
    144     char *startup = Py_GETENV("PYTHONSTARTUP");
    145     if (startup != NULL && startup[0] != '\0') {
    146         FILE *fp = fopen(startup, "r");
    147         if (fp != NULL) {
    148             (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf);
    149             PyErr_Clear();
    150             fclose(fp);
    151            } else {
    152                     int save_errno;
    153                     save_errno = errno;
    154                     PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
    155                     errno = save_errno;
    156                     PyErr_SetFromErrnoWithFilename(PyExc_IOError,
    157                                                    startup);
    158                     PyErr_Print();
    159                     PyErr_Clear();
    160         }
    161     }
    162 }
    163 
    164 
    165 static int RunModule(char *module, int set_argv0)
    166 {
    167     PyObject *runpy, *runmodule, *runargs, *result;
    168     runpy = PyImport_ImportModule("runpy");
    169     if (runpy == NULL) {
    170         fprintf(stderr, "Could not import runpy module\n");
    171         return -1;
    172     }
    173     runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
    174     if (runmodule == NULL) {
    175         fprintf(stderr, "Could not access runpy._run_module_as_main\n");
    176         Py_DECREF(runpy);
    177         return -1;
    178     }
    179     runargs = Py_BuildValue("(si)", module, set_argv0);
    180     if (runargs == NULL) {
    181         fprintf(stderr,
    182             "Could not create arguments for runpy._run_module_as_main\n");
    183         Py_DECREF(runpy);
    184         Py_DECREF(runmodule);
    185         return -1;
    186     }
    187     result = PyObject_Call(runmodule, runargs, NULL);
    188     if (result == NULL) {
    189         PyErr_Print();
    190     }
    191     Py_DECREF(runpy);
    192     Py_DECREF(runmodule);
    193     Py_DECREF(runargs);
    194     if (result == NULL) {
    195         return -1;
    196     }
    197     Py_DECREF(result);
    198     return 0;
    199 }
    200 
    201 static int RunMainFromImporter(char *filename)
    202 {
    203     PyObject *argv0 = NULL, *importer = NULL;
    204 
    205     if ((argv0 = PyString_FromString(filename)) &&
    206         (importer = PyImport_GetImporter(argv0)) &&
    207         (importer->ob_type != &PyNullImporter_Type))
    208     {
    209              /* argv0 is usable as an import source, so
    210                     put it in sys.path[0] and import __main__ */
    211         PyObject *sys_path = NULL;
    212         if ((sys_path = PySys_GetObject("path")) &&
    213             !PyList_SetItem(sys_path, 0, argv0))
    214         {
    215             Py_INCREF(argv0);
    216             Py_DECREF(importer);
    217             sys_path = NULL;
    218             return RunModule("__main__", 0) != 0;
    219         }
    220     }
    221     Py_XDECREF(argv0);
    222     Py_XDECREF(importer);
    223     if (PyErr_Occurred()) {
    224         PyErr_Print();
    225         return 1;
    226     }
    227     return -1;
    228 }
    229 
    230 
    231 /* Main program */
    232 
    233 int
    234 Py_Main(int argc, char **argv)
    235 {
    236     int c;
    237     int sts;
    238     char *command = NULL;
    239     char *filename = NULL;
    240     char *module = NULL;
    241     FILE *fp = stdin;
    242     char *p;
    243     int unbuffered = 0;
    244     int skipfirstline = 0;
    245     int stdin_is_interactive = 0;
    246     int help = 0;
    247     int version = 0;
    248     int saw_unbuffered_flag = 0;
    249     int saw_pound_flag = 0;
    250     PyCompilerFlags cf;
    251 
    252     cf.cf_flags = 0;
    253 
    254     orig_argc = argc;           /* For Py_GetArgcArgv() */
    255     orig_argv = argv;
    256 
    257 #ifdef RISCOS
    258     Py_RISCOSWimpFlag = 0;
    259 #endif
    260 
    261     /* Hash randomization needed early for all string operations
    262        (including -W and -X options). */
    263     _PyOS_opterr = 0;  /* prevent printing the error in 1st pass */
    264     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
    265       if (c == 'm' || c == 'c') {
    266         /* -c / -m is the last option: following arguments are
    267            not interpreter options. */
    268         break;
    269       }
    270       switch (c) {
    271         case '#':
    272           if (saw_pound_flag == 0) {
    273             if(freopen("stdout:", "w", stderr) == NULL) {
    274               puts("ERROR: Unable to reopen stderr as an alias to stdout!");
    275             }
    276             saw_pound_flag = 0xFF;
    277           }
    278           break;
    279         case 'E':
    280           Py_IgnoreEnvironmentFlag++;
    281           break;
    282         default:
    283           break;
    284       }
    285     }
    286     _PyRandom_Init();
    287 
    288     PySys_ResetWarnOptions();
    289     _PyOS_ResetGetOpt();
    290 
    291     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
    292         if (c == 'c') {
    293             /* -c is the last option; following arguments
    294                that look like options are left for the
    295                command to interpret. */
    296             command = (char *)malloc(strlen(_PyOS_optarg) + 2);
    297             if (command == NULL)
    298                 Py_FatalError(
    299                    "not enough memory to copy -c argument");
    300             strcpy(command, _PyOS_optarg);
    301             strcat(command, "\n");
    302             break;
    303         }
    304 
    305         if (c == 'm') {
    306             /* -m is the last option; following arguments
    307                that look like options are left for the
    308                module to interpret. */
    309             module = (char *)malloc(strlen(_PyOS_optarg) + 2);
    310             if (module == NULL)
    311                 Py_FatalError(
    312                    "not enough memory to copy -m argument");
    313             strcpy(module, _PyOS_optarg);
    314             break;
    315         }
    316 
    317         switch (c) {
    318         case 'b':
    319             Py_BytesWarningFlag++;
    320             break;
    321 
    322         case 'd':
    323             Py_DebugFlag++;
    324             break;
    325 
    326         case '3':
    327             Py_Py3kWarningFlag++;
    328             if (!Py_DivisionWarningFlag)
    329                 Py_DivisionWarningFlag = 1;
    330             break;
    331 
    332         case 'Q':
    333             if (strcmp(_PyOS_optarg, "old") == 0) {
    334                 Py_DivisionWarningFlag = 0;
    335                 break;
    336             }
    337             if (strcmp(_PyOS_optarg, "warn") == 0) {
    338                 Py_DivisionWarningFlag = 1;
    339                 break;
    340             }
    341             if (strcmp(_PyOS_optarg, "warnall") == 0) {
    342                 Py_DivisionWarningFlag = 2;
    343                 break;
    344             }
    345             if (strcmp(_PyOS_optarg, "new") == 0) {
    346                 /* This only affects __main__ */
    347                 cf.cf_flags |= CO_FUTURE_DIVISION;
    348                 /* And this tells the eval loop to treat
    349                    BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
    350                 _Py_QnewFlag = 1;
    351                 break;
    352             }
    353             fprintf(stderr,
    354                 "-Q option should be `-Qold', "
    355                 "`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
    356             return usage(2, argv[0]);
    357             /* NOTREACHED */
    358 
    359         case 'i':
    360             Py_InspectFlag++;
    361             Py_InteractiveFlag++;
    362             break;
    363 
    364         /* case 'J': reserved for Jython */
    365 
    366         case 'O':
    367             Py_OptimizeFlag++;
    368             break;
    369 
    370         case 'B':
    371             Py_DontWriteBytecodeFlag++;
    372             break;
    373 
    374         case 's':
    375             Py_NoUserSiteDirectory++;
    376             break;
    377 
    378         case 'S':
    379             Py_NoSiteFlag++;
    380             break;
    381 
    382         case 'E':
    383             /* Already handled above */
    384             break;
    385 
    386         case 't':
    387             Py_TabcheckFlag++;
    388             break;
    389 
    390         case 'u':
    391             unbuffered++;
    392             saw_unbuffered_flag = 1;
    393             break;
    394 
    395         case 'v':
    396             Py_VerboseFlag++;
    397             break;
    398 
    399 #ifdef RISCOS
    400         case 'w':
    401             Py_RISCOSWimpFlag = 1;
    402             break;
    403 #endif
    404 
    405         case 'x':
    406             skipfirstline = 1;
    407             break;
    408 
    409         /* case 'X': reserved for implementation-specific arguments */
    410 
    411         case 'U':
    412             Py_UnicodeFlag++;
    413             break;
    414         case 'h':
    415         case '?':
    416             help++;
    417             break;
    418         case 'V':
    419             version++;
    420             break;
    421 
    422         case 'W':
    423             PySys_AddWarnOption(_PyOS_optarg);
    424             break;
    425 
    426         case '#':
    427             /* Already handled above */
    428             break;
    429 
    430         /* This space reserved for other options */
    431 
    432         default:
    433             return usage(2, argv[0]);
    434             /*NOTREACHED*/
    435 
    436         }
    437     }
    438 
    439     if (help)
    440         return usage(0, argv[0]);
    441 
    442     if (version) {
    443         fprintf(stderr, "Python %s\n", PY_VERSION);
    444         return 0;
    445     }
    446 
    447     if (Py_Py3kWarningFlag && !Py_TabcheckFlag)
    448         /* -3 implies -t (but not -tt) */
    449         Py_TabcheckFlag = 1;
    450 
    451     if (!Py_InspectFlag &&
    452         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
    453         Py_InspectFlag = 1;
    454     if (!saw_unbuffered_flag &&
    455         (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
    456         unbuffered = 1;
    457 
    458     if (!Py_NoUserSiteDirectory &&
    459         (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
    460         Py_NoUserSiteDirectory = 1;
    461 
    462     if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
    463         char *buf, *warning;
    464 
    465         buf = (char *)malloc(strlen(p) + 1);
    466         if (buf == NULL)
    467             Py_FatalError(
    468                "not enough memory to copy PYTHONWARNINGS");
    469         strcpy(buf, p);
    470         for (warning = strtok(buf, ",");
    471              warning != NULL;
    472              warning = strtok(NULL, ","))
    473             PySys_AddWarnOption(warning);
    474         free(buf);
    475     }
    476 
    477     if (command == NULL && module == NULL && _PyOS_optind < argc &&
    478         strcmp(argv[_PyOS_optind], "-") != 0)
    479     {
    480 #ifdef __VMS
    481         filename = decc$translate_vms(argv[_PyOS_optind]);
    482         if (filename == (char *)0 || filename == (char *)-1)
    483             filename = argv[_PyOS_optind];
    484 
    485 #else
    486         filename = argv[_PyOS_optind];
    487 #endif
    488     }
    489 
    490     stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
    491 
    492     if (unbuffered) {
    493 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
    494         _setmode(fileno(stdin), O_BINARY);
    495         _setmode(fileno(stdout), O_BINARY);
    496 #endif
    497 #ifdef HAVE_SETVBUF
    498         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
    499         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    500         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
    501 #else /* !HAVE_SETVBUF */
    502         setbuf(stdin,  (char *)NULL);
    503         setbuf(stdout, (char *)NULL);
    504         setbuf(stderr, (char *)NULL);
    505 #endif /* !HAVE_SETVBUF */
    506     }
    507     else if (Py_InteractiveFlag) {
    508 #ifdef MS_WINDOWS
    509         /* Doesn't have to have line-buffered -- use unbuffered */
    510         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
    511         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    512 #else /* !MS_WINDOWS */
    513 #ifdef HAVE_SETVBUF
    514         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
    515         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
    516 #endif /* HAVE_SETVBUF */
    517 #endif /* !MS_WINDOWS */
    518         /* Leave stderr alone - it should be unbuffered anyway. */
    519     }
    520 #ifdef __VMS
    521     else {
    522         setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
    523     }
    524 #endif /* __VMS */
    525 
    526 #ifdef __APPLE__
    527     /* On MacOS X, when the Python interpreter is embedded in an
    528        application bundle, it gets executed by a bootstrapping script
    529        that does os.execve() with an argv[0] that's different from the
    530        actual Python executable. This is needed to keep the Finder happy,
    531        or rather, to work around Apple's overly strict requirements of
    532        the process name. However, we still need a usable sys.executable,
    533        so the actual executable path is passed in an environment variable.
    534        See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
    535        script. */
    536     if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0')
    537         Py_SetProgramName(p);
    538     else
    539         Py_SetProgramName(argv[0]);
    540 #else
    541     Py_SetProgramName(argv[0]);
    542 #endif
    543     Py_Initialize();
    544 
    545     if (Py_VerboseFlag ||
    546         (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
    547         fprintf(stderr, "Python %s on %s\n",
    548             Py_GetVersion(), Py_GetPlatform());
    549         if (!Py_NoSiteFlag)
    550             fprintf(stderr, "%s\n", COPYRIGHT);
    551     }
    552 
    553     if (command != NULL) {
    554         /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
    555         _PyOS_optind--;
    556         argv[_PyOS_optind] = "-c";
    557     }
    558 
    559     if (module != NULL) {
    560         /* Backup _PyOS_optind and force sys.argv[0] = '-c'
    561            so that PySys_SetArgv correctly sets sys.path[0] to ''
    562            rather than looking for a file called "-m". See
    563            tracker issue #8202 for details. */
    564         _PyOS_optind--;
    565         argv[_PyOS_optind] = "-c";
    566     }
    567 
    568     PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
    569 
    570     if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
    571         isatty(fileno(stdin))) {
    572         PyObject *v;
    573         v = PyImport_ImportModule("readline");
    574         if (v == NULL)
    575             PyErr_Clear();
    576         else
    577             Py_DECREF(v);
    578     }
    579 
    580     if (command) {
    581         sts = PyRun_SimpleStringFlags(command, &cf) != 0;
    582         free(command);
    583     } else if (module) {
    584         sts = (RunModule(module, 1) != 0);
    585         free(module);
    586     }
    587     else {
    588 
    589         if (filename == NULL && stdin_is_interactive) {
    590             Py_InspectFlag = 0; /* do exit on SystemExit */
    591             RunStartupFile(&cf);
    592         }
    593         /* XXX */
    594 
    595         sts = -1;               /* keep track of whether we've already run __main__ */
    596 
    597         if (filename != NULL) {
    598             sts = RunMainFromImporter(filename);
    599         }
    600 
    601         if (sts==-1 && filename!=NULL) {
    602             if ((fp = fopen(filename, "r")) == NULL) {
    603                 fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
    604                     argv[0], filename, errno, strerror(errno));
    605 
    606                 return 2;
    607             }
    608             else if (skipfirstline) {
    609                 int ch;
    610                 /* Push back first newline so line numbers
    611                    remain the same */
    612                 while ((ch = getc(fp)) != EOF) {
    613                     if (ch == '\n') {
    614                         (void)ungetc(ch, fp);
    615                         break;
    616                     }
    617                 }
    618             }
    619             {
    620                 /* XXX: does this work on Win/Win64? (see posix_fstat) */
    621                 struct stat sb;
    622                 if (fstat(fileno(fp), &sb) == 0 &&
    623                     S_ISDIR(sb.st_mode)) {
    624                     fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
    625                     fclose(fp);
    626                     return 1;
    627                 }
    628             }
    629         }
    630 
    631         if (sts==-1) {
    632             /* call pending calls like signal handlers (SIGINT) */
    633             if (Py_MakePendingCalls() == -1) {
    634                 PyErr_Print();
    635                 sts = 1;
    636             } else {
    637                 sts = PyRun_AnyFileExFlags(
    638                     fp,
    639                     filename == NULL ? "<stdin>" : filename,
    640                     filename != NULL, &cf) != 0;
    641             }
    642         }
    643 
    644     }
    645 
    646     /* Check this environment variable at the end, to give programs the
    647      * opportunity to set it from Python.
    648      */
    649     if (!Py_InspectFlag &&
    650         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
    651     {
    652         Py_InspectFlag = 1;
    653     }
    654 
    655     if (Py_InspectFlag && stdin_is_interactive &&
    656         (filename != NULL || command != NULL || module != NULL)) {
    657         Py_InspectFlag = 0;
    658         /* XXX */
    659         sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
    660     }
    661 
    662     Py_Finalize();
    663 #ifdef RISCOS
    664     if (Py_RISCOSWimpFlag)
    665         fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
    666 #endif
    667 
    668 #ifdef __INSURE__
    669     /* Insure++ is a memory analysis tool that aids in discovering
    670      * memory leaks and other memory problems.  On Python exit, the
    671      * interned string dictionary is flagged as being in use at exit
    672      * (which it is).  Under normal circumstances, this is fine because
    673      * the memory will be automatically reclaimed by the system.  Under
    674      * memory debugging, it's a huge source of useless noise, so we
    675      * trade off slower shutdown for less distraction in the memory
    676      * reports.  -baw
    677      */
    678     _Py_ReleaseInternedStrings();
    679 #endif /* __INSURE__ */
    680 
    681     return sts;
    682 }
    683 
    684 /* this is gonna seem *real weird*, but if you put some other code between
    685    Py_Main() and Py_GetArgcArgv() you will need to adjust the test in the
    686    while statement in Misc/gdbinit:ppystack */
    687 
    688 /* Make the *original* argc/argv available to other modules.
    689    This is rare, but it is needed by the secureware extension. */
    690 
    691 void
    692 Py_GetArgcArgv(int *argc, char ***argv)
    693 {
    694     *argc = orig_argc;
    695     *argv = orig_argv;
    696 }
    697 
    698 #ifdef __cplusplus
    699 }
    700 #endif
    701 
    702