/* see copyright notice in squirrel.h */ #include #include #include "sqstdblobimpl.h" #include #include #include #include #include #ifdef _WIN32 #include #endif #ifdef SQUNICODE #include #define scgetenv _wgetenv #define scsystem _wsystem #define scasctime _wasctime #define scstrftime _wstrftime #define scremove _wremove #define screname _wrename #else #define scgetenv getenv #define scsystem system #define scasctime asctime #define scstrftime strftime #define scremove remove #define screname rename #endif SQ_OPT_STRING_STRLEN(); static SQRESULT _system_getenv(HSQUIRRELVM v) { const SQChar *s; if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ sq_pushstring(v,scgetenv(s),-1); return 1; } return 0; } static SQRESULT _system_system(HSQUIRRELVM v) { const SQChar *s; if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ sq_pushinteger(v,scsystem(s)); return 1; } return sq_throwerror(v,_SC("wrong param")); } static SQRESULT _system_clock(HSQUIRRELVM v) { sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); return 1; } /* static SQRESULT _system_time(HSQUIRRELVM v) { time_t t; time(&t); sq_pushinteger(v,*((SQInteger *)&t)); return 1; } */ static SQRESULT get_int_field (HSQUIRRELVM v, const SQChar *key, int dflt) { SQInteger res; SQObjectType stype; sq_pushstring(v, key, -1); if(sq_get(v, -2) == SQ_OK){ stype = sq_gettype(v, -1); if (stype & SQOBJECT_NUMERIC){ sq_getinteger(v, -1, &res); sq_poptop(v); return res; } sq_poptop(v); } if(dflt < 0) return sq_throwerror(v, _SC("field %s is missing"), key); return dflt; } static SQRESULT _system_time(HSQUIRRELVM v) { time_t t; if (sq_gettop(v) == 1) /* called without args? */ t = time(NULL); /* get current time */ else { struct tm ts; if(sq_gettype(v, 2) != OT_TABLE) return sq_throwerror(v, _SC("table expected as parameter but got (%s)"), sq_gettypename(v, 2)); sq_settop(v, 2); /* make sure table is at the top */ SQInteger rc = get_int_field(v, "sec", 0); if(rc == SQ_ERROR) return rc; else ts.tm_sec = rc; rc = get_int_field(v, "min", 0); if(rc == SQ_ERROR) return rc; else ts.tm_min = rc; rc = get_int_field(v, "hour", 12); if(rc == SQ_ERROR) return rc; else ts.tm_hour = rc; rc = get_int_field(v, "day", -1); if(rc == SQ_ERROR) return rc; else ts.tm_mday = rc; rc = get_int_field(v, "month", -1); if(rc == SQ_ERROR) return rc; else ts.tm_mon = rc; rc = get_int_field(v, "year", -1); if(rc == SQ_ERROR) return rc; else ts.tm_year = rc - 1900; SQBool isdst = SQTrue; sq_pushstring(v, _SC("isdst"), -1); if(sq_get(v, 2) == SQ_OK){ if(sq_getbool(v, -1, &isdst) == SQ_OK){ ts.tm_isdst = isdst; } sq_poptop(v); } ts.tm_isdst = isdst; t = mktime(&ts); } if (t == (time_t)(-1)) sq_pushnull(v); else sq_pushinteger(v,(SQInteger)t); return 1; } static SQRESULT _system_difftime (HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQ_GET_FLOAT(v, 2, t1); SQ_OPT_FLOAT(v, 3, t2, 0); sq_pushfloat(v, difftime( (time_t)t1, (time_t)t2)); return 1; } static SQRESULT _system_remove(HSQUIRRELVM v) { const SQChar *s; sq_getstring(v,2,&s); if(scremove(s)==-1) return sq_throwerror(v,_SC("remove() failed")); return 0; } static SQRESULT _system_rename(HSQUIRRELVM v) { const SQChar *oldn,*newn; sq_getstring(v,2,&oldn); sq_getstring(v,3,&newn); if(screname(oldn,newn)==-1) return sq_throwerror(v,_SC("rename() failed")); return 0; } static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val) { sq_pushstring(v,name,-1); sq_pushinteger(v,val); sq_rawset(v,-3); } static SQRESULT _system_date(HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQ_OPT_STRING(v, 2, arg_format, _SC("%c")); SQ_OPT_FLOAT(v, 3, arg_time, time(NULL)); time_t t = (time_t)arg_time; struct tm *stm; if (*arg_format == _SC('!')) { /* UTC? */ stm = gmtime(&t); arg_format++; /* skip `!' */ } else stm = localtime(&t); if (stm == NULL) /* invalid date? */ sq_pushnull(v); else if (scstrcmp(arg_format, _SC("*t")) == 0) { sq_newtableex(v, 9); /* 9 = number of fields */ _set_integer_slot(v, _SC("sec"), stm->tm_sec); _set_integer_slot(v, _SC("min"), stm->tm_min); _set_integer_slot(v, _SC("hour"), stm->tm_hour); _set_integer_slot(v, _SC("day"), stm->tm_mday); _set_integer_slot(v, _SC("month"), stm->tm_mon); _set_integer_slot(v, _SC("year"), stm->tm_year+1900); _set_integer_slot(v, _SC("wday"), stm->tm_wday); _set_integer_slot(v, _SC("yday"), stm->tm_yday); sq_pushliteral(v, _SC("isdst")); sq_pushbool(v, stm->tm_isdst); sq_rawset(v, -3); } else { SQChar cc[3]; SQBlob b(0, BLOB_BUFSIZE); cc[0] = _SC('%'); cc[2] = _SC('\0'); for (; *arg_format; arg_format++) { if (*arg_format != _SC('%') || *(arg_format + 1) == _SC('\0')) /* no conversion specifier? */ b.WriteChar(*arg_format); else { size_t reslen; SQChar buff[200]; /* should be big enough for any conversion result */ cc[1] = *(++arg_format); reslen = scstrftime(buff, sizeof(buff)/sizeof(SQChar), cc, stm); b.Write(buff, reslen); } } sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len()); } return 1; } static SQRESULT _system_exit (HSQUIRRELVM v) { SQRESULT status = 0; SQ_FUNC_VARS(v); if(_top_ > 1){ SQObjectType ptype = sq_gettype(v, 1); if (ptype == OT_BOOL){ SQ_GET_BOOL(v,2, b); status = b ? EXIT_SUCCESS : EXIT_FAILURE; } else sq_getinteger(v, 2, &status); SQ_OPT_BOOL(v, 3, bclose, false); if (bclose) sq_close(v); } exit(status); } #if defined(SC_USE_MKSTEMP) #include #define SQ_TMPNAMBUFSIZE 32 #define sq_tmpnam(b,e) { \ strcpy(b, "/tmp/lua_XXXXXX"); \ e = mkstemp(b); \ if (e != -1) close(e); \ e = (e == -1); } #else #define SQ_TMPNAMBUFSIZE L_tmpnam #define sq_tmpnam(b,e) { e = (tmpnam(b) == NULL); } #endif static SQRESULT _system_tmpname (HSQUIRRELVM v) { char buff[SQ_TMPNAMBUFSIZE]; int err; sq_tmpnam(buff, err); if (err) return sq_throwerror(v, "unable to generate a unique filename"); sq_pushstring(v, buff, -1); return 1; } #include static SQRESULT _system_setlocale (HSQUIRRELVM v) { static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME}; static const char *const catnames[] = {"all", "collate", "ctype", "monetary", "numeric", "time", NULL}; SQ_FUNC_VARS(v); SQ_OPT_STRING(v, 2, l, NULL); SQ_OPT_STRING(v, 3, name, "all"); for (int i=0; catnames[i]; i++) if (strcmp(catnames[i], name) == 0){ sq_pushstring(v, setlocale(cat[i], l), -1); return 1; } return sq_throwerror(v, "invalid option %s for param %d", name, 3); } /*-------------------------------------------------------------------------*\ * Sleep for n seconds. \*-------------------------------------------------------------------------*/ static SQRESULT _system_sleep(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_FLOAT(v, 2, n); #ifdef _WIN32 Sleep((int)(n*1000)); #else struct timespec t, r; t.tv_sec = (int) n; n -= t.tv_sec; t.tv_nsec = (int) (n * 1000000000); if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; while (nanosleep(&t, &r) != 0) { t.tv_sec = r.tv_sec; t.tv_nsec = r.tv_nsec; } #endif return 0; } #include int GetMilliCount() { // Something like GetTickCount but portable // It rolls over every ~ 12.1 days (0x100000/24/60/60) // Use GetMilliSpan to correct for rollover timeb tb; ftime( &tb ); int nCount = tb.millitm + (tb.time & 0xfffff) * 1000; return nCount; } int GetMilliSpan( int nTimeStart ) { int nSpan = GetMilliCount() - nTimeStart; if ( nSpan < 0 ) nSpan += 0x100000 * 1000; return nSpan; } static SQRESULT _system_getmillicount (HSQUIRRELVM v) { sq_pushinteger(v, GetMilliCount()); return 1; } static SQRESULT _system_getmillispan (HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_INTEGER(v, 2, nTimeStart); sq_pushinteger(v, GetMilliSpan(nTimeStart)); return 1; } #if 0 struct sq_signal_list { char *name; /* name of the signal */ int sig; /* the signal */ }; static const struct sq_signal_list sq_signals_list[] = { /* ANSI C signals */ #ifdef SIGABRT {"SIGABRT", SIGABRT}, #endif #ifdef SIGFPE {"SIGFPE", SIGFPE}, #endif #ifdef SIGILL {"SIGILL", SIGILL}, #endif #ifdef SIGINT {"SIGINT", SIGINT}, #endif #ifdef SIGSEGV {"SIGSEGV", SIGSEGV}, #endif #ifdef SIGTERM {"SIGTERM", SIGTERM}, #endif /* posix signals */ #ifdef SIGHUP {"SIGHUP", SIGHUP}, #endif #ifdef SIGQUIT {"SIGQUIT", SIGQUIT}, #endif #ifdef SIGTRAP {"SIGTRAP", SIGTRAP}, #endif #ifdef SIGKILL {"SIGKILL", SIGKILL}, #endif #ifdef SIGUSR1 {"SIGUSR1", SIGUSR1}, #endif #ifdef SIGUSR2 {"SIGUSR2", SIGUSR2}, #endif #ifdef SIGPIPE {"SIGPIPE", SIGPIPE}, #endif #ifdef SIGALRM {"SIGALRM", SIGALRM}, #endif #ifdef SIGCHLD {"SIGCHLD", SIGCHLD}, #endif #ifdef SIGCONT {"SIGCONT", SIGCONT}, #endif #ifdef SIGSTOP {"SIGSTOP", SIGSTOP}, #endif #ifdef SIGTTIN {"SIGTTIN", SIGTTIN}, #endif #ifdef SIGTTOU {"SIGTTOU", SIGTTOU}, #endif /* some BSD signals */ #ifdef SIGIOT {"SIGIOT", SIGIOT}, #endif #ifdef SIGBUS {"SIGBUS", SIGBUS}, #endif #ifdef SIGCLD {"SIGCLD", SIGCLD}, #endif #ifdef SIGURG {"SIGURG", SIGURG}, #endif #ifdef SIGXCPU {"SIGXCPU", SIGXCPU}, #endif #ifdef SIGXFSZ {"SIGXFSZ", SIGXFSZ}, #endif #ifdef SIGVTALRM {"SIGVTALRM", SIGVTALRM}, #endif #ifdef SIGPROF {"SIGPROF", SIGPROF}, #endif #ifdef SIGWINCH {"SIGWINCH", SIGWINCH}, #endif #ifdef SIGPOLL {"SIGPOLL", SIGPOLL}, #endif #ifdef SIGIO {"SIGIO", SIGIO}, #endif /* add odd signals */ #ifdef SIGSTKFLT {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ #endif #ifdef SIGSYS {"SIGSYS", SIGSYS}, #endif {NULL, 0} }; static HSQUIRRELVM vsig = NULL; static void sq_sig_handle(int sig) { if(vsig){ sq_pushliteral(vsig, _SC("sq_sig_handler")); if(sq_getonregistrytable(vsig) == SQ_OK){ SQObjectType ptype = sq_gettype(v, -1); if(ptype == OT_CLOSURE || ptype == OT_NATIVECLOSURE){ sq_pushroottable(v); sq_pushinteger(v, sig); sq_call(v, 2, SQFalse, SQFalse); } } } } /* * _system_raise == raise(signal) * * signal = signal number or string */ static int _system_raise(HSQUIRRELVM v) { SQ_FUNC_VARS(v); switch(sq_gettype(v, 2)){ case OT_INTEGER:{ SQ_GET_INTEGER(v, 2, iparam); sq_pushinteger(v, raise(iparam)); } break; case OT_STRING:{ int sig = 0; SQ_GET_STRING(v, 2, signame); for(int i=0, len = sizeof(sq_signals_list)/sizeof(sq_signal_list); i < len; ++i){ if(strcmp(sq_signals_list[i].name, signame) == 0){ sig = sq_signals_list[i].sig; break; } } if(sig) sq_pushinteger(v, raise(sig)); else return sq_throwerror(v, _SC("invalid signal (%s)"), signame); } break; default: return sq_throwerror(v, _SC("invalid paramter (%s)"), sq_gettypename(v, 2)); } return 1; } #endif #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} static SQRegFunction systemlib_funcs[]={ _DECL_FUNC(getenv,2,_SC(".s")), _DECL_FUNC(system,2,_SC(".s")), _DECL_FUNC(clock,0,NULL), _DECL_FUNC(time,-1,_SC(".t")), _DECL_FUNC(difftime,-2,_SC(".nn")), _DECL_FUNC(date,-1,_SC(".sn")), _DECL_FUNC(remove,2,_SC(".s")), _DECL_FUNC(rename,3,_SC(".ss")), _DECL_FUNC(exit, -1,_SC(". b|i b")), _DECL_FUNC(sleep, 2,_SC(".n")), _DECL_FUNC(tmpname,1,_SC(".")), _DECL_FUNC(setlocale,-1,_SC(".ss")), _DECL_FUNC(getmillicount,1,_SC(".")), _DECL_FUNC(getmillispan,2,_SC(".i")), {0,0} }; #undef _DECL_FUNC SQInteger sqstd_register_systemlib(HSQUIRRELVM v) { sq_pushstring(v,_SC("os"),-1); sq_newtable(v); SQInteger i=0; while(systemlib_funcs[i].name!=0) { sq_pushstring(v,systemlib_funcs[i].name,-1); sq_newclosure(v,systemlib_funcs[i].f,0); sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); sq_newslot(v,-3,SQFalse); i++; } sq_newslot(v,-3,SQTrue); //insert os return 1; }