X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Flib.c;h=504a33c28bd67e180f7e5b463af1ad11fd3b5e61;hb=c12162407c59ff1ef111d2b2c82f6fd68dbfafe2;hp=f424438d4b5d4b8d2f47f7cd74e4143d9f88e911;hpb=966331dac7da0f9ec03ffeb052dd2cd72829b2eb;p=simgear.git diff --git a/simgear/nasal/lib.c b/simgear/nasal/lib.c index f424438d..504a33c2 100644 --- a/simgear/nasal/lib.c +++ b/simgear/nasal/lib.c @@ -12,6 +12,7 @@ #include "code.h" #define NEWSTR(c, s, l) naStr_fromdata(naNewString(c), s, l) +#define NEWCSTR(c, s) NEWSTR(c, s, strlen(s)) static naRef size(naContext c, naRef me, int argc, naRef* args) { @@ -49,8 +50,9 @@ static naRef pop(naContext c, naRef me, int argc, naRef* args) static naRef setsize(naContext c, naRef me, int argc, naRef* args) { + int sz; if(argc < 2) return naNil(); - int sz = (int)naNumValue(args[1]).num; + sz = (int)naNumValue(args[1]).num; if(!naIsVector(args[0])) return naNil(); naVec_setsize(args[0], sz); return args[0]; @@ -102,18 +104,37 @@ static naRef streq(naContext c, naRef me, int argc, naRef* args) return argc > 1 ? naNum(naStrEqual(args[0], args[1])) : naNil(); } +static naRef f_cmp(naContext c, naRef me, int argc, naRef* args) +{ + char *a, *b; + int i, len; + if(argc < 2 || !naIsString(args[0]) || !naIsString(args[1])) + naRuntimeError(c, "bad argument to cmp"); + a = naStr_data(args[0]); + b = naStr_data(args[1]); + len = naStr_len(args[0]); + if(naStr_len(args[1]) < len) + len = naStr_len(args[1]); + for(i=0; i 0) return naNum(1); + } + return naNum(0); +} + static naRef substr(naContext c, naRef me, int argc, naRef* args) { naRef src = argc > 1 ? args[0] : naNil(); - naRef startR = argc > 1 ? args[1] : naNil(); - naRef lenR = argc > 2 ? args[2] : naNil(); + naRef startR = argc > 1 ? naNumValue(args[1]) : naNil(); + naRef lenR = argc > 2 ? naNumValue(args[2]) : naNil(); int start, len; if(!naIsString(src)) return naNil(); - startR = naNumValue(startR); if(naIsNil(startR)) return naNil(); start = (int)startR.num; if(naIsNil(lenR)) { len = naStr_len(src) - start; + if(len < 0) return naNil(); } else { lenR = naNumValue(lenR); if(naIsNil(lenR)) return naNil(); @@ -122,18 +143,6 @@ static naRef substr(naContext c, naRef me, int argc, naRef* args) return naStr_substr(naNewString(c), src, start, len); } -static naRef f_strc(naContext c, naRef me, int argc, naRef* args) -{ - int idx; - struct naStr* str = args[0].ref.ptr.str; - naRef idr = argc > 1 ? naNumValue(args[1]) : naNum(0); - if(argc < 2 || IS_NIL(idr) || !IS_STR(args[0])) - naRuntimeError(c, "bad arguments to strc"); - idx = (int)naNumValue(idr).num; - if(idx > str->len) naRuntimeError(c, "strc index out of bounds"); - return naNum(str->data[idx]); -} - static naRef f_chr(naContext c, naRef me, int argc, naRef* args) { char chr[1]; @@ -163,7 +172,7 @@ static naRef typeOf(naContext c, naRef me, int argc, naRef* args) else if(naIsHash(r)) t = "hash"; else if(naIsFunc(r)) t = "func"; else if(naIsGhost(r)) t = "ghost"; - r = NEWSTR(c, t, strlen(t)); + r = NEWCSTR(c, t); return r; } @@ -173,33 +182,37 @@ static naRef f_compile(naContext c, naRef me, int argc, naRef* args) naRef script, code, fname; script = argc > 0 ? args[0] : naNil(); if(!naIsString(script)) return naNil(); - fname = NEWSTR(c, "", 9); + fname = NEWCSTR(c, ""); code = naParseCode(c, fname, 1, naStr_data(script), naStr_len(script), &errLine); if(!naIsCode(code)) return naNil(); // FIXME: export error to caller... return naBindToContext(c, code); } -// Funcation metacall API. Allows user code to generate an arg vector -// at runtime and/or call function references on arbitrary objects. static naRef f_call(naContext c, naRef me, int argc, naRef* args) { naContext subc; - naRef callargs, callme, result; + naRef callargs, callme, callns, result; + struct VecRec* vr; callargs = argc > 1 ? args[1] : naNil(); callme = argc > 2 ? args[2] : naNil(); // Might be nil, that's OK - if(!naIsFunc(args[0])) naRuntimeError(c, "call() on non-function"); - if(naIsNil(callargs)) callargs = naNewVector(c); - else if(!naIsVector(callargs)) naRuntimeError(c, "call() args not vector"); - if(!naIsHash(callme)) callme = naNil(); + callns = argc > 3 ? args[3] : naNil(); // ditto + if(!IS_HASH(callme)) callme = naNil(); + if(!IS_HASH(callns)) callns = naNil(); + if(!IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs))) + naRuntimeError(c, "bad argument to call()"); subc = naNewContext(); subc->callParent = c; c->callChild = subc; - result = naCall(subc, args[0], callargs, callme, naNil()); + vr = IS_NIL(callargs) ? 0 : callargs.ref.ptr.vec->rec; + result = naCall(subc, args[0], vr ? vr->size : 0, vr ? vr->array : 0, + callme, callns); c->callChild = 0; - if(argc > 2 && !IS_NIL(subc->dieArg)) - if(naIsVector(args[argc-1])) - naVec_append(args[argc-1], subc->dieArg); + if(argc > 2 && IS_VEC(args[argc-1])) { + if(!IS_NIL(subc->dieArg)) naVec_append(args[argc-1], subc->dieArg); + else if(naGetError(subc)) + naVec_append(args[argc-1], NEWCSTR(subc, naGetError(subc))); + } naFreeContext(subc); return result; } @@ -320,7 +333,7 @@ static naRef f_caller(naContext ctx, naRef me, int argc, naRef* args) { int fidx; struct Frame* frame; - naRef result, fr = argc ? naNumValue(args[0]) : naNil(); + naRef result, fr = argc ? naNumValue(args[0]) : naNum(1); if(IS_NIL(fr)) naRuntimeError(ctx, "non numeric argument to caller()"); fidx = (int)fr.num; if(fidx > ctx->fTop - 1) return naNil(); @@ -349,27 +362,30 @@ static naRef f_closure(naContext ctx, naRef me, int argc, naRef* args) return f->namespace; } -static int match(char* a, char* b, int l) +static int match(unsigned char* a, unsigned char* b, int l) { int i; for(i=0; i 2) start = (int)(naNumValue(args[2]).num); return naNum(find(args[0].ref.ptr.str->data, args[0].ref.ptr.str->len, - args[1].ref.ptr.str->data, args[1].ref.ptr.str->len)); + args[1].ref.ptr.str->data, args[1].ref.ptr.str->len, + start)); } static naRef f_split(naContext ctx, naRef me, int argc, naRef* args) @@ -388,7 +404,7 @@ static naRef f_split(naContext ctx, naRef me, int argc, naRef* args) } s0 = s; for(i=0; i <= sl-dl; i++) { - if(match(s+i, d, dl)) { + if(match((unsigned char*)(s+i), (unsigned char*)d, dl)) { naVec_append(result, NEWSTR(ctx, s0, s+i-s0)); s0 = s + i + dl; i += dl - 1; @@ -415,6 +431,19 @@ static naRef f_rand(naContext ctx, naRef me, int argc, naRef* args) return naNum(r); } +static naRef f_bind(naContext ctx, naRef me, int argc, naRef* args) +{ + naRef func = argc > 0 ? args[0] : naNil(); + naRef hash = argc > 1 ? args[1] : naNewHash(ctx); + naRef next = argc > 2 ? args[2] : naNil(); + if(!IS_FUNC(func) || (!IS_NIL(next) && !IS_FUNC(next)) || !IS_HASH(hash)) + naRuntimeError(ctx, "bad argument to bind"); + func = naNewFunc(ctx, func.ref.ptr.func->code); + func.ref.ptr.func->namespace = hash; + func.ref.ptr.func->next = next; + return func; +} + struct func { char* name; naCFunction func; }; static struct func funcs[] = { { "size", size }, @@ -427,8 +456,8 @@ static struct func funcs[] = { { "int", intf }, { "num", num }, { "streq", streq }, + { "cmp", f_cmp }, { "substr", substr }, - { "strc", f_strc }, { "chr", f_chr }, { "contains", contains }, { "typeof", typeOf }, @@ -441,6 +470,7 @@ static struct func funcs[] = { { "find", f_find }, { "split", f_split }, { "rand", f_rand }, + { "bind", f_bind }, }; naRef naStdLib(naContext c)