mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 08:48:29 +00:00
Write more redbean unit tests
- Fix DescribeSigset() - Introduce new unix.rmrf() API - Fix redbean sigaction() doc example code - Fix unix.sigaction() w/ more than two args - Improve redbean re module API (non-breaking) - Enhance Lua with Python string multiplication - Make third parameter of unix.socket() default to 0
This commit is contained in:
parent
c5b9902ac9
commit
1c83670229
20 changed files with 738 additions and 204 deletions
|
@ -357,6 +357,9 @@ LUA ENHANCEMENTS
|
|||
example, you can say `"hello %s" % {"world"}` instead of
|
||||
`string.format("hello %s", "world")`.
|
||||
|
||||
- redbean supports a string multiply operator, like Python. For
|
||||
example, you can say `"hi" * 2` instead of `string.rep("hi", 2)`.
|
||||
|
||||
- redbean supports octal (base 8) integer literals. For example
|
||||
`0644 == 420` is the case in redbean, whereas in upstream Lua
|
||||
`0644 == 644` would be the case.
|
||||
|
@ -1495,6 +1498,7 @@ CONSTANTS
|
|||
Logging anything at this level will result in a backtrace and
|
||||
process exit.
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
LSQLITE3 MODULE
|
||||
|
||||
|
@ -1531,6 +1535,7 @@ LSQLITE3 MODULE
|
|||
we provide an APE build of the SQLite shell which you can use to
|
||||
administrate your redbean database. See the sqlite3.com download above.
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
RE MODULE
|
||||
|
||||
|
@ -1540,29 +1545,144 @@ RE MODULE
|
|||
|
||||
# Example IPv4 Address Regular Expression (see also ParseIP)
|
||||
p = re.compile([[^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$]])
|
||||
m,a,b,c,d = p:search(𝑠)
|
||||
m,a,b,c,d = assert(p:search(𝑠))
|
||||
if m then
|
||||
print("ok", tonumber(a), tonumber(b), tonumber(c), tonumber(d))
|
||||
else
|
||||
print("not ok")
|
||||
end
|
||||
|
||||
re.search(regex:str,text:str[,flags:int]) → [match[,group_1,...]]
|
||||
Shortcut for re.compile plus regex_t*:search.
|
||||
re.search(regex:str, text:str[, flags:int])
|
||||
├─→ match:str[, group1:str, ...]
|
||||
└─→ nil, re.Errno
|
||||
|
||||
re.compile(regex:str[,flags:int]) → regex_t*
|
||||
Compiles regular expression, using the POSIX extended syntax. This
|
||||
has an O(2^𝑛) cost, so it's a good idea to do this from your
|
||||
/.init.lua file. Flags may contain re.BASIC, re.ICASE, re.NOSUB,
|
||||
and/or re.NEWLINE. See also regcomp() from libc.
|
||||
Searches for regular expression match in text.
|
||||
|
||||
regex_t*:search(text:str[,flags:int]) → [match[,group_1,...]]
|
||||
Executes regular expression. This has an O(𝑛) cost. This returns
|
||||
nothing (nil) if the pattern doesn't match anything. Otherwise it
|
||||
pushes the matched substring and any parenthesis-captured values
|
||||
too. Flags may contain re.NOTBOL or re.NOTEOL to indicate whether
|
||||
or not text should be considered at the start and/or end of a
|
||||
line.
|
||||
This is a shorthand notation roughly equivalent to:
|
||||
|
||||
preg = re.compile(regex)
|
||||
patt = preg:search(re, text)
|
||||
|
||||
`flags` defaults to zero and may have any of:
|
||||
|
||||
- `re.BASIC`
|
||||
- `re.ICASE`
|
||||
- `re.NEWLINE`
|
||||
- `re.NOSUB`
|
||||
- `re.NOTBOL`
|
||||
- `re.NOTEOL`
|
||||
|
||||
This has exponential complexity. Please use re.compile() to
|
||||
compile your regular expressions once from `/.init.lua`. This
|
||||
API exists for convenience. This isn't recommended for prod.
|
||||
|
||||
This uses POSIX extended syntax by default.
|
||||
|
||||
re.compile(regex:str[, flags:int]) → re.Regex
|
||||
├─→ preg:re.Regex
|
||||
└─→ nil, re.Errno
|
||||
|
||||
Compiles regular expression.
|
||||
|
||||
`flags` defaults to zero and may have any of:
|
||||
|
||||
- `re.BASIC`
|
||||
- `re.ICASE`
|
||||
- `re.NEWLINE`
|
||||
- `re.NOSUB`
|
||||
|
||||
This has an O(2^𝑛) cost. Consider compiling regular
|
||||
expressions once from your `/.init.lua` file.
|
||||
|
||||
If `regex` is an untrusted user value, then `unix.setrlimit`
|
||||
should be used to impose cpu and memory quotas for security.
|
||||
|
||||
This uses POSIX extended syntax by default.
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
RE REGEX OBJECT
|
||||
|
||||
re.Regex:search(text:str[, flags:int])
|
||||
├─→ match:str[, group1:str, ...]
|
||||
└─→ nil, re.Errno
|
||||
|
||||
Executes precompiled regular expression.
|
||||
|
||||
Returns nothing (nil) if the pattern doesn't match anything.
|
||||
Otherwise it pushes the matched substring and any
|
||||
parenthesis-captured values too. Flags may contain re.NOTBOL
|
||||
or re.NOTEOL to indicate whether or not text should be
|
||||
considered at the start and/or end of a line.
|
||||
|
||||
`flags` defaults to zero and may have any of:
|
||||
|
||||
- `re.NOTBOL`
|
||||
- `re.NOTEOL`
|
||||
|
||||
This has an O(𝑛) cost.
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
RE ERRNO OBJECT
|
||||
|
||||
re.Errno:errno()
|
||||
└─→ errno:int
|
||||
|
||||
Returns regex error number.
|
||||
|
||||
re.Errno:doc()
|
||||
└─→ description:str
|
||||
|
||||
Returns English string describing error code.
|
||||
|
||||
re.Errno:__tostring()
|
||||
└─→ str
|
||||
|
||||
Delegates to re.Errno:doc()
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
RE ERRORS
|
||||
|
||||
re.NOMATCH
|
||||
No match
|
||||
|
||||
re.BADPAT
|
||||
Invalid regex
|
||||
|
||||
re.ECOLLATE
|
||||
Unknown collating element
|
||||
|
||||
re.ECTYPE
|
||||
Unknown character class name
|
||||
|
||||
re.EESCAPE
|
||||
Trailing backslash
|
||||
|
||||
re.ESUBREG
|
||||
Invalid back reference
|
||||
|
||||
re.EBRACK
|
||||
Missing `]`
|
||||
|
||||
re.EPAREN
|
||||
Missing `)`
|
||||
|
||||
re.EBRACE
|
||||
Missing `}`
|
||||
|
||||
re.BADBR
|
||||
Invalid contents of `{}`
|
||||
|
||||
re.ERANGE
|
||||
Invalid character range.
|
||||
|
||||
re.ESPACE
|
||||
Out of memory
|
||||
|
||||
re.BADRPT
|
||||
Repetition not preceded by valid expression
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
RE FLAGS
|
||||
|
||||
re.BASIC
|
||||
Use this flag if you prefer the default POSIX regex syntax. We use
|
||||
|
@ -1578,27 +1698,29 @@ RE MODULE
|
|||
may only be used with re.compile and re.search.
|
||||
|
||||
re.NEWLINE
|
||||
Use this flag to change the handling of NEWLINE (\x0a) characters.
|
||||
When this flag is set, (1) a NEWLINE shall not be matched by a "."
|
||||
or any form of a non-matching list, (2) a "^" shall match the
|
||||
zero-length string immediately after a NEWLINE (regardless of
|
||||
re.NOTBOL), and (3) a "$" shall match the zero-length string
|
||||
immediately before a NEWLINE (regardless of re.NOTEOL).
|
||||
Use this flag to change the handling of NEWLINE (\x0a)
|
||||
characters. When this flag is set, (1) a NEWLINE shall not be
|
||||
matched by a "." or any form of a non-matching list, (2) a "^"
|
||||
shall match the zero-length string immediately after a NEWLINE
|
||||
(regardless of re.NOTBOL), and (3) a "$" shall match the
|
||||
zero-length string immediately before a NEWLINE (regardless of
|
||||
re.NOTEOL).
|
||||
|
||||
re.NOSUB
|
||||
Causes re.search to only report success and failure. This is
|
||||
reported via the API by returning empty string for success. This
|
||||
flag may only be used with re.compile and re.search.
|
||||
reported via the API by returning empty string for success.
|
||||
This flag may only be used with re.compile and re.search.
|
||||
|
||||
re.NOTBOL
|
||||
The first character of the string pointed to by string is not the
|
||||
beginning of the line. This flag may only be used with re.search
|
||||
and regex_t*:search.
|
||||
The first character of the string pointed to by string is not
|
||||
the beginning of the line. This flag may only be used with
|
||||
re.search and re.Regex:search.
|
||||
|
||||
re.NOTEOL
|
||||
The last character of the string pointed to by string is not the
|
||||
end of the line. This flag may only be used with re.search and
|
||||
regex_t*:search.
|
||||
The last character of the string pointed to by string is not
|
||||
the end of the line. This flag may only be used with re.search
|
||||
and re.Regex:search.
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
MAXMIND MODULE
|
||||
|
@ -1621,6 +1743,7 @@ MAXMIND MODULE
|
|||
|
||||
For further details, please see maxmind.lua in redbean-demo.com.
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
ARGON2 MODULE
|
||||
|
||||
|
@ -1688,6 +1811,7 @@ ARGON2 MODULE
|
|||
"password")
|
||||
true
|
||||
|
||||
|
||||
────────────────────────────────────────────────────────────────────────────────
|
||||
UNIX MODULE
|
||||
|
||||
|
@ -2276,6 +2400,18 @@ UNIX MODULE
|
|||
thereby assisting with simple absolute filename checks in addition
|
||||
to enabling one to exceed the traditional 260 character limit.
|
||||
|
||||
unix.rmrf(path:str)
|
||||
├─→ true
|
||||
└─→ nil, unix.Errno
|
||||
|
||||
Recursively removes filesystem path.
|
||||
|
||||
Like unix.makedirs() this function isn't actually a system call but
|
||||
rather is a Libc convenience wrapper. It's intended to be equivalent
|
||||
to using the UNIX shell's `rm -rf path` command.
|
||||
|
||||
`path` is the file or directory path you wish to destroy.
|
||||
|
||||
unix.fcntl(fd:int, cmd:int, ...)
|
||||
├─→ ...
|
||||
└─→ nil, unix.Errno
|
||||
|
@ -2532,7 +2668,7 @@ UNIX MODULE
|
|||
|
||||
`whence` can be one of:
|
||||
|
||||
- `SEEK_SET`: Sets the file position to `offset`
|
||||
- `SEEK_SET`: Sets the file position to `offset` [default]
|
||||
- `SEEK_CUR`: Sets the file position to `position + offset`
|
||||
- `SEEK_END`: Sets the file position to `filesize + offset`
|
||||
|
||||
|
@ -2580,14 +2716,14 @@ UNIX MODULE
|
|||
- `SOCK_CLOEXEC`
|
||||
- `SOCK_NONBLOCK`
|
||||
|
||||
`protocol` defaults to `IPPROTO_TCP` for AF_INET` and `0` for
|
||||
`AF_UNIX`. It can also be:
|
||||
`protocol` may be any of:
|
||||
|
||||
- `IPPROTO_IP`
|
||||
- `IPPROTO_ICMP`
|
||||
- `0` to let kernel choose [default]
|
||||
- `IPPROTO_TCP`
|
||||
- `IPPROTO_UDP`
|
||||
- `IPPROTO_RAW`
|
||||
- `IPPROTO_IP`
|
||||
- `IPPROTO_ICMP`
|
||||
|
||||
unix.socketpair([family:int[, type:int[, protocol:int]]])
|
||||
├─→ fd1:int, fd2:int
|
||||
|
@ -2964,18 +3100,19 @@ UNIX MODULE
|
|||
|
||||
Example:
|
||||
|
||||
assert(unix.sigaction(unix.SIGUSR1, function(sig)
|
||||
gotsigusr1 = true
|
||||
end))
|
||||
gotsigusr1 = false
|
||||
assert(unix.raise(unix.SIGUSR1))
|
||||
ok, err = unix.sigsuspend()
|
||||
assert(err:errno == unix.EINTR)
|
||||
if gotsigusr1
|
||||
print('hooray the signal was delivered')
|
||||
else
|
||||
print('oh no some other signal was handled')
|
||||
function OnSigUsr1(sig)
|
||||
gotsigusr1 = true
|
||||
end
|
||||
gotsigusr1 = false
|
||||
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGUSR1)))
|
||||
assert(unix.sigaction(unix.SIGUSR1, OnSigUsr1))
|
||||
assert(unix.raise(unix.SIGUSR1))
|
||||
assert(not gotsigusr1)
|
||||
ok, err = unix.sigsuspend(oldmask)
|
||||
assert(not ok)
|
||||
assert(err:errno() == unix.EINTR)
|
||||
assert(gotsigusr1)
|
||||
assert(unix.sigprocmask(unix.SIG_SETMASK, oldmask))
|
||||
|
||||
It's a good idea to not do too much work in a signal handler.
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ int LuaResolveIp(lua_State *L) {
|
|||
}
|
||||
|
||||
static int LuaCheckControlFlags(lua_State *L, int idx) {
|
||||
int f = luaL_checkinteger(L, idx);
|
||||
int f = luaL_optinteger(L, idx, 0);
|
||||
if (f & ~(kControlWs | kControlC0 | kControlC1)) {
|
||||
luaL_argerror(L, idx, "invalid control flags");
|
||||
unreachable;
|
||||
|
|
193
tool/net/lre.c
193
tool/net/lre.c
|
@ -17,13 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/lua/lauxlib.h"
|
||||
#include "third_party/regex/regex.h"
|
||||
|
||||
static const char kRegCode[][8] = {
|
||||
"OK", "NOMATCH", "BADPAT", "COLLATE", "ECTYPE", "EESCAPE", "ESUBREG",
|
||||
"EBRACK", "EPAREN", "EBRACE", "BADBR", "ERANGE", "ESPACE", "BADRPT",
|
||||
struct ReErrno {
|
||||
int err;
|
||||
char doc[64];
|
||||
};
|
||||
|
||||
static void LuaSetIntField(lua_State *L, const char *k, lua_Integer v) {
|
||||
|
@ -31,40 +30,53 @@ static void LuaSetIntField(lua_State *L, const char *k, lua_Integer v) {
|
|||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static int LuaReReturnError(lua_State *L, regex_t *r, int rc) {
|
||||
struct ReErrno *e;
|
||||
lua_pushnil(L);
|
||||
e = lua_newuserdatauv(L, sizeof(struct ReErrno), 0);
|
||||
luaL_setmetatable(L, "re.Errno");
|
||||
e->err = rc;
|
||||
regerror(rc, r, e->doc, sizeof(e->doc));
|
||||
return 2;
|
||||
}
|
||||
|
||||
static regex_t *LuaReCompileImpl(lua_State *L, const char *p, int f) {
|
||||
int e;
|
||||
int rc;
|
||||
regex_t *r;
|
||||
r = xmalloc(sizeof(regex_t));
|
||||
r = lua_newuserdatauv(L, sizeof(regex_t), 0);
|
||||
luaL_setmetatable(L, "re.Regex");
|
||||
f &= REG_EXTENDED | REG_ICASE | REG_NEWLINE | REG_NOSUB;
|
||||
f ^= REG_EXTENDED;
|
||||
if ((e = regcomp(r, p, f)) != REG_OK) {
|
||||
free(r);
|
||||
luaL_error(L, "regcomp(%s) → REG_%s", p,
|
||||
kRegCode[MAX(0, MIN(ARRAYLEN(kRegCode) - 1, e))]);
|
||||
unreachable;
|
||||
if ((rc = regcomp(r, p, f)) == REG_OK) {
|
||||
return r;
|
||||
} else {
|
||||
LuaReReturnError(L, r, rc);
|
||||
return NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int LuaReSearchImpl(lua_State *L, regex_t *r, const char *s, int f) {
|
||||
int i, n;
|
||||
int rc, i, n;
|
||||
regmatch_t *m;
|
||||
n = r->re_nsub + 1;
|
||||
m = xcalloc(n, sizeof(regmatch_t));
|
||||
if (regexec(r, s, n, m, f >> 8) == REG_OK) {
|
||||
luaL_Buffer tmp;
|
||||
n = 1 + r->re_nsub;
|
||||
m = (regmatch_t *)luaL_buffinitsize(L, &tmp, n * sizeof(regmatch_t));
|
||||
if ((rc = regexec(r, s, n, m, f >> 8)) == REG_OK) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
lua_pushlstring(L, s + m[i].rm_so, m[i].rm_eo - m[i].rm_so);
|
||||
}
|
||||
return n;
|
||||
} else {
|
||||
n = 0;
|
||||
return LuaReReturnError(L, r, rc);
|
||||
}
|
||||
free(m);
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// re
|
||||
|
||||
static int LuaReSearch(lua_State *L) {
|
||||
int f;
|
||||
regex_t *r;
|
||||
int i, e, n, f;
|
||||
const char *p, *s;
|
||||
p = luaL_checkstring(L, 1);
|
||||
s = luaL_checkstring(L, 2);
|
||||
|
@ -74,56 +86,51 @@ static int LuaReSearch(lua_State *L) {
|
|||
luaL_argerror(L, 3, "invalid flags");
|
||||
unreachable;
|
||||
}
|
||||
r = LuaReCompileImpl(L, p, f);
|
||||
n = LuaReSearchImpl(L, r, s, f);
|
||||
regfree(r);
|
||||
free(r);
|
||||
return n;
|
||||
if ((r = LuaReCompileImpl(L, p, f))) {
|
||||
return LuaReSearchImpl(L, r, s, f);
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int LuaReCompile(lua_State *L) {
|
||||
int f, e;
|
||||
int f;
|
||||
regex_t *r;
|
||||
const char *p;
|
||||
regex_t *r, **u;
|
||||
p = luaL_checkstring(L, 1);
|
||||
f = luaL_optinteger(L, 2, 0);
|
||||
if (f & ~(REG_EXTENDED | REG_ICASE | REG_NEWLINE | REG_NOSUB)) {
|
||||
luaL_argerror(L, 3, "invalid flags");
|
||||
luaL_argerror(L, 2, "invalid flags");
|
||||
unreachable;
|
||||
}
|
||||
r = LuaReCompileImpl(L, p, f);
|
||||
u = lua_newuserdata(L, sizeof(regex_t *));
|
||||
luaL_setmetatable(L, "regex_t*");
|
||||
*u = r;
|
||||
return 1;
|
||||
if ((r = LuaReCompileImpl(L, p, f))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// re.Regex
|
||||
|
||||
static int LuaReRegexSearch(lua_State *L) {
|
||||
int f;
|
||||
regex_t **u;
|
||||
regex_t *r;
|
||||
const char *s;
|
||||
u = luaL_checkudata(L, 1, "regex_t*");
|
||||
r = luaL_checkudata(L, 1, "re.Regex");
|
||||
s = luaL_checkstring(L, 2);
|
||||
f = luaL_optinteger(L, 3, 0);
|
||||
if (!*u) {
|
||||
luaL_argerror(L, 1, "destroyed");
|
||||
unreachable;
|
||||
}
|
||||
if (f & ~(REG_NOTBOL << 8 | REG_NOTEOL << 8)) {
|
||||
luaL_argerror(L, 3, "invalid flags");
|
||||
unreachable;
|
||||
}
|
||||
return LuaReSearchImpl(L, *u, s, f);
|
||||
return LuaReSearchImpl(L, r, s, f);
|
||||
}
|
||||
|
||||
static int LuaReRegexGc(lua_State *L) {
|
||||
regex_t **u;
|
||||
u = luaL_checkudata(L, 1, "regex_t*");
|
||||
if (*u) {
|
||||
regfree(*u);
|
||||
free(*u);
|
||||
*u = NULL;
|
||||
}
|
||||
regex_t *r;
|
||||
r = luaL_checkudata(L, 1, "re.Regex");
|
||||
regfree(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -143,8 +150,8 @@ static const luaL_Reg kLuaReRegexMeta[] = {
|
|||
{NULL, NULL}, //
|
||||
};
|
||||
|
||||
static void LuaReRegex(lua_State *L) {
|
||||
luaL_newmetatable(L, "regex_t*");
|
||||
static void LuaReRegexObj(lua_State *L) {
|
||||
luaL_newmetatable(L, "re.Regex");
|
||||
luaL_setfuncs(L, kLuaReRegexMeta, 0);
|
||||
luaL_newlibtable(L, kLuaReRegexMeth);
|
||||
luaL_setfuncs(L, kLuaReRegexMeth, 0);
|
||||
|
@ -152,14 +159,84 @@ static void LuaReRegex(lua_State *L) {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
int LuaRe(lua_State *L) {
|
||||
luaL_newlib(L, kLuaRe);
|
||||
LuaSetIntField(L, "BASIC", REG_EXTENDED);
|
||||
LuaSetIntField(L, "ICASE", REG_ICASE);
|
||||
LuaSetIntField(L, "NEWLINE", REG_NEWLINE);
|
||||
LuaSetIntField(L, "NOSUB", REG_NOSUB);
|
||||
LuaSetIntField(L, "NOTBOL", REG_NOTBOL << 8);
|
||||
LuaSetIntField(L, "NOTEOL", REG_NOTEOL << 8);
|
||||
LuaReRegex(L);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// re.Errno
|
||||
|
||||
static struct ReErrno *GetReErrno(lua_State *L) {
|
||||
return luaL_checkudata(L, 1, "re.Errno");
|
||||
}
|
||||
|
||||
// re.Errno:errno()
|
||||
// └─→ errno:int
|
||||
static int LuaReErrnoErrno(lua_State *L) {
|
||||
lua_pushinteger(L, GetReErrno(L)->err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// re.Errno:doc()
|
||||
// └─→ description:str
|
||||
static int LuaReErrnoDoc(lua_State *L) {
|
||||
lua_pushstring(L, GetReErrno(L)->doc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg kLuaReErrnoMeth[] = {
|
||||
{"errno", LuaReErrnoErrno}, //
|
||||
{"doc", LuaReErrnoDoc}, //
|
||||
{0}, //
|
||||
};
|
||||
|
||||
static const luaL_Reg kLuaReErrnoMeta[] = {
|
||||
{"__tostring", LuaReErrnoDoc}, //
|
||||
{0}, //
|
||||
};
|
||||
|
||||
static void LuaReErrnoObj(lua_State *L) {
|
||||
luaL_newmetatable(L, "re.Errno");
|
||||
luaL_setfuncs(L, kLuaReErrnoMeta, 0);
|
||||
luaL_newlibtable(L, kLuaReErrnoMeth);
|
||||
luaL_setfuncs(L, kLuaReErrnoMeth, 0);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_Alignas(1) static const struct thatispacked {
|
||||
const char s[8];
|
||||
char x;
|
||||
} kReMagnums[] = {
|
||||
{"BASIC", REG_EXTENDED}, // compile flag
|
||||
{"ICASE", REG_ICASE}, // compile flag
|
||||
{"NEWLINE", REG_NEWLINE}, // compile flag
|
||||
{"NOSUB", REG_NOSUB}, // compile flag
|
||||
{"NOMATCH", REG_NOMATCH}, // error
|
||||
{"BADPAT", REG_BADPAT}, // error
|
||||
{"ECOLLATE", REG_ECOLLATE}, // error
|
||||
{"ECTYPE", REG_ECTYPE}, // error
|
||||
{"EESCAPE", REG_EESCAPE}, // error
|
||||
{"ESUBREG", REG_ESUBREG}, // error
|
||||
{"EBRACK", REG_EBRACK}, // error
|
||||
{"EPAREN", REG_EPAREN}, // error
|
||||
{"EBRACE", REG_EBRACE}, // error
|
||||
{"BADBR", REG_BADBR}, // error
|
||||
{"ERANGE", REG_ERANGE}, // error
|
||||
{"ESPACE", REG_ESPACE}, // error
|
||||
{"BADRPT", REG_BADRPT}, // error
|
||||
};
|
||||
|
||||
int LuaRe(lua_State *L) {
|
||||
int i;
|
||||
char buf[9];
|
||||
luaL_newlib(L, kLuaRe);
|
||||
LuaSetIntField(L, "NOTBOL", REG_NOTBOL << 8); // search flag
|
||||
LuaSetIntField(L, "NOTEOL", REG_NOTEOL << 8); // search flag
|
||||
for (i = 0; i < ARRAYLEN(kReMagnums); ++i) {
|
||||
memcpy(buf, kReMagnums[i].s, 8);
|
||||
buf[8] = 0;
|
||||
LuaSetIntField(L, buf, kReMagnums[i].x);
|
||||
}
|
||||
LuaReRegexObj(L);
|
||||
LuaReErrnoObj(L);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -5398,7 +5398,11 @@ static void LuaInit(void) {
|
|||
lua_State *L = GL;
|
||||
LuaSetArgv(L);
|
||||
if (interpretermode) {
|
||||
exit(LuaInterpreter(L));
|
||||
int rc = LuaInterpreter(L);
|
||||
if (IsModeDbg()) {
|
||||
CheckForMemoryLeaks();
|
||||
}
|
||||
exit(rc);
|
||||
}
|
||||
if (LuaRunAsset("/.init.lua", true)) {
|
||||
hasonhttprequest = IsHookDefined("OnHttpRequest");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue