// is the utility function that walks the property tree.
// Future enhancement: support integer arguments to specify array
// elements.
-static SGPropertyNode* findnode(naContext c, naRef vec, int len)
+static SGPropertyNode* findnode(naContext c, naRef* vec, int len)
{
SGPropertyNode* p = globals->get_props();
for(int i=0; i<len; i++) {
- naRef a = naVec_get(vec, i);
+ naRef a = vec[i];
if(!naIsString(a)) return 0;
p = p->getNode(naStr_data(a));
if(p == 0) return 0;
// getprop() extension function. Concatenates its string arguments as
// property names and returns the value of the specified property. Or
// nil if it doesn't exist.
-static naRef f_getprop(naContext c, naRef args)
+static naRef f_getprop(naContext c, naRef me, int argc, naRef* args)
{
- const SGPropertyNode* p = findnode(c, args, naVec_size(args));
+ const SGPropertyNode* p = findnode(c, args, argc);
if(!p) return naNil();
switch(p->getType()) {
// setprop() extension function. Concatenates its string arguments as
// property names and sets the value of the specified property to the
// final argument.
-static naRef f_setprop(naContext c, naRef args)
+static naRef f_setprop(naContext c, naRef me, int argc, naRef* args)
{
#define BUFLEN 1024
- int argc = naVec_size(args);
char buf[BUFLEN + 1];
buf[BUFLEN] = 0;
char* p = buf;
int buflen = BUFLEN;
for(int i=0; i<argc-1; i++) {
- naRef s = naStringValue(c, naVec_get(args, i));
+ naRef s = naStringValue(c, args[i]);
if(naIsNil(s)) return naNil();
strncpy(p, naStr_data(s), buflen);
p += naStr_len(s);
}
SGPropertyNode* props = globals->get_props();
- naRef val = naVec_get(args, argc-1);
+ naRef val = args[argc-1];
if(naIsString(val)) props->setStringValue(buf, naStr_data(val));
else props->setDoubleValue(buf, naNumValue(val).num);
return naNil();
// print() extension function. Concatenates and prints its arguments
// to the FlightGear log. Uses the highest log level (SG_ALERT), to
// make sure it appears. Is there better way to do this?
-static naRef f_print(naContext c, naRef args)
+static naRef f_print(naContext c, naRef me, int argc, naRef* args)
{
#define BUFLEN 1024
char buf[BUFLEN + 1];
buf[0] = 0; // Zero-length in case there are no arguments
char* p = buf;
int buflen = BUFLEN;
- int n = naVec_size(args);
+ int n = argc;
for(int i=0; i<n; i++) {
- naRef s = naStringValue(c, naVec_get(args, i));
+ naRef s = naStringValue(c, args[i]);
if(naIsNil(s)) continue;
strncpy(p, naStr_data(s), buflen);
p += naStr_len(s);
// fgcommand() extension function. Executes a named command via the
// FlightGear command manager. Takes a single property node name as
// an argument.
-static naRef f_fgcommand(naContext c, naRef args)
+static naRef f_fgcommand(naContext c, naRef me, int argc, naRef* args)
{
- naRef cmd = naVec_get(args, 0);
- naRef props = naVec_get(args, 1);
- if(!naIsString(cmd) || !naIsGhost(props)) return naNil();
+ if(argc < 2 || !naIsString(args[0]) || !naIsGhost(args[1]))
+ naRuntimeError(c, "bad arguments to fgcommand()");
+ naRef cmd = args[0], props = args[1];
SGPropertyNode_ptr* node = (SGPropertyNode_ptr*)naGhost_ptr(props);
globals->get_commands()->execute(naStr_data(cmd), *node);
return naNil();
// settimer(func, dt, simtime) extension function. Falls through to
// FGNasalSys::setTimer(). See there for docs.
-static naRef f_settimer(naContext c, naRef args)
+static naRef f_settimer(naContext c, naRef me, int argc, naRef* args)
{
FGNasalSys* nasal = (FGNasalSys*)globals->get_subsystem("nasal");
- nasal->setTimer(args);
+ nasal->setTimer(argc, args);
return naNil();
}
// Returns a ghost handle to the argument to the currently executing
// command
-static naRef f_cmdarg(naContext c, naRef args)
+static naRef f_cmdarg(naContext c, naRef me, int argc, naRef* args)
{
FGNasalSys* nasal = (FGNasalSys*)globals->get_subsystem("nasal");
return nasal->cmdArgGhost();
// ghost (SGPropertyNode_ptr*) or a string (global property path) to
// interpolate. The second argument is a vector of pairs of
// value/delta numbers.
-static naRef f_interpolate(naContext c, naRef args)
+static naRef f_interpolate(naContext c, naRef me, int argc, naRef* args)
{
SGPropertyNode* node;
- naRef prop = naVec_get(args, 0);
+ naRef prop = argc > 0 ? args[0] : naNil();
if(naIsString(prop)) node = fgGetNode(naStr_data(prop), true);
else if(naIsGhost(prop)) node = *(SGPropertyNode_ptr*)naGhost_ptr(prop);
else return naNil();
- naRef curve = naVec_get(args, 1);
+ naRef curve = argc > 1 ? args[1] : naNil();
if(!naIsVector(curve)) return naNil();
int nPoints = naVec_size(curve) / 2;
double* values = new double[nPoints];
return naNil();
}
-static naRef f_rand(naContext c, naRef args)
+// This is a better RNG than the one in the default Nasal distribution
+// (which is based on the C library rand() implementation). It will
+// override.
+static naRef f_rand(naContext c, naRef me, int argc, naRef* args)
{
return naNum(sg_random());
}
// "saved" somehow lest they be inadvertently cleaned. In this case,
// they are inserted into a globals.__gcsave hash and removed on
// expiration.
-void FGNasalSys::setTimer(naRef args)
+void FGNasalSys::setTimer(int argc, naRef* args)
{
// Extract the handler, delta, and simtime arguments:
- naRef handler = naVec_get(args, 0);
+ naRef handler = argc > 0 ? args[0] : naNil();
if(!(naIsCode(handler) || naIsCCode(handler) || naIsFunc(handler)))
return;
- naRef delta = naNumValue(naVec_get(args, 1));
+ naRef delta = argc > 1 ? args[1] : naNil();
if(naIsNil(delta)) return;
- bool simtime = naTrue(naVec_get(args, 2)) ? true : false;
+ bool simtime = (argc > 2 && naTrue(args[2])) ? true : false;
// Generate and register a C++ timer handler
NasalTimer* t = new NasalTimer;
// array. This allows the Nasal handlers to do things like:
// Node.getChild = func { _getChild(me.ghost, arg) }
//
-#define NODEARG() \
- naRef ghost = naVec_get(args, 0); \
- SGPropertyNode_ptr* node = (SGPropertyNode_ptr*)naGhost_ptr(ghost); \
- if(!node || naGhost_type(ghost) != &PropNodeGhostType) \
- return naNil(); \
- if(naVec_size(args) > 1) { \
- args = naVec_get(args, 1); \
- if(!naIsVector(args)) return naNil(); \
- } else { args = naNil(); }
-
-static naRef f_getType(naContext c, naRef args)
+#define NODEARG() \
+ if(argc < 2 || !naIsGhost(args[0]) || \
+ naGhost_type(args[0]) != &PropNodeGhostType) \
+ naRuntimeError(c, "bad argument to props function"); \
+ SGPropertyNode_ptr* node = (SGPropertyNode_ptr*)naGhost_ptr(args[0]); \
+ naRef argv = args[1]
+
+static naRef f_getType(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
char* t = "unknown";
return NASTR(t);
}
-static naRef f_getName(naContext c, naRef args)
+static naRef f_getName(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
return NASTR((*node)->getName());
}
-static naRef f_getIndex(naContext c, naRef args)
+static naRef f_getIndex(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
return naNum((*node)->getIndex());
}
-static naRef f_getValue(naContext c, naRef args)
+static naRef f_getValue(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
switch((*node)->getType()) {
return naNil();
}
-static naRef f_setValue(naContext c, naRef args)
+static naRef f_setValue(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- naRef val = naVec_get(args, 0);
+ naRef val = naVec_get(argv, 0);
if(naIsString(val)) (*node)->setStringValue(naStr_data(val));
else (*node)->setDoubleValue(naNumValue(val).num);
return naNil();
}
-static naRef f_setIntValue(naContext c, naRef args)
+static naRef f_setIntValue(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
// Original code:
- // int iv = (int)naNumValue(naVec_get(args, 0)).num;
+ // int iv = (int)naNumValue(naVec_get(argv, 0)).num;
// Junk to pacify the gcc-2.95.3 optimizer:
- naRef tmp0 = naVec_get(args, 0);
+ naRef tmp0 = naVec_get(argv, 0);
naRef tmp1 = naNumValue(tmp0);
double tmp2 = tmp1.num;
int iv = (int)tmp2;
return naNil();
}
-static naRef f_setBoolValue(naContext c, naRef args)
+static naRef f_setBoolValue(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- naRef val = naVec_get(args, 0);
+ naRef val = naVec_get(argv, 0);
(*node)->setBoolValue(naTrue(val) ? true : false);
return naNil();
}
-static naRef f_setDoubleValue(naContext c, naRef args)
+static naRef f_setDoubleValue(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- (*node)->setDoubleValue(naNumValue(naVec_get(args, 0)).num);
+ (*node)->setDoubleValue(naNumValue(naVec_get(argv, 0)).num);
return naNil();
}
-static naRef f_getParent(naContext c, naRef args)
+static naRef f_getParent(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
SGPropertyNode* n = (*node)->getParent();
return propNodeGhostCreate(c, n);
}
-static naRef f_getChild(naContext c, naRef args)
+static naRef f_getChild(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- naRef child = naVec_get(args, 0);
+ naRef child = naVec_get(argv, 0);
if(!naIsString(child)) return naNil();
- naRef idx = naNumValue(naVec_get(args, 1));
+ naRef idx = naNumValue(naVec_get(argv, 1));
SGPropertyNode* n;
if(naIsNil(idx) || !naIsNum(idx)) {
n = (*node)->getChild(naStr_data(child));
return propNodeGhostCreate(c, n);
}
-static naRef f_getChildren(naContext c, naRef args)
+static naRef f_getChildren(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
naRef result = naNewVector(c);
- if(naIsNil(args) || naVec_size(args) == 0) {
+ if(naIsNil(argv) || naVec_size(argv) == 0) {
// Get all children
for(int i=0; i<(*node)->nChildren(); i++)
naVec_append(result, propNodeGhostCreate(c, (*node)->getChild(i)));
} else {
// Get all children of a specified name
- naRef name = naVec_get(args, 0);
+ naRef name = naVec_get(argv, 0);
if(!naIsString(name)) return naNil();
vector<SGPropertyNode_ptr> children
= (*node)->getChildren(naStr_data(name));
return result;
}
-static naRef f_removeChild(naContext c, naRef args)
+static naRef f_removeChild(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- naRef child = naVec_get(args, 0);
- naRef index = naVec_get(args, 1);
+ naRef child = naVec_get(argv, 0);
+ naRef index = naVec_get(argv, 1);
if(!naIsString(child) || !naIsNum(index)) return naNil();
(*node)->removeChild(naStr_data(child), (int)index.num);
return naNil();
}
-static naRef f_getNode(naContext c, naRef args)
+static naRef f_getNode(naContext c, naRef me, int argc, naRef* args)
{
NODEARG();
- naRef path = naVec_get(args, 0);
- bool create = naTrue(naVec_get(args, 1));
+ naRef path = naVec_get(argv, 0);
+ bool create = naTrue(naVec_get(argv, 1));
if(!naIsString(path)) return naNil();
SGPropertyNode* n = (*node)->getNode(naStr_data(path), create);
return propNodeGhostCreate(c, n);
}
-static naRef f_new(naContext c, naRef args)
+static naRef f_new(naContext c, naRef me, int argc, naRef* args)
{
return propNodeGhostCreate(c, new SGPropertyNode());
}
-static naRef f_globals(naContext c, naRef args)
+static naRef f_globals(naContext c, naRef me, int argc, naRef* args)
{
return propNodeGhostCreate(c, globals->get_props());
}