summaryrefslogtreecommitdiffstats
path: root/Modules/main.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2004-10-07 06:46:25 (GMT)
committerRaymond Hettinger <python@rcn.com>2004-10-07 06:46:25 (GMT)
commitdb29e0fe8cab58c68d1263487ba5bac7b99c7612 (patch)
tree8ca6ad43fa5c3b9878ccf022f7161be0b6ba8b5e /Modules/main.c
parentfb09f0e85cd75ec46700562687a9da3063ff0b7c (diff)
downloadcpython-db29e0fe8cab58c68d1263487ba5bac7b99c7612.zip
cpython-db29e0fe8cab58c68d1263487ba5bac7b99c7612.tar.gz
cpython-db29e0fe8cab58c68d1263487ba5bac7b99c7612.tar.bz2
SF patch #1035498: -m option to run a module as a script
(Contributed by Nick Coghlan.)
Diffstat (limited to 'Modules/main.c')
-rw-r--r--Modules/main.c80
1 files changed, 73 insertions, 7 deletions
diff --git a/Modules/main.c b/Modules/main.c
index bc543a4..1005b94 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -3,6 +3,7 @@
#include "Python.h"
#include "osdefs.h"
#include "compile.h" /* For CO_FUTURE_DIVISION */
+#include "import.h"
#ifdef __VMS
#include <unixlib.h>
@@ -33,7 +34,7 @@ static char **orig_argv;
static int orig_argc;
/* command line options */
-#define BASE_OPTS "c:dEhiOQ:StuUvVW:xX"
+#define BASE_OPTS "c:dEhim:OQ:StuUvVW:xX"
#ifndef RISCOS
#define PROGRAM_OPTS BASE_OPTS
@@ -47,7 +48,7 @@ extern int Py_RISCOSWimpFlag;
/* Short usage message (with %s for argv0) */
static char *usage_line =
-"usage: %s [option] ... [-c cmd | file | -] [arg] ...\n";
+"usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
/* Long usage message, split into parts < 512 bytes */
static char *usage_1 = "\
@@ -60,15 +61,16 @@ Options and arguments (and corresponding environment variables):\n\
and force prompts, even if stdin does not appear to be a terminal\n\
";
static char *usage_2 = "\
+-m mod : run library module as a script (terminates option list)\n\
-O : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n\
-OO : remove doc-strings in addition to the -O optimizations\n\
-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
-S : don't imply 'import site' on initialization\n\
-t : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
-u : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)\n\
- see man page for details on internal buffering relating to '-u'\n\
";
static char *usage_3 = "\
+ see man page for details on internal buffering relating to '-u'\n\
-v : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
-V : print the Python version number and exit\n\
-W arg : warning control (arg is action:message:category:module:lineno)\n\
@@ -130,6 +132,28 @@ static void RunStartupFile(PyCompilerFlags *cf)
}
}
+/* Get the path to a top-level module */
+static struct filedescr * FindModule(const char *module,
+ FILE **fp, char **filename)
+{
+ struct filedescr *fdescr = NULL;
+ *fp = NULL;
+ *filename = malloc(MAXPATHLEN);
+
+ if (*filename == NULL)
+ return NULL;
+
+ /* Find the actual module source code */
+ fdescr = _PyImport_FindModule(module, NULL,
+ *filename, MAXPATHLEN, fp, NULL);
+
+ if (fdescr == NULL) {
+ free(*filename);
+ *filename = NULL;
+ }
+
+ return fdescr;
+}
/* Main program */
@@ -140,6 +164,7 @@ Py_Main(int argc, char **argv)
int sts;
char *command = NULL;
char *filename = NULL;
+ char *module = NULL;
FILE *fp = stdin;
char *p;
int inspect = 0;
@@ -177,6 +202,18 @@ Py_Main(int argc, char **argv)
break;
}
+ if (c == 'm') {
+ /* -m is the last option; following arguments
+ that look like options are left for the
+ module to interpret. */
+ module = malloc(strlen(_PyOS_optarg) + 2);
+ if (module == NULL)
+ Py_FatalError(
+ "not enough memory to copy -m argument");
+ strcpy(module, _PyOS_optarg);
+ break;
+ }
+
switch (c) {
case 'd':
@@ -289,7 +326,7 @@ Py_Main(int argc, char **argv)
(p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
unbuffered = 1;
- if (command == NULL && _PyOS_optind < argc &&
+ if (command == NULL && module == NULL && _PyOS_optind < argc &&
strcmp(argv[_PyOS_optind], "-") != 0)
{
#ifdef __VMS
@@ -381,7 +418,7 @@ Py_Main(int argc, char **argv)
Py_Initialize();
if (Py_VerboseFlag ||
- (command == NULL && filename == NULL && stdin_is_interactive)) {
+ (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
fprintf(stderr, "Python %s on %s\n",
Py_GetVersion(), Py_GetPlatform());
if (!Py_NoSiteFlag)
@@ -394,9 +431,34 @@ Py_Main(int argc, char **argv)
argv[_PyOS_optind] = "-c";
}
+ if (module != NULL) {
+ /* Backup _PyOS_optind and find the real file */
+ struct filedescr *fdescr = NULL;
+ _PyOS_optind--;
+ if ((fdescr = FindModule(module, &fp, &filename))) {
+ argv[_PyOS_optind] = filename;
+ } else {
+ fprintf(stderr, "%s: module %s not found\n",
+ argv[0], module);
+ return 2;
+ }
+ if (!fp) {
+ fprintf(stderr,
+ "%s: module %s has no associated file\n",
+ argv[0], module);
+ return 2;
+ }
+ if (!_PyImport_IsScript(fdescr)) {
+ fprintf(stderr,
+ "%s: module %s not usable as script\n (%s)\n",
+ argv[0], module, filename);
+ return 2;
+ }
+ }
+
PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
- if ((inspect || (command == NULL && filename == NULL)) &&
+ if ((inspect || (command == NULL && filename == NULL && module == NULL)) &&
isatty(fileno(stdin))) {
PyObject *v;
v = PyImport_ImportModule("readline");
@@ -409,6 +471,10 @@ Py_Main(int argc, char **argv)
if (command) {
sts = PyRun_SimpleStringFlags(command, &cf) != 0;
free(command);
+ } else if (module) {
+ sts = PyRun_AnyFileExFlags(fp, filename, 1, &cf) != 0;
+ free(module);
+ free(filename);
}
else {
if (filename == NULL && stdin_is_interactive) {
@@ -431,7 +497,7 @@ Py_Main(int argc, char **argv)
}
if (inspect && stdin_is_interactive &&
- (filename != NULL || command != NULL))
+ (filename != NULL || command != NULL || module != NULL))
/* XXX */
sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;