/* Class index function * If the object is a userdata (ie, an object), it searches the field in * the alternative table stored in the corresponding "ubox" table. */ static int class_index_event (lua_State* L) { int t = lua_type(L,1); if (t == LUA_TUSERDATA) { /* Access alternative table */ #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */ lua_getfenv(L,1); if (!lua_rawequal(L, -1, TOLUA_NOPEER)) { lua_pushvalue(L, 2); /* key */ lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */ if (!lua_isnil(L, -1)) return 1; }; #else lua_pushstring(L,"tolua_peers"); lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */ lua_pushvalue(L,1); lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); /* key */ lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */ if (!lua_isnil(L,-1)) return 1; } #endif lua_settop(L,2); /* stack: obj key */ /* Try metatables */ lua_pushvalue(L,1); /* stack: obj key obj */ while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */ lua_remove(L,-2); /* stack: obj key mt */ if (lua_isnumber(L,2)) /* check if key is a numeric value */ { /* try operator[] */ lua_pushstring(L,".geti"); lua_rawget(L,-2); /* stack: obj key mt func */ if (lua_isfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } } else { lua_pushvalue(L,2); /* stack: obj key mt key */ lua_rawget(L,-2); /* stack: obj key mt value */ if (!lua_isnil(L,-1)) return 1; else lua_pop(L,1); /* try C/C++ variable */ lua_pushstring(L,".get"); lua_rawget(L,-2); /* stack: obj key mt tget */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); lua_rawget(L,-2); /* stack: obj key mt value */ if (lua_iscfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } else if (lua_istable(L,-1)) { /* deal with array: create table to be returned and cache it in ubox */ void* u = *((void**)lua_touserdata(L,1)); lua_newtable(L); /* stack: obj key mt value table */ lua_pushstring(L,".self"); lua_pushlightuserdata(L,u); lua_rawset(L,-3); /* store usertype in ".self" */ lua_insert(L,-2); /* stack: obj key mt table value */ lua_setmetatable(L,-2); /* set stored value as metatable */ lua_pushvalue(L,-1); /* stack: obj key met table table */ lua_pushvalue(L,2); /* stack: obj key mt table table key */ lua_insert(L,-2); /* stack: obj key mt table key table */ storeatubox(L,1); /* stack: obj key mt table */ return 1; } } } lua_settop(L,3); } lua_pushnil(L); return 1; } else if (t== LUA_TTABLE) { module_index_event(L); return 1; } lua_pushnil(L); return 1; }
/* | The effective main for one run. | HUP signals may cause several runs of the one main. */ int main1( int argc, char *argv[] ) { // the Lua interpreter lua_State * L; // the runner file char * lsyncd_runner_file = NULL; int argp = 1; // load Lua L = luaL_newstate( ); luaL_openlibs( L ); { // checks the lua version const char * version; int major, minor; lua_getglobal( L, "_VERSION" ); version = luaL_checkstring( L, -1 ); if( sscanf( version, "Lua %d.%d", &major, &minor ) != 2 ) { fprintf( stderr, "cannot parse lua library version!\n" ); exit (-1 ); } if( major < 5 || (major == 5 && minor < 1) ) { fprintf( stderr, "Lua library is too old. Needs 5.1 at least" ); exit( -1 ); } lua_pop( L, 1 ); } { // logging is prepared quite early int i = 1; add_logcat( "Normal", LOG_NOTICE ); add_logcat( "Warn", LOG_WARNING ); add_logcat( "Error", LOG_ERR ); while( i < argc ) { if( strcmp( argv[ i ], "-log" ) && strcmp( argv[ i ], "--log" ) ) { // arg is neither -log or --log i++; continue; } if( ++i >= argc ) { // -(-)log was last argument break; } if( !add_logcat( argv[ i ], LOG_NOTICE ) ) { printlogf( L, "Error", "'%s' is not a valid logging category", argv[ i ] ); exit( -1 ); } } } // registers Lsycnd's core library register_lsyncd( L ); if( check_logcat( "Debug" ) <= settings.log_level ) { // printlogf doesnt support %ld :-( printf( "kernels clocks_per_sec=%ld\n", clocks_per_sec ); } // checks if the user overrode the default runner file if( argp < argc && !strcmp( argv[ argp ], "--runner" ) ) { if (argp + 1 >= argc) { logstring( "Error", "Lsyncd Lua-runner file missing after --runner " ); exit( -1 ); } lsyncd_runner_file = argv[ argp + 1 ]; argp += 2; } if( lsyncd_runner_file ) { // checks if the runner file exists struct stat st; if( stat( lsyncd_runner_file, &st ) ) { printlogf( L, "Error", "Cannot see a runner at '%s'.", lsyncd_runner_file ); exit( -1 ); } // loads the runner file if( luaL_loadfile(L, lsyncd_runner_file ) ) { printlogf( L, "Error", "error loading '%s': %s", lsyncd_runner_file, lua_tostring( L, -1 ) ); exit( -1 ); } } else { // loads the runner from binary if( luaL_loadbuffer( L, runner_out, runner_size, "runner" ) ) { printlogf( L, "Error", "error loading precompiled runner: %s", lua_tostring( L, -1 ) ); exit( -1 ); } } // prepares the runner executing the script { if( lua_pcall( L, 0, LUA_MULTRET, 0 ) ) { printlogf( L, "Error", "preparing runner: %s", lua_tostring( L, -1 ) ); exit( -1 ); } lua_pushlightuserdata( L, (void *) & runner ); // switches the value ( result of preparing ) and the key &runner lua_insert( L, 1 ); // saves the table of the runners functions in the lua registry lua_settable( L, LUA_REGISTRYINDEX ); // saves the error function extras // &callError is the key lua_pushlightuserdata ( L, (void *) &callError ); // &runner[ callError ] the value lua_pushlightuserdata ( L, (void *) &runner ); lua_gettable ( L, LUA_REGISTRYINDEX ); lua_pushstring ( L, "callError" ); lua_gettable ( L, -2 ); lua_remove ( L, -2 ); lua_settable ( L, LUA_REGISTRYINDEX ); } // asserts the Lsyncd's version matches // between runner and core { const char *lversion; lua_getglobal( L, "lsyncd_version" ); lversion = luaL_checkstring( L, -1 ); if( strcmp( lversion, PACKAGE_VERSION ) ) { printlogf( L, "Error", "Version mismatch '%s' is '%s', but core is '%s'", lsyncd_runner_file ? lsyncd_runner_file : "( internal runner )", lversion, PACKAGE_VERSION ); exit( -1 ); } lua_pop( L, 1 ); } // loads the defaults from binary { if( luaL_loadbuffer( L, defaults_out, defaults_size, "defaults" ) ) { printlogf( L, "Error", "loading defaults: %s", lua_tostring( L, -1 ) ); exit( -1 ); } // prepares the defaults if (lua_pcall( L, 0, 0, 0 ) ) { printlogf( L, "Error", "preparing defaults: %s", lua_tostring( L, -1 ) ); exit( -1 ); } } // checks if there is a "-help" or "--help" { int i; for( i = argp; i < argc; i++ ) { if ( !strcmp( argv[ i ], "-help" ) || !strcmp( argv[ i ], "--help" ) ) { load_runner_func(L, "help"); if (lua_pcall(L, 0, 0, -2)) { exit( -1 ); } lua_pop( L, 1 ); exit( 0 ); } } } // starts the option parser in Lua script { int idx = 1; const char *s; // creates a table with all remaining argv option arguments load_runner_func( L, "configure" ); lua_newtable( L ); while( argp < argc ) { lua_pushnumber ( L, idx++ ); lua_pushstring ( L, argv[ argp++ ] ); lua_settable ( L, -3 ); } // creates a table with the cores event monitor interfaces idx = 0; lua_newtable( L ); while( monitors[ idx ] ) { lua_pushnumber ( L, idx + 1 ); lua_pushstring ( L, monitors[ idx++ ] ); lua_settable ( L, -3 ); } if( lua_pcall( L, 2, 1, -4 ) ) { exit( -1 ); } if( first_time ) { // If not first time, simply retains the config file given s = lua_tostring(L, -1); if( s ) { lsyncd_config_file = s_strdup( s ); } } lua_pop( L, 2 ); } // checks existence of the config file if( lsyncd_config_file ) { struct stat st; // gets the absolute path to the config file // so in case of HUPing the daemon, it finds it again char * apath = get_realpath( lsyncd_config_file ); if( !apath ) { printlogf( L, "Error", "Cannot find config file at '%s'.", lsyncd_config_file ); exit( -1 ); } free( lsyncd_config_file ); lsyncd_config_file = apath; if( stat( lsyncd_config_file, &st ) ) { printlogf( L, "Error", "Cannot find config file at '%s'.", lsyncd_config_file ); exit( -1 ); } // loads and executes the config file if( luaL_loadfile( L, lsyncd_config_file ) ) { printlogf( L, "Error", "error loading %s: %s", lsyncd_config_file, lua_tostring( L, -1 ) ); exit( -1 ); } if( lua_pcall( L, 0, LUA_MULTRET, 0) ) { printlogf( L, "Error", "error preparing %s: %s", lsyncd_config_file, lua_tostring( L, -1 ) ); exit( -1 ); } } #ifdef LSYNCD_WITH_INOTIFY open_inotify( L ); #endif #ifdef LSYNCD_WITH_FSEVENTS open_fsevents( L ); #endif // adds signal handlers // listens to SIGCHLD, but blocks it until pselect( ) // opens the signal handler up { sigset_t set; sigemptyset( &set ); sigaddset( &set, SIGCHLD ); signal( SIGCHLD, sig_child ); sigprocmask( SIG_BLOCK, &set, NULL ); signal( SIGHUP, sig_handler ); signal( SIGTERM, sig_handler ); } // runs initializations from runner // it will set the configuration and add watches { load_runner_func( L, "initialize" ); lua_pushboolean( L, first_time ); if( lua_pcall( L, 1, 0, -3 ) ) { exit( -1 ); } lua_pop( L, 1 ); } // // enters the master loop // masterloop( L ); // // cleanup // // tidies up all observances { int i; for( i = 0; i < observances_len; i++ ) { struct observance *obs = observances + i; obs->tidy( obs ); } observances_len = 0; nonobservances_len = 0; } // frees logging categories { int ci; struct logcat *lc; for( ci = 'A'; ci <= 'Z'; ci++ ) { for( lc = logcats[ ci - 'A' ]; lc && lc->name; lc++) { free( lc->name ); lc->name = NULL; } if( logcats[ci - 'A' ] ) { free( logcats[ ci - 'A' ] ); logcats[ ci - 'A' ] = NULL; } } } lua_close( L ); return 0; }
int Lua_MapBuff(lua_State *L) { if (!lua_isuserdata(L, 1) || !lua_isstring(L, 2)) { return 0; } CSocketBuff* pBuff = static_cast<CSocketBuff*>(lua_touserdata(L, 1)); const char* strVarType = lua_tostring(L, 2); if (CTools::Strcmp(strVarType, "INT") == 0) { int iRet = 0; bool bRet = pBuff->PeekBuff((char*)(void *)&iRet, sizeof(iRet)); if (!bRet) { return 0; } lua_pushnumber(L, 1); lua_pushnumber(L, iRet); return 2; } if (CTools::Strcmp(strVarType, "FLOAT") == 0) { float fRet = 0; bool bRet = pBuff->PeekBuff((char*)(void *)&fRet, sizeof(fRet)); if (!bRet) { return 0; } lua_pushnumber(L, 1); lua_pushnumber(L, fRet); return 2; } if (CTools::Strcmp(strVarType, "SHORT") == 0) { short sRet = 0; bool bRet = pBuff->PeekBuff((char*)(void *)&sRet, sizeof(sRet)); if (!bRet) { return 0; } lua_pushnumber(L, 1); lua_pushnumber(L, sRet); return 2; } else if (CTools::Strcmp(strVarType, "STRING") == 0) { short iStrLen = 0; bool bRet = pBuff->PeekBuff((char*)(void *)&iStrLen, sizeof(iStrLen)); if (!bRet) { return 0; } if (iStrLen <= 0) { lua_pushnumber(L, 1); lua_pushstring(L, ""); return 2; } else { char szTmp[256] = {}; bRet = pBuff->PeekBuff(szTmp, iStrLen); if (!bRet) { return 0; } lua_pushnumber(L, 1); lua_pushstring(L, szTmp); return 2; } } else { int iDataLen = 0; bool bRet = pBuff->PeekBuff((char*)(void *)&iDataLen, sizeof(iDataLen)); if (!bRet) { return 0; } if (iDataLen <= 0) { lua_pushnumber(L, 1); lua_pushlightuserdata(L, NULL); return 2; } else { bRet = pBuff->PeekBuff((char*)(void *)g_VarData, iDataLen); if (!bRet) { return 0; } lua_pushnumber(L, 1); lua_pushlightuserdata(L, (void *)g_VarData); return 2; } } return 0; }
void LuaInterface::pushLightUserdata(void* p) { lua_pushlightuserdata(L, p); checkStack(); }
bool CLuaEngine::RunLuaFunction(const char* szFunName, const char* szTableName, const char* szSubTableName, LuaParam * pInParam, int nInNum, LuaParam * pOutParam, int nOutNum) { int top = lua_gettop(m_pLuaState); if( !szTableName ) { lua_getglobal(m_pLuaState, szFunName); } else if( !szSubTableName ) { lua_getglobal(m_pLuaState, szTableName); if( lua_istable(m_pLuaState, -1) ) { lua_getfield(m_pLuaState,-1,szFunName); } } else { lua_getglobal(m_pLuaState, szTableName); if( lua_istable(m_pLuaState, -1) ) { lua_getfield(m_pLuaState, -1, szSubTableName); if( lua_istable(m_pLuaState, -1) ) { lua_getfield(m_pLuaState, -1, szFunName); } } } if( !lua_isfunction(m_pLuaState, -1) ) { DEBUG_STROUT("[CLuaEngine] func not found:%s.%s", szTableName, szFunName); lua_settop(m_pLuaState, top); return false; } for(int i = 0; i < nInNum; i++) { switch(pInParam[i].Type()) { case LUA_TNUMBER: lua_pushnumber(m_pLuaState, *(lua_Number*)pInParam[i].Data()); break; case LUA_TSTRING: lua_pushstring(m_pLuaState, (const char*)pInParam[i].Data()); break; case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(m_pLuaState, pInParam[i].Data()); break; default: DEBUG_STROUT("[CLuaEngine] call func:%s.%s error:invalid input param", szTableName, szFunName); lua_settop(m_pLuaState, top); return false; } } if( !lua_pcall(m_pLuaState, nInNum, nOutNum, 0) ) { for(int n = 0; n < nOutNum; n++) { int nType = lua_type(m_pLuaState, -1); switch(nType) { case LUA_TNUMBER: pOutParam[n].SetDataNum(lua_tonumber(m_pLuaState, -1)); lua_pop(m_pLuaState, 1); break; case LUA_TBOOLEAN: pOutParam[n].SetDataNum(lua_toboolean(m_pLuaState, -1)); lua_pop(m_pLuaState, 1); break; case LUA_TSTRING: pOutParam[n].SetDataString((const char*)lua_tostring(m_pLuaState, -1)); lua_pop(m_pLuaState, 1); break; case LUA_TLIGHTUSERDATA: pOutParam[n].SetDataPointer((void*)lua_topointer(m_pLuaState, -1)); lua_pop(m_pLuaState, 1); break; default: DEBUG_STROUT("[CLuaEngine] call func:%s.%s error:invalid output param", szTableName, szFunName); lua_settop(m_pLuaState, top); return false; } } lua_settop(m_pLuaState, top); //恢复栈成为未调用时的状态。 return true; } DEBUG_STROUT("[CLuaEngine] call func:%s.%s error:%s", szTableName, szFunName, GetLastError()); lua_settop(m_pLuaState, top); return false; }
static void push_attack_analysis(lua_State *L, attack_analysis& aa) { lua_newtable(L); // Pushing a pointer to the current object lua_pushstring(L, "att_ptr"); lua_pushlightuserdata(L, &aa); lua_rawset(L, -3); // Registering callback function for the rating method lua_pushstring(L, "rating"); lua_pushlightuserdata(L, &get_engine(L)); lua_pushcclosure(L, &cfun_attack_rating, 1); lua_rawset(L, -3); lua_pushstring(L, "movements"); push_movements(L, aa.movements); lua_rawset(L, -3); lua_pushstring(L, "target"); push_map_location(L, aa.target); lua_rawset(L, -3); lua_pushstring(L, "target_value"); lua_pushnumber(L, aa.target_value); lua_rawset(L, -3); lua_pushstring(L, "avg_losses"); lua_pushnumber(L, aa.avg_losses); lua_rawset(L, -3); lua_pushstring(L, "chance_to_kill"); lua_pushnumber(L, aa.chance_to_kill); lua_rawset(L, -3); lua_pushstring(L, "avg_damage_inflicted"); lua_pushnumber(L, aa.avg_damage_inflicted); lua_rawset(L, -3); lua_pushstring(L, "target_starting_damage"); lua_pushinteger(L, aa.target_starting_damage); lua_rawset(L, -3); lua_pushstring(L, "avg_damage_taken"); lua_pushnumber(L, aa.avg_damage_taken); lua_rawset(L, -3); lua_pushstring(L, "resources_used"); lua_pushnumber(L, aa.resources_used); lua_rawset(L, -3); lua_pushstring(L, "terrain_quality"); lua_pushnumber(L, aa.alternative_terrain_quality); lua_rawset(L, -3); lua_pushstring(L, "alternative_terrain_quality"); lua_pushnumber(L, aa.alternative_terrain_quality); lua_rawset(L, -3); lua_pushstring(L, "vulnerability"); lua_pushnumber(L, aa.vulnerability); lua_rawset(L, -3); lua_pushstring(L, "support"); lua_pushnumber(L, aa.support); lua_rawset(L, -3); lua_pushstring(L, "leader_threat"); lua_pushboolean(L, aa.leader_threat); lua_rawset(L, -3); lua_pushstring(L, "uses_leader"); lua_pushboolean(L, aa.uses_leader); lua_rawset(L, -3); lua_pushstring(L, "is_surrounded"); lua_pushboolean(L, aa.is_surrounded); lua_rawset(L, -3); }
bool sinsp_chisel::run(sinsp_evt* evt) { #ifdef HAS_LUA_CHISELS string line; ASSERT(m_ls); // // Make the event available to the API // lua_pushlightuserdata(m_ls, evt); lua_setglobal(m_ls, "sievt"); // // If this is the first event, put the event pointer on the stack. // We assume that the event pointer will never change. // if(m_lua_is_first_evt) { first_event_inits(evt); } // // If there is a timeout callback, see if it's time to call it // do_timeout(evt); // // If there is a filter, run it // if(m_lua_cinfo->m_filter != NULL) { if(!m_lua_cinfo->m_filter->run(evt)) { return false; } } // // If the script has the on_event callback, call it // if(m_lua_has_handle_evt) { lua_getglobal(m_ls, "on_event"); if(lua_pcall(m_ls, 0, 1, 0) != 0) { throw sinsp_exception(m_filename + " chisel error: " + lua_tostring(m_ls, -1)); } int oeres = lua_toboolean(m_ls, -1); lua_pop(m_ls, 1); if(m_lua_cinfo->m_end_capture == true) { throw sinsp_capture_interrupt_exception(); } if(oeres == false) { return false; } } // // If the script has a formatter, run it // if(m_lua_cinfo->m_formatter != NULL) { if(m_lua_cinfo->m_formatter->tostring(evt, &line)) { cout << line << endl; } } return true; #endif }
/* * Arguments: function, [arguments (any) ...] * Returns: [thread_ludata] */ static int thread_run (lua_State *L) { struct sys_thread *vmtd = sys_get_thread(); lua_State *NL; struct sys_thread *td; #ifndef _WIN32 pthread_attr_t attr; int res = 0; #else HANDLE hThr; const int res = 0; #endif if (!vmtd) luaL_argerror(L, 0, "Threading not initialized"); luaL_checktype(L, 1, LUA_TFUNCTION); NL = lua_newthread(L); if (!NL) goto err; td = lua_newuserdata(L, sizeof(struct sys_thread)); memset(td, 0, sizeof(struct sys_thread)); td->mutex = vmtd->mutex; td->L = NL; td->vmtd = vmtd->vmtd; #ifndef _WIN32 if ((res = pthread_attr_init(&attr)) || (res = pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE))) goto err; pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); res = pthread_create(&td->tid, &attr, (thread_func_t) thread_start, td); pthread_attr_destroy(&attr); if (!res) { #else hThr = (HANDLE) _beginthreadex(NULL, THREAD_STACK_SIZE, (thread_func_t) thread_start, td, 0, &td->tid); if (hThr) { CloseHandle(hThr); #endif thread_settable(L, NL, td->tid); /* save thread to avoid GC */ lua_xmove(L, NL, lua_gettop(L)); /* move function and args to NL */ lua_pushlightuserdata(L, td); return 1; } err: return sys_seterror(L, res); } /* * Arguments: function, master (thread_ludata), * [arguments (string | number | boolean | lightuserdata) ...], * thread, thread_udata */ static THREAD_FUNC_API thread_startvm (struct sys_thread *td) { lua_State *L = td->L; thread_settable(L, L, td->tid); sys_set_thread(td); sys_vm2_enter(td); if (lua_pcall(L, lua_gettop(L) - 1, 0, 0)) { if (td->interrupted && lua_touserdata(L, -1) == &g_TLSIndex) lua_pop(L, 1); else lua_error(L); } /* notify event_queue */ if (td->trigger) sys_trigger_notify(&td->trigger, SYS_EVEOF | SYS_EVDEL); lua_close(L); return 0; }
/* * Arguments: filename (string) | function_dump (string), * [arguments (string | number | boolean | lightuserdata) ...] * Returns: [thread_ludata] */ static int thread_runvm (lua_State *L) { const char *path = luaL_checkstring(L, 1); lua_State *NL = NULL; struct sys_vmthread *vmtd = (struct sys_vmthread *) sys_get_thread(); #ifndef _WIN32 pthread_attr_t attr; #else HANDLE hThr; #endif int res = 0; if (!vmtd) luaL_argerror(L, 0, "Threading not initialized"); NL = luaL_newstate(); if (!NL) goto err; thread_openlibs(NL); if (path[0] == LUA_SIGNATURE[0] ? luaL_loadbuffer(NL, path, lua_rawlen(L, 1), "thread") : luaL_loadfile(NL, path)) { lua_pushstring(L, lua_tostring(NL, -1)); /* error message */ lua_close(NL); lua_error(L); } /* Arguments */ lua_pushlightuserdata(NL, vmtd); /* master */ { int i, top = lua_gettop(L); for (i = 2; i <= top; ++i) { switch (lua_type(L, i)) { case LUA_TSTRING: lua_pushstring(NL, lua_tostring(L, i)); break; case LUA_TNUMBER: lua_pushnumber(NL, lua_tonumber(L, i)); break; case LUA_TBOOLEAN: lua_pushboolean(NL, lua_toboolean(L, i)); break; case LUA_TLIGHTUSERDATA: case LUA_TUSERDATA: lua_pushlightuserdata(NL, lua_touserdata(L, i)); break; default: luaL_argerror(L, i, "primitive type expected"); } } } if (vmthread_new(NL, &vmtd)) goto err_clean; #ifndef _WIN32 res = pthread_attr_init(&attr); if (res) goto err_clean; pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); res = pthread_create(&vmtd->td.tid, &attr, (thread_func_t) thread_startvm, vmtd); pthread_attr_destroy(&attr); if (!res) { #else hThr = (HANDLE) _beginthreadex(NULL, 0, (thread_func_t) thread_startvm, vmtd, 0, &vmtd->td.tid); if (hThr) { CloseHandle(hThr); #endif lua_pushlightuserdata(L, vmtd); return 1; } err_clean: lua_close(NL); err: return sys_seterror(L, res); } /* * Arguments: thread_ludata */ static int thread_interrupt (lua_State *L) { struct sys_thread *td = lua_touserdata(L, 1); td->interrupted = 1; #ifndef _WIN32 pthread_kill(td->tid, SYS_SIGINTR); #endif return 0; } static int thread_yield (lua_State *L) { (void) L; sys_vm_leave(); #ifndef _WIN32 sched_yield(); #else Sleep(0); #endif sys_vm_enter(); return 0; }
inline void push(lua_State* L, void* userdata) { lua_pushlightuserdata(L, userdata); }
ngx_int_t ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_rewrite_phase = 1; ctx->cc = cc; ctx->cc_ref = cc_ref; /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
static int lua_pushConsole(lua_State *L, mtev_console_closure_t ncct) { lua_pushlightuserdata(L, ncct); lua_pushcclosure(L, mtev_lua_ncct_print, 1); return 1; }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; lua_State *co; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx, ctx = %p, size: %d", ctx, (int) sizeof(*ctx)); ctx->entry_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(co, LUA_GLOBALSINDEX); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(co, &ngx_http_lua_request_key); lua_pushlightuserdata(co, r); lua_rawset(co, LUA_GLOBALSINDEX); /* }}} */ ctx->entry_co = co; ctx->cur_co = co; ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->entry_ref = co_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_CONTENT; return ngx_http_lua_run_thread(L, r, ctx, 0); }
static void lua_rawsetp(lua_State *L, int idx, const void *p) { lua_pushlightuserdata(L, (void*)p); lua_insert(L, -2); lua_rawset(L, lua_relindex(idx, 1)); }
// Called from lua to listen to a new event from an instance static int addon_output_event_listen_start(lua_State *L) { // Args should be : // 1) self // 2) event name // 3) process_begin // 4) process_end // 5) filter if any // Find the event const char *evt_name = luaL_checkstring(L, 2); struct event_reg *evt = event_find(evt_name); if (!evt) luaL_error(L, "Event %s does not exists", evt_name); // Check which function we should register int (*process_begin) (struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) = NULL; int (*process_end) (struct event *evt, void *obj) = NULL; if (lua_isfunction(L, 3)) process_begin = addon_event_process_begin; if (lua_isfunction(L, 4)) process_end = addon_event_process_end; struct filter *filter = NULL; if (!lua_isnoneornil(L, 5)) { const char *filter_str = luaL_checkstring(L, 5); filter = event_filter_compile((char*)filter_str, evt); if (!filter) luaL_error(L, "Error while parsing filter \"%s\"", filter_str); } // Get the output struct addon_instance_priv *p = addon_output_get_priv(L, 1); if (event_listener_register(evt, p, process_begin, process_end, filter) != POM_OK) luaL_error(L, "Error while listening to event %s", evt_name); // Add a table to self for the processing functions of this event lua_newtable(L); lua_pushlightuserdata(L, evt); lua_pushvalue(L, -2); lua_settable(L, 1); // Add the processing function if (process_begin) { lua_pushliteral(L, "begin"); lua_pushvalue(L, 3); lua_settable(L, -3); } if (process_end) { lua_pushliteral(L, "end"); lua_pushvalue(L, 4); lua_settable(L, -3); } pomlog(POMLOG_DEBUG "Output listening to event %s", evt_name); return 0; }
bool my_lua_import_hwstub() { int oldtop = lua_gettop(g_lua); lua_newtable(g_lua); // hwstub lua_newtable(g_lua); // options lua_pushboolean(g_lua, g_quiet); lua_setfield(g_lua, -2, "quiet"); lua_setfield(g_lua, -2, "options"); lua_newtable(g_lua); // dev lua_newtable(g_lua); // version lua_pushinteger(g_lua, g_hwdev_ver.bMajor); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, g_hwdev_ver.bMinor); lua_setfield(g_lua, -2, "minor"); lua_pushinteger(g_lua, g_hwdev_ver.bRevision); lua_setfield(g_lua, -2, "revision"); lua_setfield(g_lua, -2, "version"); lua_newtable(g_lua); // layout lua_newtable(g_lua); // code lua_pushinteger(g_lua, g_hwdev_layout.dCodeStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dCodeSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "code"); lua_newtable(g_lua); // stack lua_pushinteger(g_lua, g_hwdev_layout.dStackStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dStackSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "stack"); lua_newtable(g_lua); // buffer lua_pushinteger(g_lua, g_hwdev_layout.dBufferStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dBufferSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "buffer"); lua_setfield(g_lua, -2, "layout"); lua_newtable(g_lua); // target lua_pushstring(g_lua, g_hwdev_target.bName); lua_setfield(g_lua, -2, "name"); lua_pushinteger(g_lua, g_hwdev_target.dID); lua_setfield(g_lua, -2, "id"); lua_pushinteger(g_lua, HWSTUB_TARGET_UNK); lua_setfield(g_lua, -2, "UNK"); lua_pushinteger(g_lua, HWSTUB_TARGET_STMP); lua_setfield(g_lua, -2, "STMP"); lua_pushinteger(g_lua, HWSTUB_TARGET_PP); lua_setfield(g_lua, -2, "PP"); lua_pushinteger(g_lua, HWSTUB_TARGET_RK27); lua_setfield(g_lua, -2, "RK27"); lua_pushinteger(g_lua, HWSTUB_TARGET_ATJ); lua_setfield(g_lua, -2, "ATJ"); lua_setfield(g_lua, -2, "target"); if(g_hwdev_target.dID == HWSTUB_TARGET_STMP) { lua_newtable(g_lua); // stmp lua_pushinteger(g_lua, g_hwdev_stmp.wChipID); lua_setfield(g_lua, -2, "chipid"); lua_pushinteger(g_lua, g_hwdev_stmp.bRevision); lua_setfield(g_lua, -2, "rev"); lua_pushinteger(g_lua, g_hwdev_stmp.bPackage); lua_setfield(g_lua, -2, "package"); lua_setfield(g_lua, -2, "stmp"); } else if(g_hwdev_target.dID == HWSTUB_TARGET_PP) { lua_newtable(g_lua); // pp lua_pushinteger(g_lua, g_hwdev_pp.wChipID); lua_setfield(g_lua, -2, "chipid"); lua_pushlstring(g_lua, (const char *)g_hwdev_pp.bRevision, 2); lua_setfield(g_lua, -2, "rev"); lua_setfield(g_lua, -2, "pp"); } lua_pushlightuserdata(g_lua, (void *)&hw_read8); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read8"); lua_pushlightuserdata(g_lua, (void *)&hw_read16); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read16"); lua_pushlightuserdata(g_lua, (void *)&hw_read32); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read32"); lua_pushlightuserdata(g_lua, (void *)&hw_write8); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write8"); lua_pushlightuserdata(g_lua, (void *)&hw_write16); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write16"); lua_pushlightuserdata(g_lua, (void *)&hw_write32); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write32"); lua_pushcclosure(g_lua, my_lua_printlog, 0); lua_setfield(g_lua, -2, "print_log"); lua_pushcclosure(g_lua, my_lua_call, 0); lua_setfield(g_lua, -2, "call"); lua_pushcclosure(g_lua, my_lua_jump, 0); lua_setfield(g_lua, -2, "jump"); lua_setfield(g_lua, -2, "dev"); lua_newtable(g_lua); // host lua_newtable(g_lua); // version lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR); lua_setfield(g_lua, -2, "minor"); lua_setfield(g_lua, -2, "version"); lua_setfield(g_lua, -2, "host"); lua_newtable(g_lua); // soc lua_setfield(g_lua, -2, "soc"); lua_newtable(g_lua); // help lua_pushinteger(g_lua, 1); lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 2); lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 3); lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z)."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 4); lua_pushstring(g_lua, "Example: help(\"hwstub\")."); lua_settable(g_lua, -3); lua_setfield(g_lua, -2, "help"); lua_pushcclosure(g_lua, my_lua_udelay, 0); lua_setfield(g_lua, -2, "udelay"); lua_setglobal(g_lua, "hwstub"); lua_pushcfunction(g_lua, my_lua_help); lua_setglobal(g_lua, "help"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "exit"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "quit"); if(lua_gettop(g_lua) != oldtop) { printf("internal error: unbalanced my_lua_import_soc\n"); return false; } return true; }
bool register_lua_bindings(lua_State* L, Scene* scene, GLFWwindow* window){ maan::module_(L, "glm") //Register vec3 .class_<glm::vec3>("vec3") .def_constructor<float, float, float>() .def_constructor<float>() .def_constructor<glm::vec3>() .def_operator<maan::add, glm::vec3>() .def_operator<maan::sub, glm::vec3>() .def_operator<maan::mul, glm::vec3>() .def_operator<maan::add, float>() .def_operator<maan::sub, float>() .def_operator<maan::mul, float>() .def_readwrite("x", &glm::vec3::x) .def_readwrite("y", &glm::vec3::y) .def_readwrite("z", &glm::vec3::z) .endef() .function_("cross", (glm::vec3 (*)(const glm::vec3&, const glm::vec3&)) glm::cross) .function_("dot", (float (*)(const glm::vec3&, const glm::vec3&)) glm::dot) .function_("normalize", (glm::vec3 (*)(const glm::vec3&)) glm::normalize) //Register vec4 .class_<glm::vec4>("vec4") .def_constructor<float, float, float, float>() .def_constructor<float>() .def_constructor<glm::vec4>() .def_operator<maan::add, glm::vec4>() .def_operator<maan::sub, glm::vec4>() .def_operator<maan::mul, glm::vec4>() .def_operator<maan::add, float>() .def_operator<maan::sub, float>() .def_operator<maan::mul, float>() .def_readwrite("x", &glm::vec4::x) .def_readwrite("y", &glm::vec4::y) .def_readwrite("z", &glm::vec4::z) .def_readwrite("w", &glm::vec4::w) .endef() //TODO: Matrix access. .class_<glm::mat3>("mat3") .def_constructor<float>() .def_constructor<glm::mat3>() .def_constructor<glm::mat4>() .def_operator<maan::add, glm::mat3>() .def_operator<maan::sub, glm::mat3>() .def_operator<maan::mul, glm::mat3>() .def_operator<maan::mul, glm::vec3>() .def_operator<maan::add, float>() .def_operator<maan::sub, float>() .def_operator<maan::mul, float>() .endef() .function_("column", (glm::vec3 (*)(const glm::mat3&, int index)) glm::column) .function_("row", (glm::vec3 (*)(const glm::mat3&, int index)) glm::row) .function_("inverse", (glm::mat3 (*)(const glm::mat3&)) glm::inverse) .function_("transpose", (glm::mat3 (*)(const glm::mat3&)) glm::transpose) .class_<glm::mat4>("mat4") .def_constructor<float>() .def_constructor<glm::mat4>() .def_operator<maan::add, glm::mat4>() .def_operator<maan::sub, glm::mat4>() .def_operator<maan::mul, glm::mat4>() .def_operator<maan::mul, glm::vec4>() .def_operator<maan::add, float>() .def_operator<maan::sub, float>() .def_operator<maan::mul, float>() .endef() .function_("column", (glm::vec4 (*)(const glm::mat4&, int index)) glm::column) .function_("row", (glm::vec4 (*)(const glm::mat4&, int index)) glm::row) .function_("inverse", (glm::mat4 (*)(const glm::mat4&)) glm::inverse) .function_("transpose", (glm::mat4 (*)(const glm::mat4&)) glm::transpose); maan::module_(L, "scene") .class_<Particle>("Particle") .def_constructor<>() .def_constructor<const Particle&>() .def_readwrite("shape_id", &Particle::shape_id) .def_readwrite("rot", &Particle::rot) .def_readwrite("pos", &Particle::pos) .def_readwrite("size", &Particle::size) .endef() //Register shape .class_<Sphere>("Sphere") .def_constructor<>() .endef() //Register Mesh .class_<Mesh>("Mesh") .def_constructor<>() .def("add_vertex", &Mesh::add_vertex) .endef() .class_<Text::Properties>("TextProperties") .def_constructor<>() .def_constructor<const char*, float, const glm::vec4&, int, int>() .def_readwrite("color", &Text::Properties::color_) .def_readwrite("font", &Text::Properties::font_) .def_readwrite("width", &Text::Properties::width_) .def_readwrite("x", &Text::Properties::x_) .def_readwrite("y", &Text::Properties::y_) .endef() .function_("set_fov_degrees", &Scene::set_fov_degrees, scene) .function_("get_fov_degrees", &Scene::get_fov_degrees, scene) .function_("rotate", &Scene::rotate, scene) .function_("select_particle", &Scene::select_particle, scene) .function_("hide_particle", &Scene::hide_particle, scene) .function_("unhide_particle", &Scene::unhide_particle, scene) .function_("set_particle_color", &Scene::set_particle_color, scene) .function_("toggle_particle_point_drawing", &Scene::toggle_particle_point_drawing, scene) .function_("set_point_radius", &Scene::set_point_radius, scene) .function_("set_point_outline_radius", &Scene::set_point_outline_radius, scene) .function_("set_point_color", &Scene::set_point_color, scene) .function_("set_point_outline_color", &Scene::set_point_outline_color, scene) .function_("set_particle_selection_color", &Scene::set_particle_selection_color, scene) .function_("set_particle_selection_width_fraction", &Scene::set_particle_selection_width_fraction, scene) .function_("set_box_line_width", &Scene::set_box_line_width, scene) .function_("is_particle_selected", &Scene::is_particle_selected, scene) .function_("clear_particle_selections", &Scene::clear_particle_selections, scene) .function_("enable_clip_plane", &Scene::enable_clip_plane, scene) .function_("disable_clip_plane", &Scene::disable_clip_plane, scene) .function_("toggle_box", &Scene::toggle_box, scene) .function_("is_ssao_blur_enabled", &Scene::is_ssao_blur_enabled, scene) .function_("toggle_ssao_blur", &Scene::toggle_ssao_blur, scene) .function_("set_ssao_num_samples", &Scene::set_ssao_num_samples, scene) .function_("get_ssao_num_samples", &Scene::get_ssao_num_samples, scene) .function_("set_ssao_radius", &Scene::set_ssao_radius, scene) .function_("get_ssao_radius", &Scene::get_ssao_radius, scene) .function_("set_clip_plane", &Scene::set_clip_plane, scene) .function_("get_view_matrix", &Scene::get_view_matrix, scene) .function_("get_projection_matrix", &Scene::get_projection_matrix, scene) .function_("get_model_matrix", &Scene::get_model_matrix, scene) .function_("get_view_position", &Scene::get_view_position, scene) .function_("set_view_position", &Scene::set_view_position, scene) .function_("get_view_direction", &Scene::get_view_direction, scene) .function_("set_view_direction", &Scene::set_view_direction, scene) .function_("get_light_intensity", &Scene::get_light_intensity, scene) .function_("set_light_intensity", &Scene::set_light_intensity, scene) .function_("get_light_ambient_intensity", &Scene::get_light_ambient_intensity, scene) .function_("set_light_ambient_intensity", &Scene::set_light_ambient_intensity, scene) .function_("get_light_diffuse_intensity", &Scene::get_light_diffuse_intensity, scene) .function_("set_light_diffuse_intensity", &Scene::set_light_diffuse_intensity, scene) .function_("get_light_specular_intensity", &Scene::get_light_specular_intensity, scene) .function_("set_light_specular_intensity", &Scene::set_light_specular_intensity, scene) .function_("get_background_color", &Scene::get_background_color, scene) .function_("set_background_color", &Scene::set_background_color, scene) .function_("get_sky_color", &Scene::get_sky_color, scene) .function_("set_sky_color", &Scene::set_sky_color, scene) .function_("get_light_direction", &Scene::get_light_direction, scene) .function_("set_light_direction", &Scene::set_light_direction, scene) .function_("draw_text", &Scene::draw_text, scene) .function_("save_snapshot_png", &Scene::save_snapshot_png, scene); #define ADD_CLASS_FUNCTION(cls, name)\ {#name, lua ##cls##_##name}, { luaL_Reg funcs[] = { ADD_CLASS_FUNCTION(Scene, load) ADD_CLASS_FUNCTION(Scene, raw_load) ADD_CLASS_FUNCTION(Scene, set_projection_type) ADD_CLASS_FUNCTION(Scene, raytrace) {NULL, NULL} }; lua_getglobal(L, "scene"); lua_pushlightuserdata(L, reinterpret_cast<void*>(scene)); luaL_setfuncs(L, funcs, 1); lua_pop(L, 1); } { luaL_Reg funcs[] = { ADD_CLASS_FUNCTION(Window, size) ADD_CLASS_FUNCTION(Window, position) ADD_CLASS_FUNCTION(Window, set_size) ADD_CLASS_FUNCTION(Window, set_position) ADD_CLASS_FUNCTION(Window, set_title) {NULL, NULL} }; lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, "window"); lua_pushlightuserdata(L, window); luaL_setfuncs(L, funcs, 1); lua_pop(L, 1); register_keyboard_keys(L); register_mouse_buttons(L); } return true; }
static int lb_topointer(lua_State *L) { buffer *b = lb_checkbuffer(L, 1); size_t offset = real_offset(luaL_optinteger(L, 2, 1), b->len); lua_pushlightuserdata(L, &b->str[offset]); return 1; }
static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) { //push data table here lua_newtable(L); lua_pushinteger(L, engine->get_readonly_context().get_side()); lua_setfield(L, -2, "side"); //stack size is 2 [- 1: new table; -2 ai as string] static luaL_Reg const callbacks[] = { { "attack", &cfun_ai_execute_attack }, // Move maps { "get_new_dst_src", &cfun_ai_get_dstsrc }, { "get_new_src_dst", &cfun_ai_get_srcdst }, { "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc }, { "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst }, { "recalculate_move_maps", &cfun_ai_recalculate_move_maps }, { "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy }, // End of move maps // Goals and targets { "get_targets", &cfun_ai_get_targets }, // End of G & T // Aspects { "get_aggression", &cfun_ai_get_aggression }, { "get_avoid", &cfun_ai_get_avoid }, { "get_attack_depth", &cfun_ai_get_attack_depth }, { "get_attacks", &cfun_ai_get_attacks }, { "get_caution", &cfun_ai_get_caution }, { "get_grouping", &cfun_ai_get_grouping }, { "get_leader_aggression", &cfun_ai_get_leader_aggression }, { "get_leader_goal", &cfun_ai_get_leader_goal }, { "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep }, { "get_leader_value", &cfun_ai_get_leader_value }, { "get_number_of_possible_recruits_to_force_recruit", &cfun_ai_get_number_of_possible_recruits_to_force_recruit }, { "get_passive_leader", &cfun_ai_get_passive_leader }, { "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep }, { "get_recruitment_ignore_bad_combat", &cfun_ai_get_recruitment_ignore_bad_combat }, { "get_recruitment_ignore_bad_movement", &cfun_ai_get_recruitment_ignore_bad_movement }, { "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern }, { "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting }, { "get_simple_targeting", &cfun_ai_get_simple_targeting }, { "get_support_villages", &cfun_ai_get_support_villages }, { "get_village_value", &cfun_ai_get_village_value }, { "get_villages_per_scout", &cfun_ai_get_villages_per_scout }, // End of aspects // Validation/cache functions { "is_dst_src_valid", &cfun_ai_is_dst_src_valid }, { "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid }, { "is_src_dst_valid", &cfun_ai_is_src_dst_valid }, { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid }, // End of validation functions { "move", &cfun_ai_execute_move_partial }, { "move_full", &cfun_ai_execute_move_full }, { "recall", &cfun_ai_execute_recall }, { "recruit", &cfun_ai_execute_recruit }, { "stopunit_all", &cfun_ai_execute_stopunit_all }, { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks }, { "stopunit_moves", &cfun_ai_execute_stopunit_moves }, { "synced_command", &cfun_ai_execute_synced_command }, { "suitable_keep", &cfun_ai_get_suitable_keep }, { "check_recall", &cfun_ai_check_recall }, { "check_move", &cfun_ai_check_move }, { "check_stopunit", &cfun_ai_check_stopunit }, { "check_synced_command", &cfun_ai_check_synced_command }, { "check_attack", &cfun_ai_check_attack }, { "check_recruit", &cfun_ai_check_recruit }, //{ "",}, //{ "",}, { NULL, NULL } }; for (const luaL_Reg* p = callbacks; p->name; ++p) { lua_pushlightuserdata(L, engine); lua_pushcclosure(L, p->func, 1); lua_setfield(L, -2, p->name); } }
/* Choose whether to do a regular or special persistence based on an object's * metatable. "default" is whether the object, if it doesn't have a __persist * entry, is literally persistable or not. * Pushes the unpersist closure and returns true if special persistence is * used. */ static int persistspecialobject(PersistInfo *pi, int defaction) { /* perms reftbl ... obj */ lua_checkstack(pi->L, 4); /* Check whether we should persist literally, or via the __persist * metafunction */ if(!lua_getmetatable(pi->L, -1)) { if(defaction) { { int zero = 0; pi->writer(pi->L, &zero, sizeof(int), pi->ud); } return 0; } else { lua_pushstring(pi->L, "Type not literally persistable by default"); lua_error(pi->L); } } /* perms reftbl sptbl ... obj mt */ lua_pushstring(pi->L, "__persist"); /* perms reftbl sptbl ... obj mt "__persist" */ lua_rawget(pi->L, -2); /* perms reftbl sptbl ... obj mt __persist? */ if(lua_isnil(pi->L, -1)) { /* perms reftbl sptbl ... obj mt nil */ lua_pop(pi->L, 2); /* perms reftbl sptbl ... obj */ if(defaction) { { int zero = 0; pi->writer(pi->L, &zero, sizeof(int), pi->ud); } return 0; } else { lua_pushstring(pi->L, "Type not literally persistable by default"); lua_error(pi->L); return 0; /* not reached */ } } else if(lua_isboolean(pi->L, -1)) { /* perms reftbl sptbl ... obj mt bool */ if(lua_toboolean(pi->L, -1)) { /* perms reftbl sptbl ... obj mt true */ lua_pop(pi->L, 2); /* perms reftbl sptbl ... obj */ { int zero = 0; pi->writer(pi->L, &zero, sizeof(int), pi->ud); } return 0; } else { lua_pushstring(pi->L, "Metatable forbade persistence"); lua_error(pi->L); return 0; /* not reached */ } } else if(!lua_isfunction(pi->L, -1)) { lua_pushstring(pi->L, "__persist not nil, boolean, or function"); lua_error(pi->L); } /* perms reftbl ... obj mt __persist */ lua_pushvalue(pi->L, -3); /* perms reftbl ... obj mt __persist obj */ #ifdef PLUTO_PASS_USERDATA_TO_PERSIST lua_pushlightuserdata(pi->L, (void*)pi->writer); lua_pushlightuserdata(pi->L, pi->ud); /* perms reftbl ... obj mt __persist obj ud */ lua_call(pi->L, 3, 1); /* perms reftbl ... obj mt func? */ #else lua_call(pi->L, 1, 1); /* perms reftbl ... obj mt func? */ #endif /* perms reftbl ... obj mt func? */ if(!lua_isfunction(pi->L, -1)) { lua_pushstring(pi->L, "__persist function did not return a function"); lua_error(pi->L); } /* perms reftbl ... obj mt func */ { int one = 1; pi->writer(pi->L, &one, sizeof(int), pi->ud); } persist(pi); /* perms reftbl ... obj mt func */ lua_pop(pi->L, 2); /* perms reftbl ... obj */ return 1; }
void sinsp_chisel::load(string cmdstr) { m_filename = cmdstr; trim(cmdstr); ifstream is; // // Try to open the file as is // if(!openfile(m_filename, &is)) { // // Try to add the .sc extension // if(!openfile(m_filename + ".sc", &is)) { if(!openfile(m_filename + ".lua", &is)) { throw sinsp_exception("can't open file " + m_filename); } } } // // Bring the file into a string // string docstr((istreambuf_iterator<char>(is)), istreambuf_iterator<char>()); #ifdef HAS_LUA_CHISELS // // Rewind the stream // is.seekg(0); // // Load the file // std::istreambuf_iterator<char> eos; std::string scriptstr(std::istreambuf_iterator<char>(is), eos); // // Open the script // m_ls = lua_open(); luaL_openlibs(m_ls); // // Load our own lua libs // luaL_openlib(m_ls, "sysdig", ll_sysdig, 0); luaL_openlib(m_ls, "chisel", ll_chisel, 0); luaL_openlib(m_ls, "evt", ll_evt, 0); // // Add our chisel paths to package.path // for(uint32_t j = 0; j < g_chisel_dirs->size(); j++) { string path(g_chisel_dirs->at(j).m_dir); path += "?.lua"; add_lua_package_path(m_ls, path.c_str()); } // // Load the script // if(luaL_loadstring(m_ls, scriptstr.c_str()) || lua_pcall(m_ls, 0, 0, 0)) { throw sinsp_exception("Failed to load chisel " + m_filename + ": " + lua_tostring(m_ls, -1)); } // // Allocate the chisel context for the script // m_lua_cinfo = new chiselinfo(m_inspector); // // Set the context globals // lua_pushlightuserdata(m_ls, this); lua_setglobal(m_ls, "sichisel"); // // Extract the args // lua_getglobal(m_ls, "args"); if(!lua_istable(m_ls, -1)) { throw sinsp_exception("Failed to load chisel " + m_filename + ": args table missing"); } try { parse_lua_chisel_args(m_ls, &m_lua_script_info); } catch(sinsp_exception& e) { throw e; } // // Check if the script has an on_event // lua_getglobal(m_ls, "on_event"); if(lua_isfunction(m_ls, -1)) { m_lua_has_handle_evt = true; lua_pop(m_ls, 1); } #endif is.close(); }
/* Top-level delegating persist function */ static void persist(PersistInfo *pi) { /* Grab the object's type. */ int type = lua_type(pi->L, -1); int simple = type == LUA_TNIL || type == LUA_TBOOLEAN || type == LUA_TNUMBER || type == LUA_TLIGHTUSERDATA; /* Increment the number of objects persisted. */ ++(pi->counter); /* If the type isn't simple, check to see if one is already in the reftable. */ if(!simple) { /* perms reftbl ... obj */ lua_checkstack(pi->L, 2); /* If the object has already been written, write a reference to it */ lua_pushvalue(pi->L, -1); /* perms reftbl ... obj obj */ lua_rawget(pi->L, 2); /* perms reftbl ... obj ref? */ if(!lua_isnil(pi->L, -1)) { /* perms reftbl ... obj ref */ int zero = 0; int ref = (intptr_t)lua_touserdata(pi->L, -1); pi->writer(pi->L, &zero, sizeof(int), pi->ud); pi->writer(pi->L, &ref, sizeof(int), pi->ud); lua_pop(pi->L, 1); /* perms reftbl ... obj ref */ #ifdef PLUTO_DEBUG printindent(pi->level); printf("0 %d\n", ref); #endif return; } /* perms reftbl ... obj nil */ lua_pop(pi->L, 1); } /* perms reftbl ... obj */ /* If the object is nil, write the pseudoreference 0 */ if(lua_isnil(pi->L, -1)) { int zero = 0; /* firsttime */ pi->writer(pi->L, &zero, sizeof(int), pi->ud); /* ref */ pi->writer(pi->L, &zero, sizeof(int), pi->ud); #ifdef PLUTO_DEBUG printindent(pi->level); printf("0 0\n"); #endif return; } { /* indicate that it's the first time */ int one = 1; pi->writer(pi->L, &one, sizeof(int), pi->ud); } /* put the value in the reftable if necessary. Simple types don't need to be put in the reftable. */ if(!simple) { lua_pushvalue(pi->L, -1); /* perms reftbl ... obj obj */ lua_pushlightuserdata(pi->L, (void*)((intptr_t) pi->counter)); /* perms reftbl ... obj obj ref */ lua_rawset(pi->L, 2); /* perms reftbl ... obj */ } pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud); /* At this point, we'll give the permanents table a chance to play. */ { lua_pushvalue(pi->L, -1); /* perms reftbl ... obj obj */ lua_gettable(pi->L, 1); /* perms reftbl ... obj permkey? */ if(!lua_isnil(pi->L, -1)) { /* perms reftbl ... obj permkey */ int type = PLUTO_TPERMANENT; #ifdef PLUTO_DEBUG printindent(pi->level); printf("1 %d PERM\n", pi->counter); pi->level++; #endif pi->writer(pi->L, &type, sizeof(int), pi->ud); persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... obj */ #ifdef PLUTO_DEBUG pi->level--; #endif return; } else { /* perms reftbl ... obj nil */ lua_pop(pi->L, 1); /* perms reftbl ... obj */ } /* perms reftbl ... obj */ } { int type = lua_type(pi->L, -1); pi->writer(pi->L, &type, sizeof(int), pi->ud); #ifdef PLUTO_DEBUG printindent(pi->level); printf("1 %d %d\n", pi->counter, type); pi->level++; #endif } switch(lua_type(pi->L, -1)) { case LUA_TBOOLEAN: persistboolean(pi); break; case LUA_TLIGHTUSERDATA: persistlightuserdata(pi); break; case LUA_TNUMBER: persistnumber(pi); break; case LUA_TSTRING: persiststring(pi); break; case LUA_TTABLE: persisttable(pi); break; case LUA_TFUNCTION: persistfunction(pi); break; case LUA_TTHREAD: persistthread(pi); break; case LUA_TPROTO: persistproto(pi); break; case LUA_TUPVAL: persistupval(pi); break; case LUA_TUSERDATA: persistuserdata(pi); break; default: lua_assert(0); } #ifdef PLUTO_DEBUG pi->level--; #endif }
LUA_INLINE void lua_rawgetp(lua_State* L, int i, const void* p) { int abs_i = lua_absindex(L, i); lua_pushlightuserdata(L, (void*)p); lua_rawget(L, abs_i); }
// Called from C to open a pload static int addon_output_pload_open(void *obj, void **priv, struct pload *pload) { struct addon_instance_priv *p = obj; // Lock the output pom_mutex_lock(&p->lock); lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self struct addon_output_pload_priv *ppriv = malloc(sizeof(struct addon_output_pload_priv)); if (!ppriv) { pom_mutex_unlock(&p->lock); pom_oom(sizeof(struct addon_output_pload_priv)); return POM_ERR; } memset(ppriv, 0, sizeof(struct addon_output_pload_priv)); *priv = ppriv; // Get the __pload_listener table lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the open function lua_getfield(p->L, -1, "open"); // Stack : self, __pload_listener, open_func // Check if there is an open function if (lua_isnil(p->L, -1)) { pom_mutex_unlock(&p->lock); lua_pop(p->L, 3); // Stack : empty return POM_OK; } // Add self lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, open_func, self // Create a new table for the pload priv and store it into __pload_listener lua_newtable(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add output_pload_data to it addon_pload_data_push(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_data lua_setfield(p->L, -2, "__pload_data"); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add the new priv to the __pload_listener table lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv lua_pushvalue(p->L, -2); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv, pload_priv_table lua_settable(p->L, -6); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add the pload to the args addon_pload_push(p->L, pload, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload // Call the open function addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result int res = 0; if (!lua_isboolean(p->L, -1)) { pomlog(POMLOG_WARN "LUA coding error: pload open function result must be a boolean"); } else { res = lua_toboolean(p->L, -1); } if (!res) { // The payload doesn't need to be processed, remove the payload_priv_table and the __pload_data lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, result, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, result lua_pushnil(p->L); // Stack : self, __pload_listener, result, nil lua_setfield(p->L, -3, "__pload_data"); // Stack : self, __pload_listener, result } // Remove leftovers lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; }
/* | Allows user scripts to observe filedescriptors | | Params on Lua stack: | 1: file descriptor | 2: function to call when read becomes ready | 3: function to call when write becomes ready */ static int l_observe_fd( lua_State *L ) { int fd = luaL_checknumber( L, 1 ); bool ready = false; bool writey = false; // Stores the user function in the lua registry. // It uses the address of the cores ready/write functions // for the user as key if( !lua_isnoneornil( L, 2 ) ) { lua_pushlightuserdata( L, (void *) user_obs_ready ); lua_gettable( L, LUA_REGISTRYINDEX ); if( lua_isnil( L, -1 ) ) { lua_pop ( L, 1 ); lua_newtable ( L ); lua_pushlightuserdata ( L, (void *) user_obs_ready ); lua_pushvalue ( L, -2 ); lua_settable ( L, LUA_REGISTRYINDEX ); } lua_pushnumber ( L, fd ); lua_pushvalue ( L, 2 ); lua_settable ( L, -3 ); lua_pop ( L, 1 ); ready = true; } if( !lua_isnoneornil( L, 3 ) ) { lua_pushlightuserdata( L, (void *) user_obs_writey ); lua_gettable (L, LUA_REGISTRYINDEX ); if( lua_isnil(L, -1) ) { lua_pop ( L, 1 ); lua_newtable ( L ); lua_pushlightuserdata ( L, (void *) user_obs_writey ); lua_pushvalue ( L, -2 ); lua_settable ( L, LUA_REGISTRYINDEX ); } lua_pushnumber ( L, fd ); lua_pushvalue ( L, 3 ); lua_settable ( L, -3 ); lua_pop ( L, 1 ); writey = true; } // tells the core to watch the fd observe_fd( fd, ready ? user_obs_ready : NULL, writey ? user_obs_writey : NULL, user_obs_tidy, NULL ); return 0; }
// Called from C to write a pload static int addon_output_pload_write(void *output_priv, void *pload_instance_priv, void *data, size_t len) { struct addon_output_pload_priv *ppriv = pload_instance_priv; struct addon_instance_priv *p = output_priv; pom_mutex_lock(&p->lock); // First process all the plugins attached to this pload struct addon_output_pload_plugin *tmp; for (tmp = ppriv->plugins; tmp; tmp = tmp->next) { if (tmp->is_err) continue; if (addon_plugin_pload_write(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv, data, len) != POM_OK) { addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv); tmp->is_err = 1; } } lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the write function lua_getfield(p->L, -1, "write"); // Stack : self, __pload_listener, write_func // Check if there is a write function if (lua_isnil(p->L, -1)) { lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; } // Setup args lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, write_func, self lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, write_func, self, pload_priv lua_gettable(p->L, -4); // Stack : self, __pload_listener, write_func, self, pload_priv_table if (lua_isnil(p->L, -1)) { // There is no pload_priv_table, payload doesn't need to be processed lua_pop(p->L, 5); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; } lua_getfield(p->L, -1, "__pload_data"); // Stack : self, __pload_listener, write_func, self, pload_priv_table, pload_data // Update the pload_data addon_pload_data_update(p->L, -1, data, len); pom_mutex_unlock(&p->lock); int res = addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result int write_res = 0; if (res == POM_OK) { if (!lua_isboolean(p->L, -1)) { pomlog(POMLOG_WARN "LUA coding error: pload write function result must be a boolean"); } else { write_res = lua_toboolean(p->L, -1); } } if (!write_res) { // Remove the pload_priv_table since it failed lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, result, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, result } lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; }
static int db_upvalueid (lua_State *L) { int n = checkupval(L, 1, 2); lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); return 1; }
// Called from C to close a pload static int addon_output_pload_close(void *output_priv, void *pload_instance_priv) { struct addon_output_pload_priv *ppriv = pload_instance_priv; struct addon_instance_priv *p = output_priv; int res = POM_OK; pom_mutex_lock(&p->lock); // Process all the plugins attached to this pload struct addon_output_pload_plugin *tmp; for (tmp = ppriv->plugins; tmp; tmp = tmp->next) { if (tmp->is_err) continue; addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv); } lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the pload_priv_table lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv lua_gettable(p->L, -2); // Stack : self, __pload_listener, pload_priv_table if (lua_isnil(p->L, -1)) { // There is no pload_priv_table, the payload doesn't need to be processed lua_pop(p->L, 3); goto cleanup; } // Remove the payload_priv_table from __pload_listener lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv_table, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, pload_priv_table, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, pload_priv_table // Get the close function lua_getfield(p->L, -2, "close"); // Stack : self, __pload_listener, pload_priv_table, close_func if (lua_isnil(p->L, -1)) { // There is no close function lua_pop(p->L, 4); // Stack : empty goto cleanup; } // Setup args lua_pushvalue(p->L, 1); // Stack : self, __pload_listener, pload_priv_table, close_func, self lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, pload_priv_table, close_func, self, pload_priv_table res = addon_pcall(p->L, 2, 0); // Stack : self, __pload_listener, pload_priv_table lua_pop(p->L, 3); // Stack : empty cleanup: pom_mutex_unlock(&p->lock); while (ppriv->plugins) { tmp = ppriv->plugins; ppriv->plugins = tmp->next; free(tmp); } free(ppriv); return res; }
static int ts_lua_add_hook(lua_State *L) { int type; int entry; TSVConn connp; ts_lua_http_ctx *http_ctx; ts_lua_transform_ctx *transform_ctx; http_ctx = ts_lua_get_http_ctx(L); entry = lua_tointeger(L, 1); // get hook id type = lua_type(L, 2); if (type != LUA_TFUNCTION) return 0; switch (entry) { case TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE: TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, http_ctx->main_contp); lua_pushvalue(L, 2); lua_setglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE); break; case TS_LUA_HOOK_SEND_REQUEST_HDR: TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, http_ctx->main_contp); lua_pushvalue(L, 2); lua_setglobal(L, TS_LUA_FUNCTION_SEND_REQUEST); break; case TS_LUA_HOOK_READ_RESPONSE_HDR: TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, http_ctx->main_contp); lua_pushvalue(L, 2); lua_setglobal(L, TS_LUA_FUNCTION_READ_RESPONSE); break; case TS_LUA_HOOK_SEND_RESPONSE_HDR: TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, http_ctx->main_contp); lua_pushvalue(L, 2); lua_setglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE); break; case TS_LUA_REQUEST_TRANSFORM: case TS_LUA_RESPONSE_TRANSFORM: transform_ctx = (ts_lua_transform_ctx*)TSmalloc(sizeof(ts_lua_transform_ctx)); memset(transform_ctx, 0, sizeof(ts_lua_transform_ctx)); transform_ctx->hctx = http_ctx; connp = TSTransformCreate(ts_lua_transform_entry, http_ctx->txnp); TSContDataSet(connp, transform_ctx); if (entry == TS_LUA_REQUEST_TRANSFORM) { TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_REQUEST_TRANSFORM_HOOK, connp); } else { TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp); } lua_pushlightuserdata(L, transform_ctx); lua_pushvalue(L, 2); lua_rawset(L, LUA_GLOBALSINDEX); break; default: break; } return 0; }
/* ** Opcode interpreter */ const char *match (lua_State *L, const char *o, const char *s, const char *e, Instruction *op, Capture *capture, int ptop, short *labelf, const char **sfail) { /* labeled failure */ Stack stackbase[INITBACK]; Stack *stacklimit = stackbase + INITBACK; Stack *stack = stackbase; /* point to first empty slot in stack */ int capsize = INITCAPSIZE; int captop = 0; /* point to first empty slot in captures */ int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ const Instruction *p = op; /* current instruction */ byte insidepred = OUTPRED; /* labeled failure: label environment is off inside predicates */ stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = insidepred; stack++; /* labeled failure */ *sfail = s; /* labeled failure */ lua_pushlightuserdata(L, stackbase); for (;;) { #if defined(DEBUG) printf("-------------------------------------\n"); printcaplist(capture, capture + captop); printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ", s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop); printinst(op, p); #endif assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); assert(insidepred == INPRED || insidepred == OUTPRED); switch ((Opcode)p->i.code) { case IEnd: { assert(stack == getstackbase(L, ptop) + 1); capture[captop].kind = Cclose; capture[captop].s = NULL; return s; } case IGiveup: { assert(stack == getstackbase(L, ptop)); return NULL; } case IRet: { assert(stack > getstackbase(L, ptop) && (stack - 1)->s == NULL); p = (--stack)->p; continue; } case IAny: { if (s < e) { p++; s++; } else { *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ goto fail; } continue; } case ITestAny: { if (s < e) p += 2; else p += getoffset(p); continue; } case IChar: { if ((byte)*s == p->i.aux && s < e) { p++; s++; } else { *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ goto fail; } continue; } case ITestChar: { if ((byte)*s == p->i.aux && s < e) p += 2; else p += getoffset(p); continue; } case ISet: { int c = (byte)*s; if (testchar((p+1)->buff, c) && s < e) { p += CHARSETINSTSIZE; s++; } else { *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ goto fail; } continue; } case ITestSet: { int c = (byte)*s; if (testchar((p + 2)->buff, c) && s < e) p += 1 + CHARSETINSTSIZE; else p += getoffset(p); continue; } case IBehind: { int n = p->i.aux; if (n > s - o) { *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ goto fail; } s -= n; p++; continue; } case ISpan: { for (; s < e; s++) { int c = (byte)*s; if (!testchar((p+1)->buff, c)) break; } p += CHARSETINSTSIZE; continue; } case IJmp: { p += getoffset(p); continue; } case IChoice: { if (stack == stacklimit) stack = doublestack(L, &stacklimit, ptop); stack->p = p + getoffset(p); stack->s = s; stack->caplevel = captop; stack->labenv = insidepred; /* labeled failure */ stack->predchoice = 0; /* labeled failure */ stack++; p += 2; continue; } case IPredChoice: { /* labeled failure: new instruction */ if (stack == stacklimit) stack = doublestack(L, &stacklimit, ptop); stack->p = p + getoffset(p); stack->s = s; stack->caplevel = captop; stack->labenv = insidepred; stack->predchoice = 1; stack++; insidepred = INPRED; p += 2; continue; } case ICall: { if (stack == stacklimit) stack = doublestack(L, &stacklimit, ptop); stack->s = NULL; stack->p = p + 2; /* save return address */ stack++; p += getoffset(p); continue; } case ICommit: { assert(stack > getstackbase(L, ptop)); assert((stack - 1)->s != NULL); stack--; p += getoffset(p); continue; } case IPartialCommit: { assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); (stack - 1)->s = s; (stack - 1)->caplevel = captop; p += getoffset(p); continue; } case IBackCommit: { assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); s = (--stack)->s; insidepred = stack->labenv; /* labeled failure */ captop = stack->caplevel; p += getoffset(p); continue; } case IThrow: { /* labeled failure */ if (insidepred == OUTPRED) { *labelf = (p+1)->i.key; stack = getstackbase(L, ptop); stack++; } else { while (!(stack-1)->predchoice) { --stack; } *labelf = LFAIL; } *sfail = s; goto fail; } case IThrowRec: { /* labeled failure */ if (insidepred == OUTPRED) { *labelf = (p+2)->i.key; *sfail = s; if (stack == stacklimit) stack = doublestack(L, &stacklimit, ptop); stack->s = NULL; stack->p = p + 3; stack->caplevel = captop; stack++; p += getoffset(p); continue; } else { while (!(stack-1)->predchoice) { --stack; } *labelf = LFAIL; *sfail = s; } goto fail; } case IFailTwice: assert(stack > getstackbase(L, ptop)); stack--; /* go through */ case IFail: *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ fail: { /* pattern failed: try to backtrack */ do { /* remove pending calls */ assert(stack > getstackbase(L, ptop)); s = (--stack)->s; } while (s == NULL); if (ndyncap > 0) /* is there matchtime captures? */ ndyncap -= removedyncap(L, capture, stack->caplevel, captop); captop = stack->caplevel; assert((insidepred == INPRED && stack->labenv == OUTPRED) || insidepred == stack->labenv); insidepred = stack->labenv; /* labeled failure */ p = stack->p; #if defined(DEBUG) printf("**FAIL**\n"); #endif continue; } case ICloseRunTime: { CapState cs; int rem, res, n; int fr = lua_gettop(L) + 1; /* stack index of first result */ cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop; n = runtimecap(&cs, capture + captop, s, &rem); /* call function */ captop -= n; /* remove nested captures */ ndyncap -= rem; /* update number of dynamic captures */ fr -= rem; /* 'rem' items were popped from Lua stack */ res = resdyncaptures(L, fr, s - o, e - o); /* get result */ if (res == -1) { /* fail? */ *labelf = LFAIL; /* labeled failure */ updatefarthest(*sfail, s); /*labeled failure */ goto fail; } s = o + res; /* else update current position */ n = lua_gettop(L) - fr + 1; /* number of new captures */ ndyncap += n; /* update number of dynamic captures */ if (n > 0) { /* any new capture? */ if (fr + n >= SHRT_MAX) luaL_error(L, "too many results in match-time capture"); if ((captop += n + 2) >= capsize) { capture = doublecap(L, capture, captop, n + 2, ptop); capsize = 2 * captop; } /* add new captures to 'capture' list */ adddyncaptures(s, capture + captop - n - 2, n, fr); } p++; continue; } case ICloseCapture: { const char *s1 = s; assert(captop > 0); /* if possible, turn capture into a full capture */ if (capture[captop - 1].siz == 0 && s1 - capture[captop - 1].s < UCHAR_MAX) { capture[captop - 1].siz = s1 - capture[captop - 1].s + 1; p++; continue; } else { capture[captop].siz = 1; /* mark entry as closed */ capture[captop].s = s; goto pushcapture; } } case IOpenCapture: capture[captop].siz = 0; /* mark entry as open */ capture[captop].s = s; goto pushcapture; case IFullCapture: capture[captop].siz = getoff(p) + 1; /* save capture size */ capture[captop].s = s - getoff(p); /* goto pushcapture; */ pushcapture: { capture[captop].idx = p->i.key; capture[captop].kind = getkind(p); if (++captop >= capsize) { capture = doublecap(L, capture, captop, 0, ptop); capsize = 2 * captop; } p++; continue; } default: assert(0); return NULL; } } }