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     PySys_ResetWarnOptions();
    262 
    263     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
    264         if (c == 'c') {
    265             /* -c is the last option; following arguments
    266                that look like options are left for the
    267                command to interpret. */
    268             command = (char *)malloc(strlen(_PyOS_optarg) + 2);
    269             if (command == NULL)
    270                 Py_FatalError(
    271                    "not enough memory to copy -c argument");
    272             strcpy(command, _PyOS_optarg);
    273             strcat(command, "\n");
    274             break;
    275         }
    276 
    277         if (c == 'm') {
    278             /* -m is the last option; following arguments
    279                that look like options are left for the
    280                module to interpret. */
    281             module = (char *)malloc(strlen(_PyOS_optarg) + 2);
    282             if (module == NULL)
    283                 Py_FatalError(
    284                    "not enough memory to copy -m argument");
    285             strcpy(module, _PyOS_optarg);
    286             break;
    287         }
    288 
    289         switch (c) {
    290         case 'b':
    291             Py_BytesWarningFlag++;
    292             break;
    293 
    294         case 'd':
    295             Py_DebugFlag++;
    296             break;
    297 
    298         case '3':
    299             Py_Py3kWarningFlag++;
    300             if (!Py_DivisionWarningFlag)
    301                 Py_DivisionWarningFlag = 1;
    302             break;
    303 
    304         case 'Q':
    305             if (strcmp(_PyOS_optarg, "old") == 0) {
    306                 Py_DivisionWarningFlag = 0;
    307                 break;
    308             }
    309             if (strcmp(_PyOS_optarg, "warn") == 0) {
    310                 Py_DivisionWarningFlag = 1;
    311                 break;
    312             }
    313             if (strcmp(_PyOS_optarg, "warnall") == 0) {
    314                 Py_DivisionWarningFlag = 2;
    315                 break;
    316             }
    317             if (strcmp(_PyOS_optarg, "new") == 0) {
    318                 /* This only affects __main__ */
    319                 cf.cf_flags |= CO_FUTURE_DIVISION;
    320                 /* And this tells the eval loop to treat
    321                    BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
    322                 _Py_QnewFlag = 1;
    323                 break;
    324             }
    325             fprintf(stderr,
    326                 "-Q option should be `-Qold', "
    327                 "`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
    328             return usage(2, argv[0]);
    329             /* NOTREACHED */
    330 
    331         case 'i':
    332             Py_InspectFlag++;
    333             Py_InteractiveFlag++;
    334             break;
    335 
    336         /* case 'J': reserved for Jython */
    337 
    338         case 'O':
    339             Py_OptimizeFlag++;
    340             break;
    341 
    342         case 'B':
    343             Py_DontWriteBytecodeFlag++;
    344             break;
    345 
    346         case 's':
    347             Py_NoUserSiteDirectory++;
    348             break;
    349 
    350         case 'S':
    351             Py_NoSiteFlag++;
    352             break;
    353 
    354         case 'E':
    355           Py_IgnoreEnvironmentFlag++;
    356           break;
    357 
    358         case 't':
    359             Py_TabcheckFlag++;
    360             break;
    361 
    362         case 'u':
    363             unbuffered++;
    364             saw_unbuffered_flag = 1;
    365             break;
    366 
    367         case 'v':
    368             Py_VerboseFlag++;
    369             break;
    370 
    371 #ifdef RISCOS
    372         case 'w':
    373             Py_RISCOSWimpFlag = 1;
    374             break;
    375 #endif
    376 
    377         case 'x':
    378             skipfirstline = 1;
    379             break;
    380 
    381         /* case 'X': reserved for implementation-specific arguments */
    382 
    383         case 'U':
    384             Py_UnicodeFlag++;
    385             break;
    386         case 'h':
    387         case '?':
    388             help++;
    389             break;
    390         case 'V':
    391             version++;
    392             break;
    393 
    394         case 'W':
    395             PySys_AddWarnOption(_PyOS_optarg);
    396             break;
    397 
    398         case '#':
    399           if (saw_pound_flag == 0) {
    400             if(freopen("stdout:", "w", stderr) == NULL) {
    401               puts("ERROR: Unable to reopen stderr as an alias to stdout!");
    402             }
    403             saw_pound_flag = 0xFF;
    404           }
    405           break;
    406 
    407         /* This space reserved for other options */
    408 
    409         default:
    410             return usage(2, argv[0]);
    411             /*NOTREACHED*/
    412 
    413         }
    414     }
    415 
    416     if (help)
    417         return usage(0, argv[0]);
    418 
    419     if (version) {
    420         fprintf(stderr, "Python %s\n", PY_VERSION);
    421         return 0;
    422     }
    423 
    424     if (Py_Py3kWarningFlag && !Py_TabcheckFlag)
    425         /* -3 implies -t (but not -tt) */
    426         Py_TabcheckFlag = 1;
    427 
    428     if (!Py_InspectFlag &&
    429         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
    430         Py_InspectFlag = 1;
    431     if (!saw_unbuffered_flag &&
    432         (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
    433         unbuffered = 1;
    434 
    435     if (!Py_NoUserSiteDirectory &&
    436         (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
    437         Py_NoUserSiteDirectory = 1;
    438 
    439     if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
    440         char *buf, *warning;
    441 
    442         buf = (char *)malloc(strlen(p) + 1);
    443         if (buf == NULL)
    444             Py_FatalError(
    445                "not enough memory to copy PYTHONWARNINGS");
    446         strcpy(buf, p);
    447         for (warning = strtok(buf, ",");
    448              warning != NULL;
    449              warning = strtok(NULL, ","))
    450             PySys_AddWarnOption(warning);
    451         free(buf);
    452     }
    453 
    454     if (command == NULL && module == NULL && _PyOS_optind < argc &&
    455         strcmp(argv[_PyOS_optind], "-") != 0)
    456     {
    457 #ifdef __VMS
    458         filename = decc$translate_vms(argv[_PyOS_optind]);
    459         if (filename == (char *)0 || filename == (char *)-1)
    460             filename = argv[_PyOS_optind];
    461 
    462 #else
    463         filename = argv[_PyOS_optind];
    464 #endif
    465     }
    466 
    467     stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
    468 
    469     if (unbuffered) {
    470 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
    471         _setmode(fileno(stdin), O_BINARY);
    472         _setmode(fileno(stdout), O_BINARY);
    473 #endif
    474 #ifdef HAVE_SETVBUF
    475         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
    476         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    477         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
    478 #else /* !HAVE_SETVBUF */
    479         setbuf(stdin,  (char *)NULL);
    480         setbuf(stdout, (char *)NULL);
    481         setbuf(stderr, (char *)NULL);
    482 #endif /* !HAVE_SETVBUF */
    483     }
    484     else if (Py_InteractiveFlag) {
    485 #ifdef MS_WINDOWS
    486         /* Doesn't have to have line-buffered -- use unbuffered */
    487         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
    488         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    489 #else /* !MS_WINDOWS */
    490 #ifdef HAVE_SETVBUF
    491         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
    492         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
    493 #endif /* HAVE_SETVBUF */
    494 #endif /* !MS_WINDOWS */
    495         /* Leave stderr alone - it should be unbuffered anyway. */
    496     }
    497 #ifdef __VMS
    498     else {
    499         setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
    500     }
    501 #endif /* __VMS */
    502 
    503 #ifdef __APPLE__
    504     /* On MacOS X, when the Python interpreter is embedded in an
    505        application bundle, it gets executed by a bootstrapping script
    506        that does os.execve() with an argv[0] that's different from the
    507        actual Python executable. This is needed to keep the Finder happy,
    508        or rather, to work around Apple's overly strict requirements of
    509        the process name. However, we still need a usable sys.executable,
    510        so the actual executable path is passed in an environment variable.
    511        See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
    512        script. */
    513     if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0')
    514         Py_SetProgramName(p);
    515     else
    516         Py_SetProgramName(argv[0]);
    517 #else
    518     Py_SetProgramName(argv[0]);
    519 #endif
    520     Py_Initialize();
    521 
    522     if (Py_VerboseFlag ||
    523         (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
    524         fprintf(stderr, "Python %s on %s\n",
    525             Py_GetVersion(), Py_GetPlatform());
    526         if (!Py_NoSiteFlag)
    527             fprintf(stderr, "%s\n", COPYRIGHT);
    528     }
    529 
    530     if (command != NULL) {
    531         /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
    532         _PyOS_optind--;
    533         argv[_PyOS_optind] = "-c";
    534     }
    535 
    536     if (module != NULL) {
    537         /* Backup _PyOS_optind and force sys.argv[0] = '-c'
    538            so that PySys_SetArgv correctly sets sys.path[0] to ''
    539            rather than looking for a file called "-m". See
    540            tracker issue #8202 for details. */
    541         _PyOS_optind--;
    542         argv[_PyOS_optind] = "-c";
    543     }
    544 
    545     PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
    546 
    547     if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
    548         isatty(fileno(stdin))) {
    549         PyObject *v;
    550         v = PyImport_ImportModule("readline");
    551         if (v == NULL)
    552             PyErr_Clear();
    553         else
    554             Py_DECREF(v);
    555     }
    556 
    557     if (command) {
    558         sts = PyRun_SimpleStringFlags(command, &cf) != 0;
    559         free(command);
    560     } else if (module) {
    561         sts = (RunModule(module, 1) != 0);
    562         free(module);
    563     }
    564     else {
    565 
    566         if (filename == NULL && stdin_is_interactive) {
    567             Py_InspectFlag = 0; /* do exit on SystemExit */
    568             RunStartupFile(&cf);
    569         }
    570         /* XXX */
    571 
    572         sts = -1;               /* keep track of whether we've already run __main__ */
    573 
    574         if (filename != NULL) {
    575             sts = RunMainFromImporter(filename);
    576         }
    577 
    578         if (sts==-1 && filename!=NULL) {
    579             if ((fp = fopen(filename, "r")) == NULL) {
    580                 fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
    581                     argv[0], filename, errno, strerror(errno));
    582 
    583                 return 2;
    584             }
    585             else if (skipfirstline) {
    586                 int ch;
    587                 /* Push back first newline so line numbers
    588                    remain the same */
    589                 while ((ch = getc(fp)) != EOF) {
    590                     if (ch == '\n') {
    591                         (void)ungetc(ch, fp);
    592                         break;
    593                     }
    594                 }
    595             }
    596             {
    597                 /* XXX: does this work on Win/Win64? (see posix_fstat) */
    598                 struct stat sb;
    599                 if (fstat(fileno(fp), &sb) == 0 &&
    600                     S_ISDIR(sb.st_mode)) {
    601                     fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
    602                     fclose(fp);
    603                     return 1;
    604                 }
    605             }
    606         }
    607 
    608         if (sts==-1) {
    609             /* call pending calls like signal handlers (SIGINT) */
    610             if (Py_MakePendingCalls() == -1) {
    611                 PyErr_Print();
    612                 sts = 1;
    613             } else {
    614                 sts = PyRun_AnyFileExFlags(
    615                     fp,
    616                     filename == NULL ? "<stdin>" : filename,
    617                     filename != NULL, &cf) != 0;
    618             }
    619         }
    620 
    621     }
    622 
    623     /* Check this environment variable at the end, to give programs the
    624      * opportunity to set it from Python.
    625      */
    626     if (!Py_InspectFlag &&
    627         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
    628     {
    629         Py_InspectFlag = 1;
    630     }
    631 
    632     if (Py_InspectFlag && stdin_is_interactive &&
    633         (filename != NULL || command != NULL || module != NULL)) {
    634         Py_InspectFlag = 0;
    635         /* XXX */
    636         sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
    637     }
    638 
    639     Py_Finalize();
    640 #ifdef RISCOS
    641     if (Py_RISCOSWimpFlag)
    642         fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
    643 #endif
    644 
    645 #ifdef __INSURE__
    646     /* Insure++ is a memory analysis tool that aids in discovering
    647      * memory leaks and other memory problems.  On Python exit, the
    648      * interned string dictionary is flagged as being in use at exit
    649      * (which it is).  Under normal circumstances, this is fine because
    650      * the memory will be automatically reclaimed by the system.  Under
    651      * memory debugging, it's a huge source of useless noise, so we
    652      * trade off slower shutdown for less distraction in the memory
    653      * reports.  -baw
    654      */
    655     _Py_ReleaseInternedStrings();
    656 #endif /* __INSURE__ */
    657 
    658     return sts;
    659 }
    660 
    661 /* this is gonna seem *real weird*, but if you put some other code between
    662    Py_Main() and Py_GetArgcArgv() you will need to adjust the test in the
    663    while statement in Misc/gdbinit:ppystack */
    664 
    665 /* Make the *original* argc/argv available to other modules.
    666    This is rare, but it is needed by the secureware extension. */
    667 
    668 void
    669 Py_GetArgcArgv(int *argc, char ***argv)
    670 {
    671     *argc = orig_argc;
    672     *argv = orig_argv;
    673 }
    674 
    675 #ifdef __cplusplus
    676 }
    677 #endif
    678 
    679