texlive[61986] Build/source/texk/web2c: Updated MFLua.

commits+lscarso at tug.org commits+lscarso at tug.org
Sat Feb 12 19:02:58 CET 2022


Revision: 61986
          http://tug.org/svn/texlive?view=revision&revision=61986
Author:   lscarso
Date:     2022-02-12 19:02:57 +0100 (Sat, 12 Feb 2022)
Log Message:
-----------
Updated MFLua.

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/Makefile.am
    trunk/Build/source/texk/web2c/Makefile.in
    trunk/Build/source/texk/web2c/mfluadir/ChangeLog
    trunk/Build/source/texk/web2c/mfluadir/am/mflua.am
    trunk/Build/source/texk/web2c/mfluadir/am/mfluaotfcc.am
    trunk/Build/source/texk/web2c/mfluadir/mflua_version.h
    trunk/Build/source/texk/web2c/mfluadir/mfluac.c
    trunk/Build/source/texk/web2c/mfluadir/mfluac.h
    trunk/Build/source/texk/web2c/mfluajitdir/ChangeLog
    trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajit.am

Added Paths:
-----------
    trunk/Build/source/texk/web2c/mfluadir/am/mflualpeg.am
    trunk/Build/source/texk/web2c/mfluadir/am/mfluapotrace.am
    trunk/Build/source/texk/web2c/mfluadir/luapeg/
    trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.c
    trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.h
    trunk/Build/source/texk/web2c/mfluadir/mflua_svnversion.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/
    trunk/Build/source/texk/web2c/mfluadir/potrace/auxiliary.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/bitmap.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/config.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/curve.c
    trunk/Build/source/texk/web2c/mfluadir/potrace/curve.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.c
    trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/lists.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.c
    trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.c
    trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/progress.h
    trunk/Build/source/texk/web2c/mfluadir/potrace/trace.c
    trunk/Build/source/texk/web2c/mfluadir/potrace/trace.h
    trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajitlpeg.am

Modified: trunk/Build/source/texk/web2c/Makefile.am
===================================================================
--- trunk/Build/source/texk/web2c/Makefile.am	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/Makefile.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -245,9 +245,12 @@
 ## MFLua
 include $(srcdir)/mfluadir/am/mflua.am
 include $(srcdir)/mfluadir/am/mfluaotfcc.am
+include $(srcdir)/mfluadir/am/mfluapotrace.am
+include $(srcdir)/mfluadir/am/mflualpeg.am
 
 ## MFLuaJIT
 include $(srcdir)/mfluajitdir/am/mfluajit.am
+include $(srcdir)/mfluajitdir/am/mfluajitlpeg.am
 
 ## MetaPost
 include $(srcdir)/mplibdir/am/mplib.am

Modified: trunk/Build/source/texk/web2c/Makefile.in
===================================================================
--- trunk/Build/source/texk/web2c/Makefile.in	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/Makefile.in	2022-02-12 18:02:57 UTC (rev 61986)
@@ -985,11 +985,16 @@
 	libmfluajit_a-mfluajit-pool.$(OBJEXT)
 libmfluajit_a_OBJECTS = $(dist_libmfluajit_a_OBJECTS) \
 	$(nodist_libmfluajit_a_OBJECTS)
-libmfluajitotfcc_a_AR = $(AR) $(ARFLAGS)
-libmfluajitotfcc_a_LIBADD =
-libmfluajitotfcc_a_SOURCES = libmfluajitotfcc.c
-libmfluajitotfcc_a_OBJECTS =  \
-	libmfluajitotfcc_a-libmfluajitotfcc.$(OBJEXT)
+libmfluajitlpeg_a_AR = $(AR) $(ARFLAGS)
+libmfluajitlpeg_a_LIBADD =
+am_libmfluajitlpeg_a_OBJECTS =  \
+	mfluadir/luapeg/libmfluajitlpeg_a-lpeg.$(OBJEXT)
+libmfluajitlpeg_a_OBJECTS = $(am_libmfluajitlpeg_a_OBJECTS)
+libmflualpeg_a_AR = $(AR) $(ARFLAGS)
+libmflualpeg_a_LIBADD =
+am_libmflualpeg_a_OBJECTS =  \
+	mfluadir/luapeg/libmflualpeg_a-lpeg.$(OBJEXT)
+libmflualpeg_a_OBJECTS = $(am_libmflualpeg_a_OBJECTS)
 libmfluaotfcc_a_AR = $(AR) $(ARFLAGS)
 libmfluaotfcc_a_LIBADD =
 am_libmfluaotfcc_a_OBJECTS = mfluadir/otfcc/dep/extern/emyg-dtoa/libmfluaotfcc_a-emyg-dtoa.$(OBJEXT) \
@@ -1109,6 +1114,15 @@
 	mfluadir/otfcc/lib/table/libmfluaotfcc_a-SVG.$(OBJEXT) \
 	mfluadir/otfcc/lib/table/libmfluaotfcc_a-TSI5.$(OBJEXT)
 libmfluaotfcc_a_OBJECTS = $(am_libmfluaotfcc_a_OBJECTS)
+libmfluapotrace_a_AR = $(AR) $(ARFLAGS)
+libmfluapotrace_a_LIBADD =
+am_libmfluapotrace_a_OBJECTS =  \
+	mfluadir/potrace/libmfluapotrace_a-curve.$(OBJEXT) \
+	mfluadir/potrace/libmfluapotrace_a-decompose.$(OBJEXT) \
+	mfluadir/potrace/libmfluapotrace_a-luafunc.$(OBJEXT) \
+	mfluadir/potrace/libmfluapotrace_a-potracelib.$(OBJEXT) \
+	mfluadir/potrace/libmfluapotrace_a-trace.$(OBJEXT)
+libmfluapotrace_a_OBJECTS = $(am_libmfluapotrace_a_OBJECTS)
 libmplibbackends_a_AR = $(AR) $(ARFLAGS)
 libmplibbackends_a_LIBADD =
 am__objects_17 = libmplibbackends_a-pngout.$(OBJEXT)
@@ -1450,8 +1464,9 @@
 mf_nowin_DEPENDENCIES = libmf.a $(am__DEPENDENCIES_2) $(windowlib)
 dist_mflua_OBJECTS = mfluadir/mflua-mfluaextra.$(OBJEXT)
 mflua_OBJECTS = $(dist_mflua_OBJECTS)
-mflua_DEPENDENCIES = libmflua.a libmfluaotfcc.a $(am__DEPENDENCIES_2) \
-	$(windowlib) $(am__DEPENDENCIES_9) $(am__DEPENDENCIES_6)
+mflua_DEPENDENCIES = libmflua.a libmfluaotfcc.a libmfluapotrace.a \
+	libmflualpeg.a $(am__DEPENDENCIES_2) $(windowlib) \
+	$(am__DEPENDENCIES_9) $(am__DEPENDENCIES_6)
 mflua_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(mflua_LDFLAGS) $(LDFLAGS) -o $@
@@ -1459,7 +1474,8 @@
 nodist_mflua_nowin_OBJECTS = $(am__objects_42)
 mflua_nowin_OBJECTS = $(nodist_mflua_nowin_OBJECTS)
 mflua_nowin_DEPENDENCIES = libmflua.a libmfluaotfcc.a \
-	$(am__DEPENDENCIES_2) $(windowlib) $(am__DEPENDENCIES_6)
+	libmfluapotrace.a libmflualpeg.a $(am__DEPENDENCIES_2) \
+	$(windowlib) $(am__DEPENDENCIES_6)
 mflua_nowin_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(mflua_nowin_LDFLAGS) $(LDFLAGS) -o $@
@@ -1466,8 +1482,8 @@
 dist_mfluajit_OBJECTS = mfluajitdir/mfluajit-mfluajitextra.$(OBJEXT)
 mfluajit_OBJECTS = $(dist_mfluajit_OBJECTS)
 mfluajit_DEPENDENCIES = libmfluajit.a libmfluaotfcc.a \
-	$(am__DEPENDENCIES_2) $(windowlib) $(am__DEPENDENCIES_9) \
-	$(am__DEPENDENCIES_1)
+	libmfluapotrace.a libmfluajitlpeg.a $(am__DEPENDENCIES_2) \
+	$(windowlib) $(am__DEPENDENCIES_9) $(am__DEPENDENCIES_1)
 mfluajit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(mfluajit_LDFLAGS) $(LDFLAGS) -o $@
@@ -1475,7 +1491,8 @@
 nodist_mfluajit_nowin_OBJECTS = $(am__objects_43)
 mfluajit_nowin_OBJECTS = $(nodist_mfluajit_nowin_OBJECTS)
 mfluajit_nowin_DEPENDENCIES = libmfluajit.a libmfluaotfcc.a \
-	$(am__DEPENDENCIES_2) $(windowlib) $(am__DEPENDENCIES_1)
+	libmfluapotrace.a libmfluajitlpeg.a $(am__DEPENDENCIES_2) \
+	$(windowlib) $(am__DEPENDENCIES_1)
 mfluajit_nowin_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(AM_CFLAGS) $(CFLAGS) $(mfluajit_nowin_LDFLAGS) $(LDFLAGS) -o \
@@ -1787,7 +1804,6 @@
 	./$(DEPDIR)/libmfluajit_a-mfluajit-pool.Po \
 	./$(DEPDIR)/libmfluajit_a-mfluajit0.Po \
 	./$(DEPDIR)/libmfluajit_a-mfluajitini.Po \
-	./$(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po \
 	./$(DEPDIR)/libmplibbackends_a-pngout.Po \
 	./$(DEPDIR)/libmplibbackends_a-svgout.Po \
 	./$(DEPDIR)/libmplibcore_a-mp.Po \
@@ -2230,6 +2246,8 @@
 	mfluadir/$(DEPDIR)/libmfluajit_a-mfluac.Po \
 	mfluadir/$(DEPDIR)/mflua-mfluaextra.Po \
 	mfluadir/$(DEPDIR)/mflua_nowin-mfluaextra.Po \
+	mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po \
+	mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po \
 	mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json-builder.Po \
 	mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json.Po \
 	mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-sds.Po \
@@ -2346,6 +2364,11 @@
 	mfluadir/otfcc/lib/vf/$(DEPDIR)/libmfluaotfcc_a-vq.Po \
 	mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-luafunc.Po \
 	mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-otfccdll.Po \
+	mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po \
+	mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po \
+	mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po \
+	mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po \
+	mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po \
 	mfluajitdir/$(DEPDIR)/mfluajit-mfluajitextra.Po \
 	mfluajitdir/$(DEPDIR)/mfluajit_nowin-mfluajitextra.Po \
 	mplibdir/$(DEPDIR)/libmputil_a-avl.Po \
@@ -2494,8 +2517,9 @@
 	$(nodist_libluatexspecific_a_SOURCES) $(libmd5_a_SOURCES) \
 	$(nodist_libmf_a_SOURCES) $(dist_libmflua_a_SOURCES) \
 	$(nodist_libmflua_a_SOURCES) $(dist_libmfluajit_a_SOURCES) \
-	$(nodist_libmfluajit_a_SOURCES) libmfluajitotfcc.c \
-	$(libmfluaotfcc_a_SOURCES) \
+	$(nodist_libmfluajit_a_SOURCES) $(libmfluajitlpeg_a_SOURCES) \
+	$(libmflualpeg_a_SOURCES) $(libmfluaotfcc_a_SOURCES) \
+	$(libmfluapotrace_a_SOURCES) \
 	$(nodist_libmplibbackends_a_SOURCES) \
 	$(nodist_libmplibcore_a_SOURCES) \
 	$(nodist_libmplibextramath_a_SOURCES) $(libmputil_a_SOURCES) \
@@ -2561,8 +2585,9 @@
 	$(libluaharfbuzz_a_SOURCES) $(libluajitharfbuzz_a_SOURCES) \
 	$(dist_libluajittex_a_SOURCES) $(dist_libluatex_a_SOURCES) \
 	$(libmd5_a_SOURCES) $(dist_libmflua_a_SOURCES) \
-	$(dist_libmfluajit_a_SOURCES) libmfluajitotfcc.c \
-	$(libmfluaotfcc_a_SOURCES) $(libmputil_a_SOURCES) \
+	$(dist_libmfluajit_a_SOURCES) $(libmfluajitlpeg_a_SOURCES) \
+	$(libmflualpeg_a_SOURCES) $(libmfluaotfcc_a_SOURCES) \
+	$(libmfluapotrace_a_SOURCES) $(libmputil_a_SOURCES) \
 	$(am__libpdftex_a_SOURCES_DIST) $(EXTRA_libpdftex_a_SOURCES) \
 	$(libukanji_a_SOURCES) $(libunilib_a_SOURCES) \
 	$(am__libxetex_a_SOURCES_DIST) $(libsynctex_la_SOURCES) \
@@ -2830,8 +2855,11 @@
 	$(srcdir)/luatexdir/am/luasocket.am \
 	$(srcdir)/luatexdir/am/luatex.am \
 	$(srcdir)/mfluadir/am/mflua.am \
+	$(srcdir)/mfluadir/am/mflualpeg.am \
 	$(srcdir)/mfluadir/am/mfluaotfcc.am \
+	$(srcdir)/mfluadir/am/mfluapotrace.am \
 	$(srcdir)/mfluajitdir/am/mfluajit.am \
+	$(srcdir)/mfluajitdir/am/mfluajitlpeg.am \
 	$(srcdir)/mplibdir/am/libmplib.am \
 	$(srcdir)/mplibdir/am/libmputil.am \
 	$(srcdir)/mplibdir/am/mplib.am \
@@ -3147,15 +3175,17 @@
 #EXTRA_LIBRARIES += libluamisc.a liblua53misc.a  libluajitmisc.a
 
 #EXTRA_LIBRARIES += libluaffi.a  liblua53ffi.a 
-EXTRA_LIBRARIES = libmf.a libmflua.a libmfluaotfcc.a libmfluaotfcc.a \
-	libmfluajitotfcc.a libmfluajit.a libmfluaotfcc.a libmputil.a \
-	libmplibcore.a libmplibextramath.a libmplibbackends.a \
-	libkanji.a libukanji.a libpdftex.a libluasocket.a \
-	libluajitsocket.a libluamisc.a libluajitmisc.a libunilib.a \
-	libff.a libluatex.a libluajittex.a libluatexspecific.a \
-	libluajittexspecific.a libluahbtexspecific.a \
-	libluajithbtexspecific.a libluaffi.a libluaharfbuzz.a \
-	libluajitharfbuzz.a libxetex.a libsynctex.a libmd5.a
+EXTRA_LIBRARIES = libmf.a libmflua.a libmfluaotfcc.a libmfluapotrace.a \
+	libmflualpeg.a libmfluaotfcc.a libmfluapotrace.a \
+	libmflualpeg.a libmfluajit.a libmfluaotfcc.a libmfluapotrace.a \
+	libmfluajitlpeg.a libmfluajitlpeg.a libmputil.a libmplibcore.a \
+	libmplibextramath.a libmplibbackends.a libkanji.a libukanji.a \
+	libpdftex.a libluasocket.a libluajitsocket.a libluamisc.a \
+	libluajitmisc.a libunilib.a libff.a libluatex.a libluajittex.a \
+	libluatexspecific.a libluajittexspecific.a \
+	libluahbtexspecific.a libluajithbtexspecific.a libluaffi.a \
+	libluaharfbuzz.a libluajitharfbuzz.a libxetex.a libsynctex.a \
+	libmd5.a
 EXTRA_LTLIBRARIES = libsynctex.la
 lib_LIBRARIES = $(am__append_125)
 lib_LTLIBRARIES = $(am__append_124)
@@ -3893,11 +3923,11 @@
 call_mflua_LDADD = 
 dist_mflua_SOURCES = mfluadir/mfluaextra.c mfluadir/mfluaextra.h mfluadir/mflua_version.h
 mflua_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(LUA_INCLUDES)
-mflua_LDADD = libmflua.a libmfluaotfcc.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUA_LIBS)
+mflua_LDADD = libmflua.a libmfluaotfcc.a libmfluapotrace.a libmflualpeg.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUA_LIBS)
 mflua_LDFLAGS = -export-dynamic
 nodist_mflua_nowin_SOURCES = $(dist_mflua_SOURCES)
 mflua_nowin_CPPFLAGS = $(mflua_CPPFLAGS) -DMFNOWIN $(LUA_INCLUDES)
-mflua_nowin_LDADD = libmflua.a libmfluaotfcc.a $(LDADD) $(windowlib) $(LUA_LIBS)
+mflua_nowin_LDADD = libmflua.a libmfluaotfcc.a libmfluapotrace.a libmflualpeg.a $(LDADD) $(windowlib) $(LUA_LIBS)
 mflua_nowin_LDFLAGS = -export-dynamic
 
 # MFLua C sources
@@ -3922,22 +3952,11 @@
 	-std=c99 -D_CARYLL_USE_PRE_SERIALIZED -DMAIN_VER=0 -DSECONDARY_VER=10 -DPATCH_VER=4 \
 	-I$(top_srcdir)/mfluadir/otfcc/include \
 	-I$(top_srcdir)/mfluadir/otfcc/include/dep \
-	-I$(top_srcdir)/mfluadir/otfcc/lib \
-	 $(LUA_INCLUDES)
+	-I$(top_srcdir)/mfluadir/otfcc/lib 
 
-libmfluajitotfcc_a_CPPFLAGS = \
-	-std=c99 -D_CARYLL_USE_PRE_SERIALIZED -DMAIN_VER=0 -DSECONDARY_VER=10 -DPATCH_VER=4 \
-	-DJIT \
-	-I$(top_srcdir)/mfluadir/otfcc/include \
-	-I$(top_srcdir)/mfluadir/otfcc/include/dep \
-	-I$(top_srcdir)/mfluadir/otfcc/lib \
-	$(LUAJIT_INCLUDES)
-
 libmfluaotfcc_a_CFLAGS = # $(WARNING_CFLAGS)
-libmfluajitotfcc_a_CFLAGS = # $(WARNING_CFLAGS)
 
 #nodist_libmfluaotfcc_a_SOURCES = $(libmfluaotfcc_sources)
-#nodist_libmfluajitotfcc_a_SOURCES = $(libmfluaotfcc_sources)
 libmfluaotfcc_a_SOURCES = \
 	mfluadir/otfcc/dep/extern/sdsalloc.h \
 	mfluadir/otfcc/dep/extern/emyg-dtoa/emyg-dtoa.c \
@@ -4197,16 +4216,48 @@
 	mfluadir/otfcc/lib/table/head.h \
 	mfluadir/otfcc/lib/table/TSI5.c 
 
+libmfluapotrace_a_CPPFLAGS = \
+        -I$(top_srcdir)/mfluadir/potrace 
+
+libmfluapotrace_a_CFLAGS = # $(WARNING_CFLAGS)
+
+#nodist_libmfluapotrace_a_SOURCES = $(libmfluapotrace_sources)
+libmfluapotrace_a_SOURCES = \
+	mfluadir/potrace/auxiliary.h \
+	mfluadir/potrace/bitmap.h \
+	mfluadir/potrace/config.h \
+	mfluadir/potrace/curve.c \
+	mfluadir/potrace/curve.h \
+	mfluadir/potrace/decompose.c \
+	mfluadir/potrace/decompose.h \
+	mfluadir/potrace/lists.h \
+	mfluadir/potrace/luafunc.c \
+	mfluadir/potrace/luafunc.h \
+	mfluadir/potrace/potracelib.c \
+	mfluadir/potrace/potracelib.h \
+	mfluadir/potrace/progress.h \
+	mfluadir/potrace/trace.c \
+	mfluadir/potrace/trace.h
+
+libmflualpeg_a_CPPFLAGS = \
+	-I$(top_srcdir)/mfluadir/luapeg \
+	$(LUA_INCLUDES)
+
+libmflualpeg_a_CFLAGS = # $(WARNING_CFLAGS)
+libmflualpeg_a_SOURCES = \
+	mfluadir/luapeg/lpeg.c \
+	mfluadir/luapeg/lpeg.h 
+
 call_mfluajit_CPPFLAGS = -DEXEPROG=\"mfluajit.exe\"
 nodist_call_mfluajit_SOURCES = callexe.c
 call_mfluajit_LDADD = 
 dist_mfluajit_SOURCES = mfluajitdir/mfluajitextra.c mfluajitdir/mfluajitextra.h mfluadir/mflua_version.h
 mfluajit_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(LUAJIT_INCLUDES) $(LUAJIT_DEFINES)
-mfluajit_LDADD = libmfluajit.a libmfluaotfcc.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUAJIT_LIBS)
+mfluajit_LDADD = libmfluajit.a libmfluaotfcc.a libmfluapotrace.a libmfluajitlpeg.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUAJIT_LIBS)
 mfluajit_LDFLAGS = -export-dynamic $(LUAJIT_LDEXTRA)
 nodist_mfluajit_nowin_SOURCES = $(dist_mfluajit_SOURCES)
 mfluajit_nowin_CPPFLAGS = $(mfluajit_CPPFLAGS) -DMFNOWIN $(LUAJIT_INCLUDES) $(LUAJIT_DEFINES)
-mfluajit_nowin_LDADD = libmfluajit.a libmfluaotfcc.a $(LDADD) $(windowlib) $(LUAJIT_LIBS)
+mfluajit_nowin_LDADD = libmfluajit.a libmfluaotfcc.a libmfluapotrace.a libmfluajitlpeg.a $(LDADD) $(windowlib) $(LUAJIT_LIBS)
 mfluajit_nowin_LDFLAGS = -export-dynamic $(LUAJIT_LDEXTRA)
 
 # MFLuaJIT C sources
@@ -4228,6 +4279,15 @@
 # MFLuaJIT tests
 #
 mfluajit_tests = mfluajitdir/mfluajittraptest.test
+libmfluajitlpeg_a_CPPFLAGS = \
+	-I$(top_srcdir)/mfluadir/luapeg \
+	$(LUAJIT_INCLUDES)
+
+libmfluajitlpeg_a_CFLAGS = # $(WARNING_CFLAGS)
+libmfluajitlpeg_a_SOURCES = \
+	mfluadir/luapeg/lpeg.c \
+	mfluadir/luapeg/lpeg.h 
+
 mpost_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_INCLUDES) $(LIBPNG_INCLUDES) -I$(srcdir)/mplibdir
 mpost_LDADD = libmplibcore.a libmplibextramath.a libmplibbackends.a  $(KPATHSEA_LIBS) $(MPFR_LIBS) $(GMP_LIBS) \
 	$(CAIRO_LIBS) $(PIXMAN_LIBS) $(LIBPNG_LIBS) $(ZLIB_LIBS) libmputil.a
@@ -5638,7 +5698,7 @@
 .SUFFIXES: .c .cc .cin .cpp .cxx .h .hin .lo .log .mm .o .obj .p .pin .pl .pl$(EXEEXT) .test .test$(EXEEXT) .trs
 am--refresh: Makefile
 	@:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/eptexdir/am/eptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__configure_deps)
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/eptexdir/am/eptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
 	    *$$dep*) \
@@ -5660,7 +5720,7 @@
 	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
 	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
 	esac;
-$(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/eptexdir/am/eptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__empty):
+$(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/eptexdir/am/eptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__empty):
 
 $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
 	$(SHELL) ./config.status --recheck
@@ -7155,11 +7215,28 @@
 	$(AM_V_at)-rm -f libmfluajit.a
 	$(AM_V_AR)$(libmfluajit_a_AR) libmfluajit.a $(libmfluajit_a_OBJECTS) $(libmfluajit_a_LIBADD)
 	$(AM_V_at)$(RANLIB) libmfluajit.a
+mfluadir/luapeg/$(am__dirstamp):
+	@$(MKDIR_P) mfluadir/luapeg
+	@: > mfluadir/luapeg/$(am__dirstamp)
+mfluadir/luapeg/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) mfluadir/luapeg/$(DEPDIR)
+	@: > mfluadir/luapeg/$(DEPDIR)/$(am__dirstamp)
+mfluadir/luapeg/libmfluajitlpeg_a-lpeg.$(OBJEXT):  \
+	mfluadir/luapeg/$(am__dirstamp) \
+	mfluadir/luapeg/$(DEPDIR)/$(am__dirstamp)
 
-libmfluajitotfcc.a: $(libmfluajitotfcc_a_OBJECTS) $(libmfluajitotfcc_a_DEPENDENCIES) $(EXTRA_libmfluajitotfcc_a_DEPENDENCIES) 
-	$(AM_V_at)-rm -f libmfluajitotfcc.a
-	$(AM_V_AR)$(libmfluajitotfcc_a_AR) libmfluajitotfcc.a $(libmfluajitotfcc_a_OBJECTS) $(libmfluajitotfcc_a_LIBADD)
-	$(AM_V_at)$(RANLIB) libmfluajitotfcc.a
+libmfluajitlpeg.a: $(libmfluajitlpeg_a_OBJECTS) $(libmfluajitlpeg_a_DEPENDENCIES) $(EXTRA_libmfluajitlpeg_a_DEPENDENCIES) 
+	$(AM_V_at)-rm -f libmfluajitlpeg.a
+	$(AM_V_AR)$(libmfluajitlpeg_a_AR) libmfluajitlpeg.a $(libmfluajitlpeg_a_OBJECTS) $(libmfluajitlpeg_a_LIBADD)
+	$(AM_V_at)$(RANLIB) libmfluajitlpeg.a
+mfluadir/luapeg/libmflualpeg_a-lpeg.$(OBJEXT):  \
+	mfluadir/luapeg/$(am__dirstamp) \
+	mfluadir/luapeg/$(DEPDIR)/$(am__dirstamp)
+
+libmflualpeg.a: $(libmflualpeg_a_OBJECTS) $(libmflualpeg_a_DEPENDENCIES) $(EXTRA_libmflualpeg_a_DEPENDENCIES) 
+	$(AM_V_at)-rm -f libmflualpeg.a
+	$(AM_V_AR)$(libmflualpeg_a_AR) libmflualpeg.a $(libmflualpeg_a_OBJECTS) $(libmflualpeg_a_LIBADD)
+	$(AM_V_at)$(RANLIB) libmflualpeg.a
 mfluadir/otfcc/dep/extern/emyg-dtoa/$(am__dirstamp):
 	@$(MKDIR_P) mfluadir/otfcc/dep/extern/emyg-dtoa
 	@: > mfluadir/otfcc/dep/extern/emyg-dtoa/$(am__dirstamp)
@@ -7681,7 +7758,33 @@
 	$(AM_V_at)-rm -f libmfluaotfcc.a
 	$(AM_V_AR)$(libmfluaotfcc_a_AR) libmfluaotfcc.a $(libmfluaotfcc_a_OBJECTS) $(libmfluaotfcc_a_LIBADD)
 	$(AM_V_at)$(RANLIB) libmfluaotfcc.a
+mfluadir/potrace/$(am__dirstamp):
+	@$(MKDIR_P) mfluadir/potrace
+	@: > mfluadir/potrace/$(am__dirstamp)
+mfluadir/potrace/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) mfluadir/potrace/$(DEPDIR)
+	@: > mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+mfluadir/potrace/libmfluapotrace_a-curve.$(OBJEXT):  \
+	mfluadir/potrace/$(am__dirstamp) \
+	mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+mfluadir/potrace/libmfluapotrace_a-decompose.$(OBJEXT):  \
+	mfluadir/potrace/$(am__dirstamp) \
+	mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+mfluadir/potrace/libmfluapotrace_a-luafunc.$(OBJEXT):  \
+	mfluadir/potrace/$(am__dirstamp) \
+	mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+mfluadir/potrace/libmfluapotrace_a-potracelib.$(OBJEXT):  \
+	mfluadir/potrace/$(am__dirstamp) \
+	mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+mfluadir/potrace/libmfluapotrace_a-trace.$(OBJEXT):  \
+	mfluadir/potrace/$(am__dirstamp) \
+	mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
 
+libmfluapotrace.a: $(libmfluapotrace_a_OBJECTS) $(libmfluapotrace_a_DEPENDENCIES) $(EXTRA_libmfluapotrace_a_DEPENDENCIES) 
+	$(AM_V_at)-rm -f libmfluapotrace.a
+	$(AM_V_AR)$(libmfluapotrace_a_AR) libmfluapotrace.a $(libmfluapotrace_a_OBJECTS) $(libmfluapotrace_a_LIBADD)
+	$(AM_V_at)$(RANLIB) libmfluapotrace.a
+
 libmplibbackends.a: $(libmplibbackends_a_OBJECTS) $(libmplibbackends_a_DEPENDENCIES) $(EXTRA_libmplibbackends_a_DEPENDENCIES) 
 	$(AM_V_at)-rm -f libmplibbackends.a
 	$(AM_V_AR)$(libmplibbackends_a_AR) libmplibbackends.a $(libmplibbackends_a_OBJECTS) $(libmplibbackends_a_LIBADD)
@@ -8400,6 +8503,7 @@
 	-rm -f luatexdir/unilib/*.$(OBJEXT)
 	-rm -f luatexdir/utils/*.$(OBJEXT)
 	-rm -f mfluadir/*.$(OBJEXT)
+	-rm -f mfluadir/luapeg/*.$(OBJEXT)
 	-rm -f mfluadir/otfcc/dep/extern/*.$(OBJEXT)
 	-rm -f mfluadir/otfcc/dep/extern/emyg-dtoa/*.$(OBJEXT)
 	-rm -f mfluadir/otfcc/lib/bk/*.$(OBJEXT)
@@ -8429,6 +8533,7 @@
 	-rm -f mfluadir/otfcc/lib/table/vdmx/*.$(OBJEXT)
 	-rm -f mfluadir/otfcc/lib/vf/*.$(OBJEXT)
 	-rm -f mfluadir/otfcc/src/*.$(OBJEXT)
+	-rm -f mfluadir/potrace/*.$(OBJEXT)
 	-rm -f mfluajitdir/*.$(OBJEXT)
 	-rm -f mplibdir/*.$(OBJEXT)
 	-rm -f pdftexdir/*.$(OBJEXT)
@@ -8503,7 +8608,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmfluajit_a-mfluajit-pool.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmfluajit_a-mfluajit0.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmfluajit_a-mfluajitini.Po at am__quote@ # am--include-marker
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmplibbackends_a-pngout.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmplibbackends_a-svgout.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libmplibcore_a-mp.Po at am__quote@ # am--include-marker
@@ -8981,6 +9085,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/$(DEPDIR)/libmfluajit_a-mfluac.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/$(DEPDIR)/mflua-mfluaextra.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/$(DEPDIR)/mflua_nowin-mfluaextra.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json-builder.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-sds.Po at am__quote@ # am--include-marker
@@ -9097,6 +9203,11 @@
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/lib/vf/$(DEPDIR)/libmfluaotfcc_a-vq.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-luafunc.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-otfccdll.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po at am__quote@ # am--include-marker
+ at AMDEP_TRUE@@am__include@ @am__quote at mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluajitdir/$(DEPDIR)/mfluajit-mfluajitextra.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mfluajitdir/$(DEPDIR)/mfluajit_nowin-mfluajitextra.Po at am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote at mplibdir/$(DEPDIR)/libmputil_a-avl.Po at am__quote@ # am--include-marker
@@ -14512,20 +14623,34 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajit_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmfluajit_a-mfluajit-pool.obj `if test -f 'mfluajit-pool.c'; then $(CYGPATH_W) 'mfluajit-pool.c'; else $(CYGPATH_W) '$(srcdir)/mfluajit-pool.c'; fi`
 
-libmfluajitotfcc_a-libmfluajitotfcc.o: libmfluajitotfcc.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitotfcc_a_CFLAGS) $(CFLAGS) -MT libmfluajitotfcc_a-libmfluajitotfcc.o -MD -MP -MF $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Tpo -c -o libmfluajitotfcc_a-libmfluajitotfcc.o `test -f 'libmfluajitotfcc.c' || echo '$(srcdir)/'`libmfluajitotfcc.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Tpo $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='libmfluajitotfcc.c' object='libmfluajitotfcc_a-libmfluajitotfcc.o' libtool=no @AMDEPBACKSLASH@
+mfluadir/luapeg/libmfluajitlpeg_a-lpeg.o: mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitlpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitlpeg_a_CFLAGS) $(CFLAGS) -MT mfluadir/luapeg/libmfluajitlpeg_a-lpeg.o -MD -MP -MF mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Tpo -c -o mfluadir/luapeg/libmfluajitlpeg_a-lpeg.o `test -f 'mfluadir/luapeg/lpeg.c' || echo '$(srcdir)/'`mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Tpo mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/luapeg/lpeg.c' object='mfluadir/luapeg/libmfluajitlpeg_a-lpeg.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitotfcc_a_CFLAGS) $(CFLAGS) -c -o libmfluajitotfcc_a-libmfluajitotfcc.o `test -f 'libmfluajitotfcc.c' || echo '$(srcdir)/'`libmfluajitotfcc.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitlpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitlpeg_a_CFLAGS) $(CFLAGS) -c -o mfluadir/luapeg/libmfluajitlpeg_a-lpeg.o `test -f 'mfluadir/luapeg/lpeg.c' || echo '$(srcdir)/'`mfluadir/luapeg/lpeg.c
 
-libmfluajitotfcc_a-libmfluajitotfcc.obj: libmfluajitotfcc.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitotfcc_a_CFLAGS) $(CFLAGS) -MT libmfluajitotfcc_a-libmfluajitotfcc.obj -MD -MP -MF $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Tpo -c -o libmfluajitotfcc_a-libmfluajitotfcc.obj `if test -f 'libmfluajitotfcc.c'; then $(CYGPATH_W) 'libmfluajitotfcc.c'; else $(CYGPATH_W) '$(srcdir)/libmfluajitotfcc.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Tpo $(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='libmfluajitotfcc.c' object='libmfluajitotfcc_a-libmfluajitotfcc.obj' libtool=no @AMDEPBACKSLASH@
+mfluadir/luapeg/libmfluajitlpeg_a-lpeg.obj: mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitlpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitlpeg_a_CFLAGS) $(CFLAGS) -MT mfluadir/luapeg/libmfluajitlpeg_a-lpeg.obj -MD -MP -MF mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Tpo -c -o mfluadir/luapeg/libmfluajitlpeg_a-lpeg.obj `if test -f 'mfluadir/luapeg/lpeg.c'; then $(CYGPATH_W) 'mfluadir/luapeg/lpeg.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/luapeg/lpeg.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Tpo mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/luapeg/lpeg.c' object='mfluadir/luapeg/libmfluajitlpeg_a-lpeg.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitotfcc_a_CFLAGS) $(CFLAGS) -c -o libmfluajitotfcc_a-libmfluajitotfcc.obj `if test -f 'libmfluajitotfcc.c'; then $(CYGPATH_W) 'libmfluajitotfcc.c'; else $(CYGPATH_W) '$(srcdir)/libmfluajitotfcc.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluajitlpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmfluajitlpeg_a_CFLAGS) $(CFLAGS) -c -o mfluadir/luapeg/libmfluajitlpeg_a-lpeg.obj `if test -f 'mfluadir/luapeg/lpeg.c'; then $(CYGPATH_W) 'mfluadir/luapeg/lpeg.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/luapeg/lpeg.c'; fi`
 
+mfluadir/luapeg/libmflualpeg_a-lpeg.o: mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmflualpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmflualpeg_a_CFLAGS) $(CFLAGS) -MT mfluadir/luapeg/libmflualpeg_a-lpeg.o -MD -MP -MF mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Tpo -c -o mfluadir/luapeg/libmflualpeg_a-lpeg.o `test -f 'mfluadir/luapeg/lpeg.c' || echo '$(srcdir)/'`mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Tpo mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/luapeg/lpeg.c' object='mfluadir/luapeg/libmflualpeg_a-lpeg.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmflualpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmflualpeg_a_CFLAGS) $(CFLAGS) -c -o mfluadir/luapeg/libmflualpeg_a-lpeg.o `test -f 'mfluadir/luapeg/lpeg.c' || echo '$(srcdir)/'`mfluadir/luapeg/lpeg.c
+
+mfluadir/luapeg/libmflualpeg_a-lpeg.obj: mfluadir/luapeg/lpeg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmflualpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmflualpeg_a_CFLAGS) $(CFLAGS) -MT mfluadir/luapeg/libmflualpeg_a-lpeg.obj -MD -MP -MF mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Tpo -c -o mfluadir/luapeg/libmflualpeg_a-lpeg.obj `if test -f 'mfluadir/luapeg/lpeg.c'; then $(CYGPATH_W) 'mfluadir/luapeg/lpeg.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/luapeg/lpeg.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Tpo mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/luapeg/lpeg.c' object='mfluadir/luapeg/libmflualpeg_a-lpeg.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmflualpeg_a_CPPFLAGS) $(CPPFLAGS) $(libmflualpeg_a_CFLAGS) $(CFLAGS) -c -o mfluadir/luapeg/libmflualpeg_a-lpeg.obj `if test -f 'mfluadir/luapeg/lpeg.c'; then $(CYGPATH_W) 'mfluadir/luapeg/lpeg.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/luapeg/lpeg.c'; fi`
+
 mfluadir/otfcc/dep/extern/emyg-dtoa/libmfluaotfcc_a-emyg-dtoa.o: mfluadir/otfcc/dep/extern/emyg-dtoa/emyg-dtoa.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluaotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluaotfcc_a_CFLAGS) $(CFLAGS) -MT mfluadir/otfcc/dep/extern/emyg-dtoa/libmfluaotfcc_a-emyg-dtoa.o -MD -MP -MF mfluadir/otfcc/dep/extern/emyg-dtoa/$(DEPDIR)/libmfluaotfcc_a-emyg-dtoa.Tpo -c -o mfluadir/otfcc/dep/extern/emyg-dtoa/libmfluaotfcc_a-emyg-dtoa.o `test -f 'mfluadir/otfcc/dep/extern/emyg-dtoa/emyg-dtoa.c' || echo '$(srcdir)/'`mfluadir/otfcc/dep/extern/emyg-dtoa/emyg-dtoa.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/otfcc/dep/extern/emyg-dtoa/$(DEPDIR)/libmfluaotfcc_a-emyg-dtoa.Tpo mfluadir/otfcc/dep/extern/emyg-dtoa/$(DEPDIR)/libmfluaotfcc_a-emyg-dtoa.Po
@@ -16150,6 +16275,76 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluaotfcc_a_CPPFLAGS) $(CPPFLAGS) $(libmfluaotfcc_a_CFLAGS) $(CFLAGS) -c -o mfluadir/otfcc/lib/table/libmfluaotfcc_a-TSI5.obj `if test -f 'mfluadir/otfcc/lib/table/TSI5.c'; then $(CYGPATH_W) 'mfluadir/otfcc/lib/table/TSI5.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/otfcc/lib/table/TSI5.c'; fi`
 
+mfluadir/potrace/libmfluapotrace_a-curve.o: mfluadir/potrace/curve.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-curve.o -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-curve.o `test -f 'mfluadir/potrace/curve.c' || echo '$(srcdir)/'`mfluadir/potrace/curve.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/curve.c' object='mfluadir/potrace/libmfluapotrace_a-curve.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-curve.o `test -f 'mfluadir/potrace/curve.c' || echo '$(srcdir)/'`mfluadir/potrace/curve.c
+
+mfluadir/potrace/libmfluapotrace_a-curve.obj: mfluadir/potrace/curve.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-curve.obj -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-curve.obj `if test -f 'mfluadir/potrace/curve.c'; then $(CYGPATH_W) 'mfluadir/potrace/curve.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/curve.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/curve.c' object='mfluadir/potrace/libmfluapotrace_a-curve.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-curve.obj `if test -f 'mfluadir/potrace/curve.c'; then $(CYGPATH_W) 'mfluadir/potrace/curve.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/curve.c'; fi`
+
+mfluadir/potrace/libmfluapotrace_a-decompose.o: mfluadir/potrace/decompose.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-decompose.o -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-decompose.o `test -f 'mfluadir/potrace/decompose.c' || echo '$(srcdir)/'`mfluadir/potrace/decompose.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/decompose.c' object='mfluadir/potrace/libmfluapotrace_a-decompose.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-decompose.o `test -f 'mfluadir/potrace/decompose.c' || echo '$(srcdir)/'`mfluadir/potrace/decompose.c
+
+mfluadir/potrace/libmfluapotrace_a-decompose.obj: mfluadir/potrace/decompose.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-decompose.obj -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-decompose.obj `if test -f 'mfluadir/potrace/decompose.c'; then $(CYGPATH_W) 'mfluadir/potrace/decompose.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/decompose.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/decompose.c' object='mfluadir/potrace/libmfluapotrace_a-decompose.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-decompose.obj `if test -f 'mfluadir/potrace/decompose.c'; then $(CYGPATH_W) 'mfluadir/potrace/decompose.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/decompose.c'; fi`
+
+mfluadir/potrace/libmfluapotrace_a-luafunc.o: mfluadir/potrace/luafunc.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-luafunc.o -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-luafunc.o `test -f 'mfluadir/potrace/luafunc.c' || echo '$(srcdir)/'`mfluadir/potrace/luafunc.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/luafunc.c' object='mfluadir/potrace/libmfluapotrace_a-luafunc.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-luafunc.o `test -f 'mfluadir/potrace/luafunc.c' || echo '$(srcdir)/'`mfluadir/potrace/luafunc.c
+
+mfluadir/potrace/libmfluapotrace_a-luafunc.obj: mfluadir/potrace/luafunc.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-luafunc.obj -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-luafunc.obj `if test -f 'mfluadir/potrace/luafunc.c'; then $(CYGPATH_W) 'mfluadir/potrace/luafunc.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/luafunc.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/luafunc.c' object='mfluadir/potrace/libmfluapotrace_a-luafunc.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-luafunc.obj `if test -f 'mfluadir/potrace/luafunc.c'; then $(CYGPATH_W) 'mfluadir/potrace/luafunc.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/luafunc.c'; fi`
+
+mfluadir/potrace/libmfluapotrace_a-potracelib.o: mfluadir/potrace/potracelib.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-potracelib.o -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-potracelib.o `test -f 'mfluadir/potrace/potracelib.c' || echo '$(srcdir)/'`mfluadir/potrace/potracelib.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/potracelib.c' object='mfluadir/potrace/libmfluapotrace_a-potracelib.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-potracelib.o `test -f 'mfluadir/potrace/potracelib.c' || echo '$(srcdir)/'`mfluadir/potrace/potracelib.c
+
+mfluadir/potrace/libmfluapotrace_a-potracelib.obj: mfluadir/potrace/potracelib.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-potracelib.obj -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-potracelib.obj `if test -f 'mfluadir/potrace/potracelib.c'; then $(CYGPATH_W) 'mfluadir/potrace/potracelib.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/potracelib.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/potracelib.c' object='mfluadir/potrace/libmfluapotrace_a-potracelib.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-potracelib.obj `if test -f 'mfluadir/potrace/potracelib.c'; then $(CYGPATH_W) 'mfluadir/potrace/potracelib.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/potracelib.c'; fi`
+
+mfluadir/potrace/libmfluapotrace_a-trace.o: mfluadir/potrace/trace.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-trace.o -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-trace.o `test -f 'mfluadir/potrace/trace.c' || echo '$(srcdir)/'`mfluadir/potrace/trace.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/trace.c' object='mfluadir/potrace/libmfluapotrace_a-trace.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-trace.o `test -f 'mfluadir/potrace/trace.c' || echo '$(srcdir)/'`mfluadir/potrace/trace.c
+
+mfluadir/potrace/libmfluapotrace_a-trace.obj: mfluadir/potrace/trace.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -MT mfluadir/potrace/libmfluapotrace_a-trace.obj -MD -MP -MF mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Tpo -c -o mfluadir/potrace/libmfluapotrace_a-trace.obj `if test -f 'mfluadir/potrace/trace.c'; then $(CYGPATH_W) 'mfluadir/potrace/trace.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/trace.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Tpo mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mfluadir/potrace/trace.c' object='mfluadir/potrace/libmfluapotrace_a-trace.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmfluapotrace_a_CPPFLAGS) $(CPPFLAGS) $(libmfluapotrace_a_CFLAGS) $(CFLAGS) -c -o mfluadir/potrace/libmfluapotrace_a-trace.obj `if test -f 'mfluadir/potrace/trace.c'; then $(CYGPATH_W) 'mfluadir/potrace/trace.c'; else $(CYGPATH_W) '$(srcdir)/mfluadir/potrace/trace.c'; fi`
+
 libmplibbackends_a-pngout.o: pngout.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmplibbackends_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmplibbackends_a-pngout.o -MD -MP -MF $(DEPDIR)/libmplibbackends_a-pngout.Tpo -c -o libmplibbackends_a-pngout.o `test -f 'pngout.c' || echo '$(srcdir)/'`pngout.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libmplibbackends_a-pngout.Tpo $(DEPDIR)/libmplibbackends_a-pngout.Po
@@ -19707,6 +19902,8 @@
 	-rm -f luatexdir/utils/$(am__dirstamp)
 	-rm -f mfluadir/$(DEPDIR)/$(am__dirstamp)
 	-rm -f mfluadir/$(am__dirstamp)
+	-rm -f mfluadir/luapeg/$(DEPDIR)/$(am__dirstamp)
+	-rm -f mfluadir/luapeg/$(am__dirstamp)
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/$(am__dirstamp)
 	-rm -f mfluadir/otfcc/dep/extern/$(am__dirstamp)
 	-rm -f mfluadir/otfcc/dep/extern/emyg-dtoa/$(DEPDIR)/$(am__dirstamp)
@@ -19765,6 +19962,8 @@
 	-rm -f mfluadir/otfcc/lib/vf/$(am__dirstamp)
 	-rm -f mfluadir/otfcc/src/$(DEPDIR)/$(am__dirstamp)
 	-rm -f mfluadir/otfcc/src/$(am__dirstamp)
+	-rm -f mfluadir/potrace/$(DEPDIR)/$(am__dirstamp)
+	-rm -f mfluadir/potrace/$(am__dirstamp)
 	-rm -f mfluajitdir/$(DEPDIR)/$(am__dirstamp)
 	-rm -f mfluajitdir/$(am__dirstamp)
 	-rm -f mplibdir/$(DEPDIR)/$(am__dirstamp)
@@ -19856,7 +20055,6 @@
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajit-pool.Po
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajit0.Po
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajitini.Po
-	-rm -f ./$(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po
 	-rm -f ./$(DEPDIR)/libmplibbackends_a-pngout.Po
 	-rm -f ./$(DEPDIR)/libmplibbackends_a-svgout.Po
 	-rm -f ./$(DEPDIR)/libmplibcore_a-mp.Po
@@ -20334,6 +20532,8 @@
 	-rm -f mfluadir/$(DEPDIR)/libmfluajit_a-mfluac.Po
 	-rm -f mfluadir/$(DEPDIR)/mflua-mfluaextra.Po
 	-rm -f mfluadir/$(DEPDIR)/mflua_nowin-mfluaextra.Po
+	-rm -f mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po
+	-rm -f mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json-builder.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-sds.Po
@@ -20450,6 +20650,11 @@
 	-rm -f mfluadir/otfcc/lib/vf/$(DEPDIR)/libmfluaotfcc_a-vq.Po
 	-rm -f mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-luafunc.Po
 	-rm -f mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-otfccdll.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po
 	-rm -f mfluajitdir/$(DEPDIR)/mfluajit-mfluajitextra.Po
 	-rm -f mfluajitdir/$(DEPDIR)/mfluajit_nowin-mfluajitextra.Po
 	-rm -f mplibdir/$(DEPDIR)/libmputil_a-avl.Po
@@ -20638,7 +20843,6 @@
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajit-pool.Po
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajit0.Po
 	-rm -f ./$(DEPDIR)/libmfluajit_a-mfluajitini.Po
-	-rm -f ./$(DEPDIR)/libmfluajitotfcc_a-libmfluajitotfcc.Po
 	-rm -f ./$(DEPDIR)/libmplibbackends_a-pngout.Po
 	-rm -f ./$(DEPDIR)/libmplibbackends_a-svgout.Po
 	-rm -f ./$(DEPDIR)/libmplibcore_a-mp.Po
@@ -21116,6 +21320,8 @@
 	-rm -f mfluadir/$(DEPDIR)/libmfluajit_a-mfluac.Po
 	-rm -f mfluadir/$(DEPDIR)/mflua-mfluaextra.Po
 	-rm -f mfluadir/$(DEPDIR)/mflua_nowin-mfluaextra.Po
+	-rm -f mfluadir/luapeg/$(DEPDIR)/libmfluajitlpeg_a-lpeg.Po
+	-rm -f mfluadir/luapeg/$(DEPDIR)/libmflualpeg_a-lpeg.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json-builder.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-json.Po
 	-rm -f mfluadir/otfcc/dep/extern/$(DEPDIR)/libmfluaotfcc_a-sds.Po
@@ -21232,6 +21438,11 @@
 	-rm -f mfluadir/otfcc/lib/vf/$(DEPDIR)/libmfluaotfcc_a-vq.Po
 	-rm -f mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-luafunc.Po
 	-rm -f mfluadir/otfcc/src/$(DEPDIR)/libmfluaotfcc_a-otfccdll.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-curve.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-decompose.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-luafunc.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-potracelib.Po
+	-rm -f mfluadir/potrace/$(DEPDIR)/libmfluapotrace_a-trace.Po
 	-rm -f mfluajitdir/$(DEPDIR)/mfluajit-mfluajitextra.Po
 	-rm -f mfluajitdir/$(DEPDIR)/mfluajit_nowin-mfluajitextra.Po
 	-rm -f mplibdir/$(DEPDIR)/libmputil_a-avl.Po
@@ -21688,9 +21899,9 @@
 
 # Tangling MFLua
 mflua.p mflua.pool: mflua-tangle
-	$(texmf_tangle) mflua mflua
+	@$(texmf_tangle) mflua mflua
 mflua-tangle: tangle$(EXEEXT) mflua.web mflua.ch tangle-sh
-	$(texmf_tangle) mflua mflua
+	@$(texmf_tangle) mflua mflua
 
 # Extract mflua version
 $(srcdir)/mfluadir/mflua_version.h: @MAINTAINER_MODE_TRUE@ mfluadir/mf-lua.ch
@@ -21712,18 +21923,18 @@
 mfluatrap-clean:
 	rm -rf mfluatrapdir
 
-# (end of mflua.am)
-
 #libmfluaotfcc_a_DEPENDENCIES = $(ZLIB_DEPEND)
-#libmfluajitotfcc_a_DEPENDENCIES = $(ZLIB_DEPEND)
 
 $(libmfluaotfcc_a_OBJECTS): $(LUA_DEPEND)
-$(libmfluajitotfcc_a_OBJECTS): $(LUAJIT_DEPEND)
 
 #EXTRA_DIST +=
 
 #EXTRA_DIST += 
 
+$(libmfluapotrace_a_OBJECTS): $(LUA_DEPEND)
+
+$(libmflualpeg_a_OBJECTS): $(LUA_DEPEND)
+
 .PHONY: install-mfluajit-links uninstall-mfluajit-links
 @WIN32_TRUE at install-mfluajit-links: call_mfluajit$(EXEEXT)
 @MFLUAJITN_FALSE@@WIN32_TRUE@	$(INSTALL_PROGRAM) call_mfluajit$(EXEEXT) $(DESTDIR)$(bindir)/mfluajit-nowin$(EXEEXT)
@@ -21746,9 +21957,9 @@
 
 # Tangling MFLuaJIT
 mfluajit.p mfluajit.pool: mfluajit-tangle
-	$(texmf_tangle) mfluajit mfluajit
+	@$(texmf_tangle) mfluajit mfluajit
 mfluajit-tangle: tangle$(EXEEXT) mfluajit.web mfluajit.ch tangle-sh
-	$(texmf_tangle) mfluajit mfluajit
+	@$(texmf_tangle) mfluajit mfluajit
 
 # Generate mfluajit.web
 mfluajit.web: tie$(EXEEXT) $(mfluajit_web_srcs)
@@ -21765,7 +21976,7 @@
 mfluajittrap-clean:
 	rm -rf mfluajittrapdir
 
-# (end of mfluajit.am)
+$(libmfluajitlpeg_a_OBJECTS): $(LUA_DEPEND)
 
 .PHONY: install-mpost-links uninstall-mpost-links
 @WIN32_TRUE at install-mpost-links: call_mpost$(EXEEXT)

Modified: trunk/Build/source/texk/web2c/mfluadir/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/ChangeLog	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/ChangeLog	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,7 +1,7 @@
-2022-01-10  Karl Berry  <karl at freefriends.org>
+2021-01-18 Luigi Scarso <luigi.scarso at gmail.com>
+	
+	* Embedding of  potrace and lpeg.
 
-	* am/mflua.am: do not silence tangle-sh.
-
 2021-03-15 Luigi Scarso <luigi.scarso at gmail.com>
 	
 	* Code clean up (thanks to  A. Kakuto)

Modified: trunk/Build/source/texk/web2c/mfluadir/am/mflua.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/am/mflua.am	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/am/mflua.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,7 +1,6 @@
-## $Id$
 ## texk/web2c/mfluadir/am/mflua.am: Makefile fragment for MFLua.
 ##
-## Copyright 2016-2022 Karl Berry <tex-live at tug.org>
+## Copyright 2016 Karl Berry <tex-live at tug.org>
 ## Copyright 2015 Peter Breitenlohner <tex-live at tug.org>
 ## You may freely use, modify and/or distribute this file.
 
@@ -43,11 +42,11 @@
 
 dist_mflua_SOURCES = mfluadir/mfluaextra.c mfluadir/mfluaextra.h mfluadir/mflua_version.h
 mflua_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(LUA_INCLUDES)
-mflua_LDADD = libmflua.a libmfluaotfcc.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUA_LIBS)
+mflua_LDADD = libmflua.a libmfluaotfcc.a libmfluapotrace.a libmflualpeg.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUA_LIBS)
 mflua_LDFLAGS = -export-dynamic
 nodist_mflua_nowin_SOURCES = $(dist_mflua_SOURCES)
 mflua_nowin_CPPFLAGS = $(mflua_CPPFLAGS) -DMFNOWIN $(LUA_INCLUDES)
-mflua_nowin_LDADD = libmflua.a libmfluaotfcc.a $(LDADD) $(windowlib) $(LUA_LIBS)
+mflua_nowin_LDADD = libmflua.a libmfluaotfcc.a libmfluapotrace.a libmflualpeg.a $(LDADD) $(windowlib) $(LUA_LIBS)
 mflua_nowin_LDFLAGS = -export-dynamic
 
 # We must create mfluad.h and mfluadir/mflua_version.h before compiling mfluaextra.c.
@@ -56,7 +55,7 @@
 ## mflua and mflua-nowin compile mfluaextra.c with different CPPFLAGS.
 ## Automake, however, does not support CPPFLAGS for individual source files.
 ## To avoid compiling everything twice, the common objects are in a library.
-EXTRA_LIBRARIES += libmflua.a libmfluaotfcc.a 
+EXTRA_LIBRARIES += libmflua.a libmfluaotfcc.a libmfluapotrace.a libmflualpeg.a
 
 # MFLua C sources
 mflua_c_h = mfluaini.c mflua0.c mfluacoerce.h mfluad.h
@@ -77,9 +76,9 @@
 
 # Tangling MFLua
 mflua.p mflua.pool: mflua-tangle
-	$(texmf_tangle) mflua mflua
+	@$(texmf_tangle) mflua mflua
 mflua-tangle: tangle$(EXEEXT) mflua.web mflua.ch tangle-sh
-	$(texmf_tangle) mflua mflua
+	@$(texmf_tangle) mflua mflua
 
 # Extract mflua version
 $(srcdir)/mfluadir/mflua_version.h: @MAINTAINER_MODE_TRUE@ mfluadir/mf-lua.ch
@@ -137,5 +136,3 @@
 	mfluadir/mfluatrap/mflua_ttx_backend.lua \
 	mfluadir/mfluatrap/texmf.cnf \
 	mfluadir/mfluatrap/mfluatrap.diffs
-
-# (end of mflua.am)

Added: trunk/Build/source/texk/web2c/mfluadir/am/mflualpeg.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/am/mflualpeg.am	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/am/mflualpeg.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,25 @@
+## texk/web2c/mfluadir/am/mflualpeg.am: Makefile fragment for libmflualpeg.
+##
+## Copyright (C) 2022 Luigi Scarso <tex-live at tug.org>
+## You may freely use, modify and/or distribute this file.
+
+## mflualpeg
+##
+EXTRA_LIBRARIES += libmflualpeg.a
+
+$(libmflualpeg_a_OBJECTS): $(LUA_DEPEND)
+
+libmflualpeg_a_CPPFLAGS = \
+	-I$(top_srcdir)/mfluadir/luapeg \
+	$(LUA_INCLUDES)
+
+
+libmflualpeg_a_CFLAGS = # $(WARNING_CFLAGS)
+
+
+libmflualpeg_a_SOURCES = \
+	mfluadir/luapeg/lpeg.c \
+	mfluadir/luapeg/lpeg.h 
+
+
+

Modified: trunk/Build/source/texk/web2c/mfluadir/am/mfluaotfcc.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/am/mfluaotfcc.am	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/am/mfluaotfcc.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -5,35 +5,24 @@
 
 ## mfluaotfcc
 ##
-EXTRA_LIBRARIES += libmfluaotfcc.a libmfluajitotfcc.a
+EXTRA_LIBRARIES += libmfluaotfcc.a 
 
 #libmfluaotfcc_a_DEPENDENCIES = $(ZLIB_DEPEND)
-#libmfluajitotfcc_a_DEPENDENCIES = $(ZLIB_DEPEND)
 
 $(libmfluaotfcc_a_OBJECTS): $(LUA_DEPEND)
-$(libmfluajitotfcc_a_OBJECTS): $(LUAJIT_DEPEND)
 
 libmfluaotfcc_a_CPPFLAGS = \
 	-std=c99 -D_CARYLL_USE_PRE_SERIALIZED -DMAIN_VER=0 -DSECONDARY_VER=10 -DPATCH_VER=4 \
 	-I$(top_srcdir)/mfluadir/otfcc/include \
 	-I$(top_srcdir)/mfluadir/otfcc/include/dep \
-	-I$(top_srcdir)/mfluadir/otfcc/lib \
-	 $(LUA_INCLUDES)
+	-I$(top_srcdir)/mfluadir/otfcc/lib 
+##	 $(LUA_INCLUDES)
 
 
-libmfluajitotfcc_a_CPPFLAGS = \
-	-std=c99 -D_CARYLL_USE_PRE_SERIALIZED -DMAIN_VER=0 -DSECONDARY_VER=10 -DPATCH_VER=4 \
-	-DJIT \
-	-I$(top_srcdir)/mfluadir/otfcc/include \
-	-I$(top_srcdir)/mfluadir/otfcc/include/dep \
-	-I$(top_srcdir)/mfluadir/otfcc/lib \
-	$(LUAJIT_INCLUDES)
 
 libmfluaotfcc_a_CFLAGS = # $(WARNING_CFLAGS)
-libmfluajitotfcc_a_CFLAGS = # $(WARNING_CFLAGS)
 
 #nodist_libmfluaotfcc_a_SOURCES = $(libmfluaotfcc_sources)
-#nodist_libmfluajitotfcc_a_SOURCES = $(libmfluaotfcc_sources)
 
 libmfluaotfcc_a_SOURCES = \
 	mfluadir/otfcc/dep/extern/sdsalloc.h \

Added: trunk/Build/source/texk/web2c/mfluadir/am/mfluapotrace.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/am/mfluapotrace.am	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/am/mfluapotrace.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,39 @@
+## texk/web2c/luatexdir/am/mfluapotrace.am: Makefile fragment for libmfluapotrace.
+##
+## Copyright (C) 2022 Luigi Scarso <tex-live at tug.org>
+## You may freely use, modify and/or distribute this file.
+
+## mfluapotrace
+##
+EXTRA_LIBRARIES += libmfluapotrace.a 
+
+$(libmfluapotrace_a_OBJECTS): $(LUA_DEPEND)
+
+libmfluapotrace_a_CPPFLAGS = \
+        -I$(top_srcdir)/mfluadir/potrace 
+##         $(LUA_INCLUDES)
+
+
+
+libmfluapotrace_a_CFLAGS = # $(WARNING_CFLAGS)
+
+#nodist_libmfluapotrace_a_SOURCES = $(libmfluapotrace_sources)
+
+libmfluapotrace_a_SOURCES = \
+	mfluadir/potrace/auxiliary.h \
+	mfluadir/potrace/bitmap.h \
+	mfluadir/potrace/config.h \
+	mfluadir/potrace/curve.c \
+	mfluadir/potrace/curve.h \
+	mfluadir/potrace/decompose.c \
+	mfluadir/potrace/decompose.h \
+	mfluadir/potrace/lists.h \
+	mfluadir/potrace/luafunc.c \
+	mfluadir/potrace/luafunc.h \
+	mfluadir/potrace/potracelib.c \
+	mfluadir/potrace/potracelib.h \
+	mfluadir/potrace/progress.h \
+	mfluadir/potrace/trace.c \
+	mfluadir/potrace/trace.h
+
+

Added: trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,3507 @@
+#include "lpeg.h"
+
+/*
+** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $
+** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+*/
+
+/* #include <ctype.h> */
+/* #include <limits.h> */
+/* #include <stdio.h> */
+
+
+/* #include "lptypes.h" */
+/* #include "lpprint.h" */
+/* #include "lpcode.h" */
+
+
+#if defined(LPEG_DEBUG)
+
+/*
+** {======================================================
+** Printing patterns (for debugging)
+** =======================================================
+*/
+
+
+void printcharset (const byte *st) {
+  int i;
+  printf("[");
+  for (i = 0; i <= UCHAR_MAX; i++) {
+    int first = i;
+    while (testchar(st, i) && i <= UCHAR_MAX) i++;
+    if (i - 1 == first)  /* unary range? */
+      printf("(%02x)", first);
+    else if (i - 1 > first)  /* non-empty range? */
+      printf("(%02x-%02x)", first, i - 1);
+  }
+  printf("]");
+}
+
+
+static const char *capkind (int kind) {
+  const char *const modes[] = {
+    "close", "position", "constant", "backref",
+    "argument", "simple", "table", "function",
+    "query", "string", "num", "substitution", "fold",
+    "runtime", "group"};
+  return modes[kind];
+}
+
+
+static void printjmp (const Instruction *op, const Instruction *p) {
+  printf("-> %d", (int)(p + (p + 1)->offset - op));
+}
+
+
+void printinst (const Instruction *op, const Instruction *p) {
+  const char *const names[] = {
+    "any", "char", "set",
+    "testany", "testchar", "testset",
+    "span", "behind",
+    "ret", "end",
+    "choice", "jmp", "call", "open_call",
+    "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup",
+     "fullcapture", "opencapture", "closecapture", "closeruntime"
+  };
+  printf("%02ld: %s ", (long)(p - op), names[p->i.code]);
+  switch ((Opcode)p->i.code) {
+    case IChar: {
+      printf("'%c'", p->i.aux);
+      break;
+    }
+    case ITestChar: {
+      printf("'%c'", p->i.aux); printjmp(op, p);
+      break;
+    }
+    case IFullCapture: {
+      printf("%s (size = %d)  (idx = %d)",
+             capkind(getkind(p)), getoff(p), p->i.key);
+      break;
+    }
+    case IOpenCapture: {
+      printf("%s (idx = %d)", capkind(getkind(p)), p->i.key);
+      break;
+    }
+    case ISet: {
+      printcharset((p+1)->buff);
+      break;
+    }
+    case ITestSet: {
+      printcharset((p+2)->buff); printjmp(op, p);
+      break;
+    }
+    case ISpan: {
+      printcharset((p+1)->buff);
+      break;
+    }
+    case IOpenCall: {
+      printf("-> %d", (p + 1)->offset);
+      break;
+    }
+    case IBehind: {
+      printf("%d", p->i.aux);
+      break;
+    }
+    case IJmp: case ICall: case ICommit: case IChoice:
+    case IPartialCommit: case IBackCommit: case ITestAny: {
+      printjmp(op, p);
+      break;
+    }
+    default: break;
+  }
+  printf("\n");
+}
+
+
+void printpatt (Instruction *p, int n) {
+  Instruction *op = p;
+  while (p < op + n) {
+    printinst(op, p);
+    p += sizei(p);
+  }
+}
+
+
+#if defined(LPEG_DEBUG)
+static void printcap (Capture *cap) {
+  printf("%s (idx: %d - size: %d) -> %p\n",
+         capkind(cap->kind), cap->idx, cap->siz, cap->s);
+}
+
+
+void printcaplist (Capture *cap, Capture *limit) {
+  printf(">======\n");
+  for (; cap->s && (limit == NULL || cap < limit); cap++)
+    printcap(cap);
+  printf("=======\n");
+}
+#endif
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** Printing trees (for debugging)
+** =======================================================
+*/
+
+static const char *tagnames[] = {
+  "char", "set", "any",
+  "true", "false",
+  "rep",
+  "seq", "choice",
+  "not", "and",
+  "call", "opencall", "rule", "grammar",
+  "behind",
+  "capture", "run-time"
+};
+
+
+void printtree (TTree *tree, int ident) {
+  int i;
+  for (i = 0; i < ident; i++) printf(" ");
+  printf("%s", tagnames[tree->tag]);
+  switch (tree->tag) {
+    case TChar: {
+      int c = tree->u.n;
+      if (isprint(c))
+        printf(" '%c'\n", c);
+      else
+        printf(" (%02X)\n", c);
+      break;
+    }
+    case TSet: {
+      printcharset(treebuffer(tree));
+      printf("\n");
+      break;
+    }
+    case TOpenCall: case TCall: {
+      assert(sib2(tree)->tag == TRule);
+      printf(" key: %d  (rule: %d)\n", tree->key, sib2(tree)->cap);
+      break;
+    }
+    case TBehind: {
+      printf(" %d\n", tree->u.n);
+        printtree(sib1(tree), ident + 2);
+      break;
+    }
+    case TCapture: {
+      printf(" kind: '%s'  key: %d\n", capkind(tree->cap), tree->key);
+      printtree(sib1(tree), ident + 2);
+      break;
+    }
+    case TRule: {
+      printf(" n: %d  key: %d\n", tree->cap, tree->key);
+      printtree(sib1(tree), ident + 2);
+      break;  /* do not print next rule as a sibling */
+    }
+    case TGrammar: {
+      TTree *rule = sib1(tree);
+      printf(" %d\n", tree->u.n);  /* number of rules */
+      for (i = 0; i < tree->u.n; i++) {
+        printtree(rule, ident + 2);
+        rule = sib2(rule);
+      }
+      assert(rule->tag == TTrue);  /* sentinel */
+      break;
+    }
+    default: {
+      int sibs = numsiblings[tree->tag];
+      printf("\n");
+      if (sibs >= 1) {
+        printtree(sib1(tree), ident + 2);
+        if (sibs >= 2)
+          printtree(sib2(tree), ident + 2);
+      }
+      break;
+    }
+  }
+}
+
+
+void printktable (lua_State *L, int idx) {
+  int n, i;
+  lua_getuservalue(L, idx);
+  if (lua_isnil(L, -1))  /* no ktable? */
+    return;
+  n = lua_rawlen(L, -1);
+  printf("[");
+  for (i = 1; i <= n; i++) {
+    printf("%d = ", i);
+    lua_rawgeti(L, -1, i);
+    if (lua_isstring(L, -1))
+      printf("%s  ", lua_tostring(L, -1));
+    else
+      printf("%s  ", lua_typename(L, lua_type(L, -1)));
+    lua_pop(L, 1);
+  }
+  printf("]\n");
+  /* leave ktable at the stack */
+}
+
+/* }====================================================== */
+
+#endif
+/*
+** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $
+** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+*/
+
+/* #include <limits.h> */
+/* #include <string.h> */
+
+
+/* #include "lua.h" */
+/* #include "lauxlib.h" */
+
+/* #include "lpcap.h" */
+/* #include "lptypes.h" */
+/* #include "lpvm.h" */
+/* #include "lpprint.h" */
+
+
+/* initial size for call/backtrack stack */
+#if !defined(INITBACK)
+#define INITBACK	MAXBACK
+#endif
+
+
+#define getoffset(p)	(((p) + 1)->offset)
+
+static const Instruction giveup = {{IGiveup, 0, 0}};
+
+
+/*
+** {======================================================
+** Virtual Machine
+** =======================================================
+*/
+
+
+typedef struct Stack {
+  const char *s;  /* saved position (or NULL for calls) */
+  const Instruction *p;  /* next instruction */
+  int caplevel;
+} Stack;
+
+
+#define getstackbase(L, ptop)	((Stack *)lua_touserdata(L, stackidx(ptop)))
+
+
+/*
+** Make the size of the array of captures 'cap' twice as large as needed
+** (which is 'captop'). ('n' is the number of new elements.)
+*/
+static Capture *doublecap (lua_State *L, Capture *cap, int captop,
+                                         int n, int ptop) {
+  Capture *newc;
+  if (captop >= INT_MAX/((int)sizeof(Capture) * 2))
+    luaL_error(L, "too many captures");
+  newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture));
+  memcpy(newc, cap, (captop - n) * sizeof(Capture));
+  lua_replace(L, caplistidx(ptop));
+  return newc;
+}
+
+
+/*
+** Double the size of the stack
+*/
+static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {
+  Stack *stack = getstackbase(L, ptop);
+  Stack *newstack;
+  int n = *stacklimit - stack;  /* current stack size */
+  int max, newn;
+  lua_getfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
+  max = lua_tointeger(L, -1);  /* maximum allowed size */
+  lua_pop(L, 1);
+  if (n >= max)  /* already at maximum size? */
+    luaL_error(L, "backtrack stack overflow (current limit is %d)", max);
+  newn = 2 * n;  /* new size */
+  if (newn > max) newn = max;
+  newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));
+  memcpy(newstack, stack, n * sizeof(Stack));
+  lua_replace(L, stackidx(ptop));
+  *stacklimit = newstack + newn;
+  return newstack + n;  /* return next position */
+}
+
+
+/*
+** Interpret the result of a dynamic capture: false -> fail;
+** true -> keep current position; number -> next position.
+** Return new subject position. 'fr' is stack index where
+** is the result; 'curr' is current subject position; 'limit'
+** is subject's size.
+*/
+static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
+  lua_Integer res;
+  if (!lua_toboolean(L, fr)) {  /* false value? */
+    lua_settop(L, fr - 1);  /* remove results */
+    return -1;  /* and fail */
+  }
+  else if (lua_isboolean(L, fr))  /* true? */
+    res = curr;  /* keep current position */
+  else {
+    res = lua_tointeger(L, fr) - 1;  /* new position */
+    if (res < curr || res > limit)
+      luaL_error(L, "invalid position returned by match-time capture");
+  }
+  lua_remove(L, fr);  /* remove first result (offset) */
+  return res;
+}
+
+
+/*
+** Add capture values returned by a dynamic capture to the capture list
+** 'base', nested inside a group capture. 'fd' indexes the first capture
+** value, 'n' is the number of values (at least 1).
+*/
+static void adddyncaptures (const char *s, Capture *base, int n, int fd) {
+  int i;
+  base[0].kind = Cgroup;  /* create group capture */
+  base[0].siz = 0;
+  base[0].idx = 0;  /* make it an anonymous group */
+  for (i = 1; i <= n; i++) {  /* add runtime captures */
+    base[i].kind = Cruntime;
+    base[i].siz = 1;  /* mark it as closed */
+    base[i].idx = fd + i - 1;  /* stack index of capture value */
+    base[i].s = s;
+  }
+  base[i].kind = Cclose;  /* close group */
+  base[i].siz = 1;
+  base[i].s = s;
+}
+
+
+/*
+** Remove dynamic captures from the Lua stack (called in case of failure)
+*/
+static int removedyncap (lua_State *L, Capture *capture,
+                         int level, int last) {
+  int id = finddyncap(capture + level, capture + last);  /* index of 1st cap. */
+  int top = lua_gettop(L);
+  if (id == 0) return 0;  /* no dynamic captures? */
+  lua_settop(L, id - 1);  /* remove captures */
+  return top - id + 1;  /* number of values removed */
+}
+
+
+/*
+** Opcode interpreter luajit aarch64
+*/
+/* luajit aarch64  */
+/* https://github.com/LuaJIT/LuaJIT/pull/230#issuecomment-260205661 */
+/* We play safe on arm64  assuming a virtual address bits VA_BITS >47,*/
+/* even if a  Linux kernel  can be configured with VA_BITS < 47 */
+/* and lightuserdata is ok then.  Anyway, */
+/* replacing lightuserdata with full userdata seems ok wrt performance. */
+/* No need to free a userdata, it's GC */
+const char *match (lua_State *L, const char *o, const char *s, const char *e,
+                   Instruction *op, Capture *capture, int ptop) {
+#if defined(__aarch64__) && defined(MFLuaJIT) 
+  Stack *stackbase = (Stack*)lua_newuserdata(L,sizeof(Stack)*INITBACK);
+  Stack *stacklimit = stackbase + INITBACK;
+  Stack *stack = stackbase;  /* point to first empty slot in stack */
+  int capsize = INITCAPSIZE;
+  int captop = 0;  /* point to first empty slot in captures */
+  int ndyncap = 0;  /* number of dynamic captures (in Lua stack) */
+  const Instruction *p = op;  /* current instruction */
+  stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;
+#else
+  Stack stackbase[INITBACK];
+  Stack *stacklimit = stackbase + INITBACK;
+  Stack *stack = stackbase;  /* point to first empty slot in stack */
+  int capsize = INITCAPSIZE;
+  int captop = 0;  /* point to first empty slot in captures */
+  int ndyncap = 0;  /* number of dynamic captures (in Lua stack) */
+  const Instruction *p = op;  /* current instruction */
+  stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;
+  lua_pushlightuserdata(L, stackbase);
+#endif  
+  for (;;) {
+#if defined(DEBUG)
+      printf("-------------------------------------\n");
+      printcaplist(capture, capture + captop);
+      printf("s: |%s| stck:%d, dyncaps:%d, caps:%d  ",
+             s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop);
+      printinst(op, p);
+#endif
+    assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
+    switch ((Opcode)p->i.code) {
+      case IEnd: {
+        assert(stack == getstackbase(L, ptop) + 1);
+        capture[captop].kind = Cclose;
+        capture[captop].s = NULL;
+        return s;
+      }
+      case IGiveup: {
+        assert(stack == getstackbase(L, ptop));
+        return NULL;
+      }
+      case IRet: {
+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s == NULL);
+        p = (--stack)->p;
+        continue;
+      }
+      case IAny: {
+        if (s < e) { p++; s++; }
+        else goto fail;
+        continue;
+      }
+      case ITestAny: {
+        if (s < e) p += 2;
+        else p += getoffset(p);
+        continue;
+      }
+      case IChar: {
+        if ((byte)*s == p->i.aux && s < e) { p++; s++; }
+        else goto fail;
+        continue;
+      }
+      case ITestChar: {
+        if ((byte)*s == p->i.aux && s < e) p += 2;
+        else p += getoffset(p);
+        continue;
+      }
+      case ISet: {
+        int c = (byte)*s;
+        if (testchar((p+1)->buff, c) && s < e)
+          { p += CHARSETINSTSIZE; s++; }
+        else goto fail;
+        continue;
+      }
+      case ITestSet: {
+        int c = (byte)*s;
+        if (testchar((p + 2)->buff, c) && s < e)
+          p += 1 + CHARSETINSTSIZE;
+        else p += getoffset(p);
+        continue;
+      }
+      case IBehind: {
+        int n = p->i.aux;
+        if (n > s - o) goto fail;
+        s -= n; p++;
+        continue;
+      }
+      case ISpan: {
+        for (; s < e; s++) {
+          int c = (byte)*s;
+          if (!testchar((p+1)->buff, c)) break;
+        }
+        p += CHARSETINSTSIZE;
+        continue;
+      }
+      case IJmp: {
+        p += getoffset(p);
+        continue;
+      }
+      case IChoice: {
+        if (stack == stacklimit)
+          stack = doublestack(L, &stacklimit, ptop);
+        stack->p = p + getoffset(p);
+        stack->s = s;
+        stack->caplevel = captop;
+        stack++;
+        p += 2;
+        continue;
+      }
+      case ICall: {
+        if (stack == stacklimit)
+          stack = doublestack(L, &stacklimit, ptop);
+        stack->s = NULL;
+        stack->p = p + 2;  /* save return address */
+        stack++;
+        p += getoffset(p);
+        continue;
+      }
+      case ICommit: {
+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
+        stack--;
+        p += getoffset(p);
+        continue;
+      }
+      case IPartialCommit: {
+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
+        (stack - 1)->s = s;
+        (stack - 1)->caplevel = captop;
+        p += getoffset(p);
+        continue;
+      }
+      case IBackCommit: {
+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
+        s = (--stack)->s;
+        captop = stack->caplevel;
+        p += getoffset(p);
+        continue;
+      }
+      case IFailTwice:
+        assert(stack > getstackbase(L, ptop));
+        stack--;
+        /* go through */
+      case IFail:
+      fail: { /* pattern failed: try to backtrack */
+        do {  /* remove pending calls */
+          assert(stack > getstackbase(L, ptop));
+          s = (--stack)->s;
+        } while (s == NULL);
+        if (ndyncap > 0)  /* is there matchtime captures? */
+          ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
+        captop = stack->caplevel;
+        p = stack->p;
+#if defined(DEBUG)
+        printf("**FAIL**\n");
+#endif
+        continue;
+      }
+      case ICloseRunTime: {
+        CapState cs;
+        int rem, res, n;
+        int fr = lua_gettop(L) + 1;  /* stack index of first result */
+        cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop;
+        n = runtimecap(&cs, capture + captop, s, &rem);  /* call function */
+        captop -= n;  /* remove nested captures */
+        ndyncap -= rem;  /* update number of dynamic captures */
+        fr -= rem;  /* 'rem' items were popped from Lua stack */
+        res = resdyncaptures(L, fr, s - o, e - o);  /* get result */
+        if (res == -1)  /* fail? */
+          goto fail;
+        s = o + res;  /* else update current position */
+        n = lua_gettop(L) - fr + 1;  /* number of new captures */
+        ndyncap += n;  /* update number of dynamic captures */
+        if (n > 0) {  /* any new capture? */
+          if (fr + n >= SHRT_MAX)
+            luaL_error(L, "too many results in match-time capture");
+          if ((captop += n + 2) >= capsize) {
+            capture = doublecap(L, capture, captop, n + 2, ptop);
+            capsize = 2 * captop;
+          }
+          /* add new captures to 'capture' list */
+          adddyncaptures(s, capture + captop - n - 2, n, fr); 
+        }
+        p++;
+        continue;
+      }
+      case ICloseCapture: {
+        const char *s1 = s;
+        assert(captop > 0);
+        /* if possible, turn capture into a full capture */
+        if (capture[captop - 1].siz == 0 &&
+            s1 - capture[captop - 1].s < UCHAR_MAX) {
+          capture[captop - 1].siz = s1 - capture[captop - 1].s + 1;
+          p++;
+          continue;
+        }
+        else {
+          capture[captop].siz = 1;  /* mark entry as closed */
+          capture[captop].s = s;
+          goto pushcapture;
+        }
+      }
+      case IOpenCapture:
+        capture[captop].siz = 0;  /* mark entry as open */
+        capture[captop].s = s;
+        goto pushcapture;
+      case IFullCapture:
+        capture[captop].siz = getoff(p) + 1;  /* save capture size */
+        capture[captop].s = s - getoff(p);
+        /* goto pushcapture; */
+      pushcapture: {
+        capture[captop].idx = p->i.key;
+        capture[captop].kind = getkind(p);
+        if (++captop >= capsize) {
+          capture = doublecap(L, capture, captop, 0, ptop);
+          capsize = 2 * captop;
+        }
+        p++;
+        continue;
+      }
+      default: assert(0); return NULL;
+    }
+  }
+}
+
+/* }====================================================== */
+
+
+/*
+** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $
+** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+*/
+
+/* #include <limits.h> */
+
+
+/* #include "lua.h" */
+/* #include "lauxlib.h" */
+
+/* #include "lptypes.h" */
+/* #include "lpcode.h" */
+
+
+/* signals a "no-instruction */
+#define NOINST		-1
+
+
+
+static const Charset fullset_ =
+  {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+
+static const Charset *fullset = &fullset_;
+
+/*
+** {======================================================
+** Analysis and some optimizations
+** =======================================================
+*/
+
+/*
+** Check whether a charset is empty (returns IFail), singleton (IChar),
+** full (IAny), or none of those (ISet). When singleton, '*c' returns
+** which character it is. (When generic set, the set was the input,
+** so there is no need to return it.)
+*/
+static Opcode charsettype (const byte *cs, int *c) {
+  int count = 0;  /* number of characters in the set */
+  int i;
+  int candidate = -1;  /* candidate position for the singleton char */
+  for (i = 0; i < CHARSETSIZE; i++) {  /* for each byte */
+    int b = cs[i];
+    if (b == 0) {  /* is byte empty? */
+      if (count > 1)  /* was set neither empty nor singleton? */
+        return ISet;  /* neither full nor empty nor singleton */
+      /* else set is still empty or singleton */
+    }
+    else if (b == 0xFF) {  /* is byte full? */
+      if (count < (i * BITSPERCHAR))  /* was set not full? */
+        return ISet;  /* neither full nor empty nor singleton */
+      else count += BITSPERCHAR;  /* set is still full */
+    }
+    else if ((b & (b - 1)) == 0) {  /* has byte only one bit? */
+      if (count > 0)  /* was set not empty? */
+        return ISet;  /* neither full nor empty nor singleton */
+      else {  /* set has only one char till now; track it */
+        count++;
+        candidate = i;
+      }
+    }
+    else return ISet;  /* byte is neither empty, full, nor singleton */
+  }
+  switch (count) {
+    case 0: return IFail;  /* empty set */
+    case 1: {  /* singleton; find character bit inside byte */
+      int b = cs[candidate];
+      *c = candidate * BITSPERCHAR;
+      if ((b & 0xF0) != 0) { *c += 4; b >>= 4; }
+      if ((b & 0x0C) != 0) { *c += 2; b >>= 2; }
+      if ((b & 0x02) != 0) { *c += 1; }
+      return IChar;
+    }
+    default: {
+       assert(count == CHARSETSIZE * BITSPERCHAR);  /* full set */
+       return IAny;
+    }
+  }
+}
+
+
+/*
+** A few basic operations on Charsets
+*/
+static void cs_complement (Charset *cs) {
+  loopset(i, cs->cs[i] = ~cs->cs[i]);
+}
+
+static int cs_equal (const byte *cs1, const byte *cs2) {
+  loopset(i, if (cs1[i] != cs2[i]) return 0);
+  return 1;
+}
+
+static int cs_disjoint (const Charset *cs1, const Charset *cs2) {
+  loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;)
+  return 1;
+}
+
+
+/*
+** If 'tree' is a 'char' pattern (TSet, TChar, TAny), convert it into a
+** charset and return 1; else return 0.
+*/
+int tocharset (TTree *tree, Charset *cs) {
+  switch (tree->tag) {
+    case TSet: {  /* copy set */
+      loopset(i, cs->cs[i] = treebuffer(tree)[i]);
+      return 1;
+    }
+    case TChar: {  /* only one char */
+      assert(0 <= tree->u.n && tree->u.n <= UCHAR_MAX);
+      loopset(i, cs->cs[i] = 0);  /* erase all chars */
+      setchar(cs->cs, tree->u.n);  /* add that one */
+      return 1;
+    }
+    case TAny: {
+      loopset(i, cs->cs[i] = 0xFF);  /* add all characters to the set */
+      return 1;
+    }
+    default: return 0;
+  }
+}
+
+
+/*
+** Visit a TCall node taking care to stop recursion. If node not yet
+** visited, return 'f(sib2(tree))', otherwise return 'def' (default
+** value)
+*/
+static int callrecursive (TTree *tree, int f (TTree *t), int def) {
+  int key = tree->key;
+  assert(tree->tag == TCall);
+  assert(sib2(tree)->tag == TRule);
+  if (key == 0)  /* node already visited? */
+    return def;  /* return default value */
+  else {  /* first visit */
+    int result;
+    tree->key = 0;  /* mark call as already visited */
+    result = f(sib2(tree));  /* go to called rule */
+    tree->key = key;  /* restore tree */
+    return result;
+  }
+}
+
+
+/*
+** Check whether a pattern tree has captures
+*/
+int hascaptures (TTree *tree) {
+ tailcall:
+  switch (tree->tag) {
+    case TCapture: case TRunTime:
+      return 1;
+    case TCall:
+      return callrecursive(tree, hascaptures, 0);
+    case TRule:  /* do not follow siblings */
+      tree = sib1(tree); goto tailcall;
+    case TOpenCall: assert(0);
+    default: {
+      switch (numsiblings[tree->tag]) {
+        case 1:  /* return hascaptures(sib1(tree)); */
+          tree = sib1(tree); goto tailcall;
+        case 2:
+          if (hascaptures(sib1(tree)))
+            return 1;
+          /* else return hascaptures(sib2(tree)); */
+          tree = sib2(tree); goto tailcall;
+        default: assert(numsiblings[tree->tag] == 0); return 0;
+      }
+    }
+  }
+}
+
+
+/*
+** Checks how a pattern behaves regarding the empty string,
+** in one of two different ways:
+** A pattern is *nullable* if it can match without consuming any character;
+** A pattern is *nofail* if it never fails for any string
+** (including the empty string).
+** The difference is only for predicates and run-time captures;
+** for other patterns, the two properties are equivalent.
+** (With predicates, &'a' is nullable but not nofail. Of course,
+** nofail => nullable.)
+** These functions are all convervative in the following way:
+**    p is nullable => nullable(p)
+**    nofail(p) => p cannot fail
+** The function assumes that TOpenCall is not nullable;
+** this will be checked again when the grammar is fixed.
+** Run-time captures can do whatever they want, so the result
+** is conservative.
+*/
+int checkaux (TTree *tree, int pred) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny:
+    case TFalse: case TOpenCall:
+      return 0;  /* not nullable */
+    case TRep: case TTrue:
+      return 1;  /* no fail */
+    case TNot: case TBehind:  /* can match empty, but can fail */
+      if (pred == PEnofail) return 0;
+      else return 1;  /* PEnullable */
+    case TAnd:  /* can match empty; fail iff body does */
+      if (pred == PEnullable) return 1;
+      /* else return checkaux(sib1(tree), pred); */
+      tree = sib1(tree); goto tailcall;
+    case TRunTime:  /* can fail; match empty iff body does */
+      if (pred == PEnofail) return 0;
+      /* else return checkaux(sib1(tree), pred); */
+      tree = sib1(tree); goto tailcall;
+    case TSeq:
+      if (!checkaux(sib1(tree), pred)) return 0;
+      /* else return checkaux(sib2(tree), pred); */
+      tree = sib2(tree); goto tailcall;
+    case TChoice:
+      if (checkaux(sib2(tree), pred)) return 1;
+      /* else return checkaux(sib1(tree), pred); */
+      tree = sib1(tree); goto tailcall;
+    case TCapture: case TGrammar: case TRule:
+      /* return checkaux(sib1(tree), pred); */
+      tree = sib1(tree); goto tailcall;
+    case TCall:  /* return checkaux(sib2(tree), pred); */
+      tree = sib2(tree); goto tailcall;
+    default: assert(0); return 0;
+  }
+}
+
+
+/*
+** number of characters to match a pattern (or -1 if variable)
+*/
+int fixedlen (TTree *tree) {
+  int len = 0;  /* to accumulate in tail calls */
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny:
+      return len + 1;
+    case TFalse: case TTrue: case TNot: case TAnd: case TBehind:
+      return len;
+    case TRep: case TRunTime: case TOpenCall:
+      return -1;
+    case TCapture: case TRule: case TGrammar:
+      /* return fixedlen(sib1(tree)); */
+      tree = sib1(tree); goto tailcall;
+    case TCall: {
+      int n1 = callrecursive(tree, fixedlen, -1);
+      if (n1 < 0)
+        return -1;
+      else
+        return len + n1;
+    }
+    case TSeq: {
+      int n1 = fixedlen(sib1(tree));
+      if (n1 < 0)
+        return -1;
+      /* else return fixedlen(sib2(tree)) + len; */
+      len += n1; tree = sib2(tree); goto tailcall;
+    }
+    case TChoice: {
+      int n1 = fixedlen(sib1(tree));
+      int n2 = fixedlen(sib2(tree));
+      if (n1 != n2 || n1 < 0)
+        return -1;
+      else
+        return len + n1;
+    }
+    default: assert(0); return 0;
+  };
+}
+
+
+/*
+** Computes the 'first set' of a pattern.
+** The result is a conservative aproximation:
+**   match p ax -> x (for some x) ==> a belongs to first(p)
+** or
+**   a not in first(p) ==> match p ax -> fail (for all x)
+**
+** The set 'follow' is the first set of what follows the
+** pattern (full set if nothing follows it).
+**
+** The function returns 0 when this resulting set can be used for
+** test instructions that avoid the pattern altogether.
+** A non-zero return can happen for two reasons:
+** 1) match p '' -> ''            ==> return has bit 1 set
+** (tests cannot be used because they would always fail for an empty input);
+** 2) there is a match-time capture ==> return has bit 2 set
+** (optimizations should not bypass match-time captures).
+*/
+static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny: {
+      tocharset(tree, firstset);
+      return 0;
+    }
+    case TTrue: {
+      loopset(i, firstset->cs[i] = follow->cs[i]);
+      return 1;  /* accepts the empty string */
+    }
+    case TFalse: {
+      loopset(i, firstset->cs[i] = 0);
+      return 0;
+    }
+    case TChoice: {
+      Charset csaux;
+      int e1 = getfirst(sib1(tree), follow, firstset);
+      int e2 = getfirst(sib2(tree), follow, &csaux);
+      loopset(i, firstset->cs[i] |= csaux.cs[i]);
+      return e1 | e2;
+    }
+    case TSeq: {
+      if (!nullable(sib1(tree))) {
+        /* when p1 is not nullable, p2 has nothing to contribute;
+           return getfirst(sib1(tree), fullset, firstset); */
+        tree = sib1(tree); follow = fullset; goto tailcall;
+      }
+      else {  /* FIRST(p1 p2, fl) = FIRST(p1, FIRST(p2, fl)) */
+        Charset csaux;
+        int e2 = getfirst(sib2(tree), follow, &csaux);
+        int e1 = getfirst(sib1(tree), &csaux, firstset);
+        if (e1 == 0) return 0;  /* 'e1' ensures that first can be used */
+        else if ((e1 | e2) & 2)  /* one of the children has a matchtime? */
+          return 2;  /* pattern has a matchtime capture */
+        else return e2;  /* else depends on 'e2' */
+      }
+    }
+    case TRep: {
+      getfirst(sib1(tree), follow, firstset);
+      loopset(i, firstset->cs[i] |= follow->cs[i]);
+      return 1;  /* accept the empty string */
+    }
+    case TCapture: case TGrammar: case TRule: {
+      /* return getfirst(sib1(tree), follow, firstset); */
+      tree = sib1(tree); goto tailcall;
+    }
+    case TRunTime: {  /* function invalidates any follow info. */
+      int e = getfirst(sib1(tree), fullset, firstset);
+      if (e) return 2;  /* function is not "protected"? */
+      else return 0;  /* pattern inside capture ensures first can be used */
+    }
+    case TCall: {
+      /* return getfirst(sib2(tree), follow, firstset); */
+      tree = sib2(tree); goto tailcall;
+    }
+    case TAnd: {
+      int e = getfirst(sib1(tree), follow, firstset);
+      loopset(i, firstset->cs[i] &= follow->cs[i]);
+      return e;
+    }
+    case TNot: {
+      if (tocharset(sib1(tree), firstset)) {
+        cs_complement(firstset);
+        return 1;
+      }
+      /* else go through */
+    }
+    case TBehind: {  /* instruction gives no new information */
+      /* call 'getfirst' only to check for math-time captures */
+      int e = getfirst(sib1(tree), follow, firstset);
+      loopset(i, firstset->cs[i] = follow->cs[i]);  /* uses follow */
+      return e | 1;  /* always can accept the empty string */
+    }
+    default: assert(0); return 0;
+  }
+}
+
+
+/*
+** If 'headfail(tree)' true, then 'tree' can fail only depending on the
+** next character of the subject.
+*/
+static int headfail (TTree *tree) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny: case TFalse:
+      return 1;
+    case TTrue: case TRep: case TRunTime: case TNot:
+    case TBehind:
+      return 0;
+    case TCapture: case TGrammar: case TRule: case TAnd:
+      tree = sib1(tree); goto tailcall;  /* return headfail(sib1(tree)); */
+    case TCall:
+      tree = sib2(tree); goto tailcall;  /* return headfail(sib2(tree)); */
+    case TSeq:
+      if (!nofail(sib2(tree))) return 0;
+      /* else return headfail(sib1(tree)); */
+      tree = sib1(tree); goto tailcall;
+    case TChoice:
+      if (!headfail(sib1(tree))) return 0;
+      /* else return headfail(sib2(tree)); */
+      tree = sib2(tree); goto tailcall;
+    default: assert(0); return 0;
+  }
+}
+
+
+/*
+** Check whether the code generation for the given tree can benefit
+** from a follow set (to avoid computing the follow set when it is
+** not needed)
+*/
+static int needfollow (TTree *tree) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny:
+    case TFalse: case TTrue: case TAnd: case TNot:
+    case TRunTime: case TGrammar: case TCall: case TBehind:
+      return 0;
+    case TChoice: case TRep:
+      return 1;
+    case TCapture:
+      tree = sib1(tree); goto tailcall;
+    case TSeq:
+      tree = sib2(tree); goto tailcall;
+    default: assert(0); return 0;
+  } 
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Code generation
+** =======================================================
+*/
+
+
+/*
+** size of an instruction
+*/
+int sizei (const Instruction *i) {
+  switch((Opcode)i->i.code) {
+    case ISet: case ISpan: return CHARSETINSTSIZE;
+    case ITestSet: return CHARSETINSTSIZE + 1;
+    case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall:
+    case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit:
+      return 2;
+    default: return 1;
+  }
+}
+
+
+/*
+** state for the compiler
+*/
+typedef struct CompileState {
+  Pattern *p;  /* pattern being compiled */
+  int ncode;  /* next position in p->code to be filled */
+  lua_State *L;
+} CompileState;
+
+
+/*
+** code generation is recursive; 'opt' indicates that the code is being
+** generated as the last thing inside an optional pattern (so, if that
+** code is optional too, it can reuse the 'IChoice' already in place for
+** the outer pattern). 'tt' points to a previous test protecting this
+** code (or NOINST). 'fl' is the follow set of the pattern.
+*/
+static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
+                     const Charset *fl);
+
+
+void realloccode (lua_State *L, Pattern *p, int nsize) {
+  void *ud;
+  lua_Alloc f = lua_getallocf(L, &ud);
+  void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction),
+                                  nsize * sizeof(Instruction));
+  if (newblock == NULL && nsize > 0)
+    luaL_error(L, "not enough memory");
+  p->code = (Instruction *)newblock;
+  p->codesize = nsize;
+}
+
+
+static int nextinstruction (CompileState *compst) {
+  int size = compst->p->codesize;
+  if (compst->ncode >= size)
+    realloccode(compst->L, compst->p, size * 2);
+  return compst->ncode++;
+}
+
+
+#define getinstr(cs,i)		((cs)->p->code[i])
+
+
+static int addinstruction (CompileState *compst, Opcode op, int aux) {
+  int i = nextinstruction(compst);
+  getinstr(compst, i).i.code = op;
+  getinstr(compst, i).i.aux = aux;
+  return i;
+}
+
+
+/*
+** Add an instruction followed by space for an offset (to be set later)
+*/
+static int addoffsetinst (CompileState *compst, Opcode op) {
+  int i = addinstruction(compst, op, 0);  /* instruction */
+  addinstruction(compst, (Opcode)0, 0);  /* open space for offset */
+  assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2);
+  return i;
+}
+
+
+/*
+** Set the offset of an instruction
+*/
+static void setoffset (CompileState *compst, int instruction, int offset) {
+  getinstr(compst, instruction + 1).offset = offset;
+}
+
+
+/*
+** Add a capture instruction:
+** 'op' is the capture instruction; 'cap' the capture kind;
+** 'key' the key into ktable; 'aux' is the optional capture offset
+**
+*/
+static int addinstcap (CompileState *compst, Opcode op, int cap, int key,
+                       int aux) {
+  int i = addinstruction(compst, op, joinkindoff(cap, aux));
+  getinstr(compst, i).i.key = key;
+  return i;
+}
+
+
+#define gethere(compst) 	((compst)->ncode)
+
+#define target(code,i)		((i) + code[i + 1].offset)
+
+
+/*
+** Patch 'instruction' to jump to 'target'
+*/
+static void jumptothere (CompileState *compst, int instruction, int target) {
+  if (instruction >= 0)
+    setoffset(compst, instruction, target - instruction);
+}
+
+
+/*
+** Patch 'instruction' to jump to current position
+*/
+static void jumptohere (CompileState *compst, int instruction) {
+  jumptothere(compst, instruction, gethere(compst));
+}
+
+
+/*
+** Code an IChar instruction, or IAny if there is an equivalent
+** test dominating it
+*/
+static void codechar (CompileState *compst, int c, int tt) {
+  if (tt >= 0 && getinstr(compst, tt).i.code == ITestChar &&
+                 getinstr(compst, tt).i.aux == c)
+    addinstruction(compst, IAny, 0);
+  else
+    addinstruction(compst, IChar, c);
+}
+
+
+/*
+** Add a charset posfix to an instruction
+*/
+static void addcharset (CompileState *compst, const byte *cs) {
+  int p = gethere(compst);
+  int i;
+  for (i = 0; i < (int)CHARSETINSTSIZE - 1; i++)
+    nextinstruction(compst);  /* space for buffer */
+  /* fill buffer with charset */
+  loopset(j, getinstr(compst, p).buff[j] = cs[j]);
+}
+
+
+/*
+** code a char set, optimizing unit sets for IChar, "complete"
+** sets for IAny, and empty sets for IFail; also use an IAny
+** when instruction is dominated by an equivalent test.
+*/
+static void codecharset (CompileState *compst, const byte *cs, int tt) {
+  int c = 0;  /* (=) to avoid warnings */
+  Opcode op = charsettype(cs, &c);
+  switch (op) {
+    case IChar: codechar(compst, c, tt); break;
+    case ISet: {  /* non-trivial set? */
+      if (tt >= 0 && getinstr(compst, tt).i.code == ITestSet &&
+          cs_equal(cs, getinstr(compst, tt + 2).buff))
+        addinstruction(compst, IAny, 0);
+      else {
+        addinstruction(compst, ISet, 0);
+        addcharset(compst, cs);
+      }
+      break;
+    }
+    default: addinstruction(compst, op, c); break;
+  }
+}
+
+
+/*
+** code a test set, optimizing unit sets for ITestChar, "complete"
+** sets for ITestAny, and empty sets for IJmp (always fails).
+** 'e' is true iff test should accept the empty string. (Test
+** instructions in the current VM never accept the empty string.)
+*/
+static int codetestset (CompileState *compst, Charset *cs, int e) {
+  if (e) return NOINST;  /* no test */
+  else {
+    int c = 0;
+    Opcode op = charsettype(cs->cs, &c);
+    switch (op) {
+      case IFail: return addoffsetinst(compst, IJmp);  /* always jump */
+      case IAny: return addoffsetinst(compst, ITestAny);
+      case IChar: {
+        int i = addoffsetinst(compst, ITestChar);
+        getinstr(compst, i).i.aux = c;
+        return i;
+      }
+      case ISet: {
+        int i = addoffsetinst(compst, ITestSet);
+        addcharset(compst, cs->cs);
+        return i;
+      }
+      default: assert(0); return 0;
+    }
+  }
+}
+
+
+/*
+** Find the final destination of a sequence of jumps
+*/
+static int finaltarget (Instruction *code, int i) {
+  while (code[i].i.code == IJmp)
+    i = target(code, i);
+  return i;
+}
+
+
+/*
+** final label (after traversing any jumps)
+*/
+static int finallabel (Instruction *code, int i) {
+  return finaltarget(code, target(code, i));
+}
+
+
+/*
+** <behind(p)> == behind n; <p>   (where n = fixedlen(p))
+*/
+static void codebehind (CompileState *compst, TTree *tree) {
+  if (tree->u.n > 0)
+    addinstruction(compst, IBehind, tree->u.n);
+  codegen(compst, sib1(tree), 0, NOINST, fullset);
+}
+
+
+/*
+** Choice; optimizations:
+** - when p1 is headfail or
+** when first(p1) and first(p2) are disjoint, than
+** a character not in first(p1) cannot go to p1, and a character
+** in first(p1) cannot go to p2 (at it is not in first(p2)).
+** (The optimization is not valid if p1 accepts the empty string,
+** as then there is no character at all...)
+** - when p2 is empty and opt is true; a IPartialCommit can reuse
+** the Choice already active in the stack.
+*/
+static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
+                        const Charset *fl) {
+  int emptyp2 = (p2->tag == TTrue);
+  Charset cs1, cs2;
+  int e1 = getfirst(p1, fullset, &cs1);
+  if (headfail(p1) ||
+      (!e1 && (getfirst(p2, fl, &cs2), cs_disjoint(&cs1, &cs2)))) {
+    /* <p1 / p2> == test (fail(p1)) -> L1 ; p1 ; jmp L2; L1: p2; L2: */
+    int test = codetestset(compst, &cs1, 0);
+    int jmp = NOINST;
+    codegen(compst, p1, 0, test, fl);
+    if (!emptyp2)
+      jmp = addoffsetinst(compst, IJmp); 
+    jumptohere(compst, test);
+    codegen(compst, p2, opt, NOINST, fl);
+    jumptohere(compst, jmp);
+  }
+  else if (opt && emptyp2) {
+    /* p1? == IPartialCommit; p1 */
+    jumptohere(compst, addoffsetinst(compst, IPartialCommit));
+    codegen(compst, p1, 1, NOINST, fullset);
+  }
+  else {
+    /* <p1 / p2> == 
+        test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
+    int pcommit;
+    int test = codetestset(compst, &cs1, e1);
+    int pchoice = addoffsetinst(compst, IChoice);
+    codegen(compst, p1, emptyp2, test, fullset);
+    pcommit = addoffsetinst(compst, ICommit);
+    jumptohere(compst, pchoice);
+    jumptohere(compst, test);
+    codegen(compst, p2, opt, NOINST, fl);
+    jumptohere(compst, pcommit);
+  }
+}
+
+
+/*
+** And predicate
+** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n
+** (valid only when 'p' has no captures)
+*/
+static void codeand (CompileState *compst, TTree *tree, int tt) {
+  int n = fixedlen(tree);
+  if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) {
+    codegen(compst, tree, 0, tt, fullset);
+    if (n > 0)
+      addinstruction(compst, IBehind, n);
+  }
+  else {  /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */
+    int pcommit;
+    int pchoice = addoffsetinst(compst, IChoice);
+    codegen(compst, tree, 0, tt, fullset);
+    pcommit = addoffsetinst(compst, IBackCommit);
+    jumptohere(compst, pchoice);
+    addinstruction(compst, IFail, 0);
+    jumptohere(compst, pcommit);
+  }
+}
+
+
+/*
+** Captures: if pattern has fixed (and not too big) length, and it
+** has no nested captures, use a single IFullCapture instruction
+** after the match; otherwise, enclose the pattern with OpenCapture -
+** CloseCapture.
+*/
+static void codecapture (CompileState *compst, TTree *tree, int tt,
+                         const Charset *fl) {
+  int len = fixedlen(sib1(tree));
+  if (len >= 0 && len <= MAXOFF && !hascaptures(sib1(tree))) {
+    codegen(compst, sib1(tree), 0, tt, fl);
+    addinstcap(compst, IFullCapture, tree->cap, tree->key, len);
+  }
+  else {
+    addinstcap(compst, IOpenCapture, tree->cap, tree->key, 0);
+    codegen(compst, sib1(tree), 0, tt, fl);
+    addinstcap(compst, ICloseCapture, Cclose, 0, 0);
+  }
+}
+
+
+static void coderuntime (CompileState *compst, TTree *tree, int tt) {
+  addinstcap(compst, IOpenCapture, Cgroup, tree->key, 0);
+  codegen(compst, sib1(tree), 0, tt, fullset);
+  addinstcap(compst, ICloseRunTime, Cclose, 0, 0);
+}
+
+
+/*
+** Repetion; optimizations:
+** When pattern is a charset, can use special instruction ISpan.
+** When pattern is head fail, or if it starts with characters that
+** are disjoint from what follows the repetions, a simple test
+** is enough (a fail inside the repetition would backtrack to fail
+** again in the following pattern, so there is no need for a choice).
+** When 'opt' is true, the repetion can reuse the Choice already
+** active in the stack.
+*/
+static void coderep (CompileState *compst, TTree *tree, int opt,
+                     const Charset *fl) {
+  Charset st;
+  if (tocharset(tree, &st)) {
+    addinstruction(compst, ISpan, 0);
+    addcharset(compst, st.cs);
+  }
+  else {
+    int e1 = getfirst(tree, fullset, &st);
+    if (headfail(tree) || (!e1 && cs_disjoint(&st, fl))) {
+      /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */
+      int jmp;
+      int test = codetestset(compst, &st, 0);
+      codegen(compst, tree, 0, test, fullset);
+      jmp = addoffsetinst(compst, IJmp);
+      jumptohere(compst, test);
+      jumptothere(compst, jmp, test);
+    }
+    else {
+      /* test(fail(p1)) -> L2; choice L2; L1: <p>; partialcommit L1; L2: */
+      /* or (if 'opt'): partialcommit L1; L1: <p>; partialcommit L1; */
+      int commit, l2;
+      int test = codetestset(compst, &st, e1);
+      int pchoice = NOINST;
+      if (opt)
+        jumptohere(compst, addoffsetinst(compst, IPartialCommit));
+      else
+        pchoice = addoffsetinst(compst, IChoice);
+      l2 = gethere(compst);
+      codegen(compst, tree, 0, NOINST, fullset);
+      commit = addoffsetinst(compst, IPartialCommit);
+      jumptothere(compst, commit, l2);
+      jumptohere(compst, pchoice);
+      jumptohere(compst, test);
+    }
+  }
+}
+
+
+/*
+** Not predicate; optimizations:
+** In any case, if first test fails, 'not' succeeds, so it can jump to
+** the end. If pattern is headfail, that is all (it cannot fail
+** in other parts); this case includes 'not' of simple sets. Otherwise,
+** use the default code (a choice plus a failtwice).
+*/
+static void codenot (CompileState *compst, TTree *tree) {
+  Charset st;
+  int e = getfirst(tree, fullset, &st);
+  int test = codetestset(compst, &st, e);
+  if (headfail(tree))  /* test (fail(p1)) -> L1; fail; L1:  */
+    addinstruction(compst, IFail, 0);
+  else {
+    /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1:  */
+    int pchoice = addoffsetinst(compst, IChoice);
+    codegen(compst, tree, 0, NOINST, fullset);
+    addinstruction(compst, IFailTwice, 0);
+    jumptohere(compst, pchoice);
+  }
+  jumptohere(compst, test);
+}
+
+
+/*
+** change open calls to calls, using list 'positions' to find
+** correct offsets; also optimize tail calls
+*/
+static void correctcalls (CompileState *compst, int *positions,
+                          int from, int to) {
+  int i;
+  Instruction *code = compst->p->code;
+  for (i = from; i < to; i += sizei(&code[i])) {
+    if (code[i].i.code == IOpenCall) {
+      int n = code[i].i.key;  /* rule number */
+      int rule = positions[n];  /* rule position */
+      assert(rule == from || code[rule - 1].i.code == IRet);
+      if (code[finaltarget(code, i + 2)].i.code == IRet)  /* call; ret ? */
+        code[i].i.code = IJmp;  /* tail call */
+      else
+        code[i].i.code = ICall;
+      jumptothere(compst, i, rule);  /* call jumps to respective rule */
+    }
+  }
+  assert(i == to);
+}
+
+
+/*
+** Code for a grammar:
+** call L1; jmp L2; L1: rule 1; ret; rule 2; ret; ...; L2:
+*/
+static void codegrammar (CompileState *compst, TTree *grammar) {
+  int positions[MAXRULES];
+  int rulenumber = 0;
+  TTree *rule;
+  int firstcall = addoffsetinst(compst, ICall);  /* call initial rule */
+  int jumptoend = addoffsetinst(compst, IJmp);  /* jump to the end */
+  int start = gethere(compst);  /* here starts the initial rule */
+  jumptohere(compst, firstcall);
+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {
+    positions[rulenumber++] = gethere(compst);  /* save rule position */
+    codegen(compst, sib1(rule), 0, NOINST, fullset);  /* code rule */
+    addinstruction(compst, IRet, 0);
+  }
+  assert(rule->tag == TTrue);
+  jumptohere(compst, jumptoend);
+  correctcalls(compst, positions, start, gethere(compst));
+}
+
+
+static void codecall (CompileState *compst, TTree *call) {
+  int c = addoffsetinst(compst, IOpenCall);  /* to be corrected later */
+  getinstr(compst, c).i.key = sib2(call)->cap;  /* rule number */
+  assert(sib2(call)->tag == TRule);
+}
+
+
+/*
+** Code first child of a sequence
+** (second child is called in-place to allow tail call)
+** Return 'tt' for second child
+*/
+static int codeseq1 (CompileState *compst, TTree *p1, TTree *p2,
+                     int tt, const Charset *fl) {
+  if (needfollow(p1)) {
+    Charset fl1;
+    getfirst(p2, fl, &fl1);  /* p1 follow is p2 first */
+    codegen(compst, p1, 0, tt, &fl1);
+  }
+  else  /* use 'fullset' as follow */
+    codegen(compst, p1, 0, tt, fullset);
+  if (fixedlen(p1) != 0)  /* can 'p1' consume anything? */
+    return  NOINST;  /* invalidate test */
+  else return tt;  /* else 'tt' still protects sib2 */
+}
+
+
+/*
+** Main code-generation function: dispatch to auxiliar functions
+** according to kind of tree. ('needfollow' should return true
+** only for consructions that use 'fl'.)
+*/
+static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
+                     const Charset *fl) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: codechar(compst, tree->u.n, tt); break;
+    case TAny: addinstruction(compst, IAny, 0); break;
+    case TSet: codecharset(compst, treebuffer(tree), tt); break;
+    case TTrue: break;
+    case TFalse: addinstruction(compst, IFail, 0); break;
+    case TChoice: codechoice(compst, sib1(tree), sib2(tree), opt, fl); break;
+    case TRep: coderep(compst, sib1(tree), opt, fl); break;
+    case TBehind: codebehind(compst, tree); break;
+    case TNot: codenot(compst, sib1(tree)); break;
+    case TAnd: codeand(compst, sib1(tree), tt); break;
+    case TCapture: codecapture(compst, tree, tt, fl); break;
+    case TRunTime: coderuntime(compst, tree, tt); break;
+    case TGrammar: codegrammar(compst, tree); break;
+    case TCall: codecall(compst, tree); break;
+    case TSeq: {
+      tt = codeseq1(compst, sib1(tree), sib2(tree), tt, fl);  /* code 'p1' */
+      /* codegen(compst, p2, opt, tt, fl); */
+      tree = sib2(tree); goto tailcall;
+    }
+    default: assert(0);
+  }
+}
+
+
+/*
+** Optimize jumps and other jump-like instructions.
+** * Update labels of instructions with labels to their final
+** destinations (e.g., choice L1; ... L1: jmp L2: becomes
+** choice L2)
+** * Jumps to other instructions that do jumps become those
+** instructions (e.g., jump to return becomes a return; jump
+** to commit becomes a commit)
+*/
+static void peephole (CompileState *compst) {
+  Instruction *code = compst->p->code;
+  int i;
+  for (i = 0; i < compst->ncode; i += sizei(&code[i])) {
+   redo:
+    switch (code[i].i.code) {
+      case IChoice: case ICall: case ICommit: case IPartialCommit:
+      case IBackCommit: case ITestChar: case ITestSet:
+      case ITestAny: {  /* instructions with labels */
+        jumptothere(compst, i, finallabel(code, i));  /* optimize label */
+        break;
+      }
+      case IJmp: {
+        int ft = finaltarget(code, i);
+        switch (code[ft].i.code) {  /* jumping to what? */
+          case IRet: case IFail: case IFailTwice:
+          case IEnd: {  /* instructions with unconditional implicit jumps */
+            code[i] = code[ft];  /* jump becomes that instruction */
+            code[i + 1].i.code = IAny;  /* 'no-op' for target position */
+            break;
+          }
+          case ICommit: case IPartialCommit:
+          case IBackCommit: {  /* inst. with unconditional explicit jumps */
+            int fft = finallabel(code, ft);
+            code[i] = code[ft];  /* jump becomes that instruction... */
+            jumptothere(compst, i, fft);  /* but must correct its offset */
+            goto redo;  /* reoptimize its label */
+          }
+          default: {
+            jumptothere(compst, i, ft);  /* optimize label */
+            break;
+          }
+        }
+        break;
+      }
+      default: break;
+    }
+  }
+  assert(code[i - 1].i.code == IEnd);
+}
+
+
+/*
+** Compile a pattern
+*/
+Instruction *compile (lua_State *L, Pattern *p) {
+  CompileState compst;
+  compst.p = p;  compst.ncode = 0;  compst.L = L;
+  realloccode(L, p, 2);  /* minimum initial size */
+  codegen(&compst, p->tree, 0, NOINST, fullset);
+  addinstruction(&compst, IEnd, 0);
+  realloccode(L, p, compst.ncode);  /* set final size */
+  peephole(&compst);
+  return p->code;
+}
+
+
+/* }====================================================== */
+
+/*
+** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
+** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+*/
+
+/* #include "lua.h" */
+/* #include "lauxlib.h" */
+
+/* #include "lpcap.h" */
+/* #include "lptypes.h" */
+
+
+#define captype(cap)	((cap)->kind)
+
+#define isclosecap(cap)	(captype(cap) == Cclose)
+
+#define closeaddr(c)	((c)->s + (c)->siz - 1)
+
+#define isfullcap(cap)	((cap)->siz != 0)
+
+#define getfromktable(cs,v)	lua_rawgeti((cs)->L, ktableidx((cs)->ptop), v)
+
+#define pushluaval(cs)		getfromktable(cs, (cs)->cap->idx)
+
+
+
+/*
+** Put at the cache for Lua values the value indexed by 'v' in ktable
+** of the running pattern (if it is not there yet); returns its index.
+*/
+static int updatecache (CapState *cs, int v) {
+  int idx = cs->ptop + 1;  /* stack index of cache for Lua values */
+  if (v != cs->valuecached) {  /* not there? */
+    getfromktable(cs, v);  /* get value from 'ktable' */
+    lua_replace(cs->L, idx);  /* put it at reserved stack position */
+    cs->valuecached = v;  /* keep track of what is there */
+  }
+  return idx;
+}
+
+
+static int pushcapture (CapState *cs);
+
+
+/*
+** Goes back in a list of captures looking for an open capture
+** corresponding to a close
+*/
+static Capture *findopen (Capture *cap) {
+  int n = 0;  /* number of closes waiting an open */
+  for (;;) {
+    cap--;
+    if (isclosecap(cap)) n++;  /* one more open to skip */
+    else if (!isfullcap(cap))
+      if (n-- == 0) return cap;
+  }
+}
+
+
+/*
+** Go to the next capture
+*/
+static void nextcap (CapState *cs) {
+  Capture *cap = cs->cap;
+  if (!isfullcap(cap)) {  /* not a single capture? */
+    int n = 0;  /* number of opens waiting a close */
+    for (;;) {  /* look for corresponding close */
+      cap++;
+      if (isclosecap(cap)) {
+        if (n-- == 0) break;
+      }
+      else if (!isfullcap(cap)) n++;
+    }
+  }
+  cs->cap = cap + 1;  /* + 1 to skip last close (or entire single capture) */
+}
+
+
+/*
+** Push on the Lua stack all values generated by nested captures inside
+** the current capture. Returns number of values pushed. 'addextra'
+** makes it push the entire match after all captured values. The
+** entire match is pushed also if there are no other nested values,
+** so the function never returns zero.
+*/
+static int pushnestedvalues (CapState *cs, int addextra) {
+  Capture *co = cs->cap;
+  if (isfullcap(cs->cap++)) {  /* no nested captures? */
+    lua_pushlstring(cs->L, co->s, co->siz - 1);  /* push whole match */
+    return 1;  /* that is it */
+  }
+  else {
+    int n = 0;
+    while (!isclosecap(cs->cap))  /* repeat for all nested patterns */
+      n += pushcapture(cs);
+    if (addextra || n == 0) {  /* need extra? */
+      lua_pushlstring(cs->L, co->s, cs->cap->s - co->s);  /* push whole match */
+      n++;
+    }
+    cs->cap++;  /* skip close entry */
+    return n;
+  }
+}
+
+
+/*
+** Push only the first value generated by nested captures
+*/
+static void pushonenestedvalue (CapState *cs) {
+  int n = pushnestedvalues(cs, 0);
+  if (n > 1)
+    lua_pop(cs->L, n - 1);  /* pop extra values */
+}
+
+
+/*
+** Try to find a named group capture with the name given at the top of
+** the stack; goes backward from 'cap'.
+*/
+static Capture *findback (CapState *cs, Capture *cap) {
+  lua_State *L = cs->L;
+  while (cap-- > cs->ocap) {  /* repeat until end of list */
+    if (isclosecap(cap))
+      cap = findopen(cap);  /* skip nested captures */
+    else if (!isfullcap(cap))
+      continue; /* opening an enclosing capture: skip and get previous */
+    if (captype(cap) == Cgroup) {
+      getfromktable(cs, cap->idx);  /* get group name */
+      if (lp_equal(L, -2, -1)) {  /* right group? */
+        lua_pop(L, 2);  /* remove reference name and group name */
+        return cap;
+      }
+      else lua_pop(L, 1);  /* remove group name */
+    }
+  }
+  luaL_error(L, "back reference '%s' not found", lua_tostring(L, -1));
+  return NULL;  /* to avoid warnings */
+}
+
+
+/*
+** Back-reference capture. Return number of values pushed.
+*/
+static int backrefcap (CapState *cs) {
+  int n;
+  Capture *curr = cs->cap;
+  pushluaval(cs);  /* reference name */
+  cs->cap = findback(cs, curr);  /* find corresponding group */
+  n = pushnestedvalues(cs, 0);  /* push group's values */
+  cs->cap = curr + 1;
+  return n;
+}
+
+
+/*
+** Table capture: creates a new table and populates it with nested
+** captures.
+*/
+static int tablecap (CapState *cs) {
+  lua_State *L = cs->L;
+  int n = 0;
+  lua_newtable(L);
+  if (isfullcap(cs->cap++))
+    return 1;  /* table is empty */
+  while (!isclosecap(cs->cap)) {
+    if (captype(cs->cap) == Cgroup && cs->cap->idx != 0) {  /* named group? */
+      pushluaval(cs);  /* push group name */
+      pushonenestedvalue(cs);
+      lua_settable(L, -3);
+    }
+    else {  /* not a named group */
+      int i;
+      int k = pushcapture(cs);
+      for (i = k; i > 0; i--)  /* store all values into table */
+        lua_rawseti(L, -(i + 1), n + i);
+      n += k;
+    }
+  }
+  cs->cap++;  /* skip close entry */
+  return 1;  /* number of values pushed (only the table) */
+}
+
+
+/*
+** Table-query capture
+*/
+static int querycap (CapState *cs) {
+  int idx = cs->cap->idx;
+  pushonenestedvalue(cs);  /* get nested capture */
+  lua_gettable(cs->L, updatecache(cs, idx));  /* query cap. value at table */
+  if (!lua_isnil(cs->L, -1))
+    return 1;
+  else {  /* no value */
+    lua_pop(cs->L, 1);  /* remove nil */
+    return 0;
+  }
+}
+
+
+/*
+** Fold capture
+*/
+static int foldcap (CapState *cs) {
+  int n;
+  lua_State *L = cs->L;
+  int idx = cs->cap->idx;
+  if (isfullcap(cs->cap++) ||  /* no nested captures? */
+      isclosecap(cs->cap) ||  /* no nested captures (large subject)? */
+      (n = pushcapture(cs)) == 0)  /* nested captures with no values? */
+    return luaL_error(L, "no initial value for fold capture");
+  if (n > 1)
+    lua_pop(L, n - 1);  /* leave only one result for accumulator */
+  while (!isclosecap(cs->cap)) {
+    lua_pushvalue(L, updatecache(cs, idx));  /* get folding function */
+    lua_insert(L, -2);  /* put it before accumulator */
+    n = pushcapture(cs);  /* get next capture's values */
+    lua_call(L, n + 1, 1);  /* call folding function */
+  }
+  cs->cap++;  /* skip close entry */
+  return 1;  /* only accumulator left on the stack */
+}
+
+
+/*
+** Function capture
+*/
+static int functioncap (CapState *cs) {
+  int n;
+  int top = lua_gettop(cs->L);
+  pushluaval(cs);  /* push function */
+  n = pushnestedvalues(cs, 0);  /* push nested captures */
+  lua_call(cs->L, n, LUA_MULTRET);  /* call function */
+  return lua_gettop(cs->L) - top;  /* return function's results */
+}
+
+
+/*
+** Select capture
+*/
+static int numcap (CapState *cs) {
+  int idx = cs->cap->idx;  /* value to select */
+  if (idx == 0) {  /* no values? */
+    nextcap(cs);  /* skip entire capture */
+    return 0;  /* no value produced */
+  }
+  else {
+    int n = pushnestedvalues(cs, 0);
+    if (n < idx)  /* invalid index? */
+      return luaL_error(cs->L, "no capture '%d'", idx);
+    else {
+      lua_pushvalue(cs->L, -(n - idx + 1));  /* get selected capture */
+      lua_replace(cs->L, -(n + 1));  /* put it in place of 1st capture */
+      lua_pop(cs->L, n - 1);  /* remove other captures */
+      return 1;
+    }
+  }
+}
+
+
+/*
+** Return the stack index of the first runtime capture in the given
+** list of captures (or zero if no runtime captures)
+*/
+int finddyncap (Capture *cap, Capture *last) {
+  for (; cap < last; cap++) {
+    if (cap->kind == Cruntime)
+      return cap->idx;  /* stack position of first capture */
+  }
+  return 0;  /* no dynamic captures in this segment */
+}
+
+
+/*
+** Calls a runtime capture. Returns number of captures removed by
+** the call, including the initial Cgroup. (Captures to be added are
+** on the Lua stack.)
+*/
+int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
+  int n, id;
+  lua_State *L = cs->L;
+  int otop = lua_gettop(L);
+  Capture *open = findopen(close);
+  assert(captype(open) == Cgroup);
+  id = finddyncap(open, close);  /* get first dynamic capture argument */
+  close->kind = Cclose;  /* closes the group */
+  close->s = s;
+  cs->cap = open; cs->valuecached = 0;  /* prepare capture state */
+  luaL_checkstack(L, 4, "too many runtime captures");
+  pushluaval(cs);  /* push function to be called */
+  lua_pushvalue(L, SUBJIDX);  /* push original subject */
+  lua_pushinteger(L, s - cs->s + 1);  /* push current position */
+  n = pushnestedvalues(cs, 0);  /* push nested captures */
+  lua_call(L, n + 2, LUA_MULTRET);  /* call dynamic function */
+  if (id > 0) {  /* are there old dynamic captures to be removed? */
+    int i;
+    for (i = id; i <= otop; i++)
+      lua_remove(L, id);  /* remove old dynamic captures */
+    *rem = otop - id + 1;  /* total number of dynamic captures removed */
+  }
+  else
+    *rem = 0;  /* no dynamic captures removed */
+  return close - open;  /* number of captures of all kinds removed */
+}
+
+
+/*
+** Auxiliary structure for substitution and string captures: keep
+** information about nested captures for future use, avoiding to push
+** string results into Lua
+*/
+typedef struct StrAux {
+  int isstring;  /* whether capture is a string */
+  union {
+    Capture *cp;  /* if not a string, respective capture */
+    struct {  /* if it is a string... */
+      const char *s;  /* ... starts here */
+      const char *e;  /* ... ends here */
+    } s;
+  } u;
+} StrAux;
+
+#define MAXSTRCAPS	10
+
+/*
+** Collect values from current capture into array 'cps'. Current
+** capture must be Cstring (first call) or Csimple (recursive calls).
+** (In first call, fills %0 with whole match for Cstring.)
+** Returns number of elements in the array that were filled.
+*/
+static int getstrcaps (CapState *cs, StrAux *cps, int n) {
+  int k = n++;
+  cps[k].isstring = 1;  /* get string value */
+  cps[k].u.s.s = cs->cap->s;  /* starts here */
+  if (!isfullcap(cs->cap++)) {  /* nested captures? */
+    while (!isclosecap(cs->cap)) {  /* traverse them */
+      if (n >= MAXSTRCAPS)  /* too many captures? */
+        nextcap(cs);  /* skip extra captures (will not need them) */
+      else if (captype(cs->cap) == Csimple)  /* string? */
+        n = getstrcaps(cs, cps, n);  /* put info. into array */
+      else {
+        cps[n].isstring = 0;  /* not a string */
+        cps[n].u.cp = cs->cap;  /* keep original capture */
+        nextcap(cs);
+        n++;
+      }
+    }
+    cs->cap++;  /* skip close */
+  }
+  cps[k].u.s.e = closeaddr(cs->cap - 1);  /* ends here */
+  return n;
+}
+
+
+/*
+** add next capture value (which should be a string) to buffer 'b'
+*/
+static int addonestring (luaL_Buffer *b, CapState *cs, const char *what);
+
+
+/*
+** String capture: add result to buffer 'b' (instead of pushing
+** it into the stack)
+*/
+static void stringcap (luaL_Buffer *b, CapState *cs) {
+  StrAux cps[MAXSTRCAPS];
+  int n;
+  size_t len, i;
+  const char *fmt;  /* format string */
+  fmt = lua_tolstring(cs->L, updatecache(cs, cs->cap->idx), &len);
+  n = getstrcaps(cs, cps, 0) - 1;  /* collect nested captures */
+  for (i = 0; i < len; i++) {  /* traverse them */
+    if (fmt[i] != '%')  /* not an escape? */
+      luaL_addchar(b, fmt[i]);  /* add it to buffer */
+    else if (fmt[++i] < '0' || fmt[i] > '9')  /* not followed by a digit? */
+      luaL_addchar(b, fmt[i]);  /* add to buffer */
+    else {
+      int l = fmt[i] - '0';  /* capture index */
+      if (l > n)
+        luaL_error(cs->L, "invalid capture index (%d)", l);
+      else if (cps[l].isstring)
+        luaL_addlstring(b, cps[l].u.s.s, cps[l].u.s.e - cps[l].u.s.s);
+      else {
+        Capture *curr = cs->cap;
+        cs->cap = cps[l].u.cp;  /* go back to evaluate that nested capture */
+        if (!addonestring(b, cs, "capture"))
+          luaL_error(cs->L, "no values in capture index %d", l);
+        cs->cap = curr;  /* continue from where it stopped */
+      }
+    }
+  }
+}
+
+
+/*
+** Substitution capture: add result to buffer 'b'
+*/
+static void substcap (luaL_Buffer *b, CapState *cs) {
+  const char *curr = cs->cap->s;
+  if (isfullcap(cs->cap))  /* no nested captures? */
+    luaL_addlstring(b, curr, cs->cap->siz - 1);  /* keep original text */
+  else {
+    cs->cap++;  /* skip open entry */
+    while (!isclosecap(cs->cap)) {  /* traverse nested captures */
+      const char *next = cs->cap->s;
+      luaL_addlstring(b, curr, next - curr);  /* add text up to capture */
+      if (addonestring(b, cs, "replacement"))
+        curr = closeaddr(cs->cap - 1);  /* continue after match */
+      else  /* no capture value */
+        curr = next;  /* keep original text in final result */
+    }
+    luaL_addlstring(b, curr, cs->cap->s - curr);  /* add last piece of text */
+  }
+  cs->cap++;  /* go to next capture */
+}
+
+
+/*
+** Evaluates a capture and adds its first value to buffer 'b'; returns
+** whether there was a value
+*/
+static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) {
+  switch (captype(cs->cap)) {
+    case Cstring:
+      stringcap(b, cs);  /* add capture directly to buffer */
+      return 1;
+    case Csubst:
+      substcap(b, cs);  /* add capture directly to buffer */
+      return 1;
+    default: {
+      lua_State *L = cs->L;
+      int n = pushcapture(cs);
+      if (n > 0) {
+        if (n > 1) lua_pop(L, n - 1);  /* only one result */
+        if (!lua_isstring(L, -1))
+          luaL_error(L, "invalid %s value (a %s)", what, luaL_typename(L, -1));
+        luaL_addvalue(b);
+      }
+      return n;
+    }
+  }
+}
+
+
+/*
+** Push all values of the current capture into the stack; returns
+** number of values pushed
+*/
+static int pushcapture (CapState *cs) {
+  lua_State *L = cs->L;
+  luaL_checkstack(L, 4, "too many captures");
+  switch (captype(cs->cap)) {
+    case Cposition: {
+      lua_pushinteger(L, cs->cap->s - cs->s + 1);
+      cs->cap++;
+      return 1;
+    }
+    case Cconst: {
+      pushluaval(cs);
+      cs->cap++;
+      return 1;
+    }
+    case Carg: {
+      int arg = (cs->cap++)->idx;
+      if (arg + FIXEDARGS > cs->ptop)
+        return luaL_error(L, "reference to absent extra argument #%d", arg);
+      lua_pushvalue(L, arg + FIXEDARGS);
+      return 1;
+    }
+    case Csimple: {
+      int k = pushnestedvalues(cs, 1);
+      lua_insert(L, -k);  /* make whole match be first result */
+      return k;
+    }
+    case Cruntime: {
+      lua_pushvalue(L, (cs->cap++)->idx);  /* value is in the stack */
+      return 1;
+    }
+    case Cstring: {
+      luaL_Buffer b;
+      luaL_buffinit(L, &b);
+      stringcap(&b, cs);
+      luaL_pushresult(&b);
+      return 1;
+    }
+    case Csubst: {
+      luaL_Buffer b;
+      luaL_buffinit(L, &b);
+      substcap(&b, cs);
+      luaL_pushresult(&b);
+      return 1;
+    }
+    case Cgroup: {
+      if (cs->cap->idx == 0)  /* anonymous group? */
+        return pushnestedvalues(cs, 0);  /* add all nested values */
+      else {  /* named group: add no values */
+        nextcap(cs);  /* skip capture */
+        return 0;
+      }
+    }
+    case Cbackref: return backrefcap(cs);
+    case Ctable: return tablecap(cs);
+    case Cfunction: return functioncap(cs);
+    case Cnum: return numcap(cs);
+    case Cquery: return querycap(cs);
+    case Cfold: return foldcap(cs);
+    default: assert(0); return 0;
+  }
+}
+
+
+/*
+** Prepare a CapState structure and traverse the entire list of
+** captures in the stack pushing its results. 's' is the subject
+** string, 'r' is the final position of the match, and 'ptop' 
+** the index in the stack where some useful values were pushed.
+** Returns the number of results pushed. (If the list produces no
+** results, push the final position of the match.)
+*/
+int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {
+  Capture *capture = (Capture *)lua_touserdata(L, caplistidx(ptop));
+  int n = 0;
+  if (!isclosecap(capture)) {  /* is there any capture? */
+    CapState cs;
+    cs.ocap = cs.cap = capture; cs.L = L;
+    cs.s = s; cs.valuecached = 0; cs.ptop = ptop;
+    do {  /* collect their values */
+      n += pushcapture(&cs);
+    } while (!isclosecap(cs.cap));
+  }
+  if (n == 0) {  /* no capture values? */
+    lua_pushinteger(L, r - s + 1);  /* return only end position */
+    n = 1;
+  }
+  return n;
+}
+
+
+/*
+** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $
+** Copyright 2013, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+*/
+
+/* #include <ctype.h> */
+/* #include <limits.h> */
+/* #include <string.h> */
+
+
+/* #include "lua.h" */
+/* #include "lauxlib.h" */
+
+/* #include "lptypes.h" */
+/* #include "lpcap.h" */
+/* #include "lpcode.h" */
+/* #include "lpprint.h" */
+/* #include "lptree.h" */
+
+
+/* number of siblings for each tree */
+const byte numsiblings[] = {
+  0, 0, 0,	/* char, set, any */
+  0, 0,		/* true, false */	
+  1,		/* rep */
+  2, 2,		/* seq, choice */
+  1, 1,		/* not, and */
+  0, 0, 2, 1,  /* call, opencall, rule, grammar */
+  1,  /* behind */
+  1, 1  /* capture, runtime capture */
+};
+
+
+static TTree *newgrammar (lua_State *L, int arg);
+
+
+/*
+** returns a reasonable name for value at index 'idx' on the stack
+*/
+static const char *val2str (lua_State *L, int idx) {
+  const char *k = lua_tostring(L, idx);
+  if (k != NULL)
+    return lua_pushfstring(L, "%s", k);
+  else
+    return lua_pushfstring(L, "(a %s)", luaL_typename(L, idx));
+}
+
+
+/*
+** Fix a TOpenCall into a TCall node, using table 'postable' to
+** translate a key to its rule address in the tree. Raises an
+** error if key does not exist.
+*/
+static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {
+  int n;
+  lua_rawgeti(L, -1, t->key);  /* get rule's name */
+  lua_gettable(L, postable);  /* query name in position table */
+  n = lua_tonumber(L, -1);  /* get (absolute) position */
+  lua_pop(L, 1);  /* remove position */
+  if (n == 0) {  /* no position? */
+    lua_rawgeti(L, -1, t->key);  /* get rule's name again */
+    luaL_error(L, "rule '%s' undefined in given grammar", val2str(L, -1));
+  }
+  t->tag = TCall;
+  t->u.ps = n - (t - g);  /* position relative to node */
+  assert(sib2(t)->tag == TRule);
+  sib2(t)->key = t->key;  /* fix rule's key */
+}
+
+
+/*
+** Transform left associative constructions into right
+** associative ones, for sequence and choice; that is:
+** (t11 + t12) + t2  =>  t11 + (t12 + t2)
+** (t11 * t12) * t2  =>  t11 * (t12 * t2)
+** (that is, Op (Op t11 t12) t2 => Op t11 (Op t12 t2))
+*/
+static void correctassociativity (TTree *tree) {
+  TTree *t1 = sib1(tree);
+  assert(tree->tag == TChoice || tree->tag == TSeq);
+  while (t1->tag == tree->tag) {
+    int n1size = tree->u.ps - 1;  /* t1 == Op t11 t12 */
+    int n11size = t1->u.ps - 1;
+    int n12size = n1size - n11size - 1;
+    memmove(sib1(tree), sib1(t1), n11size * sizeof(TTree)); /* move t11 */
+    tree->u.ps = n11size + 1;
+    sib2(tree)->tag = tree->tag;
+    sib2(tree)->u.ps = n12size + 1;
+  }
+}
+
+
+/*
+** Make final adjustments in a tree. Fix open calls in tree 't',
+** making them refer to their respective rules or raising appropriate
+** errors (if not inside a grammar). Correct associativity of associative
+** constructions (making them right associative). Assume that tree's
+** ktable is at the top of the stack (for error messages).
+*/
+static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {
+ tailcall:
+  switch (t->tag) {
+    case TGrammar:  /* subgrammars were already fixed */
+      return;
+    case TOpenCall: {
+      if (g != NULL)  /* inside a grammar? */
+        fixonecall(L, postable, g, t);
+      else {  /* open call outside grammar */
+        lua_rawgeti(L, -1, t->key);
+        luaL_error(L, "rule '%s' used outside a grammar", val2str(L, -1));
+      }
+      break;
+    }
+    case TSeq: case TChoice:
+      correctassociativity(t);
+      break;
+  }
+  switch (numsiblings[t->tag]) {
+    case 1: /* finalfix(L, postable, g, sib1(t)); */
+      t = sib1(t); goto tailcall;
+    case 2:
+      finalfix(L, postable, g, sib1(t));
+      t = sib2(t); goto tailcall;  /* finalfix(L, postable, g, sib2(t)); */
+    default: assert(numsiblings[t->tag] == 0); break;
+  }
+}
+
+
+
+/*
+** {===================================================================
+** KTable manipulation
+**
+** - The ktable of a pattern 'p' can be shared by other patterns that
+** contain 'p' and no other constants. Because of this sharing, we
+** should not add elements to a 'ktable' unless it was freshly created
+** for the new pattern.
+**
+** - The maximum index in a ktable is USHRT_MAX, because trees and
+** patterns use unsigned shorts to store those indices.
+** ====================================================================
+*/
+
+/*
+** Create a new 'ktable' to the pattern at the top of the stack.
+*/
+static void newktable (lua_State *L, int n) {
+  lua_createtable(L, n, 0);  /* create a fresh table */
+  lua_setuservalue(L, -2);  /* set it as 'ktable' for pattern */
+}
+
+
+/*
+** Add element 'idx' to 'ktable' of pattern at the top of the stack;
+** Return index of new element.
+** If new element is nil, does not add it to table (as it would be
+** useless) and returns 0, as ktable[0] is always nil.
+*/
+static int addtoktable (lua_State *L, int idx) {
+  if (lua_isnil(L, idx))  /* nil value? */
+    return 0;
+  else {
+    int n;
+    lua_getuservalue(L, -1);  /* get ktable from pattern */
+    n = lua_rawlen(L, -1);
+    if (n >= USHRT_MAX)
+      luaL_error(L, "too many Lua values in pattern");
+    lua_pushvalue(L, idx);  /* element to be added */
+    lua_rawseti(L, -2, ++n);
+    lua_pop(L, 1);  /* remove 'ktable' */
+    return n;
+  }
+}
+
+
+/*
+** Return the number of elements in the ktable at 'idx'.
+** In Lua 5.2/5.3, default "environment" for patterns is nil, not
+** a table. Treat it as an empty table. In Lua 5.1, assumes that
+** the environment has no numeric indices (len == 0)
+*/
+static int ktablelen (lua_State *L, int idx) {
+  if (!lua_istable(L, idx)) return 0;
+  else return lua_rawlen(L, idx);
+}
+
+
+/*
+** Concatentate the contents of table 'idx1' into table 'idx2'.
+** (Assume that both indices are negative.)
+** Return the original length of table 'idx2' (or 0, if no
+** element was added, as there is no need to correct any index).
+*/
+static int concattable (lua_State *L, int idx1, int idx2) {
+  int i;
+  int n1 = ktablelen(L, idx1);
+  int n2 = ktablelen(L, idx2);
+  if (n1 + n2 > USHRT_MAX)
+    luaL_error(L, "too many Lua values in pattern");
+  if (n1 == 0) return 0;  /* nothing to correct */
+  for (i = 1; i <= n1; i++) {
+    lua_rawgeti(L, idx1, i);
+    lua_rawseti(L, idx2 - 1, n2 + i);  /* correct 'idx2' */
+  }
+  return n2;
+}
+
+
+/*
+** When joining 'ktables', constants from one of the subpatterns must
+** be renumbered; 'correctkeys' corrects their indices (adding 'n'
+** to each of them)
+*/
+static void correctkeys (TTree *tree, int n) {
+  if (n == 0) return;  /* no correction? */
+ tailcall:
+  switch (tree->tag) {
+    case TOpenCall: case TCall: case TRunTime: case TRule: {
+      if (tree->key > 0)
+        tree->key += n;
+      break;
+    }
+    case TCapture: {
+      if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)
+        tree->key += n;
+      break;
+    }
+    default: break;
+  }
+  switch (numsiblings[tree->tag]) {
+    case 1:  /* correctkeys(sib1(tree), n); */
+      tree = sib1(tree); goto tailcall;
+    case 2:
+      correctkeys(sib1(tree), n);
+      tree = sib2(tree); goto tailcall;  /* correctkeys(sib2(tree), n); */
+    default: assert(numsiblings[tree->tag] == 0); break;
+  }
+}
+
+
+/*
+** Join the ktables from p1 and p2 the ktable for the new pattern at the
+** top of the stack, reusing them when possible.
+*/
+static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
+  int n1, n2;
+  lua_getuservalue(L, p1);  /* get ktables */
+  lua_getuservalue(L, p2);
+  n1 = ktablelen(L, -2);
+  n2 = ktablelen(L, -1);
+  if (n1 == 0 && n2 == 0)  /* are both tables empty? */
+    lua_pop(L, 2);  /* nothing to be done; pop tables */
+  else if (n2 == 0 || lp_equal(L, -2, -1)) {  /* 2nd table empty or equal? */
+    lua_pop(L, 1);  /* pop 2nd table */
+    lua_setuservalue(L, -2);  /* set 1st ktable into new pattern */
+  }
+  else if (n1 == 0) {  /* first table is empty? */
+    lua_setuservalue(L, -3);  /* set 2nd table into new pattern */
+    lua_pop(L, 1);  /* pop 1st table */
+  }
+  else {
+    lua_createtable(L, n1 + n2, 0);  /* create ktable for new pattern */
+    /* stack: new p; ktable p1; ktable p2; new ktable */
+    concattable(L, -3, -1);  /* from p1 into new ktable */
+    concattable(L, -2, -1);  /* from p2 into new ktable */
+    lua_setuservalue(L, -4);  /* new ktable becomes 'p' environment */
+    lua_pop(L, 2);  /* pop other ktables */
+    correctkeys(t2, n1);  /* correction for indices from p2 */
+  }
+}
+
+
+/*
+** copy 'ktable' of element 'idx' to new tree (on top of stack)
+*/
+static void copyktable (lua_State *L, int idx) {
+  lua_getuservalue(L, idx);
+  lua_setuservalue(L, -2);
+}
+
+
+/*
+** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable'
+** from tree at the top of the stack, and correct corresponding
+** tree.
+*/
+static void mergektable (lua_State *L, int idx, TTree *stree) {
+  int n;
+  lua_getuservalue(L, -1);  /* get ktables */
+  lua_getuservalue(L, idx);
+  n = concattable(L, -1, -2);
+  lua_pop(L, 2);  /* remove both ktables */
+  correctkeys(stree, n);
+}
+
+
+/*
+** Create a new 'ktable' to the pattern at the top of the stack, adding
+** all elements from pattern 'p' (if not 0) plus element 'idx' to it.
+** Return index of new element.
+*/
+static int addtonewktable (lua_State *L, int p, int idx) {
+  newktable(L, 1);
+  if (p)
+    mergektable(L, p, NULL);
+  return addtoktable(L, idx);
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** Tree generation
+** =======================================================
+*/
+
+/*
+** In 5.2, could use 'luaL_testudata'...
+*/
+static int testpattern (lua_State *L, int idx) {
+  if (lua_touserdata(L, idx)) {  /* value is a userdata? */
+    if (lua_getmetatable(L, idx)) {  /* does it have a metatable? */
+      luaL_getmetatable(L, PATTERN_T);
+      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
+        lua_pop(L, 2);  /* remove both metatables */
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+
+static Pattern *getpattern (lua_State *L, int idx) {
+  return (Pattern *)luaL_checkudata(L, idx, PATTERN_T);
+}
+
+
+static int getsize (lua_State *L, int idx) {
+  return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
+}
+
+
+static TTree *gettree (lua_State *L, int idx, int *len) {
+  Pattern *p = getpattern(L, idx);
+  if (len)
+    *len = getsize(L, idx);
+  return p->tree;
+}
+
+
+/*
+** create a pattern. Set its uservalue (the 'ktable') equal to its
+** metatable. (It could be any empty sequence; the metatable is at
+** hand here, so we use it.)
+*/
+static TTree *newtree (lua_State *L, int len) {
+  size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern);
+  Pattern *p = (Pattern *)lua_newuserdata(L, size);
+  luaL_getmetatable(L, PATTERN_T);
+  lua_pushvalue(L, -1);
+  lua_setuservalue(L, -3);
+  lua_setmetatable(L, -2);
+  p->code = NULL;  p->codesize = 0;
+  return p->tree;
+}
+
+
+static TTree *newleaf (lua_State *L, int tag) {
+  TTree *tree = newtree(L, 1);
+  tree->tag = tag;
+  return tree;
+}
+
+
+static TTree *newcharset (lua_State *L) {
+  TTree *tree = newtree(L, bytes2slots(CHARSETSIZE) + 1);
+  tree->tag = TSet;
+  loopset(i, treebuffer(tree)[i] = 0);
+  return tree;
+}
+
+
+/*
+** add to tree a sequence where first sibling is 'sib' (with size
+** 'sibsize'); returns position for second sibling
+*/
+static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {
+  tree->tag = TSeq; tree->u.ps = sibsize + 1;
+  memcpy(sib1(tree), sib, sibsize * sizeof(TTree));
+  return sib2(tree);
+}
+
+
+/*
+** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got
+** from the array 's' (or 0 if array is NULL). (TSeq is binary, so it
+** must build a sequence of sequence of sequence...)
+*/
+static void fillseq (TTree *tree, int tag, int n, const char *s) {
+  int i;
+  for (i = 0; i < n - 1; i++) {  /* initial n-1 copies of Seq tag; Seq ... */
+    tree->tag = TSeq; tree->u.ps = 2;
+    sib1(tree)->tag = tag;
+    sib1(tree)->u.n = s ? (byte)s[i] : 0;
+    tree = sib2(tree);
+  }
+  tree->tag = tag;  /* last one does not need TSeq */
+  tree->u.n = s ? (byte)s[i] : 0;
+}
+
+
+/*
+** Numbers as patterns:
+** 0 == true (always match); n == TAny repeated 'n' times;
+** -n == not (TAny repeated 'n' times)
+*/
+static TTree *numtree (lua_State *L, int n) {
+  if (n == 0)
+    return newleaf(L, TTrue);
+  else {
+    TTree *tree, *nd;
+    if (n > 0)
+      tree = nd = newtree(L, 2 * n - 1);
+    else {  /* negative: code it as !(-n) */
+      n = -n;
+      tree = newtree(L, 2 * n);
+      tree->tag = TNot;
+      nd = sib1(tree);
+    }
+    fillseq(nd, TAny, n, NULL);  /* sequence of 'n' any's */
+    return tree;
+  }
+}
+
+
+/*
+** Convert value at index 'idx' to a pattern
+*/
+static TTree *getpatt (lua_State *L, int idx, int *len) {
+  TTree *tree;
+  switch (lua_type(L, idx)) {
+    case LUA_TSTRING: {
+      size_t slen;
+      const char *s = lua_tolstring(L, idx, &slen);  /* get string */
+      if (slen == 0)  /* empty? */
+        tree = newleaf(L, TTrue);  /* always match */
+      else {
+        tree = newtree(L, 2 * (slen - 1) + 1);
+        fillseq(tree, TChar, slen, s);  /* sequence of 'slen' chars */
+      }
+      break;
+    }
+    case LUA_TNUMBER: {
+      int n = lua_tointeger(L, idx);
+      tree = numtree(L, n);
+      break;
+    }
+    case LUA_TBOOLEAN: {
+      tree = (lua_toboolean(L, idx) ? newleaf(L, TTrue) : newleaf(L, TFalse));
+      break;
+    }
+    case LUA_TTABLE: {
+      tree = newgrammar(L, idx);
+      break;
+    }
+    case LUA_TFUNCTION: {
+      tree = newtree(L, 2);
+      tree->tag = TRunTime;
+      tree->key = addtonewktable(L, 0, idx);
+      sib1(tree)->tag = TTrue;
+      break;
+    }
+    default: {
+      return gettree(L, idx, len);
+    }
+  }
+  lua_replace(L, idx);  /* put new tree into 'idx' slot */
+  if (len)
+    *len = getsize(L, idx);
+  return tree;
+}
+
+
+/*
+** create a new tree, whith a new root and one sibling.
+** Sibling must be on the Lua stack, at index 1.
+*/
+static TTree *newroot1sib (lua_State *L, int tag) {
+  int s1;
+  TTree *tree1 = getpatt(L, 1, &s1);
+  TTree *tree = newtree(L, 1 + s1);  /* create new tree */
+  tree->tag = tag;
+  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));
+  copyktable(L, 1);
+  return tree;
+}
+
+
+/*
+** create a new tree, whith a new root and 2 siblings.
+** Siblings must be on the Lua stack, first one at index 1.
+*/
+static TTree *newroot2sib (lua_State *L, int tag) {
+  int s1, s2;
+  TTree *tree1 = getpatt(L, 1, &s1);
+  TTree *tree2 = getpatt(L, 2, &s2);
+  TTree *tree = newtree(L, 1 + s1 + s2);  /* create new tree */
+  tree->tag = tag;
+  tree->u.ps =  1 + s1;
+  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));
+  memcpy(sib2(tree), tree2, s2 * sizeof(TTree));
+  joinktables(L, 1, sib2(tree), 2);
+  return tree;
+}
+
+
+static int lp_P (lua_State *L) {
+  luaL_checkany(L, 1);
+  getpatt(L, 1, NULL);
+  lua_settop(L, 1);
+  return 1;
+}
+
+
+/*
+** sequence operator; optimizations:
+** false x => false, x true => x, true x => x
+** (cannot do x . false => false because x may have runtime captures)
+*/
+static int lp_seq (lua_State *L) {
+  TTree *tree1 = getpatt(L, 1, NULL);
+  TTree *tree2 = getpatt(L, 2, NULL);
+  if (tree1->tag == TFalse || tree2->tag == TTrue)
+    lua_pushvalue(L, 1);  /* false . x == false, x . true = x */
+  else if (tree1->tag == TTrue)
+    lua_pushvalue(L, 2);  /* true . x = x */
+  else
+    newroot2sib(L, TSeq);
+  return 1;
+}
+
+
+/*
+** choice operator; optimizations:
+** charset / charset => charset
+** true / x => true, x / false => x, false / x => x
+** (x / true is not equivalent to true)
+*/
+static int lp_choice (lua_State *L) {
+  Charset st1, st2;
+  TTree *t1 = getpatt(L, 1, NULL);
+  TTree *t2 = getpatt(L, 2, NULL);
+  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {
+    TTree *t = newcharset(L);
+    loopset(i, treebuffer(t)[i] = st1.cs[i] | st2.cs[i]);
+  }
+  else if (nofail(t1) || t2->tag == TFalse)
+    lua_pushvalue(L, 1);  /* true / x => true, x / false => x */
+  else if (t1->tag == TFalse)
+    lua_pushvalue(L, 2);  /* false / x => x */
+  else
+    newroot2sib(L, TChoice);
+  return 1;
+}
+
+
+/*
+** p^n
+*/
+static int lp_star (lua_State *L) {
+  int size1;
+  int n = (int)luaL_checkinteger(L, 2);
+  TTree *tree1 = getpatt(L, 1, &size1);
+  if (n >= 0) {  /* seq tree1 (seq tree1 ... (seq tree1 (rep tree1))) */
+    TTree *tree = newtree(L, (n + 1) * (size1 + 1));
+    if (nullable(tree1))
+      luaL_error(L, "loop body may accept empty string");
+    while (n--)  /* repeat 'n' times */
+      tree = seqaux(tree, tree1, size1);
+    tree->tag = TRep;
+    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));
+  }
+  else {  /* choice (seq tree1 ... choice tree1 true ...) true */
+    TTree *tree;
+    n = -n;
+    /* size = (choice + seq + tree1 + true) * n, but the last has no seq */
+    tree = newtree(L, n * (size1 + 3) - 1);
+    for (; n > 1; n--) {  /* repeat (n - 1) times */
+      tree->tag = TChoice; tree->u.ps = n * (size1 + 3) - 2;
+      sib2(tree)->tag = TTrue;
+      tree = sib1(tree);
+      tree = seqaux(tree, tree1, size1);
+    }
+    tree->tag = TChoice; tree->u.ps = size1 + 1;
+    sib2(tree)->tag = TTrue;
+    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));
+  }
+  copyktable(L, 1);
+  return 1;
+}
+
+
+/*
+** #p == &p
+*/
+static int lp_and (lua_State *L) {
+  newroot1sib(L, TAnd);
+  return 1;
+}
+
+
+/*
+** -p == !p
+*/
+static int lp_not (lua_State *L) {
+  newroot1sib(L, TNot);
+  return 1;
+}
+
+
+/*
+** [t1 - t2] == Seq (Not t2) t1
+** If t1 and t2 are charsets, make their difference.
+*/
+static int lp_sub (lua_State *L) {
+  Charset st1, st2;
+  int s1, s2;
+  TTree *t1 = getpatt(L, 1, &s1);
+  TTree *t2 = getpatt(L, 2, &s2);
+  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {
+    TTree *t = newcharset(L);
+    loopset(i, treebuffer(t)[i] = st1.cs[i] & ~st2.cs[i]);
+  }
+  else {
+    TTree *tree = newtree(L, 2 + s1 + s2);
+    tree->tag = TSeq;  /* sequence of... */
+    tree->u.ps =  2 + s2;
+    sib1(tree)->tag = TNot;  /* ...not... */
+    memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree));  /* ...t2 */
+    memcpy(sib2(tree), t1, s1 * sizeof(TTree));  /* ... and t1 */
+    joinktables(L, 1, sib1(tree), 2);
+  }
+  return 1;
+}
+
+
+static int lp_set (lua_State *L) {
+  size_t l;
+  const char *s = luaL_checklstring(L, 1, &l);
+  TTree *tree = newcharset(L);
+  while (l--) {
+    setchar(treebuffer(tree), (byte)(*s));
+    s++;
+  }
+  return 1;
+}
+
+
+static int lp_range (lua_State *L) {
+  int arg;
+  int top = lua_gettop(L);
+  TTree *tree = newcharset(L);
+  for (arg = 1; arg <= top; arg++) {
+    int c;
+    size_t l;
+    const char *r = luaL_checklstring(L, arg, &l);
+    luaL_argcheck(L, l == 2, arg, "range must have two characters");
+    for (c = (byte)r[0]; c <= (byte)r[1]; c++)
+      setchar(treebuffer(tree), c);
+  }
+  return 1;
+}
+
+
+/*
+** Look-behind predicate
+*/
+static int lp_behind (lua_State *L) {
+  TTree *tree;
+  TTree *tree1 = getpatt(L, 1, NULL);
+  int n = fixedlen(tree1);
+  luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");
+  luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");
+  luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");
+  tree = newroot1sib(L, TBehind);
+  tree->u.n = n;
+  return 1;
+}
+
+
+/*
+** Create a non-terminal
+*/
+static int lp_V (lua_State *L) {
+  TTree *tree = newleaf(L, TOpenCall);
+  luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");
+  tree->key = addtonewktable(L, 0, 1);
+  return 1;
+}
+
+
+/*
+** Create a tree for a non-empty capture, with a body and
+** optionally with an associated Lua value (at index 'labelidx' in the
+** stack)
+*/
+static int capture_aux (lua_State *L, int cap, int labelidx) {
+  TTree *tree = newroot1sib(L, TCapture);
+  tree->cap = cap;
+  tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);
+  return 1;
+}
+
+
+/*
+** Fill a tree with an empty capture, using an empty (TTrue) sibling.
+*/
+static TTree *auxemptycap (TTree *tree, int cap) {
+  tree->tag = TCapture;
+  tree->cap = cap;
+  sib1(tree)->tag = TTrue;
+  return tree;
+}
+
+
+/*
+** Create a tree for an empty capture
+*/
+static TTree *newemptycap (lua_State *L, int cap) {
+  return auxemptycap(newtree(L, 2), cap);
+}
+
+
+/*
+** Create a tree for an empty capture with an associated Lua value
+*/
+static TTree *newemptycapkey (lua_State *L, int cap, int idx) {
+  TTree *tree = auxemptycap(newtree(L, 2), cap);
+  tree->key = addtonewktable(L, 0, idx);
+  return tree;
+}
+
+
+/*
+** Captures with syntax p / v
+** (function capture, query capture, string capture, or number capture)
+*/
+static int lp_divcapture (lua_State *L) {
+  switch (lua_type(L, 2)) {
+    case LUA_TFUNCTION: return capture_aux(L, Cfunction, 2);
+    case LUA_TTABLE: return capture_aux(L, Cquery, 2);
+    case LUA_TSTRING: return capture_aux(L, Cstring, 2);
+    case LUA_TNUMBER: {
+      int n = lua_tointeger(L, 2);
+      TTree *tree = newroot1sib(L, TCapture);
+      luaL_argcheck(L, 0 <= n && n <= SHRT_MAX, 1, "invalid number");
+      tree->cap = Cnum;
+      tree->key = n;
+      return 1;
+    }
+    default: return luaL_argerror(L, 2, "invalid replacement value");
+  }
+}
+
+
+static int lp_substcapture (lua_State *L) {
+  return capture_aux(L, Csubst, 0);
+}
+
+
+static int lp_tablecapture (lua_State *L) {
+  return capture_aux(L, Ctable, 0);
+}
+
+
+static int lp_groupcapture (lua_State *L) {
+  if (lua_isnoneornil(L, 2))
+    return capture_aux(L, Cgroup, 0);
+  else
+    return capture_aux(L, Cgroup, 2);
+}
+
+
+static int lp_foldcapture (lua_State *L) {
+  luaL_checktype(L, 2, LUA_TFUNCTION);
+  return capture_aux(L, Cfold, 2);
+}
+
+
+static int lp_simplecapture (lua_State *L) {
+  return capture_aux(L, Csimple, 0);
+}
+
+
+static int lp_poscapture (lua_State *L) {
+  newemptycap(L, Cposition);
+  return 1;
+}
+
+
+static int lp_argcapture (lua_State *L) {
+  int n = (int)luaL_checkinteger(L, 1);
+  TTree *tree = newemptycap(L, Carg);
+  tree->key = n;
+  luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");
+  return 1;
+}
+
+
+static int lp_backref (lua_State *L) {
+  luaL_checkany(L, 1);
+  newemptycapkey(L, Cbackref, 1);
+  return 1;
+}
+
+
+/*
+** Constant capture
+*/
+static int lp_constcapture (lua_State *L) {
+  int i;
+  int n = lua_gettop(L);  /* number of values */
+  if (n == 0)  /* no values? */
+    newleaf(L, TTrue);  /* no capture */
+  else if (n == 1)
+    newemptycapkey(L, Cconst, 1);  /* single constant capture */
+  else {  /* create a group capture with all values */
+    TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2);
+    newktable(L, n);  /* create a 'ktable' for new tree */
+    tree->tag = TCapture;
+    tree->cap = Cgroup;
+    tree->key = 0;
+    tree = sib1(tree);
+    for (i = 1; i <= n - 1; i++) {
+      tree->tag = TSeq;
+      tree->u.ps = 3;  /* skip TCapture and its sibling */
+      auxemptycap(sib1(tree), Cconst);
+      sib1(tree)->key = addtoktable(L, i);
+      tree = sib2(tree);
+    }
+    auxemptycap(tree, Cconst);
+    tree->key = addtoktable(L, i);
+  }
+  return 1;
+}
+
+
+static int lp_matchtime (lua_State *L) {
+  TTree *tree;
+  luaL_checktype(L, 2, LUA_TFUNCTION);
+  tree = newroot1sib(L, TRunTime);
+  tree->key = addtonewktable(L, 1, 2);
+  return 1;
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** Grammar - Tree generation
+** =======================================================
+*/
+
+/*
+** push on the stack the index and the pattern for the
+** initial rule of grammar at index 'arg' in the stack;
+** also add that index into position table.
+*/
+static void getfirstrule (lua_State *L, int arg, int postab) {
+  lua_rawgeti(L, arg, 1);  /* access first element */
+  if (lua_isstring(L, -1)) {  /* is it the name of initial rule? */
+    lua_pushvalue(L, -1);  /* duplicate it to use as key */
+    lua_gettable(L, arg);  /* get associated rule */
+  }
+  else {
+    lua_pushinteger(L, 1);  /* key for initial rule */
+    lua_insert(L, -2);  /* put it before rule */
+  }
+  if (!testpattern(L, -1)) {  /* initial rule not a pattern? */
+    if (lua_isnil(L, -1))
+      luaL_error(L, "grammar has no initial rule");
+    else
+      luaL_error(L, "initial rule '%s' is not a pattern", lua_tostring(L, -2));
+  }
+  lua_pushvalue(L, -2);  /* push key */
+  lua_pushinteger(L, 1);  /* push rule position (after TGrammar) */
+  lua_settable(L, postab);  /* insert pair at position table */
+}
+
+/*
+** traverse grammar at index 'arg', pushing all its keys and patterns
+** into the stack. Create a new table (before all pairs key-pattern) to
+** collect all keys and their associated positions in the final tree
+** (the "position table").
+** Return the number of rules and (in 'totalsize') the total size
+** for the new tree.
+*/
+static int collectrules (lua_State *L, int arg, int *totalsize) {
+  int n = 1;  /* to count number of rules */
+  int postab = lua_gettop(L) + 1;  /* index of position table */
+  int size;  /* accumulator for total size */
+  lua_newtable(L);  /* create position table */
+  getfirstrule(L, arg, postab);
+  size = 2 + getsize(L, postab + 2);  /* TGrammar + TRule + rule */
+  lua_pushnil(L);  /* prepare to traverse grammar table */
+  while (lua_next(L, arg) != 0) {
+    if (lua_tonumber(L, -2) == 1 ||
+        lp_equal(L, -2, postab + 1)) {  /* initial rule? */
+      lua_pop(L, 1);  /* remove value (keep key for lua_next) */
+      continue;
+    }
+    if (!testpattern(L, -1))  /* value is not a pattern? */
+      luaL_error(L, "rule '%s' is not a pattern", val2str(L, -2));
+    luaL_checkstack(L, LUA_MINSTACK, "grammar has too many rules");
+    lua_pushvalue(L, -2);  /* push key (to insert into position table) */
+    lua_pushinteger(L, size);
+    lua_settable(L, postab);
+    size += 1 + getsize(L, -1);  /* update size */
+    lua_pushvalue(L, -2);  /* push key (for next lua_next) */
+    n++;
+  }
+  *totalsize = size + 1;  /* TTrue to finish list of rules */
+  return n;
+}
+
+
+static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {
+  int i;
+  TTree *nd = sib1(grammar);  /* auxiliary pointer to traverse the tree */
+  for (i = 0; i < n; i++) {  /* add each rule into new tree */
+    int ridx = frule + 2*i + 1;  /* index of i-th rule */
+    int rulesize;
+    TTree *rn = gettree(L, ridx, &rulesize);
+    nd->tag = TRule;
+    nd->key = 0;  /* will be fixed when rule is used */
+    nd->cap = i;  /* rule number */
+    nd->u.ps = rulesize + 1;  /* point to next rule */
+    memcpy(sib1(nd), rn, rulesize * sizeof(TTree));  /* copy rule */
+    mergektable(L, ridx, sib1(nd));  /* merge its ktable into new one */
+    nd = sib2(nd);  /* move to next rule */
+  }
+  nd->tag = TTrue;  /* finish list of rules */
+}
+
+
+/*
+** Check whether a tree has potential infinite loops
+*/
+static int checkloops (TTree *tree) {
+ tailcall:
+  if (tree->tag == TRep && nullable(sib1(tree)))
+    return 1;
+  else if (tree->tag == TGrammar)
+    return 0;  /* sub-grammars already checked */
+  else {
+    switch (numsiblings[tree->tag]) {
+      case 1:  /* return checkloops(sib1(tree)); */
+        tree = sib1(tree); goto tailcall;
+      case 2:
+        if (checkloops(sib1(tree))) return 1;
+        /* else return checkloops(sib2(tree)); */
+        tree = sib2(tree); goto tailcall;
+      default: assert(numsiblings[tree->tag] == 0); return 0;
+    }
+  }
+}
+
+
+/*
+** Give appropriate error message for 'verifyrule'. If a rule appears
+** twice in 'passed', there is path from it back to itself without
+** advancing the subject.
+*/
+static int verifyerror (lua_State *L, int *passed, int npassed) {
+  int i, j;
+  for (i = npassed - 1; i >= 0; i--) {  /* search for a repetition */
+    for (j = i - 1; j >= 0; j--) {
+      if (passed[i] == passed[j]) {
+        lua_rawgeti(L, -1, passed[i]);  /* get rule's key */
+        return luaL_error(L, "rule '%s' may be left recursive", val2str(L, -1));
+      }
+    }
+  }
+  return luaL_error(L, "too many left calls in grammar");
+}
+
+
+/*
+** Check whether a rule can be left recursive; raise an error in that
+** case; otherwise return 1 iff pattern is nullable.
+** The return value is used to check sequences, where the second pattern
+** is only relevant if the first is nullable.
+** Parameter 'nb' works as an accumulator, to allow tail calls in
+** choices. ('nb' true makes function returns true.)
+** Parameter 'passed' is a list of already visited rules, 'npassed'
+** counts the elements in 'passed'.
+** Assume ktable at the top of the stack.
+*/
+static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
+                       int nb) {
+ tailcall:
+  switch (tree->tag) {
+    case TChar: case TSet: case TAny:
+    case TFalse:
+      return nb;  /* cannot pass from here */
+    case TTrue:
+    case TBehind:  /* look-behind cannot have calls */
+      return 1;
+    case TNot: case TAnd: case TRep:
+      /* return verifyrule(L, sib1(tree), passed, npassed, 1); */
+      tree = sib1(tree); nb = 1; goto tailcall;
+    case TCapture: case TRunTime:
+      /* return verifyrule(L, sib1(tree), passed, npassed, nb); */
+      tree = sib1(tree); goto tailcall;
+    case TCall:
+      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */
+      tree = sib2(tree); goto tailcall;
+    case TSeq:  /* only check 2nd child if first is nb */
+      if (!verifyrule(L, sib1(tree), passed, npassed, 0))
+        return nb;
+      /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */
+      tree = sib2(tree); goto tailcall;
+    case TChoice:  /* must check both children */
+      nb = verifyrule(L, sib1(tree), passed, npassed, nb);
+      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */
+      tree = sib2(tree); goto tailcall;
+    case TRule:
+      if (npassed >= MAXRULES)
+        return verifyerror(L, passed, npassed);
+      else {
+        passed[npassed++] = tree->key;
+        /* return verifyrule(L, sib1(tree), passed, npassed); */
+        tree = sib1(tree); goto tailcall;
+      }
+    case TGrammar:
+      return nullable(tree);  /* sub-grammar cannot be left recursive */
+    default: assert(0); return 0;
+  }
+}
+
+
+static void verifygrammar (lua_State *L, TTree *grammar) {
+  int passed[MAXRULES];
+  TTree *rule;
+  /* check left-recursive rules */
+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {
+    if (rule->key == 0) continue;  /* unused rule */
+    verifyrule(L, sib1(rule), passed, 0, 0);
+  }
+  assert(rule->tag == TTrue);
+  /* check infinite loops inside rules */
+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {
+    if (rule->key == 0) continue;  /* unused rule */
+    if (checkloops(sib1(rule))) {
+      lua_rawgeti(L, -1, rule->key);  /* get rule's key */
+      luaL_error(L, "empty loop in rule '%s'", val2str(L, -1));
+    }
+  }
+  assert(rule->tag == TTrue);
+}
+
+
+/*
+** Give a name for the initial rule if it is not referenced
+*/
+static void initialrulename (lua_State *L, TTree *grammar, int frule) {
+  if (sib1(grammar)->key == 0) {  /* initial rule is not referenced? */
+    int n = lua_rawlen(L, -1) + 1;  /* index for name */
+    lua_pushvalue(L, frule);  /* rule's name */
+    lua_rawseti(L, -2, n);  /* ktable was on the top of the stack */
+    sib1(grammar)->key = n;
+  }
+}
+
+
+static TTree *newgrammar (lua_State *L, int arg) {
+  int treesize;
+  int frule = lua_gettop(L) + 2;  /* position of first rule's key */
+  int n = collectrules(L, arg, &treesize);
+  TTree *g = newtree(L, treesize);
+  luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");
+  g->tag = TGrammar;  g->u.n = n;
+  lua_newtable(L);  /* create 'ktable' */
+  lua_setuservalue(L, -2);
+  buildgrammar(L, g, frule, n);
+  lua_getuservalue(L, -1);  /* get 'ktable' for new tree */
+  finalfix(L, frule - 1, g, sib1(g));
+  initialrulename(L, g, frule);
+  verifygrammar(L, g);
+  lua_pop(L, 1);  /* remove 'ktable' */
+  lua_insert(L, -(n * 2 + 2));  /* move new table to proper position */
+  lua_pop(L, n * 2 + 1);  /* remove position table + rule pairs */
+  return g;  /* new table at the top of the stack */
+}
+
+/* }====================================================== */
+
+
+static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {
+  lua_getuservalue(L, idx);  /* push 'ktable' (may be used by 'finalfix') */
+  finalfix(L, 0, NULL, p->tree);
+  lua_pop(L, 1);  /* remove 'ktable' */
+  return compile(L, p);
+}
+
+
+static int lp_printtree (lua_State *L) {
+  TTree *tree = getpatt(L, 1, NULL);
+  int c = lua_toboolean(L, 2);
+  if (c) {
+    lua_getuservalue(L, 1);  /* push 'ktable' (may be used by 'finalfix') */
+    finalfix(L, 0, NULL, tree);
+    lua_pop(L, 1);  /* remove 'ktable' */
+  }
+  printktable(L, 1);
+  printtree(tree, 0);
+  return 0;
+}
+
+
+static int lp_printcode (lua_State *L) {
+  Pattern *p = getpattern(L, 1);
+  printktable(L, 1);
+  if (p->code == NULL)  /* not compiled yet? */
+    prepcompile(L, p, 1);
+  printpatt(p->code, p->codesize);
+  return 0;
+}
+
+
+/*
+** Get the initial position for the match, interpreting negative
+** values from the end of the subject
+*/
+static size_t initposition (lua_State *L, size_t len) {
+  lua_Integer ii = luaL_optinteger(L, 3, 1);
+  if (ii > 0) {  /* positive index? */
+    if ((size_t)ii <= len)  /* inside the string? */
+      return (size_t)ii - 1;  /* return it (corrected to 0-base) */
+    else return len;  /* crop at the end */
+  }
+  else {  /* negative index */
+    if ((size_t)(-ii) <= len)  /* inside the string? */
+      return len - ((size_t)(-ii));  /* return position from the end */
+    else return 0;  /* crop at the beginning */
+  }
+}
+
+
+/*
+** Main match function
+*/
+static int lp_match (lua_State *L) {
+#if defined(__aarch64__) && defined(MFLuaJIT)
+  Capture *capture; 
+#else
+  Capture capture[INITCAPSIZE];
+#endif
+  const char *r;
+  size_t l;
+  /*int ret_val;*/
+  Pattern *p = (getpatt(L, 1, NULL), getpattern(L, 1));
+  Instruction *code = (p->code != NULL) ? p->code : prepcompile(L, p, 1);
+  const char *s = luaL_checklstring(L, SUBJIDX, &l);
+  size_t i = initposition(L, l);
+  int ptop = lua_gettop(L);
+  lua_pushnil(L);  /* initialize subscache */
+#if defined(__aarch64__) && defined(MFLuaJIT)
+  capture = (Capture *)lua_newuserdata(L, sizeof(Capture)*INITCAPSIZE);
+#else
+  lua_pushlightuserdata(L, capture);  /* initialize caplistidx */
+#endif
+  lua_getuservalue(L, 1);  /* initialize penvidx */
+  r = match(L, s, s + i, s + l, code, capture, ptop);
+  if (r == NULL) {
+    lua_pushnil(L);
+    return 1;
+  }
+  return getcaptures(L, s, r, ptop);
+}
+
+
+
+/*
+** {======================================================
+** Library creation and functions not related to matching
+** =======================================================
+*/
+
+/* maximum limit for stack size */
+#define MAXLIM		(INT_MAX / 100)
+
+static int lp_setmax (lua_State *L) {
+  lua_Integer lim = luaL_checkinteger(L, 1);
+  luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");
+  lua_settop(L, 1);
+  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
+  return 0;
+}
+
+
+static int lp_version (lua_State *L) {
+  lua_pushstring(L, VERSION);
+  return 1;
+}
+
+
+static int lp_type (lua_State *L) {
+  if (testpattern(L, 1))
+    lua_pushliteral(L, "pattern");
+  else
+    lua_pushnil(L);
+  return 1;
+}
+
+
+int lp_gc (lua_State *L) {
+  Pattern *p = getpattern(L, 1);
+  realloccode(L, p, 0);  /* delete code block */
+  return 0;
+}
+
+
+static void createcat (lua_State *L, const char *catname, int (catf) (int)) {
+  TTree *t = newcharset(L);
+  int i;
+  for (i = 0; i <= UCHAR_MAX; i++)
+    if (catf(i)) setchar(treebuffer(t), i);
+  lua_setfield(L, -2, catname);
+}
+
+
+static int lp_locale (lua_State *L) {
+  if (lua_isnoneornil(L, 1)) {
+    lua_settop(L, 0);
+    lua_createtable(L, 0, 12);
+  }
+  else {
+    luaL_checktype(L, 1, LUA_TTABLE);
+    lua_settop(L, 1);
+  }
+  createcat(L, "alnum", isalnum);
+  createcat(L, "alpha", isalpha);
+  createcat(L, "cntrl", iscntrl);
+  createcat(L, "digit", isdigit);
+  createcat(L, "graph", isgraph);
+  createcat(L, "lower", islower);
+  createcat(L, "print", isprint);
+  createcat(L, "punct", ispunct);
+  createcat(L, "space", isspace);
+  createcat(L, "upper", isupper);
+  createcat(L, "xdigit", isxdigit);
+  return 1;
+}
+
+
+static struct luaL_Reg pattreg[] = {
+  {"ptree", lp_printtree},
+  {"pcode", lp_printcode},
+  {"match", lp_match},
+  {"B", lp_behind},
+  {"V", lp_V},
+  {"C", lp_simplecapture},
+  {"Cc", lp_constcapture},
+  {"Cmt", lp_matchtime},
+  {"Cb", lp_backref},
+  {"Carg", lp_argcapture},
+  {"Cp", lp_poscapture},
+  {"Cs", lp_substcapture},
+  {"Ct", lp_tablecapture},
+  {"Cf", lp_foldcapture},
+  {"Cg", lp_groupcapture},
+  {"P", lp_P},
+  {"S", lp_set},
+  {"R", lp_range},
+  {"locale", lp_locale},
+  {"version", lp_version},
+  {"setmaxstack", lp_setmax},
+  {"type", lp_type},
+  {NULL, NULL}
+};
+
+
+static struct luaL_Reg metareg[] = {
+  {"__mul", lp_seq},
+  {"__add", lp_choice},
+  {"__pow", lp_star},
+  {"__gc", lp_gc},
+  {"__len", lp_and},
+  {"__div", lp_divcapture},
+  {"__unm", lp_not},
+  {"__sub", lp_sub},
+  {NULL, NULL}
+};
+
+
+int luaopen_lpeg (lua_State *L);
+int luaopen_lpeg (lua_State *L) {
+  luaL_newmetatable(L, PATTERN_T);
+  lua_pushnumber(L, MAXBACK);  /* initialize maximum backtracking */
+  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
+  luaL_setfuncs(L, metareg, 0);
+#if defined(MFLuaJIT)
+  luaL_register(L,"lpeg",pattreg);
+#else
+  luaL_newlib(L, pattreg);
+#endif
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -3, "__index");
+  return 1;
+}
+
+
+int mfluaopen_lpeg(lua_State * L);
+int mfluaopen_lpeg(lua_State * L) {
+  lua_getglobal(L,"_G");
+  /* set the lpeg table */
+  lua_pushstring(L,"lpeg");
+  luaopen_lpeg(L);
+  lua_settable(L, -3);
+  return 1;
+}
+
+
+/* }====================================================== */

Added: trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/luapeg/lpeg.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,432 @@
+/*
+** $Id: lptypes.h,v 1.16 2017/01/13 13:33:17 roberto Exp $
+** LPeg - PEG pattern matching for Lua
+** Copyright 2007-2017, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
+** written by Roberto Ierusalimschy
+*/
+
+/*
+ "Amalgamated" version for Lua(jit)TeX written by Scarso Luigi.
+*/
+
+
+#if !defined(lptypes_h)
+#define lptypes_h
+
+#define LPEG_DEBUG
+#if !defined(LPEG_DEBUG)
+#define NDEBUG
+#endif
+
+#include <assert.h>
+#include <limits.h>
+/* added */
+#include <ctype.h> 
+#include <stdio.h> 
+#include <string.h> 
+
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#define VERSION         "1.0.1"
+
+
+#define PATTERN_T	"lpeg-pattern"
+#define MAXSTACKIDX	"lpeg-maxstack"
+
+
+/*
+** compatibility with Lua 5.1
+*/
+#if (LUA_VERSION_NUM == 501)
+
+#define lp_equal	lua_equal
+
+#define lua_getuservalue	lua_getfenv
+#define lua_setuservalue	lua_setfenv
+
+#define lua_rawlen		lua_objlen
+
+#define luaL_setfuncs(L,f,n)	luaL_register(L,NULL,f)
+#if !defined(MFLuaJIT)
+#define luaL_newlib(L,f)	luaL_register(L,"lpeg",f)
+#endif
+#endif
+
+
+#if !defined(lp_equal)
+#define lp_equal(L,idx1,idx2)  lua_compare(L,(idx1),(idx2),LUA_OPEQ)
+#endif
+
+
+/* default maximum size for call/backtrack stack */
+#if !defined(MAXBACK)
+#define MAXBACK         400
+#endif
+
+
+/* maximum number of rules in a grammar */
+#if !defined(MAXRULES)
+#define MAXRULES        1000
+#endif
+
+
+
+/* initial size for capture's list */
+#define INITCAPSIZE	32
+
+
+/* index, on Lua stack, for subject */
+#define SUBJIDX		2
+
+/* number of fixed arguments to 'match' (before capture arguments) */
+#define FIXEDARGS	3
+
+/* index, on Lua stack, for capture list */
+#define caplistidx(ptop)	((ptop) + 2)
+
+/* index, on Lua stack, for pattern's ktable */
+#define ktableidx(ptop)		((ptop) + 3)
+
+/* index, on Lua stack, for backtracking stack */
+#define stackidx(ptop)	((ptop) + 4)
+
+
+
+typedef unsigned char byte;
+
+
+#define BITSPERCHAR		8
+
+#define CHARSETSIZE		((UCHAR_MAX/BITSPERCHAR) + 1)
+
+
+
+typedef struct Charset {
+  byte cs[CHARSETSIZE];
+} Charset;
+
+
+
+#define loopset(v,b)    { int v; for (v = 0; v < CHARSETSIZE; v++) {b;} }
+
+/* access to charset */
+#define treebuffer(t)      ((byte *)((t) + 1))
+
+/* number of slots needed for 'n' bytes */
+#define bytes2slots(n)  (((n) - 1) / sizeof(TTree) + 1)
+
+/* set 'b' bit in charset 'cs' */
+#define setchar(cs,b)   ((cs)[(b) >> 3] |= (1 << ((b) & 7)))
+
+
+/*
+** in capture instructions, 'kind' of capture and its offset are
+** packed in field 'aux', 4 bits for each
+*/
+#define getkind(op)		((op)->i.aux & 0xF)
+#define getoff(op)		(((op)->i.aux >> 4) & 0xF)
+#define joinkindoff(k,o)	((k) | ((o) << 4))
+
+#define MAXOFF		0xF
+#define MAXAUX		0xFF
+
+
+/* maximum number of bytes to look behind */
+#define MAXBEHIND	MAXAUX
+
+
+/* maximum size (in elements) for a pattern */
+#define MAXPATTSIZE	(SHRT_MAX - 10)
+
+
+/* size (in elements) for an instruction plus extra l bytes */
+#define instsize(l)  (((l) + sizeof(Instruction) - 1)/sizeof(Instruction) + 1)
+
+
+/* size (in elements) for a ISet instruction */
+#define CHARSETINSTSIZE		instsize(CHARSETSIZE)
+
+/* size (in elements) for a IFunc instruction */
+#define funcinstsize(p)		((p)->i.aux + 2)
+
+
+
+#define testchar(st,c)	(((int)(st)[((c) >> 3)] & (1 << ((c) & 7))))
+
+
+#endif
+
+/*
+** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $
+*/
+
+#if !defined(lpcap_h)
+#define lpcap_h
+
+
+/* #include "lptypes.h" */
+
+
+/* kinds of captures */
+typedef enum CapKind {
+  Cclose,  /* not used in trees */
+  Cposition,
+  Cconst,  /* ktable[key] is Lua constant */
+  Cbackref,  /* ktable[key] is "name" of group to get capture */
+  Carg,  /* 'key' is arg's number */
+  Csimple,  /* next node is pattern */
+  Ctable,  /* next node is pattern */
+  Cfunction,  /* ktable[key] is function; next node is pattern */
+  Cquery,  /* ktable[key] is table; next node is pattern */
+  Cstring,  /* ktable[key] is string; next node is pattern */
+  Cnum,  /* numbered capture; 'key' is number of value to return */
+  Csubst,  /* substitution capture; next node is pattern */
+  Cfold,  /* ktable[key] is function; next node is pattern */
+  Cruntime,  /* not used in trees (is uses another type for tree) */
+  Cgroup  /* ktable[key] is group's "name" */
+} CapKind;
+
+
+typedef struct Capture {
+  const char *s;  /* subject position */
+  unsigned short idx;  /* extra info (group name, arg index, etc.) */
+  byte kind;  /* kind of capture */
+  byte siz;  /* size of full capture + 1 (0 = not a full capture) */
+} Capture;
+
+
+typedef struct CapState {
+  Capture *cap;  /* current capture */
+  Capture *ocap;  /* (original) capture list */
+  lua_State *L;
+  int ptop;  /* index of last argument to 'match' */
+  const char *s;  /* original string */
+  int valuecached;  /* value stored in cache slot */
+} CapState;
+
+
+int runtimecap (CapState *cs, Capture *close, const char *s, int *rem);
+int getcaptures (lua_State *L, const char *s, const char *r, int ptop);
+int finddyncap (Capture *cap, Capture *last);
+
+#endif
+
+
+/*  
+** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $
+*/
+
+#if !defined(lptree_h)
+#define lptree_h
+
+
+/* #include "lptypes.h"  */
+
+
+/*
+** types of trees
+*/
+typedef enum TTag {
+  TChar = 0,  /* 'n' = char */
+  TSet,  /* the set is stored in next CHARSETSIZE bytes */
+  TAny,
+  TTrue,
+  TFalse,
+  TRep,  /* 'sib1'* */
+  TSeq,  /* 'sib1' 'sib2' */
+  TChoice,  /* 'sib1' / 'sib2' */
+  TNot,  /* !'sib1' */
+  TAnd,  /* &'sib1' */
+  TCall,  /* ktable[key] is rule's key; 'sib2' is rule being called */
+  TOpenCall,  /* ktable[key] is rule's key */
+  TRule,  /* ktable[key] is rule's key (but key == 0 for unused rules);
+             'sib1' is rule's pattern;
+             'sib2' is next rule; 'cap' is rule's sequential number */
+  TGrammar,  /* 'sib1' is initial (and first) rule */
+  TBehind,  /* 'sib1' is pattern, 'n' is how much to go back */
+  TCapture,  /* captures: 'cap' is kind of capture (enum 'CapKind');
+                ktable[key] is Lua value associated with capture;
+                'sib1' is capture body */
+  TRunTime  /* run-time capture: 'key' is Lua function;
+               'sib1' is capture body */
+} TTag;
+
+
+/*
+** Tree trees
+** The first child of a tree (if there is one) is immediately after
+** the tree.  A reference to a second child (ps) is its position
+** relative to the position of the tree itself.
+*/
+typedef struct TTree {
+  byte tag;
+  byte cap;  /* kind of capture (if it is a capture) */
+  unsigned short key;  /* key in ktable for Lua data (0 if no key) */
+  union {
+    int ps;  /* occasional second child */
+    int n;  /* occasional counter */
+  } u;
+} TTree;
+
+
+/*
+** A complete pattern has its tree plus, if already compiled,
+** its corresponding code
+*/
+typedef struct Pattern {
+  union Instruction *code;
+  int codesize;
+  TTree tree[1];
+} Pattern;
+
+
+/* number of children for each tree */
+extern const byte numsiblings[];
+
+/* access to children */
+#define sib1(t)         ((t) + 1)
+#define sib2(t)         ((t) + (t)->u.ps)
+
+
+
+
+
+
+#endif
+
+/*
+** $Id: lpvm.h,v 1.3 2014/02/21 13:06:41 roberto Exp $
+*/
+
+#if !defined(lpvm_h)
+#define lpvm_h
+
+/* #include "lpcap.h" */
+
+
+/* Virtual Machine's instructions */
+typedef enum Opcode {
+  IAny, /* if no char, fail */
+  IChar,  /* if char != aux, fail */
+  ISet,  /* if char not in buff, fail */
+  ITestAny,  /* in no char, jump to 'offset' */
+  ITestChar,  /* if char != aux, jump to 'offset' */
+  ITestSet,  /* if char not in buff, jump to 'offset' */
+  ISpan,  /* read a span of chars in buff */
+  IBehind,  /* walk back 'aux' characters (fail if not possible) */
+  IRet,  /* return from a rule */
+  IEnd,  /* end of pattern */
+  IChoice,  /* stack a choice; next fail will jump to 'offset' */
+  IJmp,  /* jump to 'offset' */
+  ICall,  /* call rule at 'offset' */
+  IOpenCall,  /* call rule number 'key' (must be closed to a ICall) */
+  ICommit,  /* pop choice and jump to 'offset' */
+  IPartialCommit,  /* update top choice to current position and jump */
+  IBackCommit,  /* "fails" but jump to its own 'offset' */
+  IFailTwice,  /* pop one choice and then fail */
+  IFail,  /* go back to saved state on choice and jump to saved offset */
+  IGiveup,  /* internal use */
+  IFullCapture,  /* complete capture of last 'off' chars */
+  IOpenCapture,  /* start a capture */
+  ICloseCapture,
+  ICloseRunTime
+} Opcode;
+
+
+
+typedef union Instruction {
+  struct Inst {
+    byte code;
+    byte aux;
+    short key;
+  } i;
+  int offset;
+  byte buff[1];
+} Instruction;
+
+
+void printpatt (Instruction *p, int n);
+const char *match (lua_State *L, const char *o, const char *s, const char *e,
+                   Instruction *op, Capture *capture, int ptop);
+
+
+#endif
+
+/*
+** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $
+*/
+
+#if !defined(lpcode_h)
+#define lpcode_h
+
+/*#include "lua.h"*/
+
+/* #include "lptypes.h" */
+/* #include "lptree.h" */
+/* #include "lpvm.h" */
+
+int tocharset (TTree *tree, Charset *cs);
+int checkaux (TTree *tree, int pred);
+int fixedlen (TTree *tree);
+int hascaptures (TTree *tree);
+int lp_gc (lua_State *L);
+Instruction *compile (lua_State *L, Pattern *p);
+void realloccode (lua_State *L, Pattern *p, int nsize);
+int sizei (const Instruction *i);
+
+
+#define PEnullable      0
+#define PEnofail        1
+
+/*
+** nofail(t) implies that 't' cannot fail with any input
+*/
+#define nofail(t)	checkaux(t, PEnofail)
+
+/*
+** (not nullable(t)) implies 't' cannot match without consuming
+** something
+*/
+#define nullable(t)	checkaux(t, PEnullable)
+
+
+
+#endif
+/*
+** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
+*/
+
+
+#if !defined(lpprint_h)
+#define lpprint_h
+
+
+/* #include "lptree.h" */
+/* #include "lpvm.h" */
+
+
+#if defined(LPEG_DEBUG)
+
+void printpatt (Instruction *p, int n);
+void printtree (TTree *tree, int ident);
+void printktable (lua_State *L, int idx);
+void printcharset (const byte *st);
+void printcaplist (Capture *cap, Capture *limit);
+void printinst (const Instruction *op, const Instruction *p);
+
+#else
+
+#define printktable(L,idx)  \
+	luaL_error(L, "function only implemented in debug mode")
+#define printtree(tree,i)  \
+	luaL_error(L, "function only implemented in debug mode")
+#define printpatt(p,n)  \
+	luaL_error(L, "function only implemented in debug mode")
+
+#endif
+
+
+#endif
+

Added: trunk/Build/source/texk/web2c/mfluadir/mflua_svnversion.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/mflua_svnversion.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/mflua_svnversion.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1 @@
+#define mflua_svn_revision "80"

Modified: trunk/Build/source/texk/web2c/mfluadir/mflua_version.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/mflua_version.h	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/mflua_version.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,2 +1,2 @@
 #define MFLUA_VERSION "1.0.0-alpha"
-#define BANNER "This is MFLua, Version 2.71828182-" MFLUA_VERSION
+#define BANNER "This is MFLua, Version 2.71828182-" MFLUA_VERSION 

Modified: trunk/Build/source/texk/web2c/mfluadir/mfluac.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/mfluac.c	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/mfluac.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -17,7 +17,11 @@
 #include <luajit.h>
 #endif
 
+#include "potrace/luafunc.h"
 
+#include "luapeg/lpeg.h"
+
+/* otfcc */
 #if defined(NO_OTFCC)
 /* */
 #else
@@ -25,6 +29,9 @@
 extern int otfcc_dump(int argc, char *argv[]);
 #endif
 
+extern int luaopen_lpeg(lua_State *L);
+extern int mfluaopen_lpeg(lua_State * L);
+
 /* See  shell_cmd_is_allowed below */
 int shellenabledp = 1;
 int restrictedshell = 0;
@@ -482,10 +489,17 @@
   return 1;
 }
 
+static int priv_mflua_developid(lua_State *L)
+{
+  lua_pushstring(L,mflua_svn_revision);
+  return 1;
+}
 
+
+
 /**************************************************************/
 /*                                                            */
-/* otfcc private functions                                    */
+/* Adapters for LuaJIT                                        */
 /*                                                            */
 /**************************************************************/
 
@@ -520,8 +534,22 @@
   lua_gettable(L, index);
   return lua_type(L, -1);
 }
+static void lua_seti (lua_State *L, int index, lua_Integer i) {
+  index = lua_absindex(L, index);
+  lua_pushinteger(L, i);
+  lua_insert(L, -2);
+  lua_settable(L, index);
+}
 #endif
 
+
+/**************************************************************/
+/*                                                            */
+/* otfcc private functions                                    */
+/*                                                            */
+/**************************************************************/
+
+
 static int priv_mflua_otf_dump(lua_State *L) {
     if (!lua_istable(L, -1)) {
       fprintf(stderr, "! dump: expected a table\n");
@@ -632,7 +660,183 @@
 }
 
 
+/**************************************************************/
+/*                                                            */
+/* private potrace layer                                      */
+/*                                                            */
+/**************************************************************/
 
+
+static int priv_mflua_potrace_build(lua_State *L) {
+  int w,h;
+  size_t l;
+  const uint8_t *raster;
+  MFoutlines_param_t opt_param;
+  potrace_state_t *trace;
+  potrace_path_t *p;
+  potrace_dpoint_t (*c)[3];
+  double xoffs,yoffs;
+  int n,i,*tag,jj;
+
+  w=h=0;
+  raster=NULL;
+  l=0;
+  opt_param.xoffs = opt_param.yoffs = 0.0;
+  opt_param.potrace_param = NULL;
+  trace = NULL;
+
+  raster = (const uint8_t*) luaL_checklstring(L,1,&l);
+  if (raster==NULL) {
+   fprintf(stderr,"! raster is empty\n");
+   lua_settop(L,0);
+   return 0;
+  }
+  w = (int)luaL_checkinteger(L,2);
+  h = (int)luaL_checkinteger(L,3);
+  
+  if ( (w%8==0? w/8:(w/8+1))*h != l) {
+   fprintf(stderr,"! raster dimension is wrong\n");
+   lua_settop(L,0);
+   return 0;
+  }
+
+  /* optional param table */
+  if (lua_istable(L,4)){
+    lua_getfield(L,4, "xoffs");
+    if (lua_isnumber(L,-1)){
+      opt_param.xoffs = (double)lua_tonumber(L,-1);
+    }
+    lua_pop(L,1);
+    lua_getfield(L,4, "yoffs");
+    if (lua_isnumber(L,-1)){
+      opt_param.yoffs = (double)lua_tonumber(L,-1);
+    }
+    lua_pop(L,1);
+    lua_getfield(L,4, "potrace_params");
+    if (lua_istable(L,-1)){
+      opt_param.potrace_param = potrace_param_default();
+      if (!opt_param.potrace_param) {
+	fprintf(stderr, "! Error allocating potrace_param: %s\n", strerror(errno)); 
+	lua_settop(L,0);
+	return 0;
+      }
+      lua_getfield(L,-1,"turdsize");      if(lua_isnumber(L,-1)){opt_param.potrace_param->turdsize    =(int)(lua_tonumber(L,-1))   ;};lua_pop(L,1); 
+      lua_getfield(L,-1,"alphamax");      if(lua_isnumber(L,-1)){opt_param.potrace_param->alphamax    =(double)(lua_tonumber(L,-1));};lua_pop(L,1);
+      lua_getfield(L,-1,"opticurve");     if(lua_isnumber(L,-1)){opt_param.potrace_param->opticurve   =(int)(lua_tonumber(L,-1))   ;};lua_pop(L,1);
+      lua_getfield(L,-1,"opttolerance");  if(lua_isnumber(L,-1)){opt_param.potrace_param->opttolerance=(double)(lua_tonumber(L,-1));};lua_pop(L,1);
+      lua_getfield(L,-1,"turnpolicy");
+      if(lua_isnumber(L,-1)){
+	switch ((int)(lua_tonumber(L,-1))) {
+	case 1:
+	  opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_BLACK;
+	  break;
+	case 2:
+          opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_WHITE;
+          break;
+	case 3:
+          opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_LEFT;
+          break;
+	case 4:
+          opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_RIGHT;
+          break;
+	case 5: 
+	  opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_MINORITY;
+	  break;
+	case 6:
+	  opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_MAJORITY;
+	  break;;
+	case 7:
+	  opt_param.potrace_param->turnpolicy = POTRACE_TURNPOLICY_RANDOM;
+	  break;
+	default:
+          break;
+	}
+      }
+      lua_pop(L,1);
+    }
+  }
+  lua_pop(L,1);
+
+  if (potrace_getMFoutlines(raster,w,h,opt_param,&trace)) {
+   lua_settop(L,0);
+   return 0;
+  }
+
+  jj=1;
+  lua_newtable(L); // main table 
+
+  xoffs = opt_param.xoffs;yoffs = opt_param.yoffs;
+  //printf("%%%%!PS-Adobe-3.0 EPSF-3.0\n");
+  //printf("%%%%Creator: MFLua / potrace 1.16, written by Peter Selinger 2001-2019\n");
+  //printf("%%%%BoundingBox: %d %d %d %d\n", (int)(xoffs),(int)(yoffs), w, h);
+  //printf("%%%%HiResBoundingBox: %f %f %f %f\n",xoffs,yoffs, (double)(w), (double)(h));
+  //printf("%%%%Pages: 1\n");
+  //printf("%%%%EndComments\n");
+  //printf("gsave\n");
+  /* draw each curve */
+  p = trace->plist;
+  while (p != NULL) {
+    double px,py,c1x,c1y,c2x,c2y,qx,qy;
+    int j=1;
+    lua_newtable(L); // table for the cycle
+    n = p->curve.n;
+    tag = p->curve.tag;
+    c = p->curve.c;
+    //printf("%f %f moveto\n", c[n-1][2].x+xoffs, c[n-1][2].y+yoffs);
+    px=c[n-1][2].x+xoffs;py=c[n-1][2].y+yoffs; //lua_pushnumber(L,py);lua_pushnumber(L,px);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+    for (i=0; i<n; i++) {
+      lua_pushnumber(L,py);lua_pushnumber(L,px);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+      switch (tag[i]) {
+      case POTRACE_CORNER:
+        //printf("%f %f lineto\n", c[i][1].x+xoffs, c[i][1].y+yoffs);
+        //printf("%f %f lineto\n", c[i][2].x+xoffs, c[i][2].y+yoffs);
+        c1x=px;c1y=py;                          lua_pushnumber(L,c1y);lua_pushnumber(L,c1x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        c2x=c[i][1].x+xoffs;c2y=c[i][1].y+yoffs;lua_pushnumber(L,c2y);lua_pushnumber(L,c2x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        qx=c2x;qy=c2y;                          lua_pushnumber(L,qy); lua_pushnumber(L,qx); lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        px=qx;py=qy;                            lua_pushnumber(L,py); lua_pushnumber(L,px); lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        c1x=px;c1y=py;                          lua_pushnumber(L,c1y);lua_pushnumber(L,c1x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        c2x=c[i][2].x+xoffs;c2y=c[i][2].y+yoffs;lua_pushnumber(L,c2y);lua_pushnumber(L,c2x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        qx=c2x;qy=c2y;                          lua_pushnumber(L,qy); lua_pushnumber(L,qx); lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        break;
+      case POTRACE_CURVETO:
+        //printf("%f %f %f %f %f %f curveto\n", 
+        //       c[i][0].x+xoffs, c[i][0].y+yoffs,
+        //       c[i][1].x+xoffs, c[i][1].y+yoffs,
+        //       c[i][2].x+xoffs, c[i][2].y+yoffs);
+        c1x=c[i][0].x+xoffs;c1y=c[i][0].y+yoffs;lua_pushnumber(L,c1y);lua_pushnumber(L,c1x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        c2x=c[i][1].x+xoffs;c2y=c[i][1].y+yoffs;lua_pushnumber(L,c2y);lua_pushnumber(L,c2x);lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        qx=c[i][2].x+xoffs;qy=c[i][2].y+yoffs;  lua_pushnumber(L,qy); lua_pushnumber(L,qx); lua_seti(L,-3,j++);lua_seti(L,-2,j++);
+        break;
+      }
+      px=qx;py=qy;
+    }
+    /* at the end of a group of a positive path and its negative
+       children, fill. */
+    if (p->next == NULL || p->next->sign == '+') {
+      //printf("0 setgray fill\n");
+      lua_pushstring (L,"+");lua_seti(L,-2,j++);
+    } else if(p->next->sign == '-') {
+      lua_pushstring (L,"-");lua_seti(L,-2,j++);
+    }
+    /* save the cycle into the main table */
+    lua_seti(L,-2,jj++);
+    p = p->next;
+  }
+  //printf("grestore\n");
+  //printf("%%%%EOF\n");
+  
+  if (trace) {
+   potrace_state_free(trace);
+  }
+  if(opt_param.potrace_param){
+    potrace_param_free(opt_param.potrace_param);
+  }
+  lua_settop(L,-1); 
+  return 1;
+  //return 0;
+ 
+}
+
 /**************************************************************/
 /*                                                            */
 /* mflua layer                                                */
@@ -675,6 +879,7 @@
   {"turning_number", priv_mfweb_LUAGLOBALGET_turning_number},
   {"mflua_version",priv_mflua_version},
   {"mflua_banner",priv_mflua_banner},
+  {"mflua_developid",priv_mflua_developid},
   {NULL, NULL}                /* sentinel */
 };
 
@@ -684,7 +889,13 @@
     { NULL,        NULL}
 };
 
+static struct luaL_Reg mflua_trace[] = {
+    { "trace", priv_mflua_potrace_build },
+    { NULL,        NULL}
+};
 
+
+
 #define lua_swap(L) lua_insert(L, -2) 
   
 #define GETGLOBALTABLEMFLUA(a)  lua_getglobal(L, "mflua");\
@@ -710,6 +921,17 @@
   luaopen_kpse(L);
   /* to be sure of having a clear stack */
   lua_settop(L,0);
+  /* lpeg */
+#ifdef MFLuaJIT
+  lua_pushcfunction(L, luaopen_lpeg);
+  lua_pushstring(L, "lpeg");
+  lua_call(L, 1, 0);
+#else
+  luaL_requiref(L, "lpeg",luaopen_lpeg,1);
+  lua_pop(L, 1);
+#endif
+  /* to be sure of having a clear stack */
+  lua_settop(L,0);
   
 
   lua_getglobal(L, "mflua");
@@ -722,6 +944,8 @@
     if (!lua_istable(L, -1)) {
       printf("mflua table NOT registered!\n");
     } else {
+
+      /* set the MFbuiltin table */
       lua_pushstring(L,"MFbuiltin");
 #ifdef MFLuaJIT
       /* 5.1 */ 
@@ -732,6 +956,7 @@
       luaL_newlib(L,MFbuiltin_l);
 #endif
       lua_settable(L, -3);
+
       /* set the otfcc table */
       lua_pushstring(L,"otf");
 #ifdef MFLuaJIT
@@ -742,7 +967,17 @@
       luaL_newlib(L,mflua_otfcc);
 #endif
       lua_settable(L, -3);
-      
+
+      /* set the trace table */
+      lua_pushstring(L,"trace");
+#ifdef MFLuaJIT
+      /* 5.1 */
+      lua_newtable(L);
+      luaL_register (L,NULL,mflua_trace);
+#else
+      luaL_newlib(L,mflua_trace);
+#endif
+      lua_settable(L, -3);
     }
     lua_pop(L,1);
   }
@@ -770,8 +1005,11 @@
   GETGLOBALTABLEMFLUA(mfluabeginprogram);
   if (lua_istable(L, -1)) {
     lua_getfield(L,-1,"begin_program");
-    if((res=lua_pcall(L,0,0,0)))
+    if((res=lua_pcall(L,0,0,0))) {
+      lua_pushstring(L,"error in begin_program:");
+      lua_swap(L);lua_concat (L, 2);
       priv_lua_reporterrors(L, res);
+    }
   }
  EXIT:
   lua_settop(L,0);

Modified: trunk/Build/source/texk/web2c/mfluadir/mfluac.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/mfluac.h	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluadir/mfluac.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,6 +1,7 @@
 #ifndef MFLUAC_H
 #define MFLUAC_H
 
+#include <mfluadir/mflua_svnversion.h>
 #include <mfluadir/mflua_version.h> 
 extern int mfluabeginprogram(void);
 extern int mfluaPREstartofMF(void);
@@ -54,4 +55,6 @@
 #include <lauxlib.h>
 extern int luaopen_kpse(lua_State * L);
 
+#include <mfluadir/potrace/potracelib.h>
+
 #endif /* MFLUAC_H */

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/auxiliary.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/auxiliary.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/auxiliary.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,80 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+/* This header file collects some general-purpose macros (and static
+   inline functions) that are used in various places. */
+
+#ifndef AUXILIARY_H
+#define AUXILIARY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+/* ---------------------------------------------------------------------- */
+/* point arithmetic */
+
+#include "potracelib.h"
+
+struct point_s {
+  long x;
+  long y;
+};
+typedef struct point_s point_t;
+
+typedef potrace_dpoint_t dpoint_t;
+
+/* convert point_t to dpoint_t */
+static inline dpoint_t dpoint(point_t p) {
+  dpoint_t res;
+  res.x = p.x;
+  res.y = p.y;
+  return res;
+}
+
+/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
+static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
+  dpoint_t res;
+
+  res.x = a.x + lambda * (b.x - a.x);
+  res.y = a.y + lambda * (b.y - a.y);
+  return res;
+}
+
+/* ---------------------------------------------------------------------- */
+/* some useful macros. Note: the "mod" macro works correctly for
+   negative a. Also note that the test for a>=n, while redundant,
+   speeds up the mod function by 70% in the average case (significant
+   since the program spends about 16% of its time here - or 40%
+   without the test). The "floordiv" macro returns the largest integer
+   <= a/n, and again this works correctly for negative a, as long as
+   a,n are integers and n>0. */
+
+/* integer arithmetic */
+
+static inline int mod(int a, int n) {
+  return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
+}
+
+static inline int floordiv(int a, int n) {
+  return a>=0 ? a/n : -1-(-1-a)/n;
+}
+
+/* Note: the following work for integers and other numeric types. */
+#undef sign
+#undef abs
+#undef min
+#undef max
+#undef sq
+#undef cu
+#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0)
+#define abs(a) ((a)>0 ? (a) : -(a))
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#define sq(a) ((a)*(a))
+#define cu(a) ((a)*(a)*(a))
+
+#endif /* AUXILIARY_H */

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/bitmap.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/bitmap.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/bitmap.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,228 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+/* The bitmap type is defined in potracelib.h */
+#include "potracelib.h"
+
+/* The present file defines some convenient macros and static inline
+   functions for accessing bitmaps. Since they only produce inline
+   code, they can be conveniently shared by the library and frontends,
+   if desired */
+
+/* ---------------------------------------------------------------------- */
+/* some measurements */
+
+#define BM_WORDSIZE ((int)sizeof(potrace_word))
+#define BM_WORDBITS (8*BM_WORDSIZE)
+#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
+#define BM_ALLBITS (~(potrace_word)0)
+
+/* macros for accessing pixel at index (x,y). U* macros omit the
+   bounds check. */
+
+#define bm_scanline(bm, y) ((bm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(bm)->dy)
+#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
+#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
+#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
+#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
+#define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0)
+#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
+#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
+#define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x))
+#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
+#define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0)
+#define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0)
+#define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0)
+#define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0)
+#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
+
+/* calculate the size, in bytes, required for the data area of a
+   bitmap of the given dy and h. Assume h >= 0. Return -1 if the size
+   does not fit into the ptrdiff_t type. */
+static inline ptrdiff_t getsize(int dy, int h) {
+  ptrdiff_t size;
+
+  if (dy < 0) {
+    dy = -dy;
+  }
+  
+  size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE;
+
+  /* check for overflow error */
+  if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) {
+    return -1;
+  }
+
+  return size;
+}
+
+/* return the size, in bytes, of the data area of the bitmap. Return
+   -1 if the size does not fit into the ptrdiff_t type; however, this
+   cannot happen if the bitmap is well-formed, i.e., if created with
+   bm_new or bm_dup. */
+static inline ptrdiff_t bm_size(const potrace_bitmap_t *bm) {
+  return getsize(bm->dy, bm->h);
+}
+
+/* calculate the base address of the bitmap data. Assume that the
+   bitmap is well-formed, i.e., its size fits into the ptrdiff_t type.
+   This is the case if created with bm_new or bm_dup. The base address
+   may differ from bm->map if dy is negative */
+static inline potrace_word *bm_base(const potrace_bitmap_t *bm) {
+  int dy = bm->dy;
+
+  if (dy >= 0 || bm->h == 0) {
+    return bm->map;
+  } else {
+    return bm_scanline(bm, bm->h - 1);
+  }  
+}
+
+/* free the given bitmap. Leaves errno untouched. */
+static inline void bm_free(potrace_bitmap_t *bm) {
+  if (bm && bm->map) {
+    free(bm_base(bm));
+  }
+  free(bm);
+}
+
+/* return new bitmap initialized to 0. NULL with errno on error.
+   Assumes w, h >= 0. */
+static inline potrace_bitmap_t *bm_new(int w, int h) {
+  potrace_bitmap_t *bm;
+  int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
+  ptrdiff_t size;
+
+  size = getsize(dy, h);
+  if (size < 0) {
+    errno = ENOMEM;
+    return NULL;
+  }
+  if (size == 0) {
+    size = BM_WORDSIZE; /* make sure calloc() doesn't return NULL */
+  } 
+
+  bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
+  if (!bm) {
+    return NULL;
+  }
+  bm->w = w;
+  bm->h = h;
+  bm->dy = dy;
+  bm->map = (potrace_word *) calloc(1, size);
+  if (!bm->map) {
+    free(bm);
+    return NULL;
+  }
+  return bm;
+}
+
+/* clear the given bitmap. Set all bits to c. Assumes a well-formed
+   bitmap. */
+static inline void bm_clear(potrace_bitmap_t *bm, int c) {
+  /* Note: if the bitmap was created with bm_new, then it is
+     guaranteed that size will fit into the ptrdiff_t type. */
+  ptrdiff_t size = bm_size(bm);
+  memset(bm_base(bm), c ? -1 : 0, size);
+}
+
+/* duplicate the given bitmap. Return NULL on error with errno
+   set. Assumes a well-formed bitmap. */
+static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
+  potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
+  int y;
+  
+  if (!bm1) {
+    return NULL;
+  }
+  for (y=0; y < bm->h; y++) {
+    memcpy(bm_scanline(bm1, y), bm_scanline(bm, y), (size_t)bm1->dy * (size_t)BM_WORDSIZE);
+  }
+  return bm1;
+}
+
+/* invert the given bitmap. */
+static inline void bm_invert(potrace_bitmap_t *bm) {
+  int dy = bm->dy;
+  int y;
+  int i;
+  potrace_word *p;
+
+  if (dy < 0) {
+    dy = -dy;
+  }
+  
+  for (y=0; y < bm->h; y++) {
+    p = bm_scanline(bm, y);
+    for (i=0; i < dy; i++) {
+      p[i] ^= BM_ALLBITS;
+    }
+  }
+}
+
+/* turn the given bitmap upside down. This does not move the bitmap
+   data or change the bm_base() address. */
+static inline void bm_flip(potrace_bitmap_t *bm) {
+  int dy = bm->dy;
+
+  if (bm->h == 0 || bm->h == 1) {
+    return;
+  }
+  
+  bm->map = bm_scanline(bm, bm->h - 1);
+  bm->dy = -dy;
+}
+
+/* resize the bitmap to the given new height. The bitmap data remains
+   bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
+   (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
+   error with errno set. If the new height is <= the old one, no error
+   should occur. If the new height is larger, the additional bitmap
+   data is *not* initialized. */
+static inline int bm_resize(potrace_bitmap_t *bm, int h) {
+  int dy = bm->dy;
+  ptrdiff_t newsize;
+  potrace_word *newmap;
+
+  if (dy < 0) {
+    bm_flip(bm);
+  }
+  
+  newsize = getsize(dy, h);
+  if (newsize < 0) {
+    errno = ENOMEM;
+    goto error;
+  }
+  if (newsize == 0) {
+    newsize = BM_WORDSIZE; /* make sure realloc() doesn't return NULL */
+  }
+  
+  newmap = (potrace_word *)realloc(bm->map, newsize);
+  if (newmap == NULL) {
+    goto error;
+  }
+  bm->map = newmap;
+  bm->h = h;
+
+  if (dy < 0) {
+    bm_flip(bm);
+  }
+  return 0;
+  
+ error:
+  if (dy < 0) {
+    bm_flip(bm);
+  }
+  return 1;  
+}
+
+#endif /* BITMAP_H */

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/config.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/config.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/config.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,5 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+#define VERSION "1.16"
+#define HAVE_INTTYPES_H 1
+#endif

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/curve.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/curve.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/curve.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,112 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+/* private part of the path and curve data structures */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "lists.h"
+#include "curve.h"
+
+#define SAFE_CALLOC(var, n, typ) \
+  if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error 
+
+/* ---------------------------------------------------------------------- */
+/* allocate and free path objects */
+
+path_t *path_new(void) {
+  path_t *p = NULL;
+  privpath_t *priv = NULL;
+
+  SAFE_CALLOC(p, 1, path_t);
+  memset(p, 0, sizeof(path_t));
+  SAFE_CALLOC(priv, 1, privpath_t);
+  memset(priv, 0, sizeof(privpath_t));
+  p->priv = priv;
+  return p;
+
+ calloc_error:
+  free(p);
+  free(priv);
+  return NULL;
+}
+
+/* free the members of the given curve structure. Leave errno unchanged. */
+static void privcurve_free_members(privcurve_t *curve) {
+  free(curve->tag);
+  free(curve->c);
+  free(curve->vertex);
+  free(curve->alpha);
+  free(curve->alpha0);
+  free(curve->beta);
+}
+
+/* free a path. Leave errno untouched. */
+void path_free(path_t *p) {
+  if (p) {
+    if (p->priv) {
+      free(p->priv->pt);
+      free(p->priv->lon);
+      free(p->priv->sums);
+      free(p->priv->po);
+      privcurve_free_members(&p->priv->curve);
+      privcurve_free_members(&p->priv->ocurve);
+    }
+    free(p->priv);
+    /* do not free p->fcurve ! */
+  }
+  free(p);
+}  
+
+/* free a pathlist, leaving errno untouched. */
+void pathlist_free(path_t *plist) {
+  path_t *p;
+
+  list_forall_unlink(p, plist) {
+    path_free(p);
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+/* initialize and finalize curve structures */
+
+typedef dpoint_t dpoint3_t[3];
+
+/* initialize the members of the given curve structure to size m.
+   Return 0 on success, 1 on error with errno set. */
+int privcurve_init(privcurve_t *curve, int n) {
+  memset(curve, 0, sizeof(privcurve_t));
+  curve->n = n;
+  SAFE_CALLOC(curve->tag, n, int);
+  SAFE_CALLOC(curve->c, n, dpoint3_t);
+  SAFE_CALLOC(curve->vertex, n, dpoint_t);
+  SAFE_CALLOC(curve->alpha, n, double);
+  SAFE_CALLOC(curve->alpha0, n, double);
+  SAFE_CALLOC(curve->beta, n, double);
+  return 0;
+
+ calloc_error:
+  free(curve->tag);
+  free(curve->c);
+  free(curve->vertex);
+  free(curve->alpha);
+  free(curve->alpha0);
+  free(curve->beta);
+  return 1;
+}
+
+/* copy private to public curve structure */
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) {
+  c->n = pc->n;
+  c->tag = pc->tag;
+  c->c = pc->c;
+}
+    

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/curve.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/curve.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/curve.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,77 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef CURVE_H
+#define CURVE_H
+
+#include "auxiliary.h"
+
+/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
+   .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
+   defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve:
+   .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and
+   c[2]..c[1] = alpha*(c[2]..vertex).
+   Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
+*/
+
+struct privcurve_s {
+  int n;            /* number of segments */
+  int *tag;         /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
+  dpoint_t (*c)[3]; /* c[n][i]: control points. 
+		       c[n][0] is unused for tag[n]=POTRACE_CORNER */
+  /* the remainder of this structure is special to privcurve, and is
+     used in EPS debug output and special EPS "short coding". These
+     fields are valid only if "alphacurve" is set. */
+  int alphacurve;   /* have the following fields been initialized? */
+  dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
+  double *alpha;    /* only for POTRACE_CURVETO */
+  double *alpha0;   /* "uncropped" alpha parameter - for debug output only */
+  double *beta;
+};
+typedef struct privcurve_s privcurve_t;
+
+struct sums_s {
+  double x;
+  double y;
+  double x2;
+  double xy;
+  double y2;
+};
+typedef struct sums_s sums_t;
+
+/* the path structure is filled in with information about a given path
+   as it is accumulated and passed through the different stages of the
+   Potrace algorithm. Backends only need to read the fcurve and fm
+   fields of this data structure, but debugging backends may read
+   other fields. */
+struct potrace_privpath_s {
+  int len;
+  point_t *pt;     /* pt[len]: path as extracted from bitmap */
+  int *lon;        /* lon[len]: (i,lon[i]) = longest straight line from i */
+
+  int x0, y0;      /* origin for sums */
+  sums_t *sums;    /* sums[len+1]: cache for fast summing */
+
+  int m;           /* length of optimal polygon */
+  int *po;         /* po[m]: optimal polygon */
+
+  privcurve_t curve;   /* curve[m]: array of curve elements */
+  privcurve_t ocurve;  /* ocurve[om]: array of curve elements */
+  privcurve_t *fcurve;  /* final curve: this points to either curve or
+		       ocurve. Do not free this separately. */
+};
+typedef struct potrace_privpath_s potrace_privpath_t;
+
+/* shorter names */
+typedef potrace_privpath_t privpath_t;
+typedef potrace_path_t path_t;
+
+path_t *path_new(void);
+void path_free(path_t *p);
+void pathlist_free(path_t *plist);
+int privcurve_init(privcurve_t *curve, int n);
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c);
+
+#endif /* CURVE_H */
+

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,521 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "bitmap.h"
+#include "decompose.h"
+#include "progress.h"
+
+/* ---------------------------------------------------------------------- */
+/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
+
+static inline int detrand(int x, int y) {
+  unsigned int z;
+  static const unsigned char t[256] = { 
+    /* non-linear sequence: constant term of inverse in GF(8), 
+       mod x^8+x^4+x^3+x+1 */
+    0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 
+    0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 
+    0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 
+    1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 
+    0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 
+    0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 
+    0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 
+    0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 
+    1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 
+    0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 
+    1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 
+  };
+
+  /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
+     5-bit sequence */
+  z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
+  z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
+  return z;
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary bitmap manipulations */
+
+/* set the excess padding to 0 */
+static void bm_clearexcess(potrace_bitmap_t *bm) {
+  potrace_word mask;
+  int y;
+
+  if (bm->w % BM_WORDBITS != 0) {
+    mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
+    for (y=0; y<bm->h; y++) {
+      *bm_index(bm, bm->w, y) &= mask;
+    }
+  }
+}
+
+struct bbox_s {
+  int x0, x1, y0, y1;    /* bounding box */
+};
+typedef struct bbox_s bbox_t;
+
+/* clear the bm, assuming the bounding box is set correctly (faster
+   than clearing the whole bitmap) */
+static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
+  int imin = (bbox->x0 / BM_WORDBITS);
+  int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
+  int i, y;
+
+  for (y=bbox->y0; y<bbox->y1; y++) {
+    for (i=imin; i<imax; i++) {
+      bm_scanline(bm, y)[i] = 0;
+    }
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* return the "majority" value of bitmap bm at intersection (x,y). We
+   assume that the bitmap is balanced at "radius" 1.  */
+static int majority(potrace_bitmap_t *bm, int x, int y) {
+  int i, a, ct;
+
+  for (i=2; i<5; i++) { /* check at "radius" i */
+    ct = 0;
+    for (a=-i+1; a<=i-1; a++) {
+      ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
+      ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
+      ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
+      ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
+    }
+    if (ct>0) {
+      return 1;
+    } else if (ct<0) {
+      return 0;
+    }
+  }
+  return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* decompose image into paths */
+
+/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
+   must be a multiple of BM_WORDBITS. */
+static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
+  int xhi = x & -BM_WORDBITS;
+  int xlo = x & (BM_WORDBITS-1);  /* = x % BM_WORDBITS */
+  int i;
+  
+  if (xhi<xa) {
+    for (i = xhi; i < xa; i+=BM_WORDBITS) {
+      *bm_index(bm, i, y) ^= BM_ALLBITS;
+    }
+  } else {
+    for (i = xa; i < xhi; i+=BM_WORDBITS) {
+      *bm_index(bm, i, y) ^= BM_ALLBITS;
+    }
+  }
+  /* note: the following "if" is needed because x86 treats a<<b as
+     a<<(b&31). I spent hours looking for this bug. */
+  if (xlo) {
+    *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
+  }
+}
+
+/* a path is represented as an array of points, which are thought to
+   lie on the corners of pixels (not on their centers). The path point
+   (x,y) is the lower left corner of the pixel (x,y). Paths are
+   represented by the len/pt components of a path_t object (which
+   also stores other information about the path) */
+
+/* xor the given pixmap with the interior of the given path. Note: the
+   path must be within the dimensions of the pixmap. */
+static void xor_path(potrace_bitmap_t *bm, path_t *p) {
+  int xa, x, y, k, y1;
+
+  if (p->priv->len <= 0) {  /* a path of length 0 is silly, but legal */
+    return;
+  }
+
+  y1 = p->priv->pt[p->priv->len-1].y;
+
+  xa = p->priv->pt[0].x & -BM_WORDBITS;
+  for (k=0; k<p->priv->len; k++) {
+    x = p->priv->pt[k].x;
+    y = p->priv->pt[k].y;
+
+    if (y != y1) {
+      /* efficiently invert the rectangle [x,xa] x [y,y1] */
+      xor_to_ref(bm, x, min(y,y1), xa);
+      y1 = y;
+    }
+  }
+}
+
+/* Find the bounding box of a given path. Path is assumed to be of
+   non-zero length. */
+static void setbbox_path(bbox_t *bbox, path_t *p) {
+  int x, y;
+  int k;
+
+  bbox->y0 = INT_MAX;
+  bbox->y1 = 0;
+  bbox->x0 = INT_MAX;
+  bbox->x1 = 0;
+
+  for (k=0; k<p->priv->len; k++) {
+    x = p->priv->pt[k].x;
+    y = p->priv->pt[k].y;
+
+    if (x < bbox->x0) {
+      bbox->x0 = x;
+    }
+    if (x > bbox->x1) {
+      bbox->x1 = x;
+    }
+    if (y < bbox->y0) {
+      bbox->y0 = y;
+    }
+    if (y > bbox->y1) {
+      bbox->y1 = y;
+    }
+  }
+}
+
+/* compute a path in the given pixmap, separating black from white.
+   Start path at the point (x0,x1), which must be an upper left corner
+   of the path. Also compute the area enclosed by the path. Return a
+   new path_t object, or NULL on error (note that a legitimate path
+   cannot have length 0). Sign is required for correct interpretation
+   of turnpolicies. */
+static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
+  int x, y, dirx, diry, len, size;
+  uint64_t area;
+  int c, d, tmp;
+  point_t *pt, *pt1;
+  path_t *p = NULL;
+
+  x = x0;
+  y = y0;
+  dirx = 0;
+  diry = -1;
+
+  len = size = 0;
+  pt = NULL;
+  area = 0;
+  
+  while (1) {
+    /* add point to path */
+    if (len>=size) {
+      size += 100;
+      size = (int)(1.3 * size);
+      pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
+      if (!pt1) {
+	goto error;
+      }
+      pt = pt1;
+    }
+    pt[len].x = x;
+    pt[len].y = y;
+    len++;
+    
+    /* move to next point */
+    x += dirx;
+    y += diry;
+    area += x*diry;
+    
+    /* path complete? */
+    if (x==x0 && y==y0) {
+      break;
+    }
+    
+    /* determine next direction */
+    c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
+    d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
+    
+    if (c && !d) {               /* ambiguous turn */
+      if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
+	  || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
+	  || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
+	  || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
+	  || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
+	  || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
+	tmp = dirx;              /* right turn */
+	dirx = diry;
+	diry = -tmp;
+      } else {
+	tmp = dirx;              /* left turn */
+	dirx = -diry;
+	diry = tmp;
+      }
+    } else if (c) {              /* right turn */
+      tmp = dirx;
+      dirx = diry;
+      diry = -tmp;
+    } else if (!d) {             /* left turn */
+      tmp = dirx;
+      dirx = -diry;
+      diry = tmp;
+    }
+  } /* while this path */
+
+  /* allocate new path object */
+  p = path_new();
+  if (!p) {
+    goto error;
+  }
+
+  p->priv->pt = pt;
+  p->priv->len = len;
+  p->area = area <= INT_MAX ? area : INT_MAX; /* avoid overflow */
+  p->sign = sign;
+
+  return p;
+ 
+ error:
+   free(pt);
+   return NULL; 
+}
+
+/* Give a tree structure to the given path list, based on "insideness"
+   testing. I.e., path A is considered "below" path B if it is inside
+   path B. The input pathlist is assumed to be ordered so that "outer"
+   paths occur before "inner" paths. The tree structure is stored in
+   the "childlist" and "sibling" components of the path_t
+   structure. The linked list structure is also changed so that
+   negative path components are listed immediately after their
+   positive parent.  Note: some backends may ignore the tree
+   structure, others may use it e.g. to group path components. We
+   assume that in the input, point 0 of each path is an "upper left"
+   corner of the path, as returned by bm_to_pathlist. This makes it
+   easy to find an "interior" point. The bm argument should be a
+   bitmap of the correct size (large enough to hold all the paths),
+   and will be used as scratch space. Return 0 on success or -1 on
+   error with errno set. */
+
+static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
+  path_t *p, *p1;
+  path_t *heap, *heap1;
+  path_t *cur;
+  path_t *head;
+  path_t **plist_hook;          /* for fast appending to linked list */
+  path_t **hook_in, **hook_out; /* for fast appending to linked list */
+  bbox_t bbox;
+  
+  bm_clear(bm, 0);
+
+  /* save original "next" pointers */
+  list_forall(p, plist) {
+    p->sibling = p->next;
+    p->childlist = NULL;
+  }
+  
+  heap = plist;
+
+  /* the heap holds a list of lists of paths. Use "childlist" field
+     for outer list, "next" field for inner list. Each of the sublists
+     is to be turned into a tree. This code is messy, but it is
+     actually fast. Each path is rendered exactly once. We use the
+     heap to get a tail recursive algorithm: the heap holds a list of
+     pathlists which still need to be transformed. */
+
+  while (heap) {
+    /* unlink first sublist */
+    cur = heap;
+    heap = heap->childlist;
+    cur->childlist = NULL;
+  
+    /* unlink first path */
+    head = cur;
+    cur = cur->next;
+    head->next = NULL;
+
+    /* render path */
+    xor_path(bm, head);
+    setbbox_path(&bbox, head);
+
+    /* now do insideness test for each element of cur; append it to
+       head->childlist if it's inside head, else append it to
+       head->next. */
+    hook_in=&head->childlist;
+    hook_out=&head->next;
+    list_forall_unlink(p, cur) {
+      if (p->priv->pt[0].y <= bbox.y0) {
+	list_insert_beforehook(p, hook_out);
+	/* append the remainder of the list to hook_out */
+	*hook_out = cur;
+	break;
+      }
+      if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
+	list_insert_beforehook(p, hook_in);
+      } else {
+	list_insert_beforehook(p, hook_out);
+      }
+    }
+
+    /* clear bm */
+    clear_bm_with_bbox(bm, &bbox);
+
+    /* now schedule head->childlist and head->next for further
+       processing */
+    if (head->next) {
+      head->next->childlist = heap;
+      heap = head->next;
+    }
+    if (head->childlist) {
+      head->childlist->childlist = heap;
+      heap = head->childlist;
+    }
+  }
+  
+  /* copy sibling structure from "next" to "sibling" component */
+  p = plist;
+  while (p) {
+    p1 = p->sibling;
+    p->sibling = p->next;
+    p = p1;
+  }
+
+  /* reconstruct a new linked list ("next") structure from tree
+     ("childlist", "sibling") structure. This code is slightly messy,
+     because we use a heap to make it tail recursive: the heap
+     contains a list of childlists which still need to be
+     processed. */
+  heap = plist;
+  if (heap) {
+    heap->next = NULL;  /* heap is a linked list of childlists */
+  }
+  plist = NULL;
+  plist_hook = &plist;
+  while (heap) {
+    heap1 = heap->next;
+    for (p=heap; p; p=p->sibling) {
+      /* p is a positive path */
+      /* append to linked list */
+      list_insert_beforehook(p, plist_hook);
+      
+      /* go through its children */
+      for (p1=p->childlist; p1; p1=p1->sibling) {
+	/* append to linked list */
+	list_insert_beforehook(p1, plist_hook);
+	/* append its childlist to heap, if non-empty */
+	if (p1->childlist) {
+	  list_append(path_t, heap1, p1->childlist);
+	}
+      }
+    }
+    heap = heap1;
+  }
+
+  return;
+}
+
+/* find the next set pixel in a row <= y. Pixels are searched first
+   left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y'
+   or y=y' and x<x'. If found, return 0 and store pixel in
+   (*xp,*yp). Else return 1. Note that this function assumes that
+   excess bytes have been cleared with bm_clearexcess. */
+static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
+  int x;
+  int y;
+  int x0;
+
+  x0 = (*xp) & ~(BM_WORDBITS-1);
+
+  for (y=*yp; y>=0; y--) {
+    for (x=x0; x<bm->w && x>=0; x+=(unsigned)BM_WORDBITS) {
+      if (*bm_index(bm, x, y)) {
+	while (!BM_GET(bm, x, y)) {
+	  x++;
+	}
+	/* found */
+	*xp = x;
+	*yp = y;
+	return 0;
+      }
+    }
+    x0 = 0;
+  }
+  /* not found */
+  return 1;
+}
+
+/* Decompose the given bitmap into paths. Returns a linked list of
+   path_t objects with the fields len, pt, area, sign filled
+   in. Returns 0 on success with plistp set, or -1 on error with errno
+   set. */
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress) {
+  int x;
+  int y;
+  path_t *p;
+  path_t *plist = NULL;  /* linked list of path objects */
+  path_t **plist_hook = &plist;  /* used to speed up appending to linked list */
+  potrace_bitmap_t *bm1 = NULL;
+  int sign;
+
+  bm1 = bm_dup(bm);
+  if (!bm1) {
+    goto error;
+  }
+
+  /* be sure the byte padding on the right is set to 0, as the fast
+     pixel search below relies on it */
+  bm_clearexcess(bm1);
+
+  /* iterate through components */
+  x = 0;
+  y = bm1->h - 1;
+  while (findnext(bm1, &x, &y) == 0) { 
+    /* calculate the sign by looking at the original */
+    sign = BM_GET(bm, x, y) ? '+' : '-';
+
+    /* calculate the path */
+    p = findpath(bm1, x, y+1, sign, param->turnpolicy);
+    if (p==NULL) {
+      goto error;
+    }
+
+    /* update buffered image */
+    xor_path(bm1, p);
+
+    /* if it's a turd, eliminate it, else append it to the list */
+    if (p->area <= param->turdsize) {
+      path_free(p);
+    } else {
+      list_insert_beforehook(p, plist_hook);
+    }
+
+    if (bm1->h > 0) { /* to be sure */
+      progress_update(1-y/(double)bm1->h, progress);
+    }
+  }
+
+  pathlist_to_tree(plist, bm1);
+  bm_free(bm1);
+  *plistp = plist;
+
+  progress_update(1.0, progress);
+
+  return 0;
+
+ error:
+  bm_free(bm1);
+  list_forall_unlink(p, plist) {
+    path_free(p);
+  }
+  return -1;
+}

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/decompose.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef DECOMPOSE_H
+#define DECOMPOSE_H
+
+#include "potracelib.h"
+#include "progress.h"
+#include "curve.h"
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress);
+
+#endif /* DECOMPOSE_H */
+

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/lists.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/lists.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/lists.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,285 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef _PS_LISTS_H
+#define _PS_LISTS_H
+
+/* here we define some general list macros. Because they are macros,
+   they should work on any datatype with a "->next" component. Some of
+   them use a "hook". If elt and list are of type t* then hook is of
+   type t**. A hook stands for an insertion point in the list, i.e.,
+   either before the first element, or between two elements, or after
+   the last element. If an operation "sets the hook" for an element,
+   then the hook is set to just before the element. One can insert
+   something at a hook. One can also unlink at a hook: this means,
+   unlink the element just after the hook. By "to unlink", we mean the
+   element is removed from the list, but not deleted. Thus, it and its
+   components still need to be freed. */
+
+/* Note: these macros are somewhat experimental. Only the ones that
+   are actually *used* have been tested. So be careful to test any
+   that you use. Looking at the output of the preprocessor, "gcc -E"
+   (possibly piped though "indent"), might help too. Also: these
+   macros define some internal (local) variables that start with
+   "_". */
+
+/* we enclose macro definitions whose body consists of more than one
+   statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'.  The
+   reason is that we want to be able to use the macro in a context
+   such as "if (...) macro(...); else ...". If we didn't use this obscure
+   trick, we'd have to omit the ";" in such cases. */
+
+#define MACRO_BEGIN do {
+#define MACRO_END   } while (0)
+
+/* ---------------------------------------------------------------------- */
+/* macros for singly-linked lists */
+
+/* traverse list. At the end, elt is set to NULL. */
+#define list_forall(elt, list)   for (elt=list; elt!=NULL; elt=elt->next)
+
+/* set elt to the first element of list satisfying boolean condition
+   c, or NULL if not found */
+#define list_find(elt, list, c) \
+  MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
+
+/* like forall, except also set hook for elt. */
+#define list_forall2(elt, list, hook) \
+  for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
+
+/* same as list_find, except also set hook for elt. */
+#define list_find2(elt, list, c, hook) \
+  MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
+
+/* same, except only use hook. */
+#define _list_forall_hook(list, hook) \
+  for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
+
+/* same, except only use hook. Note: c may only refer to *hook, not elt. */
+#define _list_find_hook(list, c, hook) \
+  MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
+
+/* insert element after hook */
+#define list_insert_athook(elt, hook) \
+  MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
+
+/* insert element before hook */
+#define list_insert_beforehook(elt, hook) \
+  MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
+
+/* unlink element after hook, let elt be unlinked element, or NULL.
+   hook remains. */
+#define list_unlink_athook(list, elt, hook) \
+  MACRO_BEGIN \
+  elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
+  MACRO_END
+
+/* unlink the specific element, if it is in the list. Otherwise, set
+   elt to NULL */
+#define list_unlink(listtype, list, elt)      \
+  MACRO_BEGIN  	       	       	       	      \
+  listtype **_hook;			      \
+  _list_find_hook(list, *_hook==elt, _hook);  \
+  list_unlink_athook(list, elt, _hook);	      \
+  MACRO_END
+
+/* prepend elt to list */
+#define list_prepend(list, elt) \
+  MACRO_BEGIN elt->next = list; list = elt; MACRO_END
+
+/* append elt to list. */
+#define list_append(listtype, list, elt)     \
+  MACRO_BEGIN                                \
+  listtype **_hook;                          \
+  _list_forall_hook(list, _hook) {}          \
+  list_insert_athook(elt, _hook);            \
+  MACRO_END
+
+/* unlink the first element that satisfies the condition. */
+#define list_unlink_cond(listtype, list, elt, c)     \
+  MACRO_BEGIN                                        \
+  listtype **_hook;			  	     \
+  list_find2(elt, list, c, _hook);                   \
+  list_unlink_athook(list, elt, _hook);              \
+  MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+   Return NULL if out of bounds.   */
+#define list_nth(elt, list, n)                                \
+  MACRO_BEGIN                                                 \
+  int _x;  /* only evaluate n once */                         \
+  for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {}   \
+  MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+   Return NULL if out of bounds.   */
+#define list_nth_hook(elt, list, n, hook)                     \
+  MACRO_BEGIN                                                 \
+  int _x;  /* only evaluate n once */                         \
+  for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {}   \
+  MACRO_END
+
+/* set n to the length of the list */
+#define list_length(listtype, list, n)                   \
+  MACRO_BEGIN          	       	       	       	       	 \
+  listtype *_elt;   			 		 \
+  n=0;					 		 \
+  list_forall(_elt, list) 		 		 \
+    n++;				 		 \
+  MACRO_END
+
+/* set n to the index of the first element satisfying cond, or -1 if
+   none found. Also set elt to the element, or NULL if none found. */
+#define list_index(list, n, elt, c)                      \
+  MACRO_BEGIN				 		 \
+  n=0;					 		 \
+  list_forall(elt, list) {		 		 \
+    if (c) break;			 		 \
+    n++;				 		 \
+  }					 		 \
+  if (!elt)				 		 \
+    n=-1;				 		 \
+  MACRO_END
+
+/* set n to the number of elements in the list that satisfy condition c */
+#define list_count(list, n, elt, c)                      \
+  MACRO_BEGIN				 		 \
+  n=0;					 		 \
+  list_forall(elt, list) {		 		 \
+    if (c) n++;				 		 \
+  }                                                      \
+  MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define list_forall_unlink(elt, list) \
+  for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
+
+/* reverse a list (efficient) */
+#define list_reverse(listtype, list)            \
+  MACRO_BEGIN				 	\
+  listtype *_list1=NULL, *elt;			\
+  list_forall_unlink(elt, list) 		\
+    list_prepend(_list1, elt);			\
+  list = _list1;				\
+  MACRO_END
+
+/* insert the element ELT just before the first element TMP of the
+   list for which COND holds. Here COND must be a condition of ELT and
+   TMP.  Typical usage is to insert an element into an ordered list:
+   for instance, list_insert_ordered(listtype, list, elt, tmp,
+   elt->size <= tmp->size).  Note: if we give a "less than or equal"
+   condition, the new element will be inserted just before a sequence
+   of equal elements. If we give a "less than" condition, the new
+   element will be inserted just after a list of equal elements.
+   Note: it is much more efficient to construct a list with
+   list_prepend and then order it with list_merge_sort, than to
+   construct it with list_insert_ordered. */
+#define list_insert_ordered(listtype, list, elt, tmp, cond) \
+  MACRO_BEGIN                                               \
+  listtype **_hook;                                         \
+  _list_find_hook(list, (tmp=*_hook, (cond)), _hook);       \
+  list_insert_athook(elt, _hook);                           \
+  MACRO_END
+
+/* sort the given list, according to the comparison condition.
+   Typical usage is list_sort(listtype, list, a, b, a->size <
+   b->size).  Note: if we give "less than or equal" condition, each
+   segment of equal elements will be reversed in order. If we give a
+   "less than" condition, each segment of equal elements will retain
+   the original order. The latter is slower but sometimes
+   prettier. Average running time: n*n/2. */
+#define list_sort(listtype, list, a, b, cond)            \
+  MACRO_BEGIN                                            \
+  listtype *_newlist=NULL;                               \
+  list_forall_unlink(a, list)                            \
+    list_insert_ordered(listtype, _newlist, a, b, cond); \
+  list = _newlist;                                       \
+  MACRO_END
+
+/* a much faster sort algorithm (merge sort, n log n worst case). It
+   is required that the list type has an additional, unused next1
+   component. Note there is no curious reversal of order of equal
+   elements as for list_sort. */
+
+#define list_mergesort(listtype, list, a, b, cond)              \
+  MACRO_BEGIN						        \
+  listtype *_elt, **_hook1;				    	\
+							    	\
+  for (_elt=list; _elt; _elt=_elt->next1) {			\
+    _elt->next1 = _elt->next;				    	\
+    _elt->next = NULL;					    	\
+  }							    	\
+  do {			                               	    	\
+    _hook1 = &(list);				    	    	\
+    while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) {  \
+      _elt = b->next1;					    	\
+      _list_merge_cond(listtype, a, b, cond, *_hook1);      	\
+      _hook1 = &((*_hook1)->next1);			    	\
+      *_hook1 = _elt;				            	\
+    }							    	\
+  } while (_hook1 != &(list));                                 	\
+  MACRO_END
+
+/* merge two sorted lists. Store result at &result */
+#define _list_merge_cond(listtype, a, b, cond, result)   \
+  MACRO_BEGIN                                            \
+  listtype **_hook;					 \
+  _hook = &(result);					 \
+  while (1) {                                            \
+     if (a==NULL) {					 \
+       *_hook = b;					 \
+       break;						 \
+     } else if (b==NULL) {				 \
+       *_hook = a;					 \
+       break;						 \
+     } else if (cond) {					 \
+       *_hook = a;					 \
+       _hook = &(a->next);				 \
+       a = a->next;					 \
+     } else {						 \
+       *_hook = b;					 \
+       _hook = &(b->next);				 \
+       b = b->next;					 \
+     }							 \
+  }							 \
+  MACRO_END
+
+/* ---------------------------------------------------------------------- */
+/* macros for doubly-linked lists */
+
+#define dlist_append(head, end, elt)                    \
+  MACRO_BEGIN  	       	       	       	       	       	 \
+  elt->prev = end;					 \
+  elt->next = NULL;					 \
+  if (end) {						 \
+    end->next = elt;					 \
+  } else {  						 \
+    head = elt;						 \
+  }	    						 \
+  end = elt;						 \
+  MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define dlist_forall_unlink(elt, head, end) \
+  for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
+
+/* unlink the first element of the list */
+#define dlist_unlink_first(head, end, elt)               \
+  MACRO_BEGIN				       	       	 \
+  elt = head;						 \
+  if (head) {						 \
+    head = head->next;					 \
+    if (head) {						 \
+      head->prev = NULL;				 \
+    } else {						 \
+      end = NULL;					 \
+    }    						 \
+    elt->prev = NULL;					 \
+    elt->next = NULL;					 \
+  }							 \
+  MACRO_END
+
+#endif /* _PS_LISTS_H */
+

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,108 @@
+/* From potracelib_demo.c */
+
+#include "luafunc.h"
+
+
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary bitmap functions */
+
+
+/* macros for writing individual bitmap pixels */
+#define BM_WORDSIZE ((int)sizeof(potrace_word))
+#define BM_WORDBITS (8*BM_WORDSIZE)
+#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
+#define bm_scanline(bm, y) ((bm)->map + (y)*(bm)->dy)
+#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
+#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
+#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
+#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
+#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
+#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
+#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
+#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
+
+/* return new un-initialized bitmap. NULL with errno on error */
+static potrace_bitmap_t *bm_new(int w, int h) {
+  potrace_bitmap_t *bm;
+  int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
+
+  bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
+  if (!bm) {
+    return NULL;
+  }
+  bm->w = w;
+  bm->h = h;
+  bm->dy = dy;
+  bm->map = (potrace_word *) calloc(h, dy * BM_WORDSIZE);
+  if (!bm->map) {
+    free(bm);
+    return NULL;
+  }
+  return bm;
+}
+
+/* free a bitmap */
+static void bm_free(potrace_bitmap_t *bm) {
+  if (bm != NULL) {
+    free(bm->map);
+  }
+  free(bm);
+}
+
+//int potrace_getMFoutlines(const uint8_t *raster,int w, int h) {
+int potrace_getMFoutlines(const uint8_t *raster, int w, int h, MFoutlines_param_t opt_param,potrace_state_t **trace) {
+  int x, y;
+  potrace_bitmap_t *bm;
+  potrace_param_t *param;
+  potrace_state_t *st;
+  int W,X;
+  uint8_t data,pix;
+
+  /* create a bitmap */
+  bm = bm_new(w, h);
+  if (!bm) {
+    fprintf(stderr, "! Error allocating bitmap: %s\n", strerror(errno)); 
+    return 1;
+  }
+
+  /* fill the bitmap  */
+  W= (w%8)==0 ?(w/8):(w/8+1);
+  for (y=0; y<h; y++) {
+    for (X=0;X<W; X++) {
+      data = raster[W*y+X];
+      pix = (data & (1<<7))==0 ? 0:1;x = 0+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<6))==0 ? 0:1;x = 1+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<5))==0 ? 0:1;x = 2+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<4))==0 ? 0:1;x = 3+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<3))==0 ? 0:1;x = 4+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<2))==0 ? 0:1;x = 5+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<1))==0 ? 0:1;x = 6+X*8;BM_PUT(bm, x, y, pix);
+      pix = (data & (1<<0))==0 ? 0:1;x = 7+X*8;BM_PUT(bm, x, y, pix);
+    }
+  }
+
+  /* set tracing parameters, starting from defaults */
+  if (opt_param.potrace_param == NULL) {
+    param = potrace_param_default();printf("opt_param.potrace_param == NULL\n");
+    if (!param) {
+     fprintf(stderr, "! Error allocating parameters: %s\n", strerror(errno)); 
+     return 1;
+    }
+    param->turdsize = 0;
+  } else {
+    param = opt_param.potrace_param;
+  }
+  /*printf("turdsize=%d;turnpolicy=%d;alphamax=%f;opticurve=%d;opttolerance=%f\n",param->turdsize,param->turnpolicy,param->alphamax,param->opticurve,param->opttolerance);*/
+
+  /* trace the bitmap */
+  st = potrace_trace(param, bm);
+  if (!st || st->status != POTRACE_STATUS_OK) {
+    fprintf(stderr, "! Error tracing bitmap: %s\n", strerror(errno));
+    bm_free(bm);
+    return 1;
+  }
+  bm_free(bm);
+  *trace = st ;
+  return 0;
+}
\ No newline at end of file

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/luafunc.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,24 @@
+/* From potracelib_demo.c */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "potracelib.h"
+
+struct MFoutlines_param_s {
+ double xoffs ;
+ double yoffs ;
+ potrace_param_t *potrace_param;
+};
+typedef struct MFoutlines_param_s MFoutlines_param_t;
+
+/* raster: bitmap wxh, pixel packed into a byte  */
+/* w: nr. of columns                             */
+/* h: nr. of rows                                */
+/* opt_parmam: optional parameters for potrace   */
+/* trace: curves returned by potrace             */
+/* Return 1 if error, 0 if ok                    */
+int potrace_getMFoutlines(const uint8_t *raster, int w, int h, MFoutlines_param_t opt_param,potrace_state_t **trace);

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,114 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "decompose.h"
+#include "trace.h"
+#include "progress.h"
+
+/* default parameters */
+static const potrace_param_t param_default = {
+  2,                             /* turdsize */
+  POTRACE_TURNPOLICY_MINORITY,   /* turnpolicy */
+  1.0,                           /* alphamax */
+  1,                             /* opticurve */
+  0.2,                           /* opttolerance */
+  {
+    NULL,                        /* callback function */
+    NULL,                        /* callback data */
+    0.0, 1.0,                    /* progress range */
+    0.0,                         /* granularity */
+  },
+};
+
+/* Return a fresh copy of the set of default parameters, or NULL on
+   failure with errno set. */
+potrace_param_t *potrace_param_default(void) {
+  potrace_param_t *p;
+
+  p = (potrace_param_t *) malloc(sizeof(potrace_param_t));
+  if (!p) {
+    return NULL;
+  }
+  memcpy(p, &param_default, sizeof(potrace_param_t));
+  return p;
+}
+
+/* On success, returns a Potrace state st with st->status ==
+   POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
+   could be created (with errno set), or returns an incomplete Potrace
+   state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno
+   set). Complete or incomplete Potrace state can be freed with
+   potrace_state_free(). */
+potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) {
+  int r;
+  path_t *plist = NULL;
+  potrace_state_t *st;
+  progress_t prog;
+  progress_t subprog;
+  
+  /* prepare private progress bar state */
+  prog.callback = param->progress.callback;
+  prog.data = param->progress.data;
+  prog.min = param->progress.min;
+  prog.max = param->progress.max;
+  prog.epsilon = param->progress.epsilon;
+  prog.d_prev = param->progress.min;
+
+  /* allocate state object */
+  st = (potrace_state_t *)malloc(sizeof(potrace_state_t));
+  if (!st) {
+    return NULL;
+  }
+
+  progress_subrange_start(0.0, 0.1, &prog, &subprog);
+
+  /* process the image */
+  r = bm_to_pathlist(bm, &plist, param, &subprog);
+  if (r) {
+    free(st);
+    return NULL;
+  }
+
+  st->status = POTRACE_STATUS_OK;
+  st->plist = plist;
+  st->priv = NULL;  /* private state currently unused */
+
+  progress_subrange_end(&prog, &subprog);
+
+  progress_subrange_start(0.1, 1.0, &prog, &subprog);
+
+  /* partial success. */
+  r = process_path(plist, param, &subprog);
+  if (r) {
+    st->status = POTRACE_STATUS_INCOMPLETE;
+  }
+
+  progress_subrange_end(&prog, &subprog);
+
+  return st;
+}
+
+/* free a Potrace state, without disturbing errno. */
+void potrace_state_free(potrace_state_t *st) {
+  pathlist_free(st->plist);
+  free(st);
+}
+
+/* free a parameter list, without disturbing errno. */
+void potrace_param_free(potrace_param_t *p) {
+  free(p);
+}
+
+const char *potrace_version(void) {
+  return "potracelib " VERSION "";
+}

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/potracelib.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,139 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef POTRACELIB_H
+#define POTRACELIB_H
+
+/* this file defines the API for the core Potrace library. For a more
+   detailed description of the API, see potracelib.pdf */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* tracing parameters */
+
+/* turn policies */
+#define POTRACE_TURNPOLICY_BLACK 0
+#define POTRACE_TURNPOLICY_WHITE 1
+#define POTRACE_TURNPOLICY_LEFT 2
+#define POTRACE_TURNPOLICY_RIGHT 3
+#define POTRACE_TURNPOLICY_MINORITY 4
+#define POTRACE_TURNPOLICY_MAJORITY 5
+#define POTRACE_TURNPOLICY_RANDOM 6
+
+/* structure to hold progress bar callback data */
+struct potrace_progress_s {
+  void (*callback)(double progress, void *privdata); /* callback fn */
+  void *data;          /* callback function's private data */
+  double min, max;     /* desired range of progress, e.g. 0.0 to 1.0 */
+  double epsilon;      /* granularity: can skip smaller increments */
+};
+typedef struct potrace_progress_s potrace_progress_t;
+
+/* structure to hold tracing parameters */
+struct potrace_param_s {
+  int turdsize;        /* area of largest path to be ignored */
+  int turnpolicy;      /* resolves ambiguous turns in path decomposition */
+  double alphamax;     /* corner threshold */
+  int opticurve;       /* use curve optimization? */
+  double opttolerance; /* curve optimization tolerance */
+  potrace_progress_t progress; /* progress callback function */
+};
+typedef struct potrace_param_s potrace_param_t;
+
+/* ---------------------------------------------------------------------- */
+/* bitmaps */
+
+/* native word size */
+typedef unsigned long potrace_word;
+
+/* Internal bitmap format. The n-th scanline starts at scanline(n) =
+   (map + n*dy). Raster data is stored as a sequence of potrace_words
+   (NOT bytes). The leftmost bit of scanline n is the most significant
+   bit of scanline(n)[0]. */
+struct potrace_bitmap_s {
+  int w, h;              /* width and height, in pixels */
+  int dy;                /* words per scanline (not bytes) */
+  potrace_word *map;     /* raw data, dy*h words */
+};
+typedef struct potrace_bitmap_s potrace_bitmap_t;
+
+/* ---------------------------------------------------------------------- */
+/* curves */
+
+/* point */
+struct potrace_dpoint_s {
+  double x, y;
+};
+typedef struct potrace_dpoint_s potrace_dpoint_t;
+
+/* segment tags */
+#define POTRACE_CURVETO 1
+#define POTRACE_CORNER 2
+
+/* closed curve segment */
+struct potrace_curve_s {
+  int n;                    /* number of segments */
+  int *tag;                 /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
+  potrace_dpoint_t (*c)[3]; /* c[n][3]: control points. 
+			       c[n][0] is unused for tag[n]=POTRACE_CORNER */
+};
+typedef struct potrace_curve_s potrace_curve_t;
+
+/* Linked list of signed curve segments. Also carries a tree structure. */
+struct potrace_path_s {
+  int area;                         /* area of the bitmap path */
+  int sign;                         /* '+' or '-', depending on orientation */
+  potrace_curve_t curve;            /* this path's vector data */
+
+  struct potrace_path_s *next;      /* linked list structure */
+
+  struct potrace_path_s *childlist; /* tree structure */
+  struct potrace_path_s *sibling;   /* tree structure */
+
+  struct potrace_privpath_s *priv;  /* private state */
+};
+typedef struct potrace_path_s potrace_path_t;  
+
+/* ---------------------------------------------------------------------- */
+/* Potrace state */
+
+#define POTRACE_STATUS_OK         0
+#define POTRACE_STATUS_INCOMPLETE 1
+
+struct potrace_state_s {
+  int status;                       
+  potrace_path_t *plist;            /* vector data */
+
+  struct potrace_privstate_s *priv; /* private state */
+};
+typedef struct potrace_state_s potrace_state_t;
+
+/* ---------------------------------------------------------------------- */
+/* API functions */
+
+/* get default parameters */
+potrace_param_t *potrace_param_default(void);
+
+/* free parameter set */
+void potrace_param_free(potrace_param_t *p);
+
+/* trace a bitmap */
+potrace_state_t *potrace_trace(const potrace_param_t *param, 
+			       const potrace_bitmap_t *bm);
+
+/* free a Potrace state */
+void potrace_state_free(potrace_state_t *st);
+
+/* return a static plain text version string identifying this version
+   of potracelib */
+const char *potrace_version(void);
+
+#ifdef  __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* POTRACELIB_H */

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/progress.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/progress.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/progress.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,79 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+/* operations on potrace_progress_t objects, which are defined in
+   potracelib.h. Note: the code attempts to minimize runtime overhead
+   when no progress monitoring was requested. It also tries to
+   minimize excessive progress calculations beneath the "epsilon"
+   threshold. */
+
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+/* structure to hold progress bar callback data */
+struct progress_s {
+  void (*callback)(double progress, void *privdata); /* callback fn */
+  void *data;          /* callback function's private data */
+  double min, max;     /* desired range of progress, e.g. 0.0 to 1.0 */
+  double epsilon;      /* granularity: can skip smaller increments */
+  double b;            /* upper limit of subrange in superrange units */
+  double d_prev;       /* previous value of d */
+};
+typedef struct progress_s progress_t;
+
+/* notify given progress object of current progress. Note that d is
+   given in the 0.0-1.0 range, which will be scaled and translated to
+   the progress object's range. */
+static inline void progress_update(double d, progress_t *prog) {
+  double d_scaled;
+
+  if (prog != NULL && prog->callback != NULL) {
+    d_scaled = prog->min * (1-d) + prog->max * d;
+    if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) {
+      prog->callback(prog->min * (1-d) + prog->max * d, prog->data);
+      prog->d_prev = d_scaled;
+    }
+  }
+}
+
+/* start a subrange of the given progress object. The range is
+   narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
+   is below granularity threshold, disable further subdivisions. */
+static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) {
+  double min, max;
+
+  if (prog == NULL || prog->callback == NULL) {
+    sub->callback = NULL;
+    return;
+  }
+
+  min = prog->min * (1-a) + prog->max * a;
+  max = prog->min * (1-b) + prog->max * b;
+
+  if (max - min < prog->epsilon) {
+    sub->callback = NULL;    /* no further progress info in subrange */
+    sub->b = b;
+    return;
+  }
+  sub->callback = prog->callback;
+  sub->data = prog->data;
+  sub->epsilon = prog->epsilon;
+  sub->min = min;
+  sub->max = max;
+  sub->d_prev = prog->d_prev;
+  return;
+}
+
+static inline void progress_subrange_end(progress_t *prog, progress_t *sub) {
+  if (prog != NULL && prog->callback != NULL) {
+    if (sub->callback == NULL) {
+      progress_update(sub->b, prog);
+    } else {
+      prog->d_prev = sub->d_prev;
+    }
+  }    
+}
+
+#endif /* PROGRESS_H */
+

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/trace.c
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/trace.c	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/trace.c	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,1249 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+/* transform jaggy paths into smooth curves */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trace.h"
+#include "progress.h"
+
+#define INFTY 10000000	/* it suffices that this is longer than any
+			   path; it need not be really infinite */
+#define COS179 -0.999847695156	 /* the cosine of 179 degrees */
+
+/* ---------------------------------------------------------------------- */
+#define SAFE_CALLOC(var, n, typ) \
+  if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error 
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* return a direction that is 90 degrees counterclockwise from p2-p0,
+   but then restricted to one of the major wind directions (n, nw, w, etc) */
+static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
+  point_t r;
+  
+  r.y = sign(p2.x-p0.x);
+  r.x = -sign(p2.y-p0.y);
+
+  return r;
+}
+
+/* return (p1-p0)x(p2-p0), the area of the parallelogram */
+static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+  double x1, y1, x2, y2;
+
+  x1 = p1.x-p0.x;
+  y1 = p1.y-p0.y;
+  x2 = p2.x-p0.x;
+  y2 = p2.y-p0.y;
+
+  return x1*y2 - x2*y1;
+}
+
+/* ddenom/dpara have the property that the square of radius 1 centered
+   at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
+static inline double ddenom(dpoint_t p0, dpoint_t p2) {
+  point_t r = dorth_infty(p0, p2);
+
+  return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
+}
+
+/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
+static inline int cyclic(int a, int b, int c) {
+  if (a<=c) {
+    return (a<=b && b<c);
+  } else {
+    return (a<=b || b<c);
+  }
+}
+
+/* determine the center and slope of the line i..j. Assume i<j. Needs
+   "sum" components of p to be set. */
+static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
+  /* assume i<j */
+
+  int n = pp->len;
+  sums_t *sums = pp->sums;
+
+  double x, y, x2, xy, y2;
+  double k;
+  double a, b, c, lambda2, l;
+  int r=0; /* rotations from i to j */
+
+  while (j>=n) {
+    j-=n;
+    r+=1;
+  }
+  while (i>=n) {
+    i-=n;
+    r-=1;
+  }
+  while (j<0) {
+    j+=n;
+    r-=1;
+  }
+  while (i<0) {
+    i+=n;
+    r+=1;
+  }
+  
+  x = sums[j+1].x-sums[i].x+r*sums[n].x;
+  y = sums[j+1].y-sums[i].y+r*sums[n].y;
+  x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
+  xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
+  y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
+  k = j+1-i+r*n;
+  
+  ctr->x = x/k;
+  ctr->y = y/k;
+
+  a = (x2-(double)x*x/k)/k;
+  b = (xy-(double)x*y/k)/k;
+  c = (y2-(double)y*y/k)/k;
+  
+  lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
+
+  /* now find e.vector for lambda2 */
+  a -= lambda2;
+  c -= lambda2;
+
+  if (fabs(a) >= fabs(c)) {
+    l = sqrt(a*a+b*b);
+    if (l!=0) {
+      dir->x = -b/l;
+      dir->y = a/l;
+    }
+  } else {
+    l = sqrt(c*c+b*b);
+    if (l!=0) {
+      dir->x = -c/l;
+      dir->y = b/l;
+    }
+  }
+  if (l==0) {
+    dir->x = dir->y = 0;   /* sometimes this can happen when k=4:
+			      the two eigenvalues coincide */
+  }
+}
+
+/* the type of (affine) quadratic forms, represented as symmetric 3x3
+   matrices.  The value of the quadratic form at a vector (x,y) is v^t
+   Q v, where v = (x,y,1)^t. */
+typedef double quadform_t[3][3];
+
+/* Apply quadratic form Q to vector w = (w.x,w.y) */
+static inline double quadform(quadform_t Q, dpoint_t w) {
+  double v[3];
+  int i, j;
+  double sum;
+
+  v[0] = w.x;
+  v[1] = w.y;
+  v[2] = 1;
+  sum = 0.0;
+
+  for (i=0; i<3; i++) {
+    for (j=0; j<3; j++) {
+      sum += v[i] * Q[i][j] * v[j];
+    }
+  }
+  return sum;
+}
+
+/* calculate p1 x p2 */
+static inline int xprod(point_t p1, point_t p2) {
+  return p1.x*p2.y - p1.y*p2.x;
+}
+
+/* calculate (p1-p0)x(p3-p2) */
+static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+  double x1, y1, x2, y2;
+
+  x1 = p1.x - p0.x;
+  y1 = p1.y - p0.y;
+  x2 = p3.x - p2.x;
+  y2 = p3.y - p2.y;
+
+  return x1*y2 - x2*y1;
+}
+
+/* calculate (p1-p0)*(p2-p0) */
+static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+  double x1, y1, x2, y2;
+
+  x1 = p1.x - p0.x;
+  y1 = p1.y - p0.y;
+  x2 = p2.x - p0.x;
+  y2 = p2.y - p0.y;
+
+  return x1*x2 + y1*y2;
+}
+
+/* calculate (p1-p0)*(p3-p2) */
+static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+  double x1, y1, x2, y2;
+
+  x1 = p1.x - p0.x;
+  y1 = p1.y - p0.y;
+  x2 = p3.x - p2.x;
+  y2 = p3.y - p2.y;
+
+  return x1*x2 + y1*y2;
+}
+
+/* calculate distance between two points */
+static inline double ddist(dpoint_t p, dpoint_t q) {
+  return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
+}
+
+/* calculate point of a bezier curve */
+static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+  double s = 1-t;
+  dpoint_t res;
+
+  /* Note: a good optimizing compiler (such as gcc-3) reduces the
+     following to 16 multiplications, using common subexpression
+     elimination. */
+
+  res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
+  res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
+
+  return res;
+}
+
+/* calculate the point t in [0..1] on the (convex) bezier curve
+   (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
+   solution in [0..1]. */
+static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
+  double A, B, C;   /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
+  double a, b, c;   /* a t^2 + b t + c = 0 */
+  double d, s, r1, r2;
+
+  A = cprod(p0, p1, q0, q1);
+  B = cprod(p1, p2, q0, q1);
+  C = cprod(p2, p3, q0, q1);
+
+  a = A - 2*B + C;
+  b = -2*A + 2*B;
+  c = A;
+  
+  d = b*b - 4*a*c;
+
+  if (a==0 || d<0) {
+    return -1.0;
+  }
+
+  s = sqrt(d);
+
+  r1 = (-b + s) / (2 * a);
+  r2 = (-b - s) / (2 * a);
+
+  if (r1 >= 0 && r1 <= 1) {
+    return r1;
+  } else if (r2 >= 0 && r2 <= 1) {
+    return r2;
+  } else {
+    return -1.0;
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Preparation: fill in the sum* fields of a path (used for later
+   rapid summing). Return 0 on success, 1 with errno set on
+   failure. */
+static int calc_sums(privpath_t *pp) {
+  int i, x, y;
+  int n = pp->len;
+
+  SAFE_CALLOC(pp->sums, pp->len+1, sums_t);
+
+  /* origin */
+  pp->x0 = pp->pt[0].x;
+  pp->y0 = pp->pt[0].y;
+
+  /* preparatory computation for later fast summing */
+  pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
+  for (i=0; i<n; i++) {
+    x = pp->pt[i].x - pp->x0;
+    y = pp->pt[i].y - pp->y0;
+    pp->sums[i+1].x = pp->sums[i].x + x;
+    pp->sums[i+1].y = pp->sums[i].y + y;
+    pp->sums[i+1].x2 = pp->sums[i].x2 + (double)x*x;
+    pp->sums[i+1].xy = pp->sums[i].xy + (double)x*y;
+    pp->sums[i+1].y2 = pp->sums[i].y2 + (double)y*y;
+  }
+  return 0;  
+
+ calloc_error:
+  return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the
+   "lon" component of a path object (based on pt/len).	For each i,
+   lon[i] is the furthest index such that a straight line can be drawn
+   from i to lon[i]. Return 1 on error with errno set, else 0. */
+
+/* this algorithm depends on the fact that the existence of straight
+   subpaths is a triplewise property. I.e., there exists a straight
+   line through squares i0,...,in iff there exists a straight line
+   through i,j,k, for all i0<=i<j<k<=in. (Proof?) */
+
+/* this implementation of calc_lon is O(n^2). It replaces an older
+   O(n^3) version. A "constraint" means that future points must
+   satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1],
+   cur) <= 0. */
+
+/* Remark for Potrace 1.1: the current implementation of calc_lon is
+   more complex than the implementation found in Potrace 1.0, but it
+   is considerably faster. The introduction of the "nc" data structure
+   means that we only have to test the constraints for "corner"
+   points. On a typical input file, this speeds up the calc_lon
+   function by a factor of 31.2, thereby decreasing its time share
+   within the overall Potrace algorithm from 72.6% to 7.82%, and
+   speeding up the overall algorithm by a factor of 3.36. On another
+   input file, calc_lon was sped up by a factor of 6.7, decreasing its
+   time share from 51.4% to 13.61%, and speeding up the overall
+   algorithm by a factor of 1.78. In any case, the savings are
+   substantial. */
+
+/* returns 0 on success, 1 on error with errno set */
+static int calc_lon(privpath_t *pp) {
+  point_t *pt = pp->pt;
+  int n = pp->len;
+  int i, j, k, k1;
+  int ct[4], dir;
+  point_t constraint[2];
+  point_t cur;
+  point_t off;
+  int *pivk = NULL;  /* pivk[n] */
+  int *nc = NULL;    /* nc[n]: next corner */
+  point_t dk;  /* direction of k-k1 */
+  int a, b, c, d;
+
+  SAFE_CALLOC(pivk, n, int);
+  SAFE_CALLOC(nc, n, int);
+
+  /* initialize the nc data structure. Point from each point to the
+     furthest future point to which it is connected by a vertical or
+     horizontal segment. We take advantage of the fact that there is
+     always a direction change at 0 (due to the path decomposition
+     algorithm). But even if this were not so, there is no harm, as
+     in practice, correctness does not depend on the word "furthest"
+     above.  */
+  k = 0;
+  for (i=n-1; i>=0; i--) {
+    if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
+      k = i+1;  /* necessarily i<n-1 in this case */
+    }
+    nc[i] = k;
+  }
+
+  SAFE_CALLOC(pp->lon, n, int);
+
+  /* determine pivot points: for each i, let pivk[i] be the furthest k
+     such that all j with i<j<k lie on a line connecting i,k. */
+  
+  for (i=n-1; i>=0; i--) {
+    ct[0] = ct[1] = ct[2] = ct[3] = 0;
+
+    /* keep track of "directions" that have occurred */
+    dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
+    ct[dir]++;
+
+    constraint[0].x = 0;
+    constraint[0].y = 0;
+    constraint[1].x = 0;
+    constraint[1].y = 0;
+
+    /* find the next k such that no straight line from i to k */
+    k = nc[i];
+    k1 = i;
+    while (1) {
+      
+      dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
+      ct[dir]++;
+
+      /* if all four "directions" have occurred, cut this path */
+      if (ct[0] && ct[1] && ct[2] && ct[3]) {
+	pivk[i] = k1;
+	goto foundk;
+      }
+
+      cur.x = pt[k].x - pt[i].x;
+      cur.y = pt[k].y - pt[i].y;
+
+      /* see if current constraint is violated */
+      if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
+	goto constraint_viol;
+      }
+
+      /* else, update constraint */
+      if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
+	/* no constraint */
+      } else {
+	off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
+	off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
+	if (xprod(constraint[0], off) >= 0) {
+	  constraint[0] = off;
+	}
+	off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
+	off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
+	if (xprod(constraint[1], off) <= 0) {
+	  constraint[1] = off;
+	}
+      }	
+      k1 = k;
+      k = nc[k1];
+      if (!cyclic(k,i,k1)) {
+	break;
+      }
+    }
+  constraint_viol:
+    /* k1 was the last "corner" satisfying the current constraint, and
+       k is the first one violating it. We now need to find the last
+       point along k1..k which satisfied the constraint. */
+    dk.x = sign(pt[k].x-pt[k1].x);
+    dk.y = sign(pt[k].y-pt[k1].y);
+    cur.x = pt[k1].x - pt[i].x;
+    cur.y = pt[k1].y - pt[i].y;
+    /* find largest integer j such that xprod(constraint[0], cur+j*dk)
+       >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
+       of xprod. */
+    a = xprod(constraint[0], cur);
+    b = xprod(constraint[0], dk);
+    c = xprod(constraint[1], cur);
+    d = xprod(constraint[1], dk);
+    /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
+       can be solved with integer arithmetic. */
+    j = INFTY;
+    if (b<0) {
+      j = floordiv(a,-b);
+    }
+    if (d>0) {
+      j = min(j, floordiv(-c,d));
+    }
+    pivk[i] = mod(k1+j,n);
+  foundk:
+    ;
+  } /* for i */
+
+  /* clean up: for each i, let lon[i] be the largest k such that for
+     all i' with i<=i'<k, i'<k<=pivk[i']. */
+
+  j=pivk[n-1];
+  pp->lon[n-1]=j;
+  for (i=n-2; i>=0; i--) {
+    if (cyclic(i+1,pivk[i],j)) {
+      j=pivk[i];
+    }
+    pp->lon[i]=j;
+  }
+
+  for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
+    pp->lon[i] = j;
+  }
+
+  free(pivk);
+  free(nc);
+  return 0;
+
+ calloc_error:
+  free(pivk);
+  free(nc);
+  return 1;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */ 
+
+/* Auxiliary function: calculate the penalty of an edge from i to j in
+   the given path. This needs the "lon" and "sum*" data. */
+
+static double penalty3(privpath_t *pp, int i, int j) {
+  int n = pp->len;
+  point_t *pt = pp->pt;
+  sums_t *sums = pp->sums;
+
+  /* assume 0<=i<j<=n  */
+  double x, y, x2, xy, y2;
+  double k;
+  double a, b, c, s;
+  double px, py, ex, ey;
+
+  int r = 0; /* rotations from i to j */
+
+  if (j>=n) {
+    j -= n;
+    r = 1;
+  }
+  
+  /* critical inner loop: the "if" gives a 4.6 percent speedup */
+  if (r == 0) {
+    x = sums[j+1].x - sums[i].x;
+    y = sums[j+1].y - sums[i].y;
+    x2 = sums[j+1].x2 - sums[i].x2;
+    xy = sums[j+1].xy - sums[i].xy;
+    y2 = sums[j+1].y2 - sums[i].y2;
+    k = j+1 - i;
+  } else {
+    x = sums[j+1].x - sums[i].x + sums[n].x;
+    y = sums[j+1].y - sums[i].y + sums[n].y;
+    x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2;
+    xy = sums[j+1].xy - sums[i].xy + sums[n].xy;
+    y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2;
+    k = j+1 - i + n;
+  } 
+
+  px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
+  py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
+  ey = (pt[j].x - pt[i].x);
+  ex = -(pt[j].y - pt[i].y);
+
+  a = ((x2 - 2*x*px) / k + px*px);
+  b = ((xy - x*py - y*px) / k + px*py);
+  c = ((y2 - 2*y*py) / k + py*py);
+  
+  s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
+
+  return sqrt(s);
+}
+
+/* find the optimal polygon. Fill in the m and po components. Return 1
+   on failure with errno set, else 0. Non-cyclic version: assumes i=0
+   is in the polygon. Fixme: implement cyclic version. */
+static int bestpolygon(privpath_t *pp)
+{
+  int i, j, m, k;     
+  int n = pp->len;
+  double *pen = NULL; /* pen[n+1]: penalty vector */
+  int *prev = NULL;   /* prev[n+1]: best path pointer vector */
+  int *clip0 = NULL;  /* clip0[n]: longest segment pointer, non-cyclic */
+  int *clip1 = NULL;  /* clip1[n+1]: backwards segment pointer, non-cyclic */
+  int *seg0 = NULL;    /* seg0[m+1]: forward segment bounds, m<=n */
+  int *seg1 = NULL;   /* seg1[m+1]: backward segment bounds, m<=n */
+  double thispen;
+  double best;
+  int c;
+
+  SAFE_CALLOC(pen, n+1, double);
+  SAFE_CALLOC(prev, n+1, int);
+  SAFE_CALLOC(clip0, n, int);
+  SAFE_CALLOC(clip1, n+1, int);
+  SAFE_CALLOC(seg0, n+1, int);
+  SAFE_CALLOC(seg1, n+1, int);
+
+  /* calculate clipped paths */
+  for (i=0; i<n; i++) {
+    c = mod(pp->lon[mod(i-1,n)]-1,n);
+    if (c == i) {
+      c = mod(i+1,n);
+    }
+    if (c < i) {
+      clip0[i] = n;
+    } else {
+      clip0[i] = c;
+    }
+  }
+
+  /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
+     clip1[j] <= i, for i,j=0..n. */
+  j = 1;
+  for (i=0; i<n; i++) {
+    while (j <= clip0[i]) {
+      clip1[j] = i;
+      j++;
+    }
+  }
+
+  /* calculate seg0[j] = longest path from 0 with j segments */
+  i = 0;
+  for (j=0; i<n; j++) {
+    seg0[j] = i;
+    i = clip0[i];
+  }
+  seg0[j] = n;
+  m = j;
+
+  /* calculate seg1[j] = longest path to n with m-j segments */
+  i = n;
+  for (j=m; j>0; j--) {
+    seg1[j] = i;
+    i = clip1[i];
+  }
+  seg1[0] = 0;
+
+  /* now find the shortest path with m segments, based on penalty3 */
+  /* note: the outer 2 loops jointly have at most n iterations, thus
+     the worst-case behavior here is quadratic. In practice, it is
+     close to linear since the inner loop tends to be short. */
+  pen[0]=0;
+  for (j=1; j<=m; j++) {
+    for (i=seg1[j]; i<=seg0[j]; i++) {
+      best = -1;
+      for (k=seg0[j-1]; k>=clip1[i]; k--) {
+	thispen = penalty3(pp, k, i) + pen[k];
+	if (best < 0 || thispen < best) {
+	  prev[i] = k;
+	  best = thispen;
+	}
+      }
+      pen[i] = best;
+    }
+  }
+
+  pp->m = m;
+  SAFE_CALLOC(pp->po, m, int);
+
+  /* read off shortest path */
+  for (i=n, j=m-1; i>0; j--) {
+    i = prev[i];
+    pp->po[j] = i;
+  }
+
+  free(pen);
+  free(prev);
+  free(clip0);
+  free(clip1);
+  free(seg0);
+  free(seg1);
+  return 0;
+  
+ calloc_error:
+  free(pen);
+  free(prev);
+  free(clip0);
+  free(clip1);
+  free(seg0);
+  free(seg1);
+  return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 3: vertex adjustment (Sec. 2.3.1). */
+
+/* Adjust vertices of optimal polygon: calculate the intersection of
+   the two "optimal" line segments, then move it into the unit square
+   if it lies outside. Return 1 with errno set on error; 0 on
+   success. */
+
+static int adjust_vertices(privpath_t *pp) {
+  int m = pp->m;
+  int *po = pp->po;
+  int n = pp->len;
+  point_t *pt = pp->pt;
+  int x0 = pp->x0;
+  int y0 = pp->y0;
+
+  dpoint_t *ctr = NULL;      /* ctr[m] */
+  dpoint_t *dir = NULL;      /* dir[m] */
+  quadform_t *q = NULL;      /* q[m] */
+  double v[3];
+  double d;
+  int i, j, k, l;
+  dpoint_t s;
+  int r;
+
+  SAFE_CALLOC(ctr, m, dpoint_t);
+  SAFE_CALLOC(dir, m, dpoint_t);
+  SAFE_CALLOC(q, m, quadform_t);
+
+  r = privcurve_init(&pp->curve, m);
+  if (r) {
+    goto calloc_error;
+  }
+  
+  /* calculate "optimal" point-slope representation for each line
+     segment */
+  for (i=0; i<m; i++) {
+    j = po[mod(i+1,m)];
+    j = mod(j-po[i],n)+po[i];
+    pointslope(pp, po[i], j, &ctr[i], &dir[i]);
+  }
+
+  /* represent each line segment as a singular quadratic form; the
+     distance of a point (x,y) from the line segment will be
+     (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
+  for (i=0; i<m; i++) {
+    d = sq(dir[i].x) + sq(dir[i].y);
+    if (d == 0.0) {
+      for (j=0; j<3; j++) {
+	for (k=0; k<3; k++) {
+	  q[i][j][k] = 0;
+	}
+      }
+    } else {
+      v[0] = dir[i].y;
+      v[1] = -dir[i].x;
+      v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
+      for (l=0; l<3; l++) {
+	for (k=0; k<3; k++) {
+	  q[i][l][k] = v[l] * v[k] / d;
+	}
+      }
+    }
+  }
+
+  /* now calculate the "intersections" of consecutive segments.
+     Instead of using the actual intersection, we find the point
+     within a given unit square which minimizes the square distance to
+     the two lines. */
+  for (i=0; i<m; i++) {
+    quadform_t Q;
+    dpoint_t w;
+    double dx, dy;
+    double det;
+    double min, cand; /* minimum and candidate for minimum of quad. form */
+    double xmin, ymin;	/* coordinates of minimum */
+    int z;
+
+    /* let s be the vertex, in coordinates relative to x0/y0 */
+    s.x = pt[po[i]].x-x0;
+    s.y = pt[po[i]].y-y0;
+
+    /* intersect segments i-1 and i */
+
+    j = mod(i-1,m);
+
+    /* add quadratic forms */
+    for (l=0; l<3; l++) {
+      for (k=0; k<3; k++) {
+	Q[l][k] = q[j][l][k] + q[i][l][k];
+      }
+    }
+    
+    while(1) {
+      /* minimize the quadratic form Q on the unit square */
+      /* find intersection */
+
+#ifdef HAVE_GCC_LOOP_BUG
+      /* work around gcc bug #12243 */
+      free(NULL);
+#endif
+      
+      det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
+      if (det != 0.0) {
+	w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
+	w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
+	break;
+      }
+
+      /* matrix is singular - lines are parallel. Add another,
+	 orthogonal axis, through the center of the unit square */
+      if (Q[0][0]>Q[1][1]) {
+	v[0] = -Q[0][1];
+	v[1] = Q[0][0];
+      } else if (Q[1][1]) {
+	v[0] = -Q[1][1];
+	v[1] = Q[1][0];
+      } else {
+	v[0] = 1;
+	v[1] = 0;
+      }
+      d = sq(v[0]) + sq(v[1]);
+      v[2] = - v[1] * s.y - v[0] * s.x;
+      for (l=0; l<3; l++) {
+	for (k=0; k<3; k++) {
+	  Q[l][k] += v[l] * v[k] / d;
+	}
+      }
+    }
+    dx = fabs(w.x-s.x);
+    dy = fabs(w.y-s.y);
+    if (dx <= .5 && dy <= .5) {
+      pp->curve.vertex[i].x = w.x+x0;
+      pp->curve.vertex[i].y = w.y+y0;
+      continue;
+    }
+
+    /* the minimum was not in the unit square; now minimize quadratic
+       on boundary of square */
+    min = quadform(Q, s);
+    xmin = s.x;
+    ymin = s.y;
+
+    if (Q[0][0] == 0.0) {
+      goto fixx;
+    }
+    for (z=0; z<2; z++) {   /* value of the y-coordinate */
+      w.y = s.y-0.5+z;
+      w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
+      dx = fabs(w.x-s.x);
+      cand = quadform(Q, w);
+      if (dx <= .5 && cand < min) {
+	min = cand;
+	xmin = w.x;
+	ymin = w.y;
+      }
+    }
+  fixx:
+    if (Q[1][1] == 0.0) {
+      goto corners;
+    }
+    for (z=0; z<2; z++) {   /* value of the x-coordinate */
+      w.x = s.x-0.5+z;
+      w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
+      dy = fabs(w.y-s.y);
+      cand = quadform(Q, w);
+      if (dy <= .5 && cand < min) {
+	min = cand;
+	xmin = w.x;
+	ymin = w.y;
+      }
+    }
+  corners:
+    /* check four corners */
+    for (l=0; l<2; l++) {
+      for (k=0; k<2; k++) {
+	w.x = s.x-0.5+l;
+	w.y = s.y-0.5+k;
+	cand = quadform(Q, w);
+	if (cand < min) {
+	  min = cand;
+	  xmin = w.x;
+	  ymin = w.y;
+	}
+      }
+    }
+
+    pp->curve.vertex[i].x = xmin + x0;
+    pp->curve.vertex[i].y = ymin + y0;
+    continue;
+  }
+
+  free(ctr);
+  free(dir);
+  free(q);
+  return 0;
+
+ calloc_error:
+  free(ctr);
+  free(dir);
+  free(q);
+  return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
+
+/* reverse orientation of a path */
+static void reverse(privcurve_t *curve) {
+  int m = curve->n;
+  int i, j;
+  dpoint_t tmp;
+
+  for (i=0, j=m-1; i<j; i++, j--) {
+    tmp = curve->vertex[i];
+    curve->vertex[i] = curve->vertex[j];
+    curve->vertex[j] = tmp;
+  }
+}
+
+/* Always succeeds */
+static void smooth(privcurve_t *curve, double alphamax) {
+  int m = curve->n;
+
+  int i, j, k;
+  double dd, denom, alpha;
+  dpoint_t p2, p3, p4;
+
+  /* examine each vertex and find its best fit */
+  for (i=0; i<m; i++) {
+    j = mod(i+1, m);
+    k = mod(i+2, m);
+    p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
+
+    denom = ddenom(curve->vertex[i], curve->vertex[k]);
+    if (denom != 0.0) {
+      dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
+      dd = fabs(dd);
+      alpha = dd>1 ? (1 - 1.0/dd) : 0;
+      alpha = alpha / 0.75;
+    } else {
+      alpha = 4/3.0;
+    }
+    curve->alpha0[j] = alpha;	 /* remember "original" value of alpha */
+
+    if (alpha >= alphamax) {  /* pointed corner */
+      curve->tag[j] = POTRACE_CORNER;
+      curve->c[j][1] = curve->vertex[j];
+      curve->c[j][2] = p4;
+    } else {
+      if (alpha < 0.55) {
+	alpha = 0.55;
+      } else if (alpha > 1) {
+	alpha = 1;
+      }
+      p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
+      p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
+      curve->tag[j] = POTRACE_CURVETO;
+      curve->c[j][0] = p2;
+      curve->c[j][1] = p3;
+      curve->c[j][2] = p4;
+    }
+    curve->alpha[j] = alpha;	/* store the "cropped" value of alpha */
+    curve->beta[j] = 0.5;
+  }
+  curve->alphacurve = 1;
+
+  return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 5: Curve optimization (Sec. 2.4) */
+
+/* a private type for the result of opti_penalty */
+struct opti_s {
+  double pen;	   /* penalty */
+  dpoint_t c[2];   /* curve parameters */
+  double t, s;	   /* curve parameters */
+  double alpha;	   /* curve parameter */
+};
+typedef struct opti_s opti_t;
+
+/* calculate best fit from i+.5 to j+.5.  Assume i<j (cyclically).
+   Return 0 and set badness and parameters (alpha, beta), if
+   possible. Return 1 if impossible. */
+static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
+  int m = pp->curve.n;
+  int k, k1, k2, conv, i1;
+  double area, alpha, d, d1, d2;
+  dpoint_t p0, p1, p2, p3, pt;
+  double A, R, A1, A2, A3, A4;
+  double s, t;
+
+  /* check convexity, corner-freeness, and maximum bend < 179 degrees */
+
+  if (i==j) {  /* sanity - a full loop can never be an opticurve */
+    return 1;
+  }
+
+  k = i;
+  i1 = mod(i+1, m);
+  k1 = mod(k+1, m);
+  conv = convc[k1];
+  if (conv == 0) {
+    return 1;
+  }
+  d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
+  for (k=k1; k!=j; k=k1) {
+    k1 = mod(k+1, m);
+    k2 = mod(k+2, m);
+    if (convc[k1] != conv) {
+      return 1;
+    }
+    if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
+      return 1;
+    }
+    if (iprod1(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) {
+      return 1;
+    }
+  }
+
+  /* the curve we're working in: */
+  p0 = pp->curve.c[mod(i,m)][2];
+  p1 = pp->curve.vertex[mod(i+1,m)];
+  p2 = pp->curve.vertex[mod(j,m)];
+  p3 = pp->curve.c[mod(j,m)][2];
+
+  /* determine its area */
+  area = areac[j] - areac[i];
+  area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
+  if (i>=j) {
+    area += areac[m];
+  }
+
+  /* find intersection o of p0p1 and p2p3. Let t,s such that o =
+     interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
+     triangle (p0,o,p3). */
+
+  A1 = dpara(p0, p1, p2);
+  A2 = dpara(p0, p1, p3);
+  A3 = dpara(p0, p2, p3);
+  /* A4 = dpara(p1, p2, p3); */
+  A4 = A1+A3-A2;    
+  
+  if (A2 == A1) {  /* this should never happen */
+    return 1;
+  }
+
+  t = A3/(A3-A4);
+  s = A2/(A2-A1);
+  A = A2 * t / 2.0;
+  
+  if (A == 0.0) {  /* this should never happen */
+    return 1;
+  }
+
+  R = area / A;	 /* relative area */
+  alpha = 2 - sqrt(4 - R / 0.3);  /* overall alpha for p0-o-p3 curve */
+
+  res->c[0] = interval(t * alpha, p0, p1);
+  res->c[1] = interval(s * alpha, p3, p2);
+  res->alpha = alpha;
+  res->t = t;
+  res->s = s;
+
+  p1 = res->c[0];
+  p2 = res->c[1];  /* the proposed curve is now (p0,p1,p2,p3) */
+
+  res->pen = 0;
+
+  /* calculate penalty */
+  /* check tangency with edges */
+  for (k=mod(i+1,m); k!=j; k=k1) {
+    k1 = mod(k+1,m);
+    t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
+    if (t<-.5) {
+      return 1;
+    }
+    pt = bezier(t, p0, p1, p2, p3);
+    d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
+    if (d == 0.0) {  /* this should never happen */
+      return 1;
+    }
+    d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
+    if (fabs(d1) > opttolerance) {
+      return 1;
+    }
+    if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
+      return 1;
+    }
+    res->pen += sq(d1);
+  }
+
+  /* check corners */
+  for (k=i; k!=j; k=k1) {
+    k1 = mod(k+1,m);
+    t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
+    if (t<-.5) {
+      return 1;
+    }
+    pt = bezier(t, p0, p1, p2, p3);
+    d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
+    if (d == 0.0) {  /* this should never happen */
+      return 1;
+    }
+    d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
+    d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
+    d2 *= 0.75 * pp->curve.alpha[k1];
+    if (d2 < 0) {
+      d1 = -d1;
+      d2 = -d2;
+    }
+    if (d1 < d2 - opttolerance) {
+      return 1;
+    }
+    if (d1 < d2) {
+      res->pen += sq(d1 - d2);
+    }
+  }
+
+  return 0;
+}
+
+/* optimize the path p, replacing sequences of Bezier segments by a
+   single segment when possible. Return 0 on success, 1 with errno set
+   on failure. */
+static int opticurve(privpath_t *pp, double opttolerance) {
+  int m = pp->curve.n;
+  int *pt = NULL;     /* pt[m+1] */
+  double *pen = NULL; /* pen[m+1] */
+  int *len = NULL;    /* len[m+1] */
+  opti_t *opt = NULL; /* opt[m+1] */
+  int om;
+  int i,j,r;
+  opti_t o;
+  dpoint_t p0;
+  int i1;
+  double area;
+  double alpha;
+  double *s = NULL;
+  double *t = NULL;
+
+  int *convc = NULL; /* conv[m]: pre-computed convexities */
+  double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
+
+  SAFE_CALLOC(pt, m+1, int);
+  SAFE_CALLOC(pen, m+1, double);
+  SAFE_CALLOC(len, m+1, int);
+  SAFE_CALLOC(opt, m+1, opti_t);
+  SAFE_CALLOC(convc, m, int);
+  SAFE_CALLOC(areac, m+1, double);
+
+  /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
+  for (i=0; i<m; i++) {
+    if (pp->curve.tag[i] == POTRACE_CURVETO) {
+      convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
+    } else {
+      convc[i] = 0;
+    }
+  }
+
+  /* pre-calculate areas */
+  area = 0.0;
+  areac[0] = 0.0;
+  p0 = pp->curve.vertex[0];
+  for (i=0; i<m; i++) {
+    i1 = mod(i+1, m);
+    if (pp->curve.tag[i1] == POTRACE_CURVETO) {
+      alpha = pp->curve.alpha[i1];
+      area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
+      area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
+    }
+    areac[i+1] = area;
+  }
+
+  pt[0] = -1;
+  pen[0] = 0;
+  len[0] = 0;
+
+  /* Fixme: we always start from a fixed point -- should find the best
+     curve cyclically */
+
+  for (j=1; j<=m; j++) {
+    /* calculate best path from 0 to j */
+    pt[j] = j-1;
+    pen[j] = pen[j-1];
+    len[j] = len[j-1]+1;
+
+    for (i=j-2; i>=0; i--) {
+      r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
+      if (r) {
+	break;
+      }
+      if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
+	pt[j] = i;
+	pen[j] = pen[i] + o.pen;
+	len[j] = len[i] + 1;
+	opt[j] = o;
+      }
+    }
+  }
+  om = len[m];
+  r = privcurve_init(&pp->ocurve, om);
+  if (r) {
+    goto calloc_error;
+  }
+  SAFE_CALLOC(s, om, double);
+  SAFE_CALLOC(t, om, double);
+
+  j = m;
+  for (i=om-1; i>=0; i--) {
+    if (pt[j]==j-1) {
+      pp->ocurve.tag[i]     = pp->curve.tag[mod(j,m)];
+      pp->ocurve.c[i][0]    = pp->curve.c[mod(j,m)][0];
+      pp->ocurve.c[i][1]    = pp->curve.c[mod(j,m)][1];
+      pp->ocurve.c[i][2]    = pp->curve.c[mod(j,m)][2];
+      pp->ocurve.vertex[i]  = pp->curve.vertex[mod(j,m)];
+      pp->ocurve.alpha[i]   = pp->curve.alpha[mod(j,m)];
+      pp->ocurve.alpha0[i]  = pp->curve.alpha0[mod(j,m)];
+      pp->ocurve.beta[i]    = pp->curve.beta[mod(j,m)];
+      s[i] = t[i] = 1.0;
+    } else {
+      pp->ocurve.tag[i] = POTRACE_CURVETO;
+      pp->ocurve.c[i][0] = opt[j].c[0];
+      pp->ocurve.c[i][1] = opt[j].c[1];
+      pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
+      pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
+      pp->ocurve.alpha[i] = opt[j].alpha;
+      pp->ocurve.alpha0[i] = opt[j].alpha;
+      s[i] = opt[j].s;
+      t[i] = opt[j].t;
+    }
+    j = pt[j];
+  }
+
+  /* calculate beta parameters */
+  for (i=0; i<om; i++) {
+    i1 = mod(i+1,om);
+    pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
+  }
+  pp->ocurve.alphacurve = 1;
+
+  free(pt);
+  free(pen);
+  free(len);
+  free(opt);
+  free(s);
+  free(t);
+  free(convc);
+  free(areac);
+  return 0;
+
+ calloc_error:
+  free(pt);
+  free(pen);
+  free(len);
+  free(opt);
+  free(s);
+  free(t);
+  free(convc);
+  free(areac);
+  return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define TRY(x) if (x) goto try_error
+
+/* return 0 on success, 1 on error with errno set. */
+int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress) {
+  path_t *p;
+  double nn = 0, cn = 0;
+
+  if (progress->callback) {
+    /* precompute task size for progress estimates */
+    nn = 0;
+    list_forall (p, plist) {
+      nn += p->priv->len;
+    }
+    cn = 0;
+  }
+  
+  /* call downstream function with each path */
+  list_forall (p, plist) {
+    TRY(calc_sums(p->priv));
+    TRY(calc_lon(p->priv));
+    TRY(bestpolygon(p->priv));
+    TRY(adjust_vertices(p->priv));
+    if (p->sign == '-') {   /* reverse orientation of negative paths */
+      reverse(&p->priv->curve);
+    }
+    smooth(&p->priv->curve, param->alphamax);
+    if (param->opticurve) {
+      TRY(opticurve(p->priv, param->opttolerance));
+      p->priv->fcurve = &p->priv->ocurve;
+    } else {
+      p->priv->fcurve = &p->priv->curve;
+    }
+    privcurve_to_curve(p->priv->fcurve, &p->curve);
+
+    if (progress->callback) {
+      cn += p->priv->len;
+      progress_update(cn/nn, progress);
+    }
+  }
+
+  progress_update(1.0, progress);
+
+  return 0;
+
+ try_error:
+  return 1;
+}

Added: trunk/Build/source/texk/web2c/mfluadir/potrace/trace.h
===================================================================
--- trunk/Build/source/texk/web2c/mfluadir/potrace/trace.h	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluadir/potrace/trace.h	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+   This file is part of Potrace. It is free software and it is covered
+   by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include "potracelib.h"
+#include "progress.h"
+#include "curve.h"
+
+int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress);
+
+#endif /* TRACE_H */

Modified: trunk/Build/source/texk/web2c/mfluajitdir/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/mfluajitdir/ChangeLog	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluajitdir/ChangeLog	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,11 +1,8 @@
-2022-01-10  Karl Berry  <karl at freefriends.org>
-
-	* am/mfluajit.am: do not silence tangle-sh.
-
 2017-04-16 Luigi Scarso <luigi.scarso at gmail.com>
 
 	* am/mfluajit.am: delete useless lua files
 
+
 2016-04-05  Karl Berry  <karl at tug.org>
 
 	* am/mflua.am: no need for inimfluajit.

Modified: trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajit.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajit.am	2022-02-12 00:48:37 UTC (rev 61985)
+++ trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajit.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -1,7 +1,6 @@
-## $Id$
 ## texk/web2c/mfluajitdir/am/mfluajit.am: Makefile fragment for MFLuaJIT.
 ##
-## Copyright 2016-2022 Karl Berry <tex-live at tug.org>
+## Copyright 2016 Karl Berry <tex-live at tug.org>
 ## Copyright 2015 Peter Breitenlohner <tex-live at tug.org>
 ## You may freely use, modify and/or distribute this file.
 
@@ -43,11 +42,11 @@
 
 dist_mfluajit_SOURCES = mfluajitdir/mfluajitextra.c mfluajitdir/mfluajitextra.h mfluadir/mflua_version.h
 mfluajit_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(LUAJIT_INCLUDES) $(LUAJIT_DEFINES)
-mfluajit_LDADD = libmfluajit.a libmfluaotfcc.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUAJIT_LIBS)
+mfluajit_LDADD = libmfluajit.a libmfluaotfcc.a libmfluapotrace.a libmfluajitlpeg.a $(LDADD) $(windowlib) $(mf_x_libs) $(LUAJIT_LIBS)
 mfluajit_LDFLAGS = -export-dynamic $(LUAJIT_LDEXTRA)
 nodist_mfluajit_nowin_SOURCES = $(dist_mfluajit_SOURCES)
 mfluajit_nowin_CPPFLAGS = $(mfluajit_CPPFLAGS) -DMFNOWIN $(LUAJIT_INCLUDES) $(LUAJIT_DEFINES)
-mfluajit_nowin_LDADD = libmfluajit.a libmfluaotfcc.a $(LDADD) $(windowlib) $(LUAJIT_LIBS)
+mfluajit_nowin_LDADD = libmfluajit.a libmfluaotfcc.a libmfluapotrace.a libmfluajitlpeg.a $(LDADD) $(windowlib) $(LUAJIT_LIBS)
 mfluajit_nowin_LDFLAGS = -export-dynamic $(LUAJIT_LDEXTRA)
 
 # We must create mfluajitd.h and mfluadir/mflua_version.h before compiling mfluajitextra.c.
@@ -56,7 +55,7 @@
 ## mfluajit and mfluajit-nowin compile mfluajitextra.c with different CPPFLAGS.
 ## Automake, however, does not support CPPFLAGS for individual source files.
 ## To avoid compiling everything twice, the common objects are in a library.
-EXTRA_LIBRARIES += libmfluajit.a libmfluaotfcc.a
+EXTRA_LIBRARIES += libmfluajit.a libmfluaotfcc.a libmfluapotrace.a libmfluajitlpeg.a
 
 # MFLuaJIT C sources
 mfluajit_c_h = mfluajitini.c mfluajit0.c mfluajitcoerce.h mfluajitd.h
@@ -77,9 +76,9 @@
 
 # Tangling MFLuaJIT
 mfluajit.p mfluajit.pool: mfluajit-tangle
-	$(texmf_tangle) mfluajit mfluajit
+	@$(texmf_tangle) mfluajit mfluajit
 mfluajit-tangle: tangle$(EXEEXT) mfluajit.web mfluajit.ch tangle-sh
-	$(texmf_tangle) mfluajit mfluajit
+	@$(texmf_tangle) mfluajit mfluajit
 
 # Generate mfluajit.web
 mfluajit.web: tie$(EXEEXT) $(mfluajit_web_srcs)
@@ -134,5 +133,3 @@
         mfluadir/mfluatrap/mflua_ttx_backend.lua \
         mfluadir/mfluatrap/texmf.cnf \
         mfluadir/mfluatrap/mfluatrap.diffs
-
-# (end of mfluajit.am)

Added: trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajitlpeg.am
===================================================================
--- trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajitlpeg.am	                        (rev 0)
+++ trunk/Build/source/texk/web2c/mfluajitdir/am/mfluajitlpeg.am	2022-02-12 18:02:57 UTC (rev 61986)
@@ -0,0 +1,25 @@
+## texk/web2c/mfluajitdir/am/mfluajitlpeg.am: Makefile fragment for libmfluajitlpeg.
+## 
+## Copyright (C) 2022 Luigi Scarso <tex-live at tug.org>
+## You may freely use, modify and/or distribute this file.
+
+## mfluajitlpeg
+##
+EXTRA_LIBRARIES += libmfluajitlpeg.a
+
+$(libmfluajitlpeg_a_OBJECTS): $(LUA_DEPEND)
+
+libmfluajitlpeg_a_CPPFLAGS = \
+	-I$(top_srcdir)/mfluadir/luapeg \
+	$(LUAJIT_INCLUDES)
+
+
+libmfluajitlpeg_a_CFLAGS = # $(WARNING_CFLAGS)
+
+
+libmfluajitlpeg_a_SOURCES = \
+	mfluadir/luapeg/lpeg.c \
+	mfluadir/luapeg/lpeg.h 
+
+
+



More information about the tex-live-commits mailing list.