luametatex-2.11.07/0000755000175000017500000000000014760367410013017 5ustar hillehilleluametatex-2.11.07/CMakeSettings.json0000644000175000017500000000527214760367410016421 0ustar hillehille{ "configurations": [ { "name": "msvc-x64-debug", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_x64_x64" ], "buildRoot": "${projectDir}\\build\\${name}", "installRoot": "${projectDir}\\..\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "" }, { "name": "msvc-x64-release", "generator": "Ninja", "configurationType": "Release", "buildRoot": "${projectDir}\\build\\${name}", "installRoot": "${projectDir}\\..\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x64_x64" ] }, { "name": "msvc-x64-clang", "generator": "Ninja", "configurationType": "Release", "buildRoot": "${projectDir}\\build\\${name}", "installRoot": "${projectDir}\\..\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "", "inheritEnvironments": [ "clang_cl_x64" ] }, { "name": "msvc-arm64-release", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_arm64_x64" ], "buildRoot": "${projectDir}\\build\\${name}", "installRoot": "${projectDir}\\..\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "" }, { "name": "wsl-gcc-release", "generator": "Ninja", "configurationType": "RelWithDebInfo", "buildRoot": "${projectDir}\\out\\build\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}", "cmakeExecutable": "cmake", "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "linux_x64" ], "wslPath": "${defaultWSLPath}", "addressSanitizerRuntimeFlags": "detect_leaks=0" }, { "name": "msvc-x86-release", "generator": "Ninja", "configurationType": "Release", "buildRoot": "${projectDir}\\build\\${name}", "installRoot": "${projectDir}\\..\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "-v", "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x86_x64" ] } ] }luametatex-2.11.07/build.sh0000644000175000017500000001037214760367410014455 0ustar hillehille# The official designated locations are: # # luametatex[.exe] # mtxrun[.exe] -> luametatex[.exe] # mtxrun.lua (latest version) # context.lua (latest version) # This test is not yet okay but I have no time (or motivation) to look into it now, so for now we don't # use ninja (not that critical). #NINJA=$(which ninja); #if (NINJA) then # NINJA="-G Ninja" #else NINJA="" #fi if [ "$1" = "mingw-64" ] || [ "$1" = "mingw64" ] || [ "$1" = "mingw" ] || [ "$1" == "--mingw64" ] then PLATFORM="win64" SUFFIX=".exe" mkdir -p build/mingw-64 cd build/mingw-64 cmake $NINJA -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw-64.cmake ../.. elif [ "$1" = "mingw-32" ] || [ "$1" = "mingw32" ] || [ "$1" == "--mingw32" ] then PLATFORM="mswin" SUFFIX=".exe" mkdir -p build/mingw-32 cd build/mingw-32 cmake $NINJA -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw-32.cmake ../.. elif [ "$1" = "mingw-64-ucrt" ] || [ "$1" = "mingw64ucrt" ] || [ "$1" = "--mingw64ucrt" ] || [ "$1" = "ucrt" ] || [ "$1" = "--ucrt" ] then PLATFORM="win64" SUFFIX=".exe" mkdir -p build/mingw-64-ucrt cd build/mingw-64-ucrt cmake $NINJA -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw-64-ucrt.cmake ../.. elif [ "$1" = "cygwin" ] || [ "$1" = "--cygwin" ] then PLATFORM="cygwin" SUFFIX=".exe" mkdir -p build/cygwin cd build/cygwin cmake $NINJA ../.. elif [ "$1" = "osx-arm" ] || [ "$1" = "osxarm" ] || [ "$1" = "--osx-arm" ] || [ "$1" = "--osxarm" ] then PLATFORM="osx-arm" SUFFIX=" " mkdir -p build/osx-arm cd build/osx-arm cmake $NINJA -DCMAKE_OSX_ARCHITECTURES="arm64" ../.. elif [ "$1" = "osx-intel" ] || [ "$1" = "osxintel" ] || [ "$1" = "--osx-intel" ] || [ "$1" = "--osxintel" ] then PLATFORM="osx-intel" SUFFIX=" " mkdir -p build/osx-intel cd build/osx-intel cmake $NINJA -DCMAKE_OSX_ARCHITECTURES="x86_64" ../.. elif [ "$1" = "osx-universal" ] || [ "$1" = "osxuniversal" ] || [ "$1" = "--osx-universal" ] || [ "$1" = "--osxuniversal" ] then PLATFORM="osx" SUFFIX=" " mkdir -p build/osx cd build/osx cmake $NINJA -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" ../.. elif [ "$1" = "help" ] || [ "$1" = "--help" ] then echo "" echo "platforms, optionally passed as argument:" echo "" echo "mingw-64" echo "mingw-32" echo "mingw-64-ucrt" echo "cygwin" echo "osx-arm" echo "osx-intel" echo "osx-universal" echo "" echo "default platform: native" echo "" exit 0 else PLATFORM="native" SUFFIX=" " mkdir -p build/native cd build/native cmake $NINJA ../.. fi #~ make -j8 cmake --build . --parallel 8 echo "" echo "tex trees" echo "" echo "resources like public fonts : tex/texmf/...." echo "the context macro package : tex/texmf-context/...." echo "the luametatex binary : tex/texmf-$PLATFORM/bin/..." echo "optional third party modules : tex/texmf-context/...." echo "fonts installed by the user : tex/texmf-fonts/fonts/data/...." echo "styles made by the user : tex/texmf-projects/tex/context/user/...." echo "" echo "binaries:" echo "" echo "tex/texmf-/bin/luametatex$SUFFIX : the compiled binary (some 3-4MB)" echo "tex/texmf-/bin/mtxrun$SUFFIX : copy of or link to luametatex" echo "tex/texmf-/bin/context$SUFFIX : copy of or link to luametatex" echo "tex/texmf-/bin/mtxrun.lua : copy of tex/texmf-context/scripts/context/lua/mtxrun.lua" echo "tex/texmf-/bin/context.lua : copy of tex/texmf-context/scripts/context/lua/context.lua" echo "" echo "commands:" echo "" echo "mtxrun --generate : create file database" echo "mtxrun --script fonts --reload : create font database" echo "mtxrun --autogenerate context ... : run tex file (e.g. from editor)" echo "" luametatex-2.11.07/build.cmd0000644000175000017500000000534414760367410014611 0ustar hillehillerem When something fails, make sure to remove the cmake cache. When compile from rem the Visual Studio environment mixed with compiling from the command line rem some confusion can occur. setlocal @echo . @echo supported flags : --arm64 --x64 --x86 --intel64 --intel86 @echo . set luametatexsources=%~dp0 set luametatexplatform=x64 set msvcplatform=x64 for %%G in (%*) do ( if [%%G] == [--arm64] ( set luametatexplatform=arm64 set msvcplatform=x86_arm64 ) if [%%G] == [--intel64] ( set luametatexplatform=x64 set msvcplatform=amd64 ) if [%%G] == [--intel86] ( set luametatexplatform=x86 set msvcplatform=x86_amd64 ) if [%%G] == [--x64] ( set luametatexplatform=x64 set msvcplatform=amd64 ) if [%%G] == [--x86] ( set luametatexplatform=x86 set msvcplatform=x86_amd64 ) ) set visualstudiopath=c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build set luametatexbuildpath=msvc-cmd-%luametatexplatform%-release @echo . @echo luametatexplatform : %luametatexplatform% @echo msvcplatform : %msvcplatform% @echo visualstudiopath : %visualstudiopath% @echo luametatexbuildpath : %luametatexbuildpath% @echo . mkdir build chdir build rmdir /S /Q %luametatexbuildpath% mkdir %luametatexbuildpath% chdir %luametatexbuildpath% call "%visualstudiopath%\vcvarsall.bat" %msvcplatform% cmake ../.. cmake --build . --config Release --parallel 8 cd .. cd .. dir build\%luametatexbuildpath%\Release\luametatex.exe @echo . @echo tex trees: @echo . @echo resources like public fonts : tex/texmf/.... @echo the context macro package : tex/texmf-context/.... @echo the luametatex binary : tex/texmf-win64/bin/... @echo optional third party modules : tex/texmf-context/.... @echo fonts installed by the user : tex/texmf-fonts/fonts/data/.... @echo styles made by the user : tex/texmf-projects/tex/context/user/.... @echo . @echo binaries: @echo . @echo tex/texmf-win64/bin/luametatex.exe : the compiled binary (some 2-3MB) @echo tex/texmf-win64/bin/mtxrun.exe : copy of or link to luametatex.exe @echo tex/texmf-win64/bin/context.exe : copy of or link to luametatex.exe @echo tex/texmf-win64/bin/mtxrun.lua : copy of tex/texmf-context/scripts/context/lua/mtxrun.lua @echo tex/texmf-win64/bin/context.lua : copy of tex/texmf-context/scripts/context/lua/context.lua @echo . @echo commands: @echo . @echo mtxrun --generate : create file database @echo mtxrun --script fonts --reload : create font database @echo mtxrun --autogenerate context ... : run tex file (e.g. from editor) @echo . endlocal luametatex-2.11.07/build.txt0000644000175000017500000000411614760367410014661 0ustar hillehilleHi, The build script produce efficient static binaries with only a couple of system libraries as dependency. ConTeXt will not depend on anything else than provided here. Lua is the extension language to be used and that has worked well for quite a while now. The build script that is provided will compile under ./build so you might want to make a copy of the source tree to a suitable place that you can wipe after the job is done. The script accepts only a few command line arguments. build.sh : --native build/native meant for unix (linux, freebsd, openbsd, osx, arm) --mingw-32 build/mingw-32 meant for 32 bit windows (crosscompiled) --mingw-64 build/mingw-64 meant for 64 bit windows (crosscompiled) I develop LuaMetaTeX on Windows and use WLS (with OpenSuse) for cross compilation as well as native Linux binaries. Editing is done in Visual Studio with the exception of the MetaPost CWeb files for which I use SciTE. Because we use CMake, you can compile using the MSVC compiler as well as CLang. Currently the MingW crosscompiled binaries are slightly faster, next come the native ones, but till now CLang lags behind. The native compiler produces the smallest binaries and compiles fastest. build.cmd : --x64 build/msvc-cmd-x64 meant for 64 bit windows using intel/amd chips --x32 build/msvc-cmd-x86 meant for 32 bit windows using intel/amd chips --arm64 build/msvc-cmd-arm64 meant for 64 bit windows using arm chips Alternatively you can run a build job from Visual Studio. Of course it only works well if you have the right compilers installed which is easy to do from the user interface. All settings happen in CMakeLists.txt so you have to load that one. Support for LuaMetaTeX and ConTeXt is provided at the (dev-)context mailing lists and at the ConTeXt Wiki. Binaries are available at: https://build.contextgarden.net/#/waterfall?tags=c.luametatex https://dl.contextgarden.net/build/luametatex The first link shows the status, the second link is where the binaries can be downloaded. Hans Hagen luametatex-2.11.07/CMakeLists.txt0000644000175000017500000002273314760367410015566 0ustar hillehille# We use CMake but I bet we can also provide a simple make file for linux just because # when I look what gets compiled into CMake we need very little of that (and it # has a lot of dependencies - ssh related, compression, security, xml, etc), but maybe # there is a lightweight version of CMake. cmake_minimum_required(VERSION 3.9..3.28) project(luametatex VERSION 2.11 LANGUAGES C) # I need to check with Mojca of the compile farm can handle this. set(CMAKE_C_STANDARD 11) # set(CMAKE_C_STANDARD 17) # needs 3.21 # https://sourceforge.net/p/predef/wiki/OperatingSystems/ # https://sourceforge.net/p/predef/wiki/Architectures/ include(GNUInstallDirs) # Optionals (maybe have a LMT_*_TOO for each of them). We might start out with only a very few # optionals at some time, but for now we enable them (there is not not much code involved). The # idea behind these optionals is that we have very simple (!) interfaces, delegating as much as # possible to Lua. We will *not* add interfaces with many bindings because that will introduce # dependencies (and looking at e.g. LuaTeX build updates shows that clearly: a no-go). set(LMT_KPSE_TOO 1) # In case we want to manage MKII scripts (etc) with mtxrun. set(LMT_HB_TOO 1) # Maybe handy for Idris' font development (old converted ffi stuff) # This triggere link time optimization, which adds to compile time and gains (at most) a few # percent on runtime. When set, because we're sparse, we also strip the binary. # set(LMT_OPTIMIZE 1) # This makes the binary some 135K smaller so it might become the default at some point which is # nice (the smaller as runner the better). After all, we don't load external (Lua) libraries # anyway. set(LMT_STRIP 1) # When one wants to use Lua libraries, this is needed. But keep in mind that it's not supported, # so we won't look into issues that could result from that. Getting a matching library is upto # the user. Keep in mind that we might have set a different bytecode (luac) version during the # alpha/beta stages of a Lua development version. # set(LMT_PERMIT_LUA_LIBRARIES 1) if (DEFINED LMT_PERMIT_LUA_LIBRARIES) unset(LMT_STRIP) unset(LMT_OPTIMIZE) add_definitions(-DLMT_PERMIT_LUA_LIBRARIES="yes") endif () if (MSVC) if (CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options( -Wall -O2 -Wcast-align -Wcast-qual -Wno-unknown-pragmas -fno-strict-aliasing -Wno-pedantic -Wno-deprecated-declarations -Wno-missing-noreturn -Wno-shadow ) add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-DLMT_COMPILER_USED="clang") else() add_compile_options( /Wall /wd4127 # constant conditional expression /wd4131 # old style declarator /wd4152 # function pointer cast /wd4201 # nonstandard extension used: nameless struct/union /wd4244 # assignment in conditional expression /wd4456 # local vars with same name as outer variable /wd4457 # local vars with same function parameter /wd4464 # relative include path /wd4668 # missing defines /wd4702 # unreachable code /wd4710 # inlining /wd4711 # inlining /wd4774 # sprint argument 2 warning /wd4777 # format argument 2 warning /wd4820 # local vars with same name as outer variable /wd4996 # strdup etc warnings /wd5045 # spectre # /GL # whole program link optimization # /Gw # whole program data optimization (a little smaller bin) # /Ob3 # more agressive inline, much larger bin, no gain /wd4061 # enumerator * in switch * is not explicitly handled (mp) /wd4701 # potentially unitialized local variable (lua) /wd4255 # no function prototype given /wd5105 # macro expansion producing 'defined' has undefined behavior /wd4548 # expression before comma has no effect; expected expression with side-effect # indeed a bit faster but also a much larger binary: # /fp:fast # okay for amd processors too but no difference in size so probably no gain: # /favor:INTEL64 # /fsanitize:address # /std:c17 ) # We always optimize ... symbols are not in the binary anyway so there is no advantage # (like when accessing Lua api functions). We could have an additional luametatex-lua.dll # but that also creates a dependency (possible conflict). So just don't expect using # Lua libraries in luametatex. # if (DEFINED LMT_OPTIMIZE) add_compile_options( /GL # whole program link optimization /Gw # whole program data optimization (a little smaller bin) ) # endif() add_definitions(-DLMT_COMPILER_USED="msvc") endif() else() if (CMAKE_C_COMPILER_ID MATCHES "Clang") # why not -03 add_compile_options( -O2 ) add_definitions(-DLMT_COMPILER_USED="clang") else() add_compile_options( -O3 # -g0 # -mtune=nocona # fails on arm so more testing needed ) add_definitions(-DLMT_COMPILER_USED="gcc") # add_compile_options(-pg) # add_link_options(-pg) endif() add_compile_options( -Wall -Wcast-align -Wcast-qual -Wno-unknown-pragmas -Wno-unused-result -fno-strict-aliasing ) # for c17 # # add_definitions(-D__STDC_WANT_LIB_EXT2__=1) if ((DEFINED LMT_OPTIMIZE) OR (DEFINED LMT_STRIP)) if (NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) set(CMAKE_EXE_LINKER_FLAGS "-s") endif() endif() endif() if (CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options( -Wno-unknown-warning-option -Wno-nonportable-include-path -Wno-nonportable-system-include-path -Wno-newline-eof -Wno-extra-semi-stmt -Wno-sign-conversion -Wno-unused-macros -Wno-reserved-id-macro -Wno-comma -Wno-switch-enum -Wno-shadow -Wno-missing-noreturn -Wno-implicit-fallthrough # -Wno-format -Wno-reserved-identifier -Wno-date-time -Wno-format-nonliteral -Wno-float-equal # too noisy, we just look at what gcc reports -Wno-unsafe-buffer-usage -Wno-macro-redefined -Wno-undef -Wno-switch-default -Wno-class-varargs ) endif() # Not that tested (converted ffi originals): if ((DEFINED LMT_KPSE_TOO)) add_definitions(-DLMT_KPSE_TOO=1) endif() if ((DEFINED LMT_HB_TOO)) add_definitions(-DLMT_HB_TOO=1) endif() # This needs cmake >= 3.9 and produces a 60K smaller mingw binary but it take quite a bit of # runtime to get there so it should become an option (apart from testing on all builders). if (DEFINED LMT_OPTIMIZE) include(CheckIPOSupported) check_ipo_supported(RESULT ipo_supported OUTPUT ipo_message) if (ipo_supported) # # We only have one program so we do it global (can become an -- option) # # set_property(TARGET luametatex PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) # # mingw64: 2865664, nocona: 2819584, lto: 2835968 (around 1% gain on manual) # set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # else() # No message needed, just accept the fact. endif() endif() # Mimalloc is still under development, so we only support it on a few platforms. By the time it is # stable we can probably remove some of the following tests. A bit of a hack: # # When the old osx version is dropped and armhf is upgraded we can enable unix except solaris which # fails. So, only osx 10.6 and rpi 32 fail. But we will probably drop 32 bit in the future anyway. # # At the beginning of 2025 the gain is some 5 percent on the 650 page luametate manual over the # default memory allocator. # CMAKE_HOST_SYSTEM_PROCESSOR arm64 x86_64 # if (APPLE) # set(MI_OSX_ZONE 1) # endif() if (CMAKE_HOST_SOLARIS) # fails elseif (MSVC) set(luametatex_use_mimalloc 1) elseif (CMAKE_HOST_APPLE AND NOT (${CMAKE_C_COMPILER} MATCHES "arm")) # fails on the osx intel elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv7l") # fails on the rpi 32 bit elseif (CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang") # no motivation to figure specifics out else() set(luametatex_use_mimalloc 1) endif() include_directories(${CMAKE_ROOT}/source) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source) if ((DEFINED luametatex_use_mimalloc)) add_definitions(-DLUAMETATEX_USE_MIMALLOC=1) # add_definitions(-DMIMALLOC_RESET_DELAY=250) # set(luametatex_use_mimalloc 1) include(cmake/mimalloc.cmake) endif() include(cmake/tex.cmake) include(cmake/lua.cmake) include(cmake/mp.cmake) include(cmake/luarest.cmake) include(cmake/luasocket.cmake) include(cmake/luaoptional.cmake) include(cmake/pplib.cmake) include(cmake/miniz.cmake) include(cmake/softposit.cmake) include(cmake/potrace.cmake) include(cmake/luametatex.cmake) luametatex-2.11.07/source/0000755000175000017500000000000014760367410014317 5ustar hillehilleluametatex-2.11.07/source/luarest/0000755000175000017500000000000014760367410015776 5ustar hillehilleluametatex-2.11.07/source/luarest/lmtoslibext.c0000644000175000017500000003317014760367410020514 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" # if defined (_WIN32) # define MKDIR(a,b) mkdir(a) # else # define MKDIR(a,b) mkdir(a,b) # endif /*tex An attempt to figure out the basic platform, does not care about niceties like version numbers yet, and ignores platforms where \LUATEX\ is unlikely to successfully compile without major porting effort (amiga,mac,os2,vms). We dropped solaris, cygwin, hpux, iris, sysv, dos, djgpp etc. Basically we have either a windows or some kind of unix brand. */ # ifdef _WIN32 # define OSLIB_PLATTYPE "windows" # define OSLIB_PLATNAME "windows" # else # include # include # if defined(__linux__) || defined (__gnu_linux__) # define OSLIB_PLATNAME "linux" # elif defined(__MACH__) && defined(__APPLE__) # define OSLIB_PLATNAME "macosx" # elif defined(__FreeBSD__) # define OSLIB_PLATNAME "freebsd" # elif defined(__OpenBSD__) # define OSLIB_PLATNAME "openbsd" # elif defined(__BSD__) # define OSLIB_PLATNAME "bsd" # elif defined(__GNU__) # define OSLIB_PLATNAME "gnu" # else # define OSLIB_PLATNAME "generic" # endif # define OSLIB_PLATTYPE "unix" # endif static int oslib_gettypevalues(lua_State *L) { lua_createtable(L, 2, 0); lua_set_string_by_index(L, 1, "windows"); lua_set_string_by_index(L, 2, "unix"); return 1; } static int oslib_getnamevalues(lua_State *L) { lua_createtable(L, 7, 0); lua_set_string_by_index(L, 1, "windows"); lua_set_string_by_index(L, 2, "linux"); lua_set_string_by_index(L, 3, "macosx"); lua_set_string_by_index(L, 4, "freebsd"); lua_set_string_by_index(L, 5, "bsd"); lua_set_string_by_index(L, 6, "gnu"); lua_set_string_by_index(L, 7, "generic"); return 1; } /*tex There could be more platforms that don't have these two, but win32 and sunos are for sure. |gettimeofday()| for win32 is using an alternative definition */ # ifndef _WIN32 # include /*tex for |gettimeofday()| */ # include /*tex for |times()| */ # include # endif static int oslib_sleep(lua_State *L) { lua_Number interval = luaL_checknumber(L, 1); lua_Number units = luaL_optnumber(L, 2, 1); # ifdef _WIN32 Sleep((DWORD) (1e3 * interval / units)); # else /* assumes posix or bsd */ usleep((unsigned) (1e6 * interval / units)); # endif return 0; } # ifdef _WIN32 # define _UTSNAME_LENGTH 65 /*tex Structure describing the system and machine. */ typedef struct utsname { char sysname [_UTSNAME_LENGTH]; char nodename[_UTSNAME_LENGTH]; char release [_UTSNAME_LENGTH]; char version [_UTSNAME_LENGTH]; char machine [_UTSNAME_LENGTH]; } utsname; /*tex Get name and information about current kernel. */ /*tex \starttabulate[|T|r|] \NC Windows 10 \NC 10.0 \NC \NR \NC Windows Server 2016 \NC 10.0 \NC \NR \NC Windows 8.1 \NC 6.3 \NC \NR \NC Windows Server 2012 R2 \NC 6.3 \NC \NR \NC Windows 8 \NC 6.2 \NC \NR \NC Windows Server 2012 \NC 6.2 \NC \NR \NC Windows 7 \NC 6.1 \NC \NR \NC Windows Server 2008 R2 \NC 6.1 \NC \NR \NC Windows Server 2008 \NC 6.0 \NC \NR \NC Windows Vista \NC 6.0 \NC \NR \NC Windows Server 2003 R2 \NC 5.2 \NC \NR \NC Windows Server 2003 \NC 5.2 \NC \NR \NC Windows XP 64-Bit Edition \NC 5.2 \NC \NR \NC Windows XP \NC 5.1 \NC \NR \NC Windows 2000 \NC 5.0 \NC \NR \stoptabulate */ static int uname(struct utsname *uts) { OSVERSIONINFO osver; SYSTEM_INFO sysinfo; DWORD sLength; memset(uts, 0, sizeof(*uts)); osver.dwOSVersionInfoSize = sizeof(osver); GetSystemInfo(&sysinfo); strcpy(uts->sysname, "Windows"); /*tex When |GetVersionEx| becomes obsolete the version and release fields will be set to "". */ // if (0) { // GetVersionEx(&osver); // sprintf(uts->version, "%ld.%02ld", osver.dwMajorVersion, osver.dwMinorVersion); // if (osver.szCSDVersion[0] != '\0' && (strlen(osver.szCSDVersion) + strlen(uts->version) + 1) < sizeof(uts->version)) { // strcat(uts->version, " "); // strcat(uts->version, osver.szCSDVersion); // } // sprintf(uts->release, "build %ld", osver.dwBuildNumber & 0xFFFF); // } else { /*tex I can't motivate myself to figure this out. */ strcpy(uts->version, ""); strcpy(uts->release, ""); // } /*tex So far for the fragile and actually not that relevant part of |uts|. */ switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: strcpy(uts->machine, "x86_64"); break; # ifdef PROCESSOR_ARCHITECTURE_ARM64 case PROCESSOR_ARCHITECTURE_ARM64: strcpy(uts->machine, "arm64"); break; # endif case PROCESSOR_ARCHITECTURE_INTEL: strcpy(uts->machine, "i386"); break; default: strcpy(uts->machine, "unknown"); break; } sLength = sizeof(uts->nodename) - 1; GetComputerName(uts->nodename, &sLength); return 0; } # endif static int oslib_getunamefields(lua_State *L) { lua_createtable(L, 5, 0); lua_set_string_by_index(L, 1, "sysname"); lua_set_string_by_index(L, 2, "machine"); lua_set_string_by_index(L, 3, "release"); lua_set_string_by_index(L, 4, "version"); lua_set_string_by_index(L, 5, "nodename"); return 1; } static int oslib_uname(lua_State *L) { struct utsname uts; if (uname(&uts) >= 0) { lua_createtable(L,0,5); lua_pushstring(L, uts.sysname); lua_setfield(L, -2, "sysname"); lua_pushstring(L, uts.machine); lua_setfield(L, -2, "machine"); lua_pushstring(L, uts.release); lua_setfield(L, -2, "release"); lua_pushstring(L, uts.version); lua_setfield(L, -2, "version"); lua_pushstring(L, uts.nodename); lua_setfield(L, -2, "nodename"); } else { lua_pushnil(L); } return 1; } # if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) # define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 # else # define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL # endif # ifdef _WIN32 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x04 # endif static int oslib_gettimeofday(lua_State *L) { FILETIME ft; __int64 tmpres = 0; GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; tmpres /= 10; /*tex Convert file time to unix epoch: */ tmpres -= DELTA_EPOCH_IN_MICROSECS; /*tex Float: */ lua_pushnumber(L, (double) tmpres / 1000000.0); return 1; } static int oslib_enableansi(lua_State *L) { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode = 0; int done = 0; if (GetConsoleMode(handle, &mode)) { mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (SetConsoleMode(handle, mode)) { done = 1; } else { /* bad */ } } lua_pushboolean(L, done); return 1; } # else static int oslib_gettimeofday(lua_State *L) { double v; struct timeval tv; gettimeofday(&tv, NULL); v = (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; /*tex Float: */ lua_pushnumber(L, v); return 1; } static int oslib_enableansi(lua_State *L) { lua_pushboolean(L, 1); return 1; } # endif /*tex Historically we have a different os.execute than Lua! */ static int oslib_execute(lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); if (cmd) { lua_pushinteger(L, aux_utf8_system(cmd) || lmt_error_state.default_exit_code); } else { lua_pushinteger(L, 0); } return 1; } # ifdef _WIN32 static int oslib_remove (lua_State *L) { const char *filename = luaL_checkstring(L, 1); return luaL_fileresult(L, aux_utf8_remove(filename) == 0, filename); } static int oslib_rename (lua_State *L) { const char *fromname = luaL_checkstring(L, 1); const char *toname = luaL_checkstring(L, 2); return luaL_fileresult(L, aux_utf8_rename(fromname, toname) == 0, NULL); } static int oslib_getcodepage(lua_State *L) { lua_pushinteger(L, (int) GetOEMCP()); lua_pushinteger(L, (int) GetACP()); return 2; } /* static int oslib_getenv(lua_State *L) { LPWSTR wkey = utf8_to_wide(luaL_checkstring(L, 1)); char * val = wide_to_utf8(_wgetenv(wkey)); lmt_memory_free(wkey); lua_pushstring(L, val); lmt_memory_free(val); return 1; } */ static int oslib_getenv(lua_State *L) { const char *key = luaL_checkstring(L, 1); char *val = NULL; if (key) { size_t wlen = 0; LPWSTR wkey = aux_utf8_to_wide(key); _wgetenv_s(&wlen, NULL, 0, wkey); if (wlen) { LPWSTR wval = (LPWSTR) lmt_memory_malloc(wlen * sizeof(WCHAR)); if (! _wgetenv_s(&wlen, wval, wlen, wkey)) { val = aux_utf8_from_wide(wval); } } } if (val) { lua_pushstring(L, val); } else { lua_pushnil(L); } return 1; } static int oslib_setenv(lua_State *L) { const char *key = luaL_optstring(L, 1, NULL); if (key) { const char *val = luaL_optstring(L, 2, NULL); LPWSTR wkey = aux_utf8_to_wide(key); LPWSTR wval = aux_utf8_to_wide(val ? val : ""); int bad = _wputenv_s(wkey, wval); lmt_memory_free(wval); lmt_memory_free(wkey); if (bad) { return luaL_error(L, "unable to change environment"); } } lua_pushboolean(L, 1); return 1; } # else static int oslib_getcodepage(lua_State *L) { lua_pushboolean(L,0); lua_pushboolean(L,0); return 2; } static int oslib_setenv(lua_State *L) { const char *key = luaL_optstring(L, 1, NULL); if (key) { const char *val = luaL_optstring(L, 2, NULL); if (val) { char *value = lmt_memory_malloc((unsigned) (strlen(key) + strlen(val) + 2)); sprintf(value, "%s=%s", key, val); if (putenv(value)) { /* lmt_memory_free(value); */ /* valgrind reports some issue otherwise */ return luaL_error(L, "unable to change environment"); } else { /* lmt_memory_free(value); */ /* valgrind reports some issue otherwise */ } } else { (void) unsetenv(key); } } lua_pushboolean(L, 1); return 1; } # endif static const luaL_Reg oslib_function_list[] = { { "sleep", oslib_sleep }, { "uname", oslib_uname }, { "gettimeofday", oslib_gettimeofday }, { "setenv", oslib_setenv }, { "execute", oslib_execute }, # ifdef _WIN32 { "rename", oslib_rename }, { "remove", oslib_remove }, { "getenv", oslib_getenv }, # endif { "enableansi", oslib_enableansi }, { "getcodepage", oslib_getcodepage }, { "getnamevalues", oslib_getnamevalues }, { "gettypevalues", oslib_gettypevalues }, { "getunamefields", oslib_getunamefields }, { NULL, NULL }, }; /*tex The |environ| variable is depricated on windows so it made sense to just drop this old \LUATEX\ feature. */ # ifndef _WIN32 extern char **environ; # else # define environ _environ # endif int luaextend_os(lua_State *L) { /*tex We locate the library: */ lua_getglobal(L, "os"); /*tex A few constant strings: */ lua_pushliteral(L, OSLIB_PLATTYPE); lua_setfield(L, -2, "type"); lua_pushliteral(L, OSLIB_PLATNAME); lua_setfield(L, -2, "name"); /*tex The extra functions: */ for (const luaL_Reg *lib = oslib_function_list; lib->name; lib++) { lua_pushcfunction(L, lib->func); lua_setfield(L, -2, lib->name); } /*tex Environment variables: */ if (0) { char **envpointer = environ; /*tex Provided by the standard library. */ if (envpointer) { lua_pushstring(L, "env"); lua_newtable(L); while (*envpointer) { /* TODO: perhaps a memory leak here */ char *envitem = lmt_memory_strdup(*envpointer); char *envitem_orig = envitem; char *envkey = envitem; while (*envitem != '=') { envitem++; } *envitem = 0; envitem++; lua_pushstring(L, envkey); lua_pushstring(L, envitem); lua_rawset(L, -3); envpointer++; lmt_memory_free(envitem_orig); } lua_rawset(L, -3); } } /*tex Done. */ lua_pop(L, 1); return 1; } luametatex-2.11.07/source/luarest/lmtbasexxlib.c0000644000175000017500000001231114760367410020636 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" /* # define BASEXX_PDF 1 */ # include # include # include /*tex First I had a mix of own code and LHF code (base64 and base85) but in the end I decided to reuse some of pplibs code. Performance is ok, although we can speed up the base16 coders. When needed, we can have a few more but normally pure \LUA\ is quite ok for our purpose. */ # define encode_nl(L) \ (lua_type(L, 2) == LUA_TNUMBER) ? (lmt_tointeger(L, 2)) : ( (lua_isboolean(L, 2)) ? 80 : 0 ) # define lua_iof_push(L,out) \ lua_pushlstring(L,(const char *) out->buf, iof_size(out)) static int basexxlib_encode_16(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 2 * l; size_t nl = encode_nl(L); iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); if (nl) { base16_encode_ln(inp, out, 0, nl); } else { base16_encode(inp, out); } lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_decode_16(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = l / 2; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); base16_decode(inp, out); lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_encode_64(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L,1,&l); size_t n = 4 * l; size_t nl = encode_nl(L); iof *inp = iof_filter_string_reader(s,l); iof *out = iof_filter_buffer_writer(n); if (nl) { base64_encode_ln(inp,out,0,nl); } else { base64_encode(inp,out); } lua_iof_push(L,out); iof_close(out); return 1; } static int basexxlib_decode_64(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = l; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); base64_decode(inp, out); lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_encode_85(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 5 * l; size_t nl = encode_nl(L); iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); if (nl) { base85_encode_ln(inp, out, 0, 80); } else { base85_encode(inp, out); } lua_iof_push(L,out); iof_close(out); return 1; } static int basexxlib_decode_85(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = l; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); base85_decode(inp, out); lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_encode_RL(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 2 * l; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); runlength_encode(inp, out); lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_decode_RL(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 2 * l; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); runlength_decode(inp, out); lua_iof_push(L, out); iof_close(out); return 1; } static int basexxlib_encode_LZW(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 2 * l; char *t = lmt_memory_malloc(n); int flags = lmt_optinteger(L, 2, LZW_ENCODER_DEFAULTS); iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_string_writer(t, n); lzw_encode(inp, out, flags); lua_pushlstring(L, t, iof_size(out)); lmt_memory_free(t); return 1; } static int basexxlib_decode_LZW(lua_State *L) { size_t l; const unsigned char *s = (const unsigned char*) luaL_checklstring(L, 1, &l); size_t n = 2 * l; iof *inp = iof_filter_string_reader(s, l); iof *out = iof_filter_buffer_writer(n); int flags = lmt_optinteger(L, 2, LZW_DECODER_DEFAULTS); lzw_decode(inp, out, flags); lua_iof_push(L, out); iof_close(out); return 1; } static struct luaL_Reg basexxlib_function_list[] = { { "encode16", basexxlib_encode_16 }, { "decode16", basexxlib_decode_16 }, { "encode64", basexxlib_encode_64 }, { "decode64", basexxlib_decode_64 }, { "encode85", basexxlib_encode_85 }, { "decode85", basexxlib_decode_85 }, { "encodeRL", basexxlib_encode_RL }, { "decodeRL", basexxlib_decode_RL }, { "encodeLZW", basexxlib_encode_LZW }, { "decodeLZW", basexxlib_decode_LZW }, { NULL, NULL }, }; int luaopen_basexx(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, basexxlib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtxdecimallib.c0000644000175000017500000003414714760367410021145 0ustar hillehille/* See license.txt in the root of this project. */ /* decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *); decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *); decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *); # define decNumberIsCanonical(dn) # define decNumberIsFinite(dn) # define decNumberIsInfinite(dn) # define decNumberIsNaN(dn) # define decNumberIsNegative(dn) # define decNumberIsQNaN(dn) # define decNumberIsSNaN(dn) # define decNumberIsSpecial(dn) # define decNumberIsZero(dn) # define decNumberRadix(dn) The main reason why we have this module is that we already load the library in \METAPOST\ so it was a trivial extension to make. Because it is likely that we keep decimal support there, it is also quite likely that we keep this module, even if it's rarely used. The binary number system used in \METAPOST\ is not included. It is even less likely to be used and adds much to the binary. Some more functions might be added here so that we become more compatible with the other math libraries that are present. */ # include # include # include # define DECIMAL_METATABLE "decimal number" typedef decNumber *decimal; static decContext context; # define min_precision 25 # define default_precision 50 # define max_precision 2500 static void xdecimallib_initialize(void) { decContextDefault(&context, DEC_INIT_BASE); context.traps = 0; context.emax = 999999; context.emin = -999999; context.digits = default_precision; } /*tex Todo: Use metatable at the top. But we're not going to crunch numbers anyway so for now there is no need for it. Anyway, the overhade of calculations is much larger than that of locating a metatable. */ static inline decimal xdecimallib_push(lua_State *L) { decimal p = lua_newuserdatauv(L, sizeof(decNumber), 0); luaL_setmetatable(L, DECIMAL_METATABLE); return p; } static void decNumberFromDouble(decNumber *A, double B, decContext *C) /* from mplib, extra arg */ { char buf[1000]; char *c; snprintf(buf, 1000, "%-650.325lf", B); c = buf; while (*c++) { if (*c == ' ') { *c = '\0'; break; } } decNumberFromString(A, buf, C); } static inline int xdecimallib_new(lua_State *L) { decimal p = xdecimallib_push(L); switch (lua_type(L, 1)) { case LUA_TSTRING: decNumberFromString(p, lua_tostring(L, 1), &context); break; case LUA_TNUMBER: if (lua_isinteger(L, 1)) { decNumberFromInt32(p, (int32_t) lua_tointeger(L, 1)); } else { decNumberFromDouble(p, lua_tonumber(L, 1), &context); } break; default: decNumberZero(p); break; } return 1; } /* This is nicer for the user. Beware, we create a userdata object on the stack so we need to replace the original non userdata. */ static decimal xdecimallib_get(lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TUSERDATA: return (decimal) luaL_checkudata(L, i, DECIMAL_METATABLE); case LUA_TSTRING: { decimal p = xdecimallib_push(L); decNumberFromString(p, lua_tostring(L, i), &context); lua_replace(L, i); return p; } case LUA_TNUMBER: { decimal p = xdecimallib_push(L); if (lua_isinteger(L, i)) { decNumberFromInt32(p, (int32_t) lua_tointeger(L, i)); } else { decNumberFromDouble(p, lua_tonumber(L, i), &context); } lua_replace(L, i); return p; } default: { decimal p = xdecimallib_push(L); decNumberZero(p); lua_replace(L, i); return p; } } } static int xdecimallib_tostring(lua_State *L) { decimal a = xdecimallib_get(L, 1); luaL_Buffer buffer; char *b = luaL_buffinitsize(L, &buffer, (size_t) a->digits + 14); decNumberToString(a, b); luaL_addsize(&buffer, strlen(b)); luaL_pushresult(&buffer); return 1; } static int xdecimallib_toengstring(lua_State *L) { decimal a = xdecimallib_get(L, 1); luaL_Buffer buffer; char *b = luaL_buffinitsize(L, &buffer, (size_t) a->digits + 14); decNumberToEngString(a, b); luaL_addsize(&buffer, strlen(b)); luaL_pushresult(&buffer); return 1; } static int xdecimallib_tonumber(lua_State *L) { decimal a = xdecimallib_get(L, 1); char *buffer = lmt_memory_malloc((size_t) a->digits + 14); /* could be shared */ if (buffer) { double result = 0.0; decNumberToString(a, buffer); if (sscanf(buffer, "%lf", &result)) { lua_pushnumber(L, result); } else { lua_pushnil(L); } lmt_memory_free(buffer); return 1; } else { return 0; } } static int xdecimallib_copy(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberCopy(p, a); return 1; } static int xdecimallib_eq(lua_State *L) { decNumber result; decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decNumberCompare(&result, a, b, &context); lua_pushboolean(L, decNumberIsZero(&result)); return 1; } static int xdecimallib_le(lua_State *L) { decNumber result; decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); /* todo: also number or string */ decNumberCompare(&result, a, b, &context); lua_pushboolean(L, decNumberIsNegative(&result) || decNumberIsZero(&result)); return 1; } static int xdecimallib_lt(lua_State *L) { decNumber result; decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); /* todo: also number or string */ decNumberCompare(&result, a, b, &context); lua_pushboolean(L, decNumberIsNegative(&result)); return 1; } static int xdecimallib_add(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberAdd(p, a, b, &context); return 1; } static int xdecimallib_sub(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberSubtract(p, a, b, &context); return 1; } static int xdecimallib_mul(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberMultiply(p, a, b, &context); return 1; } static int xdecimallib_div(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberDivide(p, a, b, &context); return 1; } static int xdecimallib_idiv(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberDivideInteger(p, a, b, &context); return 1; } static int xdecimallib_mod(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberRemainder(p, a, b, &context); return 1; } static int xdecimallib_neg(lua_State* L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberCopyNegate(p, a); return 1; } static int xdecimallib_min(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberMin(p, a, b, &context); return 1; } static int xdecimallib_max(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberMax(p, a, b, &context); return 1; } static int xdecimallib_minus(lua_State* L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberNextMinus(p, a, &context); return 1; } static int xdecimallib_plus(lua_State* L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberNextPlus(p, a, &context); return 1; } static int xdecimallib_trim(lua_State* L) { decimal a = xdecimallib_get(L, 1); decNumberTrim(a); return 0; } static int xdecimallib_pow(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberPower(p, a, b, &context); return 1; } static int xdecimallib_abs(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberCopyAbs(p, a); return 1; } static int xdecimallib_sqrt(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberSquareRoot(p, a, &context); return 1; } static int xdecimallib_ln(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberLn(p, a, &context); return 1; } static int xdecimallib_log10(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberLog10(p, a, &context); return 1; } static int xdecimallib_exp(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal p = xdecimallib_push(L); decNumberExp(p, a, &context); return 1; } static int xdecimallib_rotate(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberRotate(p, a, b, &context); return 1; } static int xdecimallib_shift(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberShift(p, a, b, &context); return 1; } static int xdecimallib_left(lua_State *L) { decimal a = xdecimallib_get(L, 1); lua_Integer shift = luaL_optinteger(L, 2, 1); decimal p = xdecimallib_push(L); decNumber s; decNumberFromInt32(&s, (int32_t) shift); decNumberShift(p, a, &s, &context); return 1; } static int xdecimallib_right(lua_State *L) { decimal a = xdecimallib_get(L, 1); lua_Integer shift = - luaL_optinteger(L, 2, 1); decimal p = xdecimallib_push(L); decNumber s; decNumberFromInt32(&s, (int32_t) shift); decNumberShift(p, a, &s, &context); return 1; } static int xdecimallib_and(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberAnd(p, a, b, &context); return 1; } static int xdecimallib_or(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberOr(p, a, b, &context); return 1; } static int xdecimallib_xor(lua_State *L) { decimal a = xdecimallib_get(L, 1); decimal b = xdecimallib_get(L, 2); decimal p = xdecimallib_push(L); decNumberXor(p, a, b, &context); return 1; } static int xdecimallib_setp(lua_State *L) { int i = (int) luaL_optinteger(L, 1, default_precision); if (i < min_precision) { context.digits = min_precision; } else if (i > max_precision) { context.digits = max_precision; } else { context.digits = i; } lua_pushinteger(L, context.digits); return 1; } static int xdecimallib_getp(lua_State *L) { lua_pushinteger(L, context.digits); return 1; } static const luaL_Reg xdecimallib_function_list[] = { /* management */ { "new", xdecimallib_new }, { "copy", xdecimallib_copy }, { "trim", xdecimallib_trim }, { "tostring", xdecimallib_tostring }, { "toengstring", xdecimallib_toengstring }, { "tonumber", xdecimallib_tonumber }, { "setprecision", xdecimallib_setp }, { "getprecision", xdecimallib_getp }, /* operators */ { "__add", xdecimallib_add }, { "__idiv", xdecimallib_idiv }, { "__div", xdecimallib_div }, { "__mod", xdecimallib_mod }, { "__eq", xdecimallib_eq }, { "__le", xdecimallib_le }, { "__lt", xdecimallib_lt }, { "__mul", xdecimallib_mul }, { "__sub", xdecimallib_sub }, { "__unm", xdecimallib_neg }, { "__pow", xdecimallib_pow }, { "__bor", xdecimallib_or }, { "__bxor", xdecimallib_xor }, { "__band", xdecimallib_and }, { "__shl", xdecimallib_left }, { "__shr", xdecimallib_right }, /* functions */ { "conj", xdecimallib_neg }, { "abs", xdecimallib_abs }, { "pow", xdecimallib_pow }, { "sqrt", xdecimallib_sqrt }, { "ln", xdecimallib_ln }, { "log", xdecimallib_log10 }, { "exp", xdecimallib_exp }, { "bor", xdecimallib_or }, { "bxor", xdecimallib_xor }, { "band", xdecimallib_and }, { "shift", xdecimallib_shift }, { "rotate", xdecimallib_rotate }, { "minus", xdecimallib_minus }, { "plus", xdecimallib_plus }, { "min", xdecimallib_min }, { "max", xdecimallib_max }, /* */ { NULL, NULL }, }; int luaopen_xdecimal(lua_State *L) { xdecimallib_initialize(); luaL_newmetatable(L, DECIMAL_METATABLE); luaL_setfuncs(L, xdecimallib_function_list, 0); lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); lua_settable(L, -3); lua_pushliteral(L, "__tostring"); lua_pushliteral(L, "tostring"); lua_gettable(L, -3); lua_settable(L, -3); lua_pushliteral(L, "__name"); lua_pushliteral(L, "decimal"); lua_settable(L, -3); return 1; } luametatex-2.11.07/source/luarest/lmtiolibext.c0000644000175000017500000013142614760367410020505 0ustar hillehille/* See license.txt in the root of this project. */ /*tex Lua doesn't have cardinals so basically we could stick to integers and accept that we have a limited range. */ /*tex Maybe also make a string reader with a user data string, after all we can now store a position in the userdata directly. */ # include "luametatex.h" # ifdef _WIN32 # define lua_popen(L,c,m) ((void)L, _popen(c,m)) # define lua_pclose(L,file) ((void)L, _pclose(file)) # else # define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) # define lua_pclose(L,file) ((void)L, pclose(file)) # endif /* Mojca: we need to sort this out! */ # ifdef LUA_USE_POSIX # define l_fseek(f,o,w) fseeko(f,o,w) # define l_ftell(f) ftello(f) # define l_seeknum off_t # elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) && defined(_MSC_VER) && (_MSC_VER >= 1400) # define l_fseek(f,o,w) _fseeki64(f,o,w) # define l_ftell(f) _ftelli64(f) # define l_seeknum __int64 # elif defined(__MINGW32__) # define l_fseek(f,o,w) fseeko64(f,o,w) # define l_ftell(f) ftello64(f) # define l_seeknum int64_t # else # define l_fseek(f,o,w) fseek(f,o,w) # define l_ftell(f) ftell(f) # define l_seeknum long # endif # define uchar(c) ((unsigned char)(c)) /*tex A few helpers to avoid reading numbers as strings. For now we put them in their own namespace. We also have a few helpers that can make \IO\ functions \TEX\ friendly. */ static int fiolib_readcardinal1(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else { lua_pushinteger(L, a); } return 1; } else { return 0; } } static int siolib_readcardinal1(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if (p >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p]); lua_pushinteger(L, a); } return 1; } static int fiolib_readcardinal2(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); if (b == EOF) { lua_pushnil(L); } else { /* (a<<8) | b */ lua_pushinteger(L, 0x100 * a + b); } return 1; } else { return 0; } } static int fiolib_readcardinal2_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else { /* (a<<8) | b */ lua_pushinteger(L, 0x100 * a + b); } return 1; } else { return 0; } } static int siolib_readcardinal2(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 1) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p]); lua_pushinteger(L, 0x100 * a + b); } return 1; } static int siolib_readcardinal2_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 1) >= l) { lua_pushnil(L); } else { lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); lua_pushinteger(L, 0x100 * a + b); } return 1; } static int fiolib_readcardinal3(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); if (c == EOF) { lua_pushnil(L); } else { /* (a<<16) | (b<<8) | c */ lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } else { return 0; } } static int fiolib_readcardinal3_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer c = getc(f); lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else { /* (a<<16) | (b<<8) | c */ lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } else { return 0; } } static int siolib_readcardinal3(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 2) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p]); lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } static int siolib_readcardinal3_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 2) >= l) { lua_pushnil(L); } else { lua_Integer c = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } static int fiolib_readcardinal4(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); lua_Integer d = getc(f); if (d == EOF) { lua_pushnil(L); } else { /* (a<<24) | (b<<16) | (c<<8) | d */ lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } else { return 0; } } static int fiolib_readcardinal4_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer d = getc(f); lua_Integer c = getc(f); lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else { /* (a<<24) | (b<<16) | (c<<8) | d */ lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } else { return 0; } } static int siolib_readcardinal4(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer d = uchar(s[p]); lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } static int siolib_readcardinal4_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { lua_Integer d = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } static int fiolib_readcardinaltable(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); lua_Integer m = lua_tointeger(L, 3); lua_createtable(L, (int) n, 0); switch (m) { case 1: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); if (a == EOF) { break; } else { lua_pushinteger(L, a); lua_rawseti(L, -2, i); } } break; case 2: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); if (b == EOF) { break; } else { /* (a<<8) | b */ lua_pushinteger(L, 0x100 * a + b); lua_rawseti(L, -2, i); } } break; case 3: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); if (c == EOF) { break; } else { /* (a<<16) | (b<<8) | c */ lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); lua_rawseti(L, -2, i); } } break; case 4: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); lua_Integer d = getc(f); if (d == EOF) { break; } else { /* (a<<24) | (b<<16) | (c<<8) | d */ lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); lua_rawseti(L, -2, i); } } break; default: break; } return 1; } else { return 0; } } static int siolib_readcardinaltable(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer n = lua_tointeger(L, 3); lua_Integer m = lua_tointeger(L, 4); lua_Integer l = (lua_Integer) ls; lua_createtable(L, (int) n, 0); switch (m) { case 1: for (lua_Integer i = 1; i <= n; i++) { if (p >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_pushinteger(L, a); lua_rawseti(L, -2, i); } } break; case 2: for (lua_Integer i = 1; i <= n; i++) { if ((p + 1) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_pushinteger(L, 0x100 * a + b); lua_rawseti(L, -2, i); } } break; case 3: for (lua_Integer i = 1; i <= n; i++) { if ((p + 2) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); lua_rawseti(L, -2, i); } } break; case 4: for (lua_Integer i = 1; i <= n; i++) { if ((p + 3) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer d = uchar(s[p++]); lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); lua_rawseti(L, -2, i); } } break; default: break; } return 1; } static int fiolib_readinteger1(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, a - 0x100); } else { lua_pushinteger(L, a); } return 1; } else { return 0; } } static int siolib_readinteger1(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if (p >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, a - 0x100); } else { lua_pushinteger(L, a); } } return 1; } static int fiolib_readinteger2(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); if (b == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } return 1; } else { return 0; } } static int fiolib_readinteger2_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } return 1; } else { return 0; } } static int siolib_readinteger2(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 1) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } } return 1; } static int siolib_readinteger2_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 1) >= l) { lua_pushnil(L); } else { lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } } return 1; } static int fiolib_readinteger3(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); if (c == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } else { return 0; } } static int fiolib_readinteger3_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer c = getc(f); lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } return 1; } else { return 0; } } static int siolib_readinteger3(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 2) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } } return 1; } static int siolib_readinteger3_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 2) >= l) { lua_pushnil(L); } else { lua_Integer c = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } } return 1; } static int fiolib_readinteger4(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); lua_Integer d = getc(f); if (d == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } else { return 0; } } static int fiolib_readinteger4_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer d = getc(f); lua_Integer c = getc(f); lua_Integer b = getc(f); lua_Integer a = getc(f); if (a == EOF) { lua_pushnil(L); } else if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } return 1; } else { return 0; } } static int siolib_readinteger4(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer d = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } } return 1; } static int siolib_readinteger4_le(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { lua_Integer d = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer a = uchar(s[p]); if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } } return 1; } static int fiolib_readintegertable(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); lua_Integer m = lua_tointeger(L, 3); lua_createtable(L, (int) n, 0); switch (m) { case 1: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); if (a == EOF) { break; } else if (a >= 0x80) { lua_pushinteger(L, a - 0x100); } else { lua_pushinteger(L, a); } lua_rawseti(L, -2, i); } break; case 2: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); if (b == EOF) { break; } else if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } lua_rawseti(L, -2, i); } break; case 3: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); if (c == EOF) { break; } else if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } lua_rawseti(L, -2, i); } break; case 4: for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); lua_Integer b = getc(f); lua_Integer c = getc(f); lua_Integer d = getc(f); if (d == EOF) { break; } else if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } lua_rawseti(L, -2, i); } break; default: break; } return 1; } else { return 0; } } static int siolib_readintegertable(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer n = lua_tointeger(L, 3); lua_Integer m = lua_tointeger(L, 4); lua_Integer l = (lua_Integer) ls; lua_createtable(L, (int) n, 0); switch (m) { case 1: for (lua_Integer i = 1; i <= n; i++) { if (p >= l) { break; } else { lua_Integer a = uchar(s[p++]); if (a >= 0x80) { lua_pushinteger(L, a - 0x100); } else { lua_pushinteger(L, a); } lua_rawseti(L, -2, i); } } break; case 2: for (lua_Integer i = 1; i <= n; i++) { if ((p + 1) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); if (a >= 0x80) { lua_pushinteger(L, 0x100 * a + b - 0x10000); } else { lua_pushinteger(L, 0x100 * a + b); } lua_rawseti(L, -2, i); } } break; case 3: for (lua_Integer i = 1; i <= n; i++) { if ((p + 2) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); if (a >= 0x80) { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); } else { lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); } lua_rawseti(L, -2, i); } } break; case 4: for (lua_Integer i = 1; i <= n; i++) { if ((p + 3) >= l) { break; } else { lua_Integer a = uchar(s[p++]); lua_Integer b = uchar(s[p++]); lua_Integer c = uchar(s[p++]); lua_Integer d = uchar(s[p++]); if (a >= 0x80) { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); } else { lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); } lua_rawseti(L, -2, i); } } break; default: break; } return 1; } /* from ff */ static int fiolib_readfixed2(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { int a = getc(f); int b = getc(f); if (b == EOF) { lua_pushnil(L); } else { int n = 0x100 * a + b; /* really an int because we shift */ lua_pushnumber(L, (double) ((n>>8) + ((n&0xff)/256.0))); } return 1; } else { return 0; } } static int siolib_readfixed2(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { int a = uchar(s[p++]); int b = uchar(s[p]); int n = 0x100 * a + b; /* really an int because we shift */ lua_pushnumber(L, (double) ((n>>8) + ((n&0xff)/256.0))); } return 1; } static int fiolib_readfixed4(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { int a = getc(f); int b = getc(f); int c = getc(f); int d = getc(f); if (d == EOF) { lua_pushnil(L); } else { int n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d; /* really an int because we shift */ lua_pushnumber(L, (double) ((n>>16) + ((n&0xffff)/65536.0))); } return 1; } else { return 0; } } static int siolib_readfixed4(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 3) >= l) { lua_pushnil(L); } else { int a = uchar(s[p++]); int b = uchar(s[p++]); int c = uchar(s[p++]); int d = uchar(s[p]); int n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d; /* really an int because we shift */ lua_pushnumber(L, (double) ((n>>16) + ((n&0xffff)/65536.0))); } return 1; } static int fiolib_read2dot14(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { int a = getc(f); int b = getc(f); if (b == EOF) { lua_pushnil(L); } else { int n = 0x100 * a + b; /* really an int because we shift */ /* from ff */ lua_pushnumber(L, (double) (((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0))); } return 1; } else { return 0; } } static int siolib_read2dot14(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if ((p + 1) >= l) { lua_pushnil(L); } else { int a = uchar(s[p++]); int b = uchar(s[p]); int n = 0x100 * a + b; /* really an int because we shift */ lua_pushnumber(L, (double) (((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0))); } return 1; } static int fiolib_getposition(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { long p = ftell(f); if (p < 0) { lua_pushnil(L); } else { lua_pushinteger(L, p); } return 1; } else { return 0; } } static int fiolib_setposition(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { long p = lmt_tolong(L, 2); p = fseek(f, p, SEEK_SET); if (p < 0) { lua_pushnil(L); } else { lua_pushinteger(L, p); } return 1; } else { return 0; } } static int fiolib_skipposition(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { long p = lmt_tolong(L, 2); p = fseek(f, ftell(f) + p, SEEK_SET); if (p < 0) { lua_pushnil(L); } else { lua_pushinteger(L, p); } return 1; } else { return 0; } } static int fiolib_readbytetable(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); lua_createtable(L, (int) n, 0); for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); if (a == EOF) { break; } else { /* lua_pushinteger(L, i); lua_pushinteger(L, a); lua_rawset(L, -3); */ lua_pushinteger(L, a); lua_rawseti(L, -2, i); } } return 1; } else { return 0; } } static int siolib_readbytetable(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer n = lua_tointeger(L, 3); lua_Integer l = (lua_Integer) ls; if (p >= l) { lua_pushnil(L); } else { if (p + n >= l) { n = l - p ; } lua_createtable(L, (int) n, 0); for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = uchar(s[p++]); lua_pushinteger(L, a); lua_rawseti(L, -2, i); } } return 1; } static int fiolib_readbytes(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = getc(f); if (a == EOF) { return (int) (i - 1); } else { lua_pushinteger(L, a); } } return (int) n; } else { return 0; } } static int siolib_readbytes(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer n = lua_tointeger(L, 3); lua_Integer l = (lua_Integer) ls; if (p >= l) { return 0; } else { if (p + n >= l) { n = l - p ; } lua_createtable(L, (int) n, 0); for (lua_Integer i = 1; i <= n; i++) { lua_Integer a = uchar(s[p++]); lua_pushinteger(L, a); } return (int) n; } } static int fiolib_readcline(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { luaL_Buffer buf; int c = 0; int n = 0; luaL_buffinit(L, &buf); do { char *b = luaL_prepbuffer(&buf); int i = 0; while (i < LUAL_BUFFERSIZE) { c = fgetc(f); if (c == '\n') { goto GOOD; } else if (c == '\r') { c = fgetc(f); if (c != EOF && c != '\n') { ungetc((int) c, f); } goto GOOD; } else { n++; b[i++] = (char) c; } } } while (c != EOF); goto BAD; GOOD: if (n > 0) { luaL_addsize(&buf, n); luaL_pushresult(&buf); } else { lua_pushnil(L); } lua_pushinteger(L, ftell(f)); return 2; } BAD: lua_pushnil(L); return 1; } static int siolib_readcline(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if (p < l) { lua_Integer i = p; int n = 0; while (p < l) { int c = uchar(s[p++]); if (c == '\n') { goto GOOD; } else if (c == '\r') { if (p < l) { c = uchar(s[p++]); if (c != EOF && c != '\n') { --p; } } goto GOOD; } else { n++; } } goto BAD; GOOD: if (n > 0) { lua_pushlstring(L, &s[i], n); lua_pushinteger(L, p); return 2; } } BAD: lua_pushnil(L); lua_pushinteger(L, p + 1); return 2; } static int fiolib_readcstring(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { luaL_Buffer buf; int c = 0; int n = 0; luaL_buffinit(L, &buf); do { char *b = luaL_prepbuffer(&buf); int i = 0; while (i < LUAL_BUFFERSIZE) { c = fgetc(f); if (c == '\0') { goto GOOD; } else { n++; b[i++] = (char) c; } } } while (c != EOF); goto BAD; GOOD: if (n > 0) { luaL_addsize(&buf, n); luaL_pushresult(&buf); } else { lua_pushliteral(L,""); } lua_pushinteger(L, ftell(f)); return 2; } BAD: lua_pushnil(L); return 1; } static int siolib_readcstring(lua_State *L) { size_t ls = 0; const char *s = luaL_checklstring(L, 1, &ls); lua_Integer p = luaL_checkinteger(L, 2) - 1; lua_Integer l = (lua_Integer) ls; if (p < l) { lua_Integer i = p; int n = 0; while (p < l) { int c = uchar(s[p++]); if (c == '\0') { goto GOOD; } else { n++; } }; goto BAD; GOOD: if (n > 0) { lua_pushlstring(L, &s[i], n); } else { lua_pushliteral(L,""); } lua_pushinteger(L, p + 1); return 2; } BAD: lua_pushnil(L); lua_pushinteger(L, p + 1); return 2; } /* will be completed */ static int fiolib_writecardinal1(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc(n & 0xFF, f); } return 0; } static int siolib_tocardinal1(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[1] = { n & 0xFF }; lua_pushlstring(L, buffer, 1); return 1; } static int fiolib_writecardinal2(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc((n >> 8) & 0xFF, f); putc( n & 0xFF, f); } return 0; } static int siolib_tocardinal2(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[2] = { (n >> 8) & 0xFF, n & 0xFF }; lua_pushlstring(L, buffer, 2); return 1; } static int fiolib_writecardinal2_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc( n & 0xFF, f); putc((n >> 8) & 0xFF, f); } return 0; } static int siolib_tocardinal2_le(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[2] = { n & 0xFF, (n >> 8) & 0xFF }; lua_pushlstring(L, buffer, 2); return 1; } static int fiolib_writecardinal3(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc((n >> 16) & 0xFF, f); putc((n >> 8) & 0xFF, f); putc( n & 0xFF, f); } return 0; } static int siolib_tocardinal3(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[3] = { (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF }; lua_pushlstring(L, buffer, 3); return 1; } static int fiolib_writecardinal3_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc( n & 0xFF, f); putc((n >> 8) & 0xFF, f); putc((n >> 16) & 0xFF, f); } return 0; } static int siolib_tocardinal3_le(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[3] = { n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF }; lua_pushlstring(L, buffer, 3); return 1; } static int fiolib_writecardinal4(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc((n >> 24) & 0xFF, f); putc((n >> 16) & 0xFF, f); putc((n >> 8) & 0xFF, f); putc( n & 0xFF, f); } return 0; } static int siolib_tocardinal4(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[4] = { (n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF }; lua_pushlstring(L, buffer, 4); return 1; } static int fiolib_writecardinal4_le(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { lua_Integer n = lua_tointeger(L, 2); putc( n & 0xFF, f); putc((n >> 8) & 0xFF, f); putc((n >> 16) & 0xFF, f); putc((n >> 24) & 0xFF, f); } return 0; } static int siolib_tocardinal4_le(lua_State *L) { lua_Integer n = lua_tointeger(L, 1); char buffer[4] = { n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, (n >> 24) & 0xFF }; lua_pushlstring(L, buffer, 4); return 1; } /* */ static const luaL_Reg fiolib_function_list[] = { /* helpers */ { "readcardinal1", fiolib_readcardinal1 }, { "readcardinal2", fiolib_readcardinal2 }, { "readcardinal3", fiolib_readcardinal3 }, { "readcardinal4", fiolib_readcardinal4 }, { "readcardinal1le", fiolib_readcardinal1 }, { "readcardinal2le", fiolib_readcardinal2_le }, { "readcardinal3le", fiolib_readcardinal3_le }, { "readcardinal4le", fiolib_readcardinal4_le }, { "readcardinaltable", fiolib_readcardinaltable }, { "readinteger1", fiolib_readinteger1 }, { "readinteger2", fiolib_readinteger2 }, { "readinteger3", fiolib_readinteger3 }, { "readinteger4", fiolib_readinteger4 }, { "readinteger1le", fiolib_readinteger1 }, { "readinteger2le", fiolib_readinteger2_le }, { "readinteger3le", fiolib_readinteger3_le }, { "readinteger4le", fiolib_readinteger4_le }, { "readintegertable", fiolib_readintegertable }, { "readfixed2", fiolib_readfixed2 }, { "readfixed4", fiolib_readfixed4 }, { "read2dot14", fiolib_read2dot14 }, { "setposition", fiolib_setposition }, { "getposition", fiolib_getposition }, { "skipposition", fiolib_skipposition }, { "readbytes", fiolib_readbytes }, { "readbytetable", fiolib_readbytetable }, { "readcline", fiolib_readcline }, { "readcstring", fiolib_readcstring }, { "writecardinal1", fiolib_writecardinal1 }, { "writecardinal2", fiolib_writecardinal2 }, { "writecardinal3", fiolib_writecardinal3 }, { "writecardinal4", fiolib_writecardinal4 }, { "writecardinal1le", fiolib_writecardinal1 }, { "writecardinal2le", fiolib_writecardinal2_le }, { "writecardinal3le", fiolib_writecardinal3_le }, { "writecardinal4le", fiolib_writecardinal4_le }, { NULL, NULL } }; static const luaL_Reg siolib_function_list[] = { { "readcardinal1", siolib_readcardinal1 }, { "readcardinal2", siolib_readcardinal2 }, { "readcardinal3", siolib_readcardinal3 }, { "readcardinal4", siolib_readcardinal4 }, { "readcardinal1le", siolib_readcardinal1 }, { "readcardinal2le", siolib_readcardinal2_le }, { "readcardinal3le", siolib_readcardinal3_le }, { "readcardinal4le", siolib_readcardinal4_le }, { "readcardinaltable", siolib_readcardinaltable }, { "readinteger1", siolib_readinteger1 }, { "readinteger2", siolib_readinteger2 }, { "readinteger3", siolib_readinteger3 }, { "readinteger4", siolib_readinteger4 }, { "readinteger1le", siolib_readinteger1 }, { "readinteger2le", siolib_readinteger2_le }, { "readinteger3le", siolib_readinteger3_le }, { "readinteger4le", siolib_readinteger4_le }, { "readintegertable", siolib_readintegertable }, { "readfixed2", siolib_readfixed2 }, { "readfixed4", siolib_readfixed4 }, { "read2dot14", siolib_read2dot14 }, { "readbytes", siolib_readbytes }, { "readbytetable", siolib_readbytetable }, { "readcline", siolib_readcline }, { "readcstring", siolib_readcstring }, { "tocardinal1", siolib_tocardinal1 }, { "tocardinal2", siolib_tocardinal2 }, { "tocardinal3", siolib_tocardinal3 }, { "tocardinal4", siolib_tocardinal4 }, { "tocardinal1le", siolib_tocardinal1 }, { "tocardinal2le", siolib_tocardinal2_le }, { "tocardinal3le", siolib_tocardinal3_le }, { "tocardinal4le", siolib_tocardinal4_le }, { NULL, NULL } }; /*tex The sio helpers might be handy at some point. Speed-wise there is no gain over file access because with ssd and caching we basically operate in memory too. We keep them as complement to the file ones. I did consider using an userdata object for the position etc but some simple tests demonstrated that there is no real gain and the current ones permits to wrap up whatever interface one likes. */ int luaopen_fio(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, fiolib_function_list, 0); return 1; } int luaopen_sio(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, siolib_function_list, 0); return 1; } /* We patch a function in the standard |io| library. */ /*tex The following code overloads the |io.open| function to deal with so called wide characters on windows. */ /* a variant on read_line but with nothing catched */ static int io_gobble(lua_State *L) { FILE *f = lmt_valid_file(L); if (f) { int c; int n = 0; while ((c = getc(f)) != EOF && c != '\n') { n = 1; } lua_pushboolean(L, ((c == '\n') || n)); } else { lua_pushnil(L); } return 1; } # if _WIN32 # define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int l_checkmode(const char *mode) { return ( mode && *mode != '\0' && strchr("rwa", *(mode++)) && (*mode != '+' || ((void)(++mode), 1)) && (strspn(mode, "b") == strlen(mode)) ); } typedef luaL_Stream LStream; static LStream *newprefile(lua_State *L) { LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0); p->closef = NULL; luaL_setmetatable(L, LUA_FILEHANDLE); return p; } static int io_fclose(lua_State *L) { LStream *p = tolstream(L); int res = fclose(p->f); return luaL_fileresult(L, (res == 0), NULL); } static LStream *newfile(lua_State *L) { /*tex Watch out: lua 5.4 has different closers. */ LStream *p = newprefile(L); p->f = NULL; p->closef = &io_fclose; return p; } static int io_open(lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); LStream *p = newfile(L); const char *md = mode; /* to traverse/check mode */ luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); p->f = aux_utf8_fopen(filename, mode); return (p->f) ? 1 : luaL_fileresult(L, 0, filename); } static int io_pclose(lua_State *L) { LStream *p = tolstream(L); return luaL_execresult(L, _pclose(p->f)); } static int io_popen(lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); LStream *p = newprefile(L); p->f = aux_utf8_popen(filename, mode); p->closef = &io_pclose; return (p->f) ? 1 : luaL_fileresult(L, 0, filename); } int luaextend_io(lua_State *L) { lua_getglobal(L, "io"); lua_pushcfunction(L, io_open); lua_setfield(L, -2, "open"); lua_pushcfunction(L, io_popen); lua_setfield(L, -2, "popen"); lua_pushcfunction(L, io_gobble); lua_setfield(L, -2, "gobble"); lua_pop(L, 1); /*tex Larger doesn't work and limits to 512 but then no amount is okay as there's always more to demand. */ _setmaxstdio(2048); return 1; } # else // int luaextend_io(lua_State *L) // { // (void) L; // return 1; // } int luaextend_io(lua_State *L) { lua_getglobal(L, "io"); lua_pushcfunction(L, io_gobble); lua_setfield(L, -2, "gobble"); lua_pop(L, 1); return 1; } # endif luametatex-2.11.07/source/luarest/lmtsha2lib.c0000644000175000017500000000506414760367410020210 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" # include # define SHA256_RESULT_LENGTH (SHA256_STRING_LENGTH-1) # define SHA384_RESULT_LENGTH (SHA384_STRING_LENGTH-1) # define SHA512_RESULT_LENGTH (SHA512_STRING_LENGTH-1) # define sha2_body(SHA_DIGEST_LENGTH, SHA_CALCULATE, CONVERSION, SHA_RESULT_LENGTH) do { \ if (lua_type(L, 1) == LUA_TSTRING) { \ uint8_t result[SHA_DIGEST_LENGTH]; \ size_t size = 0; \ const char *data = lua_tolstring(L, 1, &size); \ SHA_CALCULATE(data, size, result, CONVERSION); \ lua_pushlstring(L, (const char *) result, SHA_RESULT_LENGTH); \ return 1; \ } \ return 0; \ } while (0) static int sha2lib_256_sum(lua_State *L) { sha2_body(SHA256_DIGEST_LENGTH, sha256_digest, SHA_BYTES, SHA256_DIGEST_LENGTH); } static int sha2lib_384_sum(lua_State *L) { sha2_body(SHA384_DIGEST_LENGTH, sha384_digest, SHA_BYTES, SHA384_DIGEST_LENGTH); } static int sha2lib_512_sum(lua_State *L) { sha2_body(SHA512_DIGEST_LENGTH, sha512_digest, SHA_BYTES, SHA512_DIGEST_LENGTH); } static int sha2lib_256_hex(lua_State *L) { sha2_body(SHA256_STRING_LENGTH, sha256_digest, SHA_LCHEX, SHA256_RESULT_LENGTH); } static int sha2lib_384_hex(lua_State *L) { sha2_body(SHA384_STRING_LENGTH, sha384_digest, SHA_LCHEX, SHA384_RESULT_LENGTH); } static int sha2lib_512_hex(lua_State *L) { sha2_body(SHA512_STRING_LENGTH, sha512_digest, SHA_LCHEX, SHA512_RESULT_LENGTH); } static int sha2lib_256_HEX(lua_State *L) { sha2_body(SHA256_STRING_LENGTH, sha256_digest, SHA_UCHEX, SHA256_RESULT_LENGTH); } static int sha2lib_384_HEX(lua_State *L) { sha2_body(SHA384_STRING_LENGTH, sha384_digest, SHA_UCHEX, SHA384_RESULT_LENGTH); } static int sha2lib_512_HEX(lua_State *L) { sha2_body(SHA512_STRING_LENGTH, sha512_digest, SHA_UCHEX, SHA512_RESULT_LENGTH); } static struct luaL_Reg sha2lib_function_list[] = { /*tex We started out with this: */ { "digest256", sha2lib_256_sum }, { "digest384", sha2lib_384_sum }, { "digest512", sha2lib_512_sum }, /*tex The next is consistent with |md5lib|: */ { "sum256", sha2lib_256_sum }, { "sum384", sha2lib_384_sum }, { "sum512", sha2lib_512_sum }, { "hex256", sha2lib_256_hex }, { "hex384", sha2lib_384_hex }, { "hex512", sha2lib_512_hex }, { "HEX256", sha2lib_256_HEX }, { "HEX384", sha2lib_384_HEX }, { "HEX512", sha2lib_512_HEX }, { NULL, NULL }, }; int luaopen_sha2(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, sha2lib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtstrlibext.c0000644000175000017500000011237014760367410020703 0ustar hillehille/* See license.txt in the root of this project. */ /* todo: byteconcat and utf concat (no separator) */ # include "luametatex.h" /*tex Helpers */ static inline int strlib_aux_tounicode(const char *s, size_t l, size_t *p) { unsigned char i = s[*p]; *p += 1; if (i < 0x80) { return i; } else if (i >= 0xF0) { if ((*p + 2) < l) { unsigned char j = s[*p]; unsigned char k = s[*p + 1]; unsigned char l = s[*p + 2]; if (j >= 0x80 && k >= 0x80 && l >= 0x80) { *p += 3; return (((((i - 0xF0) * 0x40) + (j - 0x80)) * 0x40) + (k - 0x80)) * 0x40 + (l - 0x80); } } } else if (i >= 0xE0) { if ((*p + 1) < l) { unsigned char j = s[*p]; unsigned char k = s[*p + 1]; if (j >= 0x80 && k >= 0x80) { *p += 2; return (((i - 0xE0) * 0x40) + (j - 0x80)) * 0x40 + (k - 0x80); } } } else if (i >= 0xC0) { if (*p < l) { unsigned char j = s[*p]; if (j >= 0x80) { *p += 1; return ((i - 0xC0) * 0x40) + (j - 0x80); } } } return 0xFFFD; } static inline int strlib_aux_tounichar(const char *s, size_t l, size_t p) { unsigned char i = s[p++]; if (i < 0x80) { return 1; } else if (i >= 0xF0) { if ((p + 2) < l) { unsigned char j = s[p]; unsigned char k = s[p + 1]; unsigned char l = s[p + 2]; if (j >= 0x80 && k >= 0x80 && l >= 0x80) { return 4; } } } else if (i >= 0xE0) { if ((p + 1) < l) { unsigned char j = s[p]; unsigned char k = s[p + 1]; if (j >= 0x80 && k >= 0x80) { return 3; } } } else if (i >= 0xC0) { if (p < l) { unsigned char j = s[p]; if (j >= 0x80) { return 2; } } } return 0; } static inline size_t strlib_aux_toline(const char *s, size_t l, size_t p, size_t *b) { size_t i = p; while (i < l) { if (s[i] == 13) { if ((i + 1) < l) { if (s[i + 1] == 10) { *b = 2; /* cr lf */ } else { *b = 1; /* cr */ } } return i - p; } else if (s[i] == 10) { *b = 1; /* lf */ return i - p; } else { /* other */ i += 1; } } return i - p ; } /*tex End of helpers. */ static int strlib_aux_bytepairs(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind < ls) { unsigned char i; /*tex iterator */ if (ind + 1 < ls) { lua_pushinteger(L, ind + 2); } else { lua_pushinteger(L, ind + 1); } lua_replace(L, lua_upvalueindex(2)); i = (unsigned char)*(s + ind); /*tex byte one */ lua_pushinteger(L, i); if (ind + 1 < ls) { /*tex byte two */ i = (unsigned char)*(s + ind + 1); lua_pushinteger(L, i); } else { /*tex odd string length */ lua_pushnil(L); } return 2; } else { return 0; } } static int strlib_bytepairs(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_bytepairs, 2); return 1; } static int strlib_aux_bytes(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind < ls) { /*tex iterator */ lua_pushinteger(L, ind + 1); lua_replace(L, lua_upvalueindex(2)); /*tex byte */ lua_pushinteger(L, (unsigned char)*(s + ind)); return 1; } else { return 0; } } static int strlib_bytes(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_bytes, 2); return 1; } static int strlib_aux_utf_failed(lua_State *L, int new_ind) { lua_pushinteger(L, new_ind); lua_replace(L, lua_upvalueindex(2)); lua_pushliteral(L, utf_fffd_string); return 1; } /* kind of complex ... these masks */ static int strlib_aux_utfcharacters(lua_State *L) { static const unsigned char mask[4] = { 0x80, 0xE0, 0xF0, 0xF8 }; static const unsigned char mequ[4] = { 0x00, 0xC0, 0xE0, 0xF0 }; size_t ls = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); size_t l = ls; if (ind >= l) { return 0; } else { unsigned char c = (unsigned char) s[ind]; for (size_t j = 0; j < 4; j++) { if ((c & mask[j]) == mequ[j]) { if (ind + 1 + j > l) { /*tex The result will not fit. */ return strlib_aux_utf_failed(L, (int) l); } for (size_t k = 1; k <= j; k++) { c = (unsigned char) s[ind + k]; if ((c & 0xC0) != 0x80) { /*tex We have a bad follow byte. */ return strlib_aux_utf_failed(L, (int) (ind + k)); } } /*tex The iterator. */ lua_pushinteger(L, ind + j + 1); lua_replace(L, lua_upvalueindex(2)); lua_pushlstring(L, ind + s, j + 1); return 1; } } return strlib_aux_utf_failed(L, (int) (ind + 1)); /* we found a follow byte! */ } } static int strlib_utfcharacters(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_utfcharacters, 2); return 1; } static int strlib_aux_utfvalues(lua_State *L) { size_t l = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &l); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind < l) { int v = strlib_aux_tounicode(s, l, &ind); lua_pushinteger(L, ind); lua_replace(L, lua_upvalueindex(2)); lua_pushinteger(L, v); return 1; } else { return 0; } } static int strlib_utfvalues(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_utfvalues, 2); return 1; } static int strlib_aux_characterpairs(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind < ls) { char b[1]; lua_pushinteger(L, ind + 2); /*tex So we can overshoot ls here. */ lua_replace(L, lua_upvalueindex(2)); b[0] = s[ind]; lua_pushlstring(L, b, 1); if ((ind + 1) < ls) { b[0] = s[ind + 1]; lua_pushlstring(L, b, 1); } else { lua_pushliteral(L, ""); } return 2; } else { return 0; /* string ended */ } } static int strlib_characterpairs(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_characterpairs, 2); return 1; } static int strlib_aux_characters(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); size_t ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind < ls) { char b[1]; lua_pushinteger(L, ind + 1); /* iterator */ lua_replace(L, lua_upvalueindex(2)); b[0] = *(s + ind); lua_pushlstring(L, b, 1); return 1; } else { return 0; /* string ended */ } } static int strlib_characters(lua_State *L) { luaL_checkstring(L, 1); lua_settop(L, 1); lua_pushinteger(L, 0); lua_pushcclosure(L, strlib_aux_characters, 2); return 1; } static int strlib_bytetable(lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); lua_createtable(L, (int) l, 0); for (size_t i = 0; i < l; i++) { lua_pushinteger(L, (unsigned char)*(s + i)); lua_rawseti(L, -2, i + 1); } return 1; } static int strlib_utfvaluetable(lua_State *L) { size_t n = 1; size_t l = 0; size_t p = 0; const char *s = luaL_checklstring(L, 1, &l); lua_createtable(L, (int) l, 0); while (p < l) { lua_pushinteger(L, strlib_aux_tounicode(s, l, &p)); lua_rawseti(L, -2, n++); } return 1; } static int strlib_utfcharactertable(lua_State *L) { size_t n = 1; size_t l = 0; size_t p = 0; const char *s = luaL_checklstring(L, 1, &l); lua_createtable(L, (int) l, 0); while (p < l) { int b = strlib_aux_tounichar(s, l, p); if (b) { lua_pushlstring(L, s + p, b); p += b; } else { lua_pushliteral(L, utf_fffd_string); p += 1; } lua_rawseti(L, -2, n++); } return 1; } static int strlib_linetable(lua_State *L) { size_t n = 1; size_t l = 0; size_t p = 0; const char *s = luaL_checklstring(L, 1, &l); lua_createtable(L, (int) l, 0); while (p < l) { size_t b = 0; size_t m = strlib_aux_toline(s, l, p, &b); if (m) { lua_pushlstring(L, s + p, m); } else { lua_pushliteral(L, ""); } p += m + b; lua_rawseti(L, -2, n++); } return 1; } /*tex We provide a few helpers that we derived from the lua utf8 module and slunicode. That way we're sort of covering a decent mix. */ # define MAXUNICODE 0x10FFFF /*tex This is a combination of slunicode and utf8 converters but without mode and a bit faster on the average than the utf8 one. The one character branch is a bit more efficient, as is preallocating the buffer size. */ static inline void strlib_aux_add_utfchar(luaL_Buffer *b, unsigned u) { if (u <= MAXUNICODE) { if (0x80 > u) { luaL_addchar(b, (unsigned char) u); } else { if (0x800 > u) luaL_addchar(b, (unsigned char) (0xC0 | (u >> 6))); else { if (0x10000 > u) luaL_addchar(b, (unsigned char) (0xE0 | (u >> 12))); else { luaL_addchar(b, (unsigned char) (0xF0 | (u >> 18))); luaL_addchar(b, (unsigned char) (0x80 | (0x3F & (u >> 12)))); } luaL_addchar(b, 0x80 | (0x3F & (u >> 6))); } luaL_addchar(b, 0x80 | (0x3F & u)); } } } static inline void strlib_aux_add_utfnumber(lua_State *L, luaL_Buffer *b, int index) { strlib_aux_add_utfchar(b, (unsigned) lmt_tounsigned(L, index)); } static inline void strlib_aux_add_utfstring(lua_State *L, luaL_Buffer *b, int index) { size_t ls = 0; const char *s = lua_tolstring(L, index, &ls); luaL_addlstring(b, s, ls); } static inline void strlib_aux_add_utftable(lua_State *L, luaL_Buffer *b, int index) { lua_Unsigned n = lua_rawlen(L, index); if (n > 0) { for (lua_Unsigned i = 1; i <= n; i++) { lua_rawgeti(L, index, i); switch (lua_type(L, -1)) { case LUA_TNUMBER: strlib_aux_add_utfnumber(L, b, -1); break; case LUA_TTABLE: strlib_aux_add_utftable(L, b, -1); break; case LUA_TSTRING: strlib_aux_add_utfstring(L, b, -1); break; } lua_pop(L, 1); } } } static int strlib_utfcharacter(lua_State *L) { int n = lua_gettop(L); if (n == 1 && lua_type(L, 1) == LUA_TNUMBER) { char u[6]; char *c = aux_uni2string(&u[0], (unsigned) lua_tointeger(L, 1)); *c = '\0'; lua_pushstring(L, u); return 1; } else { luaL_Buffer b; luaL_buffinitsize(L, &b, (size_t) n * 4); for (int i = 1; i <= n; i++) { switch (lua_type(L, i)) { case LUA_TNUMBER: strlib_aux_add_utfnumber(L, &b, i); break; case LUA_TTABLE: strlib_aux_add_utftable(L, &b, i); break; case LUA_TSTRING: strlib_aux_add_utfstring(L, &b, i); break; } } luaL_pushresult(&b); return 1; } } /*tex The \UTF8 codepoint function takes two arguments, being positions in the string, while slunicode byte takes two arguments representing the number of utf characters. The variant below always returns all codepoints. */ static int strlib_utfvalue(lua_State *L) { size_t l = 0; size_t p = 0; int i = 0; const char *s = luaL_checklstring(L, 1, &l); while (p < l) { lua_pushinteger(L, strlib_aux_tounicode(s, l, &p)); i++; } return i; } /*tex This is a simplified version of utf8.len but without range. */ static int strlib_utflength(lua_State *L) { size_t ls = 0; size_t ind = 0; size_t n = 0; const char *s = lua_tolstring(L, 1, &ls); while (ind < ls) { unsigned char i = (unsigned char) *(s + ind); if (i < 0x80) { ind += 1; } else if (i >= 0xF0) { ind += 4; } else if (i >= 0xE0) { ind += 3; } else if (i >= 0xC0) { ind += 2; } else { /*tex bad news, stupid recovery */ ind += 1; } n++; } lua_pushinteger(L, n); return 1; } /*tex A handy one that formats a float but also strips trailing zeros. */ static int strlib_format_f6(lua_State *L) { double n = luaL_optnumber(L, 1, 0.0); if (n == 0.0) { lua_pushliteral(L, "0"); } else if (n == 1.0) { lua_pushliteral(L, "1"); } else { char s[128]; int i, l; /* we could use sprintf here */ if (fmod(n, 1) == 0) { i = snprintf(s, 128, "%i", (int) n); } else { if (lua_type(L, 2) == LUA_TSTRING) { const char *f = lua_tostring(L, 2); i = snprintf(s, 128, f, n); } else { i = snprintf(s, 128, "%0.6f", n) ; } l = i - 1; while (l > 1) { if (s[l - 1] == '.') { break; } else if (s[l] == '0') { s[l] = '\0'; /* redundant */ --i; } else { break; } l--; } } lua_pushlstring(L, s, i); } return 1; } /*tex The next one is mostly provided as check because doing it in pure \LUA\ is not slower and it's not a bottleneck anyway. There are soms subtle side effects when we don't check for these ranges, especially the trigger bytes (|0xD7FF| etc.) because we can get negative numbers which means wrapping around and such. */ static inline unsigned char strlib_aux_hexdigit(unsigned char n) { return (n < 10 ? '0' : 'A' - 10) + n; } # define invalid_unicode(u) ( \ (u >= 0x00E000 && u <= 0x00F8FF) || \ (u >= 0x0F0000 && u <= 0x0FFFFF) || \ (u >= 0x100000 && u <= 0x10FFFF) || \ /* (u >= 0x00D800 && u <= 0x00DFFF)) { */ \ (u >= 0x00D7FF && u <= 0x00DFFF) \ ) static int strlib_format_tounicode16(lua_State *L) { lua_Integer u = lua_tointeger(L, 1); if (invalid_unicode(u)) { lua_pushliteral(L, "FFFD"); } else if (u < 0xD7FF || (u > 0xDFFF && u <= 0xFFFF)) { char s[4] ; s[3] = strlib_aux_hexdigit((unsigned char) ((u & 0x000F) >> 0)); s[2] = strlib_aux_hexdigit((unsigned char) ((u & 0x00F0) >> 4)); s[1] = strlib_aux_hexdigit((unsigned char) ((u & 0x0F00) >> 8)); s[0] = strlib_aux_hexdigit((unsigned char) ((u & 0xF000) >> 12)); lua_pushlstring(L, s, 4); } else { unsigned u1, u2; char s[8] ; u = u - 0x10000; /* negative when invalid range */ u1 = (unsigned) (u >> 10) + 0xD800; u2 = (unsigned) (u % 0x400) + 0xDC00; s[3] = strlib_aux_hexdigit((unsigned char) ((u1 & 0x000F) >> 0)); s[2] = strlib_aux_hexdigit((unsigned char) ((u1 & 0x00F0) >> 4)); s[1] = strlib_aux_hexdigit((unsigned char) ((u1 & 0x0F00) >> 8)); s[0] = strlib_aux_hexdigit((unsigned char) ((u1 & 0xF000) >> 12)); s[7] = strlib_aux_hexdigit((unsigned char) ((u2 & 0x000F) >> 0)); s[6] = strlib_aux_hexdigit((unsigned char) ((u2 & 0x00F0) >> 4)); s[5] = strlib_aux_hexdigit((unsigned char) ((u2 & 0x0F00) >> 8)); s[4] = strlib_aux_hexdigit((unsigned char) ((u2 & 0xF000) >> 12)); lua_pushlstring(L, s, 8); } return 1; } static int strlib_format_toutf8(lua_State *L) /* could be integrated into utfcharacter */ { if (lua_type(L, 1) == LUA_TTABLE) { lua_Integer n = lua_rawlen(L, 1); if (n > 0) { luaL_Buffer b; luaL_buffinitsize(L, &b, (n + 1) * 4); for (lua_Integer i = 0; i <= n; i++) { /* there should be one operation for getting a number from a table */ if (lua_rawgeti(L, 1, i) == LUA_TNUMBER) { unsigned u = (unsigned) lua_tointeger(L, -1); if (0x80 > u) { luaL_addchar(&b, (unsigned char) u); } else if (invalid_unicode(u)) { luaL_addchar(&b, 0xFF); luaL_addchar(&b, 0xFD); } else { if (0x800 > u) luaL_addchar(&b, (unsigned char) (0xC0 | (u >> 6))); else { if (0x10000 > u) luaL_addchar(&b, (unsigned char) (0xE0 | (u >> 12))); else { luaL_addchar(&b, (unsigned char) (0xF0 | (u >>18))); luaL_addchar(&b, (unsigned char) (0x80 | (0x3F & (u >> 12)))); } luaL_addchar(&b, 0x80 | (0x3F & (u >> 6))); } luaL_addchar(&b, 0x80 | (0x3F & u)); } } lua_pop(L, 1); } luaL_pushresult(&b); } else { lua_pushliteral(L, ""); } return 1; } return 0; } /* static int strlib_format_toutf16(lua_State* L) { if (lua_type(L, 1) == LUA_TTABLE) { lua_Integer n = lua_rawlen(L, 1); if (n > 0) { luaL_Buffer b; luaL_buffinitsize(L, &b, (n + 2) * 4); for (lua_Integer i = 0; i <= n; i++) { if (lua_rawgeti(L, 1, i) == LUA_TNUMBER) { unsigned u = (unsigned) lua_tointeger(L, -1); if (invalid_unicode(u)) { luaL_addchar(&b, 0xFF); luaL_addchar(&b, 0xFD); } else if (u < 0x10000) { luaL_addchar(&b, (unsigned char) ((u & 0x00FF) )); luaL_addchar(&b, (unsigned char) ((u & 0xFF00) >> 8)); } else { u = u - 0x10000; luaL_addchar(&b, (unsigned char) ((((u>>10)+0xD800) & 0x00FF) )); luaL_addchar(&b, (unsigned char) ((((u>>10)+0xD800) & 0xFF00) >> 8)); luaL_addchar(&b, (unsigned char) (( (u%1024+0xDC00) & 0x00FF) )); luaL_addchar(&b, (unsigned char) (( (u%1024+0xDC00) & 0xFF00) >> 8)); } } lua_pop(L, 1); } luaL_addchar(&b, 0); luaL_addchar(&b, 0); luaL_pushresult(&b); } else { lua_pushliteral(L, ""); } return 1; } return 0; } */ static int strlib_format_toutf32(lua_State *L) { if (lua_type(L, 1) == LUA_TTABLE) { lua_Integer n = lua_rawlen(L, 1); if (n > 0) { luaL_Buffer b; luaL_buffinitsize(L, &b, (n + 2) * 4); for (lua_Integer i = 0; i <= n; i++) { /* there should be one operation for getting a number from a table */ if (lua_rawgeti(L, 1, i) == LUA_TNUMBER) { unsigned u = (unsigned) lua_tointeger(L, -1); if (invalid_unicode(u)) { luaL_addchar(&b, 0x00); luaL_addchar(&b, 0x00); luaL_addchar(&b, 0xFF); luaL_addchar(&b, 0xFD); } else { luaL_addchar(&b, (unsigned char) ((u & 0x000000FF) )); luaL_addchar(&b, (unsigned char) ((u & 0x0000FF00) >> 8)); luaL_addchar(&b, (unsigned char) ((u & 0x00FF0000) >> 16)); luaL_addchar(&b, (unsigned char) ((u & 0xFF000000) >> 24)); } } lua_pop(L, 1); } for (int i = 0; i <= 3; i++) { luaL_addchar(&b, 0); } luaL_pushresult(&b); } else { lua_pushliteral(L, ""); } return 1; } return 0; } /* str, true : big endian str, false : little endian str, nil, true : check bom, default to big endian str, nil, false : check bom, default to little endian str, nil, nil : check bom, default to little endian */ static int strlib_utf16toutf8(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, 1, &ls); if (ls % 2) { --ls; } if (ls) { luaL_Buffer b; int more = 0; int be = 1; size_t i = 0; luaL_buffinitsize(L, &b, ls); /* unlikely to be larger if we have latin */ if (lua_type(L, 2) == LUA_TBOOLEAN) { be = lua_toboolean(L, 2); } else if (s[0] == '\xFE' && s[1] == '\xFF') { be = 1; i += 2; } else if (s[0] == '\xFF' && s[1] == '\xEF') { be = 0; i += 2; } else { be = lua_toboolean(L, 3); } while (i < ls) { unsigned char l = (unsigned char) s[i++]; unsigned char r = (unsigned char) s[i++]; unsigned now = be ? 256 * l + r : l + 256 * r; if (more) { now = (more - 0xD800) * 0x400 + (now - 0xDC00) + 0x10000; more = 0; strlib_aux_add_utfchar(&b, now); } else if (now >= 0xD800 && now <= 0xDBFF) { more = now; } else { strlib_aux_add_utfchar(&b, now); } } luaL_pushresult(&b); } else { lua_pushliteral(L, ""); } return 1; } // static char map[] = { // '0', '1', '2', '3', // '4', '5', '6', '7', // '8', '9', 'A', 'B', // 'C', 'D', 'E', 'F', // }; static int strlib_pack_rows_columns(lua_State* L) { if (lua_type(L, 1) == LUA_TTABLE) { lua_Integer rows = lua_rawlen(L, 1); if (lua_rawgeti(L, 1, 1) == LUA_TTABLE) { lua_Integer columns = lua_rawlen(L, -1); switch (lua_rawgeti(L, -1, 1)) { case LUA_TNUMBER: { lua_Integer size = rows * columns; unsigned char *result = lmt_memory_malloc(size); lua_pop(L, 2); /* row and cell */ if (result) { unsigned char *first = result; for (lua_Integer r = 1; r <= rows; r++) { if (lua_rawgeti(L, -1, r) == LUA_TTABLE) { for (lua_Integer c = 1; c <= columns; c++) { if (lua_rawgeti(L, -1, c) == LUA_TNUMBER) { lua_Integer v = lua_tointeger(L, -1); *result++ = v < 0 ? 0 : v > 255 ? 255 : (unsigned char) v; } else { *result++ = 0; } lua_pop(L, 1); } } lua_pop(L, 1); } lua_pushlstring(L, (char *) first, result - first); return 1; } } case LUA_TTABLE: { lua_Integer mode = lua_rawlen(L, -1); lua_Integer size = rows * columns * mode; unsigned char *result = lmt_memory_malloc(size); lua_pop(L, 2); /* row and cell */ if (result) { unsigned char *first = result; for (lua_Integer r = 1; r <= rows; r++) { if (lua_rawgeti(L, -1, r) == LUA_TTABLE) { for (lua_Integer c = 1; c <= columns; c++) { if (lua_rawgeti(L, -1, c) == LUA_TTABLE) { for (int i = 1; i <= mode; i++) { if (lua_rawgeti(L, -1, i) == LUA_TNUMBER) { lua_Integer v = lua_tointeger(L, -1); *result++ = v < 0 ? 0 : v > 255 ? 255 : (unsigned char) v; } else { *result++ = 0; } lua_pop(L, 1); } } lua_pop(L, 1); } } lua_pop(L, 1); } lua_pushlstring(L, (char *) first, result - first); return 1; } } } } } lua_pushnil(L); return 1; } /*tex This converts a hex string to characters. Spacing is ignored and invalid characters result in a false result. Empty strings are okay. */ static int strlib_hextocharacters(lua_State *L) { size_t ls = 0; const char *s = lua_tolstring(L, 1, &ls); if (ls > 0) { luaL_Buffer b; luaL_buffinitsize(L, &b, ls/2); while (1) { unsigned char first = *s++; switch (first) { case ' ': case '\n': case '\r': case '\t': continue; case '\0': goto DONE; default: { unsigned char second = *s++; switch (second) { case ' ': case '\n': case '\r': case '\t': continue; case '\0': goto BAD; default: { unsigned char chr; if (first >= '0' && first <= '9') { chr = 16 * (first - '0'); } else if (first>= 'A' && first <= 'F') { chr = 16 * (first - 'A' + 10); } else if (first >= 'a' && first <= 'f') { chr = 16 * (first - 'a' + 10); } else { goto BAD; } if (second >= '0' && second <= '9') { chr += second - '0'; } else if (second >= 'A' && second <= 'F') { chr += second - 'A' + 10; } else if (second >= 'a' && second <= 'f') { chr += second - 'a' + 10; } else { goto BAD; } luaL_addchar(&b, chr); break; } } break; } } } DONE: luaL_pushresult(&b); return 1; BAD: lua_pushboolean(L, 0); return 1; } else { lua_pushliteral(L, ""); return 1; } } static int strlib_octtointeger(lua_State *L) { const char *s = lua_tostring(L, 1); // lua_Integer n = 0; // int negate = *s == '-'; // if (negate) { // s++; // } // while (*s && n < 0xFFFFFFFF) { /* large enough */ // if (*s >= '0' && *s <= '7') { // n = n * 8 + *s - '0'; // } else { // break; // } // s++; // } // lua_pushinteger(L, negate ? -n : n); lua_pushinteger(L, strtoul(s, NULL, 8)); return 1; } static int strlib_dectointeger(lua_State *L) { const char *s = lua_tostring(L, 1); // lua_Integer n = 0; // int negate = *s == '-'; // if (negate) { // s++; // } // while (*s && n < 0xFFFFFFFF) { /* large enough */ // if (*s >= '0' && *s <= '9') { // n = n * 10 + *s - '0'; // } else { // break; // } // s++; // } // lua_pushinteger(L, negate ? -n : n); // lua_pushinteger(L, atol(s)); lua_pushinteger(L, strtoul(s, NULL, 10)); return 1; } static int strlib_hextointeger(lua_State *L) { const char *s = lua_tostring(L, 1); // lua_Integer n = 0; // int negate = *s == '-'; // if (negate) { // s++; // } // while (*s && n < 0xFFFFFFFF) { /* large enough */ // if (*s >= '0' && *s <= '9') { // n = n * 16 + *s - '0'; // } else if (*s >= 'A' && *s <= 'F') { // n = n * 16 + *s - 'A' + 10; // } else if (*s >= 'a' && *s <= 'f') { // n = n * 16 + *s - 'a' + 10; // } else { // break; // } // s++; // } // lua_pushinteger(L, negate ? -n : n); lua_pushinteger(L, strtoul(s, NULL, 16)); return 1; } static int strlib_chrtointeger(lua_State *L) { lua_Integer n = 0; size_t l = 0; const char *s = lua_tolstring(L, 1, &l); if (l > 0) { size_t p = 0; while (p < l && n < 0xFFFFFFFF) { /* large enough */ n = n * 255 + (unsigned char) s[p]; p++; } lua_pushinteger(L, n); } return 1; } static const luaL_Reg strlib_function_list[] = { { "characters", strlib_characters }, { "characterpairs", strlib_characterpairs }, { "bytes", strlib_bytes }, { "bytepairs", strlib_bytepairs }, { "bytetable", strlib_bytetable }, { "linetable", strlib_linetable }, { "utfvalues", strlib_utfvalues }, { "utfcharacters", strlib_utfcharacters }, { "utfcharacter", strlib_utfcharacter }, { "utfvalue", strlib_utfvalue }, { "utflength", strlib_utflength }, { "utfvaluetable", strlib_utfvaluetable }, { "utfcharactertable", strlib_utfcharactertable }, { "f6", strlib_format_f6 }, { "tounicode16", strlib_format_tounicode16 }, { "toutf8", strlib_format_toutf8 }, /* { "toutf16", strlib_format_toutf16 }, */ /* untested */ { "toutf32", strlib_format_toutf32 }, { "utf16toutf8", strlib_utf16toutf8 }, { "packrowscolumns", strlib_pack_rows_columns }, { "hextocharacters", strlib_hextocharacters }, { "octtointeger", strlib_octtointeger }, { "dectointeger", strlib_dectointeger }, { "hextointeger", strlib_hextointeger }, { "chrtointeger", strlib_chrtointeger }, { NULL, NULL }, }; /* The next (old, moved here) experiment was used to check if using some buffer is more efficient than using a table that we concat. It makes no difference. If we ever use this, the initializer |luaextend_string_buffer| will be merged into |luaextend_string|. We could gain a little on a bit more efficient |luaL_checkudata| as we use elsewhere because in practice (surprise) its overhead makes buffers like this {\em 50 percent} slower than the concatinated variant and twice as slow when we reuse a temporary table. It's just better to stay at the \LUA\ end. Replacing the userdata test with a dedicated test gives a speed boost but we're still some {\em 10 percent} slower. So, for now we comment this feature. */ # if (0) typedef struct lmt_string_buffer { char *buffer; size_t length; size_t size; size_t step; } lmt_string_buffer; static lmt_string_buffer *strlib_buffer_instance(lua_State *L) { lmt_string_buffer *b = (lmt_string_buffer *) lua_touserdata(L, 1); if (b && lua_getmetatable(L, 1)) { lua_get_metatablelua(string_buffer_instance); if (! lua_rawequal(L, -1, -2)) { b = NULL; } else if (! b->buffer) { b = NULL; } lua_pop(L, 2); return b; } return NULL; } static int strlib_buffer_gc(lua_State *L) { lmt_string_buffer *b = strlib_buffer_instance(L); if (b) { lmt_memory_free(b->buffer); } return 0; } static int strlib_buffer_new(lua_State *L) { size_t size = lmt_optsizet(L, 1, LUAL_BUFFERSIZE); size_t step = lmt_optsizet(L, 2, size); lmt_string_buffer *b = (lmt_string_buffer *) lua_newuserdatauv(L, sizeof(lmt_string_buffer), 0); b->buffer = lmt_memory_malloc(size); b->size = size; b->step = step; b->length = 0; lua_get_metatablelua(string_buffer_instance); lua_setmetatable(L, -2); return 1; } static int strlib_buffer_add(lua_State *L) { lmt_string_buffer *b = strlib_buffer_instance(L); if (b) { switch (lua_type(L, 2)) { case LUA_TSTRING: case LUA_TNUMBER: { size_t l; const char *s = lua_tolstring(L, 2, &l); size_t length = b->length + l; if (length >= b->size) { while (length >= b->size) { b->size += b->step; } b->buffer = lmt_memory_realloc(b->buffer, b->size); } memcpy(&b->buffer[b->length], s, l); b->length = length; } break; default: break; } } return 0; } static int strlib_buffer_get_data(lua_State *L) { lmt_string_buffer *b = strlib_buffer_instance(L); if (b) { lua_pushlstring(L, b->buffer, b->length); lua_pushinteger(L, (int) b->length); return 2; } else { lua_pushnil(L); return 1; } } static int strlib_buffer_get_size(lua_State *L) { lmt_string_buffer *b = strlib_buffer_instance(L); lua_pushinteger(L, b ? b->length : 0); return 1; } static const luaL_Reg strlib_function_list_buffer[] = { { "newbuffer", strlib_buffer_new }, { "addtobuffer", strlib_buffer_add }, { "getbufferdata", strlib_buffer_get_data }, { "getbuffersize", strlib_buffer_get_size }, { NULL, NULL }, }; static int luaextend_string_buffer(lua_State *L) { lua_getglobal(L, "string"); for (const luaL_Reg *lib = strlib_function_list_buffer; lib->name; lib++) { lua_pushcfunction(L, lib->func); lua_setfield(L, -2, lib->name); } lua_pop(L, 1); luaL_newmetatable(L, STRING_BUFFER_INSTANCE); lua_pushcfunction(L, strlib_buffer_gc); lua_setfield(L, -2, "__gc"); lua_pop(L, 1); return 1; } # else static int luaextend_string_buffer(lua_State *L) { (void) L; return 0; } # endif int luaextend_string(lua_State * L) { lua_getglobal(L, "string"); for (const luaL_Reg *lib = strlib_function_list; lib->name; lib++) { lua_pushcfunction(L, lib->func); lua_setfield(L, -2, lib->name); } lua_pop(L, 1); luaextend_string_buffer(L); return 1; } luametatex-2.11.07/source/luarest/lmttablibext.c0000644000175000017500000000536014760367410020641 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" static int tablib_keys(lua_State *L) { int category = 0; // 0=unknown 1=string 2=number 3=mixed lua_settop(L, 1); lua_createtable(L, 0, 0); if (lua_type(L, 1) == LUA_TTABLE) { int index = 0; lua_pushnil(L); while (lua_next(L, -3)) { int tkey = lua_type(L, -2); /* key at -2, value at -1 */ if (category != 3) { if (category == 1) { if (tkey != LUA_TSTRING) { category = 3; } } else if (category == 2) { if (tkey != LUA_TNUMBER) { category = 3; } } else { if (tkey == LUA_TSTRING) { category = 1; } else if (tkey == LUA_TNUMBER) { category = 2; } else { category = 3; } } } lua_pushvalue(L, -2); lua_rawseti(L, 2, ++index); lua_pop(L, 1); /* key kept for next iteration */ } } lua_pushinteger(L, category); return 2; } /* local function get(t,n) local min = 1 local max = #t while min <= max do local mid = min + (max - min) // 2 if t[mid] == n then return mid elseif t[mid] < n then min = mid + 1 else max = mid - 1 end end return nil end */ static int tablib_binsearch(lua_State *L) { if (lua_type(L, 1) == LUA_TTABLE) { lua_Integer val = lua_tointeger(L, 2); lua_Unsigned min = 1; lua_Unsigned max = lua_rawlen(L, 1); while (min <= max) { lua_Unsigned mid = min + (max - min) / 2; if (lua_rawgeti(L, 1, mid) == LUA_TNUMBER) { lua_Integer tmp = lua_tointeger(L, -1); lua_pop(L, 1); if (tmp == val) { lua_pushinteger(L, mid); return 1; } else if (tmp < val) { min = mid + 1; } else { max = mid - 1; } } } } lua_pushnil(L); return 1; } static const luaL_Reg tablib_function_list[] = { { "getkeys", tablib_keys }, { "binsearch", tablib_binsearch }, { NULL, NULL }, }; int luaextend_table(lua_State * L) { lua_getglobal(L, "table"); for (const luaL_Reg *lib = tablib_function_list; lib->name; lib++) { lua_pushcfunction(L, lib->func); lua_setfield(L, -2, lib->name); } lua_pop(L, 1); return 1; } luametatex-2.11.07/source/luarest/lmtxmathlib.c0000644000175000017500000003040114760367410020465 0ustar hillehille/* See license.txt in the root of this project. This is a reformatted and slightly adapted version of lmathx.c: title : C99 math functions for Lua 5.3+ author : Luiz Henrique de Figueiredo date : 24 Jun 2015 09:51:50 licence: This code is hereby placed in the public domain. In the end I just expanded and adapted the code a bit which made it easier to get rid of some compiler warnings (if possible at all). */ # include "luametatex.h" # include # define xmathlib_pi ((lua_Number)(3.141592653589793238462643383279502884)) # define xmathlib_180 ((lua_Number) 180.0) # define xmathlib_inf ((lua_Number) INFINITY) # define xmathlib_nan ((lua_Number) NAN) static int xmathlib_acos(lua_State *L) { lua_pushnumber(L, (lua_Number) acos(luaL_checknumber(L, 1))); return 1; } static int xmathlib_acosh(lua_State *L) { lua_pushnumber(L, (lua_Number) acosh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_asin(lua_State *L) { lua_pushnumber(L, (lua_Number) asin(luaL_checknumber(L, 1))); return 1; } static int xmathlib_asinh(lua_State *L) { lua_pushnumber(L, (lua_Number) asinh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_atan(lua_State *L) { if (lua_gettop(L) == 1) { lua_pushnumber(L, (lua_Number) atan(luaL_checknumber(L, 1))); } else { lua_pushnumber(L, (lua_Number) atan2(luaL_checknumber(L, 1),luaL_checknumber(L, 2))); } return 1; } static int xmathlib_atan2(lua_State *L) { lua_pushnumber(L, (lua_Number) atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_atanh(lua_State *L) { lua_pushnumber(L, (lua_Number) atanh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_cbrt(lua_State *L) { lua_pushnumber(L, (lua_Number) cbrt(luaL_checknumber(L, 1))); return 1; } static int xmathlib_ceil(lua_State *L) { lua_pushnumber(L, (lua_Number) ceil(luaL_checknumber(L, 1))); return 1; } static int xmathlib_copysign (lua_State *L) { lua_pushnumber(L, (lua_Number) copysign(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_cos(lua_State *L) { lua_pushnumber(L, (lua_Number) cos(luaL_checknumber(L, 1))); return 1; } static int xmathlib_cosh(lua_State *L) { lua_pushnumber(L, (lua_Number) cosh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_deg(lua_State *L) { lua_pushnumber(L, luaL_checknumber(L, 1) * (xmathlib_180 / xmathlib_pi)); return 1; } static int xmathlib_erf(lua_State *L) { lua_pushnumber(L, (lua_Number) erf(luaL_checknumber(L, 1))); return 1; } static int xmathlib_erfc(lua_State *L) { lua_pushnumber(L, (lua_Number) erfc(luaL_checknumber(L, 1))); return 1; } static int xmathlib_exp(lua_State *L) { lua_pushnumber(L, (lua_Number) exp(luaL_checknumber(L, 1))); return 1; } static int xmathlib_exp2(lua_State *L) { lua_pushnumber(L, (lua_Number) exp2(luaL_checknumber(L, 1))); return 1; } static int xmathlib_expm1(lua_State *L) { lua_pushnumber(L, (lua_Number) expm1(luaL_checknumber(L, 1))); return 1; } static int xmathlib_fabs(lua_State *L) { lua_pushnumber(L, (lua_Number) fabs(luaL_checknumber(L, 1))); return 1; } static int xmathlib_fdim(lua_State *L) { lua_pushnumber(L, (lua_Number) fdim(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_floor(lua_State *L) { lua_pushnumber(L, (lua_Number) floor(luaL_checknumber(L, 1))); return 1; } static int xmathlib_fma(lua_State *L) { lua_pushnumber(L, (lua_Number) fma(luaL_checknumber(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3))); return 1; } static int xmathlib_fmax(lua_State *L) { int n = lua_gettop(L); lua_Number m = luaL_checknumber(L, 1); for (int i = 2; i <= n; i++) { m = (lua_Number) fmax(m, luaL_checknumber(L, i)); } lua_pushnumber(L, m); return 1; } static int xmathlib_fmin(lua_State *L) { int n = lua_gettop(L); lua_Number m = luaL_checknumber(L, 1); for (int i = 2; i <= n; i++) { m = (lua_Number) fmin(m, luaL_checknumber(L, i)); } lua_pushnumber(L, m); return 1; } static int xmathlib_fmod(lua_State *L) { lua_pushnumber(L, (lua_Number) fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_frexp(lua_State *L) { int e; lua_pushnumber(L, (lua_Number) frexp(luaL_checknumber(L, 1), &e)); lua_pushinteger(L, e); return 2; } static int xmathlib_fremquo(lua_State *L) { int e; lua_pushnumber(L, (lua_Number) remquo(luaL_checknumber(L, 1),luaL_checknumber(L, 2), &e)); lua_pushinteger(L, e); return 2; } static int xmathlib_gamma(lua_State *L) { lua_pushnumber(L, (lua_Number) tgamma(luaL_checknumber(L, 1))); return 1; } static int xmathlib_hypot(lua_State *L) { lua_pushnumber(L, hypot(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_isfinite(lua_State *L) { lua_pushboolean(L, isfinite(luaL_checknumber(L, 1))); return 1; } static int xmathlib_isinf(lua_State *L) { lua_pushboolean(L, isinf(luaL_checknumber(L, 1))); return 1; } static int xmathlib_isnan(lua_State *L) { lua_pushboolean(L, isnan(luaL_checknumber(L, 1))); return 1; } static int xmathlib_isnormal (lua_State *L) { lua_pushboolean(L, isnormal(luaL_checknumber(L, 1))); return 1; } static int xmathlib_j0(lua_State *L) { lua_pushnumber(L, (lua_Number) j0(luaL_checknumber(L, 1))); return 1; } static int xmathlib_j1(lua_State *L) { lua_pushnumber(L, (lua_Number) j1(luaL_checknumber(L, 1))); return 1; } static int xmathlib_jn(lua_State *L) { lua_pushnumber(L, (lua_Number) jn((int) luaL_checkinteger(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_ldexp(lua_State *L) { lua_pushnumber(L, (lua_Number) ldexp(luaL_checknumber(L, 1), (int) luaL_checkinteger(L, 2))); return 1; } static int xmathlib_lgamma(lua_State *L) { lua_pushnumber (L, (lua_Number) lgamma(luaL_checknumber(L, 1))); return 1; } static int xmathlib_log(lua_State *L) { if (lua_gettop(L) == 1) { lua_pushnumber(L, (lua_Number) log(luaL_checknumber(L, 1))); } else { lua_Number n = luaL_checknumber(L, 2); if (n == 10.0) { n = (lua_Number) log10(luaL_checknumber(L, 1)); } else if (n == 2.0) { n = (lua_Number) log2(luaL_checknumber(L, 1)); } else { n = (lua_Number) log(luaL_checknumber(L, 1)) / (lua_Number) log(n); } lua_pushnumber(L, n); } return 1; } static int xmathlib_log10(lua_State *L) { lua_pushnumber(L, (lua_Number) log10(luaL_checknumber(L, 1))); return 1; } static int xmathlib_log1p(lua_State *L) { lua_pushnumber(L, (lua_Number) log1p(luaL_checknumber(L, 1))); return 1; } static int xmathlib_log2(lua_State *L) { lua_pushnumber(L, (lua_Number) log2(luaL_checknumber(L, 1))); return 1; } static int xmathlib_logb(lua_State *L) { lua_pushnumber(L, (lua_Number) logb(luaL_checknumber(L, 1))); return 1; } static int xmathlib_modf(lua_State *L) { lua_Number ip; lua_Number fp = (lua_Number) modf(luaL_checknumber(L, 1), &ip); lua_pushnumber(L, ip); lua_pushnumber(L, fp); return 2; } static int xmathlib_nearbyint(lua_State *L) { lua_pushnumber(L, (lua_Number) nearbyint(luaL_checknumber(L, 1))); return 1; } static int xmathlib_nextafter(lua_State *L) { lua_pushnumber(L, (lua_Number) nextafter(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_pow(lua_State *L) { lua_pushnumber(L, (lua_Number) pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_rad(lua_State *L) { lua_pushnumber(L, (luaL_checknumber(L, 1) * (xmathlib_pi / xmathlib_180))); return 1; } static int xmathlib_remainder(lua_State *L) { lua_pushnumber(L, (lua_Number) remainder(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int xmathlib_round(lua_State *L) { lua_pushinteger(L, lround(luaL_checknumber(L, 1))); return 1; } static int xmathlib_scalbn(lua_State *L) { lua_pushnumber(L, (lua_Number) scalbn(luaL_checknumber(L, 1), (int) luaL_checkinteger(L, 2))); return 1; } static int xmathlib_sin(lua_State *L) { lua_pushnumber(L, (lua_Number) sin(luaL_checknumber(L, 1))); return 1; } static int xmathlib_sinh(lua_State *L) { lua_pushnumber(L, (lua_Number) sinh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_sqrt(lua_State *L) { lua_pushnumber(L, (lua_Number) sqrt(luaL_checknumber(L, 1))); return 1; } static int xmathlib_tan(lua_State *L) { lua_pushnumber(L, (lua_Number) tan(luaL_checknumber(L, 1))); return 1; } static int xmathlib_tanh(lua_State *L) { lua_pushnumber(L, (lua_Number) tanh(luaL_checknumber(L, 1))); return 1; } static int xmathlib_tgamma(lua_State *L) { lua_pushnumber(L, (lua_Number) tgamma(luaL_checknumber(L, 1))); return 1; } static int xmathlib_trunc(lua_State *L) { lua_pushnumber(L, (lua_Number) trunc(luaL_checknumber(L, 1))); return 1; } static int xmathlib_y0(lua_State *L) { lua_pushnumber(L, (lua_Number) y0(luaL_checknumber(L, 1))); return 1; } static int xmathlib_y1(lua_State *L) { lua_pushnumber(L, y1(luaL_checknumber(L, 1))); return 1; } static int xmathlib_yn(lua_State *L) { lua_pushnumber(L, yn((int) luaL_checkinteger(L, 1), luaL_checknumber(L, 2))); return 1; } static const luaL_Reg xmathlib_function_list[] = { { "acos", xmathlib_acos }, { "acosh", xmathlib_acosh }, { "asin", xmathlib_asin }, { "asinh", xmathlib_asinh }, { "atan", xmathlib_atan }, { "atan2", xmathlib_atan2 }, { "atanh", xmathlib_atanh }, { "cbrt", xmathlib_cbrt }, { "ceil", xmathlib_ceil }, { "copysign", xmathlib_copysign }, { "cos", xmathlib_cos }, { "cosh", xmathlib_cosh }, { "deg", xmathlib_deg }, { "erf", xmathlib_erf }, { "erfc", xmathlib_erfc }, { "exp", xmathlib_exp }, { "exp2", xmathlib_exp2 }, { "expm1", xmathlib_expm1 }, { "fabs", xmathlib_fabs }, { "fdim", xmathlib_fdim }, { "floor", xmathlib_floor }, { "fma", xmathlib_fma }, { "fmax", xmathlib_fmax }, { "fmin", xmathlib_fmin }, { "fmod", xmathlib_fmod }, { "frexp", xmathlib_frexp }, { "gamma", xmathlib_gamma }, { "hypot", xmathlib_hypot }, { "isfinite", xmathlib_isfinite }, { "isinf", xmathlib_isinf }, { "isnan", xmathlib_isnan }, { "isnormal", xmathlib_isnormal }, { "j0", xmathlib_j0 }, { "j1", xmathlib_j1 }, { "jn", xmathlib_jn }, { "ldexp", xmathlib_ldexp }, { "lgamma", xmathlib_lgamma }, { "log", xmathlib_log }, { "log10", xmathlib_log10 }, { "log1p", xmathlib_log1p }, { "log2", xmathlib_log2 }, { "logb", xmathlib_logb }, { "modf", xmathlib_modf }, { "nearbyint", xmathlib_nearbyint }, { "nextafter", xmathlib_nextafter }, { "pow", xmathlib_pow }, { "rad", xmathlib_rad }, { "remainder", xmathlib_remainder }, { "remquo", xmathlib_fremquo }, { "round", xmathlib_round }, { "scalbn", xmathlib_scalbn }, { "sin", xmathlib_sin }, { "sinh", xmathlib_sinh }, { "sqrt", xmathlib_sqrt }, { "tan", xmathlib_tan }, { "tanh", xmathlib_tanh }, { "tgamma", xmathlib_tgamma }, { "trunc", xmathlib_trunc }, { "y0", xmathlib_y0 }, { "y1", xmathlib_y1 }, { "yn", xmathlib_yn }, { NULL, NULL }, }; int luaopen_xmath(lua_State *L) { luaL_newlib(L, xmathlib_function_list); lua_pushnumber(L, xmathlib_inf); lua_setfield(L, -2, "inf"); lua_pushnumber(L, xmathlib_nan); lua_setfield(L, -2, "nan"); lua_pushnumber(L, xmathlib_pi); lua_setfield(L, -2, "pi"); return 1; } luametatex-2.11.07/source/luarest/lmtxcomplexlib.c0000644000175000017500000002517214760367410021214 0ustar hillehille/* See license.txt in the root of this project. This is a reformatted and slightly adapted version of lcomplex.c: title : C99 complex numbers for Lua 5.3+ author : Luiz Henrique de Figueiredo date : 26 Jul 2018 17:57:06 licence: This code is hereby placed in the public domain and also under the MIT license That implementation doesn't work for MSVC so I rewrote the code to support the microsoft compiler. I no longer use the macro approach to save bytes because with expanded code it is easier to get rid of some compiler warnings (if possible at all). In an optional module we hook the error functions into the complex library. Note: Alan has to test if all works okay. */ # include "luametatex.h" # include # define COMPLEX_METATABLE "complex number" # if (_MSC_VER) /*tex Instead of the somewhat strange two-doubles-in-a-row hack in C the microsoft vatiant uses structs. Here we use the double variant. */ # define Complex _Dcomplex static inline Complex xcomplexlib_get(lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TUSERDATA: return *((Complex*) luaL_checkudata(L, i, COMPLEX_METATABLE)); case LUA_TNUMBER: case LUA_TSTRING: return _Cbuild(luaL_checknumber(L, i), 0); default: return _Cbuild(0, 0); } } # else /*tex Here we use the two-doubles-in-a-row variant. */ # define Complex double complex static inline Complex xcomplexlib_get(lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TUSERDATA: return *((Complex*)luaL_checkudata(L, i, COMPLEX_METATABLE)); case LUA_TNUMBER: case LUA_TSTRING: return luaL_checknumber(L, i); default: return 0; } } # endif static inline int xcomplexlib_push(lua_State *L, Complex z) { Complex *p = lua_newuserdatauv(L, sizeof(Complex), 0); luaL_setmetatable(L, COMPLEX_METATABLE); *p = z; return 1; } # if (_MSC_VER) static int xcomplexlib_new(lua_State *L) { xcomplexlib_push(L, _Cbuild(0, 0)); return 1; } static int xcomplexlib_inew(lua_State *L) { xcomplexlib_push(L, _Cbuild(0, 1)); return 1; } static int xcomplexlib_eq(lua_State *L) { Complex a = xcomplexlib_get(L, 1); Complex b = xcomplexlib_get(L, 2); lua_pushboolean(L, creal(a) == creal(b) && cimag(a) == cimag(b)); return 1; } static int xcomplexlib_add(lua_State *L) { Complex a = xcomplexlib_get(L, 1); Complex b = xcomplexlib_get(L, 2); return xcomplexlib_push(L, _Cbuild(creal(a) + creal(b), cimag(a) + cimag(b))); } static int xcomplexlib_sub(lua_State *L) { Complex a = xcomplexlib_get(L, 1); Complex b = xcomplexlib_get(L, 2); return xcomplexlib_push(L, _Cbuild(creal(a) - creal(b), cimag(a) - cimag(b))); } static int xcomplexlib_neg(lua_State *L) { Complex a = xcomplexlib_get(L, 1); return xcomplexlib_push(L, _Cbuild(-creal(a), -cimag(a))); } static int xcomplexlib_div(lua_State *L) { Complex b = xcomplexlib_get(L, 2); if (creal(b) == 0.0 || cimag(b) == 0.0) { return 0; } else { Complex a = xcomplexlib_get(L, 1); Complex t = { 1 / creal(b), 1 / cimag(b) }; return xcomplexlib_push(L, _Cmulcc(a, t)); } } static int xcomplexlib_mul(lua_State *L) { Complex a = xcomplexlib_get(L, 1); Complex b = xcomplexlib_get(L, 2); return xcomplexlib_push(L, _Cmulcc(a, b)); } # else static int xcomplexlib_new(lua_State *L) { return xcomplexlib_push(L, luaL_optnumber(L, 1, 0) + luaL_optnumber(L, 2, 0) * I); } static int xcomplexlib_inew(lua_State *L) { return xcomplexlib_push(L, I); } static int xcomplexlib_eq(lua_State *L) { lua_pushboolean(L, xcomplexlib_get(L, 1) == xcomplexlib_get(L, 2)); return 1; } static int xcomplexlib_add(lua_State *L) { return xcomplexlib_push(L, xcomplexlib_get(L, 1) + xcomplexlib_get(L, 2)); } static int xcomplexlib_sub(lua_State *L) { return xcomplexlib_push(L, xcomplexlib_get(L, 1) - xcomplexlib_get(L, 2)); } static int xcomplexlib_neg(lua_State *L) { return xcomplexlib_push(L, - xcomplexlib_get(L, 1)); } static int xcomplexlib_div(lua_State *L) { return xcomplexlib_push(L, xcomplexlib_get(L, 1) / xcomplexlib_get(L, 2)); } static int xcomplexlib_mul(lua_State *L) { return xcomplexlib_push(L, xcomplexlib_get(L, 1) * xcomplexlib_get(L, 2)); } # endif static int xcomplexlib_abs(lua_State *L) { lua_pushnumber(L, (lua_Number) cabs(xcomplexlib_get(L, 1))); return 1; } static int xcomplexlib_acos(lua_State *L) { return xcomplexlib_push(L, cacos(xcomplexlib_get(L, 1))); } static int xcomplexlib_acosh(lua_State *L) { return xcomplexlib_push(L, cacosh(xcomplexlib_get(L, 1))); } static int xcomplexlib_arg(lua_State *L) { lua_pushnumber(L, (lua_Number) carg(xcomplexlib_get(L, 1))); return 1; } static int xcomplexlib_asin(lua_State *L) { return xcomplexlib_push(L, casin(xcomplexlib_get(L, 1))); } static int xcomplexlib_asinh(lua_State *L) { return xcomplexlib_push(L, casinh(xcomplexlib_get(L, 1))); } static int xcomplexlib_atan(lua_State *L) { return xcomplexlib_push(L, catan(xcomplexlib_get(L, 1))); } static int xcomplexlib_atanh(lua_State *L) { return xcomplexlib_push(L, catanh(xcomplexlib_get(L, 1))); } static int xcomplexlib_cos(lua_State *L) { return xcomplexlib_push(L, ccos(xcomplexlib_get(L, 1))); } static int xcomplexlib_cosh(lua_State *L) { return xcomplexlib_push(L, ccosh(xcomplexlib_get(L, 1))); } static int xcomplexlib_exp(lua_State *L) { xcomplexlib_push(L, cexp(xcomplexlib_get(L, 1))); return 1; } static int xcomplexlib_imag(lua_State *L) { lua_pushnumber(L, (lua_Number) (cimag)(xcomplexlib_get(L, 1))); return 1; } static int xcomplexlib_log(lua_State *L) { return xcomplexlib_push(L, clog(xcomplexlib_get(L, 1))); } static int xcomplexlib_pow(lua_State *L) { return xcomplexlib_push(L, cpow(xcomplexlib_get(L, 1), xcomplexlib_get(L, 2))); } static int xcomplexlib_proj(lua_State *L) { return xcomplexlib_push(L, cproj(xcomplexlib_get(L, 1))); } static int xcomplexlib_real(lua_State *L) { lua_pushnumber(L, (lua_Number) creal(xcomplexlib_get(L, 1))); return 1; } static int xcomplexlib_sin(lua_State *L) { return xcomplexlib_push(L, csin(xcomplexlib_get(L, 1))); } static int xcomplexlib_sinh(lua_State *L) { return xcomplexlib_push(L, csinh(xcomplexlib_get(L, 1))); } static int xcomplexlib_sqrt(lua_State *L) { return xcomplexlib_push(L, csqrt(xcomplexlib_get(L, 1))); } static int xcomplexlib_tan(lua_State *L) { return xcomplexlib_push(L, ctan(xcomplexlib_get(L, 1))); } static int xcomplexlib_tanh(lua_State *L) { return xcomplexlib_push(L, ctanh(xcomplexlib_get(L, 1))); } /*tex A few convenience functions: */ static int xcomplexlib_tostring(lua_State *L) { Complex z = xcomplexlib_get(L, 1); lua_Number x = creal(z); lua_Number y = cimag(z); lua_settop(L, 0); if (x != 0.0 || y == 0.0) { lua_pushnumber(L, x); } if (y != 0.0) { if (y == 1.0) { if (x != 0.0) { lua_pushliteral(L, "+"); } } else if (y == -1.0) { lua_pushliteral(L, "-"); } else { if (y > 0.0 && x != 0.0) { lua_pushliteral(L, "+"); } lua_pushnumber(L, y); } lua_pushliteral(L, "i"); } lua_concat(L, lua_gettop(L)); return 1; } static int xcomplexlib_topair(lua_State *L) { Complex z = xcomplexlib_get(L, 1); lua_pushnumber(L, (lua_Number) creal(z)); lua_pushnumber(L, (lua_Number) cimag(z)); return 2; } static int xcomplexlib_totable(lua_State *L) { Complex z = xcomplexlib_get(L, 1); lua_createtable(L, 2, 0); lua_pushnumber(L, (lua_Number) creal(z)); lua_pushnumber(L, (lua_Number) cimag(z)); lua_rawseti(L, -3, 1); lua_rawseti(L, -3, 2); return 1; } /*tex Now we assemble the library: */ static const struct luaL_Reg xcomplexlib_function_list[] = { /* management */ { "new", xcomplexlib_new }, { "tostring", xcomplexlib_tostring }, { "topair", xcomplexlib_topair }, { "totable", xcomplexlib_totable }, { "i", xcomplexlib_inew }, /* operators */ { "__add", xcomplexlib_add }, { "__div", xcomplexlib_div }, { "__eq", xcomplexlib_eq }, { "__mul", xcomplexlib_mul }, { "__sub", xcomplexlib_sub }, { "__unm", xcomplexlib_neg }, { "__pow", xcomplexlib_pow }, /* functions */ { "abs", xcomplexlib_abs }, { "acos", xcomplexlib_acos }, { "acosh", xcomplexlib_acosh }, { "arg", xcomplexlib_arg }, { "asin", xcomplexlib_asin }, { "asinh", xcomplexlib_asinh }, { "atan", xcomplexlib_atan }, { "atanh", xcomplexlib_atanh }, { "conj", xcomplexlib_neg }, { "cos", xcomplexlib_cos }, { "cosh", xcomplexlib_cosh }, { "exp", xcomplexlib_exp }, { "imag", xcomplexlib_imag }, { "log", xcomplexlib_log }, { "pow", xcomplexlib_pow }, { "proj", xcomplexlib_proj }, { "real", xcomplexlib_real }, { "sin", xcomplexlib_sin }, { "sinh", xcomplexlib_sinh }, { "sqrt", xcomplexlib_sqrt }, { "tan", xcomplexlib_tan }, { "tanh", xcomplexlib_tanh }, /* */ { NULL, NULL }, }; int luaopen_xcomplex(lua_State *L) { luaL_newmetatable(L, COMPLEX_METATABLE); luaL_setfuncs(L, xcomplexlib_function_list, 0); lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); lua_settable(L, -3); lua_pushliteral(L, "__tostring"); lua_pushliteral(L, "tostring"); lua_gettable(L, -3); lua_settable(L, -3); lua_pushliteral(L, "I"); lua_pushliteral(L, "i"); lua_gettable(L, -3); lua_settable(L, -3); lua_pushliteral(L, "__name"); /* kind of redundant */ lua_pushliteral(L, "complex"); lua_settable(L, -3); return 1; } luametatex-2.11.07/source/luarest/lmtpdfelib.c0000644000175000017500000016442614760367410020301 0ustar hillehille/* See license.txt in the root of this project. */ /*tex This file hosts the encapsulated \PDF\ support code used for inclusion and access from \LUA. */ # include "luametatex.h" // # define PDFE_METATABLE_INSTANCE "pdfe.instance" // # define PDFE_METATABLE_DICTIONARY "pdfe.dictionary" // # define PDFE_METATABLE_ARRAY "pdfe.array" // # define PDFE_METATABLE_STREAM "pdfe.stream" // # define PDFE_METATABLE_REFERENCE "pdfe.reference" # include "../libraries/pplib/pplib.h" /*tex We start with some housekeeping. Dictionaries, arrays, streams and references get userdata, while strings, names, integers, floats and booleans become regular \LUA\ objects. We need to define a few metatable identifiers too. */ typedef struct pdfe_document { ppdoc *document; int open; int isfile; char *memstream; int pages; int index; } pdfe_document ; typedef struct pdfe_dictionary { ppdict *dictionary; } pdfe_dictionary; typedef struct pdfe_array { pparray *array; } pdfe_array; typedef struct pdfe_stream { ppstream *stream; int decode; int open; } pdfe_stream; typedef struct pdfe_reference { /* ppref *reference; */ ppxref *xref; int onum; } pdfe_reference; /*tex We need to check if we have the right userdata. A similar warning is issued when encounter a problem. We don't exit. */ static void pdfe_invalid_object_warning(const char *detail, int where) { tex_formatted_warning("pdfe lib", "lua expected, case %i", detail, where); } /* todo: use luaL_checkudata */ typedef enum pdfelib_errors { no_error, to_string_error, to_table_error, get_catalog_error, get_trailer_error, get_info_error, get_page_error, get_pages_error, get_size_error, get_status_error, get_version_error, get_n_of_pages_error, get_n_of_objects_error, get_memory_usage_error, get_from_error, get_box_error, open_error, close_error, read_error, free_error, unencrypt_error, } pdfelib_errors; static pdfe_document *pdfelib_aux_check_isdocument(lua_State *L, int n, int where) { pdfe_document *p = (pdfe_document *) lua_touserdata(L, n); if (p && lua_getmetatable(L, n)) { lua_get_metatablelua(pdfe_instance); if (! lua_rawequal(L, -1, -2)) { p = NULL; // todo: no document } else if (! p->document) { p = NULL; // todo: invalid document } lua_pop(L, 2); if (p) { return p; } } if (where != free_error) { pdfe_invalid_object_warning("document", where); } return NULL; } static pdfe_dictionary *pdfelib_aux_check_isdictionary(lua_State *L, int n, int where) { pdfe_dictionary *p = (pdfe_dictionary *) lua_touserdata(L, n); if (p && lua_getmetatable(L, n)) { lua_get_metatablelua(pdfe_dictionary_instance); if (! lua_rawequal(L, -1, -2)) { p = NULL; } lua_pop(L, 2); if (p) { return p; } } pdfe_invalid_object_warning("dictionary", where); return NULL; } static pdfe_array *pdfelib_aux_check_isarray(lua_State *L, int n, int where) { pdfe_array *p = (pdfe_array *) lua_touserdata(L, n); if (p && lua_getmetatable(L, n)) { lua_get_metatablelua(pdfe_array_instance); if (! lua_rawequal(L, -1, -2)) { p = NULL; } lua_pop(L, 2); if (p) { return p; } } pdfe_invalid_object_warning("array", where); return NULL; } static pdfe_stream *pdfelib_aux_check_isstream(lua_State *L, int n, int where) { pdfe_stream *p = (pdfe_stream *) lua_touserdata(L, n); if (p && lua_getmetatable(L, n)) { lua_get_metatablelua(pdfe_stream_instance); if (! lua_rawequal(L, -1, -2)) { p = NULL; } lua_pop(L, 2); if (p) { return p; } } pdfe_invalid_object_warning("stream", where); return NULL; } static pdfe_reference *pdfelib_aux_check_isreference(lua_State *L, int n, int where) { pdfe_reference *p = (pdfe_reference *) lua_touserdata(L, n); if (p && lua_getmetatable(L, n)) { lua_get_metatablelua(pdfe_reference_instance); if (! lua_rawequal(L, -1, -2)) { p = NULL; } lua_pop(L, 2); if (p) { return p; } } pdfe_invalid_object_warning("reference", where); return NULL; } /*tex Reporting the type of a userdata is just a sequence of tests till we find the right one. We return nothing is it is no pdfe type. \starttyping t = pdfe.type() \stoptyping */ /* # define check_type(field,meta,name) do { \ lua_get_metatablelua(meta); \ if (lua_rawequal(L, -1, -2)) { \ lua_pushstring(L, name); \ return 1; \ } \ lua_pop(L, 1); \ } while (0) static int pdfelib_type(lua_State *L) { void *p = lua_touserdata(L, 1); if (p && lua_getmetatable(L, 1)) { check_type(document, pdfe_instance, PDFE_METATABLE_INSTANCE); check_type(dictionary, pdfe_dictionary, PDFE_METATABLE_DICTIONARY); check_type(array, pdfe_array, PDFE_METATABLE_ARRAY); check_type(reference, pdfe_reference, PDFE_METATABLE_REFERENCE); check_type(stream, pdfe_stream, PDFE_METATABLE_STREAM); } return 0; } */ # define check_type(field,meta) do { \ lua_get_metatablelua(meta); \ if (lua_rawequal(L, -1, -2)) { \ lua_push_key(meta); \ return 1; \ } \ lua_pop(L, 1); \ } while (0) static int pdfelib_type(lua_State *L) { void *p = lua_touserdata(L, 1); if (p && lua_getmetatable(L, 1)) { check_type(document, pdfe_instance); check_type(dictionary, pdfe_dictionary_instance); check_type(array, pdfe_array_instance); check_type(reference, pdfe_reference_instance); check_type(stream, pdfe_stream_instance); } return 0; } /*tex The \type {tostring} metamethods are similar and report a pdfe type plus a pointer value, as is rather usual in \LUA. I ditched the macro that defined them and are now verbose. */ static int pdfelib_document_tostring(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, to_string_error); if (p) { lua_pushfstring(L, "", p->document); return 1; } else { return 0; } } static int pdfelib_dictionary_tostring(lua_State *L) { pdfe_dictionary *p = pdfelib_aux_check_isdictionary(L, 1, to_string_error); if (p) { lua_pushfstring(L, "", p->dictionary); return 1; } else { return 0; } } static int pdfelib_array_tostring(lua_State *L) { pdfe_array *p = pdfelib_aux_check_isarray(L, 1, to_string_error); if (p) { lua_pushfstring(L, "", p->array); return 1; } else { return 0; } } static int pdfelib_stream_tostring(lua_State *L) { pdfe_stream *p = pdfelib_aux_check_isstream(L, 1, to_string_error); if (p) { lua_pushfstring(L, "", p->stream); return 1; } else { return 0; } } static int pdfelib_reference_tostring(lua_State *L) { pdfe_reference *p = pdfelib_aux_check_isreference(L, 1, to_string_error); if (p) { lua_pushfstring(L, "", p->onum); return 1; } else { return 0; } } /*tex The pushers look rather similar. We have two variants, one that just pushes the object, and another that also pushes some extra information. */ static inline void pdfe_push_dictionary(lua_State *L, ppdict *dictionary) { pdfe_dictionary *d = (pdfe_dictionary *) lua_newuserdatauv(L, sizeof(pdfe_dictionary), 0); // luaL_getmetatable(L, PDFE_METATABLE_DICTIONARY); lua_get_metatablelua(pdfe_dictionary_instance); lua_setmetatable(L, -2); d->dictionary = dictionary; } static int pdfelib_aux_pushdictionary(lua_State *L, ppdict *dictionary) { if (dictionary) { pdfe_push_dictionary(L, dictionary); lua_pushinteger(L, (lua_Integer) dictionary->size); return 2; } else { return 0; } } static int pdfelib_aux_pushdictionaryonly(lua_State *L, ppdict *dictionary) { if (dictionary) { pdfe_push_dictionary(L, dictionary); return 1; } else { return 0; } } static inline void pdfe_push_array(lua_State *L, pparray *array) { pdfe_array *a = (pdfe_array *) lua_newuserdatauv(L, sizeof(pdfe_array), 0); // luaL_getmetatable(L, PDFE_METATABLE_ARRAY); lua_get_metatablelua(pdfe_array_instance); lua_setmetatable(L, -2); a->array = array; } static int pdfelib_aux_pusharray(lua_State *L, pparray *array) { if (array) { pdfe_push_array(L, array); lua_pushinteger(L, (lua_Integer) array->size); return 2; } else { return 0; } } static int pdfelib_aux_pusharrayonly(lua_State *L, pparray *array) { if (array) { pdfe_push_array(L, array); return 1; } else { return 0; } } static inline void pdfe_push_stream(lua_State *L, ppstream *stream) { pdfe_stream *s = (pdfe_stream *) lua_newuserdatauv(L, sizeof(pdfe_stream), 0); // luaL_getmetatable(L, PDFE_METATABLE_STREAM); lua_get_metatablelua(pdfe_stream_instance); lua_setmetatable(L, -2); s->stream = stream; s->open = 0; s->decode = 0; } static int pdfelib_aux_pushstream(lua_State *L, ppstream *stream) { if (stream) { pdfe_push_stream(L, stream); if (pdfelib_aux_pushdictionary(L, stream->dict) > 0) { return 3; } else { return 1; } } else { return 0; } } static int pdfelib_aux_pushstreamonly(lua_State *L, ppstream *stream) { if (stream) { pdfe_push_stream(L, stream); if (pdfelib_aux_pushdictionaryonly(L, stream->dict) > 0) { return 2; } else { return 1; } } else { return 0; } } static inline void pdfe_push_reference(lua_State *L, ppref *reference) { pdfe_reference *r = (pdfe_reference *) lua_newuserdatauv(L, sizeof(pdfe_reference), 0); // luaL_getmetatable(L, PDFE_METATABLE_REFERENCE); lua_get_metatablelua(pdfe_reference_instance); lua_setmetatable(L, -2); r->xref = reference->xref; r->onum = (int) reference->number; } static int pdfelib_aux_pushreference(lua_State *L, ppref *reference) { if (reference && reference->number != 0) { pdfe_push_reference(L, reference); lua_pushinteger(L, (lua_Integer) reference->number); return 2; } else { return 0; } } /*tex The next function checks for the type and then pushes the matching data on the stack. \starttabulate[|rT|l|l|l|] \BC type \BC meaning \BC value \BC detail \NC \NR \NC 0 \NC none \NC nil \NC \NC \NR \NC 1 \NC null \NC nil \NC \NC \NR \NC 2 \NC boolean \NC boolean \NC \NC \NR \NC 3 \NC integer \NC integer \NC \NC \NR \NC 4 \NC number \NC float \NC \NC \NR \NC 5 \NC name \NC string \NC \NC \NR \NC 6 \NC string \NC string \NC type \NC \NR \NC 7 \NC array \NC arrayobject \NC size \NC \NR \NC 8 \NC dictionary \NC dictionaryobject \NC size \NC \NR \NC 9 \NC stream \NC streamobject \NC dictionary size \NC \NR \NC 10 \NC reference \NC integer \NC \NC \NR \LL \stoptabulate A name and string can be distinguished by the extra type value that a string has. */ static int pdfelib_aux_pushvalue(lua_State *L, ppobj *object) { switch (object->type) { case PPNONE: case PPNULL: lua_pushnil(L); return 1; case PPBOOL: lua_pushboolean(L, (int) object->integer); return 1; case PPINT: lua_pushinteger(L, (lua_Integer) object-> integer); return 1; case PPNUM: lua_pushnumber(L, (double) object->number); return 1; case PPNAME: { ppname *n = ppname_decoded(object->name) ; lua_pushlstring(L, ppname_data(n), ppname_size(n)); return 1; } case PPSTRING: // lua_pushlstring(L, ppstring_data(object->string), ppstring_size(object->string)); // lua_pushboolean(L, ppstring_hex(object->string)); { ppstring *s = ppstring_decoded(object->string); lua_pushlstring(L, ppstring_data(s), ppstring_size(s)); lua_pushinteger(L, (s)->flags); return 2; } case PPARRAY: return pdfelib_aux_pusharray(L, object->array); case PPDICT: return pdfelib_aux_pushdictionary(L, object->dict); case PPSTREAM: return pdfelib_aux_pushstream(L, object->stream); case PPREF: return pdfelib_aux_pushreference(L, object->ref); } return 0; } /*tex We need to start someplace when we traverse a document's tree. There are three places: \starttyping catalogdictionary = getcatalog(documentobject) trailerdictionary = gettrailer(documentobject) infodictionary = getinfo (documentobject) \stoptyping */ static int pdfelib_getcatalog(lua_State *L) { pdfe_document* p = pdfelib_aux_check_isdocument (L, 1, get_catalog_error); if (p) { return pdfelib_aux_pushdictionaryonly (L, ppdoc_catalog (p->document)); } else { return 0; } } static int pdfelib_gettrailer(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_trailer_error); if (p) { return pdfelib_aux_pushdictionaryonly (L, ppdoc_trailer (p->document)); } else { return 0; } } static int pdfelib_getinfo(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_info_error); if (p) { return pdfelib_aux_pushdictionaryonly (L, ppdoc_info (p->document)); } else { return 0; } } static int pdfelib_getpermissions(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_info_error); if (p) { lua_pushinteger(L, ppdoc_permissions(p->document)); } else { lua_pushnil(L); } return 1; } /*tex We have three more helpers. \starttyping [key,] type, value, detail = getfromdictionary(dictionaryobject,name|index) type, value, detail = getfromarray (arrayobject,index) [key,] type, value, detail = getfromstream (streamobject,name|index) \stoptyping */ static int pdfelib_getfromarray(lua_State *L) { pdfe_array *a = pdfelib_aux_check_isarray(L, 1, get_from_error); if (a) { unsigned int index = lmt_checkinteger(L, 2) - 1; if (index < a->array->size) { ppobj *object = pparray_at(a->array,index); if (object) { lua_pushinteger(L, (lua_Integer) object->type); return 1 + pdfelib_aux_pushvalue(L, object); } } } return 0; } static int pdfelib_getfromdictionary(lua_State *L) { pdfe_dictionary *d = pdfelib_aux_check_isdictionary(L, 1, get_from_error); if (d) { if (lua_type(L, 2) == LUA_TSTRING) { const char *name = luaL_checkstring(L, 2); ppobj *object = ppdict_get_obj(d->dictionary, name); if (object) { lua_pushinteger(L, (lua_Integer) object->type); return 1 + pdfelib_aux_pushvalue(L, object); } } else { unsigned int index = lmt_checkinteger(L, 2) - 1; if (index < d->dictionary->size) { ppobj *object = ppdict_at(d->dictionary,index); if (object) { ppname *key = ppname_decoded(ppdict_key(d->dictionary, index)); lua_pushlstring(L, ppname_data(key), ppname_size(key)); lua_pushinteger(L, (lua_Integer) object->type); return 2 + pdfelib_aux_pushvalue(L, object); } } } } return 0; } static int pdfelib_getfromstream(lua_State *L) { pdfe_stream *s = (pdfe_stream *) lua_touserdata(L, get_from_error); // pdfe_stream *s = check_isstream(L, 1); if (s) { ppdict *d = s->stream->dict; if (lua_type(L, 2) == LUA_TSTRING) { const char *name = luaL_checkstring(L, 2); ppobj *object = ppdict_get_obj(d, name); if (object) { lua_pushinteger(L, (lua_Integer) object->type); return 1 + pdfelib_aux_pushvalue(L, object); } } else { unsigned int index = lmt_checkinteger(L, 2) - 1; if (index < d->size) { ppobj *object = ppdict_at(d, index); if (object) { ppname *key = ppname_decoded(ppdict_key(d, index)); lua_pushlstring(L, ppname_data(key), ppname_size(key)); lua_pushinteger(L, (lua_Integer) object->type); return 2 + pdfelib_aux_pushvalue(L, object); } } } } return 0; } /*tex An indexed table with all entries in an array can be fetched with:: \starttyping t = arraytotable(arrayobject) \stoptyping An hashed table with all entries in an dictionary can be fetched with:: \starttyping t = dictionarytotable(arrayobject) \stoptyping */ static void pdfelib_totable(lua_State *L, ppobj *object, int flat) { int n = pdfelib_aux_pushvalue(L, object); if (flat && n < 2) { return; } else { /* [value] [extra] [more] */ lua_createtable(L, n + 1, 0); if (n == 1) { /* value { nil, nil } */ lua_insert(L, -2); /* { nil, nil } value */ lua_rawseti(L, -2, 2); /* { nil , value } */ } else if (n == 2) { /* value extra { nil, nil, nil } */ lua_insert(L, -3); /* { nil, nil, nil } value extra */ lua_rawseti(L, -3, 3); /* { nil, nil, extra } value */ lua_rawseti(L, -2, 2); /* { nil, value, extra } */ } else if (n == 3) { /* value extra more { nil, nil, nil, nil } */ lua_insert(L, -4); /* { nil, nil, nil, nil, nil } value extra more */ lua_rawseti(L, -4, 4); /* { nil, nil, nil, more } value extra */ lua_rawseti(L, -3, 3); /* { nil, nil, extra, more } value */ lua_rawseti(L, -2, 2); /* { nil, value, extra, more } */ } lua_pushinteger(L, (lua_Integer) object->type); /* { nil, [value], [extra], [more] } type */ lua_rawseti(L, -2, 1); /* { type, [value], [extra], [more] } */ } } static int pdfelib_arraytotable(lua_State *L) { pdfe_array *a = pdfelib_aux_check_isarray(L, 1, to_table_error); if (a) { int flat = lua_isboolean(L, 2); int j = 0; lua_createtable(L, (int) a->array->size, 0); /* table */ for (unsigned int i = 0; i < a->array->size; i++) { ppobj *object = pparray_at(a->array,i); if (object) { pdfelib_totable(L, object, flat); /* table { type, [value], [extra], [more] } */ lua_rawseti(L, -2, ++j); /* table[i] = { type, [value], [extra], [more] } */ } } return 1; } else { return 0; } } static int pdfelib_dictionarytotable(lua_State *L) { pdfe_dictionary *d = pdfelib_aux_check_isdictionary(L, 1, to_table_error); if (d) { int flat = lua_isboolean(L, 2); lua_createtable(L, 0, (int) d->dictionary->size); /* table */ for (unsigned int i = 0; i < d->dictionary->size; i++) { ppobj *object = ppdict_at(d->dictionary, i); if (object) { ppname *key = ppname_decoded(ppdict_key(d->dictionary, i)); lua_pushlstring(L, ppname_data(key), ppname_size(key)); /* table key */ pdfelib_totable(L, object, flat); /* table key { type, [value], [extra], [more] } */ lua_rawset(L, -3); /* table[key] = { type, [value], [extra] } */ } } return 1; } else { return 0; } } /*tex All pages are collected with: \starttyping { { dict, size, objnum }, ... } = pagestotable(document) \stoptyping */ static int pdfelib_pagestotable(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, to_table_error); if (p) { ppdoc *d = p->document; int i = 1; int j = 0; lua_createtable(L, (int) ppdoc_page_count(d), 0); /* pages[1..n] */ for (ppref *r = ppdoc_first_page(d); r; r = ppdoc_next_page(d), ++i) { lua_createtable(L, 3, 0); if (ppref_obj(r)) { pdfelib_aux_pushdictionary(L, ppref_obj(r)->dict); /* table dictionary n */ lua_rawseti(L, -3, 2); /* table dictionary */ lua_rawseti(L, -2, 1); /* table */ lua_pushinteger(L, r->number); /* table reference */ lua_rawseti(L, -2, 3); /* table */ lua_rawseti(L, -2, ++j); /* pages[i] = { dictionary, size, objnum } */ } } return 1; } else { return 0; } } /*tex Streams can be fetched on one go: \starttyping string, n = readwholestream(streamobject,decode) \stoptyping */ static int pdfelib_stream_readwhole(lua_State *L) { pdfe_stream *s = pdfelib_aux_check_isstream(L, 1, read_error); if (s) { uint8_t *b = NULL; int decode = 0; size_t n = 0; if (s->open > 0) { ppstream_done(s->stream); s->open = 0; s->decode = 0; } if (lua_gettop(L) > 1 && lua_isboolean(L, 2)) { decode = lua_toboolean(L, 2); } b = ppstream_all(s->stream, &n, decode); lua_pushlstring(L, (const char *) b, n); lua_pushinteger(L, (lua_Integer) n); ppstream_done(s->stream); return 2; } else { return 0; } } /*tex Alternatively streams can be fetched stepwise: \starttyping okay = openstream(streamobject,[decode]) string, n = readfromstream(streamobject) closestream(streamobject) \stoptyping */ static int pdfelib_stream_open(lua_State *L) { pdfe_stream *s = pdfelib_aux_check_isstream(L, 1, open_error); if (s) { if (s->open == 0) { if (lua_gettop(L) > 1) { s->decode = lua_isboolean(L, 2); } s->open = 1; } lua_pushboolean(L,1); return 1; } else { return 0; } } static int pdfelib_stream_close(lua_State *L) { pdfe_stream *s = pdfelib_aux_check_isstream(L, 1, close_error); if (s && s->open > 0) { ppstream_done(s->stream); s->open = 0; s->decode = 0; } return 0; } static int pdfelib_stream_read(lua_State *L) { pdfe_stream *s = pdfelib_aux_check_isstream(L, 1, read_error); if (s) { size_t n = 0; uint8_t *d = NULL; if (s->open == 1) { d = ppstream_first(s->stream, &n, s->decode); s->open = 2; } else if (s->open == 2) { d = ppstream_next(s->stream, &n); } else { return 0; } lua_pushlstring(L, (const char *) d, n); lua_pushinteger(L, (lua_Integer) n); return 2; } else { return 0; } } /*tex There are two methods for opening a document: files and strings. \starttyping documentobject = open(filename) documentobject = new(string,length) \stoptyping Closing happens with: \starttyping close(documentobject) \stoptyping When the \type {new} function gets a peudo filename as third argument, no user data will be created but the stream is accessible as image. */ /* static int pdfelib_test(lua_State *L) { const char *filename = luaL_checkstring(L, 1); ppdoc *d = ppdoc_load(filename); if (d) { lua_pushboolean(L,1); ppdoc_free(d); } else { lua_pushboolean(L,0); } return 1; } */ static int aux_pdfelib_open(lua_State *L, FILE *f) { ppdoc *d = ppdoc_filehandle(f, 1); if (d) { pdfe_document *p = (pdfe_document *) lua_newuserdatauv(L, sizeof(pdfe_document), 0); // luaL_getmetatable(L, PDFE_METATABLE_INSTANCE); lua_get_metatablelua(pdfe_instance); lua_setmetatable(L, -2); p->document = d; p->open = 1; p->isfile = 1; p->memstream = NULL; return 1; } else { return 0; } } static int pdfelib_open(lua_State *L) { const char *filename = luaL_checkstring(L, 1); FILE *f = aux_utf8_fopen(filename, "rb"); if (f && aux_pdfelib_open(L, f)) { return 1; } else { /* tex_normal_warning("pdfe lib", "no valid file handle"); */ /* the caller should handle it */ return 0; } } static int pdfelib_openfile(lua_State *L) { luaL_Stream *fs = ((luaL_Stream *) luaL_checkudata(L, 1, LUA_FILEHANDLE)); FILE *f = (fs->closef) ? fs->f : NULL; if (f && aux_pdfelib_open(L, f)) { /*tex We trick \LUA\ in believing the file is closed. */ fs->closef = NULL; return 1; } else { /* tex_normal_warning("pdfe lib", "no valid file handle"); */ /* the caller should handle it */ return 0; } } static int pdfelib_new(lua_State *L) { size_t streamsize = 0; const char *docstream = NULL; switch (lua_type(L, 1)) { case LUA_TSTRING: docstream = lua_tolstring(L, 1, &streamsize); if (! docstream) { tex_normal_warning("pdfe lib", "invalid string"); return 0; } else { break; } case LUA_TLIGHTUSERDATA: /*tex The stream comes as a sequence of bytes. This could happen from a library (we used this for swiglib gm output tests). */ docstream = (const char *) lua_touserdata(L, 1); if (! docstream) { tex_normal_warning("pdfe lib", "invalid lightuserdata"); return 0; } else { break; } default: tex_normal_warning("pdfe lib", "string or lightuserdata expected"); return 0; } streamsize = luaL_optinteger(L, 2, streamsize); if (streamsize > 0) { char *memstream = lmt_generic_malloc((unsigned) (streamsize + 1)); /* we have no hook into pdfe free */ if (memstream) { ppdoc *d = NULL; memcpy(memstream, docstream, (streamsize + 1)); memstream[streamsize] = '\0'; d = ppdoc_mem(memstream, streamsize); if (d) { pdfe_document *p = (pdfe_document *) lua_newuserdatauv(L, sizeof(pdfe_document), 0); // luaL_getmetatable(L, PDFE_METATABLE_INSTANCE); lua_get_metatablelua(pdfe_instance); lua_setmetatable(L, -2); p->document = d; p->open = 1; p->isfile = 0; p->memstream = memstream; return 1; } else { tex_normal_warning("pdfe lib", "unable to handle stream"); } } else { tex_normal_warning("pdfe lib", "not enough memory for new stream"); } } else { tex_normal_warning("pdfe lib", "stream with size > 0 expected"); } return 0; } /* There is no garbage collection needed as the library itself manages the objects. Normally objects don't take much space. Streams use buffers so (I assume) that they are not persistent. The only collector is in the parent object (the document). */ static int pdfelib_document_free(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, free_error); if (p && p->open) { if (p->document) { ppdoc_free(p->document); p->document = NULL; } if (p->memstream) { /* pplib does this: xfree(p->memstream); */ p->memstream = NULL; } p->open = 0; } return 0; } static int pdfelib_close(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, close_error); if (p && p->open) { if (p->document) { ppdoc_free(p->document); p->document = NULL; } if (p->memstream) { /* pplib does this: xfree(p->memstream); */ p->memstream = NULL; } p->open = 0; } return 0; } /*tex A document is can be uncrypted with: \starttyping status = unencrypt(documentobject,user,owner) \stoptyping Instead of a password \type {nil} can be passed, so there are three possible useful combinations. */ static int pdfelib_unencrypt(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, unencrypt_error); if (p) { size_t u = 0; size_t o = 0; const char* user = NULL; const char* owner = NULL; int top = lua_gettop(L); if (top > 1) { if (lua_type(L,2) == LUA_TSTRING) { user = lua_tolstring(L, 2, &u); } else { /*tex we're not too picky but normally it will be nil or false */ } if (top > 2) { if (lua_type(L,3) == LUA_TSTRING) { owner = lua_tolstring(L, 3, &o); } else { /*tex we're not too picky but normally it will be nil or false */ } } lua_pushinteger(L, (lua_Integer) ppdoc_crypt_pass(p->document, user, u, owner, o)); return 1; } } lua_pushinteger(L, (lua_Integer) PPCRYPT_FAIL); return 1; } /*tex There are a couple of ways to get information about the document: \starttyping n = getsize (documentobject) major, minor = getversion (documentobject) status = getstatus (documentobject) n = getnofobjects (documentobject) n = getnofpages (documentobject) bytes, waste = getmemoryusage(documentobject) \stoptyping */ static int pdfelib_getsize(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_size_error); if (p) { lua_pushinteger(L, (lua_Integer) ppdoc_file_size(p->document)); return 1; } else { return 0; } } static int pdfelib_getversion(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_version_error); if (p) { int minor; int major = ppdoc_version_number(p->document, &minor); lua_pushinteger(L, (lua_Integer) major); lua_pushinteger(L, (lua_Integer) minor); return 2; } else { return 0; } } static int pdfelib_getstatus(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_status_error); if (p) { lua_pushinteger(L, (lua_Integer) ppdoc_crypt_status(p->document)); return 1; } else { return 0; } } static int pdfelib_getnofobjects(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_n_of_objects_error); if (p) { lua_pushinteger(L, (lua_Integer) ppdoc_objects(p->document)); return 1; } else { return 0; } } static int pdfelib_getnofpages(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_n_of_pages_error); if (p) { lua_pushinteger(L, (lua_Integer) ppdoc_page_count(p->document)); return 1; } else { return 0; } } static int pdfelib_getmemoryusage(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_memory_usage_error); if (p) { size_t w = 0; size_t m = ppdoc_memory(p->document, &w); lua_pushinteger(L, (lua_Integer) m); lua_pushinteger(L, (lua_Integer) w); return 2; } else { return 0; } } /* A specific page dictionary can be filtered with the next command. So, there is no need to parse the document page tree (with these \type {kids} arrays). \starttyping dictionaryobject = getpage(documentobject,pagenumber) \stoptyping */ static int pdfelib_aux_pushpage(lua_State *L, ppdoc *d, int page) { if ((page <= 0) || (page > ((int) ppdoc_page_count(d)))) { return 0; } else { ppref *pp = ppdoc_page(d, page); return pdfelib_aux_pushdictionaryonly(L, ppref_obj(pp)->dict); } } static int pdfelib_getpage(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_page_error); if (p) { return pdfelib_aux_pushpage(L, p->document, lmt_checkinteger(L, 2)); } else { return 0; } } static int pdfelib_aux_pushpages(lua_State *L, ppdoc *d) { int i = 1; lua_createtable(L, (int) ppdoc_page_count(d), 0); /* pages[1..n] */ for (ppref *r = ppdoc_first_page(d); r; r = ppdoc_next_page(d), ++i) { pdfelib_aux_pushdictionaryonly(L,ppref_obj(r)->dict); lua_rawseti(L, -2, i); } return 1 ; } static int pdfelib_getpages(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_pages_error); if (p) { return pdfelib_aux_pushpages(L, p->document); } else { return 0; } } /*tex The boundingbox (\type {MediaBox) and similar boxes can be available in a (page) doctionary but also in a parent object. Therefore a helper is available that does the (backtracked) lookup. \starttyping { lx, ly, rx, ry } = getbox(dictionaryobject) \stoptyping */ static int pdfelib_getbox(lua_State *L) { if (lua_gettop(L) > 1 && lua_type(L,2) == LUA_TSTRING) { pdfe_dictionary *p = pdfelib_aux_check_isdictionary(L, 1, get_box_error); if (p) { const char *key = lua_tostring(L, 2); pprect box = { 0, 0, 0, 0 }; pprect *r = ppdict_get_box(p->dictionary, key, &box); if (r) { lua_createtable(L, 4, 0); lua_pushnumber(L, r->lx); lua_rawseti(L, -2, 1); lua_pushnumber(L, r->ly); lua_rawseti(L, -2, 2); lua_pushnumber(L, r->rx); lua_rawseti(L, -2, 3); lua_pushnumber(L, r->ry); lua_rawseti(L, -2, 4); return 1; } } } return 0; } /*tex This one is needed when you use the detailed getters and run into an object reference. The regular getters resolve this automatically. \starttyping [dictionary|array|stream]object = getfromreference(referenceobject) \stoptyping */ static int pdfelib_getfromreference(lua_State *L) { pdfe_reference *r = pdfelib_aux_check_isreference(L, 1, get_from_error); if (r && r->xref) { ppref *rr = ppxref_find(r->xref, (ppuint) r->onum); if (rr) { ppobj *o = ppref_obj(rr); if (o) { lua_pushinteger(L, (lua_Integer) o->type); return 1 + pdfelib_aux_pushvalue(L, o); } } } return 0; } static int pdfelib_getfromobject(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_from_error); if (p) { ppref *rr = ppxref_find(p->document->xref, lua_tointeger(L, 2)); if (rr) { ppobj *o = ppref_obj(rr); if (o) { lua_pushinteger(L, (lua_Integer) o->type); return 1 + pdfelib_aux_pushvalue(L, o); } } } return 0; } static int pdfelib_getobjectrange(lua_State *L) { pdfe_document *p = pdfelib_aux_check_isdocument(L, 1, get_from_error); if (p) { ppref *rr = ppxref_find(p->document->xref, lua_tointeger(L, 2)); if (rr) { lua_pushinteger(L, (lua_Integer) rr->offset); lua_pushinteger(L, (lua_Integer) rr->length); return 2; } } return 0; } /*tex Here are some convenient getters: \starttyping = getstring (array|dict|ref,index|key) = getinteger (array|dict|ref,index|key) = getnumber (array|dict|ref,index|key) = getboolean (array|dict|ref,index|key) = getname (array|dict|ref,index|key) = getdictionary(array|dict|ref,index|key) = getarray (array|dict|ref,index|key) , = getstream (array|dict|ref,index|key) \stoptyping We report issues when reasonable but are silent when it makes sense. We don't error on this because we expect the user code to act reasonable on a return value. */ static int pdfelib_valid_index(lua_State *L, void **p, int *t) { *t = lua_type(L, 2); *p = lua_touserdata(L, 1); lua_settop(L, 2); if (! *p) { switch (*t) { case LUA_TSTRING: tex_normal_warning("pdfe lib", "lua expected"); break; case LUA_TNUMBER: tex_normal_warning("pdfe lib", "lua expected"); break; default: tex_normal_warning("pdfe lib", "invalid arguments"); break; } return 0; } else if (! lua_getmetatable(L, 1)) { tex_normal_warning("pdfe lib", "first argument should be a or "); return 0; } else { return 1; } } static void pdfelib_invalid_index_warning(void) { tex_normal_warning("pdfe lib", "second argument should be integer or string"); } /*tex The direct fetcher returns the result or |NULL| when there is nothing found. The indirect fetcher passes a pointer to the target variable and returns success state. The next two functions used to be macros but as we try to avoid large ones with much code, they are now functions. */ typedef void * (*pp_a_direct) (void *a, size_t index); typedef void * (*pp_d_direct) (void *d, const char *key); typedef int (*pp_a_indirect) (void *a, size_t index, void **value); typedef int (*pp_d_indirect) (void *d, const char *key, void **value); static int pdfelib_get_value_direct(lua_State *L, void **value, pp_d_direct get_d, pp_a_direct get_a) { int t = 0; void *p = NULL; if (pdfelib_valid_index(L, &p, &t)) { switch (t) { case LUA_TSTRING: { const char *key = lua_tostring(L, 2); lua_get_metatablelua(pdfe_dictionary_instance); if (lua_rawequal(L, -1, -2)) { *value = get_d(((pdfe_dictionary *) p)->dictionary, key); return 1; } else { lua_get_metatablelua(pdfe_reference_instance); if (lua_rawequal(L, -1, -3)) { ppref *r = (((pdfe_reference *) p)->xref) ? ppxref_find(((pdfe_reference *) p)->xref, (ppuint) (((pdfe_reference *) p)->onum)) : NULL; \ ppobj *o = (r) ? ppref_obj(r) : NULL; if (o && o->type == PPDICT) { *value = get_d((ppdict *) o->dict, key); return 1; } } } } break; case LUA_TNUMBER: { size_t index = lua_tointeger(L, 2); lua_get_metatablelua(pdfe_array_instance); if (lua_rawequal(L, -1, -2)) { *value = get_a(((pdfe_array *) p)->array, index); return 2; } else { lua_get_metatablelua(pdfe_reference_instance); if (lua_rawequal(L, -1, -3)) { ppref *r = (((pdfe_reference *) p)->xref) ? ppxref_find(((pdfe_reference *) p)->xref, (ppuint) (((pdfe_reference *) p)->onum)) : NULL; \ ppobj *o = (r) ? ppref_obj(r) : NULL; if (o && o->type == PPARRAY) { *value = get_a((pparray *) o->array, index); return 2; } } } } break; default: pdfelib_invalid_index_warning(); break; } } return 0; } static int pdfelib_get_value_indirect(lua_State *L, void **value, pp_d_indirect get_d, pp_a_indirect get_a) { int t = 0; void *p = NULL; if (pdfelib_valid_index(L, &p, &t)) { switch (t) { case LUA_TSTRING: { const char *key = lua_tostring(L, 2); lua_get_metatablelua(pdfe_dictionary_instance); if (lua_rawequal(L, -1, -2)) { return get_d(((pdfe_dictionary *) p)->dictionary, key, value); } else { lua_get_metatablelua(pdfe_reference_instance); if (lua_rawequal(L, -1, -3)) { ppref *r = (((pdfe_reference *) p)->xref) ? ppxref_find(((pdfe_reference *) p)->xref, (ppuint) (((pdfe_reference *) p)->onum)) : NULL; ppobj *o = (r) ? ppref_obj(r) : NULL; if (o && o->type == PPDICT) return get_d(o->dict, key, value); } } } break; case LUA_TNUMBER: { size_t index = lua_tointeger(L, 2); lua_get_metatablelua(pdfe_array_instance); if (lua_rawequal(L, -1, -2)) { return get_a(((pdfe_array *) p)->array, index, value); } else { lua_get_metatablelua(pdfe_reference_instance); if (lua_rawequal(L, -1, -3)) { ppref *r = (((pdfe_reference *) p)->xref) ? ppxref_find(((pdfe_reference *) p)->xref, (ppuint) (((pdfe_reference *) p)->onum)) : NULL; ppobj *o = (r) ? ppref_obj(r) : NULL; if (o && o->type == PPARRAY) return get_a(o->array, index, value); } } } break; default: pdfelib_invalid_index_warning(); break; } } return 0; } static int pdfelib_getstring(lua_State *L) { if (lua_gettop(L) > 1) { ppstring *value = NULL; int okay = 0; int how = 0; if (lua_type(L, 3) == LUA_TBOOLEAN) { if (lua_toboolean(L, 3)) { how = 1; } else { how = 2; } } okay = pdfelib_get_value_direct(L, (void *) &value, (void *) &ppdict_rget_string, (void *) &pparray_rget_string); if (okay && value) { if (how == 1) { value = ppstring_decoded(value); /* we probably always need that */ } /*tex This used to return one value but we made it \LUATEX\ compatible. */ lua_pushlstring(L, ppstring_data(value), ppstring_size(value)); if (how == 2) { lua_pushboolean(L, ppstring_hex(value)); return 2; } else { return 1; } } } return 0; } static int pdfelib_getinteger(lua_State *L) { if (lua_gettop(L) > 1) { ppint value = 0; if (pdfelib_get_value_indirect(L, (void *) &value, (void *) &ppdict_rget_int, (void *) &pparray_rget_int)) { lua_pushinteger(L, (lua_Integer) value); return 1; } } return 0; } static int pdfelib_getnumber(lua_State *L) { if (lua_gettop(L) > 1) { ppnum value = 0; if (pdfelib_get_value_indirect(L, (void *) &value, (void *) &ppdict_rget_num, (void *) &pparray_rget_num)) { lua_pushnumber(L, value); return 1; } } return 0; } static int pdfelib_getboolean(lua_State *L) { if (lua_gettop(L) > 1) { int value = 0; if (pdfelib_get_value_indirect(L, (void *) &value, (void *) &ppdict_rget_bool, (void *) &pparray_rget_bool)) { lua_pushboolean(L, value); return 1; } } return 0; } static int pdfelib_getname(lua_State *L) { if (lua_gettop(L) > 1) { ppname *value = NULL; pdfelib_get_value_direct(L, (void *) &value, (void *) &ppdict_rget_name, (void *) &pparray_rget_name); if (value) { value = ppname_decoded(value) ; lua_pushlstring(L, ppname_data(value), ppname_size(value)); return 1; } } return 0; } static int pdfelib_getdictionary(lua_State *L) { if (lua_gettop(L) > 1) { ppdict *value = NULL; pdfelib_get_value_direct(L, (void *) &value, (void *) &ppdict_rget_dict, (void *) &pparray_rget_dict); if (value) { return pdfelib_aux_pushdictionaryonly(L, value); } } return 0; } static int pdfelib_getarray(lua_State *L) { if (lua_gettop(L) > 1) { pparray *value = NULL; pdfelib_get_value_direct(L, (void *) &value, (void *) &ppdict_rget_array, (void *) &pparray_rget_array); if (value) { return pdfelib_aux_pusharrayonly(L, value); } } return 0; } static int pdfelib_getstream(lua_State *L) { if (lua_gettop(L) > 1) { ppobj *value = NULL; pdfelib_get_value_direct(L, (void *) &value, (void *) &ppdict_rget_obj, (void *) &pparray_rget_obj); if (value && value->type == PPSTREAM) { return pdfelib_aux_pushstreamonly(L, (ppstream *) value->stream); } } return 0; } /*tex The generic pushed that does a similar job as the previous getters acts upon the type. */ static int pdfelib_pushvalue(lua_State *L, ppobj *object) { switch (object->type) { case PPNONE: case PPNULL: lua_pushnil(L); break; case PPBOOL: lua_pushboolean(L, (int) object->integer); break; case PPINT: lua_pushinteger(L, (lua_Integer) object->integer); break; case PPNUM: lua_pushnumber(L, (double) object->number); break; case PPNAME: { ppname *n = ppname_decoded(object->name) ; lua_pushlstring(L, ppname_data(n), ppname_size(n)); } break; case PPSTRING: lua_pushlstring(L, ppstring_data(object->string), ppstring_size(object->string)); break; case PPARRAY: return pdfelib_aux_pusharrayonly(L, object->array); case PPDICT: return pdfelib_aux_pushdictionary(L, object->dict); case PPSTREAM: return pdfelib_aux_pushstream(L, object->stream); case PPREF: pdfelib_aux_pushreference(L, object->ref); break; /*tex We get a funny message in clang about covering all cases. */ /* default: lua_pushnil(L); break; */ } return 1; } /*tex Finally we arrived at the acessors for the userdata objects. The use previously defined helpers. */ static int pdfelib_document_access(lua_State *L) { if (lua_type(L, 2) == LUA_TSTRING) { // pdfe_document *p = (pdfe_document *) lua_touserdata(L, 1); const char *s = lua_tostring(L, 2); if (lua_key_eq(s, catalog) || lua_key_eq(s, Catalog)) { // return pdfelib_aux_pushdictionaryonly(L, ppdoc_catalog(p->document)); return pdfelib_getcatalog(L); } else if (lua_key_eq(s, info) || lua_key_eq(s, Info)) { // return pdfelib_aux_pushdictionaryonly(L, ppdoc_info(p->document)); return pdfelib_getinfo(L); } else if (lua_key_eq(s, trailer) || lua_key_eq(s, Trailer)) { // return pdfelib_aux_pushdictionaryonly(L, ppdoc_trailer(p->document)); return pdfelib_getcatalog(L); } else if (lua_key_eq(s, pages) || lua_key_eq(s, Pages)) { // return pdfelib_aux_pushpages(L, p->document); return pdfelib_getpages(L); } } return 0; } static int pdfelib_array_access(lua_State *L) { if (lua_type(L, 2) == LUA_TNUMBER) { pdfe_array *p = (pdfe_array *) lua_touserdata(L, 1); ppint index = lua_tointeger(L, 2) - 1; ppobj *o = pparray_rget_obj(p->array, index); if (o) { return pdfelib_pushvalue(L, o); } } return 0; } static int pdfelib_dictionary_access(lua_State *L) { pdfe_dictionary *p = (pdfe_dictionary *) lua_touserdata(L, 1); switch (lua_type(L, 2)) { case LUA_TSTRING: { const char *key = lua_tostring(L, 2); ppobj *o = ppdict_rget_obj(p->dictionary, key); if (o) { return pdfelib_pushvalue(L, o); } } break; case LUA_TNUMBER: { ppint index = lua_tointeger(L, 2) - 1; ppobj *o = ppdict_at(p->dictionary, index); if (o) { return pdfelib_pushvalue(L, o); } } break; } return 0; } static int pdfelib_stream_access(lua_State *L) { pdfe_stream *p = (pdfe_stream *) lua_touserdata(L, 1); switch (lua_type(L, 2)) { case LUA_TSTRING: { const char *key = lua_tostring(L, 2); ppobj *o = ppdict_rget_obj(p->stream->dict, key); if (o) { return pdfelib_pushvalue(L, o); } } break; case LUA_TNUMBER: { ppint index = lua_tointeger(L, 2) - 1; ppobj *o = ppdict_at(p->stream->dict, index); if (o) { return pdfelib_pushvalue(L, o); } } break; } return 0; } /*tex The length metamethods are defined last. */ static int pdfelib_array_size(lua_State *L) { pdfe_array *p = (pdfe_array *) lua_touserdata(L, 1); lua_pushinteger(L, (lua_Integer) p->array->size); return 1; } static int pdfelib_dictionary_size(lua_State *L) { pdfe_dictionary *p = (pdfe_dictionary *) lua_touserdata(L, 1); lua_pushinteger(L, (lua_Integer) p->dictionary->size); return 1; } static int pdfelib_stream_size(lua_State *L) { pdfe_stream *p = (pdfe_stream *) lua_touserdata(L, 1); lua_pushinteger(L, (lua_Integer) p->stream->dict->size); return 1; } /*tex We now initialize the main interface. We might add few more informational helpers but this is it. */ static int pdfelib_getencodingvalues(lua_State *L) { lua_createtable(L, 2, 6); lua_set_string_by_index(L, PPSTRING_PLAIN, "plain" ); /* 0 */ lua_set_string_by_index(L, PPSTRING_ENCODED, "encoded"); /* 1 */ lua_set_string_by_index(L, PPSTRING_DECODED, "decoded"); /* 2 */ /* lua_set_string_by_index(L, PPSTRING_EXEC, "exec" ); */ /* 4 */ lua_set_string_by_index(L, PPSTRING_BASE16, "base16" ); /* 8 */ lua_set_string_by_index(L, PPSTRING_BASE85, "base85" ); /* 16 */ lua_set_string_by_index(L, PPSTRING_UTF16BE, "utf16be"); /* 32 */ lua_set_string_by_index(L, PPSTRING_UTF16LE, "utf16le"); /* 64 */ return 1; } static int pdfelib_getstatusvalues(lua_State *L) { lua_createtable(L, 1, 3); lua_set_string_by_index(L, PPCRYPT_PASS, "is protected"); lua_set_string_by_index(L, PPCRYPT_FAIL, "failed to open"); lua_set_string_by_index(L, PPCRYPT_NONE, "not encrypted"); lua_set_string_by_index(L, PPCRYPT_DONE, "is decrypted"); return 1; } static int pdfelib_getfieldtypes(lua_State *L) { lua_createtable(L, 10, 1); lua_set_string_by_index(L, PPNONE, "none"); lua_set_string_by_index(L, PPNULL, "null"); lua_set_string_by_index(L, PPBOOL, "boolean"); lua_set_string_by_index(L, PPINT, "integer"); lua_set_string_by_index(L, PPNUM, "number"); lua_set_string_by_index(L, PPNAME, "name"); lua_set_string_by_index(L, PPSTRING, "string"); lua_set_string_by_index(L, PPARRAY, "array"); lua_set_string_by_index(L, PPDICT, "dictionary"); lua_set_string_by_index(L, PPSTREAM, "stream"); lua_set_string_by_index(L, PPREF, "reference"); return 1; } // PPDOC_ALLOW_PRINT // PPDOC_ALLOW_MODIFY // PPDOC_ALLOW_COPY // PPDOC_ALLOW_ANNOTS // PPDOC_ALLOW_EXTRACT // PPDOC_ALLOW_ASSEMBLY // # define PPDOC_ALLOW_PRINT_HIRES static const struct luaL_Reg pdfelib_function_list[] = { /* management */ { "type", pdfelib_type }, { "open", pdfelib_open }, { "openfile", pdfelib_openfile }, { "new", pdfelib_new }, { "close", pdfelib_close }, { "unencrypt", pdfelib_unencrypt }, { "getencodingvalues", pdfelib_getencodingvalues }, { "getstatusvalues", pdfelib_getstatusvalues }, { "getfieldtypes", pdfelib_getfieldtypes }, /* statistics */ { "getversion", pdfelib_getversion }, { "getstatus", pdfelib_getstatus }, { "getsize", pdfelib_getsize }, { "getnofobjects", pdfelib_getnofobjects }, { "getnofpages", pdfelib_getnofpages }, { "getmemoryusage", pdfelib_getmemoryusage }, /* getters */ { "getcatalog", pdfelib_getcatalog }, { "gettrailer", pdfelib_gettrailer }, { "getinfo", pdfelib_getinfo }, { "getpermissions", pdfelib_getpermissions }, { "getpage", pdfelib_getpage }, { "getpages", pdfelib_getpages }, { "getbox", pdfelib_getbox }, { "getfromreference", pdfelib_getfromreference }, { "getfromdictionary", pdfelib_getfromdictionary }, { "getfromarray", pdfelib_getfromarray }, { "getfromstream", pdfelib_getfromstream }, /* handy too */ { "getfromobject", pdfelib_getfromobject }, { "getobjectrange", pdfelib_getobjectrange }, /* collectors */ { "dictionarytotable", pdfelib_dictionarytotable }, { "arraytotable", pdfelib_arraytotable }, { "pagestotable", pdfelib_pagestotable }, /* more getters */ { "getstring", pdfelib_getstring }, { "getinteger", pdfelib_getinteger }, { "getnumber", pdfelib_getnumber }, { "getboolean", pdfelib_getboolean }, { "getname", pdfelib_getname }, { "getdictionary", pdfelib_getdictionary }, { "getarray", pdfelib_getarray }, { "getstream", pdfelib_getstream }, /* streams */ { "readwholestream", pdfelib_stream_readwhole }, /* not really needed */ { "openstream", pdfelib_stream_open }, { "readfromstream", pdfelib_stream_read }, { "closestream", pdfelib_stream_close }, /* only for me, a test hook */ /* { "test", pdfelib_test }, */ /* done */ { NULL, NULL } }; /*tex The user data metatables are defined as follows. Watch how only the document needs a garbage collector. */ static const struct luaL_Reg pdfelib_instance_metatable[] = { { "__tostring", pdfelib_document_tostring }, { "__gc", pdfelib_document_free }, { "__index", pdfelib_document_access }, { NULL, NULL }, }; static const struct luaL_Reg pdfelib_dictionary_metatable[] = { { "__tostring", pdfelib_dictionary_tostring }, { "__index", pdfelib_dictionary_access }, { "__len", pdfelib_dictionary_size }, { NULL, NULL }, }; static const struct luaL_Reg pdfelib_array_metatable[] = { { "__tostring", pdfelib_array_tostring }, { "__index", pdfelib_array_access }, { "__len", pdfelib_array_size }, { NULL, NULL }, }; static const struct luaL_Reg pdfelib_stream_metatable[] = { { "__tostring", pdfelib_stream_tostring }, { "__index", pdfelib_stream_access }, { "__len", pdfelib_stream_size }, { "__call", pdfelib_stream_readwhole }, { NULL, NULL }, }; static const struct luaL_Reg pdfelib_reference_metatable[] = { { "__tostring", pdfelib_reference_tostring }, { NULL, NULL }, }; /*tex Finally we have arrived at the main initialiser that will be called as part of \LUATEX's initializer. */ /*tex Here we hook in the error handler. */ static void pdfelib_message(const char *message, void *alien) { (void) (alien); tex_normal_warning("pdfe", message); } int luaopen_pdfe(lua_State *L) { /*tex First the four userdata object get their metatables defined. */ luaL_newmetatable(L, PDFE_METATABLE_DICTIONARY); luaL_setfuncs(L, pdfelib_dictionary_metatable, 0); luaL_newmetatable(L, PDFE_METATABLE_ARRAY); luaL_setfuncs(L, pdfelib_array_metatable, 0); luaL_newmetatable(L, PDFE_METATABLE_STREAM); luaL_setfuncs(L, pdfelib_stream_metatable, 0); luaL_newmetatable(L, PDFE_METATABLE_REFERENCE); luaL_setfuncs(L, pdfelib_reference_metatable, 0); /*tex Then comes the main (document) metatable: */ luaL_newmetatable(L, PDFE_METATABLE_INSTANCE); luaL_setfuncs(L, pdfelib_instance_metatable, 0); /*tex Last the library opens up itself to the world. */ lua_newtable(L); luaL_setfuncs(L, pdfelib_function_list, 0); pplog_callback(pdfelib_message, stderr); return 1; } luametatex-2.11.07/source/luarest/lmtsparselib.c0000644000175000017500000002362214760367410020650 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" /*tex This module just provides as a more compact alternative for storing bitsets. I have no clue if it ever will be used but we had this sparse tree mechanism so the overhead in terms of code is neglectable. A possible application is bitmaps. Because we cross the c boundary it's about three times slower when we get/set values than staying in \LUA\ although traversing from |min| to |max| is performance wise the same. We could actually gain a bit when we add more helpers (like |inc| and |dec| or so). So, for the moment I consider this a low impact, and thereby undocumented, fun project. */ # define SPARSE_STACK 8 # define SPARSE_STEP 8 # define SPARSE_BYTES 4 typedef struct sa_tree_object { sa_tree tree; int min; int max; } sa_tree_object; static sa_tree_object *sparselib_aux_check_is_sa_object(lua_State *L, int n) { sa_tree_object *o = (sa_tree_object *) lua_touserdata(L, n); if (o && lua_getmetatable(L, n)) { lua_get_metatablelua(sparse_instance); if (! lua_rawequal(L, -1, -2)) { o = NULL; } lua_pop(L, 2); if (o) { return o; } } tex_normal_warning("sparse lib", "lua expected"); return NULL; } /* bytes=0|1|2|4, default=0|* */ static int sparselib_new(lua_State *L) { int bytes = lmt_optinteger(L, 1, SPARSE_BYTES); int defval = lmt_optinteger(L, 2, 0); sa_tree_item item = { .int_value = defval }; sa_tree_object *o = lua_newuserdatauv(L, sizeof(sa_tree_object), 0); switch (bytes) { case 0: { int d = defval < 0 ? 0 : (defval > 0xF ? 0xF : defval); for (int i = 0; i <= 7; i++) { item.uint_value = set_nibble(item.uint_value,i,d); } break; } case 1: { int d = defval < 0 ? 0 : (defval > 0xFF ? 0xFF : defval); for (int i = 0; i <= 3; i++) { item.uchar_value[i] = (unsigned char) d; } break; } case 2: { int d = defval < 0 ? 0 : (defval > 0xFFFF ? 0xFFFF : defval); for (int i = 0; i <= 1; i++) { item.ushort_value[i] = (unsigned short) d; } break; } case 4: break; default: bytes = SPARSE_BYTES; break; } o->tree = sa_new_tree(user_sparse_identifier, SPARSE_STACK, SPARSE_STEP, bytes, item); o->min = -1; o->max = -1; luaL_setmetatable(L, SPARSE_METATABLE_INSTANCE); return 1; } static int sparselib_gc(lua_State *L) { sa_tree_object *o = (sa_tree_object *) lua_touserdata(L, 1); if (o) { sa_destroy_tree(o->tree); } return 0; } static int sparselib_tostring(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { lua_pushfstring(L, "", o->tree); return 1; } else { return 0; } } /* sparse, index, value */ static int sparselib_set(lua_State *L) /* maybe also globalset as fast one */ { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { quarterword level; int slot = lmt_check_for_level(L, 2, &level, cur_level); int n = lmt_tointeger(L, slot++); if (n >= 0) { int v = lmt_optinteger(L, slot++, 1); if (o->min < 0) { o->min = n; o->max = n; } else if (n < o->min) { o->min = n; } else if (n > o->max) { o->max = n; } sa_set_item_n(o->tree, n, v, (int) level); } } return 0; } /* sparse, index */ static int sparselib_get(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { int n = lmt_tointeger(L, 2); if (n >= 0) { lua_pushinteger(L, sa_get_item_n(o->tree, n)); return 1; } } lua_pushnil(L); return 1; } static int sparselib_min(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { lua_pushinteger(L, o->min >= 0 ? o->min : 0); } else { lua_pushnil(L); } return 1; } static int sparselib_max(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { lua_pushinteger(L, o->max >= 0 ? o->max : 0); } else { lua_pushnil(L); } return 1; } static int sparselib_range(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { lua_pushinteger(L, o->min >= 0 ? o->min : 0); lua_pushinteger(L, o->max >= 0 ? o->max : 0); } else { lua_pushnil(L); lua_pushnil(L); } return 2; } static int sparselib_aux_nil(lua_State *L) { lua_pushnil(L); return 1; } static int sparselib_aux_next(lua_State *L) { sa_tree_object *o = (sa_tree_object *) lua_touserdata(L, lua_upvalueindex(1)); int ind = lmt_tointeger(L, lua_upvalueindex(2)); if (ind <= o->max) { lua_pushinteger(L, (lua_Integer) ind + 1); lua_replace(L, lua_upvalueindex(2)); lua_pushinteger(L, ind); lua_pushinteger(L, sa_get_item_n(o->tree, ind)); return 2; } else { return 0; } } static int sparselib_traverse(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o && o->min >= 0) { lua_settop(L, 1); lua_pushinteger(L, o->min); lua_pushcclosure(L, sparselib_aux_next, 2); } else { lua_pushcclosure(L, sparselib_aux_nil, 0); } return 1; } typedef enum concat_options { concat_as_byte = 0, concat_as_lsb = 1, concat_as_msb = 2, } concat_options; static inline char sparselib_aux_concat(sa_tree t, int i) { int h = LMT_SA_H_PART(i); if (t->tree[h]) { int m = LMT_SA_M_PART(i); if (t->tree[h][m]) { return (char) t->tree[h][m][LMT_SA_L_PART(i)/4].uchar_value[i%4]; } else { return (char) t->dflt.uchar_value[i%4]; } } else { return (char) t->dflt.uchar_value[i%4]; } } static int sparselib_concat(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { sa_tree t = o->tree; if (t->bytes == 1) { /* quick hack: we can add whole slices */ luaL_Buffer buffer; int min = lmt_optinteger(L, 2, o->min); int max = lmt_optinteger(L, 3, o->max); int how = lmt_optinteger(L, 4, concat_as_byte); int siz = 0; if (min < 0) { min = 0; } if (max < min) { max = min; } siz = (size_t) max - (size_t) min + 1; luaL_buffinitsize(L, &buffer, siz); switch (how) { case concat_as_lsb: case concat_as_msb: { int n = 0; char b = 0; luaL_buffinitsize(L, &buffer, (siz / 8) + 1); for (int i = min; i <= max; i++) { char c = sparselib_aux_concat(t, i); if (c) { b |= how == concat_as_lsb ? (1 << n) : (1 << (7 - n)); } if (++n == 8) { luaL_addlstring(&buffer, &b, 1); n = 0; } } if (n) { luaL_addlstring(&buffer, &b, 1); } } break; default: { luaL_buffinitsize(L, &buffer, siz); for (int i = min; i <= max; i++) { char c = sparselib_aux_concat(t, i); luaL_addlstring(&buffer, &c, 1); } } break; } luaL_pushresult(&buffer); return 1; } } lua_pushnil(L); return 1; } static int sparselib_restore(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { /* restore_sa_stack(o->tree, cur_level); */ sa_restore_stack(o->tree, cur_level+1); } return 0; } static int sparselib_wipe(lua_State *L) { sa_tree_object *o = sparselib_aux_check_is_sa_object(L, 1); if (o) { int bytes = o->tree->bytes; sa_tree_item dflt = o->tree->dflt; sa_destroy_tree(o->tree); o->tree = sa_new_tree(user_sparse_identifier, SPARSE_STACK, SPARSE_STEP, bytes, dflt); o->min = -1; o->max = -1; } return 0; } static const struct luaL_Reg sparselib_instance[] = { { "__tostring", sparselib_tostring }, { "__gc", sparselib_gc }, { "__index", sparselib_get }, { "__newindex", sparselib_set }, { NULL, NULL }, }; static const luaL_Reg sparselib_function_list[] = { { "new", sparselib_new }, { "set", sparselib_set }, { "get", sparselib_get }, { "min", sparselib_min }, { "max", sparselib_max }, { "range", sparselib_range }, { "traverse", sparselib_traverse }, { "concat", sparselib_concat }, { "restore", sparselib_restore }, { "wipe", sparselib_wipe }, { NULL, NULL }, }; int luaopen_sparse(lua_State *L) { luaL_newmetatable(L, SPARSE_METATABLE_INSTANCE); luaL_setfuncs(L, sparselib_instance, 0); lua_newtable(L); luaL_setfuncs(L, sparselib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtposit.c0000644000175000017500000004154414760367410020025 0ustar hillehille/* See license.txt in the root of this project. */ /*tex This is an experiment using the posit (unum) implementation from https://gitlab.com/cerlane/SoftPosit#known, which is afaiks the standard. At some point it migh tbe interesting to have this as MetaPost number plugin too, but first I need to figure out some helpers (sin, cos, pow etc). Watch out: this is just a playground for me and a few others. There are \CONTEXT\ interfaces but these are also quite experimental. For instance we might move to 64 bit posits. And how about quires. It all depends on developments in this area. The standard is at: https://posithub.org/docs/posit_standard-2.pdf The reference code can be found here: https://gitlab.com/cerlane/SoftPosit However, the implementation lags behind the standard: no posit64 and no functions except from a few that add, subtract, multiply, divide etc. But I will keep an eye in it. Todo: check if we used the right functions (also in auxposit). */ # include # define POSIT_METATABLE "posit number" static inline posit_t *positlib_push(lua_State *L) { posit p = lua_newuserdatauv(L, sizeof(posit_t), 0); luaL_setmetatable(L, POSIT_METATABLE); return p; } static inline int positlib_new(lua_State *L) { posit p = positlib_push(L); switch (lua_type(L, 1)) { case LUA_TSTRING: *p = double_to_posit(lua_tonumber(L, 1)); break; case LUA_TNUMBER: if (lua_isinteger(L, 1)) { *p = i64_to_posit(lua_tointeger(L, 1)); } else { *p = double_to_posit(lua_tonumber(L, 1)); } break; default: p->v = 0; break; } return 1; } static inline int positlib_toposit(lua_State *L) { if (lua_type(L, 1) == LUA_TNUMBER) { posit_t p = double_to_posit(lua_tonumber(L, 1)); lua_pushinteger(L, p.v); } else { lua_pushinteger(L, 0); } return 1; } static inline int positlib_fromposit(lua_State *L) { if (lua_type(L, 1) == LUA_TNUMBER) { posit_t p = { .v = lmt_roundnumber(L, 1) }; lua_pushnumber(L, posit_to_double(p)); } else { lua_pushinteger(L, 0); } return 1; } /* This is nicer for the user. Beware, we create a userdata object on the stack so we need to replace the original non userdata. */ static posit_t *positlib_get(lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TUSERDATA: return (posit) luaL_checkudata(L, i, POSIT_METATABLE); case LUA_TSTRING: { posit p = positlib_push(L); *p = double_to_posit(lua_tonumber(L, i)); lua_replace(L, i); return p; } case LUA_TNUMBER: { posit p = positlib_push(L); *p = lua_isinteger(L, i) ? integer_to_posit(lua_tointeger(L, i)) : double_to_posit(lua_tonumber(L, i)); lua_replace(L, i); return p; } default: { posit p = positlib_push(L); lua_replace(L, i); return p; } } } static int positlib_tostring(lua_State *L) { posit p = positlib_get(L, 1); double d = posit_to_double(*p); lua_pushnumber(L, d); lua_tostring(L, -1); return 1; } static int positlib_tonumber(lua_State *L) { posit p = positlib_get(L, 1); double d = posit_to_double(*p); lua_pushnumber(L, d); return 1; } static int positlib_copy(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = *a; return 1; } static int positlib_eq(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); lua_pushboolean(L, posit_eq(*a, *b)); return 1; } static int positlib_le(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); lua_pushboolean(L, posit_le(*a, *b)); return 1; } static int positlib_lt(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); lua_pushboolean(L, posit_lt(*a, *b)); return 1; } static int positlib_add(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_add(*a, *b); return 1; } static int positlib_sub(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_sub(*a, *b); return 1; } static int positlib_mul(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_mul(*a, *b); return 1; } static int positlib_div(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_div(*a, *b); return 1; } static int positlib_round(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = posit_round_to_integer(*a); return 1; } static int positlib_rounded(lua_State *L) { posit a = positlib_get(L, 1); lua_pushinteger(L, posit_to_integer(*a)); return 1; } static int positlib_integer(lua_State *L) { posit p = positlib_get(L, 1); lua_pushinteger(L, (lua_Integer) posit_to_i64(*p)); return 1; } static int positlib_NaN(lua_State *L) { posit p = positlib_get(L, 1); lua_pushboolean(L, p->v == (uint32_t) 0x80000000); return 1; } static int positlib_NaR(lua_State *L) { posit p = positlib_get(L, 1); lua_pushboolean(L, posit_is_NaR(p->v)); return 1; } // static int positlib_idiv(lua_State *L) { // return 0; // } // static int positlib_mod(lua_State *L) { // return 0; // } static int positlib_neg(lua_State* L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = posit_neg(*a); return 1; } static int positlib_min(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_lt(*a, *b) ? *a : *b; return 1; } static int positlib_max(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); *p = posit_lt(*a, *b) ? *b : *a; return 1; } static int positlib_pow(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(pow(posit_to_double(*a),posit_to_double(*b))); return 1; } static int positlib_abs(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = posit_abs(*a); return 1; } static int positlib_sqrt(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = posit_sqrt(*a); return 1; } // static int positlib_ln(lua_State *L) // { // posit a = positlib_get(L, 1); // posit p = positlib_push(L); // *p = double_to_posit(ln(posit_to_double(*a))); // return 1; // } static int positlib_log10(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(log10(posit_to_double(*a))); return 1; } static int positlib_log1p(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(log1p(posit_to_double(*a))); return 1; } static int positlib_log2(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(log2(posit_to_double(*a))); return 1; } static int positlib_logb(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(logb(posit_to_double(*a))); return 1; } static int positlib_log(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); if (lua_gettop(L) == 1) { *p = double_to_posit(log(posit_to_double(*a))); } else { posit b = positlib_get(L, 2); double d = posit_to_double(*a); double n = posit_to_double(*b); if (n == 10.0) { n = (lua_Number) log10(d); } else if (n == 2.0) { n = (lua_Number) log2(d); } else { n = (lua_Number) log(d) / (lua_Number) log(n); } *p = double_to_posit(n); } return 1; } static int positlib_exp(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(exp(posit_to_double(*a))); return 1; } static int positlib_exp2(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(exp2(posit_to_double(*a))); return 1; } static int positlib_ceil(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(ceil(posit_to_double(*a))); return 1; } static int positlib_floor(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(floor(posit_to_double(*a))); return 1; } static int positlib_modf(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); posit q = positlib_push(L); double d; *q = double_to_posit(modf(posit_to_double(*a),&d)); *p = double_to_posit(d); return 2; } static int positlib_sin(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(sin(posit_to_double(*a))); return 1; } static int positlib_cos(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(cos(posit_to_double(*a))); return 1; } static int positlib_tan(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(tan(posit_to_double(*a))); return 1; } static int positlib_asin(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(asin(posit_to_double(*a))); return 1; } static int positlib_acos(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(acos(posit_to_double(*a))); return 1; } static int positlib_atan(lua_State *L) { posit a = positlib_get(L, 1); posit p = positlib_push(L); *p = double_to_posit(atan(posit_to_double(*a))); return 1; } static int positlib_rotate(lua_State *L) { posit a = positlib_get(L, 1); lua_Integer n = luaL_optinteger(L, 2, 1); posit p = positlib_push(L); if (n > 0) { p->v = (a->v >> n) | (a->v << (posit_bits - n)); } else if (n < 0) { p->v = (a->v << n) | (a->v >> (posit_bits - n)); } else { p->v = a->v; } return 1; } static int positlib_shift(lua_State *L) { posit a = positlib_get(L, 1); lua_Integer shift = luaL_optinteger(L, 2, 1); posit p = positlib_push(L); if (shift > 0) { p->v = (a->v >> shift) & 0xFFFFFFFF; } else if (shift < 0) { p->v = (a->v << -shift) & 0xFFFFFFFF; } else { p->v = a->v; } return 1; } static int positlib_left(lua_State *L) { posit a = positlib_get(L, 1); lua_Integer shift = luaL_optinteger(L, 2, 1); posit p = positlib_push(L); p->v = (a->v << shift) & 0xFFFFFFFF; return 1; } static int positlib_right(lua_State *L) { posit_t *a = positlib_get(L, 1); lua_Integer shift = - luaL_optinteger(L, 2, 1); posit_t *p = positlib_push(L); p->v = (a->v >> shift) & 0xFFFFFFFF; return 1; } static int positlib_and(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); p->v = (a->v) & (b->v); return 1; } static int positlib_or(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); p->v = (a->v) | (b->v); return 1; } static int positlib_xor(lua_State *L) { posit a = positlib_get(L, 1); posit b = positlib_get(L, 2); posit p = positlib_push(L); p->v = (a->v) ^ (b->v); return 1; } static const luaL_Reg positlib_function_list[] = { /* management */ { "new", positlib_new }, { "copy", positlib_copy }, { "tostring", positlib_tostring }, { "tonumber", positlib_tonumber }, { "integer", positlib_integer }, { "rounded", positlib_rounded }, { "toposit", positlib_toposit }, { "fromposit", positlib_fromposit }, /* operators */ { "__add", positlib_add }, // { "__idiv", positlib_idiv }, { "__div", positlib_div }, // { "__mod", positlib_mod }, { "__eq", positlib_eq }, { "__le", positlib_le }, { "__lt", positlib_lt }, { "__mul", positlib_mul }, { "__sub", positlib_sub }, { "__unm", positlib_neg }, { "__pow", positlib_pow }, { "__bor", positlib_or }, { "__bxor", positlib_xor }, { "__band", positlib_and }, { "__shl", positlib_left }, { "__shr", positlib_right }, /* */ { "NaN", positlib_NaN }, { "NaR", positlib_NaR }, /* */ { "bor", positlib_or }, { "bxor", positlib_xor }, { "band", positlib_and }, { "shift", positlib_shift }, { "rotate", positlib_rotate }, /* */ { "min", positlib_min }, { "max", positlib_max }, { "abs", positlib_abs }, { "conj", positlib_neg }, { "modf", positlib_modf }, /* */ { "acos", positlib_acos }, // { "acosh", positlib_acosh }, { "asin", positlib_asin }, // { "asinh", positlib_asinh }, { "atan", positlib_atan }, // { "atan2", positlib_atan2 }, // { "atanh", positlib_atanh }, // { "cbrt", positlib_cbrt }, { "ceil", positlib_ceil }, // { "copysign", positlib_copysign }, { "cos", positlib_cos }, // { "cosh", positlib_cosh }, // { "deg", positlib_deg }, // { "erf", positlib_erf }, // { "erfc", positlib_erfc }, { "exp", positlib_exp }, { "exp2", positlib_exp2 }, // { "expm1", positlib_expm1 }, // { "fabs", positlib_fabs }, // { "fdim", positlib_fdim }, { "floor", positlib_floor }, // { "fma", positlib_fma }, // { "fmax", positlib_fmax }, // { "fmin", positlib_fmin }, // { "fmod", positlib_fmod }, // { "frexp", positlib_frexp }, // { "gamma", positlib_gamma }, // { "hypot", positlib_hypot }, // { "isfinite", positlib_isfinite }, // { "isinf", positlib_isinf }, // { "isnan", positlib_isnan }, // { "isnormal", positlib_isnormal }, // { "j0", positlib_j0 }, // { "j1", positlib_j1 }, // { "jn", positlib_jn }, // { "ldexp", positlib_ldexp }, // { "lgamma", positlib_lgamma }, { "log", positlib_log }, { "log10", positlib_log10 }, { "log1p", positlib_log1p }, { "log2", positlib_log2 }, { "logb", positlib_logb }, // { "modf", positlib_modf }, // { "nearbyint", positlib_nearbyint }, // { "nextafter", positlib_nextafter }, { "pow", positlib_pow }, // { "rad", positlib_rad }, // { "remainder", positlib_remainder }, // { "remquo", positlib_fremquo }, { "round", positlib_round }, // { "scalbn", positlib_scalbn }, { "sin", positlib_sin }, // { "sinh", positlib_sinh }, { "sqrt", positlib_sqrt }, { "tan", positlib_tan }, // { "tanh", positlib_tanh }, // { "tgamma", positlib_tgamma }, // { "trunc", positlib_trunc }, // { "y0", positlib_y0 }, // { "y1", positlib_y1 }, // { "yn", positlib_yn }, /* */ { NULL, NULL }, }; int luaopen_posit(lua_State *L) { luaL_newmetatable(L, POSIT_METATABLE); luaL_setfuncs(L, positlib_function_list, 0); lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); lua_settable(L, -3); lua_pushliteral(L, "__tostring"); lua_pushliteral(L, "tostring"); lua_gettable(L, -3); lua_settable(L, -3); lua_pushliteral(L, "__name"); lua_pushliteral(L, "posit"); lua_settable(L, -3); return 1; } luametatex-2.11.07/source/luarest/lmtfilelib.c0000644000175000017500000006214714760367410020277 0ustar hillehille/* See license.txt in the root of this project. This is a replacement for lfs, a file system manipulation library from the Kepler project. I started from the lfs.c file from luatex because we need to keep a similar interface. That file mentioned: Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem) The original library offers the following functions: lfs.attributes(filepath [, attributename | attributetable]) lfs.chdir(path) lfs.currentdir() lfs.dir(path) lfs.link(old, new[, symlink]) -- lfs.lock(fh, mode) -- lfs.lock_dir(path) lfs.mkdir(path) lfs.rmdir(path) -- lfs.setmode(filepath, mode) lfs.symlinkattributes(filepath [, attributename]) lfs.touch(filepath [, atime [, mtime]]) -- lfs.unlock(fh) We have additional code in other modules and the code was already adapted a little. In the meantime the code looks quite different. Because \TEX| is multi-platform we try to provide a consistent interface. So, for instance blocksize and inode number are not relevant for us, nor are user and group ids. The lock functions have been removed as they serve no purpose in a \TEX\ system and devices make no sense either. The iterator could be improved. I also fixed some anomalities. Permissions are not useful either. */ # include "../lua/lmtinterface.h" # include "../utilities/auxmemory.h" # include "../utilities/auxfile.h" # ifndef R_OK # define F_OK 0x0 # define W_OK 0x2 # define R_OK 0x4 # endif # define DIR_METATABLE "file.directory" # ifndef _WIN32 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # endif # ifdef _WIN32 # ifndef WINVER # define WINVER 0x0601 # undef _WIN32_WINNT # define _WIN32_WINNT 0x0601 # endif # endif // # ifndef _LARGEFILE64_SOURCE # define _LARGEFILE64_SOURCE 1 // # endif # include # include # include # include # include # include // # ifdef _MSC_VER // # ifndef MAX_PATH // # define MAX_PATH 256 // # endif // # endif # ifdef _WIN32 # include # include # include # include # include # include # include /* Todo MS Windows: By default, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, prepend "\\?\" to the path. For more information, see Naming Files, Paths, and Namespaces. */ # ifdef MAX_PATH # define MY_MAXPATHLEN MAX_PATH # else # define MY_MAXPATHLEN 255 # endif # else /* the next one is sensitive for c99 */ # include # include # include # include # include # include # ifdef MAXPATHLEN # define MY_MAXPATHLEN MAXPATHLEN # else # define MY_MAXPATHLEN 255 # endif # endif /* This has to go to the h file. See luainit.c where it's also needed. */ # ifdef _WIN32 # ifndef S_ISDIR # define S_ISDIR(mode) (mode & _S_IFDIR) # endif # ifndef S_ISREG # define S_ISREG(mode) (mode & _S_IFREG) # endif # ifndef S_ISLNK # define S_ISLNK(mode) (0) # endif # ifndef S_ISSUB # define S_ISSUB(mode) (file_data.attrib & _A_SUBDIR) # endif # define info_struct struct _stati64 # define utime_struct struct __utimbuf64 # define exec_mode_flag _S_IEXEC /* There is a difference between msvc and mingw wrt the daylight saving time correction being applied toy the times. I couldn't figure it out and don't want to waste more time on it. */ /* A windows path should not end with a / so maybe we should check for that and remove it when we have one. Even better is to add a period. size_t l = wcslen(w) - 1; if (w[l] == L'/') { w[l] == L'\0'); } */ typedef struct dir_data { intptr_t handle; int closed; char pattern[MY_MAXPATHLEN+1]; } dir_data; static int get_stat(const char *s, info_struct *i) { LPWSTR w = aux_utf8_to_wide(s); int r = _wstati64(w, i); lmt_memory_free(w); return r; } static int mk_dir(const char *s) { LPWSTR w = aux_utf8_to_wide(s); int r = _wmkdir(w); lmt_memory_free(w); return r; } static int ch_dir(const char *s) { LPWSTR w = aux_utf8_to_wide(s); int r = _wchdir(w); lmt_memory_free(w); return r; } static int rm_dir(const char *s) { LPWSTR w = aux_utf8_to_wide(s); int r = _wrmdir(w); lmt_memory_free(w); return r; } // # if defined(__MINGW64__) || defined(__MINGW32__) // extern int CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags); // # endif static int mk_symlink(const char *t, const char *f) { LPWSTR wt = aux_utf8_to_wide(t); LPWSTR wf = aux_utf8_to_wide(f); int r = CreateSymbolicLinkW((LPCWSTR) t, (LPCWSTR) f, 0x2) != 0; lmt_memory_free(wt); lmt_memory_free(wf); return r; } static int mk_link(const char *t, const char *f) { LPWSTR wt = aux_utf8_to_wide(t); LPWSTR wf = aux_utf8_to_wide(f); int r = CreateSymbolicLinkW((LPCWSTR) t, (LPCWSTR) f, 0x3) != 0; lmt_memory_free(wt); lmt_memory_free(wf); return r; } static int ch_to_exec(const char *s, int n) { LPWSTR w = aux_utf8_to_wide(s); int r = _wchmod(w, n); lmt_memory_free(w); return r; } // # ifdef _MSC_VER // // static int set_utime(const char *s, utime_struct *b) // { // LPWSTR w = utf8_to_wide(s); // HANDLE h = CreateFileW(w, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); // int r = -1; // lmt_memory_free(w); // if (h != INVALID_HANDLE_VALUE) { // r = SetFileTime(h, (const struct _FILETIME *) b, (const struct _FILETIME *) b, (const struct _FILETIME *) b); // CloseHandle(h); // } // return r; // } // // # else static int set_utime(const char *s, utime_struct *b) { LPWSTR w = aux_utf8_to_wide(s); int r = _wutime64(w, b); lmt_memory_free(w); return r; } // # endif # else # define info_struct struct stat # define utime_struct struct utimbuf typedef struct dir_data { DIR *handle; int closed; char pattern[MY_MAXPATHLEN+1]; } dir_data; # define get_stat stat # define mk_dir(p) (mkdir((p), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH)) # define ch_dir chdir # define get_cwd getcwd # define rm_dir rmdir # define mk_symlink(f,t) (symlink(f,t) != -1) # define mk_link(f,t) (link(f,t) != -1) # define ch_to_exec(f,n) (chmod(f,n)) # define exec_mode_flag S_IXUSR | S_IXGRP | S_IXOTH # define set_utime(f,b) utime(f,b) # endif # include # include # include /* This function changes the current directory. success = chdir(name) */ static int filelib_chdir(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { lua_pushboolean(L, ! ch_dir(luaL_checkstring(L, 1))); } else { lua_pushboolean(L, 0); } return 1; } /* This function returns the current directory or false. name = currentdir() */ # ifdef _WIN32 static int filelib_currentdir(lua_State *L) { LPWSTR wpath = NULL; int size = 256; while (1) { LPWSTR temp = lmt_memory_realloc(wpath, size * sizeof(WCHAR)); wpath = temp; if (! wpath) { lua_pushboolean(L, 0); break; } else if (_wgetcwd(wpath, size)) { char *path = aux_utf8_from_wide(wpath); lua_pushstring(L, path); lmt_memory_free(path); break; } else if (errno != ERANGE) { lua_pushboolean(L, 0); break; } else { size *= 2; } } lmt_memory_free(wpath); return 1; } # else static int filelib_currentdir(lua_State *L) { char *path = NULL; size_t size = MY_MAXPATHLEN; while (1) { path = lmt_memory_realloc(path, size); if (! path) { lua_pushboolean(L,0); break; } if (get_cwd(path, size)) { lua_pushstring(L, path); break; } if (errno != ERANGE) { lua_pushboolean(L,0); break; } size *= 2; } lmt_memory_free(path); return 1; } # endif /* This functions create a link: success = link(target,name,[true=symbolic]) success = symlink(target,name) */ static int filelib_link(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING && lua_type(L, 2) == LUA_TSTRING) { const char *oldpath = lua_tostring(L, 1); const char *newpath = lua_tostring(L, 2); lua_pushboolean(L, lua_toboolean(L, 3) ? mk_symlink(oldpath, newpath) : mk_link(oldpath, newpath)); } else { lua_pushboolean(L, 0); } return 1; } static int filelib_symlink(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING && lua_type(L, 2) == LUA_TSTRING) { const char *oldpath = lua_tostring(L, 1); const char *newpath = lua_tostring(L, 2); lua_pushboolean(L, mk_symlink(oldpath, newpath)); } else { lua_pushboolean(L, 0); } return 1; } /* This function creates a directory. success = mkdir(name) */ static int filelib_mkdir(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { lua_pushboolean(L, mk_dir(lua_tostring(L, 1)) != -1); } else { lua_pushboolean(L, 0); } return 1; } /* This function removes a directory (non-recursive). success = mkdir(name) */ static int filelib_rmdir(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { lua_pushboolean(L, rm_dir(luaL_checkstring(L, 1)) != -1); } else { lua_pushboolean(L, 0); } return 1; } /* The directory iterator returns multiple values: for name, mode, size, mtime in dir(path) do ... end For practical reasons we keep the metatable the same. */ # ifdef _WIN32 static inline int push_entry(lua_State *L, struct _wfinddata_t file_data, int details) { char *s = aux_utf8_from_wide(file_data.name); lua_pushstring(L, s); lmt_memory_free(s); if (S_ISSUB(file_data.attrib)) { lua_push_key(directory); } else { lua_push_key(file); } if (details) { lua_pushinteger(L, file_data.size); lua_pushinteger(L, file_data.time_write); return 4; } else { return 2; } } static int filelib_aux_dir_iterator(lua_State *L) { struct _wfinddata_t file_data; int details = 1; dir_data *d = (dir_data *) luaL_checkudata(L, 1, DIR_METATABLE); lua_getiuservalue(L, 1, 1); details = lua_toboolean(L, -1); lua_pop(L, 1); luaL_argcheck(L, d->closed == 0, 1, "closed directory"); if (d->handle == 0L) { /* first entry */ LPWSTR s = aux_utf8_to_wide(d->pattern); if ((d->handle = _wfindfirst(s, &file_data)) == -1L) { d->closed = 1; lmt_memory_free(s); return 0; } else { lmt_memory_free(s); return push_entry(L, file_data, details); } } else if (_wfindnext(d->handle, &file_data) == -1L) { /* no more entries */ /* lmt_memory_free(d->handle); */ /* is done for us */ _findclose(d->handle); d->closed = 1; return 0; } else { /* successive entries */ return push_entry(L, file_data, details); } } static int filelib_aux_dir_close(lua_State *L) { dir_data *d = (dir_data *) lua_touserdata(L, 1); if (!d->closed && d->handle) { _findclose(d->handle); } d->closed = 1; return 0; } static int filelib_dir(lua_State *L) { const char *path = luaL_checkstring(L, 1); int detail = lua_type(L, 2) == LUA_TBOOLEAN ? lua_toboolean(L, 2) : 1; dir_data *d ; lua_pushcfunction(L, filelib_aux_dir_iterator); d = (dir_data *) lua_newuserdatauv(L, sizeof(dir_data), 1); lua_pushboolean(L, detail); lua_setiuservalue(L, -2, 1); luaL_getmetatable(L, DIR_METATABLE); lua_setmetatable(L, -2); d->closed = 0; d->handle = 0L; if (path && strlen(path) > MY_MAXPATHLEN-2) { luaL_error(L, "path too long: %s", path); } else { sprintf(d->pattern, "%s/*", path ? path : "."); /* brrr */ } return 2; } # else /*tex On unix we cannot get the size and time in one go without interference. Also, not all file systems return this field. So eventually we might not do this on unix and revert to the slower method at the lua end when DT_DIR is undefined. After a report from the mailing list about symbolic link issues this is what Taco and I came up with. The |_less| variant is mainly there because in \UNIX\ we then can avoid a costly |stat| when we don't need the details (only a symlink demands such a |stat|). */ static int filelib_aux_dir_iterator(lua_State *L) { struct dirent *entry; dir_data *d; int details = 1; lua_pushcfunction(L, filelib_aux_dir_iterator); d = (dir_data *) luaL_checkudata(L, 1, DIR_METATABLE); lua_getiuservalue(L, 1, 1); details = lua_toboolean(L, -1); lua_pop(L, 1); luaL_argcheck(L, d->closed == 0, 1, "closed directory"); entry = readdir (d->handle); if (entry) { lua_pushstring(L, entry->d_name); # ifdef _DIRENT_HAVE_D_TYPE if (! details) { if (entry->d_type == DT_DIR) { lua_push_key(directory); return 2; } else if (entry->d_type == DT_REG) { lua_push_key(file); return 2; } } # endif /*tex We can have a symlink and/or we need the details an dfor both we need to |get_stat|. */ { info_struct info; char file_path[2*MY_MAXPATHLEN]; snprintf(file_path, 2*MY_MAXPATHLEN, "%s/%s", d->pattern, entry->d_name); if (! get_stat(file_path, &info)) { if (S_ISDIR(info.st_mode)) { lua_push_key(directory); } else if (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode)) { lua_push_key(file); } else { lua_pushnil(L); return 2; } if (details) { lua_pushinteger(L, info.st_size); lua_pushinteger(L, info.st_mtime); return 4; } } else { lua_pushnil(L); } return 2; } } else { closedir(d->handle); d->closed = 1; return 0; } } static int filelib_aux_dir_close(lua_State *L) { dir_data *d = (dir_data *) lua_touserdata(L, 1); if (!d->closed && d->handle) { closedir(d->handle); } d->closed = 1; return 0; } static int filelib_dir(lua_State *L) { const char *path = luaL_checkstring(L, 1); dir_data *d; lua_pushcfunction(L, filelib_aux_dir_iterator); d = (dir_data *) lua_newuserdatauv(L, sizeof(dir_data), 1); lua_pushboolean(L, lua_type(L, 2) == LUA_TBOOLEAN ? lua_toboolean(L, 2) : 1); lua_setiuservalue(L, -2, 1); luaL_getmetatable(L, DIR_METATABLE); lua_setmetatable(L, -2); d->closed = 0; d->handle = opendir(path ? path : "."); if (! d->handle) { luaL_error(L, "cannot open %s: %s", path, strerror(errno)); } snprintf(d->pattern, MY_MAXPATHLEN, "%s", path ? path : "."); return 2; } # endif static int dir_create_meta(lua_State *L) { luaL_newmetatable(L, DIR_METATABLE); lua_newtable(L); lua_pushcfunction(L, filelib_aux_dir_iterator); lua_setfield(L, -2, "next"); lua_pushcfunction(L, filelib_aux_dir_close); lua_setfield(L, -2, "close"); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, filelib_aux_dir_close); lua_setfield(L, -2, "__gc"); return 1; } # define mode2string(mode) \ ((S_ISREG(mode)) ? "file" : ((S_ISDIR(mode)) ? "directory" : ((S_ISLNK(mode)) ? "link" : "other"))) /* We keep this for a while: will change to { r, w, x hash } */ # ifdef _WIN32 static const char *perm2string(unsigned short mode) { static char perms[10] = "---------"; /* persistent change hence the for loop */ for (int i = 0; i < 9; i++) { perms[i]='-'; } if (mode & _S_IREAD) { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; } if (mode & _S_IWRITE) { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; } if (mode & _S_IEXEC) { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; } return perms; } # else static const char *perm2string(mode_t mode) { static char perms[10] = "---------"; /* persistent change hence the for loop */ for (int i = 0; i < 9; i++) { perms[i]='-'; } if (mode & S_IRUSR) perms[0] = 'r'; if (mode & S_IWUSR) perms[1] = 'w'; if (mode & S_IXUSR) perms[2] = 'x'; if (mode & S_IRGRP) perms[3] = 'r'; if (mode & S_IWGRP) perms[4] = 'w'; if (mode & S_IXGRP) perms[5] = 'x'; if (mode & S_IROTH) perms[6] = 'r'; if (mode & S_IWOTH) perms[7] = 'w'; if (mode & S_IXOTH) perms[8] = 'x'; return perms; } # endif /* The next one sets access time and modification values for a file: utime(filename) : current, current utime(filename,acess) : access, access utime(filename,acess,modification) : access, modification */ static int filelib_touch(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { const char *file = luaL_checkstring(L, 1); utime_struct utb, *buf; if (lua_gettop(L) == 1) { buf = NULL; } else { utb.actime = (time_t) luaL_optinteger(L, 2, 0); utb.modtime = (time_t) luaL_optinteger(L, 3, utb.actime); buf = &utb; } lua_pushboolean(L, set_utime(file, buf) != -1); } else { lua_pushboolean(L, 0); } return 1; } static void push_st_mode (lua_State *L, info_struct *info) { lua_pushstring (L, mode2string (info->st_mode)); } /* inode protection mode */ static void push_st_size (lua_State *L, info_struct *info) { lua_pushinteger(L, (lua_Integer) info->st_size); } /* file size, in bytes */ static void push_st_mtime(lua_State *L, info_struct *info) { lua_pushinteger(L, (lua_Integer) info->st_mtime); } /* time of last data modification */ static void push_st_atime(lua_State *L, info_struct *info) { lua_pushinteger(L, (lua_Integer) info->st_atime); } /* time of last access */ static void push_st_ctime(lua_State *L, info_struct *info) { lua_pushinteger(L, (lua_Integer) info->st_ctime); } /* time of last file status change */ static void push_st_perm (lua_State *L, info_struct *info) { lua_pushstring (L, perm2string (info->st_mode)); } /* permissions string */ static void push_st_nlink(lua_State *L, info_struct *info) { lua_pushinteger(L, (lua_Integer) info->st_nlink); } /* number of hard links to the file */ typedef void (*push_info_struct_function) (lua_State *L, info_struct *info); struct file_stat_members { const char *name; push_info_struct_function push; }; static struct file_stat_members members[] = { { "mode", push_st_mode }, { "size", push_st_size }, { "modification", push_st_mtime }, { "access", push_st_atime }, { "change", push_st_ctime }, { "permissions", push_st_perm }, { "nlink", push_st_nlink }, { NULL, NULL }, }; /* Get file or symbolic link information. Returns a table or nil. */ static int filelib_attributes(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { info_struct info; const char *file = luaL_checkstring(L, 1); if (get_stat(file, &info)) { /* bad news */ } else if (lua_isstring(L, 2)) { const char *member = lua_tostring(L, 2); for (int i = 0; members[i].name; i++) { if (strcmp(members[i].name, member) == 0) { members[i].push(L, &info); return 1; } } } else { lua_settop(L, 2); if (! lua_istable(L, 2)) { lua_createtable(L, 0, 6); } for (int i = 0; members[i].name; i++) { lua_pushstring(L, members[i].name); members[i].push(L, &info); lua_rawset(L, -3); } return 1; } } lua_pushnil(L); return 1; } # define is_whatever(L,IS_OK,okay) do { \ if (lua_type(L, 1) == LUA_TSTRING) { \ info_struct info; \ const char *name = lua_tostring(L, 1); \ if (get_stat(name, &info)) { \ lua_pushboolean(L, 0); \ } else { \ lua_pushboolean(L, okay && ! access(name, IS_OK)); \ } \ } else { \ lua_pushboolean(L, 0); \ } \ return 1; \ } while(1) static int filelib_isdir (lua_State *L) { is_whatever(L, F_OK,(S_ISDIR(info.st_mode))); } static int filelib_isreadabledir (lua_State *L) { is_whatever(L, R_OK,(S_ISDIR(info.st_mode))); } static int filelib_iswriteabledir (lua_State *L) { is_whatever(L, W_OK,(S_ISDIR(info.st_mode))); } static int filelib_isfile (lua_State *L) { is_whatever(L, F_OK,(S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))); } static int filelib_isreadablefile (lua_State *L) { is_whatever(L, R_OK,(S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))); } static int filelib_iswriteablefile(lua_State *L) { is_whatever(L, W_OK,(S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))); } static int filelib_setexecutable(lua_State *L) { int ok = 0; if (lua_type(L, 1) == LUA_TSTRING) { info_struct info; const char *name = lua_tostring(L, 1); if (! get_stat(name, &info) && S_ISREG(info.st_mode)) { if (ch_to_exec(name, info.st_mode | exec_mode_flag)) { /* the setting failed */ } else { ok = 1; } } else { /* not a valid file */ } } lua_pushboolean(L, ok); return 1; } /* Push the symlink target to the top of the stack. Assumes the file name is at position 1 of the stack. Returns 1 if successful (with the target on top of the stack), 0 on failure (with stack unchanged, and errno set). link("name") : table link("name","target") : targetname */ static int filelib_symlinktarget(lua_State *L) { const char *file = aux_utf8_readlink(luaL_checkstring(L, 1)); if (file) { lua_pushstring(L, file); } else { lua_pushnil(L); } return 1; } static const struct luaL_Reg filelib_function_list[] = { { "attributes", filelib_attributes }, { "chdir", filelib_chdir }, { "currentdir", filelib_currentdir }, { "dir", filelib_dir }, { "mkdir", filelib_mkdir }, { "rmdir", filelib_rmdir }, { "touch", filelib_touch }, /* */ { "link", filelib_link }, { "symlink", filelib_symlink }, { "setexecutable", filelib_setexecutable }, { "symlinktarget", filelib_symlinktarget }, /* */ { "isdir", filelib_isdir }, { "isfile", filelib_isfile }, { "iswriteabledir", filelib_iswriteabledir }, { "iswriteablefile", filelib_iswriteablefile }, { "isreadabledir", filelib_isreadabledir }, { "isreadablefile", filelib_isreadablefile }, /* */ { NULL, NULL }, }; int luaopen_filelib(lua_State *L) { dir_create_meta(L); luaL_newlib(L,filelib_function_list); return 1; } luametatex-2.11.07/source/luarest/lmtziplib.c0000644000175000017500000001515414760367410020156 0ustar hillehille/* See license.txt in the root of this project. */ # define ZLIB_CONST 1 # include "luametatex.h" /*tex This is a rather minimalistic interface to zlib. We can wrap around it and need some specific file overhead anyway. Also, we never needed all that stream stuff. */ # define ziplib_in_char_ptr const unsigned char * # define ziplib_out_char_ptr unsigned char * # define ziplib_buffer_size 16*1024 static int ziplib_aux_compress( lua_State *L, const char *data, int size, int level, int method, int window, int memory, int strategy, int buffersize ) { int state; z_stream zipstream; zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */ zipstream.next_out = Z_NULL; zipstream.avail_out = 0; zipstream.next_in = Z_NULL; zipstream.avail_in = 0; state = deflateInit2(&zipstream, level, method, window, memory, strategy); if (state == Z_OK) { luaL_Buffer buffer; luaL_buffinit(L, &buffer); zipstream.next_in = (ziplib_in_char_ptr) data; zipstream.avail_in = size; while (1) { zipstream.next_out = (ziplib_out_char_ptr) luaL_prepbuffsize(&buffer, buffersize); zipstream.avail_out = buffersize; state = deflate(&zipstream, Z_FINISH); if (state != Z_OK && state != Z_STREAM_END) { lua_pushnil(L); break; } else { luaL_addsize(&buffer, buffersize - zipstream.avail_out); if (zipstream.avail_out != 0) { luaL_pushresult(&buffer); break; } } } deflateEnd(&zipstream); } else { lua_pushnil(L); } return 1; } static int ziplib_compress(lua_State *L) /* data compresslevel method window memory strategy */ { const char *data = luaL_checkstring(L, 1); int size = (int) lua_rawlen(L, 1); int level = lmt_optinteger(L, 2, Z_DEFAULT_COMPRESSION); int method = lmt_optinteger(L, 3, Z_DEFLATED); int window = lmt_optinteger(L, 4, 15); int memory = lmt_optinteger(L, 5, 8); int strategy = lmt_optinteger(L, 6, Z_DEFAULT_STRATEGY); return ziplib_aux_compress(L, data, size, level, method, window, memory, strategy, ziplib_buffer_size); } static int ziplib_compresssize(lua_State *L) /* data size compresslevel window */ { const char *data = luaL_checkstring(L, 1); int size = (int) lua_rawlen(L, 1); int buffersize = lmt_optinteger(L, 2, ziplib_buffer_size); int level = lmt_optinteger(L, 3, Z_DEFAULT_COMPRESSION); int window = lmt_optinteger(L, 4, 15); /* like decompresssize */ return ziplib_aux_compress(L, data, size, level, Z_DEFLATED, window, 8, Z_DEFAULT_STRATEGY, buffersize); } static int ziplib_decompress(lua_State *L) { const char *data = luaL_checkstring(L, 1); int size = (int) lua_rawlen(L, 1); int window = lmt_optinteger(L, 2, 15); int state; z_stream zipstream; zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */ zipstream.next_out = Z_NULL; zipstream.avail_out = 0; zipstream.next_in = Z_NULL; zipstream.avail_in = 0; state = inflateInit2(&zipstream, window); if (state == Z_OK) { luaL_Buffer buffer; luaL_buffinit(L, &buffer); zipstream.next_in = (ziplib_in_char_ptr) data; zipstream.avail_in = size; while (1) { zipstream.next_out = (ziplib_out_char_ptr) luaL_prepbuffsize(&buffer, ziplib_buffer_size); zipstream.avail_out = ziplib_buffer_size; state = inflate(&zipstream, Z_NO_FLUSH); luaL_addsize(&buffer, ziplib_buffer_size - zipstream.avail_out); if (state == Z_STREAM_END) { luaL_pushresult(&buffer); break; } else if (state != Z_OK) { lua_pushnil(L); break; } else if (zipstream.avail_out == 0) { continue; } else if (zipstream.avail_in == 0) { luaL_pushresult(&buffer); break; } } inflateEnd(&zipstream); } else { lua_pushnil(L); } return 1; } static int ziplib_decompresssize(lua_State *L) { const char *data = luaL_checkstring(L, 1); int size = (int) lua_rawlen(L, 1); int targetsize = lmt_tointeger(L, 2); int window = lmt_optinteger(L, 3, 15); int state; z_stream zipstream; zipstream.zalloc = &lmt_zlib_alloc; /* Z_NULL */ zipstream.zfree = &lmt_zlib_free; /* Z_NULL */ zipstream.next_out = Z_NULL; zipstream.avail_out = 0; zipstream.next_in = Z_NULL; zipstream.avail_in = 0; state = inflateInit2(&zipstream, window); if (state == Z_OK) { luaL_Buffer buffer; zipstream.next_in = (ziplib_in_char_ptr) data; zipstream.avail_in = size; zipstream.next_out = (ziplib_out_char_ptr) luaL_buffinitsize(L, &buffer, (lua_Integer) targetsize + 100); zipstream.avail_out = targetsize + 100; state = inflate(&zipstream, Z_NO_FLUSH); /* maybe Z_FINISH buffer large enough */ if (state != Z_OK && state != Z_STREAM_END) { lua_pushnil(L); } else if (zipstream.avail_in == 0) { luaL_pushresultsize(&buffer, targetsize); } else { lua_pushnil(L); } inflateEnd(&zipstream); } else { lua_pushnil(L); } return 1; } static int ziplib_adler32(lua_State *L) { int checksum = lmt_optinteger(L, 2, 0); size_t buffersize = 0; const char *buffer = lua_tolstring(L, 1, &buffersize); checksum = adler32(checksum, (ziplib_in_char_ptr) buffer, (unsigned int) buffersize); lua_pushinteger(L, checksum); return 1; } static int ziplib_crc32(lua_State *L) { int checksum = lmt_optinteger(L, 2, 0); size_t buffersize = 0; const char *buffer = lua_tolstring(L, 1, &buffersize); checksum = crc32(checksum, (ziplib_in_char_ptr) buffer, (unsigned int) buffersize); lua_pushinteger(L, checksum); return 1; } static struct luaL_Reg ziplib_function_list[] = { { "compress", ziplib_compress }, { "compresssize", ziplib_compresssize }, { "decompress", ziplib_decompress }, { "decompresssize", ziplib_decompresssize }, { "adler32", ziplib_adler32 }, { "crc32", ziplib_crc32 }, { NULL, NULL }, }; int luaopen_xzip(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, ziplib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtdecodelib.c0000644000175000017500000005422114760367410020575 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" /*tex Some png helpers, I could have introduced a userdata for blobs at some point but it's not that useful as string sare also sequences of bytes and lua handles those well. These are interfaces can change any time we like without notice till we like what we have. */ /* t xsize ysize bpp (includes mask) */ static int pnglib_applyfilter(lua_State *L) { size_t size; const char *s = luaL_checklstring(L, 1, &size); int xsize = lmt_tointeger(L, 2); int ysize = lmt_tointeger(L, 3); int slice = lmt_tointeger(L, 4); int len = xsize * slice + 1; /* filter byte */ int n = 0; int m = len - 1; unsigned char *t; if (ysize * len != (int) size) { tex_formatted_warning("png filter", "sizes don't match: %i expected, %i provided", ysize *len, size); return 0; } t = lmt_memory_malloc(size); if (! t) { tex_normal_warning("png filter", "not enough memory"); return 0; } memcpy(t, s, size); for (int i = 0; i < ysize; i++) { switch (t[n]) { case 0 : break; case 1 : for (int j = n + slice + 1; j <= n + m; j++) { t[j] = (unsigned char) (t[j] + t[j-slice]); } break; case 2 : if (i > 0) { for (int j = n + 1; j <= n + m; j++) { t[j] = (unsigned char) (t[j] + t[j-len]); } } break; case 3 : if (i > 0) { for (int j = n + 1; j <= n + slice; j++) { t[j] = (unsigned char) (t[j] + t[j-len]/2); } for (int j = n + slice + 1; j <= n + m; j++) { t[j] = (unsigned char) (t[j] + (t[j-slice] + t[j-len])/2); } } else { for (int j = n + slice + 1; j <= n + m; j++) { t[j] = (unsigned char) (t[j] + t[j-slice]/2); } } break; case 4 : if (i > 0) { for (int j = n + 1; j <= n + slice; j++) { int p = j - len; t[j] = (unsigned char) (t[j] + t[p]); } for (int j = n + slice + 1; j <= n + m; j++) { int p = j - len; unsigned char a = t[j-slice]; unsigned char b = t[p]; unsigned char c = t[p-slice]; int pa = b - c; int pb = a - c; int pc = pa + pb; if (pa < 0) { pa = - pa; } if (pb < 0) { pb = - pb; } if (pc < 0) { pc = - pc; } t[j] = (unsigned char) (t[j] + ((pa <= pb && pa <= pc) ? a : ((pb <= pc) ? b : c))); } } else { /* What to do here? */ /* for (int j = n + slice + 1; j <= n + m; j++) { int p = j - len; unsigned char a = t[j-slice]; unsigned char b = t[p]; unsigned char c = t[p-slice]; int pa = b - c; int pb = a - c; int pc = pa + pb; if (pa < 0) { pa = - pa; } if (pb < 0) { pb = - pb; } if (pc < 0) { pc = - pc; } t[j] = (unsigned char) (t[j] + ((pa <= pb && pa <= pc) ? a : ((pb <= pc) ? b : c))); } */ } break; default: break; } n = n + len; } /* wipe out filter byte */ { int j = 0; /* source */ int m = 0; /* target */ for (int i = 0; i < ysize; i++) { // (void) memcpy(&t[m], &t[j+1], len-1); /* target source size */ (void) memmove(&t[m], &t[j+1], (size_t)len - 1); /* target source size */ j += len; m += len - 1; } lua_pushlstring(L, (char *) t, size-ysize); /* int j = 0; luaL_Buffer b; luaL_buffinit(L, &b); for (int i = 0; i < ysize; i++) { luaL_addlstring(&b, (const char *)&t[j+1], len-1); j += len; } luaL_pushresult(&b); */ } lmt_memory_free(t); return 1; } /* t xsize ysize bpp (includes mask) bytes */ static int pnglib_splitmask(lua_State *L) { size_t size; const char *t = luaL_checklstring(L, 1, &size); int xsize = lmt_tointeger(L, 2); int ysize = lmt_tointeger(L, 3); int bpp = lmt_tointeger(L, 4); /* 1 or 3 */ int bytes = lmt_tointeger(L, 5); /* 1 or 2 */ int slice = (bpp + 1) * bytes; int len = xsize * slice; int blen = bpp * bytes; int mlen = bytes; int nt = 0; int nb = 0; int nm = 0; int bsize = ysize * xsize * blen; int msize = ysize * xsize * mlen; char *b, *m; /* we assume that the filter byte is gone */ if (ysize * len != (int) size) { tex_formatted_warning("png split", "sizes don't match: %i expected, %i provided", ysize * len, size); return 0; } b = lmt_memory_malloc(bsize); m = lmt_memory_malloc(msize); if (! (b && m)) { tex_normal_warning("png split mask", "not enough memory"); return 0; } /* a bit optimized */ switch (blen) { case 1: /* 8 bit gray or indexed graphics */ for (int i = 0; i < ysize * xsize; i++) { b[nb++] = t[nt++]; m[nm++] = t[nt++]; } break; case 3: /* 8 bit rgb graphics */ for (int i = 0; i < ysize * xsize; i++) { /* b[nb++] = t[nt++]; b[nb++] = t[nt++]; b[nb++] = t[nt++]; */ memcpy(&b[nb], &t[nt], 3); nt += 3; nb += 3; m[nm++] = t[nt++]; } break; default: /* everything else */ for (int i = 0; i < ysize * xsize; i++) { memcpy (&b[nb], &t[nt], blen); nt += blen; nb += blen; memcpy (&m[nm], &t[nt], mlen); nt += mlen; nm += mlen; } break; } lua_pushlstring(L, b, bsize); lmt_memory_free(b); lua_pushlstring(L, m, msize); lmt_memory_free(m); return 2; } /* output input xsize ysize slice pass filter */ static int pnglib_interlace(lua_State *L) { int xstarts[] = { 0, 4, 0, 2, 0, 1, 0 }; int ystarts[] = { 0, 0, 4, 0, 2, 0, 1 }; int xsteps[] = { 8, 8, 4, 4, 2, 2, 1 }; int ysteps[] = { 8, 8, 8, 4, 4, 2, 2 }; size_t isize = 0; size_t psize = 0; const char *inp; const char *pre; char *out; int xsize, ysize, xstep, ystep, xstart, ystart, slice, pass, nx, ny; int target, start, step, size; /* dimensions */ xsize = lmt_tointeger(L, 1); ysize = lmt_tointeger(L, 2); slice = lmt_tointeger(L, 3); pass = lmt_tointeger(L, 4); if (pass < 1 || pass > 7) { tex_formatted_warning("png interlace", "bass pass: %i (1..7)", pass); return 0; } pass = pass - 1; /* */ nx = (xsize + xsteps[pass] - xstarts[pass] - 1) / xsteps[pass]; ny = (ysize + ysteps[pass] - ystarts[pass] - 1) / ysteps[pass]; /* */ xstart = xstarts[pass]; xstep = xsteps[pass]; ystart = ystarts[pass]; ystep = ysteps[pass]; /* */ xstep = xstep * slice; xstart = xstart * slice; xsize = xsize * slice; target = ystart * xsize + xstart; ystep = ystep * xsize; /* */ step = nx * xstep; size = ysize * xsize; start = 0; /* */ inp = luaL_checklstring(L, 5, &isize); pre = NULL; out = NULL; if (pass > 0) { pre = luaL_checklstring(L, 6, &psize); if ((int) psize < size) { tex_formatted_warning("png interlace", "output sizes don't match: %i expected, %i provided", psize, size); return 0; } } /* todo: some more checking */ out = lmt_memory_malloc(size); if (out) { if (pass == 0) { memset(out, 0, size); } else { memcpy(out, pre, psize); } } else { tex_normal_warning("png interlace", "not enough memory"); return 0; } switch (slice) { case 1: for (int j = 0; j < ny; j++) { int t = target + j * ystep; for (int i = t; i < t + step; i += xstep) { out[i] = inp[start]; start = start + slice; } } break; case 2: for (int j = 0; j < ny; j++) { int t = target + j * ystep; for (int i = t; i < t + step; i += xstep) { out[i] = inp[start]; out[i+1] = inp[start+1]; start = start + slice; } } break; case 3: for (int j = 0; j < ny; j++) { int t = target + j * ystep; for (int i = t; i < t + step;i += xstep) { out[i] = inp[start]; out[i+1] = inp[start+1]; out[i+2] = inp[start+2]; start = start + slice; } } break; default: for (int j = 0; j < ny; j++) { int t = target + j * ystep; for (int i = t; i < t + step; i += xstep) { memcpy(&out[i], &inp[start], slice); start = start + slice; } } break; } lua_pushlstring(L, out, size); lmt_memory_free(out); return 1; } /* content xsize ysize parts run factor */ # define extract1(a,b) ((a >> b) & 0x01) # define extract2(a,b) ((a >> b) & 0x03) # define extract4(a,b) ((a >> b) & 0x0F) static int pnglib_expand(lua_State *L) { size_t tsize; const char *t = luaL_checklstring(L, 1, &tsize); char *o = NULL; int n = 0; int k = 0; int xsize = lmt_tointeger(L, 2); int ysize = lmt_tointeger(L, 3); int parts = lmt_tointeger(L, 4); int xline = lmt_tointeger(L, 5); int factor = lua_toboolean(L, 6); int size = ysize * xsize; int extra = ysize * xsize + 16; /* probably a few bytes is enough */ if (xline*ysize > (int) tsize) { tex_formatted_warning("png expand","expand sizes don't match: %i expected, %i provided",size,parts*tsize); return 0; } o = lmt_memory_malloc(extra); if (! o) { tex_normal_warning ("png expand", "not enough memory"); return 0; } /* we could use on branch and factor variables ,, saves code, costs cycles */ if (factor) { switch (parts) { case 4: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; o[k++] = (unsigned char) extract4 (v, 4) * 0x11; o[k++] = (unsigned char) extract4 (v, 0) * 0x11; } n = n + xline; } break; case 2: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; for (int b = 6; b >= 0; b -= 2) { o[k++] = (unsigned char) extract2 (v, b) * 0x55; } } n = n + xline; } break; default: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; for (int b = 7; b >= 0; b--) { o[k++] = (unsigned char) extract1 (v, b) * 0xFF; } } n = n + xline; } break; } } else { switch (parts) { case 4: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; o[k++] = (unsigned char) extract4 (v, 4); o[k++] = (unsigned char) extract4 (v, 0); } n = n + xline; } break; case 2: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; for (int b = 6; b >= 0; b -= 2) { o[k++] = (unsigned char) extract2 (v, b); } } n = n + xline; } break; default: for (int i = 0; i < ysize; i++) { k = i * xsize; for (int j = n; j < n + xline; j++) { unsigned char v = t[j]; for (int b = 7; b >= 0; b--) { o[k++] = (unsigned char) extract1 (v, b); } } n = n + xline; } break; } } lua_pushlstring(L, o, size); lmt_memory_free(o); return 1; } /*tex This is just a quick and dirty experiment. We need to satisfy pdf standards and simple graphics can be converted this way. Maybe add some more control over calculating |k|. */ static int pnglib_tocmyk(lua_State *L) { size_t tsize; const char *t = luaL_checklstring(L, 1, &tsize); int depth = lmt_optinteger(L, 2, 0); if ((tsize > 0) && (depth == 8 || depth == 16)) { size_t osize = 0; char *o = NULL; if (depth == 8) { o = lmt_memory_malloc(4 * (tfloor(tsize/3) + 1)); /*tex Plus some slack. */ } else { o = lmt_memory_malloc(8 * (tfloor(tsize/6) + 1)); /*tex Plus some slack. */ } if (! o) { tex_normal_warning ("png tocmyk", "not enough memory"); return 0; } else if (depth == 8) { /* for (size_t i = 0; i < tsize; i += 3) { o[osize++] = (const char) (0xFF - t[i]); o[osize++] = (const char) (0xFF - t[i + 1]); o[osize++] = (const char) (0xFF - t[i + 2]); o[osize++] = '\0'; } */ for (size_t i = 0; i < tsize; ) { o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = '\0'; } } else { /*tex This needs checking! */ /* for (size_t i = 0; i < tsize; i += 6) { o[osize++] = (const char) (0xFF - t[i]); o[osize++] = (const char) (0xFF - t[i + 1]); o[osize++] = (const char) (0xFF - t[i + 2]); o[osize++] = (const char) (0xFF - t[i + 3]); o[osize++] = (const char) (0xFF - t[i + 4]); o[osize++] = (const char) (0xFF - t[i + 5]); o[osize++] = '\0'; o[osize++] = '\0'; } */ for (size_t i = 0; i < tsize; ) { o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = (const char) (0xFF - t[i++]); o[osize++] = '\0'; o[osize++] = '\0'; } } lua_pushlstring(L, o, osize-1); lmt_memory_free(o); } else { lua_pushnil(L); } return 1; } /*tex Make a mask for a pallete. */ static int pnglib_tomask(lua_State *L) /* for palette */ { size_t tsize, ssize; const char *t = luaL_checklstring(L, 1, &tsize); const char *s = luaL_checklstring(L, 2, &ssize); size_t xsize = lmt_tosizet(L, 3); size_t ysize = lmt_tosizet(L, 4); int colordepth = lmt_tointeger(L, 5); size_t osize = xsize * ysize; if (osize == tsize) { char *o = lmt_memory_malloc(osize); char *v = lmt_memory_calloc(256,1); size_t len = xsize * colordepth / 8; // ceil size_t k = 0; memset(v, 0xFF, 256); memcpy(v, s, ssize > 256 ? 256 : ssize); for (size_t i = 0; i < ysize; i++) { size_t f = i * len; size_t l = f + len; switch (colordepth) { case 8: for (size_t j = f; j < l; j++) { int c = t[j]; o[k++] = (unsigned char) v[c]; } break; case 4: for (size_t j = f; j < l; j++) { int c = t[j]; o[k++] = (unsigned char) v[(c >> 4) & 0x0F]; o[k++] = (unsigned char) v[(c >> 0) & 0x0F]; } break; case 2: for (size_t j = f; j < l; j++) { int c = t[j]; o[k++] = (unsigned char) v[(c >> 6) & 0x03]; o[k++] = (unsigned char) v[(c >> 4) & 0x03]; o[k++] = (unsigned char) v[(c >> 2) & 0x03]; o[k++] = (unsigned char) v[(c >> 0) & 0x03]; } break; default: for (size_t j = f; j < l; j++) { int c = t[j]; o[k++] = (unsigned char) v[(c >> 7) & 0x01]; o[k++] = (unsigned char) v[(c >> 6) & 0x01]; o[k++] = (unsigned char) v[(c >> 5) & 0x01]; o[k++] = (unsigned char) v[(c >> 4) & 0x01]; o[k++] = (unsigned char) v[(c >> 3) & 0x01]; o[k++] = (unsigned char) v[(c >> 2) & 0x01]; o[k++] = (unsigned char) v[(c >> 1) & 0x01]; o[k++] = (unsigned char) v[(c >> 0) & 0x01]; } break; } } lua_pushlstring(L, o, osize); lmt_memory_free(o); } else { lua_pushnil(L); } return 1; } static int pnglib_makemask(lua_State *L) /* for palette */ { size_t size; const char *content = luaL_checklstring(L, 1, &size); char mapping[256] = { 0x00 }; char *mask = lmt_memory_malloc(size); switch (lua_type(L, 2)) { case LUA_TNUMBER: { int n = (int) lua_tointeger(L, 2); n = n < 0 ? 0 : n > 255 ? 255 : n; for (int i = 0; i <= n; i++) { mapping[i] = 0xFF; } } break; case LUA_TTABLE: { int n = (int) lua_rawlen(L, 2); for (int i = 1; i <= n; i++) { if (lua_rawgeti(L, 2, i) == LUA_TTABLE) { int m = (int) lua_rawlen(L, -1); if (m == 3) { int b, e, v; lua_rawgeti(L, -1, 1); lua_rawgeti(L, -2, 2); lua_rawgeti(L, -3, 3); b = (int) lua_tointeger(L, -3); e = (int) lua_tointeger(L, -2); v = (int) lua_tointeger(L, -1); b = b < 0 ? 0 : b > 255 ? 255 : b; e = e < 0 ? 0 : e > 255 ? 255 : e; v = v < 0 ? 0 : v > 255 ? 255 : v; for (int i = b; i <= e; i++) { mapping[i] = (char) v; } lua_pop(L, 3); } } lua_pop(L, 1); } } case LUA_TSTRING: { size_t l = 0; const char *m = luaL_checklstring(L, 1, &l); memcpy(mask, m, l > size ? size : l); } break; default: break; } for (int i = 0; i < (int) size; i++) { mask[i] = (unsigned char) mapping[(unsigned char) content[i]]; } lua_pushlstring(L, mask, size); lua_pushlstring(L, mapping, 256); lmt_memory_free(mask); return 2; } static const struct luaL_Reg pngdecodelib_function_list[] = { { "applyfilter", pnglib_applyfilter }, { "splitmask", pnglib_splitmask }, { "interlace", pnglib_interlace }, { "expand", pnglib_expand }, { "tocmyk", pnglib_tocmyk }, { "tomask", pnglib_tomask }, { "makemask", pnglib_makemask }, { NULL, NULL }, }; int luaopen_pngdecode(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, pngdecodelib_function_list, 0); return 1; } /*tex This is a placeholder! */ static const struct luaL_Reg pdfdecodelib_function_list[] = { { NULL, NULL } }; int luaopen_pdfdecode(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, pdfdecodelib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtaeslib.c0000644000175000017500000000653714760367410020131 0ustar hillehille/* See license.txt in the root of this project. */ # include "luametatex.h" # include // AES_HAS_IV AES_INLINE_IV AES_CONTINUE AES_NULL_PADDING static const uint8_t nulliv[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; typedef size_t aes_coder ( const void *input, size_t length, void *output, const void *key, size_t keylength, const void *iv, int flags ); /* data key [block] [inline] [padding] */ /* key : 16 24 32 */ /* random_bytes is taken from pplib */ static int aeslib_aux_code(lua_State *L, aes_coder code) { size_t inputlength = 0; const char *input = lua_tolstring(L, 1, &inputlength); if (inputlength) { size_t keylength = 0; const char *key = lua_tolstring(L, 2, &keylength); if (keylength == 16 || keylength == 24 || keylength == 32) { luaL_Buffer buffer; /* always */ int flags = 0; /* the same length as input plus optional 16 from iv */ char *output = NULL; size_t outputlength = 0; /* this is optional, iv get copied in aes */ const uint8_t *iv = NULL; switch (lua_type(L, 3)) { case LUA_TSTRING: { size_t ivlength = 0; iv = (const uint8_t *) lua_tolstring(L, 3, &ivlength); if (ivlength != 16) { iv = nulliv; } break; } case LUA_TBOOLEAN: if (lua_toboolean(L, 3)) { uint8_t randiv[16]; random_bytes(randiv, 16); iv = (const uint8_t *) randiv; break; } // fall through default: iv = nulliv; } if (lua_toboolean(L, 4)) { flags |= AES_INLINE_IV; } if (! lua_toboolean(L, 5)) { flags |= AES_NULL_PADDING; } /* always multiples of 16 and we might have the iv too */ output = luaL_buffinitsize(L, &buffer, inputlength + 32); outputlength = code(input, inputlength, output, key, keylength, iv, flags); if (outputlength) { luaL_pushresultsize(&buffer, outputlength); return 1; } } else { luaL_error(L, "aeslib: key of length 16, 24 or 32 expected"); } } lua_pushnil(L); return 1; } static int aeslib_encode(lua_State *L) { return aeslib_aux_code(L, &aes_encode_data); } static int aeslib_decode(lua_State *L) { return aeslib_aux_code(L, &aes_decode_data); } static int aeslib_random(lua_State *L) { uint8_t iv[32]; int n = (int) luaL_optinteger(L, 1, 16); if (n > 32) { n = 32; } random_bytes(iv, n); lua_pushlstring(L, (const char *) iv, n); return 1; } static struct luaL_Reg aeslib_function_list[] = { /*tex We started out with this: */ { "encode", aeslib_encode }, { "decode", aeslib_decode }, { "random", aeslib_random }, { NULL, NULL }, }; int luaopen_aes(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, aeslib_function_list, 0); return 1; } luametatex-2.11.07/source/luarest/lmtpotrace.c0000644000175000017500000004676314760367410020334 0ustar hillehille/* See license.txt in the root of this project. */ /*tex We use the library part of potrace: 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. For the following code we used some of: A simple and self-contained demo of the potracelib API. that comes with the file set. We can use a minimal set of files because potrace has been very table for a while! In case one wonders why we need it: one can think of vectorizing logos, old fonts, shapes of any kind that can be used anywhere in \CONTEXT\ and \METAFUN. Just stay tuned. */ # include # include # include # define POTRACE_METATABLE "potracer" #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) /* also internal frees */ static potrace_bitmap_t *new_bitmap(int w, int h) { int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS; potrace_bitmap_t *bitmap = (potrace_bitmap_t *) lmt_memory_malloc(sizeof(potrace_bitmap_t)); if (! bitmap) { return NULL; } bitmap->w = w; bitmap->h = h; bitmap->dy = dy; bitmap->map = (potrace_word *) lmt_memory_calloc(h, dy * BM_WORDSIZE); if (! bitmap->map) { lmt_memory_free(bitmap); return NULL; } else { return bitmap; } } static void free_bitmap(potrace_bitmap_t *bitmap) { if (bitmap) { lmt_memory_free(bitmap->map); } lmt_memory_free(bitmap); } static const char* const policies[] = { "black", "white", "left", "right", "minority", "majority", "random", NULL }; typedef struct potracer { potrace_state_t *state; potrace_param_t *parameters; potrace_bitmap_t *bitmap; const char *bytes; int width; int height; int swap; int nx; int ny; unsigned char value; unsigned char match; /* 7 bytes padding */ } potracer; static potracer *potracelib_aux_maybe_ispotracer(lua_State *L) { return (potracer *) luaL_checkudata(L, 1, POTRACE_METATABLE); } static unsigned char lmt_tochar(lua_State *L, int index) { const char *s = lua_tostring(L, index); return s ? (unsigned char) s[0] : '0'; } static void potracelib_aux_get_parameters(lua_State *L, int index, potracer *p) { if (lua_type(L, index) == LUA_TTABLE) { if (lua_getfield(L, index, "size") == LUA_TNUMBER ) { p->parameters->turdsize = lmt_tointeger(L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "threshold") == LUA_TNUMBER ) { p->parameters->alphamax = lua_tonumber (L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "tolerance") == LUA_TNUMBER ) { p->parameters->opttolerance = lua_tonumber (L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "optimize") == LUA_TBOOLEAN) { p->parameters->opticurve = lua_toboolean(L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "value") == LUA_TSTRING ) { p->value = lmt_tochar (L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "negate") == LUA_TBOOLEAN) { p->match = ! lua_toboolean(L, -1); } lua_pop(L, 1); if (lua_getfield(L, index, "policy") == LUA_TSTRING ) { p->parameters->turnpolicy = luaL_checkoption(L, -1, "minority", policies); } lua_pop(L, 1); } } static void potracelib_get_bitmap(potracer *p, unsigned char match) { /* Kind of suboptimal but it might change anyway so let the compiler worry about it. */ const char *bytes = p->bytes; if (bytes) { unsigned char c = p->value; if (p->swap) { if (p->nx != 1 || p->ny != 1) { /* maybe a 3x3 fast one */ for (int x = 0; x < p->width; x += p->nx) { int bp = (p->height/p->ny) * (x/p->nx); /* yet unchecked */ for (int y = 0; y < p->height; y += p->ny) { unsigned char b = (unsigned char) bytes[bp++] == c ? 1 : 0; if (b) { int dy = p->height - y - 1; for (int xn = 0; xn < p->nx; xn++) { for (int yn = 0; yn < p->ny; yn++) { BM_PUT(p->bitmap, x + xn, dy - yn, b); } } } } } } else { /* fast one */ for (int x = 0; x < p->width; x++) { int bp = p->height * x; int dy = p->height - 1; for (int y = 0; y < p->height; y++) { unsigned char b = (unsigned char) bytes[bp++] == c ? 1 : 0; if (b) { BM_PUT(p->bitmap, x, dy - y, b); } } } } } else { if (p->nx != 1 || p->ny != 1) { /* maybe a 3x3 fast one and also when one of them is 1 */ for (int y = 0; y < p->height; y += p->ny) { int bp = (p->width/p->nx) * (y/p->ny); for (int x = 0; x < p->width; x += p->nx) { unsigned char b = (unsigned char) bytes[bp++] == c ? 1 : 0; if (b) { int dy = p->height - y - 1; for (int xn = 0; xn < p->nx; xn++) { for (int yn = 0; yn < p->ny; yn++) { BM_PUT(p->bitmap, x + xn, dy - yn, b); } } } } } } else { /* fast one */ for (int y = 0; y < p->height; y++) { int bp = p->width * y; int dy = p->height - y - 1; for (int x = 0; x < p->width; x++) { unsigned char b = ((unsigned char) bytes[bp++] == c ? 1 : 0) == match; if (b) { BM_PUT(p->bitmap, x, dy, b); } } } } } } } # define max_explode 4 static int potracelib_getnewfields(lua_State *L) { lua_createtable(L, 0, 8); lua_set_string_by_key(L, "bytes", "string"); lua_set_string_by_key(L, "width", "integer"); lua_set_string_by_key(L, "height", "integer"); lua_set_string_by_key(L, "nx", "integer"); lua_set_string_by_key(L, "ny", "integer"); lua_set_string_by_key(L, "swap", "boolean"); lua_set_string_by_key(L, "value", "character"); lua_set_string_by_key(L, "negate", "boolean"); return 1; } static int potracelib_getprocessfields(lua_State *L) { lua_createtable(L, 0, 8); lua_set_string_by_key(L, "size", "integer"); lua_set_string_by_key(L, "threshold", "number"); lua_set_string_by_key(L, "tolerance", "number"); lua_set_string_by_key(L, "optimize", "boolean"); lua_set_string_by_key(L, "value", "characetr"); lua_set_string_by_key(L, "negate", "boolean"); lua_set_string_by_key(L, "policy", "string"); return 1; } static int potracelib_getpolicyvalues(lua_State *L) { lua_createtable(L, 7, 0); lua_set_string_by_index(L, 1, "black"); lua_set_string_by_index(L, 2, "white"); lua_set_string_by_index(L, 3, "left"); lua_set_string_by_index(L, 4, "right"); lua_set_string_by_index(L, 5, "minority"); lua_set_string_by_index(L, 6, "majority"); lua_set_string_by_index(L, 7, "random"); return 1; } static int potracelib_new(lua_State *L) { if (lua_type(L, 1) == LUA_TTABLE) { potracer p = { .state = NULL, .parameters = NULL, .bitmap = NULL, .bytes = NULL, .height = 0, .width = 0, .swap = 0, .nx = 1, .ny = 1, .value = '1', .match = 1, }; size_t length = 0; if (lua_getfield(L, 1, "bytes") == LUA_TSTRING) { p.bytes = lua_tolstring(L, -1, &length); } lua_pop(L, 1); if (lua_getfield(L, 1, "width") == LUA_TNUMBER) { p.width = lmt_tointeger(L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "height") == LUA_TNUMBER) { p.height = lmt_tointeger(L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "nx") == LUA_TNUMBER) { p.nx = lmt_tointeger(L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "ny") == LUA_TNUMBER) { p.ny = lmt_tointeger(L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "swap") == LUA_TBOOLEAN) { p.swap = lua_toboolean(L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "value") == LUA_TSTRING) { p.value = lmt_tochar (L, -1); } lua_pop(L, 1); if (lua_getfield(L, 1, "negate") == LUA_TBOOLEAN) { p.match = ! lua_toboolean(L, -1); } lua_pop(L, 1); if (! p.bytes) { return 0; } if ((size_t) (p.width * p.height) > length) { return 0; } p.nx = p.nx < 1 ? 1 : (p.nx > max_explode ? max_explode : p.nx); p.ny = p.ny < 1 ? 1 : (p.ny > max_explode ? max_explode : p.ny); p.width *= p.nx; p.height *= p.ny; if (p.swap) { int tmp = p.width; p.width = p.height; p.height = tmp; tmp = p.nx; p.nx = p.ny; p.ny = tmp; } p.parameters = potrace_param_default(); if (! p.parameters) { free_bitmap(p.bitmap); return 0; } potracelib_aux_get_parameters(L, 1, &p); lua_pop(L, 1); { potracer *pp = (potracer *) lua_newuserdatauv(L, sizeof(potracer), 0); if (pp) { *pp = p; luaL_getmetatable(L, POTRACE_METATABLE); lua_setmetatable(L, -2); return 1; } } } return 0; } static void potracelib_aux_free(potracer *p) { if (p) { if (p->state) { potrace_state_free(p->state); p->state = NULL; } if (p->parameters) { potrace_param_free(p->parameters); p->parameters = NULL; } if (p->bitmap) { free_bitmap(p->bitmap); p->bitmap = NULL; } } } static int potracelib_free(lua_State *L) { potracelib_aux_free(potracelib_aux_maybe_ispotracer(L)); return 0; } static int aux_potracelib_entries(potracer *p) { potrace_path_t *entry = p->state->plist; int entries = 0; while (entry) { entries++; entry = entry->next; } return entries; } /* maybe also - last*/ static potrace_path_t *aux_potrace_goto_first(potracer *p, int nofentries, int *first, int *last, int *used) { potrace_path_t *entry = p->state->plist; if (*first && ! *last) { *last = nofentries; } if (*last < 0) { *last = nofentries - *last; if (*last < 0) { *last = 1; } } if (*first <= 0) { *first = 1; } if ((! *last) || (*last > nofentries)) { *last = nofentries; } if (*first > *last) { *first = *last; } for (int i = 1; i < *first; i++) { entry = entry->next; } *used = *last - *first + 1; return entry; } static int potracelib_totable_normal(lua_State *L, potracer *p, int first, int last) { int entries = 0; int nofentries = aux_potracelib_entries(p); int used = nofentries; potrace_path_t *entry = aux_potrace_goto_first(p, nofentries, &first, &last, &used); lua_createtable(L, used, 0); while (entry) { int segments = 0; int n = entry->curve.n; int m = n + 1; int *tag = entry->curve.tag; // int sign = (entry->next == NULL || entry->next->sign == '+') ? 1 : 0; int sign = (entry->sign == '+') ? 1 : 0; potrace_dpoint_t (*c)[3] =entry->curve.c; lua_createtable(L, m, sign ? 2 : 1); if (sign) { lua_push_boolean_at_key(L, sign, 1); } lua_push_integer_at_key(L, index, first + entries); /* for tracing when we select */ lua_createtable(L, 2, 0); lua_push_number_at_index(L, 1, c[n-1][2].x); lua_push_number_at_index(L, 2, c[n-1][2].y); lua_rawseti(L, -2, ++segments); for (int i = 0; i < n; i++) { switch (tag[i]) { case POTRACE_CORNER: lua_createtable(L, 2, 0); lua_push_number_at_index(L, 1, c[i][1].x); lua_push_number_at_index(L, 2, c[i][1].y); lua_rawseti(L, -2, ++segments); lua_createtable(L, 2, 0); lua_push_number_at_index(L, 1, c[i][2].x); lua_push_number_at_index(L, 2, c[i][2].y); lua_rawseti(L, -2, ++segments); break; case POTRACE_CURVETO: lua_createtable(L, 6, 0); lua_push_number_at_index(L, 1, c[i][2].x); lua_push_number_at_index(L, 2, c[i][2].y); lua_push_number_at_index(L, 3, c[i][0].x); lua_push_number_at_index(L, 4, c[i][0].y); lua_push_number_at_index(L, 5, c[i][1].x); lua_push_number_at_index(L, 6, c[i][1].y); lua_rawseti(L, -2, ++segments); break; } } lua_rawseti(L, -2, ++entries); if (first + entries > last) { break; } else { entry = entry->next; } } return 1; } /*tex These intermediate state tables are based on the debugger in |backend_eps.c|. There is no need to speed them up. */ static int potracelib_totable_debug(lua_State *L, potracer *p, int first, int last) { int entries = 0; int nofentries = aux_potracelib_entries(p); int used = nofentries; potrace_path_t *entry = aux_potrace_goto_first(p, nofentries, &first, &last, &used); lua_createtable(L, used, 0); while (entry) { point_t *pt = entry->priv->pt; int segments = 0; // int sign = (entry->next == NULL || entry->next->sign == '+') ? 1 : 0; int sign = (entry->sign == '+') ? 1 : 0; lua_newtable(L); if (sign) { lua_push_boolean_at_key(L, sign, 1); } lua_push_integer_at_key(L, index, first + entries); /* for tracing when we select */ /*tex We can get a redundant point 0 when we go left and come back right on the same line, but we can simplify that at the receiving end. */ if (sign) { point_t cur = pt[entry->priv->len - 1]; point_t prev = cur; lua_push_integer_at_index(L, ++segments, cur.x); lua_push_integer_at_index(L, ++segments, cur.y); for (int i = 0; i < entry->priv->len; i++) { if (pt[i].x != cur.x && pt[i].y != cur.y) { cur = prev; lua_push_integer_at_index(L, ++segments, cur.x); lua_push_integer_at_index(L, ++segments, cur.y); } prev = pt[i]; } lua_push_integer_at_index(L, ++segments, pt[entry->priv->len-1].x); lua_push_integer_at_index(L, ++segments, pt[entry->priv->len-1].y); } else { point_t cur = pt[0]; point_t prev = cur; lua_push_integer_at_index(L, ++segments, cur.x); lua_push_integer_at_index(L, ++segments, cur.y); for (int i = entry->priv->len - 1; i >= 0; i--) { if (pt[i].x != cur.x && pt[i].y != cur.y) { cur = prev; lua_push_integer_at_index(L, ++segments, cur.x); lua_push_integer_at_index(L, ++segments, cur.y); } prev = pt[i]; } lua_push_integer_at_index(L, ++segments, pt[0].x); lua_push_integer_at_index(L, ++segments, pt[0].y); } lua_rawseti(L, -2, ++entries); if (first + entries > last) { break; } else { entry = entry->next; } } return 1; } static int potracelib_totable(lua_State *L) { int debug = lua_toboolean(L, 2); int first = lmt_optinteger(L, 3, 0); int last = lmt_optinteger(L, 4, first); lua_settop(L, 1); { potracer *p = potracelib_aux_maybe_ispotracer(L); if (p) { return debug ? potracelib_totable_debug(L, p, first, last) : potracelib_totable_normal(L, p, first, last); } else { return 0; } } } static int potracelib_process(lua_State *L) { potracer *p = potracelib_aux_maybe_ispotracer(L); if (p) { potracelib_aux_get_parameters(L, 2, p); if (p->bitmap) { free_bitmap(p->bitmap); } p->bitmap = new_bitmap(p->width, p->height); if (p->bitmap) { potracelib_get_bitmap(p, p->match); p->state = potrace_trace(p->parameters, p->bitmap); if (p->state && p->state->status == POTRACE_STATUS_OK) { lua_pushboolean(L, 1); return 1; } } } lua_pushboolean(L, 0); return 1; } static int potracelib_tostring(lua_State * L) { potracer *p = potracelib_aux_maybe_ispotracer(L); if (p) { (void) lua_pushfstring(L, "", p); } else { lua_pushnil(L); } return 1; } /*tex We keep the interface simple because we glue via \LUA\ and have to connect to \METAPOST\ too. */ static const struct luaL_Reg potracelib_instance_metatable[] = { { "__tostring", potracelib_tostring }, { "__gc", potracelib_free }, { NULL, NULL }, }; static const luaL_Reg potracelib_function_list[] = { { "new", potracelib_new }, { "free", potracelib_free }, { "process", potracelib_process }, { "totable", potracelib_totable }, { "getnewfields", potracelib_getnewfields }, { "getprocessfields", potracelib_getprocessfields }, { "getpolicyvalues", potracelib_getpolicyvalues }, { NULL, NULL }, }; int luaopen_potrace(lua_State *L) { luaL_newmetatable(L, POTRACE_METATABLE); luaL_setfuncs(L, potracelib_instance_metatable, 0); lua_newtable(L); luaL_setfuncs(L, potracelib_function_list, 0); return 1; }luametatex-2.11.07/source/luarest/lmtmd5lib.c0000644000175000017500000000445714760367410020045 0ustar hillehille/* See license.txt in the root of this project. */ # include # include # include # include # include "luametatex.h" /* # define wrapped_md5(message,len,output) md5_digest(message,len,(unsigned char *) output, 0) static int md5lib_sum(lua_State *L) { char buf[16]; size_t l; const char *message = luaL_checklstring(L, 1, &l); wrapped_md5(message, l, buf); lua_pushlstring(L, buf, 16L); return 1; } static int md5lib_hex(lua_State *L) { char buf[16]; char hex[32]; iof *inp = iof_filter_string_reader(buf, 16); iof *out = iof_filter_string_writer(hex, 32); size_t l; const char *message = luaL_checklstring(L, 1, &l); wrapped_md5(message, l, buf); base16_encode_lc(inp, out); lua_pushlstring(L, hex, iof_size(out)); iof_free(inp); iof_free(out); return 1; } static int md5lib_HEX(lua_State *L) { char buf[16]; char hex[32]; iof *inp = iof_filter_string_reader(buf, 16); iof *out = iof_filter_string_writer(hex, 32); size_t l; const char *message = luaL_checklstring(L, 1, &l); wrapped_md5(message, l, buf); base16_encode_uc(inp, out); lua_pushlstring(L, hex, iof_size(out)); iof_free(inp); iof_free(out); return 1; } */ # define MD5_RESULT_LENGTH (MD5_STRING_LENGTH-1) # define md5_body(MD5_LENGTH, CONVERSION, RESULT_LENGTH) do { \ if (lua_type(L, 1) == LUA_TSTRING) { \ uint8_t result[MD5_LENGTH]; \ size_t size = 0; \ const char *data = lua_tolstring(L, 1, &size); \ md5_digest(data, size, (unsigned char *) result, CONVERSION); \ lua_pushlstring(L, (const char *) result, RESULT_LENGTH); \ return 1; \ } \ return 0; \ } while (0) static int md5lib_sum(lua_State *L) { md5_body(MD5_DIGEST_LENGTH, MD5_BYTES, MD5_DIGEST_LENGTH); } static int md5lib_hex(lua_State *L) { md5_body(MD5_STRING_LENGTH, MD5_LCHEX, MD5_RESULT_LENGTH); } static int md5lib_HEX(lua_State *L) { md5_body(MD5_STRING_LENGTH, MD5_UCHEX, MD5_RESULT_LENGTH); } static struct luaL_Reg md5lib_function_list[] = { { "sum", md5lib_sum }, { "hex", md5lib_hex }, { "HEX", md5lib_HEX }, { NULL, NULL }, }; int luaopen_md5(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, md5lib_function_list, 0); return 1; } luametatex-2.11.07/source/libraries/0000755000175000017500000000000014760367405016277 5ustar hillehilleluametatex-2.11.07/source/libraries/softposit/0000755000175000017500000000000014760367405020331 5ustar hillehilleluametatex-2.11.07/source/libraries/softposit/build/0000755000175000017500000000000014760367405021430 5ustar hillehilleluametatex-2.11.07/source/libraries/softposit/build/Linux-x86_64-GCC/0000755000175000017500000000000015030577462024052 5ustar hillehilleluametatex-2.11.07/source/libraries/softposit/build/Linux-x86_64-GCC/Makefile0000644000175000017500000001450214760367405025517 0ustar hillehille#============================================================================ # #This C source file is part of the SoftPosit Posit Arithmetic Package #by S. H. Leong (Cerlane). # #Copyright 2017, 2018 A*STAR. All rights reserved. # #This C source file was based on SoftFloat IEEE Floating-Point Arithmetic #Package, Release 3d, by John R. Hauser. # # # Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the # University of California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR ?= ../../source PYTHON_DIR ?= ../../python SPECIALIZE_TYPE ?= 8086-SSE COMPILER ?= gcc SOFTPOSIT_OPTS ?= \ -DINLINE_LEVEL=5 #\ -DSOFTPOSIT_QUAD -lquadmath COMPILE_PYTHON = \ $(COMPILER) -fPIC -c $(PYTHON_DIR)/softposit_python_wrap.c \ -I/usr/include/python \ -I$(SOURCE_DIR)/include -I. COMPILE_PYTHON3 = \ $(COMPILER) -fPIC -c $(PYTHON_DIR)/softposit_python_wrap.c \ -I/usr/include/python3 \ -I$(SOURCE_DIR)/include -I. LINK_PYTHON = \ ld -shared *.o -o $(PYTHON_DIR)/_softposit.so ifeq ($(OS),Windows_NT) DELETE = del /Q /F else DELETE = rm -f endif C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include OPTIMISATION = -O2 #-march=core-avx2 COMPILE_C = \ $(COMPILER) -c -Werror-implicit-function-declaration -DSOFTPOSIT_FAST_INT64 \ $(SOFTPOSIT_OPTS) $(C_INCLUDES) $(OPTIMISATION) \ -o $@ MAKELIB = ar crs $@ MAKESLIB = $(COMPILER) -shared $^ OBJ = .o LIB = .a SLIB = .so .PHONY: all all: softposit$(LIB) quad: SOFTPOSIT_OPTS+= -DSOFTPOSIT_QUAD -lquadmath quad: all python2: SOFTPOSIT_OPTS+= -fPIC python2: all $(COMPILE_PYTHON) $(LINK_PYTHON) python3: SOFTPOSIT_OPTS+= -fPIC python3: all $(COMPILE_PYTHON3) $(LINK_PYTHON) julia: SOFTPOSIT_OPTS+= -fPIC julia: softposit$(SLIB) OBJS_PRIMITIVES = OBJS_SPECIALIZE = OBJS_OTHERS = \ s_addMagsP8$(OBJ) \ s_subMagsP8$(OBJ) \ s_mulAddP8$(OBJ) \ p8_add$(OBJ) \ p8_sub$(OBJ) \ p8_mul$(OBJ) \ p8_div$(OBJ) \ p8_sqrt$(OBJ) \ p8_to_p16$(OBJ) \ p8_to_p32$(OBJ) \ p8_to_pX2$(OBJ) \ p8_to_i32$(OBJ) \ p8_to_i64$(OBJ) \ p8_to_ui32$(OBJ) \ p8_to_ui64$(OBJ) \ p8_roundToInt$(OBJ) \ p8_mulAdd$(OBJ) \ p8_eq$(OBJ) \ p8_le$(OBJ) \ p8_lt$(OBJ) \ quire8_fdp_add$(OBJ) \ quire8_fdp_sub$(OBJ) \ ui32_to_p8$(OBJ) \ ui64_to_p8$(OBJ) \ i32_to_p8$(OBJ) \ i64_to_p8$(OBJ) \ s_addMagsP16$(OBJ) \ s_subMagsP16$(OBJ) \ s_mulAddP16$(OBJ) \ p16_to_ui32$(OBJ) \ p16_to_ui64$(OBJ) \ p16_to_i32$(OBJ) \ p16_to_i64$(OBJ) \ p16_to_p8$(OBJ) \ p16_to_p32$(OBJ) \ p16_to_pX2$(OBJ) \ p16_roundToInt$(OBJ) \ p16_add$(OBJ) \ p16_sub$(OBJ) \ p16_mul$(OBJ) \ p16_mulAdd$(OBJ) \ p16_div$(OBJ) \ p16_eq$(OBJ) \ p16_le$(OBJ) \ p16_lt$(OBJ) \ p16_sqrt$(OBJ) \ quire16_fdp_add$(OBJ) \ quire16_fdp_sub$(OBJ) \ quire_helper$(OBJ) \ ui32_to_p16$(OBJ) \ ui64_to_p16$(OBJ) \ i32_to_p16$(OBJ) \ i64_to_p16$(OBJ) \ s_addMagsP32$(OBJ) \ s_subMagsP32$(OBJ) \ s_mulAddP32$(OBJ) \ p32_to_ui32$(OBJ) \ p32_to_ui64$(OBJ) \ p32_to_i32$(OBJ) \ p32_to_i64$(OBJ) \ p32_to_p8$(OBJ) \ p32_to_p16$(OBJ) \ p32_to_pX2$(OBJ) \ p32_roundToInt$(OBJ) \ p32_add$(OBJ) \ p32_sub$(OBJ) \ p32_mul$(OBJ) \ p32_mulAdd$(OBJ) \ p32_div$(OBJ) \ p32_eq$(OBJ) \ p32_le$(OBJ) \ p32_lt$(OBJ) \ p32_sqrt$(OBJ) \ quire32_fdp_add$(OBJ) \ quire32_fdp_sub$(OBJ) \ ui32_to_p32$(OBJ) \ ui64_to_p32$(OBJ) \ i32_to_p32$(OBJ) \ i64_to_p32$(OBJ) \ s_approxRecipSqrt_1Ks$(OBJ) \ c_convertDecToPosit8$(OBJ) \ c_convertPosit8ToDec$(OBJ) \ c_convertDecToPosit16$(OBJ) \ c_convertPosit16ToDec$(OBJ) \ c_convertQuire8ToPosit8$(OBJ) \ c_convertQuire16ToPosit16$(OBJ) \ c_convertQuire32ToPosit32$(OBJ) \ c_convertDecToPosit32$(OBJ) \ c_convertPosit32ToDec$(OBJ) \ c_int$(OBJ) \ s_addMagsPX2$(OBJ) \ s_subMagsPX2$(OBJ) \ s_mulAddPX2$(OBJ) \ pX2_add$(OBJ) \ pX2_sub$(OBJ) \ pX2_mul$(OBJ) \ pX2_div$(OBJ) \ pX2_mulAdd$(OBJ) \ pX2_roundToInt$(OBJ) \ pX2_sqrt$(OBJ) \ pX2_eq$(OBJ) \ pX2_le$(OBJ) \ pX2_lt$(OBJ) \ ui32_to_pX2$(OBJ) \ ui64_to_pX2$(OBJ) \ i32_to_pX2$(OBJ) \ i64_to_pX2$(OBJ) \ c_convertQuireX2ToPositX2$(OBJ) OBJS_ALL := $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softposit_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softposit.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softposit$(LIB): $(OBJS_ALL) $(MAKELIB) $^ softposit$(SLIB): $(OBJS_ALL) $(MAKESLIB) -o $@ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softposit_python_wrap.o softposit$(LIB) softposit$(SLIB) luametatex-2.11.07/source/libraries/softposit/build/Linux-x86_64-GCC/platform.h0000644000175000017500000000432214760367405026053 0ustar hillehille /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3d, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else #define INLINE extern inline #endif luametatex-2.11.07/source/libraries/softposit/LICENSE0000644000175000017500000000327214760367405021342 0ustar hillehilleBSD 3-Clause License This is part of the SoftPosit Posit Arithmetic Package by S. H. Leong (Cerlane). Copyright 2017 2018 A*STAR. All rights reserved. Many of the C source files design were based on SoftFloat IEEE Floating-Point Arithmetic Package, Release 3d, by John R. Hauser. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. luametatex-2.11.07/source/libraries/softposit/source/0000755000175000017500000000000014760367405021631 5ustar hillehilleluametatex-2.11.07/source/libraries/softposit/source/s_mulAddPX2.c0000644000175000017500000001747114760367405024071 0ustar hillehille /*============================================================================ This C source file is part of the SoftPosit Posit Arithmetic Package by S. H. Leong (Cerlane). Copyright 2017, 2018 A*STAR. All rights reserved. This C source file was based on SoftFloat IEEE Floating-Point Arithmetic Package, Release 3d, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include "platform.h" #include "internals.h" //a*b+c posit_2_t softposit_mulAddPX2( uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast32_t op, int x ){ union ui32_pX2 uZ; int regZ; uint_fast32_t fracA, fracZ, regime, tmp; bool signA, signB, signC, signZ, regSA, regSB, regSC, regSZ, bitNPlusOne=0, bitsMore=0, rcarry; int_fast32_t expA, expC, expZ; int_fast16_t kA=0, kC=0, kZ=0, shiftRight; uint_fast64_t frac64C, frac64Z; if (x<2 || x>32){ uZ.ui = 0x80000000; return uZ.p; } //NaR if ( uiA==0x80000000 || uiB==0x80000000 || uiC==0x80000000 ){ uZ.ui = 0x80000000; return uZ.p; } else if (uiA==0 || uiB==0){ if (op == softposit_mulAdd_subC) uZ.ui = -uiC; else uZ.ui = uiC; return uZ.p; } signA = signP32UI( uiA ); signB = signP32UI( uiB ); signC = signP32UI( uiC );//^ (op == softposit_mulAdd_subC); signZ = signA ^ signB;// ^ (op == softposit_mulAdd_subProd); if(signA) uiA = (-uiA & 0xFFFFFFFF); if(signB) uiB = (-uiB & 0xFFFFFFFF); if(signC) uiC = (-uiC & 0xFFFFFFFF); regSA = signregP32UI(uiA); regSB = signregP32UI(uiB); regSC = signregP32UI(uiC); if (x==2){ uZ.ui = (regSA®SB) ? (0x40000000) : (0x0); if (signZ){// i.e. negative prod if (signC){ uZ.ui |= uiC; uZ.ui = -uZ.ui & 0xFFFFFFFF; } else{//prod is negative if (uiC==uZ.ui) uZ.ui = 0; else uZ.ui =(uZ.ui>0)?( 0xC0000000):(0x40000000); } } else{ //prod : same sign signZ=0 if (signC){ if (uiC==uZ.ui) uZ.ui = 0; else uZ.ui = (uZ.ui>0) ? (0x40000000) : (0xC0000000); } else{//C is positive uZ.ui |= uiC; } } return uZ.p; } else{ tmp = (uiA<<2)&0xFFFFFFFF; if (regSA){ while (tmp>>31){ kA++; tmp= (tmp<<1) & 0xFFFFFFFF; } } else{ kA=-1; while (!(tmp>>31)){ kA--; tmp= (tmp<<1) & 0xFFFFFFFF; } tmp&=0x7FFFFFFF; } expA = tmp>>29; //to get 2 bits fracA = ((tmp<<2) | 0x80000000) & 0xFFFFFFFF; tmp = (uiB<<2)&0xFFFFFFFF; if (regSB){ while (tmp>>31){ kA++; tmp= (tmp<<1) & 0xFFFFFFFF; } } else{ kA--; while (!(tmp>>31)){ kA--; tmp= (tmp<<1) & 0xFFFFFFFF; } tmp&=0x7FFFFFFF; } expA += tmp>>29; frac64Z = (uint_fast64_t) fracA * (((tmp<<2) | 0x80000000) & 0xFFFFFFFF); if (expA>3){ kA++; expA&=0x3; // -=4 } rcarry = frac64Z>>63;//1st bit of frac64Z if (rcarry){ expA++; if (expA>3){ kA ++; expA&=0x3; } frac64Z>>=1; } if (uiC!=0){ tmp = (uiC<<2)&0xFFFFFFFF; if (regSC){ while (tmp>>31){ kC++; tmp= (tmp<<1) & 0xFFFFFFFF; } } else{ kC=-1; while (!(tmp>>31)){ kC--; tmp= (tmp<<1) & 0xFFFFFFFF; } tmp&=0x7FFFFFFF; } expC = tmp>>29; //to get 2 bits frac64C = (((tmp<<1) | 0x40000000ULL) & 0x7FFFFFFFULL)<<32; shiftRight = ((kA-kC)<<2) + (expA-expC); if (shiftRight<0){ // |uiC| > |Prod| if (shiftRight<=-63){ bitsMore = 1; frac64Z = 0; //set bitsMore to one? } else if ((frac64Z<<(64+shiftRight))!=0) bitsMore = 1; if (signZ==signC) frac64Z = frac64C + (frac64Z>>-shiftRight); else {//different signs frac64Z = frac64C - (frac64Z>>-shiftRight) ; signZ=signC; if (bitsMore) frac64Z-=1; } kZ = kC; expZ = expC; } else if (shiftRight>0){// |uiC| < |Prod| //if (frac32C&((1<=63) { bitsMore = 1; frac64C = 0; } else if ((frac64C<<(64-shiftRight))!=0) bitsMore = 1; if (signZ==signC) frac64Z = frac64Z + (frac64C>>shiftRight); else{ frac64Z = frac64Z - (frac64C>>shiftRight); if (bitsMore) frac64Z-=1; } kZ = kA; expZ = expA; } else{ if(frac64C==frac64Z && signZ!=signC ){ //check if same number uZ.ui = 0; return uZ.p; } else{ if (signZ==signC) frac64Z += frac64C; else{ if (frac64Z>63; //first left bit if(rcarry){ expZ++; if (expZ>3){ kZ++; expZ&=0x3; } frac64Z=(frac64Z>>1)&0x7FFFFFFFFFFFFFFF; } else { //for subtract cases if (frac64Z!=0){ while((frac64Z>>59)==0){ kZ--; frac64Z<<=4; } while((frac64Z>>62)==0){ expZ--; frac64Z<<=1; if (expZ<0){ kZ--; expZ=3; } } } } } else{ kZ = kA; expZ=expA; } if(kZ<0){ regZ = -kZ; regSZ = 0; regime = 0x40000000>>regZ; } else{ regZ = kZ+1; regSZ=1; regime = 0x7FFFFFFF - (0x7FFFFFFF>>regZ); } if(regZ>(x-2)){ //max or min pos. exp and frac does not matter. uZ.ui=(regSZ) ? (0x7FFFFFFF & ((int32_t)0x80000000>>(x-1)) ): (0x1 << (32-x)); } else{ if (regZ