Files
simgear/simgear/nasal/misc.c
T
andy b05e32fa8c Sync with Nasal CVS (soon to become Nasal 1.1). Notable new features:
Nasal now supports calls to "subcontexts" and errors can be thrown
across them, leading to complete stack traces when call() is used,
instead of the truncated ones we now see.

Vectors can now be concatenated using the ~ operator that used to work
only for strings.

Better runtime error messages in general due to a fancier
naRuntimeError() implementation

A big data size shrink on 64 bit systems; the size of a naRef dropped
by a factor of two.

"Braceless code blocks" have been added to the parser, so you can
write expressions like "if(a) b();" just like in C.  Note that there's
still a parser bug in there that fails when you nest a braced block
within a braceless one.

Character constants that appear in Nasal source code can now be
literal multibyte UTF8 characters (this was always supported for
string literals, but character constants were forced to be a single
byte).

New modules: "bits", "thread", "utf8" and (gulp...) "io".  The bits
library might be useful to FlightGear, the utf8 one probably not as
Plib does not support wide character text rendering.  The thread
library will work fine for spawning threads to do Nasal stuff, but
obviously contact with the rest of FlightGear must be
hand-synchronized as FlightGear isn't threadsafe.  The io library is
no doubt the most useful, as it exposes all the basic stdio.h
facilities; it's also frighteningly dangerous when combined with
networked code...
2007-03-29 18:50:12 +00:00

243 lines
5.5 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "nasal.h"
#include "code.h"
static void* chkptr(void* p)
{
naRef foo;
SETPTR(foo, p);
if(PTR(foo).obj != p) *(int*)0=0;
return p;
}
void naFree(void* m) { free(m); }
void* naAlloc(int n) { return chkptr(malloc(n)); }
void* naRealloc(void* b, int n) { return chkptr(realloc(b, n)); }
void naBZero(void* m, int n) { memset(m, 0, n); }
void naTempSave(naContext c, naRef r)
{
int i;
if(!IS_OBJ(r)) return;
if(c->ntemps >= c->tempsz) {
struct naObj** newtemps;
c->tempsz *= 2;
newtemps = naAlloc(c->tempsz * sizeof(struct naObj*));
for(i=0; i<c->ntemps; i++)
newtemps[i] = c->temps[i];
naFree(c->temps);
c->temps = newtemps;
}
c->temps[c->ntemps++] = PTR(r).obj;
}
naRef naObj(int type, struct naObj* o)
{
naRef r;
SETPTR(r, o);
o->type = type;
return r;
}
int naTrue(naRef r)
{
if(IS_NIL(r)) return 0;
if(IS_NUM(r)) return r.num != 0;
if(IS_STR(r)) return 1;
return 0;
}
naRef naNumValue(naRef n)
{
double d;
if(IS_NUM(n)) return n;
if(IS_NIL(n)) return naNil();
if(IS_STR(n) && naStr_tonum(n, &d))
return naNum(d);
return naNil();
}
naRef naStringValue(naContext c, naRef r)
{
if(IS_NIL(r) || IS_STR(r)) return r;
if(IS_NUM(r)) {
naRef s = naNewString(c);
naStr_fromnum(s, r.num);
return s;
}
return naNil();
}
naRef naNew(struct Context* c, int type)
{
naRef result;
if(c->nfree[type] == 0)
c->free[type] = naGC_get(&globals->pools[type],
OBJ_CACHE_SZ, &c->nfree[type]);
result = naObj(type, c->free[type][--c->nfree[type]]);
naTempSave(c, result);
return result;
}
naRef naNewString(struct Context* c)
{
naRef s = naNew(c, T_STR);
PTR(s).str->len = 0;
PTR(s).str->data = 0;
PTR(s).str->hashcode = 0;
return s;
}
naRef naNewVector(struct Context* c)
{
naRef r = naNew(c, T_VEC);
PTR(r).vec->rec = 0;
return r;
}
naRef naNewHash(struct Context* c)
{
naRef r = naNew(c, T_HASH);
PTR(r).hash->rec = 0;
return r;
}
naRef naNewCode(struct Context* c)
{
return naNew(c, T_CODE);
}
naRef naNewCCode(struct Context* c, naCFunction fptr)
{
naRef r = naNew(c, T_CCODE);
PTR(r).ccode->fptr = fptr;
return r;
}
naRef naNewFunc(struct Context* c, naRef code)
{
naRef func = naNew(c, T_FUNC);
PTR(func).func->code = code;
PTR(func).func->namespace = naNil();
PTR(func).func->next = naNil();
return func;
}
naRef naNewGhost(naContext c, naGhostType* type, void* ptr)
{
naRef ghost = naNew(c, T_GHOST);
PTR(ghost).ghost->gtype = type;
PTR(ghost).ghost->ptr = ptr;
return ghost;
}
naGhostType* naGhost_type(naRef ghost)
{
if(!IS_GHOST(ghost)) return 0;
return PTR(ghost).ghost->gtype;
}
void* naGhost_ptr(naRef ghost)
{
if(!IS_GHOST(ghost)) return 0;
return PTR(ghost).ghost->ptr;
}
naRef naNil()
{
naRef r;
SETPTR(r, 0);
return r;
}
naRef naNum(double num)
{
naRef r;
SETNUM(r, num);
return r;
}
int naEqual(naRef a, naRef b)
{
double na=0, nb=0;
if(IS_REF(a) && IS_REF(b) && PTR(a).obj == PTR(b).obj)
return 1; // Object identity (and nil == nil)
if(IS_NIL(a) || IS_NIL(b))
return 0;
if(IS_NUM(a) && IS_NUM(b) && a.num == b.num)
return 1; // Numeric equality
if(IS_STR(a) && IS_STR(b) && naStr_equal(a, b))
return 1; // String equality
// Numeric equality after conversion
if(IS_NUM(a)) { na = a.num; }
else if(!(IS_STR(a) && naStr_tonum(a, &na))) { return 0; }
if(IS_NUM(b)) { nb = b.num; }
else if(!(IS_STR(b) && naStr_tonum(b, &nb))) { return 0; }
return na == nb ? 1 : 0;
}
int naStrEqual(naRef a, naRef b)
{
int i;
if(!(IS_STR(a) && IS_STR(b)))
return 0;
if(PTR(a).str->len != PTR(b).str->len)
return 0;
for(i=0; i<PTR(a).str->len; i++)
if(PTR(a).str->data[i] != PTR(b).str->data[i])
return 0;
return 1;
}
int naTypeSize(int type)
{
switch(type) {
case T_STR: return sizeof(struct naStr);
case T_VEC: return sizeof(struct naVec);
case T_HASH: return sizeof(struct naHash);
case T_CODE: return sizeof(struct naCode);
case T_FUNC: return sizeof(struct naFunc);
case T_CCODE: return sizeof(struct naCCode);
case T_GHOST: return sizeof(struct naGhost);
};
return 0x7fffffff; // Make sure the answer is nonsense :)
}
int naIsNil(naRef r) { return IS_NIL(r); }
int naIsNum(naRef r) { return IS_NUM(r); }
int naIsString(naRef r) { return IS_STR(r); }
int naIsScalar(naRef r) { return IS_SCALAR(r); }
int naIsVector(naRef r) { return IS_VEC(r); }
int naIsHash(naRef r) { return IS_HASH(r); }
int naIsFunc(naRef r) { return IS_FUNC(r); }
int naIsCode(naRef r) { return IS_CODE(r); }
int naIsCCode(naRef r) { return IS_CCODE(r); }
int naIsGhost(naRef r) { return IS_GHOST(r); }
void naSetUserData(naContext c, void* p) { c->userData = p; }
void* naGetUserData(naContext c)
{
if(c->userData) return c->userData;
return c->callParent ? naGetUserData(c->callParent) : 0;
}
void naAddSym(naContext c, naRef ns, char *sym, naRef val)
{
naRef name = naStr_fromdata(naNewString(c), sym, strlen(sym));
naHash_set(ns, naInternSymbol(name), val);
}
naRef naGenLib(naContext c, naCFuncItem *fns)
{
naRef ns = naNewHash(c);
for(/**/; fns->name; fns++)
naAddSym(c, ns, fns->name, naNewFunc(c, naNewCCode(c, fns->func)));
return ns;
}