FlightGear next
NasalSys.hxx
Go to the documentation of this file.
1// NasalSys.hxx -
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <map>
7#include <memory>
8
9#include <simgear/math/SGMath.hxx> // keep before any cppbind include to enable
10 // SGVec2<T> conversion.
11#include <simgear/misc/sg_dir.hxx>
12#include <simgear/misc/sg_path.hxx>
13#include <simgear/nasal/cppbind/NasalHash.hxx>
14#include <simgear/nasal/nasal.h>
15#include <simgear/props/props.hxx>
16#include <simgear/structure/subsystem_mgr.hxx>
17#include <simgear/threads/SGQueue.hxx>
18
19
20class FGNasalScript;
21class FGNasalListener;
22class SGCondition;
24class TimerObj;
25class NasalSysPrivate;
26struct NasalTimer;
28
29namespace simgear { class BufferedLogCallback; }
30
31SGPropertyNode* ghostToPropNode(naRef ref);
32
33class FGNasalSys : public SGSubsystem
34{
35public:
36 FGNasalSys();
37 virtual ~FGNasalSys();
38
39 // Subsystem API.
40 void init() override;
41 void shutdown() override;
42 void update(double dt) override;
43
44 // Subsystem identification.
45 static const char* staticSubsystemClassId() { return "nasal"; }
46
47 // Loads a nasal script from an external file and inserts it as a
48 // global module of the specified name.
49 bool loadModule(SGPath file, const char* moduleName);
50
51 // Simple hook to run arbitrary source code. Returns a bool to
52 // indicate successful execution. Does *not* return any Nasal
53 // values, because handling garbage-collected objects from C space
54 // is deep voodoo and violates the "simple hook" idea.
55 bool parseAndRun(const std::string& source);
56
57 bool parseAndRunWithOutput(const std::string& source,
58 std::string& output,
59 std::string& errors);
60
61 // Implementation of the settimer extension function
62 void setTimer(naContext c, int argc, naRef* args);
63
64 // Implementation of the setlistener extension function
65 naRef setListener(naContext c, int argc, naRef* args);
66 naRef removeListener(naContext c, int argc, naRef* args);
67
68 // Returns a ghost wrapper for the current _cmdArg
69 naRef cmdArgGhost();
70
71 void setCmdArg(SGPropertyNode* aNode);
72
77 naRef wrappedPropsNode(SGPropertyNode* aProps);
78
79 // Callbacks for command and timer bindings
80 virtual bool handleCommand( const char* moduleName,
81 const char* fileName,
82 const char* src,
83 const SGPropertyNode* arg = 0,
84 SGPropertyNode* root = 0);
85 virtual bool handleCommand(const SGPropertyNode* arg, SGPropertyNode *root);
86
87 bool createModule(const char* moduleName, const char* fileName,
88 const char* src, int len, const SGPropertyNode* cmdarg=0,
89 int argc=0, naRef*args=0);
90
91 void deleteModule(const char* moduleName);
92
93 naRef getModule(const std::string& moduleName) const;
94 naRef getModule(const char* moduleName);
95
96 bool addCommand(naRef func, const std::string& name);
97 bool removeCommand(const std::string& name);
98
102 void hashset(naRef hash, const char* key, naRef val);
103
107 void globalsSet(const char* key, naRef val);
108
109 naRef call(naRef code, int argc, naRef* args, naRef locals);
110 naRef callWithContext(naContext ctx, naRef code, int argc, naRef* args, naRef locals);
111
112 naRef callMethod(naRef code, naRef self, int argc, naRef* args, naRef locals);
113 naRef callMethodWithContext(naContext ctx, naRef code, naRef self, int argc, naRef* args, naRef locals);
114
115 naRef propNodeGhost(SGPropertyNode* handle);
116
119
120 // can't call this 'globals' due to naming clash
121 naRef nasalGlobals() const;
122
123 nasal::Hash getGlobals() const;
124
125 // This mechanism is here to allow naRefs to be passed to
126 // locations "outside" the interpreter. Normally, such a
127 // reference would be garbage collected unexpectedly. By passing
128 // it to gcSave and getting a key/handle, it can be cached in a
129 // globals.__gcsave hash. Be sure to release it with gcRelease
130 // when done.
131 int gcSave(naRef r);
132 void gcRelease(int key);
133
147
150 simgear::BufferedLogCallback* log() const;
151
153
159 static naRef getPropertyValue(naContext c, SGPropertyNode* node);
160
161 bool reloadModuleFromFile(const std::string& moduleName);
162
163 // private methods: the class has a lot of friends to allow particular classes
164 // to do book-keeping, this is not ideal.
165private:
166 friend FGNasalModuleListener;
167
168 void initLogLevelConstants();
169
170 void loadPropertyScripts();
171 void loadPropertyScripts(SGPropertyNode* n);
172 void loadScriptDirectory(simgear::Dir nasalDir, SGPropertyNode* loadorder,
173 bool excludeUnspecifiedInLoadOrder);
174 void addModule(std::string moduleName, simgear::PathList scripts);
175 static void logError(naContext);
176 naRef parse(naContext ctx, const char* filename, const char* buf, int len,
177 std::string& errors);
178 naRef genPropsModule();
179
180 friend TimerObj;
181
182 void addPersistentTimer(TimerObj* pto);
183 void removePersistentTimer(TimerObj* obj);
184
185 // NasalTimer is a friend to invoke handleTimer and do the actual
186 // dispatch of the settimer-d callback
187 friend NasalTimer;
188
189 void handleTimer(NasalTimer* t);
190
191 static void logNasalStack(naContext context, string_list& stack);
192
193 // members: should only be the d-ptr
194private:
195 std::unique_ptr<NasalSysPrivate> d;
196};
SGPropertyNode * ghostToPropNode(naRef ref)
Nasal model data container.
simgear::BufferedLogCallback * log() const
retrive the associated log object, for displaying log output somewhere (a UI, presumably)
bool removeCommand(const std::string &name)
naRef removeListener(naContext c, int argc, naRef *args)
void setCmdArg(SGPropertyNode *aNode)
void update(double dt) override
bool createModule(const char *moduleName, const char *fileName, const char *src, int len, const SGPropertyNode *cmdarg=0, int argc=0, naRef *args=0)
void setTimer(naContext c, int argc, naRef *args)
void registerToUnload(FGNasalModelData *data)
naRef cmdArgGhost()
naRef call(naRef code, int argc, naRef *args, naRef locals)
Definition NasalSys.cxx:314
naRef callMethod(naRef code, naRef self, int argc, naRef *args, naRef locals)
Definition NasalSys.cxx:331
static naRef getPropertyValue(naContext c, SGPropertyNode *node)
Convert the value of an SGPropertyNode to its Nasal representation.
void deleteModule(const char *moduleName)
static const char * staticSubsystemClassId()
Definition NasalSys.hxx:45
int gcSave(naRef r)
void registerToLoad(FGNasalModelData *data)
void hashset(naRef hash, const char *key, naRef val)
Set member of specified hash to given value.
Definition NasalSys.cxx:302
naRef callWithContext(naContext ctx, naRef code, int argc, naRef *args, naRef locals)
Definition NasalSys.cxx:319
bool addCommand(naRef func, const std::string &name)
void init() override
bool reloadModuleFromFile(const std::string &moduleName)
void shutdown() override
naRef nasalGlobals() const
virtual ~FGNasalSys()
Definition NasalSys.cxx:354
naRef callMethodWithContext(naContext ctx, naRef code, naRef self, int argc, naRef *args, naRef locals)
Definition NasalSys.cxx:341
naRef setListener(naContext c, int argc, naRef *args)
string_list getAndClearErrorList()
naRef getModule(const std::string &moduleName) const
void gcRelease(int key)
bool checkIOrules()
Check if IOrules correctly work to limit access from Nasal scripts to the file system.
nasal::Hash getGlobals() const
virtual bool handleCommand(const char *moduleName, const char *fileName, const char *src, const SGPropertyNode *arg=0, SGPropertyNode *root=0)
void globalsSet(const char *key, naRef val)
Set member of globals hash to given value.
Definition NasalSys.cxx:309
bool parseAndRunWithOutput(const std::string &source, std::string &output, std::string &errors)
Definition NasalSys.cxx:364
naRef propNodeGhost(SGPropertyNode *handle)
naRef wrappedPropsNode(SGPropertyNode *aProps)
create Nasal props.Node for an SGPropertyNode* This is the actual ghost, wrapped in a Nasal sugar cla...
bool parseAndRun(const std::string &source)
Definition NasalSys.cxx:388
bool loadModule(SGPath file, const char *moduleName)
const char * name
std::vector< std::string > string_list
Definition globals.hxx:36
naCFunction func