- [NEW] Updatada la versió de Lua a 5.5.0
- [FIX] Afegits defines de Lua per a cada SO
This commit is contained in:
+176
-80
@@ -22,15 +22,7 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
/*
|
||||
** LUA_IGMARK is a mark to ignore all before it when building the
|
||||
** luaopen_ function name.
|
||||
*/
|
||||
#if !defined (LUA_IGMARK)
|
||||
#define LUA_IGMARK "-"
|
||||
#endif
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -67,11 +59,8 @@ static const char *const CLIBS = "_CLIBS";
|
||||
#define setprogdir(L) ((void)0)
|
||||
|
||||
|
||||
/*
|
||||
** Special type equivalent to '(void*)' for functions in gcc
|
||||
** (to suppress warnings when converting function pointers)
|
||||
*/
|
||||
typedef void (*voidf)(void);
|
||||
/* cast void* to a Lua function */
|
||||
#define cast_Lfunc(p) cast(lua_CFunction, cast_func(p))
|
||||
|
||||
|
||||
/*
|
||||
@@ -104,26 +93,13 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
|
||||
#if defined(LUA_USE_DLOPEN) /* { */
|
||||
/*
|
||||
** {========================================================================
|
||||
** This is an implementation of loadlib based on the dlfcn interface.
|
||||
** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
|
||||
** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
|
||||
** as an emulation layer on top of native functions.
|
||||
** This is an implementation of loadlib based on the dlfcn interface,
|
||||
** which is available in all POSIX systems.
|
||||
** =========================================================================
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/*
|
||||
** Macro to convert pointer-to-void* to pointer-to-function. This cast
|
||||
** is undefined according to ISO C, but POSIX assumes that it works.
|
||||
** (The '__extension__' in gnu compilers is only to avoid warnings.)
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define cast_func(p) (__extension__ (lua_CFunction)(p))
|
||||
#else
|
||||
#define cast_func(p) ((lua_CFunction)(p))
|
||||
#endif
|
||||
|
||||
|
||||
static void lsys_unloadlib (void *lib) {
|
||||
dlclose(lib);
|
||||
@@ -139,7 +115,7 @@ static void *lsys_load (lua_State *L, const char *path, int seeglb) {
|
||||
|
||||
|
||||
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
|
||||
lua_CFunction f = cast_func(dlsym(lib, sym));
|
||||
lua_CFunction f = cast_Lfunc(dlsym(lib, sym));
|
||||
if (l_unlikely(f == NULL))
|
||||
lua_pushstring(L, dlerror());
|
||||
return f;
|
||||
@@ -215,7 +191,7 @@ static void *lsys_load (lua_State *L, const char *path, int seeglb) {
|
||||
|
||||
|
||||
static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
|
||||
lua_CFunction f = (lua_CFunction)(voidf)GetProcAddress((HMODULE)lib, sym);
|
||||
lua_CFunction f = cast_Lfunc(GetProcAddress((HMODULE)lib, sym));
|
||||
if (f == NULL) pusherror(L);
|
||||
return f;
|
||||
}
|
||||
@@ -292,7 +268,8 @@ static int noenv (lua_State *L) {
|
||||
|
||||
|
||||
/*
|
||||
** Set a path
|
||||
** Set a path. (If using the default path, assume it is a string
|
||||
** literal in C and create it as an external string.)
|
||||
*/
|
||||
static void setpath (lua_State *L, const char *fieldname,
|
||||
const char *envname,
|
||||
@@ -303,7 +280,7 @@ static void setpath (lua_State *L, const char *fieldname,
|
||||
if (path == NULL) /* no versioned environment variable? */
|
||||
path = getenv(envname); /* try unversioned name */
|
||||
if (path == NULL || noenv(L)) /* no environment variable? */
|
||||
lua_pushstring(L, dft); /* use default */
|
||||
lua_pushexternalstring(L, dft, strlen(dft), NULL, NULL); /* use default */
|
||||
else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
|
||||
lua_pushstring(L, path); /* nothing to change */
|
||||
else { /* path contains a ";;": insert default path in its place */
|
||||
@@ -311,13 +288,13 @@ static void setpath (lua_State *L, const char *fieldname,
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
if (path < dftmark) { /* is there a prefix before ';;'? */
|
||||
luaL_addlstring(&b, path, dftmark - path); /* add it */
|
||||
luaL_addlstring(&b, path, ct_diff2sz(dftmark - path)); /* add it */
|
||||
luaL_addchar(&b, *LUA_PATH_SEP);
|
||||
}
|
||||
luaL_addstring(&b, dft); /* add default */
|
||||
if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */
|
||||
luaL_addchar(&b, *LUA_PATH_SEP);
|
||||
luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark);
|
||||
luaL_addlstring(&b, dftmark + 2, ct_diff2sz((path + len - 2) - dftmark));
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
}
|
||||
@@ -329,6 +306,16 @@ static void setpath (lua_State *L, const char *fieldname,
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** External strings created by DLLs may need the DLL code to be
|
||||
** deallocated. This implies that a DLL can only be unloaded after all
|
||||
** its strings were deallocated. To ensure that, we create a 'library
|
||||
** string' to represent each DLL, and when this string is deallocated
|
||||
** it closes its corresponding DLL.
|
||||
** (The string itself is irrelevant; its userdata is the DLL pointer.)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** return registry.CLIBS[path]
|
||||
*/
|
||||
@@ -343,34 +330,41 @@ static void *checkclib (lua_State *L, const char *path) {
|
||||
|
||||
|
||||
/*
|
||||
** registry.CLIBS[path] = plib -- for queries
|
||||
** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
|
||||
** Deallocate function for library strings.
|
||||
** Unload the DLL associated with the string being deallocated.
|
||||
*/
|
||||
static void addtoclib (lua_State *L, const char *path, void *plib) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
|
||||
lua_pushlightuserdata(L, plib);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, path); /* CLIBS[path] = plib */
|
||||
lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
|
||||
lua_pop(L, 1); /* pop CLIBS table */
|
||||
static void *freelib (void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||
/* string itself is irrelevant and static */
|
||||
(void)ptr; (void)osize; (void)nsize;
|
||||
lsys_unloadlib(ud); /* unload library represented by the string */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
|
||||
** handles in list CLIBS
|
||||
** Create a library string that, when deallocated, will unload 'plib'
|
||||
*/
|
||||
static int gctm (lua_State *L) {
|
||||
lua_Integer n = luaL_len(L, 1);
|
||||
for (; n >= 1; n--) { /* for each handle, in reverse order */
|
||||
lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
|
||||
lsys_unloadlib(lua_touserdata(L, -1));
|
||||
lua_pop(L, 1); /* pop handle */
|
||||
}
|
||||
return 0;
|
||||
static void createlibstr (lua_State *L, void *plib) {
|
||||
/* common content for all library strings */
|
||||
static const char dummy[] = "01234567890";
|
||||
lua_pushexternalstring(L, dummy, sizeof(dummy) - 1, freelib, plib);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** registry.CLIBS[path] = plib -- for queries.
|
||||
** Also create a reference to strlib, so that the library string will
|
||||
** only be collected when registry.CLIBS is collected.
|
||||
*/
|
||||
static void addtoclib (lua_State *L, const char *path, void *plib) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
|
||||
lua_pushlightuserdata(L, plib);
|
||||
lua_setfield(L, -2, path); /* CLIBS[path] = plib */
|
||||
createlibstr(L, plib);
|
||||
luaL_ref(L, -2); /* keep library string in CLIBS */
|
||||
lua_pop(L, 1); /* pop CLIBS table */
|
||||
}
|
||||
|
||||
|
||||
/* error codes for 'lookforfunc' */
|
||||
#define ERRLIB 1
|
||||
@@ -384,8 +378,8 @@ static int gctm (lua_State *L) {
|
||||
** Then, if 'sym' is '*', return true (as library has been loaded).
|
||||
** Otherwise, look for symbol 'sym' in the library and push a
|
||||
** C function with that symbol.
|
||||
** Return 0 and 'true' or a function in the stack; in case of
|
||||
** errors, return an error code and an error message in the stack.
|
||||
** Return 0 with 'true' or a function in the stack; in case of
|
||||
** errors, return an error code with an error message in the stack.
|
||||
*/
|
||||
static int lookforfunc (lua_State *L, const char *path, const char *sym) {
|
||||
void *reg = checkclib(L, path); /* check loaded C libraries */
|
||||
@@ -566,7 +560,7 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) {
|
||||
mark = strchr(modname, *LUA_IGMARK);
|
||||
if (mark) {
|
||||
int stat;
|
||||
openfunc = lua_pushlstring(L, modname, mark - modname);
|
||||
openfunc = lua_pushlstring(L, modname, ct_diff2sz(mark - modname));
|
||||
openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc);
|
||||
stat = lookforfunc(L, filename, openfunc);
|
||||
if (stat != ERRFUNC) return stat;
|
||||
@@ -591,7 +585,7 @@ static int searcher_Croot (lua_State *L) {
|
||||
const char *p = strchr(name, '.');
|
||||
int stat;
|
||||
if (p == NULL) return 0; /* is root */
|
||||
lua_pushlstring(L, name, p - name);
|
||||
lua_pushlstring(L, name, ct_diff2sz(p - name));
|
||||
filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
|
||||
if (filename == NULL) return 1; /* root not found */
|
||||
if ((stat = loadfunc(L, filename, name)) != 0) {
|
||||
@@ -629,12 +623,12 @@ static void findloader (lua_State *L, const char *name) {
|
||||
!= LUA_TTABLE))
|
||||
luaL_error(L, "'package.searchers' must be a table");
|
||||
luaL_buffinit(L, &msg);
|
||||
luaL_addstring(&msg, "\n\t"); /* error-message prefix for first message */
|
||||
/* iterate over available searchers to find a loader */
|
||||
for (i = 1; ; i++) {
|
||||
luaL_addstring(&msg, "\n\t"); /* error-message prefix */
|
||||
if (l_unlikely(lua_rawgeti(L, 3, i) == LUA_TNIL)) { /* no more searchers? */
|
||||
lua_pop(L, 1); /* remove nil */
|
||||
luaL_buffsub(&msg, 2); /* remove prefix */
|
||||
luaL_buffsub(&msg, 2); /* remove last prefix */
|
||||
luaL_pushresult(&msg); /* create error message */
|
||||
luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1));
|
||||
}
|
||||
@@ -645,17 +639,126 @@ static void findloader (lua_State *L, const char *name) {
|
||||
else if (lua_isstring(L, -2)) { /* searcher returned error message? */
|
||||
lua_pop(L, 1); /* remove extra return */
|
||||
luaL_addvalue(&msg); /* concatenate error message */
|
||||
luaL_addstring(&msg, "\n\t"); /* prefix for next message */
|
||||
}
|
||||
else { /* no error message */
|
||||
else /* no error message */
|
||||
lua_pop(L, 2); /* remove both returns */
|
||||
luaL_buffsub(&msg, 2); /* remove prefix */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [RZC 12/03/2026] ==================================
|
||||
// Soport per a rutes relatives i absolutes
|
||||
//
|
||||
static void resolve_module_name(lua_State *L, char *out, size_t outsz) {
|
||||
const char *req = luaL_checkstring(L, 1);
|
||||
|
||||
// 1. RUTA ABSOLUTA: empieza por ':'
|
||||
if (req[0] == ':') {
|
||||
strncpy(out, req + 1, outsz - 1);
|
||||
out[outsz - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Obtener módulo llamador
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L, 1, &ar)) {
|
||||
// No hay llamador → usar nombre tal cual
|
||||
strncpy(out, req, outsz - 1);
|
||||
out[outsz - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
lua_getinfo(L, "S", &ar);
|
||||
|
||||
// ar.source contiene algo como "@ia.test" o "@main"
|
||||
const char *src = ar.source;
|
||||
if (!src) {
|
||||
// No viene de archivo → usar nombre tal cual
|
||||
strncpy(out, req, outsz - 1);
|
||||
out[outsz - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
// Quitar '@'
|
||||
//src++;
|
||||
|
||||
// 3. Extraer directorio del módulo llamador
|
||||
// Ej: "ia.tools.other" → "ia.tools"
|
||||
char caller[256];
|
||||
strncpy(caller, src, sizeof(caller) - 1);
|
||||
caller[sizeof(caller) - 1] = '\0';
|
||||
|
||||
char *lastdot = strrchr(caller, '.');
|
||||
if (lastdot)
|
||||
*lastdot = '\0'; // dejar solo el directorio
|
||||
else
|
||||
caller[0] = '\0'; // está en la raíz
|
||||
|
||||
// 4. RUTA RELATIVA HACIA ARRIBA: empieza por ".."
|
||||
if (req[0] == '.' && req[1] == '.') {
|
||||
// Contar cuántos '.' consecutivos hay
|
||||
int up = 0;
|
||||
while (req[up] == '.')
|
||||
up++;
|
||||
|
||||
// up = número de puntos → niveles a subir
|
||||
// Ej: "..test" → up=2 → subir 1 nivel
|
||||
// "...main" → up=3 → subir 2 niveles
|
||||
|
||||
int levels = up - 1;
|
||||
|
||||
// Copiar caller a buffer temporal
|
||||
char temp[256];
|
||||
strncpy(temp, caller, sizeof(temp) - 1);
|
||||
temp[sizeof(temp) - 1] = '\0';
|
||||
|
||||
// Subir niveles
|
||||
for (int i = 0; i < levels; i++) {
|
||||
char *p = strrchr(temp, '.');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
else {
|
||||
temp[0] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Concatenar lo que queda después de los puntos
|
||||
const char *rest = req + up;
|
||||
|
||||
if (temp[0] == '\0') {
|
||||
// Hemos llegado a la raíz
|
||||
strncpy(out, rest, outsz - 1);
|
||||
} else {
|
||||
snprintf(out, outsz, "%s.%s", temp, rest);
|
||||
}
|
||||
|
||||
out[outsz - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. RUTA RELATIVA NORMAL (no empieza por ':' ni por '..')
|
||||
if (caller[0] == '\0') {
|
||||
// Estamos en la raíz
|
||||
strncpy(out, req, outsz - 1);
|
||||
} else {
|
||||
snprintf(out, outsz, "%s.%s", caller, req);
|
||||
}
|
||||
|
||||
out[outsz - 1] = '\0';
|
||||
}
|
||||
// ===================================================
|
||||
|
||||
static int ll_require (lua_State *L) {
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
// [RZC 12/03/2026] ==================================
|
||||
// Soport per a rutes relatives i absolutes
|
||||
//
|
||||
//const char *name = luaL_checkstring(L, 1);
|
||||
char resolved[256];
|
||||
resolve_module_name(L, resolved, sizeof(resolved));
|
||||
const char *name = resolved;
|
||||
// ===================================================
|
||||
|
||||
lua_settop(L, 1); /* LOADED table will be at index 2 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
lua_getfield(L, 2, name); /* LOADED[name] */
|
||||
@@ -708,8 +811,13 @@ static const luaL_Reg ll_funcs[] = {
|
||||
|
||||
|
||||
static void createsearcherstable (lua_State *L) {
|
||||
static const lua_CFunction searchers[] =
|
||||
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
|
||||
static const lua_CFunction searchers[] = {
|
||||
searcher_preload,
|
||||
searcher_Lua,
|
||||
searcher_C,
|
||||
searcher_Croot,
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
/* create 'searchers' table */
|
||||
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
|
||||
@@ -723,21 +831,9 @@ static void createsearcherstable (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** create table CLIBS to keep track of loaded C libraries,
|
||||
** setting a finalizer to close all libraries when closing state.
|
||||
*/
|
||||
static void createclibstable (lua_State *L) {
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */
|
||||
lua_createtable(L, 0, 1); /* create metatable for CLIBS */
|
||||
lua_pushcfunction(L, gctm);
|
||||
lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_package (lua_State *L) {
|
||||
createclibstable(L);
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */
|
||||
lua_pop(L, 1); /* will not use it now */
|
||||
luaL_newlib(L, pk_funcs); /* create 'package' table */
|
||||
createsearcherstable(L);
|
||||
/* set paths */
|
||||
|
||||
Reference in New Issue
Block a user