4 #include <simgear/misc/sg_path.hxx>
5 #include <simgear/structure/subsystem_mgr.hxx>
6 #include <simgear/nasal/nasal.h>
13 class FGNasalListener;
15 class FGNasalSys : public SGSubsystem
19 virtual ~FGNasalSys();
21 virtual void update(double dt) { /* noop */ }
23 // Loads a nasal script from an external file and inserts it as a
24 // global module of the specified name.
25 void loadModule(SGPath file, const char* moduleName);
27 // Simple hook to run arbitrary source code. Returns a bool to
28 // indicate successful execution. Does *not* return any Nasal
29 // values, because handling garbage-collected objects from C space
30 // is deep voodoo and violates the "simple hook" idea.
31 bool parseAndRun(const char* sourceCode);
33 // Slightly more complicated hook to get a handle to a precompiled
34 // Nasal script that can be invoked via a call() method. The
35 // caller is expected to delete the FGNasalScript returned from
36 // this function. The "name" argument specifies the "file name"
37 // for the source code that will be printed in Nasal stack traces
39 FGNasalScript* parseScript(const char* src, const char* name=0);
41 // Implementation of the settimer extension function
42 void setTimer(int argc, naRef* args);
44 // Implementation of the setlistener extension function
45 naRef setListener(int argc, naRef* args);
46 naRef removeListener(int argc, naRef* args);
48 // Returns a ghost wrapper for the current _cmdArg
51 // Callbacks for command and timer bindings
52 virtual bool handleCommand(const SGPropertyNode* arg);
54 void createModule(const char* moduleName, const char* fileName,
55 const char* src, int len);
58 friend class FGNasalScript;
59 friend class FGNasalListener;
62 // FGTimer subclass for handling Nasal timer callbacks.
63 // See the implementation of the settimer() extension function for
67 virtual void timerExpired();
74 map<int, FGNasalListener *> _listener;
75 static int _listenerId;
77 void loadPropertyScripts();
78 void hashset(naRef hash, const char* key, naRef val);
79 void logError(naContext);
80 naRef parse(const char* filename, const char* buf, int len);
81 naRef genPropsModule();
82 naRef propNodeGhost(SGPropertyNode* handle);
84 // This mechanism is here to allow naRefs to be passed to
85 // locations "outside" the interpreter. Normally, such a
86 // reference would be garbage collected unexpectedly. By passing
87 // it to gcSave and getting a key/handle, it can be cached in a
88 // globals.__gcsave hash. Be sure to release it with gcRelease
91 void gcRelease(int key);
96 SGPropertyNode* _cmdArg;
101 public: void handleTimer(NasalTimer* t);
104 class FGNasalScript {
106 ~FGNasalScript() { _nas->gcRelease(_gcKey); }
110 naCall(_nas->_context, _code, 0, &n, naNil(), naNil());
111 return naGetError(_nas->_context) == 0;
115 friend class FGNasalSys;
121 class FGNasalListener : public SGPropertyChangeListener {
123 FGNasalListener(SGPropertyNode_ptr node, naRef handler,
124 FGNasalSys* nasal, int key)
125 : _node(node), _handler(handler), _gcKey(key), _nas(nasal) {}
128 _nas->gcRelease(_gcKey);
131 void valueChanged(SGPropertyNode* node) {
132 _nas->_cmdArg = node;
133 naContext c = naNewContext();
135 naCall(c, _handler, 0, 0, naNil(), naNil());
143 friend class FGNasalSys;
144 SGPropertyNode_ptr _node;
150 #endif // __NASALSYS_HXX