Date: Fri, 15 Jan 2021 14:06:00 +0100 From: Mateusz Guzik <mjguzik@gmail.com> To: Kyle Evans <kevans@freebsd.org> Cc: src-committers@freebsd.org, dev-commits-src-all@freebsd.org, dev-commits-src-main@freebsd.org Subject: Re: git: 0495ed398c4f - main - contrib/lua: update to 5.4.2 Message-ID: <CAGudoHGv3aP-QgR23NPvnJHcwMMc=qAs7HSMnxQMaZu-RywKSg@mail.gmail.com> In-Reply-To: <202101140558.10E5wMNW079125@gitrepo.freebsd.org> References: <202101140558.10E5wMNW079125@gitrepo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
There is some garbage shown by the boot loader since this commit. Screenshot from VirtualBox: https://people.freebsd.org/~mjg/loader_artifact.png An additional fixup is needed to see it: commit 0974bfa3a8da2201b0a415e72593552f5ac59379 (HEAD -> main, freebsd/main, freebsd/HEAD) Author: Toomas Soome <tsoome@FreeBSD.org> Date: Fri Jan 15 14:58:12 2021 +0200 loader: do not update palette in text mode (real fix) otherwise the screen is blank. On 1/14/21, Kyle Evans <kevans@freebsd.org> wrote: > The branch main has been updated by kevans: > > URL: > https://cgit.FreeBSD.org/src/commit/?id=0495ed398c4f64013bab2327eb13a303e1f90c13 > > commit 0495ed398c4f64013bab2327eb13a303e1f90c13 > Merge: 7ae27c2d6c4f 0ea45b9cd43c > Author: Kyle Evans <kevans@FreeBSD.org> > AuthorDate: 2021-01-14 05:56:18 +0000 > Commit: Kyle Evans <kevans@FreeBSD.org> > CommitDate: 2021-01-14 05:56:18 +0000 > > contrib/lua: update to 5.4.2 > > Merge commit '0ea45b9cd43ce1247eb3eee9bfd5cee3d19068e7' into main > > contrib/lua/Makefile | 30 +- > contrib/lua/README | 2 +- > contrib/lua/doc/contents.html | 81 +- > contrib/lua/doc/lua.1 | 93 +- > contrib/lua/doc/manual.html | 3260 > ++++++++++++++++++++++++++-------------- > contrib/lua/doc/readme.html | 115 +- > contrib/lua/src/Makefile | 83 +- > contrib/lua/src/lapi.c | 706 +++++---- > contrib/lua/src/lapi.h | 27 +- > contrib/lua/src/lauxlib.c | 385 ++--- > contrib/lua/src/lauxlib.h | 54 +- > contrib/lua/src/lbaselib.c | 139 +- > contrib/lua/src/lbitlib.c | 233 --- > contrib/lua/src/lcode.c | 1141 ++++++++++---- > contrib/lua/src/lcode.h | 34 +- > contrib/lua/src/lcorolib.c | 89 +- > contrib/lua/src/lctype.c | 43 +- > contrib/lua/src/lctype.h | 18 +- > contrib/lua/src/ldblib.c | 94 +- > contrib/lua/src/ldebug.c | 462 ++++-- > contrib/lua/src/ldebug.h | 21 +- > contrib/lua/src/ldo.c | 559 +++---- > contrib/lua/src/ldo.h | 38 +- > contrib/lua/src/ldump.c | 197 +-- > contrib/lua/src/lfunc.c | 223 ++- > contrib/lua/src/lfunc.h | 50 +- > contrib/lua/src/lgc.c | 1387 +++++++++++------ > contrib/lua/src/lgc.h | 128 +- > contrib/lua/src/linit.c | 7 +- > contrib/lua/src/liolib.c | 121 +- > contrib/lua/src/ljumptab.h | 112 ++ > contrib/lua/src/llex.c | 74 +- > contrib/lua/src/llex.h | 12 +- > contrib/lua/src/llimits.h | 134 +- > contrib/lua/src/lmathlib.c | 433 +++++- > contrib/lua/src/lmem.c | 178 ++- > contrib/lua/src/lmem.h | 72 +- > contrib/lua/src/loadlib.c | 261 ++-- > contrib/lua/src/lobject.c | 340 +++-- > contrib/lua/src/lobject.h | 737 ++++++--- > contrib/lua/src/lopcodes.c | 190 ++- > contrib/lua/src/lopcodes.h | 401 +++-- > contrib/lua/src/lopnames.h | 103 ++ > contrib/lua/src/loslib.c | 85 +- > contrib/lua/src/lparser.c | 967 ++++++++---- > contrib/lua/src/lparser.h | 80 +- > contrib/lua/src/lprefix.h | 4 +- > contrib/lua/src/lstate.c | 221 ++- > contrib/lua/src/lstate.h | 202 ++- > contrib/lua/src/lstring.c | 135 +- > contrib/lua/src/lstring.h | 22 +- > contrib/lua/src/lstrlib.c | 504 +++++-- > contrib/lua/src/ltable.c | 692 ++++++--- > contrib/lua/src/ltable.h | 22 +- > contrib/lua/src/ltablib.c | 52 +- > contrib/lua/src/ltm.c | 173 ++- > contrib/lua/src/ltm.h | 37 +- > contrib/lua/src/lua.c | 439 +++--- > contrib/lua/src/lua.h | 60 +- > contrib/lua/src/luac.c | 470 ++++-- > contrib/lua/src/luaconf.h.dist | 253 ++-- > contrib/lua/src/lualib.h | 5 +- > contrib/lua/src/lundump.c | 266 ++-- > contrib/lua/src/lundump.h | 8 +- > contrib/lua/src/lutf8lib.c | 117 +- > contrib/lua/src/lvm.c | 1762 ++++++++++++++-------- > contrib/lua/src/lvm.h | 91 +- > contrib/lua/src/lzio.c | 2 +- > contrib/lua/src/lzio.h | 2 +- > lib/liblua/Makefile | 2 +- > lib/liblua/luaconf.h | 248 ++- > stand/liblua/luaconf.h | 244 ++- > 72 files changed, 12945 insertions(+), 7087 deletions(-) > > diff --cc contrib/lua/Makefile > index a2820e04fe24,000000000000..36447a0f61c7 > mode 100644,000000..100644 > --- a/contrib/lua/Makefile > +++ b/contrib/lua/Makefile > @@@ -1,114 -1,0 +1,106 @@@ > +# Makefile for installing Lua > +# See doc/readme.html for installation and customization instructions. > + > +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT > ======================= > + > +# Your platform. See PLATS for possible values. > - PLAT= none > ++PLAT= guess > + > +# Where to install. The installation starts in the src and doc > directories, > +# so take care if INSTALL_TOP is not an absolute path. See the local > target. > +# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with > +# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. > +INSTALL_TOP= /usr/local > +INSTALL_BIN= $(INSTALL_TOP)/bin > +INSTALL_INC= $(INSTALL_TOP)/include > +INSTALL_LIB= $(INSTALL_TOP)/lib > +INSTALL_MAN= $(INSTALL_TOP)/man/man1 > +INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V > +INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V > + > +# How to install. If your install program does not support "-p", then > +# you may have to run ranlib on the installed liblua.a. > +INSTALL= install -p > +INSTALL_EXEC= $(INSTALL) -m 0755 > +INSTALL_DATA= $(INSTALL) -m 0644 > +# > +# If you don't have "install" you can use "cp" instead. > +# INSTALL= cp -p > +# INSTALL_EXEC= $(INSTALL) > +# INSTALL_DATA= $(INSTALL) > + > +# Other utilities. > +MKDIR= mkdir -p > +RM= rm -f > + > +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE > ======= > + > +# Convenience platforms targets. > - PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris > ++PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw > posix solaris > + > +# What to install. > +TO_BIN= lua luac > +TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp > +TO_LIB= liblua.a > +TO_MAN= lua.1 luac.1 > + > +# Lua version and release. > - V= 5.3 > - R= $V.6 > ++V= 5.4 > ++R= $V.2 > + > +# Targets start here. > +all: $(PLAT) > + > - $(PLATS) clean: > - cd src && $(MAKE) $@ > - > - test: dummy > - src/lua -v > ++$(PLATS) help test clean: > ++ @cd src && $(MAKE) $@ > + > +install: dummy > + cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) > $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) > + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) > + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) > + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) > + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) > + > +uninstall: > + cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) > + cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) > + cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) > + cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) > + > +local: > + $(MAKE) install INSTALL_TOP=../install > + > - none: > - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" > - @echo " $(PLATS)" > - @echo "See doc/readme.html for complete instructions." > - > - # make may get confused with test/ and install/ > ++# make may get confused with install/ if it does not support .PHONY. > +dummy: > + > - # echo config parameters > ++# Echo config parameters. > +echo: > + @cd src && $(MAKE) -s echo > + @echo "PLAT= $(PLAT)" > + @echo "V= $V" > + @echo "R= $R" > + @echo "TO_BIN= $(TO_BIN)" > + @echo "TO_INC= $(TO_INC)" > + @echo "TO_LIB= $(TO_LIB)" > + @echo "TO_MAN= $(TO_MAN)" > + @echo "INSTALL_TOP= $(INSTALL_TOP)" > + @echo "INSTALL_BIN= $(INSTALL_BIN)" > + @echo "INSTALL_INC= $(INSTALL_INC)" > + @echo "INSTALL_LIB= $(INSTALL_LIB)" > + @echo "INSTALL_MAN= $(INSTALL_MAN)" > + @echo "INSTALL_LMOD= $(INSTALL_LMOD)" > + @echo "INSTALL_CMOD= $(INSTALL_CMOD)" > + @echo "INSTALL_EXEC= $(INSTALL_EXEC)" > + @echo "INSTALL_DATA= $(INSTALL_DATA)" > + > - # echo pkg-config data > ++# Echo pkg-config data. > +pc: > + @echo "version=$R" > + @echo "prefix=$(INSTALL_TOP)" > + @echo "libdir=$(INSTALL_LIB)" > + @echo "includedir=$(INSTALL_INC)" > + > - # list targets that do not create files (but not all makes understand > .PHONY) > - .PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho > ++# Targets that do not create files (not all makes understand .PHONY). > ++.PHONY: all $(PLATS) help test clean install uninstall local dummy echo > pc > + > +# (end of Makefile) > diff --cc contrib/lua/README > index f8bdb6f41d00,000000000000..bc8a9d737d26 > mode 100644,000000..100644 > --- a/contrib/lua/README > +++ b/contrib/lua/README > @@@ -1,6 -1,0 +1,6 @@@ > + > - This is Lua 5.3.6, released on 14 Sep 2020. > ++This is Lua 5.4.2, released on 13 Nov 2020. > + > +For installation instructions, license details, and > +further information about Lua, see doc/readme.html. > + > diff --cc contrib/lua/src/ljumptab.h > index 000000000000,8306f250ccb6..8306f250ccb6 > mode 000000,100644..100644 > --- a/contrib/lua/src/ljumptab.h > +++ b/contrib/lua/src/ljumptab.h > diff --cc contrib/lua/src/lopnames.h > index 000000000000,965cec9bf2fa..965cec9bf2fa > mode 000000,100644..100644 > --- a/contrib/lua/src/lopnames.h > +++ b/contrib/lua/src/lopnames.h > diff --cc contrib/lua/src/lstrlib.c > index 28064960818f,000000000000..ed88abdb4db2 > mode 100644,000000..100644 > --- a/contrib/lua/src/lstrlib.c > +++ b/contrib/lua/src/lstrlib.c > @@@ -1,1605 -1,0 +1,1825 @@@ > +/* > - ** $Id: lstrlib.c,v 1.254.1.1 2017/04/19 17:29:57 roberto Exp $ > ++** $Id: lstrlib.c $ > +** Standard library for string operations and pattern-matching > +** See Copyright Notice in lua.h > +*/ > + > +#define lstrlib_c > +#define LUA_LIB > + > +#include "lprefix.h" > + > + > +#include <ctype.h> > +#include <float.h> > +#include <limits.h> > +#include <locale.h> > ++#include <math.h> > +#include <stddef.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include "lua.h" > + > +#include "lauxlib.h" > +#include "lualib.h" > + > + > +/* > +** maximum number of captures that a pattern can do during > +** pattern-matching. This limit is arbitrary, but must fit in > +** an unsigned char. > +*/ > +#if !defined(LUA_MAXCAPTURES) > +#define LUA_MAXCAPTURES 32 > +#endif > + > + > +/* macro to 'unsign' a character */ > +#define uchar(c) ((unsigned char)(c)) > + > + > +/* > +** Some sizes are better limited to fit in 'int', but must also fit in > +** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) > +*/ > +#define MAX_SIZET ((size_t)(~(size_t)0)) > + > +#define MAXSIZE \ > + (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) > + > + > + > + > +static int str_len (lua_State *L) { > + size_t l; > + luaL_checklstring(L, 1, &l); > + lua_pushinteger(L, (lua_Integer)l); > + return 1; > +} > + > + > - /* translate a relative string position: negative means back from end */ > - static lua_Integer posrelat (lua_Integer pos, size_t len) { > - if (pos >= 0) return pos; > - else if (0u - (size_t)pos > len) return 0; > - else return (lua_Integer)len + pos + 1; > ++/* > ++** translate a relative initial string position > ++** (negative means back from end): clip result to [1, inf). > ++** The length of any string in Lua must fit in a lua_Integer, > ++** so there are no overflows in the casts. > ++** The inverted comparison avoids a possible overflow > ++** computing '-pos'. > ++*/ > ++static size_t posrelatI (lua_Integer pos, size_t len) { > ++ if (pos > 0) > ++ return (size_t)pos; > ++ else if (pos == 0) > ++ return 1; > ++ else if (pos < -(lua_Integer)len) /* inverted comparison */ > ++ return 1; /* clip to 1 */ > ++ else return len + (size_t)pos + 1; > ++} > ++ > ++ > ++/* > ++** Gets an optional ending string position from argument 'arg', > ++** with default value 'def'. > ++** Negative means back from end: clip result to [0, len] > ++*/ > ++static size_t getendpos (lua_State *L, int arg, lua_Integer def, > ++ size_t len) { > ++ lua_Integer pos = luaL_optinteger(L, arg, def); > ++ if (pos > (lua_Integer)len) > ++ return len; > ++ else if (pos >= 0) > ++ return (size_t)pos; > ++ else if (pos < -(lua_Integer)len) > ++ return 0; > ++ else return len + (size_t)pos + 1; > +} > + > + > +static int str_sub (lua_State *L) { > + size_t l; > + const char *s = luaL_checklstring(L, 1, &l); > - lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); > - lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); > - if (start < 1) start = 1; > - if (end > (lua_Integer)l) end = l; > ++ size_t start = posrelatI(luaL_checkinteger(L, 2), l); > ++ size_t end = getendpos(L, 3, -1, l); > + if (start <= end) > - lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); > ++ lua_pushlstring(L, s + start - 1, (end - start) + 1); > + else lua_pushliteral(L, ""); > + return 1; > +} > + > + > +static int str_reverse (lua_State *L) { > + size_t l, i; > + luaL_Buffer b; > + const char *s = luaL_checklstring(L, 1, &l); > + char *p = luaL_buffinitsize(L, &b, l); > + for (i = 0; i < l; i++) > + p[i] = s[l - i - 1]; > + luaL_pushresultsize(&b, l); > + return 1; > +} > + > + > +static int str_lower (lua_State *L) { > + size_t l; > + size_t i; > + luaL_Buffer b; > + const char *s = luaL_checklstring(L, 1, &l); > + char *p = luaL_buffinitsize(L, &b, l); > + for (i=0; i<l; i++) > + p[i] = tolower(uchar(s[i])); > + luaL_pushresultsize(&b, l); > + return 1; > +} > + > + > +static int str_upper (lua_State *L) { > + size_t l; > + size_t i; > + luaL_Buffer b; > + const char *s = luaL_checklstring(L, 1, &l); > + char *p = luaL_buffinitsize(L, &b, l); > + for (i=0; i<l; i++) > + p[i] = toupper(uchar(s[i])); > + luaL_pushresultsize(&b, l); > + return 1; > +} > + > + > +static int str_rep (lua_State *L) { > + size_t l, lsep; > + const char *s = luaL_checklstring(L, 1, &l); > + lua_Integer n = luaL_checkinteger(L, 2); > + const char *sep = luaL_optlstring(L, 3, "", &lsep); > + if (n <= 0) lua_pushliteral(L, ""); > + else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ > + return luaL_error(L, "resulting string too large"); > + else { > + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; > + luaL_Buffer b; > + char *p = luaL_buffinitsize(L, &b, totallen); > + while (n-- > 1) { /* first n-1 copies (followed by separator) */ > + memcpy(p, s, l * sizeof(char)); p += l; > + if (lsep > 0) { /* empty 'memcpy' is not that cheap */ > + memcpy(p, sep, lsep * sizeof(char)); > + p += lsep; > + } > + } > + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by > separator) */ > + luaL_pushresultsize(&b, totallen); > + } > + return 1; > +} > + > + > +static int str_byte (lua_State *L) { > + size_t l; > + const char *s = luaL_checklstring(L, 1, &l); > - lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); > - lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); > ++ lua_Integer pi = luaL_optinteger(L, 2, 1); > ++ size_t posi = posrelatI(pi, l); > ++ size_t pose = getendpos(L, 3, pi, l); > + int n, i; > - if (posi < 1) posi = 1; > - if (pose > (lua_Integer)l) pose = l; > + if (posi > pose) return 0; /* empty interval; return no values */ > - if (pose - posi >= INT_MAX) /* arithmetic overflow? */ > ++ if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */ > + return luaL_error(L, "string slice too long"); > + n = (int)(pose - posi) + 1; > + luaL_checkstack(L, n, "string slice too long"); > + for (i=0; i<n; i++) > + lua_pushinteger(L, uchar(s[posi+i-1])); > + return n; > +} > + > + > +static int str_char (lua_State *L) { > + int n = lua_gettop(L); /* number of arguments */ > + int i; > + luaL_Buffer b; > + char *p = luaL_buffinitsize(L, &b, n); > + for (i=1; i<=n; i++) { > - lua_Integer c = luaL_checkinteger(L, i); > - luaL_argcheck(L, uchar(c) == c, i, "value out of range"); > ++ lua_Unsigned c = (lua_Unsigned)luaL_checkinteger(L, i); > ++ luaL_argcheck(L, c <= (lua_Unsigned)UCHAR_MAX, i, "value out of > range"); > + p[i - 1] = uchar(c); > + } > + luaL_pushresultsize(&b, n); > + return 1; > +} > + > + > - static int writer (lua_State *L, const void *b, size_t size, void *B) { > - (void)L; > - luaL_addlstring((luaL_Buffer *) B, (const char *)b, size); > ++/* > ++** Buffer to store the result of 'string.dump'. It must be initialized > ++** after the call to 'lua_dump', to ensure that the function is on the > ++** top of the stack when 'lua_dump' is called. ('luaL_buffinit' might > ++** push stuff.) > ++*/ > ++struct str_Writer { > ++ int init; /* true iff buffer has been initialized */ > ++ luaL_Buffer B; > ++}; > ++ > ++ > ++static int writer (lua_State *L, const void *b, size_t size, void *ud) { > ++ struct str_Writer *state = (struct str_Writer *)ud; > ++ if (!state->init) { > ++ state->init = 1; > ++ luaL_buffinit(L, &state->B); > ++ } > ++ luaL_addlstring(&state->B, (const char *)b, size); > + return 0; > +} > + > + > +static int str_dump (lua_State *L) { > - luaL_Buffer b; > ++ struct str_Writer state; > + int strip = lua_toboolean(L, 2); > + luaL_checktype(L, 1, LUA_TFUNCTION); > - lua_settop(L, 1); > - luaL_buffinit(L,&b); > - if (lua_dump(L, writer, &b, strip) != 0) > ++ lua_settop(L, 1); /* ensure function is on the top of the stack */ > ++ state.init = 0; > ++ if (lua_dump(L, writer, &state, strip) != 0) > + return luaL_error(L, "unable to dump given function"); > - luaL_pushresult(&b); > ++ luaL_pushresult(&state.B); > + return 1; > +} > + > + > + > ++/* > ++** {====================================================== > ++** METAMETHODS > ++** ======================================================= > ++*/ > ++ > ++#if defined(LUA_NOCVTS2N) /* { */ > ++ > ++/* no coercion from strings to numbers */ > ++ > ++static const luaL_Reg stringmetamethods[] = { > ++ {"__index", NULL}, /* placeholder */ > ++ {NULL, NULL} > ++}; > ++ > ++#else /* }{ */ > ++ > ++static int tonum (lua_State *L, int arg) { > ++ if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */ > ++ lua_pushvalue(L, arg); > ++ return 1; > ++ } > ++ else { /* check whether it is a numerical string */ > ++ size_t len; > ++ const char *s = lua_tolstring(L, arg, &len); > ++ return (s != NULL && lua_stringtonumber(L, s) == len + 1); > ++ } > ++} > ++ > ++ > ++static void trymt (lua_State *L, const char *mtname) { > ++ lua_settop(L, 2); /* back to the original arguments */ > ++ if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname)) > ++ luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, > ++ luaL_typename(L, -2), luaL_typename(L, -1)); > ++ lua_insert(L, -3); /* put metamethod before arguments */ > ++ lua_call(L, 2, 1); /* call metamethod */ > ++} > ++ > ++ > ++static int arith (lua_State *L, int op, const char *mtname) { > ++ if (tonum(L, 1) && tonum(L, 2)) > ++ lua_arith(L, op); /* result will be on the top */ > ++ else > ++ trymt(L, mtname); > ++ return 1; > ++} > ++ > ++ > ++static int arith_add (lua_State *L) { > ++ return arith(L, LUA_OPADD, "__add"); > ++} > ++ > ++static int arith_sub (lua_State *L) { > ++ return arith(L, LUA_OPSUB, "__sub"); > ++} > ++ > ++static int arith_mul (lua_State *L) { > ++ return arith(L, LUA_OPMUL, "__mul"); > ++} > ++ > ++static int arith_mod (lua_State *L) { > ++ return arith(L, LUA_OPMOD, "__mod"); > ++} > ++ > ++static int arith_pow (lua_State *L) { > ++ return arith(L, LUA_OPPOW, "__pow"); > ++} > ++ > ++static int arith_div (lua_State *L) { > ++ return arith(L, LUA_OPDIV, "__div"); > ++} > ++ > ++static int arith_idiv (lua_State *L) { > ++ return arith(L, LUA_OPIDIV, "__idiv"); > ++} > ++ > ++static int arith_unm (lua_State *L) { > ++ return arith(L, LUA_OPUNM, "__unm"); > ++} > ++ > ++ > ++static const luaL_Reg stringmetamethods[] = { > ++ {"__add", arith_add}, > ++ {"__sub", arith_sub}, > ++ {"__mul", arith_mul}, > ++ {"__mod", arith_mod}, > ++ {"__pow", arith_pow}, > ++ {"__div", arith_div}, > ++ {"__idiv", arith_idiv}, > ++ {"__unm", arith_unm}, > ++ {"__index", NULL}, /* placeholder */ > ++ {NULL, NULL} > ++}; > ++ > ++#endif /* } */ > ++ > ++/* }====================================================== */ > ++ > +/* > +** {====================================================== > +** PATTERN MATCHING > +** ======================================================= > +*/ > + > + > +#define CAP_UNFINISHED (-1) > +#define CAP_POSITION (-2) > + > + > +typedef struct MatchState { > + const char *src_init; /* init of source string */ > + const char *src_end; /* end ('\0') of source string */ > + const char *p_end; /* end ('\0') of pattern */ > + lua_State *L; > + int matchdepth; /* control for recursive depth (to avoid C stack > overflow) */ > + unsigned char level; /* total number of captures (finished or > unfinished) */ > + struct { > + const char *init; > + ptrdiff_t len; > + } capture[LUA_MAXCAPTURES]; > +} MatchState; > + > + > +/* recursive function */ > +static const char *match (MatchState *ms, const char *s, const char *p); > + > + > +/* maximum recursion depth for 'match' */ > +#if !defined(MAXCCALLS) > +#define MAXCCALLS 200 > +#endif > + > + > +#define L_ESC '%' > +#define SPECIALS "^$*+?.([%-" > + > + > +static int check_capture (MatchState *ms, int l) { > + l -= '1'; > + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) > + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); > + return l; > +} > + > + > +static int capture_to_close (MatchState *ms) { > + int level = ms->level; > + for (level--; level>=0; level--) > + if (ms->capture[level].len == CAP_UNFINISHED) return level; > + return luaL_error(ms->L, "invalid pattern capture"); > +} > + > + > +static const char *classend (MatchState *ms, const char *p) { > + switch (*p++) { > + case L_ESC: { > + if (p == ms->p_end) > + luaL_error(ms->L, "malformed pattern (ends with '%%')"); > + return p+1; > + } > + case '[': { > + if (*p == '^') p++; > + do { /* look for a ']' */ > + if (p == ms->p_end) > + luaL_error(ms->L, "malformed pattern (missing ']')"); > + if (*(p++) == L_ESC && p < ms->p_end) > + p++; /* skip escapes (e.g. '%]') */ > + } while (*p != ']'); > + return p+1; > + } > + default: { > + return p; > + } > + } > +} > + > + > +static int match_class (int c, int cl) { > + int res; > + switch (tolower(cl)) { > + case 'a' : res = isalpha(c); break; > + case 'c' : res = iscntrl(c); break; > + case 'd' : res = isdigit(c); break; > + case 'g' : res = isgraph(c); break; > + case 'l' : res = islower(c); break; > + case 'p' : res = ispunct(c); break; > + case 's' : res = isspace(c); break; > + case 'u' : res = isupper(c); break; > + case 'w' : res = isalnum(c); break; > + case 'x' : res = isxdigit(c); break; > + case 'z' : res = (c == 0); break; /* deprecated option */ > + default: return (cl == c); > + } > + return (islower(cl) ? res : !res); > +} > + > + > +static int matchbracketclass (int c, const char *p, const char *ec) { > + int sig = 1; > + if (*(p+1) == '^') { > + sig = 0; > + p++; /* skip the '^' */ > + } > + while (++p < ec) { > + if (*p == L_ESC) { > + p++; > + if (match_class(c, uchar(*p))) > + return sig; > + } > + else if ((*(p+1) == '-') && (p+2 < ec)) { > + p+=2; > + if (uchar(*(p-2)) <= c && c <= uchar(*p)) > + return sig; > + } > + else if (uchar(*p) == c) return sig; > + } > + return !sig; > +} > + > + > +static int singlematch (MatchState *ms, const char *s, const char *p, > + const char *ep) { > + if (s >= ms->src_end) > + return 0; > + else { > + int c = uchar(*s); > + switch (*p) { > + case '.': return 1; /* matches any char */ > + case L_ESC: return match_class(c, uchar(*(p+1))); > + case '[': return matchbracketclass(c, p, ep-1); > + default: return (uchar(*p) == c); > + } > + } > +} > + > + > +static const char *matchbalance (MatchState *ms, const char *s, > + const char *p) { > + if (p >= ms->p_end - 1) > + luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); > + if (*s != *p) return NULL; > + else { > + int b = *p; > + int e = *(p+1); > + int cont = 1; > + while (++s < ms->src_end) { > + if (*s == e) { > + if (--cont == 0) return s+1; > + } > + else if (*s == b) cont++; > + } > + } > + return NULL; /* string ends out of balance */ > +} > + > + > +static const char *max_expand (MatchState *ms, const char *s, > + const char *p, const char *ep) { > + ptrdiff_t i = 0; /* counts maximum expand for item */ > + while (singlematch(ms, s + i, p, ep)) > + i++; > + /* keeps trying to match with the maximum repetitions */ > + while (i>=0) { > + const char *res = match(ms, (s+i), ep+1); > + if (res) return res; > + i--; /* else didn't match; reduce 1 repetition to try again */ > + } > + return NULL; > +} > + > + > +static const char *min_expand (MatchState *ms, const char *s, > + const char *p, const char *ep) { > + for (;;) { > + const char *res = match(ms, s, ep+1); > + if (res != NULL) > + return res; > + else if (singlematch(ms, s, p, ep)) > + s++; /* try with one more repetition */ > + else return NULL; > + } > +} > + > + > +static const char *start_capture (MatchState *ms, const char *s, > + const char *p, int what) { > + const char *res; > + int level = ms->level; > + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); > + ms->capture[level].init = s; > + ms->capture[level].len = what; > + ms->level = level+1; > + if ((res=match(ms, s, p)) == NULL) /* match failed? */ > + ms->level--; /* undo capture */ > + return res; > +} > + > + > +static const char *end_capture (MatchState *ms, const char *s, > + const char *p) { > + int l = capture_to_close(ms); > + const char *res; > + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ > + if ((res = match(ms, s, p)) == NULL) /* match failed? */ > + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ > + return res; > +} > + > + > +static const char *match_capture (MatchState *ms, const char *s, int l) { > + size_t len; > + l = check_capture(ms, l); > + len = ms->capture[l].len; > + if ((size_t)(ms->src_end-s) >= len && > + memcmp(ms->capture[l].init, s, len) == 0) > + return s+len; > + else return NULL; > +} > + > + > +static const char *match (MatchState *ms, const char *s, const char *p) { > + if (ms->matchdepth-- == 0) > + luaL_error(ms->L, "pattern too complex"); > + init: /* using goto's to optimize tail recursion */ > + if (p != ms->p_end) { /* end of pattern? */ > + switch (*p) { > + case '(': { /* start capture */ > + if (*(p + 1) == ')') /* position capture? */ > + s = start_capture(ms, s, p + 2, CAP_POSITION); > + else > + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); > + break; > + } > + case ')': { /* end capture */ > + s = end_capture(ms, s, p + 1); > + break; > + } > + case '$': { > + if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? > */ > + goto dflt; /* no; go to default */ > + s = (s == ms->src_end) ? s : NULL; /* check end of string */ > + break; > + } > + case L_ESC: { /* escaped sequences not in the format class[*+?-]? > */ > + switch (*(p + 1)) { > + case 'b': { /* balanced string? */ > + s = matchbalance(ms, s, p + 2); > + if (s != NULL) { > + p += 4; goto init; /* return match(ms, s, p + 4); */ > + } /* else fail (s == NULL) */ > + break; > + } > + case 'f': { /* frontier? */ > + const char *ep; char previous; > + p += 2; > + if (*p != '[') > + luaL_error(ms->L, "missing '[' after '%%f' in pattern"); > + ep = classend(ms, p); /* points to what is next */ > + previous = (s == ms->src_init) ? '\0' : *(s - 1); > + if (!matchbracketclass(uchar(previous), p, ep - 1) && > + matchbracketclass(uchar(*s), p, ep - 1)) { > + p = ep; goto init; /* return match(ms, s, ep); */ > + } > + s = NULL; /* match failed */ > + break; > + } > + case '0': case '1': case '2': case '3': > + case '4': case '5': case '6': case '7': > + case '8': case '9': { /* capture results (%0-%9)? */ > + s = match_capture(ms, s, uchar(*(p + 1))); > + if (s != NULL) { > + p += 2; goto init; /* return match(ms, s, p + 2) */ > + } > + break; > + } > + default: goto dflt; > + } > + break; > + } > + default: dflt: { /* pattern class plus optional suffix */ > + const char *ep = classend(ms, p); /* points to optional suffix > */ > + /* does not match at least once? */ > + if (!singlematch(ms, s, p, ep)) { > + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? > */ > + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ > + } > + else /* '+' or no suffix */ > + s = NULL; /* fail */ > + } > + else { /* matched once */ > + switch (*ep) { /* handle optional suffix */ > + case '?': { /* optional */ > + const char *res; > + if ((res = match(ms, s + 1, ep + 1)) != NULL) > + s = res; > + else { > + p = ep + 1; goto init; /* else return match(ms, s, ep + > 1); */ > + } > + break; > + } > + case '+': /* 1 or more repetitions */ > + s++; /* 1 match already done */ > + /* FALLTHROUGH */ > + case '*': /* 0 or more repetitions */ > + s = max_expand(ms, s, p, ep); > + break; > + case '-': /* 0 or more repetitions (minimum) */ > + s = min_expand(ms, s, p, ep); > + break; > + default: /* no suffix */ > + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ > + } > + } > + break; > + } > + } > + } > + ms->matchdepth++; > + return s; > +} > + > + > + > +static const char *lmemfind (const char *s1, size_t l1, > + const char *s2, size_t l2) { > + if (l2 == 0) return s1; /* empty strings are everywhere */ > + else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ > + else { > + const char *init; /* to search for a '*s2' inside 's1' */ > + l2--; /* 1st char will be checked by 'memchr' */ > + l1 = l1-l2; /* 's2' cannot be found after that */ > + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) > { > + init++; /* 1st char is already checked */ > + if (memcmp(init, s2+1, l2) == 0) > + return init-1; > + else { /* correct 'l1' and 's1' to try again */ > + l1 -= init-s1; > + s1 = init; > + } > + } > + return NULL; /* not found */ > + } > +} > + > + > - static void push_onecapture (MatchState *ms, int i, const char *s, > - const char *e) { > ++/* > ++** get information about the i-th capture. If there are no captures > ++** and 'i==0', return information about the whole match, which > ++** is the range 's'..'e'. If the capture is a string, return > ++** its length and put its address in '*cap'. If it is an integer > ++** (a position), push it on the stack and return CAP_POSITION. > ++*/ > ++static size_t get_onecapture (MatchState *ms, int i, const char *s, > ++ const char *e, const char **cap) { > + if (i >= ms->level) { > - if (i == 0) /* ms->level == 0, too */ > - lua_pushlstring(ms->L, s, e - s); /* add whole match */ > - else > ++ if (i != 0) > + luaL_error(ms->L, "invalid capture index %%%d", i + 1); > ++ *cap = s; > ++ return e - s; > + } > + else { > *** 6490 LINES SKIPPED *** > _______________________________________________ > dev-commits-src-all@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all > To unsubscribe, send any mail to > "dev-commits-src-all-unsubscribe@freebsd.org" > -- Mateusz Guzik <mjguzik gmail.com>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAGudoHGv3aP-QgR23NPvnJHcwMMc=qAs7HSMnxQMaZu-RywKSg>