From 6ce41f687db70b716e3f0f0ec6b6747c6b57d427 Mon Sep 17 00:00:00 2001 From: Jeremy Baxter Date: Wed, 12 Jun 2024 14:34:58 +1200 Subject: [PATCH] environ: implement __pairs metamethod Implements: https://todo.sr.ht/~jeremy/callisto/11 --- lenviron.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ test.lua | 12 ++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lenviron.c b/lenviron.c index 1c09423..d2ff144 100644 --- a/lenviron.c +++ b/lenviron.c @@ -10,11 +10,15 @@ #include #include +#include #include #include #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} }; diff --git a/test.lua b/test.lua index 29396db..5f2954c 100644 --- a/test.lua +++ b/test.lua @@ -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)