ldebug.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
00003 ** Debug Interface
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 #include <stdarg.h>
00009 #include <stddef.h>
00010 #include <string.h>
00011 
00012 
00013 #define ldebug_c
00014 #define LUA_CORE
00015 
00016 #include "lua.h"
00017 
00018 #include "lapi.h"
00019 #include "lcode.h"
00020 #include "ldebug.h"
00021 #include "ldo.h"
00022 #include "lfunc.h"
00023 #include "lobject.h"
00024 #include "lopcodes.h"
00025 #include "lstate.h"
00026 #include "lstring.h"
00027 #include "ltable.h"
00028 #include "ltm.h"
00029 #include "lvm.h"
00030 
00031 
00032 
00033 
00034 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
00035 
00036 
00037 static int currentpc (lua_State *L, CallInfo *ci) {
00038   if (!isLua(ci)) return -1;  /* function is not a Lua function? */
00039   if (ci == L->ci)
00040     ci->savedpc = L->savedpc;
00041   return pcRel(ci->savedpc, ci_func(ci)->l.p);
00042 }
00043 
00044 
00045 static int currentline (lua_State *L, CallInfo *ci) {
00046   int pc = currentpc(L, ci);
00047   if (pc < 0)
00048     return -1;  /* only active lua functions have current-line information */
00049   else
00050     return getline(ci_func(ci)->l.p, pc);
00051 }
00052 
00053 
00054 /*
00055 ** this function can be called asynchronous (e.g. during a signal)
00056 */
00057 LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
00058   if (func == NULL || mask == 0) {  /* turn off hooks? */
00059     mask = 0;
00060     func = NULL;
00061   }
00062   L->hook = func;
00063   L->basehookcount = count;
00064   resethookcount(L);
00065   L->hookmask = cast_byte(mask);
00066   return 1;
00067 }
00068 
00069 
00070 LUA_API lua_Hook lua_gethook (lua_State *L) {
00071   return L->hook;
00072 }
00073 
00074 
00075 LUA_API int lua_gethookmask (lua_State *L) {
00076   return L->hookmask;
00077 }
00078 
00079 
00080 LUA_API int lua_gethookcount (lua_State *L) {
00081   return L->basehookcount;
00082 }
00083 
00084 
00085 LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
00086   int status;
00087   CallInfo *ci;
00088   lua_lock(L);
00089   for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
00090     level--;
00091     if (f_isLua(ci))  /* Lua function? */
00092       level -= ci->tailcalls;  /* skip lost tail calls */
00093   }
00094   if (level == 0 && ci > L->base_ci) {  /* level found? */
00095     status = 1;
00096     ar->i_ci = cast_int(ci - L->base_ci);
00097   }
00098   else if (level < 0) {  /* level is of a lost tail call? */
00099     status = 1;
00100     ar->i_ci = 0;
00101   }
00102   else status = 0;  /* no such level */
00103   lua_unlock(L);
00104   return status;
00105 }
00106 
00107 
00108 static Proto *getluaproto (CallInfo *ci) {
00109   return (isLua(ci) ? ci_func(ci)->l.p : NULL);
00110 }
00111 
00112 
00113 static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
00114   const char *name;
00115   Proto *fp = getluaproto(ci);
00116   if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
00117     return name;  /* is a local variable in a Lua function */
00118   else {
00119     StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
00120     if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */
00121       return "(*temporary)";
00122     else
00123       return NULL;
00124   }
00125 }
00126 
00127 
00128 LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
00129   CallInfo *ci = L->base_ci + ar->i_ci;
00130   const char *name = findlocal(L, ci, n);
00131   lua_lock(L);
00132   if (name)
00133       luaA_pushobject(L, ci->base + (n - 1));
00134   lua_unlock(L);
00135   return name;
00136 }
00137 
00138 
00139 LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
00140   CallInfo *ci = L->base_ci + ar->i_ci;
00141   const char *name = findlocal(L, ci, n);
00142   lua_lock(L);
00143   if (name)
00144       setobjs2s(L, ci->base + (n - 1), L->top - 1);
00145   L->top--;  /* pop value */
00146   lua_unlock(L);
00147   return name;
00148 }
00149 
00150 
00151 static void funcinfo (lua_Debug *ar, Closure *cl) {
00152   if (cl->c.isC) {
00153     ar->source = "=[C]";
00154     ar->linedefined = -1;
00155     ar->lastlinedefined = -1;
00156     ar->what = "C";
00157   }
00158   else {
00159     ar->source = getstr(cl->l.p->source);
00160     ar->linedefined = cl->l.p->linedefined;
00161     ar->lastlinedefined = cl->l.p->lastlinedefined;
00162     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
00163   }
00164   luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
00165 }
00166 
00167 
00168 static void info_tailcall (lua_Debug *ar) {
00169   ar->name = ar->namewhat = "";
00170   ar->what = "tail";
00171   ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
00172   ar->source = "=(tail call)";
00173   luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
00174   ar->nups = 0;
00175 }
00176 
00177 
00178 static void collectvalidlines (lua_State *L, Closure *f) {
00179   if (f == NULL || f->c.isC) {
00180     setnilvalue(L->top);
00181   }
00182   else {
00183     Table *t = luaH_new(L, 0, 0);
00184     int *lineinfo = f->l.p->lineinfo;
00185     int i;
00186     for (i=0; i<f->l.p->sizelineinfo; i++)
00187       setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
00188     sethvalue(L, L->top, t); 
00189   }
00190   incr_top(L);
00191 }
00192 
00193 
00194 static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
00195                     Closure *f, CallInfo *ci) {
00196   int status = 1;
00197   if (f == NULL) {
00198     info_tailcall(ar);
00199     return status;
00200   }
00201   for (; *what; what++) {
00202     switch (*what) {
00203       case 'S': {
00204         funcinfo(ar, f);
00205         break;
00206       }
00207       case 'l': {
00208         ar->currentline = (ci) ? currentline(L, ci) : -1;
00209         break;
00210       }
00211       case 'u': {
00212         ar->nups = f->c.nupvalues;
00213         break;
00214       }
00215       case 'n': {
00216         ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
00217         if (ar->namewhat == NULL) {
00218           ar->namewhat = "";  /* not found */
00219           ar->name = NULL;
00220         }
00221         break;
00222       }
00223       case 'L':
00224       case 'f':  /* handled by lua_getinfo */
00225         break;
00226       default: status = 0;  /* invalid option */
00227     }
00228   }
00229   return status;
00230 }
00231 
00232 
00233 LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
00234   int status;
00235   Closure *f = NULL;
00236   CallInfo *ci = NULL;
00237   lua_lock(L);
00238   if (*what == '>') {
00239     StkId func = L->top - 1;
00240     luai_apicheck(L, ttisfunction(func));
00241     what++;  /* skip the '>' */
00242     f = clvalue(func);
00243     L->top--;  /* pop function */
00244   }
00245   else if (ar->i_ci != 0) {  /* no tail call? */
00246     ci = L->base_ci + ar->i_ci;
00247     lua_assert(ttisfunction(ci->func));
00248     f = clvalue(ci->func);
00249   }
00250   status = auxgetinfo(L, what, ar, f, ci);
00251   if (strchr(what, 'f')) {
00252     if (f == NULL) setnilvalue(L->top);
00253     else setclvalue(L, L->top, f);
00254     incr_top(L);
00255   }
00256   if (strchr(what, 'L'))
00257     collectvalidlines(L, f);
00258   lua_unlock(L);
00259   return status;
00260 }
00261 
00262 
00263 /*
00264 ** {======================================================
00265 ** Symbolic Execution and code checker
00266 ** =======================================================
00267 */
00268 
00269 #define check(x)    if (!(x)) return 0;
00270 
00271 #define checkjump(pt,pc)  check(0 <= pc && pc < pt->sizecode)
00272 
00273 #define checkreg(pt,reg)  check((reg) < (pt)->maxstacksize)
00274 
00275 
00276 
00277 static int precheck (const Proto *pt) {
00278   check(pt->maxstacksize <= MAXSTACK);
00279   check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
00280   check(!(pt->is_vararg & VARARG_NEEDSARG) ||
00281               (pt->is_vararg & VARARG_HASARG));
00282   check(pt->sizeupvalues <= pt->nups);
00283   check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
00284   check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
00285   return 1;
00286 }
00287 
00288 
00289 #define checkopenop(pt,pc)  luaG_checkopenop((pt)->code[(pc)+1])
00290 
00291 int luaG_checkopenop (Instruction i) {
00292   switch (GET_OPCODE(i)) {
00293     case OP_CALL:
00294     case OP_TAILCALL:
00295     case OP_RETURN:
00296     case OP_SETLIST: {
00297       check(GETARG_B(i) == 0);
00298       return 1;
00299     }
00300     default: return 0;  /* invalid instruction after an open call */
00301   }
00302 }
00303 
00304 
00305 static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
00306   switch (mode) {
00307     case OpArgN: check(r == 0); break;
00308     case OpArgU: break;
00309     case OpArgR: checkreg(pt, r); break;
00310     case OpArgK:
00311       check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
00312       break;
00313   }
00314   return 1;
00315 }
00316 
00317 
00318 static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
00319   int pc;
00320   int last;  /* stores position of last instruction that changed `reg' */
00321   last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */
00322   check(precheck(pt));
00323   for (pc = 0; pc < lastpc; pc++) {
00324     Instruction i = pt->code[pc];
00325     OpCode op = GET_OPCODE(i);
00326     int a = GETARG_A(i);
00327     int b = 0;
00328     int c = 0;
00329     check(op < NUM_OPCODES);
00330     checkreg(pt, a);
00331     switch (getOpMode(op)) {
00332       case iABC: {
00333         b = GETARG_B(i);
00334         c = GETARG_C(i);
00335         check(checkArgMode(pt, b, getBMode(op)));
00336         check(checkArgMode(pt, c, getCMode(op)));
00337         break;
00338       }
00339       case iABx: {
00340         b = GETARG_Bx(i);
00341         if (getBMode(op) == OpArgK) check(b < pt->sizek);
00342         break;
00343       }
00344       case iAsBx: {
00345         b = GETARG_sBx(i);
00346         if (getBMode(op) == OpArgR) {
00347           int dest = pc+1+b;
00348           check(0 <= dest && dest < pt->sizecode);
00349           if (dest > 0) {
00350             int j;
00351             /* check that it does not jump to a setlist count; this
00352                is tricky, because the count from a previous setlist may
00353                have the same value of an invalid setlist; so, we must
00354                go all the way back to the first of them (if any) */
00355             for (j = 0; j < dest; j++) {
00356               Instruction d = pt->code[dest-1-j];
00357               if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
00358             }
00359             /* if 'j' is even, previous value is not a setlist (even if
00360                it looks like one) */
00361             check((j&1) == 0);
00362           }
00363         }
00364         break;
00365       }
00366     }
00367     if (testAMode(op)) {
00368       if (a == reg) last = pc;  /* change register `a' */
00369     }
00370     if (testTMode(op)) {
00371       check(pc+2 < pt->sizecode);  /* check skip */
00372       check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
00373     }
00374     switch (op) {
00375       case OP_LOADBOOL: {
00376         if (c == 1) {  /* does it jump? */
00377           check(pc+2 < pt->sizecode);  /* check its jump */
00378           check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
00379                 GETARG_C(pt->code[pc+1]) != 0);
00380         }
00381         break;
00382       }
00383       case OP_LOADNIL: {
00384         if (a <= reg && reg <= b)
00385           last = pc;  /* set registers from `a' to `b' */
00386         break;
00387       }
00388       case OP_GETUPVAL:
00389       case OP_SETUPVAL: {
00390         check(b < pt->nups);
00391         break;
00392       }
00393       case OP_GETGLOBAL:
00394       case OP_SETGLOBAL: {
00395         check(ttisstring(&pt->k[b]));
00396         break;
00397       }
00398       case OP_SELF: {
00399         checkreg(pt, a+1);
00400         if (reg == a+1) last = pc;
00401         break;
00402       }
00403       case OP_CONCAT: {
00404         check(b < c);  /* at least two operands */
00405         break;
00406       }
00407       case OP_TFORLOOP: {
00408         check(c >= 1);  /* at least one result (control variable) */
00409         checkreg(pt, a+2+c);  /* space for results */
00410         if (reg >= a+2) last = pc;  /* affect all regs above its base */
00411         break;
00412       }
00413       case OP_FORLOOP:
00414       case OP_FORPREP:
00415         checkreg(pt, a+3);
00416         /* go through */
00417       case OP_JMP: {
00418         int dest = pc+1+b;
00419         /* not full check and jump is forward and do not skip `lastpc'? */
00420         if (reg != NO_REG && pc < dest && dest <= lastpc)
00421           pc += b;  /* do the jump */
00422         break;
00423       }
00424       case OP_CALL:
00425       case OP_TAILCALL: {
00426         if (b != 0) {
00427           checkreg(pt, a+b-1);
00428         }
00429         c--;  /* c = num. returns */
00430         if (c == LUA_MULTRET) {
00431           check(checkopenop(pt, pc));
00432         }
00433         else if (c != 0)
00434           checkreg(pt, a+c-1);
00435         if (reg >= a) last = pc;  /* affect all registers above base */
00436         break;
00437       }
00438       case OP_RETURN: {
00439         b--;  /* b = num. returns */
00440         if (b > 0) checkreg(pt, a+b-1);
00441         break;
00442       }
00443       case OP_SETLIST: {
00444         if (b > 0) checkreg(pt, a + b);
00445         if (c == 0) {
00446           pc++;
00447           check(pc < pt->sizecode - 1);
00448         }
00449         break;
00450       }
00451       case OP_CLOSURE: {
00452         int nup, j;
00453         check(b < pt->sizep);
00454         nup = pt->p[b]->nups;
00455         check(pc + nup < pt->sizecode);
00456         for (j = 1; j <= nup; j++) {
00457           OpCode op1 = GET_OPCODE(pt->code[pc + j]);
00458           check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
00459         }
00460         if (reg != NO_REG)  /* tracing? */
00461           pc += nup;  /* do not 'execute' these pseudo-instructions */
00462         break;
00463       }
00464       case OP_VARARG: {
00465         check((pt->is_vararg & VARARG_ISVARARG) &&
00466              !(pt->is_vararg & VARARG_NEEDSARG));
00467         b--;
00468         if (b == LUA_MULTRET) check(checkopenop(pt, pc));
00469         checkreg(pt, a+b-1);
00470         break;
00471       }
00472       default: break;
00473     }
00474   }
00475   return pt->code[last];
00476 }
00477 
00478 #undef check
00479 #undef checkjump
00480 #undef checkreg
00481 
00482 /* }====================================================== */
00483 
00484 
00485 int luaG_checkcode (const Proto *pt) {
00486   return (symbexec(pt, pt->sizecode, NO_REG) != 0);
00487 }
00488 
00489 
00490 static const char *kname (Proto *p, int c) {
00491   if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
00492     return svalue(&p->k[INDEXK(c)]);
00493   else
00494     return "?";
00495 }
00496 
00497 
00498 static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
00499                                const char **name) {
00500   if (isLua(ci)) {  /* a Lua function? */
00501     Proto *p = ci_func(ci)->l.p;
00502     int pc = currentpc(L, ci);
00503     Instruction i;
00504     *name = luaF_getlocalname(p, stackpos+1, pc);
00505     if (*name)  /* is a local? */
00506       return "local";
00507     i = symbexec(p, pc, stackpos);  /* try symbolic execution */
00508     lua_assert(pc != -1);
00509     switch (GET_OPCODE(i)) {
00510       case OP_GETGLOBAL: {
00511         int g = GETARG_Bx(i);  /* global index */
00512         lua_assert(ttisstring(&p->k[g]));
00513         *name = svalue(&p->k[g]);
00514         return "global";
00515       }
00516       case OP_MOVE: {
00517         int a = GETARG_A(i);
00518         int b = GETARG_B(i);  /* move from `b' to `a' */
00519         if (b < a)
00520           return getobjname(L, ci, b, name);  /* get name for `b' */
00521         break;
00522       }
00523       case OP_GETTABLE: {
00524         int k = GETARG_C(i);  /* key index */
00525         *name = kname(p, k);
00526         return "field";
00527       }
00528       case OP_GETUPVAL: {
00529         int u = GETARG_B(i);  /* upvalue index */
00530         *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
00531         return "upvalue";
00532       }
00533       case OP_SELF: {
00534         int k = GETARG_C(i);  /* key index */
00535         *name = kname(p, k);
00536         return "method";
00537       }
00538       default: break;
00539     }
00540   }
00541   return NULL;  /* no useful name found */
00542 }
00543 
00544 
00545 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
00546   Instruction i;
00547   if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
00548     return NULL;  /* calling function is not Lua (or is unknown) */
00549   ci--;  /* calling function */
00550   i = ci_func(ci)->l.p->code[currentpc(L, ci)];
00551   if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
00552       GET_OPCODE(i) == OP_TFORLOOP)
00553     return getobjname(L, ci, GETARG_A(i), name);
00554   else
00555     return NULL;  /* no useful name can be found */
00556 }
00557 
00558 
00559 /* only ANSI way to check whether a pointer points to an array */
00560 static int isinstack (CallInfo *ci, const TValue *o) {
00561   StkId p;
00562   for (p = ci->base; p < ci->top; p++)
00563     if (o == p) return 1;
00564   return 0;
00565 }
00566 
00567 
00568 void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
00569   //logt("luaG_typeerror");
00570   //logg("operation is '%s'", op ? op : "NULL");
00571   const char *name = NULL;
00572   const char *t = luaT_typenames[ttype(o)];
00573   //logg("type name is '%s'", t ? t : "NULL");
00574   const char *kind = (isinstack(L->ci, o)) ?
00575     getobjname(L, L->ci, cast_int(o - L->base), &name) :
00576     NULL;
00577   //logg("kind is '%s'", kind ? kind : "NULL");
00578   if (kind)
00579     luaG_runerror_m(L, "attempt to %s %s " LUA_QS " (a %s value)",
00580         op, kind, name, t);
00581   else
00582     luaG_runerror_m(L, "attempt to %s a %s value", op, t);
00583 }
00584 
00585 
00586 void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
00587   if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
00588   lua_assert(!ttisstring(p1) && !ttisnumber(p1));
00589   luaG_typeerror(L, p1, "concatenate");
00590 }
00591 
00592 
00593 void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
00594   TValue temp;
00595   if (luaV_tonumber(p1, &temp) == NULL)
00596     p2 = p1;  /* first operand is wrong */
00597   luaG_typeerror(L, p2, "perform arithmetic on");
00598 }
00599 
00600 
00601 int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
00602   //logt("luaG_ordererror");
00603   const char *t1 = luaT_typenames[ttype(p1)];
00604   const char *t2 = luaT_typenames[ttype(p2)];
00605 #if 0
00606   // This does not cause a crash on Symbian.
00607   setsvalue2s(L, L->top, luaS_new(L, "dummy message"));
00608   incr_top(L);
00609   luaD_throw(L, LUA_ERRRUN);
00610 #else
00611   if (t1[2] == t2[2])
00612     luaG_runerror_m(L, "attempt to compare two %s values", t1);
00613   else
00614     luaG_runerror_m(L, "attempt to compare %s with %s", t1, t2);
00615 #endif
00616   return 0;
00617 }
00618 
00619 
00620 void luaG_errormsg (lua_State *L) {
00621   //logt("luaG_errormsg");
00622   if (L->errfunc != 0) {  /* is there an error handling function? */
00623     //logt("have error handling function");
00624     StkId errfunc = restorestack(L, L->errfunc);
00625     if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
00626     setobjs2s(L, L->top, L->top - 1);  /* move argument */
00627     setobjs2s(L, L->top - 1, errfunc);  /* push function */
00628     incr_top(L);
00629     luaD_call(L, L->top - 2, 1);  /* call it */
00630   }
00631   //logt("throwing now");
00632   luaD_throw(L, LUA_ERRRUN);
00633 }
00634 
00635 #if EXCEPTION_CRASHES_VARARGS_BUG
00636 // It seems that on Symbian, merely invoking a function with varargs
00637 // can mess up the stack so that an exception (or possibly some other
00638 // kind of a return) will then cause a KERN-EXEC 3. Possibly we will
00639 // have to avoid invoking this function on Symbian until we can find a
00640 // fix. In any case, this is a known problem, see
00641 // http://discussion.forum.nokia.com/forum/showthread.php?t=115248.
00642 // Upgrading to GCCE 4 might possibly help?
00643 void luaG_runerror_wa (lua_State *L, const char *s) {
00644   //logt("luaG_runerror_wa");
00645   setsvalue2s(L, L->top, luaS_new(L, s));
00646   incr_top(L);
00647   luaG_errormsg(L);
00648 }
00649 
00650 #else
00651 
00652 // only used in luaG_runerror
00653 static void addinfo (lua_State *L, const char *msg) {
00654   //logt("addinfo");
00655   CallInfo *ci = L->ci;
00656   if (isLua(ci)) {  /* is Lua code? */
00657     //logt("is Lua code");
00658     char buff[LUA_IDSIZE];  /* add file:line information */
00659     int line = currentline(L, ci);
00660     luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
00661     luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
00662   }
00663 }
00664 
00665 void luaG_runerror_ok (lua_State *L, const char *fmt, ...) {
00666   //logt("luaG_runerror");
00667   va_list argp;
00668   va_start(argp, fmt);
00669   addinfo(L, luaO_pushvfstring(L, fmt, argp));
00670   va_end(argp);
00671   luaG_errormsg(L);
00672 }
00673 
00674 #endif

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1