diff --git a/libc/calls/execve.c b/libc/calls/execve.c index ab6212a26..55dc288f9 100644 --- a/libc/calls/execve.c +++ b/libc/calls/execve.c @@ -23,14 +23,6 @@ #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" -static noasan bool __asan_is_valid_strlist(char *const *p) { - for (;; ++p) { - if (!__asan_is_valid(p, sizeof(char *))) return false; - if (!*p) return true; - if (!__asan_is_valid(*p, 1)) return false; - } -} - /** * Replaces current process with program. * diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index bab24408c..0b2ee1d04 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -402,6 +402,14 @@ bool __asan_is_valid_iov(const struct iovec *iov, int iovlen) { } } +bool __asan_is_valid_strlist(char *const *p) { + for (;; ++p) { + if (!__asan_is_valid(p, sizeof(char *))) return false; + if (!*p) return true; + if (!__asan_is_valid(*p, 1)) return false; + } +} + static const char *__asan_dscribe_heap_poison(long c) { switch (c) { case kAsanHeapFree: diff --git a/libc/intrin/asan.internal.h b/libc/intrin/asan.internal.h index 8f301e39b..b8d45ce8f 100644 --- a/libc/intrin/asan.internal.h +++ b/libc/intrin/asan.internal.h @@ -25,5 +25,6 @@ void __asan_poison(uintptr_t, size_t, int); void __asan_unpoison(uintptr_t, size_t); bool __asan_is_valid(const void *, size_t); bool __asan_is_valid_iov(const struct iovec *, int); +bool __asan_is_valid_strlist(char *const *); #endif /* COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ */ diff --git a/libc/str/getzipcdir.c b/libc/str/getzipcdir.c index d69ec9c3f..82c73b02b 100644 --- a/libc/str/getzipcdir.c +++ b/libc/str/getzipcdir.c @@ -38,18 +38,18 @@ void *GetZipCdir(const uint8_t *p, size_t n) { if (READ32LE(p + i) == kZipCdir64LocatorMagic && i + kZipCdir64LocatorSize <= n && IsZipCdir64(p, n, ZIP_LOCATE64_OFFSET(p + i))) { - return (void *)(p + ZIP_LOCATE64_OFFSET(p + i)); + return p + ZIP_LOCATE64_OFFSET(p + i); } else if (READ32LE(p + i) == kZipCdirHdrMagic && IsZipCdir32(p, n, i)) { j = i; do { if (READ32LE(p + j) == kZipCdir64LocatorMagic && j + kZipCdir64LocatorSize <= n && IsZipCdir64(p, n, ZIP_LOCATE64_OFFSET(p + j))) { - return (void *)(p + ZIP_LOCATE64_OFFSET(p + j)); + return p + ZIP_LOCATE64_OFFSET(p + j); } } while (j-- && i - j < 1024); - return (void *)(p + i); + return p + i; } } while (i--); - return NULL; + return 0; } diff --git a/libc/str/highwayhash64.c b/libc/str/highwayhash64.c index c013ef7ac..bfd45c532 100644 --- a/libc/str/highwayhash64.c +++ b/libc/str/highwayhash64.c @@ -15,6 +15,7 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" #include "libc/str/highwayhash64.h" asm(".ident\t\"\\n\\n\ @@ -30,14 +31,14 @@ typedef struct { } HighwayHashState; static void HighwayHashReset(const uint64_t key[4], HighwayHashState *state) { - state->mul0[0] = 0xdbe6d5d5fe4cce2full; - state->mul0[1] = 0xa4093822299f31d0ull; - state->mul0[2] = 0x13198a2e03707344ull; - state->mul0[3] = 0x243f6a8885a308d3ull; - state->mul1[0] = 0x3bd39e10cb0ef593ull; - state->mul1[1] = 0xc0acf169b5f18a8cull; - state->mul1[2] = 0xbe5466cf34e90c6cull; - state->mul1[3] = 0x452821e638d01377ull; + state->mul0[0] = 0xdbe6d5d5fe4cce2f; + state->mul0[1] = 0xa4093822299f31d0; + state->mul0[2] = 0x13198a2e03707344; + state->mul0[3] = 0x243f6a8885a308d3; + state->mul1[0] = 0x3bd39e10cb0ef593; + state->mul1[1] = 0xc0acf169b5f18a8c; + state->mul1[2] = 0xbe5466cf34e90c6c; + state->mul1[3] = 0x452821e638d01377; state->v0[0] = state->mul0[0] ^ key[0]; state->v0[1] = state->mul0[1] ^ key[1]; state->v0[2] = state->mul0[2] ^ key[2]; @@ -50,14 +51,14 @@ static void HighwayHashReset(const uint64_t key[4], HighwayHashState *state) { static void ZipperMergeAndAdd(const uint64_t v1, const uint64_t v0, uint64_t *add1, uint64_t *add0) { - *add0 += (((v0 & 0xff000000ull) | (v1 & 0xff00000000ull)) >> 24) | - (((v0 & 0xff0000000000ull) | (v1 & 0xff000000000000ull)) >> 16) | - (v0 & 0xff0000ull) | ((v0 & 0xff00ull) << 32) | - ((v1 & 0xff00000000000000ull) >> 8) | (v0 << 56); - *add1 += (((v1 & 0xff000000ull) | (v0 & 0xff00000000ull)) >> 24) | - (v1 & 0xff0000ull) | ((v1 & 0xff0000000000ull) >> 16) | - ((v1 & 0xff00ull) << 24) | ((v0 & 0xff000000000000ull) >> 8) | - ((v1 & 0xffull) << 48) | (v0 & 0xff00000000000000ull); + *add0 += (((v0 & 0xff000000) | (v1 & 0xff00000000)) >> 24) | + (((v0 & 0xff0000000000) | (v1 & 0xff000000000000)) >> 16) | + (v0 & 0xff0000) | ((v0 & 0xff00) << 32) | + ((v1 & 0xff00000000000000) >> 8) | (v0 << 56); + *add1 += (((v1 & 0xff000000) | (v0 & 0xff00000000)) >> 24) | (v1 & 0xff0000) | + ((v1 & 0xff0000000000) >> 16) | ((v1 & 0xff00) << 24) | + ((v0 & 0xff000000000000) >> 8) | ((v1 & 0xff) << 48) | + (v0 & 0xff00000000000000); } static void Update(const uint64_t lanes[4], HighwayHashState *state) { @@ -74,20 +75,13 @@ static void Update(const uint64_t lanes[4], HighwayHashState *state) { ZipperMergeAndAdd(state->v0[3], state->v0[2], &state->v1[3], &state->v1[2]); } -static uint64_t Read64(const uint8_t *src) { - return (uint64_t)src[0] | ((uint64_t)src[1] << 8) | ((uint64_t)src[2] << 16) | - ((uint64_t)src[3] << 24) | ((uint64_t)src[4] << 32) | - ((uint64_t)src[5] << 40) | ((uint64_t)src[6] << 48) | - ((uint64_t)src[7] << 56); -} - static void HighwayHashUpdatePacket(const uint8_t *packet, HighwayHashState *state) { uint64_t lanes[4]; - lanes[0] = Read64(packet + 0); - lanes[1] = Read64(packet + 8); - lanes[2] = Read64(packet + 16); - lanes[3] = Read64(packet + 24); + lanes[0] = READ64LE(packet + 000); + lanes[1] = READ64LE(packet + 010); + lanes[2] = READ64LE(packet + 020); + lanes[3] = READ64LE(packet + 030); Update(lanes, state); } @@ -130,10 +124,10 @@ static void HighwayHashUpdateRemainder(const uint8_t *bytes, } static void Permute(const uint64_t v[4], uint64_t *permuted) { - permuted[0] = (v[2] >> 32) | (v[2] << 32); - permuted[1] = (v[3] >> 32) | (v[3] << 32); - permuted[2] = (v[0] >> 32) | (v[0] << 32); - permuted[3] = (v[1] >> 32) | (v[1] << 32); + permuted[0] = v[2] >> 32 | v[2] << 32; + permuted[1] = v[3] >> 32 | v[3] << 32; + permuted[2] = v[0] >> 32 | v[0] << 32; + permuted[3] = v[1] >> 32 | v[1] << 32; } static void PermuteAndUpdate(HighwayHashState *state) { diff --git a/libc/str/thompike.h b/libc/str/thompike.h index c975aaf8d..2cae952ce 100644 --- a/libc/str/thompike.h +++ b/libc/str/thompike.h @@ -2,10 +2,10 @@ #define COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ #include "libc/nexgen32e/bsr.h" -#define ThomPikeCont(x) (((x)&0300) == 0200) +#define ThomPikeCont(x) (0200 == (0300 & (x))) #define ThomPikeByte(x) ((x) & (((1 << ThomPikeMsb(x)) - 1) | 3)) #define ThomPikeLen(x) (7 - ThomPikeMsb(x)) -#define ThomPikeMsb(x) (((x)&0xff) < 252 ? bsr(~(x)&0xff) : 1) -#define ThomPikeMerge(x, y) ((x) << 6 | (y)&077) +#define ThomPikeMsb(x) ((255 & (x)) < 252 ? bsr(255 & ~(x)) : 1) +#define ThomPikeMerge(x, y) ((x) << 6 | 077 & (y)) #endif /* COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ */ diff --git a/libc/str/windowstimetotimeval.c b/libc/str/windowstimetotimeval.c index f591f8fed..615897b4f 100644 --- a/libc/str/windowstimetotimeval.c +++ b/libc/str/windowstimetotimeval.c @@ -22,8 +22,6 @@ * Converts Windows COBOL timestamp to UNIX epoch in microseconds. */ struct timeval WindowsTimeToTimeVal(int64_t x) { - /* return WindowsDurationToTimeVal(x - MODERNITYSECONDS * HECTONANOSECONDS); - */ return (struct timeval){x / HECTONANOSECONDS - MODERNITYSECONDS, x % HECTONANOSECONDS / 10}; } diff --git a/libc/x/filecmp.c b/libc/x/filecmp.c index 39077015b..be074b2a8 100644 --- a/libc/x/filecmp.c +++ b/libc/x/filecmp.c @@ -17,9 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/alg/alg.h" -#include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/errno.h" +#include "libc/macros.internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/madv.h" #include "libc/sysv/consts/map.h" @@ -55,7 +55,7 @@ int filecmp(const char *pathname1, const char *pathname2) { madvise(addr1, size1, MADV_WILLNEED | MADV_SEQUENTIAL); madvise(addr2, size2, MADV_WILLNEED | MADV_SEQUENTIAL); errno = olderr; - res = memcmp(addr1, addr2, min(size1, size2)); + res = memcmp(addr1, addr2, MIN(size1, size2)); if (!res && size1 != size2) { char kNul = '\0'; if (size1 > size2) { diff --git a/test/libc/calls/readansi_test.c b/test/libc/calls/readansi_test.c index f0ddc8362..f5ad10afe 100644 --- a/test/libc/calls/readansi_test.c +++ b/test/libc/calls/readansi_test.c @@ -29,10 +29,8 @@ TEST(readansi, test) { ASSERT_NE(-1, pipe(fds)); ASSERT_NE(-1, (pid = fork())); if (!pid) { - close(fds[0]); s = "a\eM\e[A→\e[123;456R\e[>c\eOz\xc2\x9bM"; write(fds[1], s, strlen(s)); - close(fds[1]); _exit(0); } close(fds[1]); @@ -54,7 +52,6 @@ TEST(readansi, test) { EXPECT_STREQ("\xc2\x9bM", b); EXPECT_EQ(0, readansi(fds[0], b, 16)); EXPECT_STREQ("", b); - close(fds[0]); ASSERT_NE(-1, wait(&ws)); ASSERT_TRUE(WIFEXITED(ws)); ASSERT_EQ(0, WEXITSTATUS(ws)); diff --git a/test/libc/str/highwayhash64_test.c b/test/libc/str/highwayhash64_test.c index 0c7bb7f35..13ccfc39b 100644 --- a/test/libc/str/highwayhash64_test.c +++ b/test/libc/str/highwayhash64_test.c @@ -27,37 +27,37 @@ #define kMaxSize 64 static const uint64_t kTestKey1[4] = { - 0x0706050403020100ull, - 0x0F0E0D0C0B0A0908ull, - 0x1716151413121110ull, - 0x1F1E1D1C1B1A1918ull, + 0x0706050403020100, + 0x0F0E0D0C0B0A0908, + 0x1716151413121110, + 0x1F1E1D1C1B1A1918, }; -static const uint64_t kTestKey2[4] = {1ull, 2ull, 3ull, 4ull}; +static const uint64_t kTestKey2[4] = {1, 2, 3, 4}; const uint64_t kExpected64[kMaxSize + 1] = { - 0x907A56DE22C26E53ull, 0x7EAB43AAC7CDDD78ull, 0xB8D0569AB0B53D62ull, - 0x5C6BEFAB8A463D80ull, 0xF205A46893007EDAull, 0x2B8A1668E4A94541ull, - 0xBD4CCC325BEFCA6Full, 0x4D02AE1738F59482ull, 0xE1205108E55F3171ull, - 0x32D2644EC77A1584ull, 0xF6E10ACDB103A90Bull, 0xC3BBF4615B415C15ull, - 0x243CC2040063FA9Cull, 0xA89A58CE65E641FFull, 0x24B031A348455A23ull, - 0x40793F86A449F33Bull, 0xCFAB3489F97EB832ull, 0x19FE67D2C8C5C0E2ull, - 0x04DD90A69C565CC2ull, 0x75D9518E2371C504ull, 0x38AD9B1141D3DD16ull, - 0x0264432CCD8A70E0ull, 0xA9DB5A6288683390ull, 0xD7B05492003F028Cull, - 0x205F615AEA59E51Eull, 0xEEE0C89621052884ull, 0x1BFC1A93A7284F4Full, - 0x512175B5B70DA91Dull, 0xF71F8976A0A2C639ull, 0xAE093FEF1F84E3E7ull, - 0x22CA92B01161860Full, 0x9FC7007CCF035A68ull, 0xA0C964D9ECD580FCull, - 0x2C90F73CA03181FCull, 0x185CF84E5691EB9Eull, 0x4FC1F5EF2752AA9Bull, - 0xF5B7391A5E0A33EBull, 0xB9B84B83B4E96C9Cull, 0x5E42FE712A5CD9B4ull, - 0xA150F2F90C3F97DCull, 0x7FA522D75E2D637Dull, 0x181AD0CC0DFFD32Bull, - 0x3889ED981E854028ull, 0xFB4297E8C586EE2Dull, 0x6D064A45BB28059Cull, - 0x90563609B3EC860Cull, 0x7AA4FCE94097C666ull, 0x1326BAC06B911E08ull, - 0xB926168D2B154F34ull, 0x9919848945B1948Dull, 0xA2A98FC534825EBEull, - 0xE9809095213EF0B6ull, 0x582E5483707BC0E9ull, 0x086E9414A88A6AF5ull, - 0xEE86B98D20F6743Dull, 0xF89B7FF609B1C0A7ull, 0x4C7D9CC19E22C3E8ull, - 0x9A97005024562A6Full, 0x5DD41CF423E6EBEFull, 0xDF13609C0468E227ull, - 0x6E0DA4F64188155Aull, 0xB755BA4B50D7D4A1ull, 0x887A3484647479BDull, - 0xAB8EEBE9BF2139A0ull, 0x75542C5D4CD2A6FFull, + 0x907A56DE22C26E53, 0x7EAB43AAC7CDDD78, 0xB8D0569AB0B53D62, + 0x5C6BEFAB8A463D80, 0xF205A46893007EDA, 0x2B8A1668E4A94541, + 0xBD4CCC325BEFCA6F, 0x4D02AE1738F59482, 0xE1205108E55F3171, + 0x32D2644EC77A1584, 0xF6E10ACDB103A90B, 0xC3BBF4615B415C15, + 0x243CC2040063FA9C, 0xA89A58CE65E641FF, 0x24B031A348455A23, + 0x40793F86A449F33B, 0xCFAB3489F97EB832, 0x19FE67D2C8C5C0E2, + 0x04DD90A69C565CC2, 0x75D9518E2371C504, 0x38AD9B1141D3DD16, + 0x0264432CCD8A70E0, 0xA9DB5A6288683390, 0xD7B05492003F028C, + 0x205F615AEA59E51E, 0xEEE0C89621052884, 0x1BFC1A93A7284F4F, + 0x512175B5B70DA91D, 0xF71F8976A0A2C639, 0xAE093FEF1F84E3E7, + 0x22CA92B01161860F, 0x9FC7007CCF035A68, 0xA0C964D9ECD580FC, + 0x2C90F73CA03181FC, 0x185CF84E5691EB9E, 0x4FC1F5EF2752AA9B, + 0xF5B7391A5E0A33EB, 0xB9B84B83B4E96C9C, 0x5E42FE712A5CD9B4, + 0xA150F2F90C3F97DC, 0x7FA522D75E2D637D, 0x181AD0CC0DFFD32B, + 0x3889ED981E854028, 0xFB4297E8C586EE2D, 0x6D064A45BB28059C, + 0x90563609B3EC860C, 0x7AA4FCE94097C666, 0x1326BAC06B911E08, + 0xB926168D2B154F34, 0x9919848945B1948D, 0xA2A98FC534825EBE, + 0xE9809095213EF0B6, 0x582E5483707BC0E9, 0x086E9414A88A6AF5, + 0xEE86B98D20F6743D, 0xF89B7FF609B1C0A7, 0x4C7D9CC19E22C3E8, + 0x9A97005024562A6F, 0x5DD41CF423E6EBEF, 0xDF13609C0468E227, + 0x6E0DA4F64188155A, 0xB755BA4B50D7D4A1, 0x887A3484647479BD, + 0xAB8EEBE9BF2139A0, 0x75542C5D4CD2A6FF, }; uint32_t KnuthMultiplicativeHash32(const void *buf, size_t size) { diff --git a/test/libc/x/filecmp_test.c b/test/libc/x/filecmp_test.c new file mode 100644 index 000000000..fd1c94f41 --- /dev/null +++ b/test/libc/x/filecmp_test.c @@ -0,0 +1,61 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" +#include "libc/rand/rand.h" +#include "libc/runtime/gc.internal.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/madv.h" +#include "libc/sysv/consts/o.h" +#include "libc/testlib/ezbench.h" +#include "libc/testlib/testlib.h" +#include "libc/x/x.h" + +#define N (72 * 1024) + +char p[N]; +char testlib_enable_tmp_setup_teardown; + +TEST(filecmp, testEqual) { + rngset(p, N, rand64, -1); + EXPECT_EQ(0, xbarf("a", p, N)); + EXPECT_EQ(0, xbarf("b", p, N)); + EXPECT_EQ(0, filecmp("a", "b")); +} + +TEST(filecmp, testNotEqual) { + rngset(p, N, rand64, -1); + EXPECT_EQ(0, xbarf("a", p, N)); + p[N / 2]++; + EXPECT_EQ(0, xbarf("b", p, N)); + EXPECT_NE(0, filecmp("a", "b")); +} + +TEST(filecmp, testDifferentLength) { + rngset(p, N, rand64, -1); + EXPECT_EQ(0, xbarf("a", p, N)); + EXPECT_EQ(0, xbarf("b", p, N - 1)); + EXPECT_NE(0, filecmp("a", "b")); +} + +BENCH(filecmp, bench) { + rngset(p, N, rand64, -1); + EXPECT_EQ(0, xbarf("a", p, N)); + EXPECT_EQ(0, xbarf("b", p, N)); + EZBENCH2("filecmp", donothing, filecmp("a", "b")); +} diff --git a/test/libc/x/test.mk b/test/libc/x/test.mk index ed5dc0b68..b5fa44aa6 100644 --- a/test/libc/x/test.mk +++ b/test/libc/x/test.mk @@ -31,7 +31,9 @@ TEST_LIBC_X_DIRECTDEPS = \ LIBC_RUNTIME \ LIBC_STDIO \ LIBC_STR \ + LIBC_RAND \ LIBC_STUBS \ + LIBC_SYSV \ LIBC_TESTLIB \ LIBC_UNICODE \ LIBC_X \ diff --git a/third_party/lua/lapi.c b/third_party/lua/lapi.c index ce9ba51d1..0f8c7c001 100644 --- a/third_party/lua/lapi.c +++ b/third_party/lua/lapi.c @@ -110,7 +110,12 @@ LUA_API int lua_checkstack (lua_State *L, int n) { return res; } - +/** + * Exchanges values between different threads of the same state. + * + * This funcetion pops n values from the stack from, and pushes them onto + * the stack to. + */ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { int i; if (from == to) return; @@ -126,7 +131,15 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_unlock(to); } - +/** + * lua_atpanic + * + * [-0, +0, –] + * + * lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); + * + * Sets a new panic function and returns the old one (see §4.4). + */ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); @@ -136,7 +149,15 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { return old; } - +/** + * lua_version + * + * [-0, +0, –] + * + * lua_Number lua_version (lua_State *L); + * + * Returns the version number of this core. + */ LUA_API lua_Number lua_version (lua_State *L) { UNUSED(L); return LUA_VERSION_NUM; @@ -149,21 +170,51 @@ LUA_API lua_Number lua_version (lua_State *L) { */ -/* -** convert an acceptable stack index into an absolute index -*/ +/** + * lua_absindex + * + * [-0, +0, –] + * + * int lua_absindex (lua_State *L, int idx); + * + * Converts the acceptable index idx into an equivalent absolute index (that + * is, one that does not depend on the stack size). + */ LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx : cast_int(L->top - L->ci->func) + idx; } - +/** + * lua_gettop + * + * [-0, +0, –] + * + * int lua_gettop (lua_State *L); + * + * Returns the index of the top element in the stack. Because indices start + * at 1, this result is equal to the number of elements in the stack; in + * particular, 0 means an empty stack. + */ LUA_API int lua_gettop (lua_State *L) { return cast_int(L->top - (L->ci->func + 1)); } - +/** + * lua_settop + * + * [-?, +?, e] + * + * void lua_settop (lua_State *L, int index); + * + * Accepts any index, or 0, and sets the stack top to this index. If the new + * top is greater than the old one, then the new elements are filled with + * nil. If index is 0, then all stack elements are removed. + * + * This function can run arbitrary code when removing an index marked as + * to-be-closed from the stack. + */ LUA_API void lua_settop (lua_State *L, int idx) { CallInfo *ci; StkId func, newtop; @@ -481,6 +532,11 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { */ +/** + * lua_pushnil [-0, +1, –] + * + * Pushes a nil value onto the stack. + */ LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); setnilvalue(s2v(L->top)); @@ -489,6 +545,11 @@ LUA_API void lua_pushnil (lua_State *L) { } +/** + * lua_pushnumber [-0, +1, –] + * + * Pushes a float with value n onto the stack. + */ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); setfltvalue(s2v(L->top), n); @@ -497,6 +558,13 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { } +/** + * lua_pushinteger [-0, +1, –] + * + * void lua_pushinteger (lua_State *L, lua_Integer n); + * + * Pushes an integer with value n onto the stack. + */ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); setivalue(s2v(L->top), n); @@ -522,6 +590,17 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { } +/** + * lua_pushstring [-0, +1, m] + * + * Pushes the zero-terminated string pointed to by s onto the stack. Lua will + * make or reuse an internal copy of the given string, so the memory at s can + * be freed or reused immediately after the function returns. + * + * Returns a pointer to the internal copy of the string (see §4.1.3). + * + * If s is NULL, pushes nil and returns NULL. + */ LUA_API const char *lua_pushstring (lua_State *L, const char *s) { lua_lock(L); if (s == NULL) @@ -539,6 +618,12 @@ LUA_API const char *lua_pushstring (lua_State *L, const char *s) { } +/** + * lua_pushvfstring [-0, +1, v] + * + * Equivalent to lua_pushfstring, except that it receives a va_list instead + * of a variable number of arguments. + */ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *ret; @@ -550,6 +635,25 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, } +/** + * lua_pushfstring [-0, +1, v] + * + * Pushes onto the stack a formatted string and returns a pointer to this + * string (see §4.1.3). It is similar to the ISO C function sprintf, but has + * two important differences. First, you do not have to allocate space for + * the result; the result is a Lua string and Lua takes care of memory + * allocation (and deallocation, through garbage collection). Second, the + * conversion specifiers are quite restricted. There are no flags, widths, or + * precisions. The conversion specifiers can only be '%%' (inserts the + * character '%'), '%s' (inserts a zero-terminated string, with no size + * restrictions), '%f' (inserts a lua_Number), '%I' (inserts a lua_Integer), + * '%p' (inserts a pointer), '%d' (inserts an int), '%c' (inserts an int as a + * one-byte character), and '%U' (inserts a long int as a UTF-8 byte + * sequence). + * + * This function may raise errors due to memory overflow or an invalid + * conversion specifier. + */ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; @@ -563,6 +667,32 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { } +/** + * lua_pushcclosure [-n, +1, m] + * + * Pushes a new C closure onto the stack. This function receives a pointer to + * a C function and pushes onto the stack a Lua value of type function that, + * when called, invokes the corresponding C function. The parameter n tells + * how many upvalues this function will have (see §4.2). + * + * Any function to be callable by Lua must follow the correct protocol to + * receive its parameters and return its results (see lua_CFunction). + * + * When a C function is created, it is possible to associate some values with + * it, the so called upvalues; these upvalues are then accessible to the + * function whenever it is called. This association is called a C closure + * (see §4.2). To create a C closure, first the initial values for its + * upvalues must be pushed onto the stack. (When there are multiple upvalues, + * the first value is pushed first.) Then lua_pushcclosure is called to + * create and push the C function onto the stack, with the argument n telling + * how many values will be associated with the function. lua_pushcclosure + * also pops these values from the stack. + * + * The maximum value for n is 255. + * + * When n is zero, this function creates a light C function, which is just a + * pointer to the C function. In that case, it never raises a memory error. + */ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { @@ -589,6 +719,11 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { } +/** + * lua_pushboolean [-0, +1, –] + * + * Pushes a boolean value with value b onto the stack. + */ LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); if (b) @@ -600,6 +735,16 @@ LUA_API void lua_pushboolean (lua_State *L, int b) { } +/** + * lua_pushlightuserdata [-0, +1, –] + * + * Pushes a light userdata onto the stack. + * + * Userdata represent C values in Lua. A light userdata represents a pointer, + * a void*. It is a value (like a number): you do not create it, it has no + * individual metatable, and it is not collected (as it was never created). A + * light userdata is equal to "any" light userdata with the same C address. + */ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); setpvalue(s2v(L->top), p); @@ -608,6 +753,12 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { } +/** + * lua_pushthread [-0, +1, –] + * + * Pushes the thread represented by L onto the stack. Returns 1 if this + * thread is the main thread of its state. + */ LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); setthvalue(L, s2v(L->top), L); @@ -1220,6 +1371,13 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { */ +/** + * lua_error [-1, +0, v] + * + * Raises a Lua error, using the value on the top of the stack as the error + * object. This function does a long jump, and therefore never returns (see + * luaL_error). + */ LUA_API int lua_error (lua_State *L) { TValue *errobj; lua_lock(L); @@ -1231,10 +1389,39 @@ LUA_API int lua_error (lua_State *L) { else luaG_errormsg(L); /* raise a regular error */ /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ + unreachable; } +/** + * lua_next [-1, +(2|0), v] + * + * Pops a key from the stack, and pushes a key–value pair from the table at + * the given index, the "next" pair after the given key. If there are no more + * elements in the table, then lua_next returns 0 and pushes nothing. + * + * A typical table traversal looks like this: + * + * // table is in the stack at index 't' + * lua_pushnil(L); // first key + * while (lua_next(L, t) != 0) { + * // uses 'key' (at index -2) and 'value' (at index -1) + * printf("%s - %s\n", + * lua_typename(L, lua_type(L, -2)), + * lua_typename(L, lua_type(L, -1))); + * // removes 'value'; keeps 'key' for next iteration + * lua_pop(L, 1); + * } + * + * While traversing a table, avoid calling lua_tolstring directly on a key, + * unless you know that the key is actually a string. Recall that + * lua_tolstring may change the value at the given index; this confuses the + * next call to lua_next. + * + * This function may raise an error if the given key is neither nil nor + * present in the table. See function next for the caveats of modifying the + * table during its traversal. + */ LUA_API int lua_next (lua_State *L, int idx) { Table *t; int more; @@ -1252,6 +1439,27 @@ LUA_API int lua_next (lua_State *L, int idx) { } +/** + * lua_toclose [-0, +0, m] + * + * Marks the given index in the stack as a to-be-closed slot (see §3.3.8). + * Like a to-be-closed variable in Lua, the value at that slot in the stack + * will be closed when it goes out of scope. Here, in the context of a C + * function, to go out of scope means that the running function returns to + * Lua, or there is an error, or the slot is removed from the stack through + * lua_settop or lua_pop, or there is a call to lua_closeslot. A slot marked + * as to-be-closed should not be removed from the stack by any other function + * in the API except lua_settop or lua_pop, unless previously deactivated by + * lua_closeslot. + * + * This function should not be called for an index that is equal to or below + * an active to-be-closed slot. + * + * Note that, both in case of errors and of a regular return, by the time the + * __close metamethod runs, the C stack was already unwound, so that any + * automatic C variable declared in the calling function (e.g., a buffer) + * will be out of scope. + */ LUA_API void lua_toclose (lua_State *L, int idx) { int nresults; StkId o; @@ -1266,7 +1474,15 @@ LUA_API void lua_toclose (lua_State *L, int idx) { lua_unlock(L); } - +/** + * lua_concat [-n, +1, e] + * + * Concatenates the n values at the top of the stack, pops them, and leaves + * the result on the top. If n is 1, the result is the single value on the + * stack (that is, the function does nothing); if n is 0, the result is the + * empty string. Concatenation is performed following the usual semantics of + * Lua (see §3.4.6). + */ LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); @@ -1281,6 +1497,13 @@ LUA_API void lua_concat (lua_State *L, int n) { } +/** + * lua_len [-0, +1, e] + * + * Returns the length of the value at the given index. It is equivalent to + * the '#' operator in Lua (see §3.4.7) and may trigger a metamethod for the + * "length" event (see §2.4). The result is pushed on the stack. + */ LUA_API void lua_len (lua_State *L, int idx) { TValue *t; lua_lock(L); @@ -1291,6 +1514,13 @@ LUA_API void lua_len (lua_State *L, int idx) { } +/** + * lua_getallocf [-0, +0, –] + * + * Returns the memory-allocation function of a given state. If ud is not + * NULL, Lua stores in *ud the opaque pointer given when the memory-allocator + * function was set. + */ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { lua_Alloc f; lua_lock(L); @@ -1301,6 +1531,13 @@ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { } +/** + * lua_setallocf [-0, +0, –] + * + * void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + * + * Changes the allocator function of a given state to f with user data ud. + */ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { lua_lock(L); G(L)->ud = ud; @@ -1309,6 +1546,13 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { } +/** + * lua_setwarnf [-0, +0, –] + * + * Sets the warning function to be used by Lua to emit warnings (see + * lua_WarnFunction). The ud parameter sets the value ud passed to the + * warning function. + */ void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) { lua_lock(L); G(L)->ud_warn = ud; @@ -1317,6 +1561,14 @@ void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) { } +/** + * lua_warning [-0, +0, –] + * + * Emits a warning with the given message. A message in a call with tocont + * true should be continued in another call to this function. + * + * See warn for more details about warnings. + */ void lua_warning (lua_State *L, const char *msg, int tocont) { lua_lock(L); luaE_warning(L, msg, tocont); @@ -1325,6 +1577,19 @@ void lua_warning (lua_State *L, const char *msg, int tocont) { +/** + * lua_newuserdatauv [-0, +1, m] + * + * This function creates and pushes on the stack a new full userdata, with + * nuvalue associated Lua values, called user values, plus an associated + * block of raw memory with size bytes. (The user values can be set and read + * with the functions lua_setiuservalue and lua_getiuservalue.) + * + * The function returns the address of the block of memory. Lua ensures that + * this address is valid as long as the corresponding userdata is alive (see + * §2.5). Moreover, if the userdata is marked for finalization (see §2.5.3), + * its address is valid at least until the call to its finalizer. + */ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { Udata *u; lua_lock(L); @@ -1338,7 +1603,6 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { } - static const char *aux_upvalue (TValue *fi, int n, TValue **val, GCObject **owner) { switch (ttypetag(fi)) { @@ -1366,6 +1630,16 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, } +/** + * lua_getupvalue [-0, +(0|1), –] + * + * Gets information about the n-th upvalue of the closure at index funcindex. + * It pushes the upvalue's value onto the stack and returns its name. Returns + * NULL (and pushes nothing) when the index n is greater than the number of + * upvalues. + * + * See debug.getupvalue for more information about upvalues. + */ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ @@ -1380,6 +1654,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { } +/** + * lua_setupvalue [-(0|1), +0, –] + * + * Sets the value of a closure's upvalue. It assigns the value on the top of + * the stack to the upvalue and returns its name. It also pops the value from + * the stack. + * + * Returns NULL (and pops nothing) when the index n is greater than the + * number of upvalues. + * + * Parameters funcindex and n are as in the function lua_getupvalue. + */ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ @@ -1413,6 +1699,20 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { } +/** + * lua_upvalueid [-0, +0, –] + * + * Returns a unique identifier for the upvalue numbered n from the closure at + * index funcindex. + * + * These unique identifiers allow a program to check whether different + * closures share upvalues. Lua closures that share an upvalue (that is, that + * access a same external local variable) will return identical ids for those + * upvalue indices. + * + * Parameters funcindex and n are as in the function lua_getupvalue, but n + * cannot be greater than the number of upvalues. + */ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { TValue *fi = index2value(L, fidx); switch (ttypetag(fi)) { @@ -1435,6 +1735,12 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { } +/** + * lua_upvaluejoin [-0, +0, –] + * + * Make the n1-th upvalue of the Lua closure at index funcindex1 refer to the + * n2-th upvalue of the Lua closure at index funcindex2. + */ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, int fidx2, int n2) { LClosure *f1; diff --git a/third_party/lua/lauxlib.c b/third_party/lua/lauxlib.c index 62d95ff83..0438c3ce5 100644 --- a/third_party/lua/lauxlib.c +++ b/third_party/lua/lauxlib.c @@ -15,6 +15,38 @@ /* clang-format off */ + +/** + * @fileoverview The Auxiliary Library + * + * The auxiliary library provides several convenient functions to interface C + * with Lua. While the basic API provides the primitive functions for all + * interactions between C and Lua, the auxiliary library provides + * higher-level functions for some common tasks. + * + * All functions and types from the auxiliary library are defined in header + * file lauxlib.h and have a prefix luaL_. + * + * All functions in the auxiliary library are built on top of the basic API, + * and so they provide nothing that cannot be done with that API. + * Nevertheless, the use of the auxiliary library ensures more consistency to + * your code. + * + * Several functions in the auxiliary library use internally some extra stack + * slots. When a function in the auxiliary library uses less than five slots, + * it does not check the stack size; it simply assumes that there are enough + * slots. + * + * Several functions in the auxiliary library are used to check C function + * arguments. Because the error message is formatted for arguments (e.g., + * "bad argument #1"), you should not use these functions for other stack + * values. + * + * Functions called luaL_check* always raise an error if the check is not + * satisfied. + */ + + #if !defined(MAX_SIZET) /* maximum value for size_t */ #define MAX_SIZET ((size_t)(~(size_t)0)) @@ -116,6 +148,13 @@ static int lastlevel (lua_State *L) { } +/** + * luaL_traceback [-0, +1, m] + * + * Creates and pushes a traceback of the stack L1. If msg is not NULL, it is + * appended at the beginning of the traceback. The level parameter tells at + * which level to start the traceback. + */ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level) { luaL_Buffer b; @@ -160,6 +199,17 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, ** ======================================================= */ +/** + * luaL_argerror [-0, +0, v] + * + * Raises an error reporting a problem with argument arg of the C function + * that called it, using a standard message that includes extramsg as a + * comment: + * + * bad argument #arg to 'funcname' (extramsg) + * + * This function never returns. + */ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { lua_Debug ar; if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ @@ -177,7 +227,13 @@ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { arg, ar.name, extramsg); } - +/** + * luaL_typeerror [-0, +0, v] + * + * Raises a type error for the argument arg of the C function that called it, + * using a standard message; tname is a "name" for the expected type. This + * function never returns. + */ LUALIB_API int luaL_typeerror (lua_State *L, int arg, const char *tname) { const char *msg; const char *typearg; /* name for the type of the actual argument */ @@ -196,12 +252,18 @@ static void tag_error (lua_State *L, int arg, int tag) { luaL_typeerror(L, arg, lua_typename(L, tag)); } - -/* -** The use of 'lua_pushfstring' ensures this function does not -** need reserved stack space when called. -*/ +/** + * luaL_where [-0, +1, m] + * + * Pushes onto the stack a string identifying the current position of the + * control at level lvl in the call stack. Typically this string has the + * following format: + */ LUALIB_API void luaL_where (lua_State *L, int level) { + /* + ** The use of 'lua_pushfstring' ensures this function does not + ** need reserved stack space when called. + */ lua_Debug ar; if (lua_getstack(L, level, &ar)) { /* check function at level */ lua_getinfo(L, "Sl", &ar); /* get info about it */ @@ -213,13 +275,23 @@ LUALIB_API void luaL_where (lua_State *L, int level) { lua_pushfstring(L, ""); /* else, no information available... */ } - -/* -** Again, the use of 'lua_pushvfstring' ensures this function does -** not need reserved stack space when called. (At worst, it generates -** an error with "stack overflow" instead of the given message.) -*/ +/** + * luaL_error [-0, +0, v] + * + * Raises an error. The error message format is given by fmt plus any extra + * arguments, following the same rules of lua_pushfstring. It also adds at + * the beginning of the message the file name and the line number where the + * error occurred, if this information is available. + * + * This function never returns, but it is an idiom to use it in C functions + * as return luaL_error(args). + */ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + /* + ** Again, the use of 'lua_pushvfstring' ensures this function does + ** not need reserved stack space when called. (At worst, it generates + ** an error with "stack overflow" instead of the given message.) + */ va_list argp; va_start(argp, fmt); luaL_where(L, 1); @@ -229,7 +301,12 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { return lua_error(L); } - +/** + * luaL_fileresult [-0, +(1|3), m] + * + * This function produces the return values for file-related functions in the + * standard library (io.open, os.rename, file:seek, etc.). + */ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { int en = errno; /* calls to Lua API may change this value */ if (stat) { @@ -268,6 +345,12 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { #endif /* } */ +/** + * luaL_execresult [-0, +3, m] + * + * This function produces the return values for process-related functions in + * the standard library (os.execute and io.close). + */ LUALIB_API int luaL_execresult (lua_State *L, int stat) { if (stat != 0 && errno != 0) /* error with an 'errno'? */ return luaL_fileresult(L, 0, NULL); @@ -294,6 +377,17 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) { ** ======================================================= */ +/** + * luaL_newmetatable [-0, +1, m] + * + * If the registry already has the key tname, returns 0. Otherwise, creates a + * new table to be used as a metatable for userdata, adds to this new table + * the pair __name = tname, adds to the registry the pair [tname] = new + * table, and returns 1. + * + * In both cases, the function pushes onto the stack the final value + * associated with tname in the registry. + */ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ @@ -306,13 +400,23 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { return 1; } - +/** + * luaL_setmetatable [-0, +0, –] + * + * Sets the metatable of the object on the top of the stack as the metatable + * associated with name tname in the registry (see luaL_newmetatable). + */ LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { luaL_getmetatable(L, tname); lua_setmetatable(L, -2); } - +/** + * luaL_testudata [-0, +0, m] + * + * This function works like luaL_checkudata, except that, when the test + * fails, it returns NULL instead of raising an error. + */ LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { /* value is a userdata? */ @@ -327,7 +431,13 @@ LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { return NULL; /* value is not a userdata with a metatable */ } - +/** + * luaL_checkudata [-0, +0, v] + * + * Checks whether the function argument arg is a userdata of the type tname + * (see luaL_newmetatable) and returns the userdata's memory-block address + * (see lua_touserdata). + */ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { void *p = luaL_testudata(L, ud, tname); luaL_argexpected(L, p != NULL, ud, tname); @@ -343,6 +453,21 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { ** ======================================================= */ +/** + * luaL_checkoption [-0, +0, v] + * + * Checks whether the function argument arg is a string and searches for this + * string in the array lst (which must be NULL-terminated). Returns the index + * in the array where the string was found. Raises an error if the argument + * is not a string or if the string cannot be found. + * + * If def is not NULL, the function uses def as a default value when there is + * no argument arg or when this argument is nil. + * + * This is a useful function for mapping strings to C enums. (The usual + * convention in Lua libraries is to use strings instead of numbers to select + * options.) + */ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, const char *const lst[]) { const char *name = (def) ? luaL_optstring(L, arg, def) : @@ -373,18 +498,39 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { } +/** + * luaL_checktype [-0, +0, v] + * + * Checks whether the function argument arg has type t. See lua_type for the + * encoding of types for t. + */ LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { if (l_unlikely(lua_type(L, arg) != t)) tag_error(L, arg, t); } +/** + * luaL_checkany [-0, +0, v] + * + * Checks whether the function has an argument of any type (including nil) at + * position arg. + */ LUALIB_API void luaL_checkany (lua_State *L, int arg) { if (l_unlikely(lua_type(L, arg) == LUA_TNONE)) luaL_argerror(L, arg, "value expected"); } +/** + * luaL_checklstring [-0, +0, v] + * + * Checks whether the function argument arg is a string and returns this + * string; if l is not NULL fills its referent with the string's length. + * + * This function uses lua_tolstring to get its result, so all conversions and + * caveats of that function apply here. + */ LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { const char *s = lua_tolstring(L, arg, len); if (l_unlikely(!s)) tag_error(L, arg, LUA_TSTRING); @@ -392,6 +538,19 @@ LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { } +/** + * luaL_optlstring [-0, +0, v] + * + * If the function argument arg is a string, returns this string. If this + * argument is absent or is nil, returns d. Otherwise, raises an error. + * + * If l is not NULL, fills its referent with the result's length. If the + * result is NULL (only possible when returning d and d == NULL), its length + * is considered zero. + * + * This function uses lua_tolstring to get its result, so all conversions and + * caveats of that function apply here. + */ LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, const char *def, size_t *len) { if (lua_isnoneornil(L, arg)) { @@ -403,6 +562,12 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, } +/** + * luaL_checknumber [-0, +0, v] + * + * Checks whether the function argument arg is a number and returns this + * number converted to a lua_Number. + */ LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { int isnum; lua_Number d = lua_tonumberx(L, arg, &isnum); @@ -412,6 +577,13 @@ LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { } +/** + * luaL_optnumber [-0, +0, v] + * + * If the function argument arg is a number, returns this number as a + * lua_Number. If this argument is absent or is nil, returns d. Otherwise, + * raises an error. + */ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { return luaL_opt(L, luaL_checknumber, arg, def); } @@ -425,6 +597,12 @@ static void interror (lua_State *L, int arg) { } +/** + * luaL_checkinteger [-0, +0, v] + * + * Checks whether the function argument arg is an integer (or can be + * converted to an integer) and returns this integer. + */ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { int isnum; lua_Integer d = lua_tointegerx(L, arg, &isnum); @@ -435,6 +613,13 @@ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { } +/** + * luaL_optinteger [-0, +0, v] + * + * If the function argument arg is an integer (or it is convertible to an + * integer), returns this integer. If this argument is absent or is nil, + * returns d. Otherwise, raises an error. + */ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, lua_Integer def) { return luaL_opt(L, luaL_checkinteger, arg, def); @@ -562,6 +747,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { } +/** + * luaL_addlstring [-?, +?, m] + * + * Adds the string pointed to by s with length l to the buffer B (see + * luaL_Buffer). The string can contain embedded zeros. + */ LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ char *b = prepbuffsize(B, l, -1); @@ -571,11 +762,23 @@ LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { } +/** + * luaL_addstring [-?, +?, m] + * + * Adds the zero-terminated string pointed to by s to the buffer B (see + * luaL_Buffer). + */ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { luaL_addlstring(B, s, strlen(s)); } +/** + * luaL_pushresult [-?, +1, m] + * + * Finishes the use of buffer B leaving the final string on the top of the + * stack. + */ LUALIB_API void luaL_pushresult (luaL_Buffer *B) { lua_State *L = B->L; checkbufferlevel(B, -1); @@ -586,6 +789,11 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B) { } +/** + * luaL_pushresultsize [-?, +1, m] + * + * Equivalent to the sequence luaL_addsize, luaL_pushresult. + */ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { luaL_addsize(B, sz); luaL_pushresult(B); @@ -612,6 +820,12 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) { } +/** + * luaL_buffinit [-0, +0, –] + * + * Initializes a buffer B (see luaL_Buffer). This function does not allocate + * any space; the buffer must be declared as a variable. + */ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { B->L = L; B->b = B->init.b; @@ -621,6 +835,11 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { } +/** + * luaL_buffinitsize [-?, +?, m] + * + * Equivalent to the sequence luaL_buffinit, luaL_prepbuffsize. + */ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { luaL_buffinit(L, B); return prepbuffsize(B, sz, -1); @@ -671,6 +890,15 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { } +/** + * luaL_unref [-0, +0, –] + * + * Releases the reference ref from the table at index t (see luaL_ref). The + * entry is removed from the table, so that the referred object can be + * collected. The reference ref is also freed to be used again. + * + * If ref is LUA_NOREF or LUA_REFNIL, luaL_unref does nothing. + */ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { if (ref >= 0) { t = lua_absindex(L, t); @@ -759,6 +987,21 @@ static int skipcomment (LoadF *lf, int *cp) { } +/** + * luaL_loadfilex [-0, +1, m] + * + * Loads a file as a Lua chunk. This function uses lua_load to load the chunk + * in the file named filename. If filename is NULL, then it loads from the + * standard input. The first line in the file is ignored if it starts with a + * #. + * + * The string mode works as in the function lua_load. + * + * This function returns the same results as lua_load or LUA_ERRFILE for + * file-related errors. + * + * As lua_load, this function only loads the chunk; it does not run it. + */ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { LoadF lf; @@ -811,6 +1054,16 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { } +/** + * luaL_loadbufferx [-0, +1, –] + * + * Loads a buffer as a Lua chunk. This function uses lua_load to load the + * chunk in the buffer pointed to by buff with size sz. + * + * This function returns the same results as lua_load. name is the chunk + * name, used for debug information and error messages. The string mode works + * as in the function lua_load. + */ LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, const char *name, const char *mode) { LoadS ls; @@ -820,6 +1073,16 @@ LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, } +/** + * luaL_loadstring [-0, +1, –] + * + * Loads a string as a Lua chunk. This function uses lua_load to load the + * chunk in the zero-terminated string s. + * + * This function returns the same results as lua_load. + * + * Also as lua_load, this function only loads the chunk; it does not run it. + */ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { return luaL_loadbuffer(L, s, strlen(s), s); } @@ -828,6 +1091,14 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { +/** + * luaL_getmetafield [-0, +(0|1), m] + * + * Pushes onto the stack the field e from the metatable of the object at + * index obj and returns the type of the pushed value. If the object does not + * have a metatable, or if the metatable does not have this field, pushes + * nothing and returns LUA_TNIL. + */ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { if (!lua_getmetatable(L, obj)) /* no metatable? */ return LUA_TNIL; @@ -844,6 +1115,17 @@ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { } +/** + * luaL_callmeta [-0, +(0|1), e] + * + * Calls a metamethod. + * + * If the object at index obj has a metatable and this metatable has a field + * e, this function calls this field passing the object as its only argument. + * In this case this function returns true and pushes onto the stack the + * value returned by the call. If there is no metatable or no metamethod, + * this function returns false without pushing any value on the stack. + */ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { obj = lua_absindex(L, obj); if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ @@ -854,6 +1136,14 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { } +/** + * luaL_len [-0, +0, e] + * + * Returns the "length" of the value at the given index as a number; it is + * equivalent to the '#' operator in Lua (see §3.4.7). Raises an error if the + * result of the operation is not an integer. (This case can only happen + * through metamethods.) + */ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { lua_Integer l; int isnum; @@ -866,6 +1156,18 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { } +/** + * luaL_tolstring [-0, +1, e] + * + * Converts any Lua value at the given index to a C string in a reasonable + * format. The resulting string is pushed onto the stack and also returned by + * the function (see §4.1.3). If len is not NULL, the function also sets *len + * with the string length. + * + * If the value has a metatable with a __tostring field, then luaL_tolstring + * calls the corresponding metamethod with the value as argument, and uses + * the result of the call as its result. + */ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ if (!lua_isstring(L, -1)) @@ -970,6 +1272,12 @@ LUALIB_API void luaL_requiref (lua_State *L, const char *modname, } +/** + * luaL_addgsub [-0, +0, m] + * + * Adds a copy of the string s to the buffer B (see luaL_Buffer), replacing + * any occurrence of the string p with the string r. + */ LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, const char *p, const char *r) { const char *wild; @@ -983,6 +1291,12 @@ LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, } +/** + * luaL_gsub [-0, +1, m] + * + * Creates a copy of string s, replacing any occurrence of the string p with + * the string r. Pushes the resulting string on the stack and returns it. + */ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, const char *r) { luaL_Buffer b; @@ -1070,6 +1384,16 @@ static void warnfon (void *ud, const char *message, int tocont) { } +/** + * luaL_newstate [-0, +0, –] + * + * Creates a new Lua state. It calls lua_newstate with an allocator based on + * the standard C allocation functions and then sets a warning function and a + * panic function (see §4.4) that print messages to the standard error + * output. + * + * Returns the new state, or NULL if there is a memory allocation error. + */ LUALIB_API lua_State *luaL_newstate (void) { lua_State *L = lua_newstate(l_alloc, NULL); if (l_likely(L)) { diff --git a/third_party/lua/lstate.c b/third_party/lua/lstate.c index fd0f7152b..db3871d69 100644 --- a/third_party/lua/lstate.c +++ b/third_party/lua/lstate.c @@ -275,6 +275,16 @@ static void close_state (lua_State *L) { } +/** + * lua_newthread [-0, +1, m] + * + * Creates a new thread, pushes it on the stack, and returns a pointer to a + * lua_State that represents this new thread. The new thread returned by this + * function shares with the original thread its global environment, but has + * an independent execution stack. + * + * Threads are subject to garbage collection, like any Lua object. + */ LUA_API lua_State *lua_newthread (lua_State *L) { global_State *g; lua_State *L1; diff --git a/third_party/python/Objects/unicodetype_db.inc b/third_party/python/Objects/unicodetype_db.inc index 2948c4dfa..593146edd 100644 --- a/third_party/python/Objects/unicodetype_db.inc +++ b/third_party/python/Objects/unicodetype_db.inc @@ -502,7 +502,7 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = { /* extended case mappings */ -const Py_UCS4 _PyUnicode_ExtendedCase[] = { +const uint16_t _PyUnicode_ExtendedCase[] = { 181, 956, 924,