Browse Source

command-line arguments

David Rose 16 years ago
parent
commit
1dda2cfb99

+ 28 - 2
direct/src/plugin/p3dFileParams.cxx

@@ -82,6 +82,25 @@ set_tokens(const P3D_token tokens[], size_t num_tokens) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::set_args
+//       Access: Public
+//  Description: Specifies the command-line arguments associated with
+//               the instance.
+////////////////////////////////////////////////////////////////////
+void P3DFileParams::
+set_args(int argc, const char *argv[]) {
+  _args.clear();
+
+  for (int i = 0; i < argc; ++i) {
+    const char *arg = argv[i];
+    if (arg == NULL) {
+      arg = "";
+    }
+    _args.push_back(arg);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DFileParams::lookup_token
 //     Function: P3DFileParams::lookup_token
 //       Access: Public
 //       Access: Public
@@ -136,10 +155,17 @@ make_xml() {
   for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
   for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
     const Token &token = (*ti);
     const Token &token = (*ti);
     TiXmlElement *xtoken = new TiXmlElement("token");
     TiXmlElement *xtoken = new TiXmlElement("token");
-    xtoken->SetAttribute("keyword", token._keyword.c_str());
-    xtoken->SetAttribute("value", token._value.c_str());
+    xtoken->SetAttribute("keyword", token._keyword);
+    xtoken->SetAttribute("value", token._value);
     xfparams->LinkEndChild(xtoken);
     xfparams->LinkEndChild(xtoken);
   }
   }
 
 
+  Args::const_iterator ai;
+  for (ai = _args.begin(); ai != _args.end(); ++ai) {
+    TiXmlElement *xarg = new TiXmlElement("arg");
+    xarg->SetAttribute("value", (*ai));
+    xfparams->LinkEndChild(xarg);
+  }
+
   return xfparams;
   return xfparams;
 }
 }

+ 3 - 0
direct/src/plugin/p3dFileParams.h

@@ -32,6 +32,7 @@ public:
 
 
   void set_p3d_filename(const string &p3d_filename);
   void set_p3d_filename(const string &p3d_filename);
   void set_tokens(const P3D_token tokens[], size_t num_tokens);
   void set_tokens(const P3D_token tokens[], size_t num_tokens);
+  void set_args(int argc, const char *argv[]);
 
 
   inline const string &get_p3d_filename() const;
   inline const string &get_p3d_filename() const;
   string lookup_token(const string &keyword) const;
   string lookup_token(const string &keyword) const;
@@ -46,9 +47,11 @@ private:
     string _value;
     string _value;
   };
   };
   typedef vector<Token> Tokens;
   typedef vector<Token> Tokens;
+  typedef vector<string> Args;
 
 
   string _p3d_filename;
   string _p3d_filename;
   Tokens _tokens;
   Tokens _tokens;
+  Args _args;
 };
 };
 
 
 #include "p3dFileParams.I"
 #include "p3dFileParams.I"

+ 2 - 1
direct/src/plugin/p3dInstance.cxx

@@ -51,7 +51,8 @@ typedef P3DSplashWindow SplashWindowType;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3DInstance::
 P3DInstance::
 P3DInstance(P3D_request_ready_func *func, 
 P3DInstance(P3D_request_ready_func *func, 
-            const P3D_token tokens[], size_t num_tokens, void *user_data) :
+            const P3D_token tokens[], size_t num_tokens, 
+            int argc, const char *argv[], void *user_data) :
   _func(func)
   _func(func)
 {
 {
   _browser_script_object = NULL;
   _browser_script_object = NULL;

+ 2 - 1
direct/src/plugin/p3dInstance.h

@@ -49,7 +49,8 @@ class P3DToplevelObject;
 class P3DInstance : public P3D_instance, public P3DReferenceCount {
 class P3DInstance : public P3D_instance, public P3DReferenceCount {
 public:
 public:
   P3DInstance(P3D_request_ready_func *func, 
   P3DInstance(P3D_request_ready_func *func, 
-              const P3D_token tokens[], size_t num_tokens, void *user_data);
+              const P3D_token tokens[], size_t num_tokens, 
+              int argc, const char *argv[], void *user_data);
   ~P3DInstance();
   ~P3DInstance();
 
 
   void set_p3d_url(const string &p3d_url);
   void set_p3d_url(const string &p3d_url);

+ 3 - 2
direct/src/plugin/p3dInstanceManager.cxx

@@ -207,8 +207,9 @@ read_contents_file(const string &contents_filename) {
 P3DInstance *P3DInstanceManager::
 P3DInstance *P3DInstanceManager::
 create_instance(P3D_request_ready_func *func, 
 create_instance(P3D_request_ready_func *func, 
                 const P3D_token tokens[], size_t num_tokens, 
                 const P3D_token tokens[], size_t num_tokens, 
-                void *user_data) {
-  P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, user_data);
+                int argc, const char *argv[], void *user_data) {
+  P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, argc, argv,
+                                      user_data);
   inst->ref();
   inst->ref();
   _instances.insert(inst);
   _instances.insert(inst);
 
 

+ 1 - 1
direct/src/plugin/p3dInstanceManager.h

@@ -55,7 +55,7 @@ public:
   P3DInstance *
   P3DInstance *
   create_instance(P3D_request_ready_func *func, 
   create_instance(P3D_request_ready_func *func, 
                   const P3D_token tokens[], size_t num_tokens, 
                   const P3D_token tokens[], size_t num_tokens, 
-                  void *user_data);
+                  int argc, const char *argv[], void *user_data);
 
 
   bool set_p3d_filename(P3DInstance *inst, bool is_local,
   bool set_p3d_filename(P3DInstance *inst, bool is_local,
                         const string &p3d_filename);
                         const string &p3d_filename);

+ 19 - 3
direct/src/plugin/p3dPythonRun.cxx

@@ -942,7 +942,6 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
   }
   }
 
 
   PyObject *token_list = PyList_New(0);
   PyObject *token_list = PyList_New(0);
-
   TiXmlElement *xtoken = xfparams->FirstChildElement("token");
   TiXmlElement *xtoken = xfparams->FirstChildElement("token");
   while (xtoken != NULL) {
   while (xtoken != NULL) {
     string keyword, value;
     string keyword, value;
@@ -963,11 +962,28 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
 
 
     xtoken = xtoken->NextSiblingElement("token");
     xtoken = xtoken->NextSiblingElement("token");
   }
   }
+
+  PyObject *arg_list = PyList_New(0);
+  TiXmlElement *xarg = xfparams->FirstChildElement("arg");
+  while (xarg != NULL) {
+    string value;
+    const char *value_c = xarg->Attribute("value");
+    if (value_c != NULL) {
+      value = value_c;
+    }
+
+    PyObject *str = Py_BuildValue("s", value.c_str());
+    PyList_Append(arg_list, str);
+    Py_DECREF(str);
+
+    xarg = xarg->NextSiblingElement("arg");
+  }
   
   
   PyObject *result = PyObject_CallMethod
   PyObject *result = PyObject_CallMethod
-    (_runner, (char *)"setP3DFilename", (char *)"sOi", p3d_filename.c_str(),
-     token_list, inst->get_instance_id());
+    (_runner, (char *)"setP3DFilename", (char *)"sOOi", p3d_filename.c_str(),
+     token_list, arg_list, inst->get_instance_id());
   Py_DECREF(token_list);
   Py_DECREF(token_list);
+  Py_DECREF(arg_list);
 
 
   if (result == NULL) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();

+ 3 - 2
direct/src/plugin/p3d_plugin.cxx

@@ -105,12 +105,13 @@ P3D_finalize() {
 P3D_instance *
 P3D_instance *
 P3D_new_instance(P3D_request_ready_func *func, 
 P3D_new_instance(P3D_request_ready_func *func, 
                  const P3D_token tokens[], size_t num_tokens,
                  const P3D_token tokens[], size_t num_tokens,
-                 void *user_data) {
+                 int argc, const char *argv[], void *user_data) {
   nout << "new_instance\n";
   nout << "new_instance\n";
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   ACQUIRE_LOCK(_api_lock);
   ACQUIRE_LOCK(_api_lock);
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
-  P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, user_data);
+  P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, 
+                                                  argc, argv, user_data);
   RELEASE_LOCK(_api_lock);
   RELEASE_LOCK(_api_lock);
   return result;
   return result;
 }
 }

+ 9 - 0
direct/src/plugin/p3d_plugin.h

@@ -224,6 +224,14 @@ typedef struct {
    passed to the application, who is free to decide how to interpret
    passed to the application, who is free to decide how to interpret
    them; they have no meaning at the system level.
    them; they have no meaning at the system level.
 
 
+   The argc/argv parameters are intended for when the plugin is
+   invoked from the command line; they should be filled a standard
+   C-style argc/argv parameter list, corresponding to the command-line
+   parameters passed to the application.  They may be 0 and NULL when
+   the plugin is invoked from the web.  As above, this array and its
+   string data will be copied into the core API's own internal
+   storage, and need not persist after this call.
+
    The user_data pointer is any arbitrary pointer value; it will be
    The user_data pointer is any arbitrary pointer value; it will be
    copied into the _user_data member of the new P3D_instance object.
    copied into the _user_data member of the new P3D_instance object.
    This pointer is intended for the host to use to store private data
    This pointer is intended for the host to use to store private data
@@ -234,6 +242,7 @@ typedef struct {
 typedef P3D_instance *
 typedef P3D_instance *
 P3D_new_instance_func(P3D_request_ready_func *func, 
 P3D_new_instance_func(P3D_request_ready_func *func, 
                       const P3D_token tokens[], size_t num_tokens,
                       const P3D_token tokens[], size_t num_tokens,
+                      int argc, const char *argv[],
                       void *user_data);
                       void *user_data);
 
 
 /* This function should be called at some point after
 /* This function should be called at some point after

+ 2 - 1
direct/src/plugin_npapi/ppInstance.cxx

@@ -957,7 +957,8 @@ create_instance() {
   if (!_tokens.empty()) {
   if (!_tokens.empty()) {
     tokens = &_tokens[0];
     tokens = &_tokens[0];
   }
   }
-  _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), this);
+  _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), 
+                               0, NULL, this);
 
 
   if (_p3d_inst != NULL) {
   if (_p3d_inst != NULL) {
     // Now get the browser's window object, to pass to the plugin.
     // Now get the browser's window object, to pass to the plugin.

+ 15 - 10
direct/src/plugin_standalone/panda3d.cxx

@@ -609,30 +609,35 @@ make_parent_window(P3D_window_handle &parent_window,
 //               play a particular .p3d file.
 //               play a particular .p3d file.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_instance *Panda3D::
 P3D_instance *Panda3D::
-create_instance(const string &arg, P3D_window_type window_type,
+create_instance(const string &p3d, P3D_window_type window_type,
                 int win_x, int win_y, int win_width, int win_height,
                 int win_x, int win_y, int win_width, int win_height,
                 P3D_window_handle parent_window, char **args, int num_args) {
                 P3D_window_handle parent_window, char **args, int num_args) {
-  P3D_token tokens[] = {
-    { "src", arg.c_str() },
-  };
-  int num_tokens = sizeof(tokens) / sizeof(P3D_token);
-
   // If the supplied parameter name is a real file, pass it in on the
   // If the supplied parameter name is a real file, pass it in on the
   // parameter list.  Otherwise, assume it's a URL and let the plugin
   // parameter list.  Otherwise, assume it's a URL and let the plugin
   // download it.
   // download it.
-  Filename p3d_filename = Filename::from_os_specific(arg);
-  string os_p3d_filename;
+  Filename p3d_filename = Filename::from_os_specific(p3d);
+  string os_p3d_filename = p3d;
+  bool is_local = false;
   if (p3d_filename.exists()) {
   if (p3d_filename.exists()) {
     p3d_filename.make_absolute();
     p3d_filename.make_absolute();
     os_p3d_filename = p3d_filename.to_os_specific();
     os_p3d_filename = p3d_filename.to_os_specific();
+    is_local = true;
   } 
   } 
 
 
-  P3D_instance *inst = P3D_new_instance(NULL, tokens, num_tokens, NULL);
+  // Build up the argument list, beginning with the p3d_filename.
+  pvector<const char *> argv;
+  argv.push_back(os_p3d_filename.c_str());
+  for (int i = 0; i < num_args; ++i) {
+    argv.push_back(args[i]);
+  }
+
+  P3D_instance *inst = P3D_new_instance(NULL, NULL, 0,
+                                        argv.size(), &argv[0], NULL);
 
 
   if (inst != NULL) {
   if (inst != NULL) {
     P3D_instance_setup_window
     P3D_instance_setup_window
       (inst, window_type, win_x, win_y, win_width, win_height, parent_window);
       (inst, window_type, win_x, win_y, win_width, win_height, parent_window);
-    P3D_instance_start(inst, true, os_p3d_filename.c_str());
+    P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
   }
   }
 
 
   return inst;
   return inst;

+ 5 - 5
direct/src/plugin_standalone/panda3d.h

@@ -55,11 +55,11 @@ private:
   void make_parent_window(P3D_window_handle &parent_window, 
   void make_parent_window(P3D_window_handle &parent_window, 
                           int win_width, int win_height);
                           int win_width, int win_height);
 
 
-  P3D_instance *create_instance(const string &arg, P3D_window_type window_type,
-                                int win_x, int win_y, int win_width, 
-                                int win_height,
-                                P3D_window_handle parent_window,
-                                char **args, int num_args);
+  P3D_instance *
+  create_instance(const string &p3d, P3D_window_type window_type,
+                  int win_x, int win_y, int win_width, int win_height,
+                  P3D_window_handle parent_window,
+                  char **args, int num_args);
   void delete_instance(P3D_instance *instance);
   void delete_instance(P3D_instance *instance);
 
 
   void usage();
   void usage();

+ 7 - 3
direct/src/showutil/FreezeTool.py

@@ -371,6 +371,9 @@ class Freezer:
             self.moduleName = moduleName
             self.moduleName = moduleName
             self.filename = filename
             self.filename = filename
 
 
+        def __repr__(self):
+            return 'ModuleDef(%s, %s, %s)' % (repr(self.token), repr(self.moduleName), repr(self.filename))
+
     def __init__(self, previous = None, debugLevel = 0):
     def __init__(self, previous = None, debugLevel = 0):
         # Normally, we are freezing for our own platform.  Change this
         # Normally, we are freezing for our own platform.  Change this
         # if untrue.
         # if untrue.
@@ -646,7 +649,6 @@ class Freezer:
                 parentName, baseName = newName.rsplit('.', 1)
                 parentName, baseName = newName.rsplit('.', 1)
                 if parentName in excludeDict:
                 if parentName in excludeDict:
                     token = excludeDict[parentName]
                     token = excludeDict[parentName]
-            
             if token == self.MTInclude:
             if token == self.MTInclude:
                 includes.append(mdef)
                 includes.append(mdef)
             elif token == self.MTAuto or token == self.MTGuess:
             elif token == self.MTAuto or token == self.MTGuess:
@@ -772,10 +774,12 @@ class Freezer:
                     # Previously exported.
                     # Previously exported.
                     pass
                     pass
                 else:
                 else:
-                    if newName in self.mf.modules or \
-                       newName in startupModules or \
+                    if mdef.moduleName in self.mf.modules or \
+                       mdef.moduleName in startupModules or \
                        mdef.filename:
                        mdef.filename:
                         moduleDefs.append((newName, mdef))
                         moduleDefs.append((newName, mdef))
+                    else:
+                        print "Unknown module %s" % (mdef.moduleName)
             elif token == self.MTForbid:
             elif token == self.MTForbid:
                 if not prev or prev.token != self.MTForbid:
                 if not prev or prev.token != self.MTForbid:
                     moduleDefs.append((newName, mdef))
                     moduleDefs.append((newName, mdef))

+ 26 - 12
direct/src/showutil/Packager.py

@@ -194,8 +194,9 @@ class Packager:
                 message = 'No main_module specified for application %s' % (self.packageName)
                 message = 'No main_module specified for application %s' % (self.packageName)
                 raise PackagerError, message
                 raise PackagerError, message
             if self.mainModule:
             if self.mainModule:
-                if self.mainModule not in self.freezer.modules:
-                    self.freezer.addModule(self.mainModule)
+                moduleName, newName = self.mainModule
+                if newName not in self.freezer.modules:
+                    self.freezer.addModule(moduleName, newName = newName)
 
 
             # Pick up any unfrozen Python files.
             # Pick up any unfrozen Python files.
             self.freezer.done()
             self.freezer.done()
@@ -601,7 +602,7 @@ class Packager:
             if self.version:
             if self.version:
                 xpackage.SetAttribute('version', self.version)
                 xpackage.SetAttribute('version', self.version)
 
 
-            xpackage.SetAttribute('main_module', self.mainModule)
+            xpackage.SetAttribute('main_module', self.mainModule[1])
 
 
             for variable, value in self.configs.items():
             for variable, value in self.configs.items():
                 if isinstance(value, types.UnicodeType):
                 if isinstance(value, types.UnicodeType):
@@ -1463,15 +1464,19 @@ class Packager:
 
 
     def parse_main_module(self, words):
     def parse_main_module(self, words):
         """
         """
-        main_module moduleName
+        main_module moduleName [newName]
         """
         """
+        newName = None
 
 
         try:
         try:
-            command, moduleName = words
+            if len(words) == 2:
+                command, moduleName = words
+            else:
+                command, moduleName, newName = words
         except ValueError:
         except ValueError:
             raise ArgumentError
             raise ArgumentError
 
 
-        self.mainModule(moduleName)
+        self.mainModule(moduleName, newName = newName)
 
 
     def parse_freeze_exe(self, words):
     def parse_freeze_exe(self, words):
         """
         """
@@ -1879,11 +1884,13 @@ class Packager:
         if not self.currentPackage:
         if not self.currentPackage:
             raise OutsideOfPackageError
             raise OutsideOfPackageError
 
 
-        if self.currentPackage.mainModule and self.currentPackage.mainModule != moduleName:
+        if self.currentPackage.mainModule and self.currentPackage.mainModule[0] != moduleName:
             self.notify.warning("Replacing main_module %s with %s" % (
             self.notify.warning("Replacing main_module %s with %s" % (
-                self.currentPackage.mainModule, moduleName))
+                self.currentPackage.mainModule[0], moduleName))
 
 
-        self.currentPackage.mainModule = moduleName
+        if not newName:
+            newName = moduleName
+        self.currentPackage.mainModule = (moduleName, newName)
 
 
     def freeze(self, filename, compileToExe = False):
     def freeze(self, filename, compileToExe = False):
         """ Freezes all of the current Python code into either an
         """ Freezes all of the current Python code into either an
@@ -1906,10 +1913,17 @@ class Packager:
             raise PackagerError, message
             raise PackagerError, message
 
 
         if package.mainModule:
         if package.mainModule:
-            if package.mainModule not in freezer.modules:
-                freezer.addModule(package.mainModule, newName = '__main__')
+            moduleName, newName = package.mainModule
+            if compileToExe:
+                # If we're producing an exe, the main module must
+                # be called "__main__".
+                newName = '__main__'
+                package.mainModule = (moduleName, newName)
+
+            if newName not in freezer.modules:
+                freezer.addModule(moduleName, newName = newName)
             else:
             else:
-                freezer.modules['__main__'] = freezer.modules[package.mainModule]
+                freezer.modules[newName] = freezer.modules[moduleName]
         freezer.done(compileToExe = compileToExe)
         freezer.done(compileToExe = compileToExe)
 
 
         if not package.dryRun:
         if not package.dryRun:

+ 6 - 0
direct/src/showutil/packp3d.py

@@ -128,6 +128,12 @@ def makePackedApp(args):
         
         
     packager.endPackage(appBase, p3dApplication = True)
     packager.endPackage(appBase, p3dApplication = True)
 
 
+def main(appRunner):
+    """ This function is called when this module is invoked as
+    packp3d.p3d. """
+
+    makePackedApp(appRunner.argv[1:])
+
 if __name__ == '__main__':
 if __name__ == '__main__':
     try:
     try:
         makePackedApp(sys.argv[1:])
         makePackedApp(sys.argv[1:])

+ 4 - 3
direct/src/showutil/runp3d.py

@@ -223,12 +223,12 @@ class AppRunner(DirectObject):
             v = VFSImporter.VFSImporter(MultifileRoot)
             v = VFSImporter.VFSImporter(MultifileRoot)
             loader = v.find_module(moduleName)
             loader = v.find_module(moduleName)
             if not loader:
             if not loader:
-                message = "No %s.py found in application." % (mainName)
+                message = "No %s found in application." % (moduleName)
                 raise StandardError, message
                 raise StandardError, message
             
             
             main = loader.load_module(moduleName)
             main = loader.load_module(moduleName)
             if hasattr(main, 'main') and callable(main.main):
             if hasattr(main, 'main') and callable(main.main):
-                main.main()
+                main.main(self)
 
 
     def getPandaScriptObject(self):
     def getPandaScriptObject(self):
         """ Called by the browser to query the Panda instance's
         """ Called by the browser to query the Panda instance's
@@ -251,7 +251,7 @@ class AppRunner(DirectObject):
                                needsResponse = False)
                                needsResponse = False)
         self.deferredEvals = []
         self.deferredEvals = []
 
 
-    def setP3DFilename(self, p3dFilename, tokens = [],
+    def setP3DFilename(self, p3dFilename, tokens = [], argv = [],
                        instanceId = None):
                        instanceId = None):
         # One day we will have support for multiple instances within a
         # One day we will have support for multiple instances within a
         # Python session.  Against that day, we save the instance ID
         # Python session.  Against that day, we save the instance ID
@@ -260,6 +260,7 @@ class AppRunner(DirectObject):
 
 
         self.tokens = tokens
         self.tokens = tokens
         self.tokenDict = dict(tokens)
         self.tokenDict = dict(tokens)
+        self.argv = argv
 
 
         # Tell the browser that Python is up and running, and ready to
         # Tell the browser that Python is up and running, and ready to
         # respond to queries.
         # respond to queries.