environ: implement __pairs metamethod

Implements: https://todo.sr.ht/~jeremy/callisto/11
This commit is contained in:
Jeremy Baxter 2024-06-12 14:34:58 +12:00
parent b3f6d52152
commit 6ce41f687d
2 changed files with 60 additions and 0 deletions

View file

@ -10,11 +10,15 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <lua/lauxlib.h>
#include <lua/lua.h>
#include "callisto.h"
#include "util.h"
extern char **environ;
/***
* Table enabling easy access to environment
@ -94,11 +98,55 @@ environ__newindex(lua_State *L)
return 0;
}
int
pairs_iter(lua_State *L)
{
char *line, *name;
size_t *envi, len;
int i;
len = 0;
envi = (size_t *)lua_touserdata(L, 1);
line = environ[*envi];
if (line == NULL) {
lua_pushnil(L);
return 1;
}
name = calloc(strlen(line), sizeof(char));
/* extract the name portion from the environ line */
for (i = 0; line[i] != '='; i++) {
if (line[i] == '\0')
return lfailm(L, "process environment is corrupted");
name[len] = line[i];
len++;
}
(*envi)++;
lua_pushlstring(L, name, len);
return 1;
}
int
environ__pairs(lua_State *L)
{
size_t *p;
lua_pushcfunction(L, pairs_iter);
p = lua_newuserdatauv(L, sizeof(size_t), 0);
*p = 0;
return 2;
}
/* clang-format off */
static const luaL_Reg mt[] = {
{"__index", environ__index},
{"__newindex", environ__newindex},
{"__pairs", environ__pairs},
{NULL, NULL}
};

View file

@ -41,6 +41,17 @@ local tests = {
environ[var] = val
assert(environ[var] == "hello")
return 'environ["' .. var .. '"] = "' .. val .. '"'
end,
pairs = function ()
local ev = {}
local var = "VAR"
environ[var] = "1"
for env in pairs(environ) do
ev[env] = environ[env]
end
assert(ev[var] == "1")
return "pairs(environ)"
end
},
@ -251,6 +262,7 @@ do
-- environ
test(environ.getvar)
test(environ.setvar)
test(environ.pairs)
-- fs
test(fs.copy)