- ·ç¾Æ ½ºÅà Ãâ·ÂÇϱâ
- assert, error, debug.trackback
- ¿¡·¯ ¹ß»ý½Ã ÄݽºÅà ¾ò¾î³»±â
- ÄÚ·çÆ¾(coroutine) ³»ºÎ¿¡¼ ¹®Á¦°¡ ¹ß»ýÇßÀ» ¶§ ¾Ë¾Æ³»±â
- ½ºÅ©¸³Æ® ó¸® Áß ¿¡·¯ ¹ß»ý½Ã C ÇÔ¼ö È£ÃâÇϱâ
1 ·ç¾Æ ½ºÅà Ãâ·ÂÇϱâ
void print_stack(lua_State* L)
{
int top = lua_gettop(L);
for (int i=top; i>=1; --i)
{
printf("%02d | ", i);
switch (lua_type(L, i))
{
case LUA_TNIL:
printf("nil | \n");
break;
case LUA_TBOOLEAN:
printf("boolean | %d\n", (int)lua_toboolean(L, i));
break;
case LUA_TNUMBER:
printf("number | %f\n", lua_tonumber(L, i));
break;
case LUA_TSTRING:
printf("string | %s\n", lua_tostring(L, i));
break;
case LUA_TTABLE:
printf("table | 0x%08x\n", (int)lua_topointer(L, i));
break;
case LUA_TFUNCTION:
printf("function | 0x%08x\n", (int)lua_topointer(L, i));
break;
case LUA_TUSERDATA:
printf("userdata | 0x%08x\n", (int)lua_topointer(L, i));
break;
case LUA_TTHREAD:
printf("thread | 0x%08x\n", (int)lua_topointer(L, i));
break;
default:
printf("unknown | \n");
break;
}
}
} µüÈ÷ ¹«½¼ ºñ¹ý °°Àº °ÍÀº ¾Æ´Ï´Ù¸¸, ¾Æ·¡¿Í °°Àº ÇÔ¼ö¿Í Á¶ÇÕÇϸé, ·ç¾Æ ½ºÅà °ü·Ã ¹ö±×¸¦ Àâ´Â µ¥ ¾î´À Á¤µµ µµ¿òÀÌ µÈ´Ù.
function print_all_symbols(t, indent, printed)
assert(type(t) == "table")
assert(type(indent) == "number")
assert(type(printed) == "table")
if printed[t] then return end
printed[t] = true
local prefix = ""
for i=0,indent do
prefix = prefix .. " "
end
for key, value in pairs(t) do
print(prefix .. tostring(key) .. "=" .. tostring(value))
if type(value) == "table" then
print_all_symbols(value, indent+1, printed)
end
end
end
print_all_symbols(_G, 0, {})
2 assert, error, debug.trackback
3 ¿¡·¯ ¹ß»ý½Ã ÄݽºÅà ¾ò¾î³»±â
¹®ÀÚ¿À̳ª ÆÄÀÏ¿¡ ÀÖ´Â ½ºÅ©¸³Æ®¸¦ ½ÇÇàÇÒ ¶§, doXXX ½Ã¸®Á ÀÌ¿ëÇÏÁö ¸»°í, lua_pcall ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¾ß ÇÑ´Ù.
//////////////////////////////////////////////////////////////////////////////
/// \brief ¹öÆÛ ¾È¿¡ ÀÖ´Â ½ºÅ©¸³Æ®¸¦ ½ÇÇàÇÑ´Ù.
/// \param script ½ÇÇàÇÒ ½ºÅ©¸³Æ®
/// \param chunkname ½ºÅ©¸³Æ®ÀÇ À̸§. ¿¡·¯°¡ »ý±ä °æ¿ì, µð¹ö±×¿ëÀ¸·Î
/// chunknameÀÌ Ãâ·ÂµÈ´Ù. ±×·¯¹Ç·Î ¾î´À Á¤µµ´Â Àǹ̰¡ ÀÖ´Â °ªÀ» ÁÙ °Í.
/// \return bool ½ºÅ©¸³Æ®¸¦ ¹«»çÈ÷ ½ÇÇàÇÑ °æ¿ì¿¡´Â false¸¦ ¹ÝȯÇϰí, ¹«¾ð°¡
/// ¿¡·¯°¡ »ý±ä °æ¿ì¿¡´Â true¸¦ ¹ÝȯÇÑ´Ù.
//////////////////////////////////////////////////////////////////////////////
bool execute(lua_State* L, const string& script, const string& chunkname)
{
// ¸ÕÀú ½ºÅ©¸³Æ®¸¦ ÆÄ½ÌÇØ¼ ûũ¸¦ ¸¸µç ´ÙÀ½, ½ºÅÿ¡ Ǫ½¬
if (luaL_loadbuffer(L, script.c_str(), script.size(), chunkname.c_str()))
{
// ÆÄ½Ì ½ÇÆÐ!
return true;
}
// Æ®·¹À̽º ÇÔ¼ö¸¦ À§¿¡¼ ÆÄ½ÌÇÑ Ã»Å© ¹Ø¿¡´Ù ³¢¿ö³Ö´Â´Ù.
// Æ®·¹À̽º ÇÔ¼ö´Â Àü¿ª Å×ÀÌºí¿¡ "_TRACEBACK"À̶õ À̸§À¸·Î µé¾î°¡ÀÖ´Ù.
int base = lua_gettop(L);
lua_getglobal(L, "_TRACEBACK");
lua_insert(L, base);
// ½ÇÇàÇÑ´Ù.
return lua_pcall(L, 0, 0, base) != 0;
} À§ÀÇ ÇÔ¼ö¸¦ ÅëÇØ ½ºÅ©¸³Æ®¸¦ ½ÇÇàÇÏ¸é ¿¡·¯ ¹ß»ý½Ã, ½ºÅà ÃÖ»óÀ§¿¡ ¿¡·¯ ¸Þ½ÃÁö¿Í ½ºÅà Ʈ·¹À̽º°¡ ÇϳªÀÇ ¹®ÀÚ¿·Î Ǫ½¬µÈ´Ù. ´ëÃæ ´ÙÀ½°ú °°Àº Çü½ÄÀÌ´Ù.
[string "D:\Cuvit\Stools\SIDE\script\test.lua"]:16: too many players (4 max)
stack traceback
[C]: in function 'PLAYER_CREATE'
[string "D:\Cuvit\Stools\SIDE\Script\test.lua"]:16:in main chunk
¾ÕÂÊÀÇ string, C µîÀº ÇÔ¼ö°¡ ¾îµð¿¡ Á¸ÀçÇÏ´ÂÁö¸¦ ³ªÅ¸³½´Ù. stringÀº ¹®ÀÚ¿ ¹öÆÛ·Î¼ Á¸ÀçÇÑ´Ù´Â Àǹ̰í, C´Â C ÂÊ¿¡ Á¸ÀçÇÑ´Ù´Â Àǹ̴Ù. ¿©±â¿¡´Â ¾øÁö¸¸, fileµµ ÀÖÀ» °Å¶ó´Â °É ½±°Ô ÁüÀÛÇÒ ?ÀÖ´Ù. (¹®ÀÚ¿ ³»ºÎ¿¡ ¶óÀÎ Çǵ尡 µé¾î°¡ Àֱ⠶§¹®¿¡ ¿©·¯ ¶óÀÎÀ¸·Î Ç¥½ÃµÈ °ÍÀ̶ó´Â Á¡À» À¯ÀÇÇÏÀÚ. ½ÇÁ¦ ½ºÅÿ¡ ¿©·¯ ¶óÀÎÀÌ µé¾î°¡ ÀÖ´Â °ÍÀÌ ¾Æ´Ï´Ù.)
µüÈ÷ ½Å°æ½á¾ßÇÒ GUI °°Àº °ÍÀÌ ¾ø´Ù¸é ±×³É Ãâ·ÂÇØµµ µÇ°í, ¾Æ´Ï¶ó¸é "\n" ¹®ÀÚ·Î ºÐ¸®Çؼ Ãâ·ÂÇØµµ µÈ´Ù. ºÐ¸®ÇÑ ´ÙÀ½¿¡ ¾Æ·¡¿¡ ÀÖ´Â ÆÄ½Ì ¹æ¹ýÀ» ÅëÇØ, ÆÄÀÏ+¶óÀÎ+¸Þ½ÃÁö Çü½ÄÀ¸·Î ¸¸µé ¼öµµ ÀÖÀ» °ÍÀÌ´Ù.
4 ÄÚ·çÆ¾(coroutine) ³»ºÎ¿¡¼ ¹®Á¦°¡ ¹ß»ýÇßÀ» ¶§ ¾Ë¾Æ³»±â
ÄÚ·çÆ¾ ³»ºÎ¿¡¼ ¹®¹ý ¿¡·¯ µîÀÌ ³µÀ» ¶§, ·ç¾Æ´Â À̸¦ ȸ鿡 Ãâ·ÂÇØÁÖÁö ¾Ê´Â´Ù. º¸È£ ¸ðµå¿¡¼ µ¿ÀÛÇϱ⠶§¹®ÀÌ´Ù. ÀÌ°É Á¦´ë·Î Ãâ·ÂÇϱâ À§Çؼ´Â...
coroutine.resume(co)
ÀÌ·¸°Ô ÇÒ °ÍÀÌ ¾Æ´Ï¶ó, ´ÙÀ½°ú °°ÀÌ ÇØ¾ßÇÑ´Ù.
success, msg = coroutine.resume(co)
success º¯¼ö¿¡ µé¾î°¥ ¼ö ÀÖ´Â °ªÀº true ¶Ç´Â falseÀÌ´Ù. trueÀÎ °æ¿ì´Â coroutineÀÌ Á¤»óÀûÀ¸·Î Á¾·áµÇ¾ú°Å³ª, »ç¿ëÀÚ°¡ coroutine.yield()¸¦ È£ÃâÇßÀ» °æ¿ìÀÌ´Ù. falseÀÎ °æ¿ì´Â ¹®Á¦°¡ »ý±ä °æ¿ìÀÌ´Ù.
msg º¯¼ö¿¡ µé¾î°¡´Â °ªÀÇ Á¾·ù´Â ¼¼ °¡Áö´Ù. ù°, coroutine.resume()ÀÌ Á¤»ó Á¾·áµÇ¸é¼ »ç¿ëÀÚ°¡ ¸®ÅÏÇÑ °ªÀÏ °æ¿ìÀ̰í, µÎ ¹øÂ°´Â coroutine.yield()¸¦ È£ÃâÇÏ¸é¼ »ç¿ëÀÚ°¡ Àü´ÞÇÑ ÆÄ¶ó¹ÌÅÍ Áß ÇϳªÀÎ °æ¿ìÀ̰í, ¸¶Áö¸·À¸·Î coroutine.resume()ÀÌ ºñÁ¤»ó Á¾·á(¹®¹ý ¿¡·¯ µîÀ¸·Î)µÇ¸é¼ ³ª¿Â ¿¡·¯ ¸Þ½ÃÁö ¹®ÀÚ¿ÀÎ °æ¿ìÀÌ´Ù. Âü°í·Î ù¹øÂ°¿Í µÎ¹øÂ° °æ¿ì, »ç¿ëÀÚ°¡ ¾Æ¹« °Íµµ ¸®ÅÏÇÏÁö ¾Ê°Å³ª, Àü´ÞÇÏÁö ¾ÊÀ¸¸é msg º¯¼ö¿¡´Â nil °ªÀÌ µé¾î°¡°Ô µÈ´Ù.
¾î·µç ¼¼¹øÂ° °æ¿ì, msg¸¦ ÀÌ¿ëÇÏ¸é ¿¡·¯ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÒ ¼ö ÀÖ´Ù. Áï success °ªÀ» º¸°í, falseÀÎ °æ¿ì msg º¯¼ö¸¦ ¹Þ¾Æ³»¾î Ãâ·ÂÇÏ¸é µÇ´Â °ÍÀÌ´Ù. ÀÌ ¿¡·¯ ¸Þ½ÃÁöÀÇ Æ÷¸ËÀº LUA 5.0ÀÇ °æ¿ì, ´ÙÀ½°ú °°´Ù.
[string "CHUNKNAME"]:LINE: ERRORMSG
À̰Ͱú ÇÔ²² ¿¡·¯¸¦ ¹ß»ý½ÃŲ ½ºÅ©¸³Æ®¸¦ Àß Ãâ·ÂÇÏ¸é ²Ï ¾µ¸¸ÇÑ µð¹ö±× Á¤º¸¸¦ ¾òÀ» ¼ö ÀÖ´Ù. (Á» ¹«½ÄÇϱâ´Â ÇÏ´Ù.)
void LuaAPI::debugmsg(ostream& os, const string& msg, const string& script)
{
// ¿¡·¯ ¹ß»ý ½Ã ·ç¾Æ°¡ ¸®ÅÏÇÏ´Â ¿¡·¯ ¸Þ½ÃÁöÀÇ Æ÷¸ËÀº ´ÙÀ½°ú °°´Ù.
// [string "CHUNKNAME"]:LINE: ERRORMSG
// ±×·¯¹Ç·Î "\"]:" ¹®ÀÚ¿À» ãÀº µÚ, ±× ´ÙÀ½ÀÇ ":" ¹®ÀÚ¿À» ã°í,
// ±× »çÀÌÀÇ ¹®ÀÚ¿À» ¼ýÀÚ·Î º¯È¯ÇÏ¸é ¶óÀÎ ¹øÈ£°¡ µÈ´Ù.
size_t line_begin = msg.find("\"]:", 0);
size_t line_end = msg.find(":", line_begin+3);
string line_string = msg.substr(line_begin+3, line_end - line_begin - 3);
int line = atoi(line_string.c_str());
os << "!!! SCRIPT ERROR OCCURRED !!!!" << endl;
os << "=== SCRIPT ERROR MSG >>>" << endl << msg << endl;
os << "=== SCRIPT ERROR OCCURRED LINE >>>" << endl;
for (int i=__max(1, line-2); i<=line+2; i++)
{
if (i == line) os << ">> " << setw(3) << MUtil::itos(i) << "| ";
else os << " " << setw(3) << MUtil::itos(i) << "| ";
string nth = MUtil::nthline(script, (size_t)i);
if (nth.size() < 65) os << nth << endl;
else os << nth.substr(0, 65) << " [...]" << endl;
}
}
5 ½ºÅ©¸³Æ® ó¸® Áß ¿¡·¯ ¹ß»ý½Ã C ÇÔ¼ö È£ÃâÇϱâ
·ç¾Æ ¶óÀ̺귯¸® ¼Ò½º Áß¿¡ $(LUA)\src\lauxlib.c ÆÄÀÏÀ» ¿¬ ´ÙÀ½ callalert ÇÔ¼ö¸¦ ã¾Æ¼ º¸¸é, ¿¡·¯°¡ »ý°åÀ» °æ¿ì, Àü¿ª Å×ÀÌºí¿¡ "_ALERT"¶ó´Â ÇÔ¼ö°¡ ÀÖ´ÂÁö ã¾Æº¸°í, ÀÖÀ¸¸é À̸¦ È£ÃâÇϰí, ¾ø´Ù¸é stderr¿¡ ¿¡·¯ ¸Þ½ÃÁö¸¦ »Ñ¸°´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù.
lauxlib.c
...»ý·«...
static void callalert (lua_State *L, int status)
{
if (status != 0) {
lua_getglobal(L, "_ALERT");
if (lua_isfunction(L, -1)) {
lua_insert(L, -2);
lua_call(L, 1, 0);
}
else {
/* no _ALERT function; print it on stderr */
fprintf(stderr, "%s\n", lua_tostring(L, -2));
lua_pop(L, 2); /* remove error message and _ALERT */
}
}
}
...»ý·«... À̰ÍÀ» ÀÌ¿ëÇÏ¸é ¿¡·¯ ¹ß»ý½Ã¿¡ C ÇÔ¼ö¸¦ È£ÃâÇÒ ¼ö ÀÖ´Ù. Áï "_ALERT"¶ó´Â À̸§À¸·Î C ÇÔ¼ö¸¦ Àü¿ª Å×ÀÌºí¿¡´Ù µî·ÏÇØÁÖ¸é, ¿¡·¯ ¹ß»ý½Ã ·ç¾Æ°¡ À̸¦ È£ÃâÇØÁÖ´Â °ÍÀÌ´Ù.
int myAlert(lua_State* L)
{
string error_msg = string(lua_tostring(L, -1));
cerr << error_msg << endl;
return 0;
}
...»ý·«...
lua_pushcfunction(L, myAlert);
lua_setglobal(L, "_ALERT");
lua_atpanic ÇÔ¼ö¸¦ ÀÌ¿ëÇØµµ °°Àº °á°ú¸¦ ¾òÀ» ¼ö ÀÖ´Ù.
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)