00001 /* 00002 ** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ 00003 ** Auxiliary functions for building Lua libraries 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <ctype.h> 00009 #include <errno.h> 00010 #include <stdarg.h> 00011 #include <stdio.h> 00012 #include <stdlib.h> 00013 #include <string.h> 00014 00015 00016 /* This file uses only the official API of Lua. 00017 ** Any function declared here could be written as an application function. 00018 */ 00019 00020 #define lauxlib_c 00021 #define LUA_LIB 00022 00023 #include "lua.h" 00024 00025 #include "lauxlib.h" 00026 00027 #define FREELIST_REF 0 /* free list of references */ 00028 00029 00030 /* convert a stack index to positive */ 00031 #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ 00032 lua_gettop(L) + (i) + 1) 00033 00034 00035 /* 00036 ** {====================================================== 00037 ** Error-report functions 00038 ** ======================================================= 00039 */ 00040 00041 00042 LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { 00043 lua_Debug ar; 00044 if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ 00045 return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); 00046 lua_getinfo(L, "n", &ar); 00047 if (strcmp(ar.namewhat, "method") == 0) { 00048 narg--; /* do not count `self' */ 00049 if (narg == 0) /* error is in the self argument itself? */ 00050 return luaL_error(L, "calling " LUA_QS " on bad self (%s)", 00051 ar.name, extramsg); 00052 } 00053 if (ar.name == NULL) 00054 ar.name = "?"; 00055 return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", 00056 narg, ar.name, extramsg); 00057 } 00058 00059 00060 LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { 00061 const char *msg = lua_pushfstring(L, "%s expected, got %s", 00062 tname, luaL_typename(L, narg)); 00063 return luaL_argerror(L, narg, msg); 00064 } 00065 00066 00067 static void tag_error (lua_State *L, int narg, int tag) { 00068 luaL_typerror(L, narg, lua_typename(L, tag)); 00069 } 00070 00071 00072 LUALIB_API void luaL_where (lua_State *L, int level) { 00073 lua_Debug ar; 00074 if (lua_getstack(L, level, &ar)) { /* check function at level */ 00075 lua_getinfo(L, "Sl", &ar); /* get info about it */ 00076 if (ar.currentline > 0) { /* is there info? */ 00077 lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); 00078 return; 00079 } 00080 } 00081 lua_pushliteral(L, ""); /* else, no information available... */ 00082 } 00083 00084 00085 LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { 00086 va_list argp; 00087 va_start(argp, fmt); 00088 luaL_where(L, 1); 00089 lua_pushvfstring(L, fmt, argp); 00090 va_end(argp); 00091 lua_concat(L, 2); 00092 return lua_error(L); 00093 } 00094 00095 /* }====================================================== */ 00096 00097 00098 LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, 00099 const char *const lst[]) { 00100 const char *name = (def) ? luaL_optstring(L, narg, def) : 00101 luaL_checkstring(L, narg); 00102 int i; 00103 for (i=0; lst[i]; i++) 00104 if (strcmp(lst[i], name) == 0) 00105 return i; 00106 return luaL_argerror(L, narg, 00107 lua_pushfstring(L, "invalid option " LUA_QS, name)); 00108 } 00109 00110 00111 LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { 00112 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ 00113 if (!lua_isnil(L, -1)) /* name already in use? */ 00114 return 0; /* leave previous value on top, but return 0 */ 00115 lua_pop(L, 1); 00116 lua_newtable(L); /* create metatable */ 00117 lua_pushvalue(L, -1); 00118 lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ 00119 return 1; 00120 } 00121 00122 00123 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { 00124 void *p = lua_touserdata(L, ud); 00125 if (p != NULL) { /* value is a userdata? */ 00126 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ 00127 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ 00128 if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ 00129 lua_pop(L, 2); /* remove both metatables */ 00130 return p; 00131 } 00132 } 00133 } 00134 luaL_typerror(L, ud, tname); /* else error */ 00135 return NULL; /* to avoid warnings */ 00136 } 00137 00138 00139 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { 00140 if (!lua_checkstack(L, space)) 00141 luaL_error(L, "stack overflow (%s)", mes); 00142 } 00143 00144 00145 LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { 00146 if (lua_type(L, narg) != t) 00147 tag_error(L, narg, t); 00148 } 00149 00150 00151 LUALIB_API void luaL_checkany (lua_State *L, int narg) { 00152 if (lua_type(L, narg) == LUA_TNONE) 00153 luaL_argerror(L, narg, "value expected"); 00154 } 00155 00156 00157 LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { 00158 const char *s = lua_tolstring(L, narg, len); 00159 if (!s) tag_error(L, narg, LUA_TSTRING); 00160 return s; 00161 } 00162 00163 00164 LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, 00165 const char *def, size_t *len) { 00166 if (lua_isnoneornil(L, narg)) { 00167 if (len) 00168 *len = (def ? strlen(def) : 0); 00169 return def; 00170 } 00171 else return luaL_checklstring(L, narg, len); 00172 } 00173 00174 00175 LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { 00176 lua_Number d = lua_tonumber(L, narg); 00177 if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ 00178 tag_error(L, narg, LUA_TNUMBER); 00179 return d; 00180 } 00181 00182 00183 LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { 00184 return luaL_opt(L, luaL_checknumber, narg, def); 00185 } 00186 00187 00188 LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { 00189 lua_Integer d = lua_tointeger(L, narg); 00190 if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ 00191 tag_error(L, narg, LUA_TNUMBER); 00192 return d; 00193 } 00194 00195 00196 LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, 00197 lua_Integer def) { 00198 return luaL_opt(L, luaL_checkinteger, narg, def); 00199 } 00200 00201 00202 LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { 00203 if (!lua_getmetatable(L, obj)) /* no metatable? */ 00204 return 0; 00205 lua_pushstring(L, event); 00206 lua_rawget(L, -2); 00207 if (lua_isnil(L, -1)) { 00208 lua_pop(L, 2); /* remove metatable and metafield */ 00209 return 0; 00210 } 00211 else { 00212 lua_remove(L, -2); /* remove only metatable */ 00213 return 1; 00214 } 00215 } 00216 00217 00218 LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { 00219 obj = abs_index(L, obj); 00220 if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ 00221 return 0; 00222 lua_pushvalue(L, obj); 00223 lua_call(L, 1, 1); 00224 return 1; 00225 } 00226 00227 00228 LUALIB_API void (luaL_register) (lua_State *L, const char *libname, 00229 const luaL_Reg *l) { 00230 luaI_openlib(L, libname, l, 0); 00231 } 00232 00233 00234 static int libsize (const luaL_Reg *l) { 00235 int size = 0; 00236 for (; l->name; l++) size++; 00237 return size; 00238 } 00239 00240 00241 LUALIB_API void luaI_openlib (lua_State *L, const char *libname, 00242 const luaL_Reg *l, int nup) { 00243 if (libname) { 00244 int size = libsize(l); 00245 /* check whether lib already exists */ 00246 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); 00247 lua_getfield(L, -1, libname); /* get _LOADED[libname] */ 00248 if (!lua_istable(L, -1)) { /* not found? */ 00249 lua_pop(L, 1); /* remove previous result */ 00250 /* try global variable (and create one if it does not exist) */ 00251 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) 00252 luaL_error(L, "name conflict for module " LUA_QS, libname); 00253 lua_pushvalue(L, -1); 00254 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ 00255 } 00256 lua_remove(L, -2); /* remove _LOADED table */ 00257 lua_insert(L, -(nup+1)); /* move library table to below upvalues */ 00258 } 00259 for (; l->name; l++) { 00260 int i; 00261 for (i=0; i<nup; i++) /* copy upvalues to the top */ 00262 lua_pushvalue(L, -nup); 00263 lua_pushcclosure(L, l->func, nup); 00264 lua_setfield(L, -(nup+2), l->name); 00265 } 00266 lua_pop(L, nup); /* remove upvalues */ 00267 } 00268 00269 00270 00271 /* 00272 ** {====================================================== 00273 ** getn-setn: size for arrays 00274 ** ======================================================= 00275 */ 00276 00277 #if defined(LUA_COMPAT_GETN) 00278 00279 static int checkint (lua_State *L, int topop) { 00280 int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; 00281 lua_pop(L, topop); 00282 return n; 00283 } 00284 00285 00286 static void getsizes (lua_State *L) { 00287 lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); 00288 if (lua_isnil(L, -1)) { /* no `size' table? */ 00289 lua_pop(L, 1); /* remove nil */ 00290 lua_newtable(L); /* create it */ 00291 lua_pushvalue(L, -1); /* `size' will be its own metatable */ 00292 lua_setmetatable(L, -2); 00293 lua_pushliteral(L, "kv"); 00294 lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ 00295 lua_pushvalue(L, -1); 00296 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ 00297 } 00298 } 00299 00300 00301 LUALIB_API void luaL_setn (lua_State *L, int t, int n) { 00302 t = abs_index(L, t); 00303 lua_pushliteral(L, "n"); 00304 lua_rawget(L, t); 00305 if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ 00306 lua_pushliteral(L, "n"); /* use it */ 00307 lua_pushinteger(L, n); 00308 lua_rawset(L, t); 00309 } 00310 else { /* use `sizes' */ 00311 getsizes(L); 00312 lua_pushvalue(L, t); 00313 lua_pushinteger(L, n); 00314 lua_rawset(L, -3); /* sizes[t] = n */ 00315 lua_pop(L, 1); /* remove `sizes' */ 00316 } 00317 } 00318 00319 00320 LUALIB_API int luaL_getn (lua_State *L, int t) { 00321 int n; 00322 t = abs_index(L, t); 00323 lua_pushliteral(L, "n"); /* try t.n */ 00324 lua_rawget(L, t); 00325 if ((n = checkint(L, 1)) >= 0) return n; 00326 getsizes(L); /* else try sizes[t] */ 00327 lua_pushvalue(L, t); 00328 lua_rawget(L, -2); 00329 if ((n = checkint(L, 2)) >= 0) return n; 00330 return (int)lua_objlen(L, t); 00331 } 00332 00333 #endif 00334 00335 /* }====================================================== */ 00336 00337 00338 00339 LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, 00340 const char *r) { 00341 const char *wild; 00342 size_t l = strlen(p); 00343 luaL_Buffer b; 00344 luaL_buffinit(L, &b); 00345 while ((wild = strstr(s, p)) != NULL) { 00346 luaL_addlstring(&b, s, wild - s); /* push prefix */ 00347 luaL_addstring(&b, r); /* push replacement in place of pattern */ 00348 s = wild + l; /* continue after `p' */ 00349 } 00350 luaL_addstring(&b, s); /* push last suffix */ 00351 luaL_pushresult(&b); 00352 return lua_tostring(L, -1); 00353 } 00354 00355 00356 LUALIB_API const char *luaL_findtable (lua_State *L, int idx, 00357 const char *fname, int szhint) { 00358 const char *e; 00359 lua_pushvalue(L, idx); 00360 do { 00361 e = strchr(fname, '.'); 00362 if (e == NULL) e = fname + strlen(fname); 00363 lua_pushlstring(L, fname, e - fname); 00364 lua_rawget(L, -2); 00365 if (lua_isnil(L, -1)) { /* no such field? */ 00366 lua_pop(L, 1); /* remove this nil */ 00367 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ 00368 lua_pushlstring(L, fname, e - fname); 00369 lua_pushvalue(L, -2); 00370 lua_settable(L, -4); /* set new table into field */ 00371 } 00372 else if (!lua_istable(L, -1)) { /* field has a non-table value? */ 00373 lua_pop(L, 2); /* remove table and value */ 00374 return fname; /* return problematic part of the name */ 00375 } 00376 lua_remove(L, -2); /* remove previous table */ 00377 fname = e + 1; 00378 } while (*e == '.'); 00379 return NULL; 00380 } 00381 00382 00383 00384 /* 00385 ** {====================================================== 00386 ** Generic Buffer manipulation 00387 ** ======================================================= 00388 */ 00389 00390 00391 #define bufflen(B) ((B)->p - (B)->buffer) 00392 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) 00393 00394 #define LIMIT (LUA_MINSTACK/2) 00395 00396 00397 static int emptybuffer (luaL_Buffer *B) { 00398 size_t l = bufflen(B); 00399 if (l == 0) return 0; /* put nothing on stack */ 00400 else { 00401 lua_pushlstring(B->L, B->buffer, l); 00402 B->p = B->buffer; 00403 B->lvl++; 00404 return 1; 00405 } 00406 } 00407 00408 00409 static void adjuststack (luaL_Buffer *B) { 00410 if (B->lvl > 1) { 00411 lua_State *L = B->L; 00412 int toget = 1; /* number of levels to concat */ 00413 size_t toplen = lua_strlen(L, -1); 00414 do { 00415 size_t l = lua_strlen(L, -(toget+1)); 00416 if (B->lvl - toget + 1 >= LIMIT || toplen > l) { 00417 toplen += l; 00418 toget++; 00419 } 00420 else break; 00421 } while (toget < B->lvl); 00422 lua_concat(L, toget); 00423 B->lvl = B->lvl - toget + 1; 00424 } 00425 } 00426 00427 00428 LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { 00429 if (emptybuffer(B)) 00430 adjuststack(B); 00431 return B->buffer; 00432 } 00433 00434 00435 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { 00436 while (l--) 00437 luaL_addchar(B, *s++); 00438 } 00439 00440 00441 LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { 00442 luaL_addlstring(B, s, strlen(s)); 00443 } 00444 00445 00446 LUALIB_API void luaL_pushresult (luaL_Buffer *B) { 00447 emptybuffer(B); 00448 lua_concat(B->L, B->lvl); 00449 B->lvl = 1; 00450 } 00451 00452 00453 LUALIB_API void luaL_addvalue (luaL_Buffer *B) { 00454 lua_State *L = B->L; 00455 size_t vl; 00456 const char *s = lua_tolstring(L, -1, &vl); 00457 if (vl <= bufffree(B)) { /* fit into buffer? */ 00458 memcpy(B->p, s, vl); /* put it there */ 00459 B->p += vl; 00460 lua_pop(L, 1); /* remove from stack */ 00461 } 00462 else { 00463 if (emptybuffer(B)) 00464 lua_insert(L, -2); /* put buffer before new value */ 00465 B->lvl++; /* add new value into B stack */ 00466 adjuststack(B); 00467 } 00468 } 00469 00470 00471 LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { 00472 B->L = L; 00473 B->p = B->buffer; 00474 B->lvl = 0; 00475 } 00476 00477 /* }====================================================== */ 00478 00479 00480 LUALIB_API int luaL_ref (lua_State *L, int t) { 00481 int ref; 00482 t = abs_index(L, t); 00483 if (lua_isnil(L, -1)) { 00484 lua_pop(L, 1); /* remove from stack */ 00485 return LUA_REFNIL; /* `nil' has a unique fixed reference */ 00486 } 00487 lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ 00488 ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ 00489 lua_pop(L, 1); /* remove it from stack */ 00490 if (ref != 0) { /* any free element? */ 00491 lua_rawgeti(L, t, ref); /* remove it from list */ 00492 lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ 00493 } 00494 else { /* no free elements */ 00495 ref = (int)lua_objlen(L, t); 00496 ref++; /* create new reference */ 00497 } 00498 lua_rawseti(L, t, ref); 00499 return ref; 00500 } 00501 00502 00503 LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { 00504 if (ref >= 0) { 00505 t = abs_index(L, t); 00506 lua_rawgeti(L, t, FREELIST_REF); 00507 lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ 00508 lua_pushinteger(L, ref); 00509 lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ 00510 } 00511 } 00512 00513 00514 00515 /* 00516 ** {====================================================== 00517 ** Load functions 00518 ** ======================================================= 00519 */ 00520 00521 typedef struct LoadF { 00522 int extraline; 00523 FILE *f; 00524 char buff[LUAL_BUFFERSIZE]; 00525 } LoadF; 00526 00527 00528 static const char *getF (lua_State *L, void *ud, size_t *size) { 00529 LoadF *lf = (LoadF *)ud; 00530 (void)L; 00531 if (lf->extraline) { 00532 lf->extraline = 0; 00533 *size = 1; 00534 return "\n"; 00535 } 00536 if (feof(lf->f)) return NULL; 00537 *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); 00538 return (*size > 0) ? lf->buff : NULL; 00539 } 00540 00541 00542 static int errfile (lua_State *L, const char *what, int fnameindex) { 00543 const char *serr = strerror(errno); 00544 const char *filename = lua_tostring(L, fnameindex) + 1; 00545 lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); 00546 lua_remove(L, fnameindex); 00547 return LUA_ERRFILE; 00548 } 00549 00550 00551 LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { 00552 LoadF lf; 00553 int status, readstatus; 00554 int c; 00555 int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ 00556 lf.extraline = 0; 00557 if (filename == NULL) { 00558 lua_pushliteral(L, "=stdin"); 00559 lf.f = stdin; 00560 } 00561 else { 00562 lua_pushfstring(L, "@%s", filename); 00563 lf.f = fopen(filename, "r"); 00564 if (lf.f == NULL) return errfile(L, "open", fnameindex); 00565 } 00566 c = getc(lf.f); 00567 if (c == '#') { /* Unix exec. file? */ 00568 lf.extraline = 1; 00569 while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ 00570 if (c == '\n') c = getc(lf.f); 00571 } 00572 if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ 00573 lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ 00574 if (lf.f == NULL) return errfile(L, "reopen", fnameindex); 00575 /* skip eventual `#!...' */ 00576 while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; 00577 lf.extraline = 0; 00578 } 00579 ungetc(c, lf.f); 00580 status = lua_load(L, getF, &lf, lua_tostring(L, -1)); 00581 readstatus = ferror(lf.f); 00582 if (filename) fclose(lf.f); /* close file (even in case of errors) */ 00583 if (readstatus) { 00584 lua_settop(L, fnameindex); /* ignore results from `lua_load' */ 00585 return errfile(L, "read", fnameindex); 00586 } 00587 lua_remove(L, fnameindex); 00588 return status; 00589 } 00590 00591 00592 typedef struct LoadS { 00593 const char *s; 00594 size_t size; 00595 } LoadS; 00596 00597 00598 static const char *getS (lua_State *L, void *ud, size_t *size) { 00599 LoadS *ls = (LoadS *)ud; 00600 (void)L; 00601 if (ls->size == 0) return NULL; 00602 *size = ls->size; 00603 ls->size = 0; 00604 return ls->s; 00605 } 00606 00607 00608 LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, 00609 const char *name) { 00610 LoadS ls; 00611 ls.s = buff; 00612 ls.size = size; 00613 return lua_load(L, getS, &ls, name); 00614 } 00615 00616 00617 LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { 00618 return luaL_loadbuffer(L, s, strlen(s), s); 00619 } 00620 00621 00622 00623 /* }====================================================== */ 00624 00625 00626 static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { 00627 (void)ud; 00628 (void)osize; 00629 if (nsize == 0) { 00630 free(ptr); 00631 return NULL; 00632 } 00633 else 00634 return realloc(ptr, nsize); 00635 } 00636 00637 00638 static int atpanic_print (lua_State *L) { 00639 (void)L; /* to avoid warnings */ 00640 fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", 00641 lua_tostring(L, -1)); 00642 return 0; 00643 } 00644 00645 00646 LUALIB_API lua_State *luaL_newstate (void) { 00647 lua_State *L = lua_newstate(l_alloc, NULL); 00648 if (L) lua_atpanic(L, &atpanic_print); 00649 return L; 00650 } 00651
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1