static void* threadtop(void* param) #endif { ThreadData* td = param; naCall(td->ctx, td->func, 0, 0, naNil(), naNil()); naFreeContext(td->ctx); naFree(td); return 0; }
static naRef f_open(naContext c, naRef me, int argc, naRef* args) { FILE* f; naRef file = argc > 0 ? naStringValue(c, args[0]) : naNil(); naRef mode = argc > 1 ? naStringValue(c, args[1]) : naNil(); if(!IS_STR(file)) naRuntimeError(c, "bad argument to open()"); f = fopen(naStr_data(file), IS_STR(mode) ? naStr_data(mode) : "rb"); if(!f) naRuntimeError(c, strerror(errno)); return naIOGhost(c, f); }
naRef naStr_substr(naRef dest, naRef str, int start, int len) { struct naStr* dst = PTR(dest).str; struct naStr* s = PTR(str).str; if(!(IS_STR(dest)&&IS_STR(str))) return naNil(); if(start + len > LEN(s)) return naNil(); setlen(dst, len); memcpy(DATA(dst), DATA(s) + start, len); return dest; }
naRef naStr_substr(naRef dest, naRef str, int start, int len) { struct naStr* dst = dest.ref.ptr.str; struct naStr* s = str.ref.ptr.str; if(!(IS_STR(dest)&&IS_STR(str))) return naNil(); if(start + len > s->len) { dst->len = 0; dst->data = 0; return naNil(); } setlen(dst, len); memcpy(dst->data, s->data + start, len); return dest; }
static naRef f_seek(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc > 0 ? ioghost(args[0]) : 0; naRef pos = argc > 1 ? naNumValue(args[1]) : naNil(); naRef whn = argc > 2 ? naNumValue(args[2]) : naNil(); if(!g || !IS_NUM(pos) || !IS_NUM(whn)) naRuntimeError(c, "bad argument to seek()"); g->type->seek(c, g->handle, (int)pos.num, (int)whn.num); return naNil(); }
static naRef f_setfld(naContext c, naRef me, int argc, naRef* args) { naRef s = argc > 0 ? args[0] : naNil(); int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1; int len = argc > 2 ? (int)naNumValue(args[2]).num : -1; naRef val = argc > 3 ? naNumValue(args[3]) : naNil(); if(!argc || !MUTABLE(args[0])|| bit < 0 || len < 0 || IS_NIL(val)) naRuntimeError(c, "missing/bad argument to setfld"); setfld(c, (void*)naStr_data(s), naStr_len(s), bit, len, (unsigned int)val.num); return naNil(); }
static naRef f_read(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc > 0 ? ioghost(args[0]) : 0; naRef str = argc > 1 ? args[1] : naNil(); naRef len = argc > 2 ? naNumValue(args[2]) : naNil(); if(!g || !MUTABLE(str) || !IS_NUM(len)) naRuntimeError(c, "bad argument to read()"); if(naStr_len(str) < (int)len.num) naRuntimeError(c, "string not big enough for read"); return naNum(g->type->read(c, g->handle, naStr_data(str), (int)len.num)); }
naRef naStr_fromdata(naRef dst, char* data, int len) { if(!IS_STR(dst)) return naNil(); setlen(dst.ref.ptr.str, len); memcpy(dst.ref.ptr.str->data, data, len); return dst; }
//------------------------------------------------------------------------------ naRef getStringMethods(naContext c) { if( !init ) return naNil(); return string_methods; }
naRef naStr_fromdata(naRef dst, const char* data, int len) { if(!IS_STR(dst)) return naNil(); setlen(PTR(dst).str, len); memcpy(DATA(PTR(dst).str), data, len); return dst; }
// Handles multiple EOL conventions by using stdio's ungetc. Will not // work for other IO types without converting them to FILE* with // fdopen() or whatnot... static naRef f_readln(naContext ctx, naRef me, int argc, naRef* args) { naRef result; struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0; int i=0, c, sz = 128; char *buf; if(!g || g->type != &naStdIOType) naRuntimeError(ctx, "bad argument to readln()"); buf = naAlloc(sz); while(1) { c = getcguard(ctx, g->handle, buf); if(c == EOF || c == '\n') break; if(c == '\r') { int c2 = getcguard(ctx, g->handle, buf); if(c2 != EOF && c2 != '\n') if(EOF == ungetc(c2, g->handle)) break; break; } buf[i++] = c; if(i >= sz) buf = naRealloc(buf, sz *= 2); } result = c == EOF ? naNil() : naStr_fromdata(naNewString(ctx), buf, i); naFree(buf); return result; }
naRef naHash_cget(naRef hash, char* key) { struct naStr str; naRef result, key2; tmpStr(&key2, &str, key); return naHash_get(hash, key2, &result) ? result : naNil(); }
static naRef f_flush(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0; if(!g) naRuntimeError(c, "bad argument to flush()"); g->type->flush(c, g->handle); return naNil(); }
static naRef f_write(naContext c, naRef me, int argc, naRef* args) { struct naIOGhost* g = argc > 0 ? ioghost(args[0]) : 0; naRef str = argc > 1 ? args[1] : naNil(); if(!g || !IS_STR(str)) naRuntimeError(c, "bad argument to write()"); return naNum(g->type->write(c, g->handle, naStr_data(str), naStr_len(str))); }
static naRef f_semdown(naContext c, naRef me, int argc, naRef* args) { if(argc > 0 && naGhost_type(args[0]) == &SemType) { naModUnlock(); naSemDown(naGhost_ptr(args[0])); naModLock(); } return naNil(); }
static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args) { int n=0; struct stat s; naRef result, path = argc > 0 ? naStringValue(ctx, args[0]) : naNil(); if(!IS_STR(path)) naRuntimeError(ctx, "bad argument to stat()"); if(stat(naStr_data(path), &s) < 0) { if(errno == ENOENT) return naNil(); naRuntimeError(ctx, strerror(errno)); } result = naNewVector(ctx); naVec_setsize(result, 12); #define FLD(x) naVec_set(result, n++, naNum(s.st_##x)); FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid); FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime); #undef FLD naVec_set(result, n++, ftype(ctx, s.st_mode)); return result; }
naRef naStr_concat(naRef dest, naRef s1, naRef s2) { struct naStr* dst = PTR(dest).str; struct naStr* a = PTR(s1).str; struct naStr* b = PTR(s2).str; if(!(IS_STR(s1)&&IS_STR(s2)&&IS_STR(dest))) return naNil(); setlen(dst, LEN(a) + LEN(b)); memcpy(DATA(dst), DATA(a), LEN(a)); memcpy(DATA(dst) + LEN(a), DATA(b), LEN(b)); return dest; }
naRef naStr_concat(naRef dest, naRef s1, naRef s2) { struct naStr* dst = dest.ref.ptr.str; struct naStr* a = s1.ref.ptr.str; struct naStr* b = s2.ref.ptr.str; if(!(IS_STR(s1)&&IS_STR(s2)&&IS_STR(dest))) return naNil(); setlen(dst, a->len + b->len); memcpy(dst->data, a->data, a->len); memcpy(dst->data + a->len, b->data, b->len); return dest; }
static naRef dofld(naContext c, int argc, naRef* args, int sign) { naRef s = argc > 0 ? args[0] : naNil(); int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1; int len = argc > 2 ? (int)naNumValue(args[2]).num : -1; unsigned int f; if(!naIsString(s) || !MUTABLE(args[0]) || bit < 0 || len < 0) naRuntimeError(c, "missing/bad argument to fld/sfld"); f = fld(c, (void*)naStr_data(s), naStr_len(s), bit, len); if(!sign) return naNum(f); if(f & (1 << (len-1))) f |= ~((1<<len)-1); // sign extend return naNum((signed int)f); }
static naRef f_newthread(naContext c, naRef me, int argc, naRef* args) { ThreadData *td; if(argc < 1 || !naIsFunc(args[0])) naRuntimeError(c, "bad/missing argument to newthread"); td = naAlloc(sizeof(*td)); td->ctx = naNewContext(); td->func = args[0]; naTempSave(td->ctx, td->func); #ifdef _WIN32 CreateThread(0, 0, threadtop, td, 0, 0); #else { pthread_t t; int err; if((err = pthread_create(&t, 0, threadtop, td))) naRuntimeError(c, "newthread failed: %s", strerror(err)); pthread_detach(t); } #endif return naNil(); }
static naRef f_buf(naContext c, naRef me, int argc, naRef* args) { naRef len = argc ? naNumValue(args[0]) : naNil(); if(IS_NIL(len)) naRuntimeError(c, "missing/bad argument to buf"); return naStr_buf(naNewString(c), (int)len.num); }
static naRef f_unlock(naContext c, naRef me, int argc, naRef* args) { if(argc > 0 && naGhost_type(args[0]) == &LockType) naUnlock(naGhost_ptr(args[0])); return naNil(); }
static naRef f_semup(naContext c, naRef me, int argc, naRef* args) { if(argc > 0 && naGhost_type(args[0]) == &SemType) naSemUp(naGhost_ptr(args[0]), 1); return naNil(); }