Mercurial
comparison third_party/luajit/src/lib_aux.c @ 186:8cf4ec5e2191 hg-web
Fixed merge conflict.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 22:38:59 -0800 |
| parents | 94705b5986b3 |
| children |
comparison
equal
deleted
inserted
replaced
| 176:fed99fc04e12 | 186:8cf4ec5e2191 |
|---|---|
| 1 /* | |
| 2 ** Auxiliary library for the Lua/C API. | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 ** | |
| 5 ** Major parts taken verbatim or adapted from the Lua interpreter. | |
| 6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h | |
| 7 */ | |
| 8 | |
| 9 #include <errno.h> | |
| 10 #include <stdarg.h> | |
| 11 #include <stdio.h> | |
| 12 | |
| 13 #define lib_aux_c | |
| 14 #define LUA_LIB | |
| 15 | |
| 16 #include "lua.h" | |
| 17 #include "lauxlib.h" | |
| 18 | |
| 19 #include "lj_obj.h" | |
| 20 #include "lj_err.h" | |
| 21 #include "lj_state.h" | |
| 22 #include "lj_trace.h" | |
| 23 #include "lj_lib.h" | |
| 24 #include "lj_vmevent.h" | |
| 25 | |
| 26 #if LJ_TARGET_POSIX | |
| 27 #include <sys/wait.h> | |
| 28 #endif | |
| 29 | |
| 30 /* -- I/O error handling -------------------------------------------------- */ | |
| 31 | |
| 32 LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname) | |
| 33 { | |
| 34 if (stat) { | |
| 35 setboolV(L->top++, 1); | |
| 36 return 1; | |
| 37 } else { | |
| 38 int en = errno; /* Lua API calls may change this value. */ | |
| 39 setnilV(L->top++); | |
| 40 if (fname) | |
| 41 lua_pushfstring(L, "%s: %s", fname, strerror(en)); | |
| 42 else | |
| 43 lua_pushfstring(L, "%s", strerror(en)); | |
| 44 setintV(L->top++, en); | |
| 45 lj_trace_abort(G(L)); | |
| 46 return 3; | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 LUALIB_API int luaL_execresult(lua_State *L, int stat) | |
| 51 { | |
| 52 if (stat != -1) { | |
| 53 #if LJ_TARGET_POSIX | |
| 54 if (WIFSIGNALED(stat)) { | |
| 55 stat = WTERMSIG(stat); | |
| 56 setnilV(L->top++); | |
| 57 lua_pushliteral(L, "signal"); | |
| 58 } else { | |
| 59 if (WIFEXITED(stat)) | |
| 60 stat = WEXITSTATUS(stat); | |
| 61 if (stat == 0) | |
| 62 setboolV(L->top++, 1); | |
| 63 else | |
| 64 setnilV(L->top++); | |
| 65 lua_pushliteral(L, "exit"); | |
| 66 } | |
| 67 #else | |
| 68 if (stat == 0) | |
| 69 setboolV(L->top++, 1); | |
| 70 else | |
| 71 setnilV(L->top++); | |
| 72 lua_pushliteral(L, "exit"); | |
| 73 #endif | |
| 74 setintV(L->top++, stat); | |
| 75 return 3; | |
| 76 } | |
| 77 return luaL_fileresult(L, 0, NULL); | |
| 78 } | |
| 79 | |
| 80 /* -- Module registration ------------------------------------------------- */ | |
| 81 | |
| 82 LUALIB_API const char *luaL_findtable(lua_State *L, int idx, | |
| 83 const char *fname, int szhint) | |
| 84 { | |
| 85 const char *e; | |
| 86 lua_pushvalue(L, idx); | |
| 87 do { | |
| 88 e = strchr(fname, '.'); | |
| 89 if (e == NULL) e = fname + strlen(fname); | |
| 90 lua_pushlstring(L, fname, (size_t)(e - fname)); | |
| 91 lua_rawget(L, -2); | |
| 92 if (lua_isnil(L, -1)) { /* no such field? */ | |
| 93 lua_pop(L, 1); /* remove this nil */ | |
| 94 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | |
| 95 lua_pushlstring(L, fname, (size_t)(e - fname)); | |
| 96 lua_pushvalue(L, -2); | |
| 97 lua_settable(L, -4); /* set new table into field */ | |
| 98 } else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | |
| 99 lua_pop(L, 2); /* remove table and value */ | |
| 100 return fname; /* return problematic part of the name */ | |
| 101 } | |
| 102 lua_remove(L, -2); /* remove previous table */ | |
| 103 fname = e + 1; | |
| 104 } while (*e == '.'); | |
| 105 return NULL; | |
| 106 } | |
| 107 | |
| 108 static int libsize(const luaL_Reg *l) | |
| 109 { | |
| 110 int size = 0; | |
| 111 for (; l && l->name; l++) size++; | |
| 112 return size; | |
| 113 } | |
| 114 | |
| 115 LUALIB_API void luaL_pushmodule(lua_State *L, const char *modname, int sizehint) | |
| 116 { | |
| 117 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16); | |
| 118 lua_getfield(L, -1, modname); | |
| 119 if (!lua_istable(L, -1)) { | |
| 120 lua_pop(L, 1); | |
| 121 if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, sizehint) != NULL) | |
| 122 lj_err_callerv(L, LJ_ERR_BADMODN, modname); | |
| 123 lua_pushvalue(L, -1); | |
| 124 lua_setfield(L, -3, modname); /* _LOADED[modname] = new table. */ | |
| 125 } | |
| 126 lua_remove(L, -2); /* Remove _LOADED table. */ | |
| 127 } | |
| 128 | |
| 129 LUALIB_API void luaL_openlib(lua_State *L, const char *libname, | |
| 130 const luaL_Reg *l, int nup) | |
| 131 { | |
| 132 lj_lib_checkfpu(L); | |
| 133 if (libname) { | |
| 134 luaL_pushmodule(L, libname, libsize(l)); | |
| 135 lua_insert(L, -(nup + 1)); /* Move module table below upvalues. */ | |
| 136 } | |
| 137 if (l) | |
| 138 luaL_setfuncs(L, l, nup); | |
| 139 else | |
| 140 lua_pop(L, nup); /* Remove upvalues. */ | |
| 141 } | |
| 142 | |
| 143 LUALIB_API void luaL_register(lua_State *L, const char *libname, | |
| 144 const luaL_Reg *l) | |
| 145 { | |
| 146 luaL_openlib(L, libname, l, 0); | |
| 147 } | |
| 148 | |
| 149 LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) | |
| 150 { | |
| 151 luaL_checkstack(L, nup, "too many upvalues"); | |
| 152 for (; l->name; l++) { | |
| 153 int i; | |
| 154 for (i = 0; i < nup; i++) /* Copy upvalues to the top. */ | |
| 155 lua_pushvalue(L, -nup); | |
| 156 lua_pushcclosure(L, l->func, nup); | |
| 157 lua_setfield(L, -(nup + 2), l->name); | |
| 158 } | |
| 159 lua_pop(L, nup); /* Remove upvalues. */ | |
| 160 } | |
| 161 | |
| 162 LUALIB_API const char *luaL_gsub(lua_State *L, const char *s, | |
| 163 const char *p, const char *r) | |
| 164 { | |
| 165 const char *wild; | |
| 166 size_t l = strlen(p); | |
| 167 luaL_Buffer b; | |
| 168 luaL_buffinit(L, &b); | |
| 169 while ((wild = strstr(s, p)) != NULL) { | |
| 170 luaL_addlstring(&b, s, (size_t)(wild - s)); /* push prefix */ | |
| 171 luaL_addstring(&b, r); /* push replacement in place of pattern */ | |
| 172 s = wild + l; /* continue after `p' */ | |
| 173 } | |
| 174 luaL_addstring(&b, s); /* push last suffix */ | |
| 175 luaL_pushresult(&b); | |
| 176 return lua_tostring(L, -1); | |
| 177 } | |
| 178 | |
| 179 /* -- Buffer handling ----------------------------------------------------- */ | |
| 180 | |
| 181 #define bufflen(B) ((size_t)((B)->p - (B)->buffer)) | |
| 182 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) | |
| 183 | |
| 184 static int emptybuffer(luaL_Buffer *B) | |
| 185 { | |
| 186 size_t l = bufflen(B); | |
| 187 if (l == 0) | |
| 188 return 0; /* put nothing on stack */ | |
| 189 lua_pushlstring(B->L, B->buffer, l); | |
| 190 B->p = B->buffer; | |
| 191 B->lvl++; | |
| 192 return 1; | |
| 193 } | |
| 194 | |
| 195 static void adjuststack(luaL_Buffer *B) | |
| 196 { | |
| 197 if (B->lvl > 1) { | |
| 198 lua_State *L = B->L; | |
| 199 int toget = 1; /* number of levels to concat */ | |
| 200 size_t toplen = lua_strlen(L, -1); | |
| 201 do { | |
| 202 size_t l = lua_strlen(L, -(toget+1)); | |
| 203 if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l)) | |
| 204 break; | |
| 205 toplen += l; | |
| 206 toget++; | |
| 207 } while (toget < B->lvl); | |
| 208 lua_concat(L, toget); | |
| 209 B->lvl = B->lvl - toget + 1; | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B) | |
| 214 { | |
| 215 if (emptybuffer(B)) | |
| 216 adjuststack(B); | |
| 217 return B->buffer; | |
| 218 } | |
| 219 | |
| 220 LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l) | |
| 221 { | |
| 222 if (l <= bufffree(B)) { | |
| 223 memcpy(B->p, s, l); | |
| 224 B->p += l; | |
| 225 } else { | |
| 226 emptybuffer(B); | |
| 227 lua_pushlstring(B->L, s, l); | |
| 228 B->lvl++; | |
| 229 adjuststack(B); | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s) | |
| 234 { | |
| 235 luaL_addlstring(B, s, strlen(s)); | |
| 236 } | |
| 237 | |
| 238 LUALIB_API void luaL_pushresult(luaL_Buffer *B) | |
| 239 { | |
| 240 emptybuffer(B); | |
| 241 lua_concat(B->L, B->lvl); | |
| 242 B->lvl = 1; | |
| 243 } | |
| 244 | |
| 245 LUALIB_API void luaL_addvalue(luaL_Buffer *B) | |
| 246 { | |
| 247 lua_State *L = B->L; | |
| 248 size_t vl; | |
| 249 const char *s = lua_tolstring(L, -1, &vl); | |
| 250 if (vl <= bufffree(B)) { /* fit into buffer? */ | |
| 251 memcpy(B->p, s, vl); /* put it there */ | |
| 252 B->p += vl; | |
| 253 lua_pop(L, 1); /* remove from stack */ | |
| 254 } else { | |
| 255 if (emptybuffer(B)) | |
| 256 lua_insert(L, -2); /* put buffer before new value */ | |
| 257 B->lvl++; /* add new value into B stack */ | |
| 258 adjuststack(B); | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B) | |
| 263 { | |
| 264 B->L = L; | |
| 265 B->p = B->buffer; | |
| 266 B->lvl = 0; | |
| 267 } | |
| 268 | |
| 269 /* -- Reference management ------------------------------------------------ */ | |
| 270 | |
| 271 #define FREELIST_REF 0 | |
| 272 | |
| 273 /* Convert a stack index to an absolute index. */ | |
| 274 #define abs_index(L, i) \ | |
| 275 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) | |
| 276 | |
| 277 LUALIB_API int luaL_ref(lua_State *L, int t) | |
| 278 { | |
| 279 int ref; | |
| 280 t = abs_index(L, t); | |
| 281 if (lua_isnil(L, -1)) { | |
| 282 lua_pop(L, 1); /* remove from stack */ | |
| 283 return LUA_REFNIL; /* `nil' has a unique fixed reference */ | |
| 284 } | |
| 285 lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ | |
| 286 ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ | |
| 287 lua_pop(L, 1); /* remove it from stack */ | |
| 288 if (ref != 0) { /* any free element? */ | |
| 289 lua_rawgeti(L, t, ref); /* remove it from list */ | |
| 290 lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ | |
| 291 } else { /* no free elements */ | |
| 292 ref = (int)lua_objlen(L, t); | |
| 293 ref++; /* create new reference */ | |
| 294 } | |
| 295 lua_rawseti(L, t, ref); | |
| 296 return ref; | |
| 297 } | |
| 298 | |
| 299 LUALIB_API void luaL_unref(lua_State *L, int t, int ref) | |
| 300 { | |
| 301 if (ref >= 0) { | |
| 302 t = abs_index(L, t); | |
| 303 lua_rawgeti(L, t, FREELIST_REF); | |
| 304 lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ | |
| 305 lua_pushinteger(L, ref); | |
| 306 lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 /* -- Default allocator and panic function -------------------------------- */ | |
| 311 | |
| 312 static int panic(lua_State *L) | |
| 313 { | |
| 314 const char *s = lua_tostring(L, -1); | |
| 315 fputs("PANIC: unprotected error in call to Lua API (", stderr); | |
| 316 fputs(s ? s : "?", stderr); | |
| 317 fputc(')', stderr); fputc('\n', stderr); | |
| 318 fflush(stderr); | |
| 319 return 0; | |
| 320 } | |
| 321 | |
| 322 #ifndef LUAJIT_DISABLE_VMEVENT | |
| 323 static int error_finalizer(lua_State *L) | |
| 324 { | |
| 325 const char *s = lua_tostring(L, -1); | |
| 326 fputs("ERROR in finalizer: ", stderr); | |
| 327 fputs(s ? s : "?", stderr); | |
| 328 fputc('\n', stderr); | |
| 329 fflush(stderr); | |
| 330 return 0; | |
| 331 } | |
| 332 #endif | |
| 333 | |
| 334 #ifdef LUAJIT_USE_SYSMALLOC | |
| 335 | |
| 336 #if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND) | |
| 337 #error "Must use builtin allocator for 64 bit target" | |
| 338 #endif | |
| 339 | |
| 340 static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize) | |
| 341 { | |
| 342 (void)ud; | |
| 343 (void)osize; | |
| 344 if (nsize == 0) { | |
| 345 free(ptr); | |
| 346 return NULL; | |
| 347 } else { | |
| 348 return realloc(ptr, nsize); | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 LUALIB_API lua_State *luaL_newstate(void) | |
| 353 { | |
| 354 lua_State *L = lua_newstate(mem_alloc, NULL); | |
| 355 if (L) { | |
| 356 G(L)->panic = panic; | |
| 357 #ifndef LUAJIT_DISABLE_VMEVENT | |
| 358 luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); | |
| 359 lua_pushcfunction(L, error_finalizer); | |
| 360 lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN)); | |
| 361 G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN); | |
| 362 L->top--; | |
| 363 #endif | |
| 364 } | |
| 365 return L; | |
| 366 } | |
| 367 | |
| 368 #else | |
| 369 | |
| 370 LUALIB_API lua_State *luaL_newstate(void) | |
| 371 { | |
| 372 lua_State *L; | |
| 373 #if LJ_64 && !LJ_GC64 | |
| 374 L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL); | |
| 375 #else | |
| 376 L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL); | |
| 377 #endif | |
| 378 if (L) { | |
| 379 G(L)->panic = panic; | |
| 380 #ifndef LUAJIT_DISABLE_VMEVENT | |
| 381 luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE); | |
| 382 lua_pushcfunction(L, error_finalizer); | |
| 383 lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN)); | |
| 384 G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN); | |
| 385 L->top--; | |
| 386 #endif | |
| 387 } | |
| 388 return L; | |
| 389 } | |
| 390 | |
| 391 #if LJ_64 && !LJ_GC64 | |
| 392 LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | |
| 393 { | |
| 394 UNUSED(f); UNUSED(ud); | |
| 395 fputs("Must use luaL_newstate() for 64 bit target\n", stderr); | |
| 396 return NULL; | |
| 397 } | |
| 398 #endif | |
| 399 | |
| 400 #endif | |
| 401 |