/* weet: * 1. 用负值索引找栈中的对象 * 2. 可以看出一些栈的设计思路 * */ static TObject *negindex (lua_State *L, int idx) { if (idx > LUA_REGISTRYINDEX) { api_check(L, idx != 0 && -idx <= L->top - L->base); return L->top+idx; } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); case LUA_GLOBALSINDEX: return gt(L); default: { TObject *func = (L->base - 1); idx = LUA_GLOBALSINDEX - idx; lua_assert(iscfunction(func)); return (idx <= clvalue(func)->c.nupvalues) /* (weet: 哈哈, 原来lua把闭包变量放在这个地方!! */ ? &clvalue(func)->c.upvalue[idx-1] : NULL; } } }
TObject *negindex (lua_State *L, int idx) { if (idx > LUA_REGISTRYINDEX) { api_check(L, idx != 0 && -idx <= L->top - L->base); return L->top+idx; } else if (idx < -40000) { return (TObject*)luaH_getnum(hvalue(registry(L)), -idx - 40000); } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); case LUA_GLOBALSINDEX: return gt(L); default: { TObject *func = (L->base - 1); idx = LUA_GLOBALSINDEX - idx; lua_assert(iscfunction(func)); return (idx <= clvalue(func)->c.nupvalues) ? &clvalue(func)->c.upvalue[idx-1] : NULL; } } }
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { StkId o = luaA_indexAcceptable(L, idx); return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f; }
LUA_API int lua_iscfunction (lua_State *L, int idx) { StkId o = luaA_indexAcceptable(L, idx); return (o == NULL) ? 0 : iscfunction(o); }
//----------------------------------------------------------------// static void _dumpType ( lua_State* L, int idx, const char *name, bool verbose, TableSet& foundTables ) { MOAILuaState state ( L ); const char *format = DUMP_FORMAT; idx = state.AbsIndex( idx ); StkId tvalue = state->base + idx - 1; switch ( lua_type ( state, idx )) { case LUA_TBOOLEAN: ZLLog::Print ( format, tvalue, "bool", name ); ZLLog::Print ( " = %s", lua_toboolean ( state, idx ) ? "true" : "false" ); break; case LUA_TFUNCTION: { const char *funcType = iscfunction ( tvalue ) ? "C function" : "Lua function"; ZLLog::Print ( format, clvalue ( tvalue ), funcType, name ); break; } case LUA_TLIGHTUSERDATA: ZLLog::Print ( format, pvalue ( tvalue ), "pointer", name ); break; case LUA_TNIL: ZLLog::Print ( format, tvalue, "nil", name ); break; case LUA_TNONE: // Intentionally do nothing--not even the line break. return; case LUA_TNUMBER: ZLLog::Print ( format, tvalue, "number", name ); ZLLog::Print ( " = %f", lua_tonumber ( state, idx )); break; case LUA_TSTRING: ZLLog::Print ( format, rawtsvalue( tvalue ), "string", name ); ZLLog::Print ( " = \"%s\"", lua_tostring ( state, idx )); break; case LUA_TTABLE: { struct Table* htable = hvalue( tvalue ); if ( foundTables.contains ( htable )) { ZLLog::Print ( DUMP_FORMAT " (see above)", htable, "table", name ); break; } else { foundTables.insert ( htable ); ZLLog::Print ( format, htable, "table", name ); if ( verbose ) { ZLLog::Print ( "\n" ); lua_pushnil ( state ); while ( lua_next ( state, idx ) ) { STLString elementName( name ); elementName.append ( "." ); elementName.append ( lua_tostring ( state, -2 )); _dumpType ( state, -1, elementName.c_str (), verbose, foundTables ); lua_pop ( state, 1 ); } } } } return; // suppress newline case LUA_TTHREAD: ZLLog::Print ( format, thvalue( tvalue ), "thread", name ); break; case LUA_TUSERDATA: if ( lua_islightuserdata ( state, idx ) ) { ZLLog::Print ( format, lua_topointer ( state, idx ) , "light userdata", name ); } else { ZLLog::Print ( format, lua_topointer( state, idx ), "userdata", name ); if ( verbose ) { lua_getglobal ( state, "tostring" ); lua_pushvalue ( state, idx ); lua_pcall ( state, 1, 1, 0 ); ZLLog::Print ( "\n\t%s", lua_tostring ( state, -1 )); state.Pop ( 1 ); } } break; default: ZLLog::Print ( "*** Unexpected type: %d ***", lua_type ( state, idx )); } ZLLog::Print ( "\n" ); }