diff options
author | Hans Hagen <pragma@wxs.nl> | 2020-02-16 10:59:14 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2020-02-16 10:59:14 +0100 |
commit | 8e11d447440b44990432ac838953a8cde4ef914f (patch) | |
tree | f30b2ff2d8a10f1aff50e1522d968618a97f067c | |
parent | 43fc66771a0c9d27cc0b7fe7a69392ea313bd0ca (diff) | |
download | context-8e11d447440b44990432ac838953a8cde4ef914f.tar.gz |
2020-02-11 16:39:00
74 files changed, 3653 insertions, 2550 deletions
diff --git a/doc/context/documents/general/manuals/ecmascript-mkiv.pdf b/doc/context/documents/general/manuals/ecmascript-mkiv.pdf Binary files differnew file mode 100644 index 000000000..308dfda78 --- /dev/null +++ b/doc/context/documents/general/manuals/ecmascript-mkiv.pdf diff --git a/doc/context/documents/general/manuals/libraries-mkiv.pdf b/doc/context/documents/general/manuals/libraries-mkiv.pdf Binary files differindex 9b13d7414..aa18726e3 100644 --- a/doc/context/documents/general/manuals/libraries-mkiv.pdf +++ b/doc/context/documents/general/manuals/libraries-mkiv.pdf diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf Binary files differindex b128ed767..766e9a709 100644 --- a/doc/context/documents/general/manuals/luametatex.pdf +++ b/doc/context/documents/general/manuals/luametatex.pdf diff --git a/doc/context/documents/general/manuals/sql-mkiv.pdf b/doc/context/documents/general/manuals/sql-mkiv.pdf Binary files differindex 09e63bcc8..57f6a9dc0 100644 --- a/doc/context/documents/general/manuals/sql-mkiv.pdf +++ b/doc/context/documents/general/manuals/sql-mkiv.pdf diff --git a/doc/context/sources/general/manuals/libraries/ecmascript-mkiv.tex b/doc/context/sources/general/manuals/libraries/ecmascript-mkiv.tex new file mode 100644 index 000000000..70350142c --- /dev/null +++ b/doc/context/sources/general/manuals/libraries/ecmascript-mkiv.tex @@ -0,0 +1,420 @@ +% language=us + +% author : Hans Hagen +% copyright : PRAGMA ADE & ConTeXt Development Team +% license : Creative Commons Attribution ShareAlike 4.0 International +% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions +% origin : the ConTeXt distribution +% +% comment : Because this manual is distributed with TeX distributions it comes with a rather +% liberal license. We try to adapt these documents to upgrades in the (sub)systems +% that they describe. Using parts of the content otherwise can therefore conflict +% with existing functionality and we cannot be held responsible for that. Many of +% the manuals contain characteristic graphics and personal notes or examples that +% make no sense when used out-of-context. +% +% comment : Some chapters might have been published in TugBoat, the NTG Maps, the ConTeXt +% Group journal or otherwise. Thanks to the editors for corrections. Also thanks +% to users for testing, feedback and corrections. + +% for now: + +\usemodule[article-basic] +\usemodule[abbreviations-smallcaps] +\usemodule[scite] +\usemodule[ecmascript] + +\definecolor + [maincolor] + [r=.4] + +\definecolor + [extracolor] + [g=.4] + +\setupbodyfont + [11pt] + +\setuptype + [color=maincolor] + +% \setuptyping +% [color=maincolor] + +\definefontsynonym + [TitlePageMono] + [file:lmmonoproplt10-bold*default] + +\setuphead + [color=maincolor] + +\usesymbols + [cc] + +\setupinteraction + [hidden] + +\loadfontgoodies[lm] + +\startdocument + [metadata:author=Hans Hagen, + metadata:title=ecmascript in context lmtx, + author=Hans Hagen, + affiliation=PRAGMA ADE, + location=Hasselt NL, + title=\ECNASCRIPT\ in \CONTEXT\ \LMTX, + support=www.contextgarden.net, + website=www.pragma-ade.nl] + +\starttext + +\startMPpage + StartPage; + + fill Page withcolor "darkgreen"; + + draw textext.lrt("\tttf ECMA") + xsized .75PaperWidth + shifted ulcorner (Page enlarged -15mm ) + withcolor "white" ; + + draw textext.llft("\tttf SCRIPT") + xsized .50PaperWidth + shifted urcorner (Page enlarged -15mm topenlarged -70mm) + withcolor "white" ; + + draw textext.llft("\tttf in context lmtx") + xsized .50PaperWidth + shifted urcorner (Page enlarged -15mm topenlarged -110mm) + withcolor "white" ; + + draw textext.llft("\tttf using the optional mujs library") + xsized .50PaperWidth + shifted lrcorner (Page enlarged -15mm bottomenlarged -10mm) + withcolor "white" ; + + StopPage; +\stopMPpage + +\dontcomplain + +% \startsubject[title=Contents] +% +% \placelist[section][alternative=a] +% +% \stopsubject + +\startsection[title=Introduction] + +When you use \CONTEXT\ there is no way around noticing that the \LUA\ scripting +language is an important component. When we progressed from \LUATEX\ to +\LUAMETATEX\ did didn't change. I like that language a lot! Among the reasons are +that it reminds me of \PASCAL, that it's clean, fast and well maintained. There +is no huge infrastructure involved, nor lots of libraries and therefore +dependencies. + +So why bother about another scripting language? One can argue that because of the +World Wide Web one should use \JAVASCRIPT\ instead. It might make sense from a +commercial point of view, or for some promotional reason. But that all makes +little sense in the perspective of \CONTEXT. But, when I was playing with +optional libraries in \LUAMETATEX, + +On and off I wonder if I should spend some time on adding \LUA\ annotation +support to the open source mupdf viewer. After all, it has some basic +\JAVASCRIPT\ support (but currently not enough, for instance it lacks control +over widgets and layers and such.) However, then I noticed that the related +\JAVASCRIPT\ code was actually an independent library and looking at the header +files it looked quite a bit like the \LUA\ interface. So, just for the fun of it I +gave it a try, and when doing so, I realized that having support for \JAVASCRIPT, +or actually \ECMASCRIPT, because that is what it is, could make users who are +afraid of \LUA\ willing to play with simple scripting in \CONTEXT. Of course, +after a while they will figure out that \LUA\ is the real deal. + +Therefore, instead of sticking to an experiment, I decided to make support for +the \type {mujs} library an option. After all, every now and they we need +something new to play with. But be warned: it's an optional thing. The +interpreter is not embedded in the binary and is loaded on demand (when present). +In spite of that performance is quite okay. + +\stopsection + +\startsection[title=A few examples] + +Because the provided interface is pretty limited, a few simple examples will do. +There are plenty of tutorials on the Internet. The main thing to keep in mind is +that an \ECMASCRIPT\ interpreter is normally pretty limited when it comes to +communicating with its environment. For instance, the main application provides +way to print something (to a console) or read from files. So, commands that +relate to this are specific for \LUAMETATEX. Before anything can be done you need +to load the (\type {mujs}) library, which is done with: + +\starttyping +\usemodule[ecmascript] +\stoptyping + +You can write a message to the log (or an output pane or console) with the \type +{console} function, one that normally is present in a \JAVASCRIPT\ (\ECMASCRIPT) +environment: + +\starttyping +\ecmacode {console("Example Three!")} +\stoptyping + +Printing something to the \TEX\ engine is done with this command: + +\startbuffer +\ecmacode {texprint("Just a {\\bf short} sentence.")} +\stopbuffer + +\typebuffer[option=TEX] + +This produces: + +\getbuffer + +and is comparable with the \type {tex.print} (which prints lines) function at the +\LUA\ end. This means that there is also \type {texsprint} (which accumulates +parts into lines). In practice one will probably always use that one. + +When there are two arguments, the first argument has to be a number and sets the +so called catcode table to be used. + +\startbuffer +\ecmacode {texprint(catcodes.vrb,"Just a {\\bf short} sentence.")} +\stopbuffer + +\typebuffer[option=TEX] + +This results in a verbatim print: {\tttf \inlinebuffer} The backslash is just that, +a backslash and not a trigger for a \TEX\ command. + +You can do pretty much everything with these print commands. Take for instance the +following example: + +\startbuffer +\startecmacode + console("We're doing some MetaPost!"); + texsprint( + "\\startMPcode " + + 'fill fullsquare xyscaled (6cm,1cm) withcolor "darkred";' + + 'fill fullsquare xyscaled (4cm,1cm) withcolor "darkgreen";' + + 'fill fullsquare xyscaled (2cm,1cm) withcolor "darkblue";' + + "\\stopMPcode " + ); +\stopecmacode +\stopbuffer + +\typebuffer[option=TEX] + +This produces: + +\startlinecorrection +\getbuffer +\stoplinecorrection + +in \LUA\ we can do this: + +\startbuffer +\startluacode + context.startMPcode() + context('fill fullsquare xyscaled (6cm,1cm) withcolor "middlecyan";') + context('fill fullsquare xyscaled (4cm,1cm) withcolor "middlemagenta";') + context('fill fullsquare xyscaled (2cm,1cm) withcolor "middleyellow";') + context.stopMPcode() +\stopluacode +\stopbuffer + +\typebuffer[option=TEX] + +The result is the same but the code to produce it looks more like \CONTEXT, if +only because way more built in features are provided. It makes no sense to do +the same with another scripting language. + +\startlinecorrection +\getbuffer +\stoplinecorrection + +As mentioned, reading from files is to be provided by the main program and indeed +we do have some basic interface. Actually we delegate all to the \LUA\ end by +using a callback mechanism but users won't see these details. It suffices to know +that file lookups are done the same way as in the main program because we use the +same resolvers. One can (in the spirit of \ECMASCRIPT) open a file by creating a +new file object. After that one can read from the file and, when done, close it. + +\startbuffer +\startecmacode + var f = File("ecmascript-mkiv.tex","r"); + var l = f.read("*a"); + f.close(); + texprint( + "This file has " + + l.length // or: l.length.toString() + + " bytes!" + ) +\stopecmacode +\stopbuffer + +\typebuffer[option=TEX] + +Which reports that: \quotation {\inlinebuffer} The arguments to the \type {read} +method are the same as in \LUA, so for instance \type {*a} reads the whole file, +\type {*l} a single line, and a number will read that many bytes. There is +currently no support for writing as I see no need for it (yet). + +You can load an external file too. + +\startluacode +io.savedata("ecmascript-demo-001.js",[[ +function filesize(name) { + var f = File(name,"r"); + if (f != undefined) { + var l = f.read("*a"); + f.close(); + return l.length; + } else { + return 0; + } +} +]]) +\stopluacode + +\startbuffer +\ecmafile{ecmascript-demo-001.js} +\stopbuffer + +\typebuffer[option=TEX] \getbuffer + +This file defines a function: + +\typefile{ecmascript-demo-001.js} + +We use this as follows: + +\startbuffer +\startecmacode + texsprint( + "This file has " + + filesize("ecmascript-mkiv.tex") + + " bytes!" + ) +\stopecmacode +\stopbuffer + +\typebuffer[option=TEX] + +The result is the same as before: \quotation {\inlinebuffer} but by using a +predefined function we save ourselves some typing. Actually, a more efficient +variant is this: + +\starttyping +function filesize(name) { + var f = File(name,"r"); + if (f != undefined) { + var l = f.seek("end"); + f.close(); + return l; + } else { + return 0; + } +} +\stoptyping + +As with the \type {read} method, the \type {seek} method behaves the same as +its \LUA\ counterpart, which is a good reason to have a look at the \LUA\ +manual. + +If you want you want also access the \ECMASCRIPT\ interpreter from the \LUA\ end, +not that it makes much sense, but maybe you have a lot of complex code that you +don't want to rewrite. Here is an example: + +\startbuffer +\startluacode + optional.loaded.mujs.execute [[ + var MyMax = 10; // an example of persistence + ]] + + optional.loaded.mujs.execute [[ + texsprint("\\startpacked"); + for (var i = 1; i <= MyMax; i++) { + texprint( + "Here is some rather dumb math test: " + + Math.sqrt(i/MyMax) + + "!\\par" + ); + } + texsprint("\\stoppacked"); + ]] +\stopluacode +\stopbuffer + +\typebuffer[option=TEX] + +This assumes that you have loaded the module \type {ecmascript} which does the +necessary preparations. Watch the different ways to add comment and also watch +how we need to escape the \CONTEXT\ commands. Of course the syntax of both +languages is different too. + +\getbuffer + +For now there is not much more to tell. I might add a few features (and more +examples). And the low level optional interface is not yet declared stable but as +we wrap it in higher level commands no one will notice changes at that end. + +\stopsection + +\startsection[title=Extensions] + +To summarize, for printing to \TEX\ we have: + +\starttyping +texsprint([catcodetableid,]string|number) +\stoptyping + +and + +\starttyping +texprint(catcodetableid,]string|number) +\stoptyping + +and for printing to the console: + +\starttyping +console(string|number) +\stoptyping + +A file is opened with: + +\starttyping +var f = File.new(filename[,mode]) +\stoptyping + +and the returned file object has the methods: + +\starttyping +var str = f:read([string|number]) +var pos = f:seek(whence[,offset]) +\stoptyping + +There is a predefined table \type {catcodes} with sybolic entries +for: + +\starttabulate +\NC \type {tex} \NC regular \TEX\ catcode regime \NC \NR +\NC \type {ctx} \NC standard \CONTEXT\ catcode regime \NC \NR +\NC \type {vrb} \NC verbatim catcode regime \NC \NR +\NC \type {prt} \NC protected \CONTEXT\ catcode regime \NC \NR +\stoptabulate + +\stopsection + +\startsection[title=Colofon] + +\starttabulate[|B|p|] +\NC author \NC \getvariable{document}{author}, \getvariable{document}{affiliation}, \getvariable{document}{location} \NC \NR +\NC version \NC \currentdate \NC \NR +\NC website \NC \getvariable{document}{website} \endash\ \getvariable{document}{support} \NC \NR +\stoptabulate + +\stopsection + +\stopdocument diff --git a/doc/context/sources/general/manuals/libraries/libraries-mkiv.tex b/doc/context/sources/general/manuals/libraries/libraries-mkiv.tex index 6a322c771..f1801efc0 100644 --- a/doc/context/sources/general/manuals/libraries/libraries-mkiv.tex +++ b/doc/context/sources/general/manuals/libraries/libraries-mkiv.tex @@ -61,7 +61,7 @@ support=www.contextgarden.net, website=www.pragma-ade.nl] -\startluasetups[swiglib] +\startluasetups[libraries] context.nohyphens() for i=1,640 do context.definedfont { string.formatters["TitlePageMono at %p"](65536*(10+math.random(5))) } @@ -76,7 +76,7 @@ StartPage ; fill Page enlarged 1cm withcolor \MPcolor{extracolor} ; - draw textext("\framed[loffset=2pt,roffset=2pt,frame=off,width=\paperwidth,align={normal,paragraph,verytolerant,stretch}]{\luasetup{swiglib}}") + draw textext("\framed[loffset=2pt,roffset=2pt,frame=off,width=\paperwidth,align={normal,paragraph,verytolerant,stretch}]{\luasetup{libraries}}") xysized (PaperWidth,PaperHeight) shifted center Page withcolor .8white ; @@ -247,6 +247,7 @@ There are some optional libraries present, like: \NC libs-imp-sqlite \NC sqlite \NC sqlite3 \NC sqlite3 \NC \NR %NC libs-imp-postgress \NC libpg \NC libpg \NC libpg \NC \NR % untested \NC libs-imp-zint \NC libzint \NC libzint \NC libzint \NC \NR +\NC libs-imp-mujs \NC libmujs \NC libmujs \NC libmujs \NC \NR \NC libs-imp-ghostscript \NC ghostscript \NC gswin64 \NC libgs \NC \NR \NC libs-imp-graphicsmagick \NC graphicsmagick \NC several \NC unknown \NC \NR %NC font-phb-imp-internal \NC hb \NC libharfbuzz \NC libharfbuzz \NC \NR % maybe, for idris, testing uniscribe diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-callbacks.tex b/doc/context/sources/general/manuals/luametatex/luametatex-callbacks.tex index e713d13c3..e3e2a91e1 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-callbacks.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-callbacks.tex @@ -13,6 +13,7 @@ \libindex{register} \libindex{list} \libindex{find} +\libindex{known} This library has functions that register, find and list callbacks. Callbacks are \LUA\ functions that are called in well defined places. There are two kind of @@ -28,18 +29,14 @@ but in the end might not give the user the expected outcome. The first thing you need to do is registering a callback: \startfunctioncall -id, error = - callback.register(<string> callback_name, <function> func) -id, error = - callback.register(<string> callback_name, nil) -id, error = - callback.register(<string> callback_name, false) +id = callback.register(<string> callback_name, <function> func) +id = callback.register(<string> callback_name, nil) +id = callback.register(<string> callback_name, false) \stopfunctioncall Here the \syntax {callback_name} is a predefined callback name, see below. The function returns the internal \type {id} of the callback or \type {nil}, if the -callback could not be registered. In the latter case, \type {error} contains an -error message, otherwise it is \type {nil}. +callback could not be registered. \LUATEX\ internalizes the callback function in such a way that it does not matter if you redefine a function accidentally. @@ -65,7 +62,12 @@ The keys in the table are the known callback names, the value is a boolean where <function> f = callback.find(callback_name) \stopfunctioncall -If the callback is not set, \type {find} returns \type {nil}. +If the callback is not set, \type {find} returns \type {nil}. The \type {known} +function can be used to check if a callback is supported. + +\startfunctioncall +if callback.known("foo") then ... end +\stopfunctioncall \stopsection diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex b/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex index 19a4078c1..4ec846b38 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex @@ -15,6 +15,8 @@ what is gone. We start with the primitives that were dropped. \type {\expandglyphsinfont} \type {\ignoreligaturesinfont} \type {\tagcode} + \type {\leftghost} + \type {\rightghost} \NC \NR \NC backend \NC \type {\dviextension} \type {\dvivariable } @@ -151,6 +153,8 @@ show_whatsit Being the core of extensibility, the typesetting callbacks of course stayed. This is what we ended up with: +% \ctxlua{inspect(table.sortedkeys(callbacks.list))} + \starttyping find_log_file, find_data_file, find_format_file, open_data_file, read_data_file, process_jobname, start_run, stop_run, define_font, pre_output_filter, diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-enhancements.tex b/doc/context/sources/general/manuals/luametatex/luametatex-enhancements.tex index 06e0ce327..d70b8f2c0 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-enhancements.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-enhancements.tex @@ -14,7 +14,7 @@ From day one, \LUATEX\ has offered extra features compared to the superset of \PDFTEX, which includes \ETEX, and \ALEPH. This has not been limited to the possibility to execute \LUA\ code via \prm {directlua}, but \LUATEX\ also adds functionality via new \TEX|-|side primitives or extensions to existing ones. The -same is true fir \LUAMETATEX. Some primitives have \type {luatex} in their name +same is true for \LUAMETATEX. Some primitives have \type {luatex} in their name and there will be no \type {luametatex} variants. This is because we consider \LUAMETATEX\ to be \LUATEX 2\high{+}. @@ -40,14 +40,10 @@ it may be needed to put these assignments before the above line: \stoptyping More fine|-|grained primitives control is possible and you can look up the -details in \in {section} [luaprimitives]. For simplicity's sake, this manual -assumes that you have executed the \prm {directlua} command as given above. - -The startup behaviour documented above is considered stable in the sense that -there will not be backward|-|incompatible changes any more. We have promoted some -rather generic \PDFTEX\ primitives to core \LUATEX\ ones, and a few that we -inherited from \ALEPH\ (\OMEGA) are also promoted. Effectively this means that we -now only have the \type {tex}, \type {etex} and \type {luatex} sets left. +details in \in {section} [luaprimitives]. There are only three kinds of +primitives: \type {tex}, \type {etex} and \type {luatex} but a future version +might drop this and no longer make that distinction as it no longer serves +a purpose. \stopsubsection @@ -225,7 +221,7 @@ commands are: Fonts are loaded via \LUA\ and a minimal amount of information is kept at the \TEX\ end. Sharing resources is up to the loaders. The engine doesn't really care -about what a character (or glyph) number represents (an \UNICODE\ or index) as it +about what a character (or glyph) number represents (a \UNICODE\ or index) as it only is interested in dimensions. \stopsubsection @@ -246,7 +242,7 @@ nodes that have for instance a \type {font} and \type {char} property and \typ {\kern 10pt} becomes a \nod {kern} node with a \type {width} property. Spaces are alien to \TEX\ as they are turned into \nod {glue} nodes. So, a simple paragraph is mostly a mix of sequences of \nod {glyph} nodes (words) and \nod {glue} nodes -(spaces). A node can have a subtype to that it can be recognized as for instance +(spaces). A node can have a subtype so that it can be recognized as for instance a space related glue. The sequences of characters at some point are extended with \nod {disc} nodes @@ -271,7 +267,7 @@ and carry only the minimal amount of information needed. In traditional \TEX\ a character node only held the font and slot number, in \LUATEX\ we also store some language related information, the expansion factor, etc. Now that we have access to these nodes from \LUA\ it makes sense to be able to carry more information -with an node and this is where attributes kick in. +with a node and this is where attributes kick in. \stopsubsection @@ -379,7 +375,7 @@ code: Later we will see that you can access properties of a node. The boxes here are so called \nod {hlist} nodes that have a field \type {list} that points to the content. Because the attributes are a list themselves you can access them by -indexing the node (here we do that with \type {[a]}. Running this snippet gives: +indexing the node (here we do that with \type {[a]}). Running this snippet gives: \start \getbuffer[tex] @@ -597,7 +593,7 @@ function calls is that they are stored in the format (but without upvalues). Catcode tables are a new feature that allows you to switch to a predefined catcode regime in a single statement. You can have lots of different tables, but -if you need a dozen you might wonder what you're doing. . This subsystem is +if you need a dozen you might wonder what you're doing. This subsystem is backward compatible: if you never use the following commands, your document will not notice any difference in behaviour compared to traditional \TEX. The contents of each catcode table is independent from any other catcode table, and its @@ -795,10 +791,10 @@ but faster (only measurable with millions of calls) and probably more convenient \topicindex {expansion} -The \lpr {expanded} primitive takes a token list and expands it content which can +The \lpr {expanded} primitive takes a token list and expands its content which can come in handy: it avoids a tricky mix of \prm {expandafter} and \prm {noexpand}. You can compare it with what happens inside the body of an \prm {edef}. But this -kind of expansion it still doesn't expand some primitive operations. +kind of expansion still doesn't expand some primitive operations. \startbuffer \newcount\NumberOfCalls @@ -890,14 +886,14 @@ so called prefixed commands (except box assignments). \startsubsection[title={\lpr {ignorepars}}] -This primitives is like \prm {ignorespaces} but also skips paragraph ending +This primitive is like \prm {ignorespaces} but also skips paragraph ending commands (normally \prm {par} and empty lines). \stopsubsection \startsubsection[title={\lpr {futureexpand}, \lpr {futureexpandis}, \lpr {futureexpandisap}}] -These commands are use as: +These commands are used as: \starttyping \futureexpand\sometoken\whenfound\whennotfound @@ -1152,7 +1148,7 @@ measurable when you runs tens of millions of complex tests and in that case it i very likely to drown in the real action. It's a convenience mechanism, in the sense that it can make your code look a bit easier to follow. -There is an nice side effect of this mechanism. When you define: +There is a nice side effect of this mechanism. When you define: \starttyping \def\quitcondition{\orelse\iffalse} @@ -1244,7 +1240,7 @@ the backend to include an image. The wrapping is needed because a special itself is a whatsit and as such has no dimensions. In \PDFTEX\ a special whatsit for images was introduced and that one {\em has} -dimensions. As a consequence, in several places where the engine to deal with the +dimensions. As a consequence, in several places where the engine deals with the dimensions of nodes, it now has to check the details of whatsits. By inheriting code from \PDFTEX, the \LUATEX\ engine also had that property. However, at some point this approach was abandoned and a more natural trick was used: images (and @@ -1254,7 +1250,7 @@ dimensions, the code could be simplified. When direction nodes and localpar nodes also became first class nodes, whatsits again became just that: nodes representing whatever you want, but without dimensions, and therefore they could again be ignored when dimensions mattered. -And, because images were disguised as rules, as mentioned ,their dimensions +And, because images were disguised as rules, as mentioned, their dimensions automatically were taken into account. This seperation between front and backend cleaned up the code base already quite a bit. @@ -1263,7 +1259,7 @@ engine never looks at subtypes of rules. That was up to the backend. This means that image support is not present in \LUAMETATEX. When an image specification was parsed the special properties, like the filename, or additional attributes, were stored in the backend and all that \LUATEX\ does is registering a reference to an -image s specification in the rule node. But, having no backend means nothing is +image's specification in the rule node. But, having no backend means nothing is stored, which in turn would make the image inclusion primitives kind of weird. Therefore you need to realize that contrary to \LUATEX, {\em in \LUAMETATEX\ @@ -1286,7 +1282,7 @@ of course be implemented in \LUA. \LL \stoptabulate -An implementation probably should accepts the usual optional dimension parameters +An implementation probably should accept the usual optional dimension parameters for \type {\use...resource} in the same format as for rules. With images, these dimensions are then used instead of the ones given to \lpr {useimageresource} but the original dimensions are not overwritten, so that a \lpr {useimageresource} @@ -1494,7 +1490,7 @@ The approach is that we try to make node lists balanced but also try to avoid some side effects. What happens is quite intuitive if we forget about spaces (turned into glue) but even there what happens makes sense if you look at it in detail. However that logic makes in|-|group switching kind of useless when no -proper nested grouping is used: switching from right to left several times +properly nested grouping is used: switching from right to left several times nested, results in spacing ending up after each other due to nested mirroring. Of course a sane macro package will manage this for the user but here we are discussing the low level injection of directional information. diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-fonts.tex b/doc/context/sources/general/manuals/luametatex/luametatex-fonts.tex index 077d9e51e..917ebfeb8 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-fonts.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-fonts.tex @@ -9,7 +9,7 @@ \startsection[title={Introduction}] Only traditional font support is built in, anything more needs to be implemented -in \LUA. This is conform the \LUATEX\ philosophy. When you pass a font to the +in \LUA. This conforms to the \LUATEX\ philosophy. When you pass a font to the frontend only the dimensions matter, as these are used in typesetting, and optionally ligatures and kerns when you rely on the built|-|in font handler. For math some extra data is needed, like information about extensibles and next in @@ -79,37 +79,14 @@ The names and their internal remapping are: \LL \stoptabulate -The \type {characters} table is a list of character hashes indexed by an integer -number. The number is the \quote {internal code} \TEX\ knows this character by. -For proper paragraph building and math rendering the following fields can be -present in en entry in the \type {characters} table. You can of course add all -kind of extra fields. The engine only uses those that it needs for typesetting -a paragraph or formula. - -Each character hash itself is a hash. For example, here is the character \quote -{f} (decimal 102) in the font \type {cmr10 at 10pt}. The numbers that represent -dimensions are in scaled points. - -\starttyping -[102] = { - ["width"] = 200250, - ["height"] = 455111, - ["depth"] = 0, - ["italic"] = 50973, - ["kerns"] = { - [63] = 50973, - [93] = 50973, - [39] = 50973, - [33] = 50973, - [41] = 50973 - }, - ["ligatures"] = { - [102] = { ["char"] = 11, ["type"] = 0 }, - [108] = { ["char"] = 13, ["type"] = 0 }, - [105] = { ["char"] = 12, ["type"] = 0 } - } -} -\stoptyping +The \type {characters} table is a \LUA\ hash table where the keys are integers. +When a character in the input is turned into a glyph node, it gets a character +code that normally refers to an entry in that table. For proper paragraph +building and math rendering the following fields can be present in an entry in +the \type {characters} table. You can of course add all kind of extra fields. The +engine only uses those that it needs for typesetting a paragraph or formula. The +subtables that define ligatures and kerns are also hashes with integer keys, and +these indices should point to entries in the main characters table. Providing ligatures and kerns this way permits \TEX\ to construct ligatures and add inter|-|character kerning. However, normally you will use an \OPENTYPE\ font @@ -139,6 +116,31 @@ has no ligatures and kerns and is normally not processed at all. \LL \stoptabulate +For example, here is the character \quote {f} (decimal 102) in the font \type +{cmr10 at 10pt}. The numbers that represent dimensions are in scaled points. + +\starttyping +[102] = { + ["width"] = 200250, + ["height"] = 455111, + ["depth"] = 0, + ["italic"] = 50973, + ["kerns"] = { + [63] = 50973, + [93] = 50973, + [39] = 50973, + [33] = 50973, + [41] = 50973 + }, + ["ligatures"] = { + [102] = { ["char"] = 11, ["type"] = 0 }, + [108] = { ["char"] = 13, ["type"] = 0 }, + [105] = { ["char"] = 12, ["type"] = 0 } + } +} +\stoptyping + + Two very special string indexes can be used also: \type {left_boundary} is a virtual character whose ligatures and kerns are used to handle word boundary processing. \type {right_boundary} is similar but not actually used for anything @@ -235,7 +237,7 @@ indicates the final insertion point. % \topicindex {fonts+virtual} Virtual fonts have been introduced to overcome limitations of good old \TEX. They -were mostly use for providing a direct mapping from for instance accented +were mostly used for providing a direct mapping from for instance accented characters onto a glyph. The backend was responsible for turning a reference to a character slot into a real glyph, possibly constructed from other glyphs. In our case there is no backend so there is also no need to pass this information @@ -247,12 +249,11 @@ A virtual character can itself point to virtual characters but be careful with nesting as you can create loops and overflow the stack (which often indicates an error anyway). -At the font level there can be a \type {fonts} an (indexed) \LUA\ table. The -values are one- or two|-|key hashes themselves, each entry indicating one of the -base fonts in a virtual font. In case your font is referring to itself in for -instance a virtual font, you can use the \type {slot} command with a zero font -reference, which indicates that the font itself is used. So, a table looks like -this: +At the font level there can be a an (indexed) \type {fonts} table. The values are +one- or two|-|key hashes themselves, each entry indicating one of the base fonts +in a virtual font. In case your font is referring to itself in for instance a +virtual font, you can use the \type {slot} command with a zero font reference, +which indicates that the font itself is used. So, a table looks like this: \starttyping fonts = { diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex b/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex index 56d5c7436..774f3d8d9 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex @@ -101,8 +101,9 @@ Hans Hagen \vfilll {\bf remark:} \LUAMETATEX\ development is mostly done by Hans Hagen and Alan -Braslau, who love playing with the three languages involved. Testing is done by -\CONTEXT\ developers and users. Many thanks for their patience! +Braslau, who love playing with the three languages involved. And as usual Mojca +Miklavec make sure all compiles well on the buildbot infrastructure. Testing is +done by \CONTEXT\ developers and users. Many thanks for their patience! {\bf remark:} When there are non|-|intrusive features that also make sense in \LUATEX, these will be applied in the experimental branch first, so that there is diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-languages.tex b/doc/context/sources/general/manuals/luametatex/luametatex-languages.tex index 19112a7f1..b6607a9bb 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-languages.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-languages.tex @@ -85,17 +85,6 @@ time (in case of a single|-|glyph word). \startitem \type {ligature}, for constructed ligatures bit 1 is set. \stopitem - \startitem - \type {ghost}, for so called \quote {ghost objects} bit 2 is set. - \stopitem - \startitem - \type {left}, for ligatures created from a left word boundary and for - ghosts created from \lpr {leftghost} bit 3 gets set. - \stopitem - \startitem - \type {right}, for ligatures created from a right word boundary and - for ghosts created from \lpr {rightghost} bit 4 is set. - \stopitem \stopitemize The \nod {glyph} nodes also contain language data, split into four items that @@ -142,8 +131,8 @@ initialized you start out with nothing, otherwise you already have a set. When a \lpr {hjcode} is greater than 0 but less than 32 is indicates the to be used length. In the following example we map a character (\type {x}) onto -another one in the patterns and tell the engine that \type {œ} counts as one -character. Because traditionally zero itself is reserved for inhibiting +another one in the patterns and tell the engine that \type {œ} counts as two +characters. Because traditionally zero itself is reserved for inhibiting hyphenation, a value of 32 counts as zero. Here are some examples (we assume that French patterns are used): @@ -369,7 +358,7 @@ before---after \par \stopcombination \stopbuffer -\startplacefigure[locationreference=automatichyphenmode:1,title={The automatic modes \type {0} (default), \type {1} and \type {2}, with a \prm {hsize} +\startplacefigure[reference=automatichyphenmode:1,title={The automatic modes \type {0} (default), \type {1} and \type {2}, with a \prm {hsize} of 6em and 2pt (which triggers a linebreak).}] \dontcomplain \tt \getbuffer[demo] \stopplacefigure @@ -435,13 +424,6 @@ there are a few exceptions. \stopitem \startitem - The \ALEPH|-|derived commands \lpr {leftghost} and \lpr {rightghost} - create nodes of a third subtype: \quote {ghost}. These nodes are ignored - completely by all further processing until the stage where inter|-|glyph - kerning is added. -\stopitem - -\startitem Automatic discretionaries are handled differently. \TEX82 inserts an empty discretionary after sensing an input character that matches the \prm {hyphenchar} in the current font. This test is wrong in our opinion: whether @@ -511,7 +493,7 @@ have been added: \stoptyping The first parameter has the following consequences for automatic discs (the ones -resulting from an \prm {exhyphenchar}: +resulting from an \prm {exhyphenchar}): \starttabulate[|c|l|l|] \DB mode \BC automatic disc \type {-} \BC explicit disc \prm{-} \NC \NR @@ -609,7 +591,7 @@ actual explicit hyphen character if needed). For example, this matches the word The motivation behind the \ETEX\ extension \prm {savinghyphcodes} was that hyphenation heavily depended on font encodings. This is no longer true in \LUATEX, and the corresponding primitive is basically ignored. Because we now -have \lpr {hjcode}, the case relate codes can be used exclusively for \prm +have \lpr {hjcode}, the case related codes can be used exclusively for \prm {uppercase} and \prm {lowercase}. The three curly brace pair pattern in an exception can be somewhat unexpected so @@ -777,8 +759,8 @@ boundary items after it is done with them, and it does the same for \quote {ghost} nodes. Finally, at the end of the kerning stage, all remaining \quote {character} nodes are converted to \quote {glyph} nodes. -This word separation is worth mentioning because, if you overrule from \LUA\ only -one of the two callbacks related to font handling, then you have to make sure you +This separation is worth mentioning because, if you overrule from \LUA\ only one +of the two callbacks related to font handling, then you have to make sure you perform the tasks normally done by \LUATEX\ itself in order to make sure that the other, non|-|overruled, routine continues to function properly. @@ -826,7 +808,7 @@ Here is that nested solution again, in a different representation: \starttabulate[|l|c|c|c|c|c|c|] \DB \BC pre \BC \BC post \BC \BC replace \BC \NC \NR \TB -\NC topdisc \NC \type {f-} \NC (1) \NC \NC sub 1 \NC \NC sub 2 \NC \NR +\NC topdisc \NC \type {f-} \NC (1) \NC sub 1 \NC \NC sub 2 \NC \NC \NR \NC sub 1 \NC \type {f-} \NC (2) \NC \type {i} \NC (3) \NC \type {<fi>} \NC (4) \NC \NR \NC sub 2 \NC \type {<ff>-} \NC (5) \NC \type {i} \NC (6) \NC \type {<ffi>} \NC (7) \NC \NR \LL @@ -907,13 +889,13 @@ approach. \topicindex {paragraphs} \topicindex {discretionaries} -This code is almost unchanged, but because of the above|-|mentioned changes -with respect to discretionaries and ligatures, line breaking will potentially be +This code is almost unchanged, but because of the above|-|mentioned changes with +respect to discretionaries and ligatures, line breaking will potentially be different from traditional \TEX. The actual line breaking code is still based on -the \TEX82 algorithms, and it does not expect there to be discretionaries inside -of discretionaries. But, as patterns evolve and font handling can influence -discretionaries, you need to be aware of the fact that long term consistency is not -an engine matter only. +the \TEX82 algorithms, and there can be no discretionaries inside of +discretionaries. But, as patterns evolve and font handling can influence +discretionaries, you need to be aware of the fact that long term consistency is +not an engine matter only. But that situation is now fairly common in \LUATEX, due to the changes to the ligaturing mechanism. And also, the \LUATEX\ discretionary nodes are implemented diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-math.tex b/doc/context/sources/general/manuals/luametatex/luametatex-math.tex index 111a6cf03..ce4fe1544 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-math.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-math.tex @@ -593,10 +593,12 @@ with zero being the default behaviour. \start +\def\MathHack#1{\mathsurroundmode#1\relax\inlinebuffer} + \def\OneLiner#1#2% {\NC \type{#1} - \NC \dontleavehmode\inframed[align=normal,offset=0pt,frame=off]{\mathsurroundmode#1\relax\hsize 100pt x$x$x} - \NC \dontleavehmode\inframed[align=normal,offset=0pt,frame=off]{\mathsurroundmode#1\relax\hsize 100pt x $x$ x} + \NC \dontleavehmode\inframed[align=normal,offset=0pt,frame=off]{\hsize 100pt x$\MathHack{#1}x$x} + \NC \dontleavehmode\inframed[align=normal,offset=0pt,frame=off]{\hsize 100pt x $\MathHack{#1}x$ x} \NC #2 \NC \NR} @@ -605,7 +607,7 @@ with zero being the default behaviour. \mathsurroundskip20pt \stopbuffer -\typebuffer \getbuffer +\typebuffer \starttabulate[|c|c|c|pl|] \DB mode \BC x\$x\$x \BC x \$x\$ x \BC effect \NC \NR diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-metapost.tex b/doc/context/sources/general/manuals/luametatex/luametatex-metapost.tex index 3f0d0a945..5128f3d2a 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-metapost.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-metapost.tex @@ -448,32 +448,6 @@ id in the range 0 to 255; the returned \type {w} is in AFM units. <number> d = char_depth(mp,<string> fontname, <number> char) \stopfunctioncall -These are rather useless and might become obsolete. - -\subsection{\type {get_[boolean|numeric|string|path]}} - -\libindex{get_boolean} -\libindex{get_numeric} -\libindex{get_path} -\libindex{get_string} - -When a script call brings you from the \METAPOST\ run (temporarily) back to -\LUA\ you can access variables, but only if they are known (so for instance -anonymous capsules like loop variables are not accessible). - -\startfunctioncall -<boolean> w = get_boolean(mp,<string> name) -<number> n = get_numeric(mp,<string> name) -<string> s = get_string (mp,<string> name) -<table> p = get_path (mp,<string> name) -\stopfunctioncall - -The path is returned a a table with subtables that have six numbers: the -coordinates of the point, pre- and postcontrol. A \type {cycle} fields indicates -if a path is cyclic. - -\stopsection - \stopchapter \stopcomponent diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-nodes.tex b/doc/context/sources/general/manuals/luametatex/luametatex-nodes.tex index 8b4f6101c..16c6e1202 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-nodes.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-nodes.tex @@ -16,11 +16,11 @@ \TEX's nodes are represented in \LUA\ as userdata objects with a variable set of fields or by a numeric identifier when requested. When you print a node userdata -object you will see these numbers. In the following syntax tables, such as the -type of such a userdata object is represented as \syntax {<node>}. +object you will see these numbers. In the following syntax tables the type of +such a userdata object is represented as \syntax {<node>}. \blank -\dontleavehmode {\bf The return values of \type {node.types()} are:} \showtypes +\dontleavehmode {\bf The return values of \type {node.types} are:} \showtypes \blank In \ETEX\ the \prm {lastnodetype} primitive has been introduced. With this @@ -41,7 +41,7 @@ also reported with this helper, but they are backend specific. \def\ShowValues#1{ \blank \dontleavehmode - {\bf The return values of \type {node.values("#1"} are:} + {\bf The return values of \type {node.values("#1")} are:} \showvalues{#1} \blank } @@ -489,7 +489,7 @@ bits for the \type {subtype} field are: \stoptabulate The \type {expansion_factor} has been introduced as part of the separation -between font- and backend. It is the result of extensive experiments with a more +between front- and backend. It is the result of extensive experiments with a more efficient implementation of expansion. Early versions of \LUATEX\ already replaced multiple instances of fonts in the backend by scaling but contrary to \PDFTEX\ in \LUATEX\ we now also got rid of font copies in the frontend and @@ -1011,7 +1011,7 @@ providing an overview of the possible top|-|level \type {id} types. <table> t = node.types() \stopfunctioncall -when we issue this command, we get a table. The currently visible types are +When we issue this command, we get a table. The currently visible types are \inlineluavalue { node.types() } where the numbers are the internal identifiers. Only those nodes are reported that make sense to users so there can be gaps in the range of numbers. @@ -1031,7 +1031,7 @@ This converts a single type name to its internal numeric representation. The \type {node.id("glyph")} command returns the number \inlineluavalue { node.id ("glyph") } and \type {node.id("hlist")} returns \inlineluavalue { node.id -("hlist") } where the number don't relate to importance or some ordering; they +("hlist") } where the numbers don't relate to importance or some ordering; they just appear in the order that is handy for the engine. Commands like this are rather optimized so performance should be ok but you can of course always store the id in a \LUA\ number. @@ -1056,8 +1056,8 @@ there is no node with that id. \libindex {fields} \libindex {has_field} -This function returns an indexed table with valid field names for a particular type of -node. +This function returns an indexed table with valid field names for a particular +type of node. \startfunctioncall <table> t = node.fields(<number|string> id) @@ -1185,9 +1185,9 @@ affect all the nodes that share that list. node.write(<node> n) \stopfunctioncall -This function that will append a node list to \TEX's \quote {current list}. The -node list is not deep|-|copied! There is no error checking either! You mignt need -to enforce horizontal mode in order for this to work as expected. +This function will append a node list to \TEX's \quote {current list}. The node +list is not deep|-|copied! There is no error checking either! You might need to +enforce horizontal mode in order for this to work as expected. \stopsubsubsection @@ -1199,7 +1199,7 @@ to enforce horizontal mode in order for this to work as expected. \libindex {slide} -This helper makes sure that the node lists is double linked and returns the found +This helper makes sure that the node list is double linked and returns the found tail node. \startfunctioncall @@ -1445,8 +1445,8 @@ experimental) convenience. This helper returns the location of the first match at or after node \type {n}: \startfunctioncall -<node> n = node.traverse_list(<node> n, <integer> subtype) -<node> n, subtype = node.traverse_list(<node> n) +<node> n = node.find_node(<node> n, <integer> subtype) +<node> n, subtype = node.find_node(<node> n) \stopfunctioncall \stopsubsubsection diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-primitives.tex b/doc/context/sources/general/manuals/luametatex/luametatex-primitives.tex index 382ed05a4..9e26c6bc4 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-primitives.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-primitives.tex @@ -337,8 +337,6 @@ new primitives, a summary is given below. \NC \type {noboundary} \NC command \NC \NC \NR \NC \type {protrusionboundary} \NC command \NC \NC \NR \NC \type {wordboundary} \NC command \NC \NC \NR -\NC \type {leftghost} \NC charactercode \NC \NC \NR -\NC \type {rightghost} \NC charactercode \NC \NC \NR \NC \type {nohrule} \NC command \NC \NC \NR \NC \type {novrule} \NC command \NC \NC \NR \NC \type {insertht} \NC number \NC \NC \NR diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-tex.tex b/doc/context/sources/general/manuals/luametatex/luametatex-tex.tex index 839bae409..25f70dd2f 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex-tex.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex-tex.tex @@ -273,7 +273,7 @@ on the actual \TEX\ values. As a result, most of the \LUA\ table operators (like \type {pairs} and \type {#}) do not work on such items. At the moment, it is possible to access almost every parameter that you can use -after \prm {the}, is a single tokens or is sort of special in \TEX. This excludes +after \prm {the}, is a single token or is sort of special in \TEX. This excludes parameters that need extra arguments, like \type {\the\scriptfont}. The subset comprising simple integer and dimension registers are writable as well as readable (like \prm {tracingcommands} and \prm {parindent}). @@ -1133,6 +1133,11 @@ The known fields are: \LL \stoptabulate +When a second string argument is given to the \type {getnest}, the value with +that name is returned. Of course the level must be valid. When \type {setnest} +gets a third argument that value is assigned to the field given as second +argument. + \stopsubsection \startsubsection[reference=sec:luaprint,title={Print functions}] @@ -2171,7 +2176,7 @@ a bit but for passing strings conversion to and from tokens has to be done anywa \stopsubsection -\startsubsection[title= {Picking up one token}] +\startsubsection[title={Picking up one token}] \libindex {get_next} \libindex {scan_token} diff --git a/doc/context/sources/general/manuals/sql/sql-mkiv.tex b/doc/context/sources/general/manuals/sql/sql-mkiv.tex index 4d2ecbc6e..835065ba0 100644 --- a/doc/context/sources/general/manuals/sql/sql-mkiv.tex +++ b/doc/context/sources/general/manuals/sql/sql-mkiv.tex @@ -493,8 +493,8 @@ context --extra=sql-tables --help \startsection[title=Example] -The distribution has a few examples, for instance a logger. The following code shows -a bit of this (we assume that the swiglib sqlite module is present): +The distribution has a few examples, for instance a logger. The following code +shows a bit of this (we assume that \SQLITE\ is installed): \startbuffer require("util-sql") diff --git a/doc/context/sources/general/manuals/svg/svg-lmtx-mozilla.lua b/doc/context/sources/general/manuals/svg/svg-lmtx-mozilla.lua index 0797f6406..802efcf3d 100644 --- a/doc/context/sources/general/manuals/svg/svg-lmtx-mozilla.lua +++ b/doc/context/sources/general/manuals/svg/svg-lmtx-mozilla.lua @@ -351,4 +351,15 @@ return { <path d="M0,5 h-3 M0,7 h3 M0,9 h-1" stroke="rgba(255,0,0,.5)" /> </svg> ]], + [[ + svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg"> + <path d="M60,15 L60,110 M30,40 L90,40 M30,75 L90,75 M30,110 L90,110" stroke="grey" /> + <text text-anchor="start" x="60" y="40">A</text> + <text text-anchor="middle" x="60" y="75">A</text> + <text text-anchor="end" x="60" y="110">A</text> + <circle cx="60" cy="40" r="3" fill="red" /> + <circle cx="60" cy="75" r="3" fill="red" /> + <circle cx="60" cy="110" r="3" fill="red" /> + </svg> + ]], } diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua index 908d45686..fcba696c4 100644 --- a/scripts/context/lua/mtx-fonts.lua +++ b/scripts/context/lua/mtx-fonts.lua @@ -16,7 +16,7 @@ local lower = string.lower local concat = table.concat local write_nl = (logs and logs.writer) or (texio and texio.write_nl) or print -local otlversion = 3.110 +local otlversion = 3.111 local helpinfo = [[ <?xml version="1.0"?> diff --git a/scripts/context/lua/mtx-unicode.lua b/scripts/context/lua/mtx-unicode.lua index 85860ddfd..297807889 100644 --- a/scripts/context/lua/mtx-unicode.lua +++ b/scripts/context/lua/mtx-unicode.lua @@ -699,9 +699,12 @@ do local hash = { } + local crap = lpeg.P("e") * lpeg.R("09","..","09")^1 * lpeg.P(" ")^1 + local replace = lpeg.replacer { - ["#"] = "hash", - ["*"] = "asterisk" + [crap] = "", + ["#"] = "hash", + ["*"] = "asterisk", } for i=1,#t do diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index bcc3bb243..15e99eb91 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -2102,7 +2102,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 42339, stripped down to: 21588 +-- original size: 41758, stripped down to: 22643 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2445,13 +2445,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -2470,6 +2470,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -2490,6 +2492,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -2561,6 +2565,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -2570,7 +2576,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -2598,12 +2604,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -2611,12 +2621,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -2625,6 +2639,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -2641,6 +2657,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -2653,11 +2671,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -2679,6 +2699,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -2698,6 +2720,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -2715,6 +2739,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -2738,6 +2764,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3779,7 +3806,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-os"] = package.loaded["l-os"] or true --- original size: 18925, stripped down to: 10095 +-- original size: 19102, stripped down to: 10192 if not modules then modules={} end modules ['l-os']={ version=1.001, @@ -4200,6 +4227,12 @@ function os.validdate(year,month,day) end return year,month,day end +function os.date(fmt,...) + if not fmt then + fmt="%Y-%m-%d %H:%M" + end + return date(fmt,...) +end local osexit=os.exit local exitcode=nil function os.setexitcode(code) @@ -6530,7 +6563,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 45072, stripped down to: 22629 +-- original size: 45188, stripped down to: 22734 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -6945,9 +6978,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -7412,7 +7448,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 29567, stripped down to: 16483 +-- original size: 32649, stripped down to: 18257 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7649,92 +7685,160 @@ function tables.encapsulate(core,capsule,protect) } ) end end -local f_hashed_string=formatters["[%Q]=%Q,"] -local f_hashed_number=formatters["[%Q]=%s,"] -local f_hashed_boolean=formatters["[%Q]=%l,"] -local f_hashed_table=formatters["[%Q]="] -local f_indexed_string=formatters["[%s]=%Q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%Q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(0,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(0,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(0) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(0,v) +if JITSUPPORTED then + local f_hashed_string=formatters["[%Q]=%Q,"] + local f_hashed_number=formatters["[%Q]=%s,"] + local f_hashed_boolean=formatters["[%Q]=%l,"] + local f_hashed_table=formatters["[%Q]="] + local f_indexed_string=formatters["[%s]=%Q,"] + local f_indexed_number=formatters["[%s]=%s,"] + local f_indexed_boolean=formatters["[%s]=%l,"] + local f_indexed_table=formatters["[%s]="] + local f_ordered_string=formatters["%Q,"] + local f_ordered_number=formatters["%s,"] + local f_ordered_boolean=formatters["%l,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(0,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(0,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(0) + fastserialize(v) + m=m+1 r[m]=f_indexed_table(0) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) + for i=1,n do + local v=t[i] + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_ordered_string(v) + elseif tv=="number" then + m=m+1 r[m]=f_ordered_number(v) + elseif tv=="table" then + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_ordered_boolean(v) + end end end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(k,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(k,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(k) + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(k,v) + end + end + else local tv=type(v) if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) + m=m+1 r[m]=f_hashed_string(k,v) elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) + m=m+1 r[m]=f_hashed_number(k,v) elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) + m=m+1 r[m]=f_hashed_table(k) fastserialize(v) elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) + m=m+1 r[m]=f_hashed_boolean(k,v) end end + end + m=m+1 + if outer then + r[m]="}" else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end + r[m]="}," end + return r end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," + return concat(fastserialize(t,true)) + end +else + local f_v=formatters["[%q]=%q,"] + local f_t=formatters["[%q]="] + local f_q=formatters["%q,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + m=m+1 + r[m]="[0]='" + if type(v)=="table" then + fastserialize(v) + else + r[m]=format("%q,",v) + end + end + for i=1,n do + local v=t[i] + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",i) + fastserialize(v) + else + r[m]=format("[%i]=%q,",i,v) + end + end + end + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",k) + fastserialize(v) + else + r[m]=format("[%i]=%q,",k,v) + end + end + else + m=m+1 + if type(v)=="table" then + r[m]=format("[%q]=",k) + fastserialize(v) + else + r[m]=format("[%q]=%q,",k,v) + end + end + end + m=m+1 + if outer then + r[m]="}" + else + r[m]="}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) end function table.deserialize(str) if not str or str=="" then @@ -7828,27 +7932,27 @@ function table.twowaymapper(t) return t end local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] +local f_start_key_num=JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str=formatters["%w[%q]={"] local f_start_key_boo=formatters["%w[%l]={"] local f_start_key_nop=formatters["%w{"] local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%Q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%Q,"] +local f_key_num_value_num=JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num=JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num=JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] +local f_key_num_value_str=JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str=formatters["%w[%Q]=%Q,"] local f_key_boo_value_str=formatters["%w[%l]=%Q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] +local f_key_num_value_boo=JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo=formatters["%w[%Q]=%l,"] local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] +local f_key_num_value_not=JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not=formatters["%w[%Q]={},"] local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq=JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq=formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] +local f_val_num=JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str=formatters["%w%Q,"] local f_val_boo=formatters["%w%l,"] local f_val_not=formatters["%w{},"] @@ -21589,7 +21693,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16070, stripped down to: 11353 +-- original size: 16099, stripped down to: 11379 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21876,7 +21980,7 @@ function caches.is_writable(filepath,filename) local tmaname,tmcname=setluanames(filepath,filename) return is_writable(tmaname) end -local saveoptions={ compact=true } +local saveoptions={ compact=true,accurate=not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname,tmcname=setluanames(filepath,filename) data.cache_uuid=osuuid() @@ -25385,363 +25489,147 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-lib"] = package.loaded["util-lib"] or true +package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 17659, stripped down to: 9560 +-- original size: 5822, stripped down to: 3629 -if not modules then modules={} end modules ['util-lib']={ +if not modules then modules={} end modules ['libs-ini']={ version=1.001, comment="companion to luat-lib.mkiv", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", + license="see context related readme files" } +local type,unpack=type,unpack local type=type -local next=next -local pcall=pcall -local gsub=string.gsub -local find=string.find -local sort=table.sort -local pathpart=file.pathpart local nameonly=file.nameonly local joinfile=file.join -local removesuffix=file.removesuffix local addsuffix=file.addsuffix -local findfile=resolvers.findfile -local findfiles=resolvers.findfiles -local expandpaths=resolvers.expandedpathlistfromvariable local qualifiedpath=file.is_qualified_path local isfile=lfs.isfile -local done=false -local function locate(required,version,trace,report,action) - if type(required)~="string" then - report("provide a proper library name") - return - end - if trace then - report("requiring library %a with version %a",required,version or "any") - end - local found_library=nil - local required_full=gsub(required,"%.","/") - local required_path=pathpart(required_full) - local required_base=nameonly(required_full) - if qualifiedpath(required) then - if isfile(addsuffix(required,os.libsuffix)) then - if trace then - report("qualified name %a found",required) +local findfile=resolvers.findfile +local expandpaths=resolvers.expandedpathlistfromvariable +local report=logs.reporter("resolvers","libraries") +local trace=false +trackers.register("resolvers.lib",function(v) trace=v end) +local function findlib(required) + local suffix=os.libsuffix or "so" + if not qualifiedpath(required) then + local list=directives.value("system.librarynames" ) + local only=nameonly(required) + if type(list)=="table" then + list=list[only] + if type(list)~="table" then + list={ only } end - found_library=required else - if trace then - report("qualified name %a not found",required) - end - end - else - local required_name=required_base.."."..os.libsuffix - local version=type(version)=="string" and version~="" and version or false - local engine=environment.ownmain or false - if trace and not done then - local list=expandpaths("lib") - for i=1,#list do - report("tds path %i: %s",i,list[i]) - end + list={ only } end - local function found(locate,asked_library,how,...) - if trace then - report("checking %s: %a",how,asked_library) - end - return locate(asked_library,...) + if trace then + report("using lookup list for library %a: % | t",only,list) end - local function check(locate,...) - local found=nil - if version then - local asked_library=joinfile(required_path,version,required_name) - if trace then - report("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) + for i=1,#list do + local name=list[i] + local found=findfile(name,"lib") + if not found then + found=findfile(addsuffix(name,suffix),"lib") end - if not found or found=="" then - local asked_library=joinfile(required_path,required_name) + if found then if trace then - report("checking %s: %a","with version",asked_library) + report("library %a resolved via %a path to %a",name,"tds lib",found) end - found=locate(asked_library,...) - end - return found and found~="" and found or false - end - local function attempt(checkpattern) - if trace then - report("checking tds lib paths strictly") - end - local found=findfile and check(findfile,"lib") - if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace then - report("checking tds lib paths with wildcard") - end - local asked_library=joinfile(required_path,".*",required_name) - if trace then - report("checking %s: %a","latest version",asked_library) - end - local list=findfiles(asked_library,"lib",true) - if list and #list>0 then - sort(list) - local found=list[#list] - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - if trace then - report("checking lib paths") - end - package.extralibpath(environment.ownpath) - local paths=package.libpaths() - local pattern="/[^/]+%."..os.libsuffix.."$" - for i=1,#paths do - required_path=gsub(paths[i],pattern,"") - local found=check(lfs.isfound) - if type(found)=="string" and (not checkpattern or find(found,checkpattern)) then - return found - end - end - return false end - if engine then - if trace then - report("attemp 1, engine %a",engine) - end - found_library=attempt("/"..engine.."/") - if not found_library then - if trace then - report("attemp 2, no engine",asked_library) + if expandpaths then + local list=expandpaths("PATH") + local base=addsuffix(only,suffix) + for i=1,#list do + local full=joinfile(list[i],base) + local found=isfile(full) and full + if found then + if trace then + report("library %a resolved via %a path to %a",name,"system",found) + end + return found end - found_library=attempt() end - else - found_library=attempt() end - end - if not found_library then + elseif isfile(addsuffix(required,suffix)) then if trace then - report("not found: %a",required) + report("library with qualified name %a %sfound",required,"") end - library=false + return required else if trace then - report("found: %a",found_library) - end - local result,message=action(found_library,required_base) - if result then - library=result - else - library=false - report("load error: message %a, library %a",tostring(message or "unknown"),found_library or "no library") + report("library with qualified name %a %sfound",required,"not ") end end - if trace then - if not library then - report("unknown library: %a",required) - else - report("stored library: %a",required) - end - end - return library or nil + return false end -resolvers.locatelib=locate -do - local report_swiglib=logs.reporter("swiglib") - local trace_swiglib=false - local savedrequire=require - local loadedlibs={} - local loadlib=package.loadlib - local pushdir=dir.push - local popdir=dir.pop - trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) - function requireswiglib(required,version) - local library=loadedlibs[library] - if library==nil then - local trace_swiglib=trace_swiglib or package.helpers.trace - library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) - pushdir(pathpart(name)) - local opener="luaopen_"..base - if trace_swiglib then - report_swiglib("opening: %a with %a",name,opener) - end - local library,message=loadlib(name,opener) - local libtype=type(library) - if libtype=="function" then - library=library() +local foundlibraries=table.setmetatableindex(function(t,k) + local v=findlib(k) + t[k]=v + return v +end) +function resolvers.findlib(required) + return foundlibraries[required] +end +local libraries={} +resolvers.libraries=libraries +local report=logs.reporter("optional") +if optional then optional.loaded={} end +function libraries.validoptional(name) + local thelib=optional and optional[name] + if not thelib then + elseif thelib.initialize then + return thelib + else + report("invalid optional library %a",libname) + end +end +function libraries.optionalloaded(name,libnames) + local thelib=optional and optional[name] + if not thelib then + report("no optional %a library found",name) + else + local thelib_initialize=thelib.initialize + if not thelib_initialize then + report("invalid optional library %a",name) + else + if type(libnames)=="string" then + libnames={ libnames } + end + if type(libnames)=="table" then + for i=1,#libnames do + local libname=libnames[i] + local filename=foundlibraries[libname] + if filename then + libnames[i]=filename + else + report("unable to locate library %a",libname) + return + end + end + local initialized=thelib_initialize(unpack(libnames)) + if initialized then + report("using library '% + t'",libnames) else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + report("unable to initialize library '% + t'",libnames) end - popdir() - return library - end) - loadedlibs[required]=library or false - end - return library - end - function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) - end - end - local swiglibs={} - local initializer="core" - function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer - else - fullname="swiglib."..name + return initialized end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end - statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end - end) end if FFISUPPORTED and ffi and ffi.load then - local report_ffilib=logs.reporter("ffilib") - local trace_ffilib=false - local savedffiload=ffi.load - trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) - local loaded={} - local function locateindeed(name) - name=removesuffix(name) - local l=loaded[name] - if l==nil then - local state,library=pcall(savedffiload,name) - if type(library)=="userdata" then - l=library - elseif type(state)=="userdata" then - l=state - else - l=false - end - loaded[name]=l - elseif trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local function getlist(required) - local list=directives.value("system.librarynames" ) - if type(list)=="table" then - list=list[required] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",required,list) - end - return list - end - end - return { required } - end - function ffilib(name,version) - name=removesuffix(name) - local l=loaded[name] - if l~=nil then - if trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local list=getlist(name) - if version=="system" then - for i=1,#list do - local library=locateindeed(list[i]) - if type(library)=="userdata" then - return library - end - end - else - for i=1,#list do - local library=locate(list[i],version,trace_ffilib,report_ffilib,locateindeed) - if type(library)=="userdata" then - return library - end - end - end - end + local ffiload=ffi.load function ffi.load(name) - local list=getlist(name) - for i=1,#list do - local library=ffilib(list[i]) - if type(library)=="userdata" then - return library - end - end - if trace_ffilib then - report_ffilib("trying to load %a using normal loader",name) - end - for i=1,#list do - local state,library=pcall(savedffiload,list[i]) - if type(library)=="userdata" then - return library - elseif type(state)=="userdata" then - return library - end - end - end -end -do - local isfile=lfs.isfile - local report=logs.reporter("resolvers","lib") - local trace=false - trackers.register("resolvers.lib",function(v) trace=v end) - local function action(filename) - return isfile(filename) and filename or false - end - function resolvers.findlib(required) - local list=directives.value("system.librarynames" ) - local only=nameonly(required) - if type(list)=="table" then - list=list[only] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",only,list) - end - else - list={ only } - end + local full=name and foundlibraries[name] + if full then + return ffiload(full) else - list={ only } - end - for i=1,#list do - local name=list[i] - local found=locate(name,false,trace,report,action) - if found then - return found - end - end - local getpaths=resolvers.expandedpathlistfromvariable - if getpaths then - local list=getpaths("PATH") - local base=addsuffix(only,os.libsuffix) - for i=1,#list do - local full=joinfile(list[i],base) - local found=locate(full,false,trace,report,action) - if found then - return found - end - end + return ffiload(name) end end end @@ -26187,10 +26075,10 @@ end end -- of closure --- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1047142 --- stripped bytes : 416876 +-- original bytes : 1038128 +-- stripped bytes : 410736 -- end library merge @@ -26304,7 +26192,7 @@ local ownlibs = { -- order can be made better 'data-tmf.lua', 'data-lst.lua', - 'util-lib.lua', -- swiglib + 'libs-ini.lua', 'luat-sta.lua', 'luat-fmt.lua', diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index bcc3bb243..15e99eb91 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -2102,7 +2102,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 42339, stripped down to: 21588 +-- original size: 41758, stripped down to: 22643 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2445,13 +2445,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -2470,6 +2470,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -2490,6 +2492,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -2561,6 +2565,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -2570,7 +2576,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -2598,12 +2604,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -2611,12 +2621,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -2625,6 +2639,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -2641,6 +2657,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -2653,11 +2671,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -2679,6 +2699,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -2698,6 +2720,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -2715,6 +2739,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -2738,6 +2764,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3779,7 +3806,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-os"] = package.loaded["l-os"] or true --- original size: 18925, stripped down to: 10095 +-- original size: 19102, stripped down to: 10192 if not modules then modules={} end modules ['l-os']={ version=1.001, @@ -4200,6 +4227,12 @@ function os.validdate(year,month,day) end return year,month,day end +function os.date(fmt,...) + if not fmt then + fmt="%Y-%m-%d %H:%M" + end + return date(fmt,...) +end local osexit=os.exit local exitcode=nil function os.setexitcode(code) @@ -6530,7 +6563,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 45072, stripped down to: 22629 +-- original size: 45188, stripped down to: 22734 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -6945,9 +6978,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -7412,7 +7448,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 29567, stripped down to: 16483 +-- original size: 32649, stripped down to: 18257 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7649,92 +7685,160 @@ function tables.encapsulate(core,capsule,protect) } ) end end -local f_hashed_string=formatters["[%Q]=%Q,"] -local f_hashed_number=formatters["[%Q]=%s,"] -local f_hashed_boolean=formatters["[%Q]=%l,"] -local f_hashed_table=formatters["[%Q]="] -local f_indexed_string=formatters["[%s]=%Q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%Q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(0,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(0,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(0) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(0,v) +if JITSUPPORTED then + local f_hashed_string=formatters["[%Q]=%Q,"] + local f_hashed_number=formatters["[%Q]=%s,"] + local f_hashed_boolean=formatters["[%Q]=%l,"] + local f_hashed_table=formatters["[%Q]="] + local f_indexed_string=formatters["[%s]=%Q,"] + local f_indexed_number=formatters["[%s]=%s,"] + local f_indexed_boolean=formatters["[%s]=%l,"] + local f_indexed_table=formatters["[%s]="] + local f_ordered_string=formatters["%Q,"] + local f_ordered_number=formatters["%s,"] + local f_ordered_boolean=formatters["%l,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(0,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(0,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(0) + fastserialize(v) + m=m+1 r[m]=f_indexed_table(0) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) + for i=1,n do + local v=t[i] + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_ordered_string(v) + elseif tv=="number" then + m=m+1 r[m]=f_ordered_number(v) + elseif tv=="table" then + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_ordered_boolean(v) + end end end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(k,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(k,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(k) + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(k,v) + end + end + else local tv=type(v) if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) + m=m+1 r[m]=f_hashed_string(k,v) elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) + m=m+1 r[m]=f_hashed_number(k,v) elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) + m=m+1 r[m]=f_hashed_table(k) fastserialize(v) elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) + m=m+1 r[m]=f_hashed_boolean(k,v) end end + end + m=m+1 + if outer then + r[m]="}" else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end + r[m]="}," end + return r end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," + return concat(fastserialize(t,true)) + end +else + local f_v=formatters["[%q]=%q,"] + local f_t=formatters["[%q]="] + local f_q=formatters["%q,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + m=m+1 + r[m]="[0]='" + if type(v)=="table" then + fastserialize(v) + else + r[m]=format("%q,",v) + end + end + for i=1,n do + local v=t[i] + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",i) + fastserialize(v) + else + r[m]=format("[%i]=%q,",i,v) + end + end + end + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",k) + fastserialize(v) + else + r[m]=format("[%i]=%q,",k,v) + end + end + else + m=m+1 + if type(v)=="table" then + r[m]=format("[%q]=",k) + fastserialize(v) + else + r[m]=format("[%q]=%q,",k,v) + end + end + end + m=m+1 + if outer then + r[m]="}" + else + r[m]="}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) end function table.deserialize(str) if not str or str=="" then @@ -7828,27 +7932,27 @@ function table.twowaymapper(t) return t end local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] +local f_start_key_num=JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str=formatters["%w[%q]={"] local f_start_key_boo=formatters["%w[%l]={"] local f_start_key_nop=formatters["%w{"] local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%Q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%Q,"] +local f_key_num_value_num=JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num=JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num=JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] +local f_key_num_value_str=JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str=formatters["%w[%Q]=%Q,"] local f_key_boo_value_str=formatters["%w[%l]=%Q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] +local f_key_num_value_boo=JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo=formatters["%w[%Q]=%l,"] local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] +local f_key_num_value_not=JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not=formatters["%w[%Q]={},"] local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq=JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq=formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] +local f_val_num=JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str=formatters["%w%Q,"] local f_val_boo=formatters["%w%l,"] local f_val_not=formatters["%w{},"] @@ -21589,7 +21693,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16070, stripped down to: 11353 +-- original size: 16099, stripped down to: 11379 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21876,7 +21980,7 @@ function caches.is_writable(filepath,filename) local tmaname,tmcname=setluanames(filepath,filename) return is_writable(tmaname) end -local saveoptions={ compact=true } +local saveoptions={ compact=true,accurate=not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname,tmcname=setluanames(filepath,filename) data.cache_uuid=osuuid() @@ -25385,363 +25489,147 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-lib"] = package.loaded["util-lib"] or true +package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 17659, stripped down to: 9560 +-- original size: 5822, stripped down to: 3629 -if not modules then modules={} end modules ['util-lib']={ +if not modules then modules={} end modules ['libs-ini']={ version=1.001, comment="companion to luat-lib.mkiv", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", + license="see context related readme files" } +local type,unpack=type,unpack local type=type -local next=next -local pcall=pcall -local gsub=string.gsub -local find=string.find -local sort=table.sort -local pathpart=file.pathpart local nameonly=file.nameonly local joinfile=file.join -local removesuffix=file.removesuffix local addsuffix=file.addsuffix -local findfile=resolvers.findfile -local findfiles=resolvers.findfiles -local expandpaths=resolvers.expandedpathlistfromvariable local qualifiedpath=file.is_qualified_path local isfile=lfs.isfile -local done=false -local function locate(required,version,trace,report,action) - if type(required)~="string" then - report("provide a proper library name") - return - end - if trace then - report("requiring library %a with version %a",required,version or "any") - end - local found_library=nil - local required_full=gsub(required,"%.","/") - local required_path=pathpart(required_full) - local required_base=nameonly(required_full) - if qualifiedpath(required) then - if isfile(addsuffix(required,os.libsuffix)) then - if trace then - report("qualified name %a found",required) +local findfile=resolvers.findfile +local expandpaths=resolvers.expandedpathlistfromvariable +local report=logs.reporter("resolvers","libraries") +local trace=false +trackers.register("resolvers.lib",function(v) trace=v end) +local function findlib(required) + local suffix=os.libsuffix or "so" + if not qualifiedpath(required) then + local list=directives.value("system.librarynames" ) + local only=nameonly(required) + if type(list)=="table" then + list=list[only] + if type(list)~="table" then + list={ only } end - found_library=required else - if trace then - report("qualified name %a not found",required) - end - end - else - local required_name=required_base.."."..os.libsuffix - local version=type(version)=="string" and version~="" and version or false - local engine=environment.ownmain or false - if trace and not done then - local list=expandpaths("lib") - for i=1,#list do - report("tds path %i: %s",i,list[i]) - end + list={ only } end - local function found(locate,asked_library,how,...) - if trace then - report("checking %s: %a",how,asked_library) - end - return locate(asked_library,...) + if trace then + report("using lookup list for library %a: % | t",only,list) end - local function check(locate,...) - local found=nil - if version then - local asked_library=joinfile(required_path,version,required_name) - if trace then - report("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) + for i=1,#list do + local name=list[i] + local found=findfile(name,"lib") + if not found then + found=findfile(addsuffix(name,suffix),"lib") end - if not found or found=="" then - local asked_library=joinfile(required_path,required_name) + if found then if trace then - report("checking %s: %a","with version",asked_library) + report("library %a resolved via %a path to %a",name,"tds lib",found) end - found=locate(asked_library,...) - end - return found and found~="" and found or false - end - local function attempt(checkpattern) - if trace then - report("checking tds lib paths strictly") - end - local found=findfile and check(findfile,"lib") - if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace then - report("checking tds lib paths with wildcard") - end - local asked_library=joinfile(required_path,".*",required_name) - if trace then - report("checking %s: %a","latest version",asked_library) - end - local list=findfiles(asked_library,"lib",true) - if list and #list>0 then - sort(list) - local found=list[#list] - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - if trace then - report("checking lib paths") - end - package.extralibpath(environment.ownpath) - local paths=package.libpaths() - local pattern="/[^/]+%."..os.libsuffix.."$" - for i=1,#paths do - required_path=gsub(paths[i],pattern,"") - local found=check(lfs.isfound) - if type(found)=="string" and (not checkpattern or find(found,checkpattern)) then - return found - end - end - return false end - if engine then - if trace then - report("attemp 1, engine %a",engine) - end - found_library=attempt("/"..engine.."/") - if not found_library then - if trace then - report("attemp 2, no engine",asked_library) + if expandpaths then + local list=expandpaths("PATH") + local base=addsuffix(only,suffix) + for i=1,#list do + local full=joinfile(list[i],base) + local found=isfile(full) and full + if found then + if trace then + report("library %a resolved via %a path to %a",name,"system",found) + end + return found end - found_library=attempt() end - else - found_library=attempt() end - end - if not found_library then + elseif isfile(addsuffix(required,suffix)) then if trace then - report("not found: %a",required) + report("library with qualified name %a %sfound",required,"") end - library=false + return required else if trace then - report("found: %a",found_library) - end - local result,message=action(found_library,required_base) - if result then - library=result - else - library=false - report("load error: message %a, library %a",tostring(message or "unknown"),found_library or "no library") + report("library with qualified name %a %sfound",required,"not ") end end - if trace then - if not library then - report("unknown library: %a",required) - else - report("stored library: %a",required) - end - end - return library or nil + return false end -resolvers.locatelib=locate -do - local report_swiglib=logs.reporter("swiglib") - local trace_swiglib=false - local savedrequire=require - local loadedlibs={} - local loadlib=package.loadlib - local pushdir=dir.push - local popdir=dir.pop - trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) - function requireswiglib(required,version) - local library=loadedlibs[library] - if library==nil then - local trace_swiglib=trace_swiglib or package.helpers.trace - library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) - pushdir(pathpart(name)) - local opener="luaopen_"..base - if trace_swiglib then - report_swiglib("opening: %a with %a",name,opener) - end - local library,message=loadlib(name,opener) - local libtype=type(library) - if libtype=="function" then - library=library() +local foundlibraries=table.setmetatableindex(function(t,k) + local v=findlib(k) + t[k]=v + return v +end) +function resolvers.findlib(required) + return foundlibraries[required] +end +local libraries={} +resolvers.libraries=libraries +local report=logs.reporter("optional") +if optional then optional.loaded={} end +function libraries.validoptional(name) + local thelib=optional and optional[name] + if not thelib then + elseif thelib.initialize then + return thelib + else + report("invalid optional library %a",libname) + end +end +function libraries.optionalloaded(name,libnames) + local thelib=optional and optional[name] + if not thelib then + report("no optional %a library found",name) + else + local thelib_initialize=thelib.initialize + if not thelib_initialize then + report("invalid optional library %a",name) + else + if type(libnames)=="string" then + libnames={ libnames } + end + if type(libnames)=="table" then + for i=1,#libnames do + local libname=libnames[i] + local filename=foundlibraries[libname] + if filename then + libnames[i]=filename + else + report("unable to locate library %a",libname) + return + end + end + local initialized=thelib_initialize(unpack(libnames)) + if initialized then + report("using library '% + t'",libnames) else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + report("unable to initialize library '% + t'",libnames) end - popdir() - return library - end) - loadedlibs[required]=library or false - end - return library - end - function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) - end - end - local swiglibs={} - local initializer="core" - function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer - else - fullname="swiglib."..name + return initialized end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end - statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end - end) end if FFISUPPORTED and ffi and ffi.load then - local report_ffilib=logs.reporter("ffilib") - local trace_ffilib=false - local savedffiload=ffi.load - trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) - local loaded={} - local function locateindeed(name) - name=removesuffix(name) - local l=loaded[name] - if l==nil then - local state,library=pcall(savedffiload,name) - if type(library)=="userdata" then - l=library - elseif type(state)=="userdata" then - l=state - else - l=false - end - loaded[name]=l - elseif trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local function getlist(required) - local list=directives.value("system.librarynames" ) - if type(list)=="table" then - list=list[required] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",required,list) - end - return list - end - end - return { required } - end - function ffilib(name,version) - name=removesuffix(name) - local l=loaded[name] - if l~=nil then - if trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local list=getlist(name) - if version=="system" then - for i=1,#list do - local library=locateindeed(list[i]) - if type(library)=="userdata" then - return library - end - end - else - for i=1,#list do - local library=locate(list[i],version,trace_ffilib,report_ffilib,locateindeed) - if type(library)=="userdata" then - return library - end - end - end - end + local ffiload=ffi.load function ffi.load(name) - local list=getlist(name) - for i=1,#list do - local library=ffilib(list[i]) - if type(library)=="userdata" then - return library - end - end - if trace_ffilib then - report_ffilib("trying to load %a using normal loader",name) - end - for i=1,#list do - local state,library=pcall(savedffiload,list[i]) - if type(library)=="userdata" then - return library - elseif type(state)=="userdata" then - return library - end - end - end -end -do - local isfile=lfs.isfile - local report=logs.reporter("resolvers","lib") - local trace=false - trackers.register("resolvers.lib",function(v) trace=v end) - local function action(filename) - return isfile(filename) and filename or false - end - function resolvers.findlib(required) - local list=directives.value("system.librarynames" ) - local only=nameonly(required) - if type(list)=="table" then - list=list[only] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",only,list) - end - else - list={ only } - end + local full=name and foundlibraries[name] + if full then + return ffiload(full) else - list={ only } - end - for i=1,#list do - local name=list[i] - local found=locate(name,false,trace,report,action) - if found then - return found - end - end - local getpaths=resolvers.expandedpathlistfromvariable - if getpaths then - local list=getpaths("PATH") - local base=addsuffix(only,os.libsuffix) - for i=1,#list do - local full=joinfile(list[i],base) - local found=locate(full,false,trace,report,action) - if found then - return found - end - end + return ffiload(name) end end end @@ -26187,10 +26075,10 @@ end end -- of closure --- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1047142 --- stripped bytes : 416876 +-- original bytes : 1038128 +-- stripped bytes : 410736 -- end library merge @@ -26304,7 +26192,7 @@ local ownlibs = { -- order can be made better 'data-tmf.lua', 'data-lst.lua', - 'util-lib.lua', -- swiglib + 'libs-ini.lua', 'luat-sta.lua', 'luat-fmt.lua', diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index bcc3bb243..15e99eb91 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -2102,7 +2102,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 42339, stripped down to: 21588 +-- original size: 41758, stripped down to: 22643 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2445,13 +2445,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -2470,6 +2470,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -2490,6 +2492,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -2561,6 +2565,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -2570,7 +2576,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -2598,12 +2604,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -2611,12 +2621,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -2625,6 +2639,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -2641,6 +2657,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -2653,11 +2671,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -2679,6 +2699,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -2698,6 +2720,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -2715,6 +2739,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -2738,6 +2764,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3779,7 +3806,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-os"] = package.loaded["l-os"] or true --- original size: 18925, stripped down to: 10095 +-- original size: 19102, stripped down to: 10192 if not modules then modules={} end modules ['l-os']={ version=1.001, @@ -4200,6 +4227,12 @@ function os.validdate(year,month,day) end return year,month,day end +function os.date(fmt,...) + if not fmt then + fmt="%Y-%m-%d %H:%M" + end + return date(fmt,...) +end local osexit=os.exit local exitcode=nil function os.setexitcode(code) @@ -6530,7 +6563,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 45072, stripped down to: 22629 +-- original size: 45188, stripped down to: 22734 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -6945,9 +6978,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -7412,7 +7448,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 29567, stripped down to: 16483 +-- original size: 32649, stripped down to: 18257 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7649,92 +7685,160 @@ function tables.encapsulate(core,capsule,protect) } ) end end -local f_hashed_string=formatters["[%Q]=%Q,"] -local f_hashed_number=formatters["[%Q]=%s,"] -local f_hashed_boolean=formatters["[%Q]=%l,"] -local f_hashed_table=formatters["[%Q]="] -local f_indexed_string=formatters["[%s]=%Q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%Q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(0,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(0,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(0) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(0,v) +if JITSUPPORTED then + local f_hashed_string=formatters["[%Q]=%Q,"] + local f_hashed_number=formatters["[%Q]=%s,"] + local f_hashed_boolean=formatters["[%Q]=%l,"] + local f_hashed_table=formatters["[%Q]="] + local f_indexed_string=formatters["[%s]=%Q,"] + local f_indexed_number=formatters["[%s]=%s,"] + local f_indexed_boolean=formatters["[%s]=%l,"] + local f_indexed_table=formatters["[%s]="] + local f_ordered_string=formatters["%Q,"] + local f_ordered_number=formatters["%s,"] + local f_ordered_boolean=formatters["%l,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(0,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(0,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(0) + fastserialize(v) + m=m+1 r[m]=f_indexed_table(0) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) + for i=1,n do + local v=t[i] + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_ordered_string(v) + elseif tv=="number" then + m=m+1 r[m]=f_ordered_number(v) + elseif tv=="table" then + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_ordered_boolean(v) + end end end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(k,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(k,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(k) + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(k,v) + end + end + else local tv=type(v) if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) + m=m+1 r[m]=f_hashed_string(k,v) elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) + m=m+1 r[m]=f_hashed_number(k,v) elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) + m=m+1 r[m]=f_hashed_table(k) fastserialize(v) elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) + m=m+1 r[m]=f_hashed_boolean(k,v) end end + end + m=m+1 + if outer then + r[m]="}" else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end + r[m]="}," end + return r end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," + return concat(fastserialize(t,true)) + end +else + local f_v=formatters["[%q]=%q,"] + local f_t=formatters["[%q]="] + local f_q=formatters["%q,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + m=m+1 + r[m]="[0]='" + if type(v)=="table" then + fastserialize(v) + else + r[m]=format("%q,",v) + end + end + for i=1,n do + local v=t[i] + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",i) + fastserialize(v) + else + r[m]=format("[%i]=%q,",i,v) + end + end + end + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",k) + fastserialize(v) + else + r[m]=format("[%i]=%q,",k,v) + end + end + else + m=m+1 + if type(v)=="table" then + r[m]=format("[%q]=",k) + fastserialize(v) + else + r[m]=format("[%q]=%q,",k,v) + end + end + end + m=m+1 + if outer then + r[m]="}" + else + r[m]="}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) end function table.deserialize(str) if not str or str=="" then @@ -7828,27 +7932,27 @@ function table.twowaymapper(t) return t end local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] +local f_start_key_num=JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str=formatters["%w[%q]={"] local f_start_key_boo=formatters["%w[%l]={"] local f_start_key_nop=formatters["%w{"] local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%Q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%Q,"] +local f_key_num_value_num=JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num=JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num=JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] +local f_key_num_value_str=JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str=formatters["%w[%Q]=%Q,"] local f_key_boo_value_str=formatters["%w[%l]=%Q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] +local f_key_num_value_boo=JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo=formatters["%w[%Q]=%l,"] local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] +local f_key_num_value_not=JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not=formatters["%w[%Q]={},"] local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq=JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq=formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] +local f_val_num=JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str=formatters["%w%Q,"] local f_val_boo=formatters["%w%l,"] local f_val_not=formatters["%w{},"] @@ -21589,7 +21693,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16070, stripped down to: 11353 +-- original size: 16099, stripped down to: 11379 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21876,7 +21980,7 @@ function caches.is_writable(filepath,filename) local tmaname,tmcname=setluanames(filepath,filename) return is_writable(tmaname) end -local saveoptions={ compact=true } +local saveoptions={ compact=true,accurate=not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname,tmcname=setluanames(filepath,filename) data.cache_uuid=osuuid() @@ -25385,363 +25489,147 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-lib"] = package.loaded["util-lib"] or true +package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 17659, stripped down to: 9560 +-- original size: 5822, stripped down to: 3629 -if not modules then modules={} end modules ['util-lib']={ +if not modules then modules={} end modules ['libs-ini']={ version=1.001, comment="companion to luat-lib.mkiv", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", + license="see context related readme files" } +local type,unpack=type,unpack local type=type -local next=next -local pcall=pcall -local gsub=string.gsub -local find=string.find -local sort=table.sort -local pathpart=file.pathpart local nameonly=file.nameonly local joinfile=file.join -local removesuffix=file.removesuffix local addsuffix=file.addsuffix -local findfile=resolvers.findfile -local findfiles=resolvers.findfiles -local expandpaths=resolvers.expandedpathlistfromvariable local qualifiedpath=file.is_qualified_path local isfile=lfs.isfile -local done=false -local function locate(required,version,trace,report,action) - if type(required)~="string" then - report("provide a proper library name") - return - end - if trace then - report("requiring library %a with version %a",required,version or "any") - end - local found_library=nil - local required_full=gsub(required,"%.","/") - local required_path=pathpart(required_full) - local required_base=nameonly(required_full) - if qualifiedpath(required) then - if isfile(addsuffix(required,os.libsuffix)) then - if trace then - report("qualified name %a found",required) +local findfile=resolvers.findfile +local expandpaths=resolvers.expandedpathlistfromvariable +local report=logs.reporter("resolvers","libraries") +local trace=false +trackers.register("resolvers.lib",function(v) trace=v end) +local function findlib(required) + local suffix=os.libsuffix or "so" + if not qualifiedpath(required) then + local list=directives.value("system.librarynames" ) + local only=nameonly(required) + if type(list)=="table" then + list=list[only] + if type(list)~="table" then + list={ only } end - found_library=required else - if trace then - report("qualified name %a not found",required) - end - end - else - local required_name=required_base.."."..os.libsuffix - local version=type(version)=="string" and version~="" and version or false - local engine=environment.ownmain or false - if trace and not done then - local list=expandpaths("lib") - for i=1,#list do - report("tds path %i: %s",i,list[i]) - end + list={ only } end - local function found(locate,asked_library,how,...) - if trace then - report("checking %s: %a",how,asked_library) - end - return locate(asked_library,...) + if trace then + report("using lookup list for library %a: % | t",only,list) end - local function check(locate,...) - local found=nil - if version then - local asked_library=joinfile(required_path,version,required_name) - if trace then - report("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) + for i=1,#list do + local name=list[i] + local found=findfile(name,"lib") + if not found then + found=findfile(addsuffix(name,suffix),"lib") end - if not found or found=="" then - local asked_library=joinfile(required_path,required_name) + if found then if trace then - report("checking %s: %a","with version",asked_library) + report("library %a resolved via %a path to %a",name,"tds lib",found) end - found=locate(asked_library,...) - end - return found and found~="" and found or false - end - local function attempt(checkpattern) - if trace then - report("checking tds lib paths strictly") - end - local found=findfile and check(findfile,"lib") - if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace then - report("checking tds lib paths with wildcard") - end - local asked_library=joinfile(required_path,".*",required_name) - if trace then - report("checking %s: %a","latest version",asked_library) - end - local list=findfiles(asked_library,"lib",true) - if list and #list>0 then - sort(list) - local found=list[#list] - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - if trace then - report("checking lib paths") - end - package.extralibpath(environment.ownpath) - local paths=package.libpaths() - local pattern="/[^/]+%."..os.libsuffix.."$" - for i=1,#paths do - required_path=gsub(paths[i],pattern,"") - local found=check(lfs.isfound) - if type(found)=="string" and (not checkpattern or find(found,checkpattern)) then - return found - end - end - return false end - if engine then - if trace then - report("attemp 1, engine %a",engine) - end - found_library=attempt("/"..engine.."/") - if not found_library then - if trace then - report("attemp 2, no engine",asked_library) + if expandpaths then + local list=expandpaths("PATH") + local base=addsuffix(only,suffix) + for i=1,#list do + local full=joinfile(list[i],base) + local found=isfile(full) and full + if found then + if trace then + report("library %a resolved via %a path to %a",name,"system",found) + end + return found end - found_library=attempt() end - else - found_library=attempt() end - end - if not found_library then + elseif isfile(addsuffix(required,suffix)) then if trace then - report("not found: %a",required) + report("library with qualified name %a %sfound",required,"") end - library=false + return required else if trace then - report("found: %a",found_library) - end - local result,message=action(found_library,required_base) - if result then - library=result - else - library=false - report("load error: message %a, library %a",tostring(message or "unknown"),found_library or "no library") + report("library with qualified name %a %sfound",required,"not ") end end - if trace then - if not library then - report("unknown library: %a",required) - else - report("stored library: %a",required) - end - end - return library or nil + return false end -resolvers.locatelib=locate -do - local report_swiglib=logs.reporter("swiglib") - local trace_swiglib=false - local savedrequire=require - local loadedlibs={} - local loadlib=package.loadlib - local pushdir=dir.push - local popdir=dir.pop - trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) - function requireswiglib(required,version) - local library=loadedlibs[library] - if library==nil then - local trace_swiglib=trace_swiglib or package.helpers.trace - library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) - pushdir(pathpart(name)) - local opener="luaopen_"..base - if trace_swiglib then - report_swiglib("opening: %a with %a",name,opener) - end - local library,message=loadlib(name,opener) - local libtype=type(library) - if libtype=="function" then - library=library() +local foundlibraries=table.setmetatableindex(function(t,k) + local v=findlib(k) + t[k]=v + return v +end) +function resolvers.findlib(required) + return foundlibraries[required] +end +local libraries={} +resolvers.libraries=libraries +local report=logs.reporter("optional") +if optional then optional.loaded={} end +function libraries.validoptional(name) + local thelib=optional and optional[name] + if not thelib then + elseif thelib.initialize then + return thelib + else + report("invalid optional library %a",libname) + end +end +function libraries.optionalloaded(name,libnames) + local thelib=optional and optional[name] + if not thelib then + report("no optional %a library found",name) + else + local thelib_initialize=thelib.initialize + if not thelib_initialize then + report("invalid optional library %a",name) + else + if type(libnames)=="string" then + libnames={ libnames } + end + if type(libnames)=="table" then + for i=1,#libnames do + local libname=libnames[i] + local filename=foundlibraries[libname] + if filename then + libnames[i]=filename + else + report("unable to locate library %a",libname) + return + end + end + local initialized=thelib_initialize(unpack(libnames)) + if initialized then + report("using library '% + t'",libnames) else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + report("unable to initialize library '% + t'",libnames) end - popdir() - return library - end) - loadedlibs[required]=library or false - end - return library - end - function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) - end - end - local swiglibs={} - local initializer="core" - function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer - else - fullname="swiglib."..name + return initialized end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end - statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end - end) end if FFISUPPORTED and ffi and ffi.load then - local report_ffilib=logs.reporter("ffilib") - local trace_ffilib=false - local savedffiload=ffi.load - trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) - local loaded={} - local function locateindeed(name) - name=removesuffix(name) - local l=loaded[name] - if l==nil then - local state,library=pcall(savedffiload,name) - if type(library)=="userdata" then - l=library - elseif type(state)=="userdata" then - l=state - else - l=false - end - loaded[name]=l - elseif trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local function getlist(required) - local list=directives.value("system.librarynames" ) - if type(list)=="table" then - list=list[required] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",required,list) - end - return list - end - end - return { required } - end - function ffilib(name,version) - name=removesuffix(name) - local l=loaded[name] - if l~=nil then - if trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local list=getlist(name) - if version=="system" then - for i=1,#list do - local library=locateindeed(list[i]) - if type(library)=="userdata" then - return library - end - end - else - for i=1,#list do - local library=locate(list[i],version,trace_ffilib,report_ffilib,locateindeed) - if type(library)=="userdata" then - return library - end - end - end - end + local ffiload=ffi.load function ffi.load(name) - local list=getlist(name) - for i=1,#list do - local library=ffilib(list[i]) - if type(library)=="userdata" then - return library - end - end - if trace_ffilib then - report_ffilib("trying to load %a using normal loader",name) - end - for i=1,#list do - local state,library=pcall(savedffiload,list[i]) - if type(library)=="userdata" then - return library - elseif type(state)=="userdata" then - return library - end - end - end -end -do - local isfile=lfs.isfile - local report=logs.reporter("resolvers","lib") - local trace=false - trackers.register("resolvers.lib",function(v) trace=v end) - local function action(filename) - return isfile(filename) and filename or false - end - function resolvers.findlib(required) - local list=directives.value("system.librarynames" ) - local only=nameonly(required) - if type(list)=="table" then - list=list[only] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",only,list) - end - else - list={ only } - end + local full=name and foundlibraries[name] + if full then + return ffiload(full) else - list={ only } - end - for i=1,#list do - local name=list[i] - local found=locate(name,false,trace,report,action) - if found then - return found - end - end - local getpaths=resolvers.expandedpathlistfromvariable - if getpaths then - local list=getpaths("PATH") - local base=addsuffix(only,os.libsuffix) - for i=1,#list do - local full=joinfile(list[i],base) - local found=locate(full,false,trace,report,action) - if found then - return found - end - end + return ffiload(name) end end end @@ -26187,10 +26075,10 @@ end end -- of closure --- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1047142 --- stripped bytes : 416876 +-- original bytes : 1038128 +-- stripped bytes : 410736 -- end library merge @@ -26304,7 +26192,7 @@ local ownlibs = { -- order can be made better 'data-tmf.lua', 'data-lst.lua', - 'util-lib.lua', -- swiglib + 'libs-ini.lua', 'luat-sta.lua', 'luat-fmt.lua', diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index bcc3bb243..15e99eb91 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -2102,7 +2102,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 42339, stripped down to: 21588 +-- original size: 41758, stripped down to: 22643 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2445,13 +2445,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -2470,6 +2470,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -2490,6 +2492,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -2561,6 +2565,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -2570,7 +2576,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -2598,12 +2604,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -2611,12 +2621,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -2625,6 +2639,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -2641,6 +2657,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -2653,11 +2671,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -2679,6 +2699,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -2698,6 +2720,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -2715,6 +2739,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -2738,6 +2764,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3779,7 +3806,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-os"] = package.loaded["l-os"] or true --- original size: 18925, stripped down to: 10095 +-- original size: 19102, stripped down to: 10192 if not modules then modules={} end modules ['l-os']={ version=1.001, @@ -4200,6 +4227,12 @@ function os.validdate(year,month,day) end return year,month,day end +function os.date(fmt,...) + if not fmt then + fmt="%Y-%m-%d %H:%M" + end + return date(fmt,...) +end local osexit=os.exit local exitcode=nil function os.setexitcode(code) @@ -6530,7 +6563,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 45072, stripped down to: 22629 +-- original size: 45188, stripped down to: 22734 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -6945,9 +6978,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -7412,7 +7448,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 29567, stripped down to: 16483 +-- original size: 32649, stripped down to: 18257 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7649,92 +7685,160 @@ function tables.encapsulate(core,capsule,protect) } ) end end -local f_hashed_string=formatters["[%Q]=%Q,"] -local f_hashed_number=formatters["[%Q]=%s,"] -local f_hashed_boolean=formatters["[%Q]=%l,"] -local f_hashed_table=formatters["[%Q]="] -local f_indexed_string=formatters["[%s]=%Q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%Q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(0,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(0,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(0) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(0,v) +if JITSUPPORTED then + local f_hashed_string=formatters["[%Q]=%Q,"] + local f_hashed_number=formatters["[%Q]=%s,"] + local f_hashed_boolean=formatters["[%Q]=%l,"] + local f_hashed_table=formatters["[%Q]="] + local f_indexed_string=formatters["[%s]=%Q,"] + local f_indexed_number=formatters["[%s]=%s,"] + local f_indexed_boolean=formatters["[%s]=%l,"] + local f_indexed_table=formatters["[%s]="] + local f_ordered_string=formatters["%Q,"] + local f_ordered_number=formatters["%s,"] + local f_ordered_boolean=formatters["%l,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(0,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(0,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(0) + fastserialize(v) + m=m+1 r[m]=f_indexed_table(0) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) + for i=1,n do + local v=t[i] + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_ordered_string(v) + elseif tv=="number" then + m=m+1 r[m]=f_ordered_number(v) + elseif tv=="table" then + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_ordered_boolean(v) + end end end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(k,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(k,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(k) + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(k,v) + end + end + else local tv=type(v) if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) + m=m+1 r[m]=f_hashed_string(k,v) elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) + m=m+1 r[m]=f_hashed_number(k,v) elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) + m=m+1 r[m]=f_hashed_table(k) fastserialize(v) elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) + m=m+1 r[m]=f_hashed_boolean(k,v) end end + end + m=m+1 + if outer then + r[m]="}" else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end + r[m]="}," end + return r end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," + return concat(fastserialize(t,true)) + end +else + local f_v=formatters["[%q]=%q,"] + local f_t=formatters["[%q]="] + local f_q=formatters["%q,"] + function table.fastserialize(t,prefix) + local r={ type(prefix)=="string" and prefix or "return" } + local m=1 + local function fastserialize(t,outer) + local n=#t + m=m+1 + r[m]="{" + if n>0 then + local v=t[0] + if v then + m=m+1 + r[m]="[0]='" + if type(v)=="table" then + fastserialize(v) + else + r[m]=format("%q,",v) + end + end + for i=1,n do + local v=t[i] + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",i) + fastserialize(v) + else + r[m]=format("[%i]=%q,",i,v) + end + end + end + for k,v in next,t do + local tk=type(k) + if tk=="number" then + if k>n or k<0 then + m=m+1 + if type(v)=="table" then + r[m]=format("[%i]=",k) + fastserialize(v) + else + r[m]=format("[%i]=%q,",k,v) + end + end + else + m=m+1 + if type(v)=="table" then + r[m]=format("[%q]=",k) + fastserialize(v) + else + r[m]=format("[%q]=%q,",k,v) + end + end + end + m=m+1 + if outer then + r[m]="}" + else + r[m]="}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) end function table.deserialize(str) if not str or str=="" then @@ -7828,27 +7932,27 @@ function table.twowaymapper(t) return t end local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] +local f_start_key_num=JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str=formatters["%w[%q]={"] local f_start_key_boo=formatters["%w[%l]={"] local f_start_key_nop=formatters["%w{"] local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%Q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%Q,"] +local f_key_num_value_num=JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num=JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num=JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] +local f_key_num_value_str=JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str=formatters["%w[%Q]=%Q,"] local f_key_boo_value_str=formatters["%w[%l]=%Q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] +local f_key_num_value_boo=JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo=formatters["%w[%Q]=%l,"] local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] +local f_key_num_value_not=JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not=formatters["%w[%Q]={},"] local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq=JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq=formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] +local f_val_num=JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str=formatters["%w%Q,"] local f_val_boo=formatters["%w%l,"] local f_val_not=formatters["%w{},"] @@ -21589,7 +21693,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16070, stripped down to: 11353 +-- original size: 16099, stripped down to: 11379 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21876,7 +21980,7 @@ function caches.is_writable(filepath,filename) local tmaname,tmcname=setluanames(filepath,filename) return is_writable(tmaname) end -local saveoptions={ compact=true } +local saveoptions={ compact=true,accurate=not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname,tmcname=setluanames(filepath,filename) data.cache_uuid=osuuid() @@ -25385,363 +25489,147 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-lib"] = package.loaded["util-lib"] or true +package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 17659, stripped down to: 9560 +-- original size: 5822, stripped down to: 3629 -if not modules then modules={} end modules ['util-lib']={ +if not modules then modules={} end modules ['libs-ini']={ version=1.001, comment="companion to luat-lib.mkiv", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", + license="see context related readme files" } +local type,unpack=type,unpack local type=type -local next=next -local pcall=pcall -local gsub=string.gsub -local find=string.find -local sort=table.sort -local pathpart=file.pathpart local nameonly=file.nameonly local joinfile=file.join -local removesuffix=file.removesuffix local addsuffix=file.addsuffix -local findfile=resolvers.findfile -local findfiles=resolvers.findfiles -local expandpaths=resolvers.expandedpathlistfromvariable local qualifiedpath=file.is_qualified_path local isfile=lfs.isfile -local done=false -local function locate(required,version,trace,report,action) - if type(required)~="string" then - report("provide a proper library name") - return - end - if trace then - report("requiring library %a with version %a",required,version or "any") - end - local found_library=nil - local required_full=gsub(required,"%.","/") - local required_path=pathpart(required_full) - local required_base=nameonly(required_full) - if qualifiedpath(required) then - if isfile(addsuffix(required,os.libsuffix)) then - if trace then - report("qualified name %a found",required) +local findfile=resolvers.findfile +local expandpaths=resolvers.expandedpathlistfromvariable +local report=logs.reporter("resolvers","libraries") +local trace=false +trackers.register("resolvers.lib",function(v) trace=v end) +local function findlib(required) + local suffix=os.libsuffix or "so" + if not qualifiedpath(required) then + local list=directives.value("system.librarynames" ) + local only=nameonly(required) + if type(list)=="table" then + list=list[only] + if type(list)~="table" then + list={ only } end - found_library=required else - if trace then - report("qualified name %a not found",required) - end - end - else - local required_name=required_base.."."..os.libsuffix - local version=type(version)=="string" and version~="" and version or false - local engine=environment.ownmain or false - if trace and not done then - local list=expandpaths("lib") - for i=1,#list do - report("tds path %i: %s",i,list[i]) - end + list={ only } end - local function found(locate,asked_library,how,...) - if trace then - report("checking %s: %a",how,asked_library) - end - return locate(asked_library,...) + if trace then + report("using lookup list for library %a: % | t",only,list) end - local function check(locate,...) - local found=nil - if version then - local asked_library=joinfile(required_path,version,required_name) - if trace then - report("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) + for i=1,#list do + local name=list[i] + local found=findfile(name,"lib") + if not found then + found=findfile(addsuffix(name,suffix),"lib") end - if not found or found=="" then - local asked_library=joinfile(required_path,required_name) + if found then if trace then - report("checking %s: %a","with version",asked_library) + report("library %a resolved via %a path to %a",name,"tds lib",found) end - found=locate(asked_library,...) - end - return found and found~="" and found or false - end - local function attempt(checkpattern) - if trace then - report("checking tds lib paths strictly") - end - local found=findfile and check(findfile,"lib") - if found and (not checkpattern or find(found,checkpattern)) then return found end - if trace then - report("checking tds lib paths with wildcard") - end - local asked_library=joinfile(required_path,".*",required_name) - if trace then - report("checking %s: %a","latest version",asked_library) - end - local list=findfiles(asked_library,"lib",true) - if list and #list>0 then - sort(list) - local found=list[#list] - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - if trace then - report("checking lib paths") - end - package.extralibpath(environment.ownpath) - local paths=package.libpaths() - local pattern="/[^/]+%."..os.libsuffix.."$" - for i=1,#paths do - required_path=gsub(paths[i],pattern,"") - local found=check(lfs.isfound) - if type(found)=="string" and (not checkpattern or find(found,checkpattern)) then - return found - end - end - return false end - if engine then - if trace then - report("attemp 1, engine %a",engine) - end - found_library=attempt("/"..engine.."/") - if not found_library then - if trace then - report("attemp 2, no engine",asked_library) + if expandpaths then + local list=expandpaths("PATH") + local base=addsuffix(only,suffix) + for i=1,#list do + local full=joinfile(list[i],base) + local found=isfile(full) and full + if found then + if trace then + report("library %a resolved via %a path to %a",name,"system",found) + end + return found end - found_library=attempt() end - else - found_library=attempt() end - end - if not found_library then + elseif isfile(addsuffix(required,suffix)) then if trace then - report("not found: %a",required) + report("library with qualified name %a %sfound",required,"") end - library=false + return required else if trace then - report("found: %a",found_library) - end - local result,message=action(found_library,required_base) - if result then - library=result - else - library=false - report("load error: message %a, library %a",tostring(message or "unknown"),found_library or "no library") + report("library with qualified name %a %sfound",required,"not ") end end - if trace then - if not library then - report("unknown library: %a",required) - else - report("stored library: %a",required) - end - end - return library or nil + return false end -resolvers.locatelib=locate -do - local report_swiglib=logs.reporter("swiglib") - local trace_swiglib=false - local savedrequire=require - local loadedlibs={} - local loadlib=package.loadlib - local pushdir=dir.push - local popdir=dir.pop - trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) - function requireswiglib(required,version) - local library=loadedlibs[library] - if library==nil then - local trace_swiglib=trace_swiglib or package.helpers.trace - library=locate(required,version,trace_swiglib,report_swiglib,function(name,base) - pushdir(pathpart(name)) - local opener="luaopen_"..base - if trace_swiglib then - report_swiglib("opening: %a with %a",name,opener) - end - local library,message=loadlib(name,opener) - local libtype=type(library) - if libtype=="function" then - library=library() +local foundlibraries=table.setmetatableindex(function(t,k) + local v=findlib(k) + t[k]=v + return v +end) +function resolvers.findlib(required) + return foundlibraries[required] +end +local libraries={} +resolvers.libraries=libraries +local report=logs.reporter("optional") +if optional then optional.loaded={} end +function libraries.validoptional(name) + local thelib=optional and optional[name] + if not thelib then + elseif thelib.initialize then + return thelib + else + report("invalid optional library %a",libname) + end +end +function libraries.optionalloaded(name,libnames) + local thelib=optional and optional[name] + if not thelib then + report("no optional %a library found",name) + else + local thelib_initialize=thelib.initialize + if not thelib_initialize then + report("invalid optional library %a",name) + else + if type(libnames)=="string" then + libnames={ libnames } + end + if type(libnames)=="table" then + for i=1,#libnames do + local libname=libnames[i] + local filename=foundlibraries[libname] + if filename then + libnames[i]=filename + else + report("unable to locate library %a",libname) + return + end + end + local initialized=thelib_initialize(unpack(libnames)) + if initialized then + report("using library '% + t'",libnames) else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false + report("unable to initialize library '% + t'",libnames) end - popdir() - return library - end) - loadedlibs[required]=library or false - end - return library - end - function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) - end - end - local swiglibs={} - local initializer="core" - function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer - else - fullname="swiglib."..name + return initialized end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) end - return library end - statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end - end) end if FFISUPPORTED and ffi and ffi.load then - local report_ffilib=logs.reporter("ffilib") - local trace_ffilib=false - local savedffiload=ffi.load - trackers.register("resolvers.ffilib",function(v) trace_ffilib=v end) - local loaded={} - local function locateindeed(name) - name=removesuffix(name) - local l=loaded[name] - if l==nil then - local state,library=pcall(savedffiload,name) - if type(library)=="userdata" then - l=library - elseif type(state)=="userdata" then - l=state - else - l=false - end - loaded[name]=l - elseif trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local function getlist(required) - local list=directives.value("system.librarynames" ) - if type(list)=="table" then - list=list[required] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",required,list) - end - return list - end - end - return { required } - end - function ffilib(name,version) - name=removesuffix(name) - local l=loaded[name] - if l~=nil then - if trace_ffilib then - report_ffilib("reusing already loaded %a",name) - end - return l - end - local list=getlist(name) - if version=="system" then - for i=1,#list do - local library=locateindeed(list[i]) - if type(library)=="userdata" then - return library - end - end - else - for i=1,#list do - local library=locate(list[i],version,trace_ffilib,report_ffilib,locateindeed) - if type(library)=="userdata" then - return library - end - end - end - end + local ffiload=ffi.load function ffi.load(name) - local list=getlist(name) - for i=1,#list do - local library=ffilib(list[i]) - if type(library)=="userdata" then - return library - end - end - if trace_ffilib then - report_ffilib("trying to load %a using normal loader",name) - end - for i=1,#list do - local state,library=pcall(savedffiload,list[i]) - if type(library)=="userdata" then - return library - elseif type(state)=="userdata" then - return library - end - end - end -end -do - local isfile=lfs.isfile - local report=logs.reporter("resolvers","lib") - local trace=false - trackers.register("resolvers.lib",function(v) trace=v end) - local function action(filename) - return isfile(filename) and filename or false - end - function resolvers.findlib(required) - local list=directives.value("system.librarynames" ) - local only=nameonly(required) - if type(list)=="table" then - list=list[only] - if type(list)=="table" then - if trace then - report("using lookup list for library %a: % | t",only,list) - end - else - list={ only } - end + local full=name and foundlibraries[name] + if full then + return ffiload(full) else - list={ only } - end - for i=1,#list do - local name=list[i] - local found=locate(name,false,trace,report,action) - if found then - return found - end - end - local getpaths=resolvers.expandedpathlistfromvariable - if getpaths then - local list=getpaths("PATH") - local base=addsuffix(only,os.libsuffix) - for i=1,#list do - local full=joinfile(list[i],base) - local found=locate(full,false,trace,report,action) - if found then - return found - end - end + return ffiload(name) end end end @@ -26187,10 +26075,10 @@ end end -- of closure --- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1047142 --- stripped bytes : 416876 +-- original bytes : 1038128 +-- stripped bytes : 410736 -- end library merge @@ -26304,7 +26192,7 @@ local ownlibs = { -- order can be made better 'data-tmf.lua', 'data-lst.lua', - 'util-lib.lua', -- swiglib + 'libs-ini.lua', 'luat-sta.lua', 'luat-fmt.lua', diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 9e0025e0f..8570ac7a9 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2020.01.26 18:34} +\newcontextversion{2020.02.11 16:36} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index aa7c02cf4..e02bc12dd 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} %D For those who want to use this: diff --git a/tex/context/base/mkiv/char-emj.lua b/tex/context/base/mkiv/char-emj.lua index b00e9ebf8..e6c059174 100644 --- a/tex/context/base/mkiv/char-emj.lua +++ b/tex/context/base/mkiv/char-emj.lua @@ -16,6 +16,7 @@ return { ["a button (blood type)"]={ 0x1F170, 0xFE0F }, ["ab button (blood type)"]={ 0x1F18E }, ["abacus"]={ 0x1F9EE }, + ["accordion"]={ 0x1FA97 }, ["adhesive bandage"]={ 0x1FA79 }, ["admission tickets"]={ 0x1F39F, 0xFE0F }, ["aerial tramway"]={ 0x1F6A1 }, @@ -29,6 +30,7 @@ return { ["ambulance"]={ 0x1F691 }, ["american football"]={ 0x1F3C8 }, ["amphora"]={ 0x1F3FA }, + ["anatomical heart"]={ 0x1FAC0 }, ["anchor"]={ 0x2693 }, ["anger symbol"]={ 0x1F4A2 }, ["angry face"]={ 0x1F620 }, @@ -40,8 +42,20 @@ return { ["aquarius"]={ 0x2652 }, ["aries"]={ 0x2648 }, ["articulated lorry"]={ 0x1F69B }, + ["artist"]={ 0x1F9D1, 0x200D, 0x1F3A8 }, ["artist palette"]={ 0x1F3A8 }, + ["artist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3A8 }, + ["artist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3A8 }, + ["artist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3A8 }, + ["artist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3A8 }, + ["artist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3A8 }, ["astonished face"]={ 0x1F632 }, + ["astronaut"]={ 0x1F9D1, 0x200D, 0x1F680 }, + ["astronaut: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F680 }, + ["astronaut: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F680 }, + ["astronaut: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F680 }, + ["astronaut: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F680 }, + ["astronaut: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F680 }, ["atm sign"]={ 0x1F3E7 }, ["atom symbol"]={ 0x269B, 0xFE0F }, ["auto rickshaw"]={ 0x1F6FA }, @@ -115,9 +129,12 @@ return { ["beaming face with smiling eyes"]={ 0x1F601 }, ["bear"]={ 0x1F43B }, ["beating heart"]={ 0x1F493 }, + ["beaver"]={ 0x1F9AB }, ["bed"]={ 0x1F6CF, 0xFE0F }, ["beer mug"]={ 0x1F37A }, + ["beetle"]={ 0x1FAB2 }, ["bell"]={ 0x1F514 }, + ["bell pepper"]={ 0x1FAD1 }, ["bell with slash"]={ 0x1F515 }, ["bellhop bell"]={ 0x1F6CE, 0xFE0F }, ["bento box"]={ 0x1F371 }, @@ -128,6 +145,8 @@ return { ["biohazard"]={ 0x2623, 0xFE0F }, ["bird"]={ 0x1F426 }, ["birthday cake"]={ 0x1F382 }, + ["bison"]={ 0x1F9AC }, + ["black cat"]={ 0x1F408, 0x200D, 0x2B1B }, ["black circle"]={ 0x26AB }, ["black flag"]={ 0x1F3F4 }, ["black heart"]={ 0x1F5A4 }, @@ -143,12 +162,14 @@ return { ["blue circle"]={ 0x1F535 }, ["blue heart"]={ 0x1F499 }, ["blue square"]={ 0x1F7E6 }, + ["blueberries"]={ 0x1FAD0 }, ["boar"]={ 0x1F417 }, ["bomb"]={ 0x1F4A3 }, ["bone"]={ 0x1F9B4 }, ["bookmark"]={ 0x1F516 }, ["bookmark tabs"]={ 0x1F4D1 }, ["books"]={ 0x1F4DA }, + ["boomerang"]={ 0x1FA83 }, ["bottle with popping cork"]={ 0x1F37E }, ["bouquet"]={ 0x1F490 }, ["bow and arrow"]={ 0x1F3F9 }, @@ -170,14 +191,9 @@ return { ["breast-feeding: medium-dark skin tone"]={ 0x1F931, 0x1F3FE }, ["breast-feeding: medium-light skin tone"]={ 0x1F931, 0x1F3FC }, ["brick"]={ 0x1F9F1 }, - ["bride with veil"]={ 0x1F470 }, - ["bride with veil: dark skin tone"]={ 0x1F470, 0x1F3FF }, - ["bride with veil: light skin tone"]={ 0x1F470, 0x1F3FB }, - ["bride with veil: medium skin tone"]={ 0x1F470, 0x1F3FD }, - ["bride with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE }, - ["bride with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC }, ["bridge at night"]={ 0x1F309 }, ["briefcase"]={ 0x1F4BC }, + ["briefs"]={ 0x1FA72 }, ["bright button"]={ 0x1F506 }, ["broccoli"]={ 0x1F966 }, ["broken heart"]={ 0x1F494 }, @@ -185,6 +201,8 @@ return { ["brown circle"]={ 0x1F7E4 }, ["brown heart"]={ 0x1F90E }, ["brown square"]={ 0x1F7EB }, + ["bubble tea"]={ 0x1F9CB }, + ["bucket"]={ 0x1FAA3 }, ["bug"]={ 0x1F41B }, ["building construction"]={ 0x1F3D7, 0xFE0F }, ["bullet train"]={ 0x1F685 }, @@ -218,6 +236,7 @@ return { ["card index dividers"]={ 0x1F5C2, 0xFE0F }, ["carousel horse"]={ 0x1F3A0 }, ["carp streamer"]={ 0x1F38F }, + ["carpentry saw"]={ 0x1FA9A }, ["carrot"]={ 0x1F955 }, ["castle"]={ 0x1F3F0 }, ["cat"]={ 0x1F408 }, @@ -284,9 +303,11 @@ return { ["club suit"]={ 0x2663, 0xFE0F }, ["clutch bag"]={ 0x1F45D }, ["coat"]={ 0x1F9E5 }, + ["cockroach"]={ 0x1FAB3 }, ["cocktail glass"]={ 0x1F378 }, ["coconut"]={ 0x1F965 }, ["coffin"]={ 0x26B0, 0xFE0F }, + ["coin"]={ 0x1FA99 }, ["cold face"]={ 0x1F976 }, ["collision"]={ 0x1F4A5 }, ["comet"]={ 0x2604, 0xFE0F }, @@ -305,6 +326,12 @@ return { ["construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC }, ["control knobs"]={ 0x1F39B, 0xFE0F }, ["convenience store"]={ 0x1F3EA }, + ["cook"]={ 0x1F9D1, 0x200D, 0x1F373 }, + ["cook: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F373 }, + ["cook: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F373 }, + ["cook: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F373 }, + ["cook: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F373 }, + ["cook: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F373 }, ["cooked rice"]={ 0x1F35A }, ["cookie"]={ 0x1F36A }, ["cooking"]={ 0x1F373 }, @@ -392,12 +419,14 @@ return { ["dim button"]={ 0x1F505 }, ["direct hit"]={ 0x1F3AF }, ["disappointed face"]={ 0x1F61E }, + ["disguised face"]={ 0x1F978 }, + ["divide"]={ 0x2797 }, ["diving mask"]={ 0x1F93F }, - ["division sign"]={ 0x2797 }, ["diya lamp"]={ 0x1FA94 }, ["dizzy"]={ 0x1F4AB }, ["dizzy face"]={ 0x1F635 }, ["dna"]={ 0x1F9EC }, + ["dodo"]={ 0x1F9A4 }, ["dog"]={ 0x1F415 }, ["dog face"]={ 0x1F436 }, ["dollar banknote"]={ 0x1F4B5 }, @@ -447,6 +476,7 @@ return { ["eject button"]={ 0x23CF, 0xFE0F }, ["electric plug"]={ 0x1F50C }, ["elephant"]={ 0x1F418 }, + ["elevator"]={ 0x1F6D7 }, ["eleven o’clock"]={ 0x1F55A }, ["eleven-thirty"]={ 0x1F566 }, ["elf"]={ 0x1F9DD }, @@ -486,6 +516,12 @@ return { ["face with tongue"]={ 0x1F61B }, ["face without mouth"]={ 0x1F636 }, ["factory"]={ 0x1F3ED }, + ["factory worker"]={ 0x1F9D1, 0x200D, 0x1F3ED }, + ["factory worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3ED }, + ["factory worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3ED }, + ["factory worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3ED }, + ["factory worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3ED }, + ["factory worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3ED }, ["fairy"]={ 0x1F9DA }, ["fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF }, ["fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB }, @@ -520,12 +556,19 @@ return { ["family: woman, woman, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467 }, ["family: woman, woman, girl, boy"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F466 }, ["family: woman, woman, girl, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F467 }, + ["farmer"]={ 0x1F9D1, 0x200D, 0x1F33E }, + ["farmer: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F33E }, + ["farmer: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F33E }, + ["farmer: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F33E }, + ["farmer: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F33E }, + ["farmer: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F33E }, ["fast down button"]={ 0x23EC }, ["fast reverse button"]={ 0x23EA }, ["fast up button"]={ 0x23EB }, ["fast-forward button"]={ 0x23E9 }, ["fax machine"]={ 0x1F4E0 }, ["fearful face"]={ 0x1F628 }, + ["feather"]={ 0x1FAB6 }, ["female sign"]={ 0x2640, 0xFE0F }, ["ferris wheel"]={ 0x1F3A1 }, ["ferry"]={ 0x26F4, 0xFE0F }, @@ -538,6 +581,12 @@ return { ["fire engine"]={ 0x1F692 }, ["fire extinguisher"]={ 0x1F9EF }, ["firecracker"]={ 0x1F9E8 }, + ["firefighter"]={ 0x1F9D1, 0x200D, 0x1F692 }, + ["firefighter: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F692 }, + ["firefighter: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F692 }, + ["firefighter: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F692 }, + ["firefighter: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F692 }, + ["firefighter: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F692 }, ["fireworks"]={ 0x1F386 }, ["first quarter moon"]={ 0x1F313 }, ["first quarter moon face"]={ 0x1F31B }, @@ -684,7 +733,6 @@ return { ["flag: lithuania"]={ 0x1F1F1, 0x1F1F9 }, ["flag: luxembourg"]={ 0x1F1F1, 0x1F1FA }, ["flag: macao sar china"]={ 0x1F1F2, 0x1F1F4 }, - ["flag: macedonia"]={ 0x1F1F2, 0x1F1F0 }, ["flag: madagascar"]={ 0x1F1F2, 0x1F1EC }, ["flag: malawi"]={ 0x1F1F2, 0x1F1FC }, ["flag: malaysia"]={ 0x1F1F2, 0x1F1FE }, @@ -718,6 +766,7 @@ return { ["flag: niue"]={ 0x1F1F3, 0x1F1FA }, ["flag: norfolk island"]={ 0x1F1F3, 0x1F1EB }, ["flag: north korea"]={ 0x1F1F0, 0x1F1F5 }, + ["flag: north macedonia"]={ 0x1F1F2, 0x1F1F0 }, ["flag: northern mariana islands"]={ 0x1F1F2, 0x1F1F5 }, ["flag: norway"]={ 0x1F1F3, 0x1F1F4 }, ["flag: oman"]={ 0x1F1F4, 0x1F1F2 }, @@ -811,6 +860,7 @@ return { ["flamingo"]={ 0x1F9A9 }, ["flashlight"]={ 0x1F526 }, ["flat shoe"]={ 0x1F97F }, + ["flatbread"]={ 0x1FAD3 }, ["fleur-de-lis"]={ 0x269C, 0xFE0F }, ["flexed biceps"]={ 0x1F4AA }, ["flexed biceps: dark skin tone"]={ 0x1F4AA, 0x1F3FF }, @@ -821,6 +871,7 @@ return { ["floppy disk"]={ 0x1F4BE }, ["flower playing cards"]={ 0x1F3B4 }, ["flushed face"]={ 0x1F633 }, + ["fly"]={ 0x1FAB0 }, ["flying disc"]={ 0x1F94F }, ["flying saucer"]={ 0x1F6F8 }, ["fog"]={ 0x1F32B, 0xFE0F }, @@ -831,6 +882,7 @@ return { ["folded hands: medium skin tone"]={ 0x1F64F, 0x1F3FD }, ["folded hands: medium-dark skin tone"]={ 0x1F64F, 0x1F3FE }, ["folded hands: medium-light skin tone"]={ 0x1F64F, 0x1F3FC }, + ["fondue"]={ 0x1FAD5 }, ["foot"]={ 0x1F9B6 }, ["foot: dark skin tone"]={ 0x1F9B6, 0x1F3FF }, ["foot: light skin tone"]={ 0x1F9B6, 0x1F3FB }, @@ -926,6 +978,13 @@ return { ["handshake"]={ 0x1F91D }, ["hatching chick"]={ 0x1F423 }, ["headphone"]={ 0x1F3A7 }, + ["headstone"]={ 0x1FAA6 }, + ["health worker"]={ 0x1F9D1, 0x200D, 0x2695, 0xFE0F }, + ["health worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2695, 0xFE0F }, + ["health worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2695, 0xFE0F }, ["hear-no-evil monkey"]={ 0x1F649 }, ["heart decoration"]={ 0x1F49F }, ["heart exclamation"]={ 0x2763, 0xFE0F }, @@ -947,6 +1006,7 @@ return { ["hollow red circle"]={ 0x2B55 }, ["honey pot"]={ 0x1F36F }, ["honeybee"]={ 0x1F41D }, + ["hook"]={ 0x1FA9D }, ["horizontal traffic light"]={ 0x1F6A5 }, ["horse"]={ 0x1F40E }, ["horse face"]={ 0x1F434 }, @@ -971,8 +1031,9 @@ return { ["hugging face"]={ 0x1F917 }, ["hundred points"]={ 0x1F4AF }, ["hushed face"]={ 0x1F62F }, + ["hut"]={ 0x1F6D6 }, + ["ice"]={ 0x1F9CA }, ["ice cream"]={ 0x1F368 }, - ["ice cube"]={ 0x1F9CA }, ["ice hockey"]={ 0x1F3D2 }, ["ice skate"]={ 0x26F8, 0xFE0F }, ["id button"]={ 0x1F194 }, @@ -1016,6 +1077,12 @@ return { ["jeans"]={ 0x1F456 }, ["joker"]={ 0x1F0CF }, ["joystick"]={ 0x1F579, 0xFE0F }, + ["judge"]={ 0x1F9D1, 0x200D, 0x2696, 0xFE0F }, + ["judge: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, + ["judge: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2696, 0xFE0F }, ["kaaba"]={ 0x1F54B }, ["kangaroo"]={ 0x1F998 }, ["key"]={ 0x1F511 }, @@ -1047,12 +1114,14 @@ return { ["kitchen knife"]={ 0x1F52A }, ["kite"]={ 0x1FA81 }, ["kiwi fruit"]={ 0x1F95D }, + ["knot"]={ 0x1FAA2 }, ["koala"]={ 0x1F428 }, ["lab coat"]={ 0x1F97C }, ["label"]={ 0x1F3F7, 0xFE0F }, ["lacrosse"]={ 0x1F94D }, + ["ladder"]={ 0x1FA9C }, ["lady beetle"]={ 0x1F41E }, - ["laptop computer"]={ 0x1F4BB }, + ["laptop"]={ 0x1F4BB }, ["large blue diamond"]={ 0x1F537 }, ["large orange diamond"]={ 0x1F536 }, ["last quarter moon"]={ 0x1F317 }, @@ -1099,6 +1168,7 @@ return { ["locked with pen"]={ 0x1F50F }, ["locomotive"]={ 0x1F682 }, ["lollipop"]={ 0x1F36D }, + ["long drum"]={ 0x1FA98 }, ["lotion bottle"]={ 0x1F9F4 }, ["loudly crying face"]={ 0x1F62D }, ["loudspeaker"]={ 0x1F4E2 }, @@ -1111,6 +1181,7 @@ return { ["love-you gesture: medium-dark skin tone"]={ 0x1F91F, 0x1F3FE }, ["love-you gesture: medium-light skin tone"]={ 0x1F91F, 0x1F3FC }, ["luggage"]={ 0x1F9F3 }, + ["lungs"]={ 0x1FAC1 }, ["lying face"]={ 0x1F925 }, ["mage"]={ 0x1F9D9 }, ["mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF }, @@ -1118,11 +1189,13 @@ return { ["mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD }, ["mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE }, ["mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC }, + ["magic wand"]={ 0x1FA84 }, ["magnet"]={ 0x1F9F2 }, ["magnifying glass tilted left"]={ 0x1F50D }, ["magnifying glass tilted right"]={ 0x1F50E }, ["mahjong red dragon"]={ 0x1F004 }, ["male sign"]={ 0x2642, 0xFE0F }, + ["mammoth"]={ 0x1F9A3 }, ["man"]={ 0x1F468 }, ["man artist"]={ 0x1F468, 0x200D, 0x1F3A8 }, ["man artist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A8 }, @@ -1220,6 +1293,12 @@ return { ["man farmer: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F33E }, ["man farmer: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F33E }, ["man farmer: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F33E }, + ["man feeding baby"]={ 0x1F468, 0x200D, 0x1F37C }, + ["man feeding baby: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F37C }, + ["man feeding baby: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F37C }, + ["man feeding baby: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F37C }, + ["man feeding baby: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F37C }, + ["man feeding baby: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F37C }, ["man firefighter"]={ 0x1F468, 0x200D, 0x1F692 }, ["man firefighter: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F692 }, ["man firefighter: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F692 }, @@ -1299,18 +1378,12 @@ return { ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, - ["man in suit levitating"]={ 0x1F574, 0xFE0F }, - ["man in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, - ["man in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, - ["man in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, - ["man in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, - ["man in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, - ["man in tuxedo"]={ 0x1F935 }, - ["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF }, - ["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB }, - ["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD }, - ["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE }, - ["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC }, + ["man in tuxedo"]={ 0x1F935, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man judge"]={ 0x1F468, 0x200D, 0x2696, 0xFE0F }, ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, @@ -1497,18 +1570,18 @@ return { ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, - ["man with chinese cap"]={ 0x1F472 }, - ["man with chinese cap: dark skin tone"]={ 0x1F472, 0x1F3FF }, - ["man with chinese cap: light skin tone"]={ 0x1F472, 0x1F3FB }, - ["man with chinese cap: medium skin tone"]={ 0x1F472, 0x1F3FD }, - ["man with chinese cap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE }, - ["man with chinese cap: medium-light skin tone"]={ 0x1F472, 0x1F3FC }, - ["man with probing cane"]={ 0x1F468, 0x200D, 0x1F9AF }, - ["man with probing cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF }, - ["man with probing cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF }, - ["man with probing cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF }, - ["man with probing cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF }, - ["man with probing cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF }, + ["man with veil"]={ 0x1F470, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: dark skin tone"]={ 0x1F470, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: light skin tone"]={ 0x1F470, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium skin tone"]={ 0x1F470, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man with white cane"]={ 0x1F468, 0x200D, 0x1F9AF }, + ["man with white cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF }, + ["man with white cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF }, + ["man with white cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF }, + ["man with white cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF }, + ["man with white cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF }, ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642, 0xFE0F }, ["man: bald"]={ 0x1F468, 0x200D, 0x1F9B2 }, ["man: beard"]={ 0x1F9D4 }, @@ -1560,6 +1633,12 @@ return { ["martial arts uniform"]={ 0x1F94B }, ["mate"]={ 0x1F9C9 }, ["meat on bone"]={ 0x1F356 }, + ["mechanic"]={ 0x1F9D1, 0x200D, 0x1F527 }, + ["mechanic: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F527 }, + ["mechanic: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F527 }, + ["mechanic: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F527 }, + ["mechanic: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F527 }, + ["mechanic: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F527 }, ["mechanical arm"]={ 0x1F9BE }, ["mechanical leg"]={ 0x1F9BF }, ["medical symbol"]={ 0x2695, 0xFE0F }, @@ -1573,15 +1652,25 @@ return { ["men holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men holding hands: dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: light skin tone"]={ 0x1F46C, 0x1F3FB }, + ["men holding hands: light skin tone, dark skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["men holding hands: light skin tone, medium skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: light skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["men holding hands: light skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium skin tone"]={ 0x1F46C, 0x1F3FD }, + ["men holding hands: medium skin tone, dark skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium skin tone, light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men holding hands: medium skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium-dark skin tone"]={ 0x1F46C, 0x1F3FE }, + ["men holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium-dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, ["men holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, ["men holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium-light skin tone"]={ 0x1F46C, 0x1F3FC }, + ["men holding hands: medium-light skin tone, dark skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium-light skin tone, light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium-light skin tone, medium skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men with bunny ears"]={ 0x1F46F, 0x200D, 0x2642, 0xFE0F }, ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642, 0xFE0F }, ["menorah"]={ 0x1F54E }, @@ -1614,10 +1703,12 @@ return { ["middle finger: medium skin tone"]={ 0x1F595, 0x1F3FD }, ["middle finger: medium-dark skin tone"]={ 0x1F595, 0x1F3FE }, ["middle finger: medium-light skin tone"]={ 0x1F595, 0x1F3FC }, + ["military helmet"]={ 0x1FA96 }, ["military medal"]={ 0x1F396, 0xFE0F }, ["milky way"]={ 0x1F30C }, ["minibus"]={ 0x1F690 }, - ["minus sign"]={ 0x2796 }, + ["minus"]={ 0x2796 }, + ["mirror"]={ 0x1FA9E }, ["moai"]={ 0x1F5FF }, ["mobile phone"]={ 0x1F4F1 }, ["mobile phone off"]={ 0x1F4F4 }, @@ -1643,6 +1734,7 @@ return { ["mountain railway"]={ 0x1F69E }, ["mouse"]={ 0x1F401 }, ["mouse face"]={ 0x1F42D }, + ["mouse trap"]={ 0x1FAA4 }, ["mouth"]={ 0x1F444 }, ["movie camera"]={ 0x1F3A5 }, ["mrs. claus"]={ 0x1F936 }, @@ -1651,13 +1743,19 @@ return { ["mrs. claus: medium skin tone"]={ 0x1F936, 0x1F3FD }, ["mrs. claus: medium-dark skin tone"]={ 0x1F936, 0x1F3FE }, ["mrs. claus: medium-light skin tone"]={ 0x1F936, 0x1F3FC }, - ["multiplication sign"]={ 0x2716, 0xFE0F }, + ["multiply"]={ 0x2716, 0xFE0F }, ["mushroom"]={ 0x1F344 }, ["musical keyboard"]={ 0x1F3B9 }, ["musical note"]={ 0x1F3B5 }, ["musical notes"]={ 0x1F3B6 }, ["musical score"]={ 0x1F3BC }, ["muted speaker"]={ 0x1F507 }, + ["mx claus"]={ 0x1F9D1, 0x200D, 0x1F384 }, + ["mx claus: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F384 }, + ["mx claus: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F384 }, + ["mx claus: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F384 }, + ["mx claus: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F384 }, + ["mx claus: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F384 }, ["nail polish"]={ 0x1F485 }, ["nail polish: dark skin tone"]={ 0x1F485, 0x1F3FF }, ["nail polish: light skin tone"]={ 0x1F485, 0x1F3FB }, @@ -1670,6 +1768,7 @@ return { ["nazar amulet"]={ 0x1F9FF }, ["necktie"]={ 0x1F454 }, ["nerd face"]={ 0x1F913 }, + ["nesting dolls"]={ 0x1FA86 }, ["neutral face"]={ 0x1F610 }, ["new button"]={ 0x1F195 }, ["new moon"]={ 0x1F311 }, @@ -1680,6 +1779,12 @@ return { ["night with stars"]={ 0x1F303 }, ["nine o’clock"]={ 0x1F558 }, ["nine-thirty"]={ 0x1F564 }, + ["ninja"]={ 0x1F977 }, + ["ninja: dark skin tone"]={ 0x1F977, 0x1F3FF }, + ["ninja: light skin tone"]={ 0x1F977, 0x1F3FB }, + ["ninja: medium skin tone"]={ 0x1F977, 0x1F3FD }, + ["ninja: medium-dark skin tone"]={ 0x1F977, 0x1F3FE }, + ["ninja: medium-light skin tone"]={ 0x1F977, 0x1F3FC }, ["no bicycles"]={ 0x1F6B3 }, ["no entry"]={ 0x26D4 }, ["no littering"]={ 0x1F6AF }, @@ -1701,6 +1806,12 @@ return { ["octopus"]={ 0x1F419 }, ["oden"]={ 0x1F362 }, ["office building"]={ 0x1F3E2 }, + ["office worker"]={ 0x1F9D1, 0x200D, 0x1F4BC }, + ["office worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F4BC }, + ["office worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F4BC }, + ["office worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F4BC }, + ["office worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F4BC }, + ["office worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F4BC }, ["ogre"]={ 0x1F479 }, ["oil drum"]={ 0x1F6E2, 0xFE0F }, ["ok button"]={ 0x1F197 }, @@ -1729,6 +1840,7 @@ return { ["older person: medium skin tone"]={ 0x1F9D3, 0x1F3FD }, ["older person: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE }, ["older person: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC }, + ["olive"]={ 0x1FAD2 }, ["om"]={ 0x1F549, 0xFE0F }, ["on! arrow"]={ 0x1F51B }, ["oncoming automobile"]={ 0x1F698 }, @@ -1809,15 +1921,26 @@ return { ["people holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, ["people holding hands: dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: light skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, + ["people holding hands: light skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: light skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: light skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, ["people holding hands: medium skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium-dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, ["people holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, ["people holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: medium-light skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium-light skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium-light skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people hugging"]={ 0x1FAC2 }, ["people with bunny ears"]={ 0x1F46F }, ["people wrestling"]={ 0x1F93C }, ["performing arts"]={ 0x1F3AD }, @@ -1859,6 +1982,12 @@ return { ["person facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD }, ["person facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE }, ["person facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC }, + ["person feeding baby"]={ 0x1F9D1, 0x200D, 0x1F37C }, + ["person feeding baby: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F37C }, + ["person feeding baby: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F37C }, + ["person feeding baby: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F37C }, + ["person feeding baby: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F37C }, + ["person feeding baby: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F37C }, ["person fencing"]={ 0x1F93A }, ["person frowning"]={ 0x1F64D }, ["person frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF }, @@ -1908,12 +2037,36 @@ return { ["person in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD }, ["person in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE }, ["person in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC }, + ["person in manual wheelchair"]={ 0x1F9D1, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9BD }, + ["person in motorized wheelchair"]={ 0x1F9D1, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9BC }, ["person in steamy room"]={ 0x1F9D6 }, ["person in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF }, ["person in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB }, ["person in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD }, ["person in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE }, ["person in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC }, + ["person in suit levitating"]={ 0x1F574, 0xFE0F }, + ["person in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, + ["person in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, + ["person in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, + ["person in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, + ["person in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, + ["person in tuxedo"]={ 0x1F935 }, + ["person in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF }, + ["person in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB }, + ["person in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD }, + ["person in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE }, + ["person in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC }, ["person juggling"]={ 0x1F939 }, ["person juggling: dark skin tone"]={ 0x1F939, 0x1F3FF }, ["person juggling: light skin tone"]={ 0x1F939, 0x1F3FB }, @@ -2022,25 +2175,80 @@ return { ["person wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD }, ["person wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE }, ["person wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC }, + ["person with skullcap"]={ 0x1F472 }, + ["person with skullcap: dark skin tone"]={ 0x1F472, 0x1F3FF }, + ["person with skullcap: light skin tone"]={ 0x1F472, 0x1F3FB }, + ["person with skullcap: medium skin tone"]={ 0x1F472, 0x1F3FD }, + ["person with skullcap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE }, + ["person with skullcap: medium-light skin tone"]={ 0x1F472, 0x1F3FC }, + ["person with veil"]={ 0x1F470 }, + ["person with veil: dark skin tone"]={ 0x1F470, 0x1F3FF }, + ["person with veil: light skin tone"]={ 0x1F470, 0x1F3FB }, + ["person with veil: medium skin tone"]={ 0x1F470, 0x1F3FD }, + ["person with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE }, + ["person with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC }, + ["person with white cane"]={ 0x1F9D1, 0x200D, 0x1F9AF }, + ["person with white cane: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9AF }, + ["person with white cane: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9AF }, + ["person with white cane: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9AF }, + ["person with white cane: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9AF }, + ["person with white cane: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9AF }, + ["person: bald"]={ 0x1F9D1, 0x200D, 0x1F9B2 }, ["person: blond hair"]={ 0x1F471 }, + ["person: curly hair"]={ 0x1F9D1, 0x200D, 0x1F9B1 }, ["person: dark skin tone"]={ 0x1F9D1, 0x1F3FF }, + ["person: dark skin tone, bald"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B2 }, ["person: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF }, + ["person: dark skin tone, curly hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B1 }, + ["person: dark skin tone, red hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B0 }, + ["person: dark skin tone, white hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B3 }, ["person: light skin tone"]={ 0x1F9D1, 0x1F3FB }, + ["person: light skin tone, bald"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B2 }, ["person: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB }, + ["person: light skin tone, curly hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B1 }, + ["person: light skin tone, red hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B0 }, + ["person: light skin tone, white hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B3 }, ["person: medium skin tone"]={ 0x1F9D1, 0x1F3FD }, + ["person: medium skin tone, bald"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B2 }, ["person: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD }, + ["person: medium skin tone, curly hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B1 }, + ["person: medium skin tone, red hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B0 }, + ["person: medium skin tone, white hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B3 }, ["person: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE }, + ["person: medium-dark skin tone, bald"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B2 }, ["person: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE }, + ["person: medium-dark skin tone, curly hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B1 }, + ["person: medium-dark skin tone, red hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B0 }, + ["person: medium-dark skin tone, white hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B3 }, ["person: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC }, + ["person: medium-light skin tone, bald"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B2 }, ["person: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC }, + ["person: medium-light skin tone, curly hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B1 }, + ["person: medium-light skin tone, red hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B0 }, + ["person: medium-light skin tone, white hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B3 }, + ["person: red hair"]={ 0x1F9D1, 0x200D, 0x1F9B0 }, + ["person: white hair"]={ 0x1F9D1, 0x200D, 0x1F9B3 }, ["petri dish"]={ 0x1F9EB }, ["pick"]={ 0x26CF, 0xFE0F }, + ["pickup truck"]={ 0x1F6FB }, ["pie"]={ 0x1F967 }, ["pig"]={ 0x1F416 }, ["pig face"]={ 0x1F437 }, ["pig nose"]={ 0x1F43D }, ["pile of poo"]={ 0x1F4A9 }, ["pill"]={ 0x1F48A }, + ["pilot"]={ 0x1F9D1, 0x200D, 0x2708, 0xFE0F }, + ["pilot: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2708, 0xFE0F }, + ["pilot: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2708, 0xFE0F }, + ["pinched fingers"]={ 0x1F90C }, + ["pinched fingers: dark skin tone"]={ 0x1F90C, 0x1F3FF }, + ["pinched fingers: light skin tone"]={ 0x1F90C, 0x1F3FB }, + ["pinched fingers: medium skin tone"]={ 0x1F90C, 0x1F3FD }, + ["pinched fingers: medium-dark skin tone"]={ 0x1F90C, 0x1F3FE }, + ["pinched fingers: medium-light skin tone"]={ 0x1F90C, 0x1F3FC }, ["pinching hand"]={ 0x1F90F }, ["pinching hand: dark skin tone"]={ 0x1F90F, 0x1F3FF }, ["pinching hand: light skin tone"]={ 0x1F90F, 0x1F3FB }, @@ -2054,11 +2262,15 @@ return { ["pisces"]={ 0x2653 }, ["pistol"]={ 0x1F52B }, ["pizza"]={ 0x1F355 }, + ["piñata"]={ 0x1FA85 }, + ["placard"]={ 0x1FAA7 }, ["place of worship"]={ 0x1F6D0 }, ["play button"]={ 0x25B6, 0xFE0F }, ["play or pause button"]={ 0x23EF, 0xFE0F }, ["pleading face"]={ 0x1F97A }, - ["plus sign"]={ 0x2795 }, + ["plunger"]={ 0x1FAA0 }, + ["plus"]={ 0x2795 }, + ["polar bear"]={ 0x1F43B, 0x200D, 0x2744, 0xFE0F }, ["police car"]={ 0x1F693 }, ["police car light"]={ 0x1F6A8 }, ["police officer"]={ 0x1F46E }, @@ -2076,6 +2288,7 @@ return { ["pot of food"]={ 0x1F372 }, ["potable water"]={ 0x1F6B0 }, ["potato"]={ 0x1F954 }, + ["potted plant"]={ 0x1FAB4 }, ["poultry leg"]={ 0x1F357 }, ["pound banknote"]={ 0x1F4B7 }, ["pouting cat"]={ 0x1F63E }, @@ -2101,7 +2314,6 @@ return { ["princess: medium-dark skin tone"]={ 0x1F478, 0x1F3FE }, ["princess: medium-light skin tone"]={ 0x1F478, 0x1F3FC }, ["printer"]={ 0x1F5A8, 0xFE0F }, - ["probing cane"]={ 0x1F9AF }, ["prohibited"]={ 0x1F6AB }, ["purple circle"]={ 0x1F7E3 }, ["purple heart"]={ 0x1F49C }, @@ -2187,10 +2399,12 @@ return { ["ringed planet"]={ 0x1FA90 }, ["roasted sweet potato"]={ 0x1F360 }, ["robot"]={ 0x1F916 }, + ["rock"]={ 0x1FAA8 }, ["rocket"]={ 0x1F680 }, ["roll of paper"]={ 0x1F9FB }, ["rolled-up newspaper"]={ 0x1F5DE, 0xFE0F }, ["roller coaster"]={ 0x1F3A2 }, + ["roller skate"]={ 0x1F6FC }, ["rolling on the floor laughing"]={ 0x1F923 }, ["rooster"]={ 0x1F413 }, ["rose"]={ 0x1F339 }, @@ -2220,10 +2434,18 @@ return { ["saxophone"]={ 0x1F3B7 }, ["scarf"]={ 0x1F9E3 }, ["school"]={ 0x1F3EB }, + ["scientist"]={ 0x1F9D1, 0x200D, 0x1F52C }, + ["scientist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F52C }, + ["scientist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F52C }, + ["scientist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F52C }, + ["scientist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F52C }, + ["scientist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F52C }, ["scissors"]={ 0x2702, 0xFE0F }, ["scorpio"]={ 0x264F }, ["scorpion"]={ 0x1F982 }, + ["screwdriver"]={ 0x1FA9B }, ["scroll"]={ 0x1F4DC }, + ["seal"]={ 0x1F9AD }, ["seat"]={ 0x1F4BA }, ["see-no-evil monkey"]={ 0x1F648 }, ["seedling"]={ 0x1F331 }, @@ -2236,6 +2458,7 @@ return { ["service dog"]={ 0x1F415, 0x200D, 0x1F9BA }, ["seven o’clock"]={ 0x1F556 }, ["seven-thirty"]={ 0x1F562 }, + ["sewing needle"]={ 0x1FAA1 }, ["shallow pan of food"]={ 0x1F958 }, ["shamrock"]={ 0x2618, 0xFE0F }, ["shark"]={ 0x1F988 }, @@ -2259,6 +2482,12 @@ return { ["sign of the horns: medium skin tone"]={ 0x1F918, 0x1F3FD }, ["sign of the horns: medium-dark skin tone"]={ 0x1F918, 0x1F3FE }, ["sign of the horns: medium-light skin tone"]={ 0x1F918, 0x1F3FC }, + ["singer"]={ 0x1F9D1, 0x200D, 0x1F3A4 }, + ["singer: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3A4 }, + ["singer: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3A4 }, + ["singer: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3A4 }, + ["singer: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3A4 }, + ["singer: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3A4 }, ["six o’clock"]={ 0x1F555 }, ["six-thirty"]={ 0x1F561 }, ["skateboard"]={ 0x1F6F9 }, @@ -2285,6 +2514,7 @@ return { ["smiling face with horns"]={ 0x1F608 }, ["smiling face with smiling eyes"]={ 0x1F60A }, ["smiling face with sunglasses"]={ 0x1F60E }, + ["smiling face with tear"]={ 0x1F972 }, ["smirking face"]={ 0x1F60F }, ["snail"]={ 0x1F40C }, ["snake"]={ 0x1F40D }, @@ -2345,6 +2575,12 @@ return { ["stopwatch"]={ 0x23F1, 0xFE0F }, ["straight ruler"]={ 0x1F4CF }, ["strawberry"]={ 0x1F353 }, + ["student"]={ 0x1F9D1, 0x200D, 0x1F393 }, + ["student: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F393 }, + ["student: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F393 }, + ["student: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F393 }, + ["student: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F393 }, + ["student: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F393 }, ["studio microphone"]={ 0x1F399, 0xFE0F }, ["stuffed flatbread"]={ 0x1F959 }, ["sun"]={ 0x2600, 0xFE0F }, @@ -2374,19 +2610,32 @@ return { ["suspension railway"]={ 0x1F69F }, ["swan"]={ 0x1F9A2 }, ["sweat droplets"]={ 0x1F4A6 }, - ["swim brief"]={ 0x1FA72 }, ["synagogue"]={ 0x1F54D }, ["syringe"]={ 0x1F489 }, ["t-rex"]={ 0x1F996 }, ["t-shirt"]={ 0x1F455 }, ["taco"]={ 0x1F32E }, ["takeout box"]={ 0x1F961 }, + ["tamale"]={ 0x1FAD4 }, ["tanabata tree"]={ 0x1F38B }, ["tangerine"]={ 0x1F34A }, ["taurus"]={ 0x2649 }, ["taxi"]={ 0x1F695 }, + ["teacher"]={ 0x1F9D1, 0x200D, 0x1F3EB }, + ["teacher: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3EB }, + ["teacher: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3EB }, + ["teacher: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3EB }, + ["teacher: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3EB }, + ["teacher: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3EB }, ["teacup without handle"]={ 0x1F375 }, + ["teapot"]={ 0x1FAD6 }, ["tear-off calendar"]={ 0x1F4C6 }, + ["technologist"]={ 0x1F9D1, 0x200D, 0x1F4BB }, + ["technologist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F4BB }, + ["technologist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F4BB }, + ["technologist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F4BB }, + ["technologist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F4BB }, + ["technologist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F4BB }, ["teddy bear"]={ 0x1F9F8 }, ["telephone"]={ 0x260E, 0xFE0F }, ["telephone receiver"]={ 0x1F4DE }, @@ -2399,6 +2648,7 @@ return { ["test tube"]={ 0x1F9EA }, ["thermometer"]={ 0x1F321, 0xFE0F }, ["thinking face"]={ 0x1F914 }, + ["thong sandal"]={ 0x1FA74 }, ["thought balloon"]={ 0x1F4AD }, ["thread"]={ 0x1F9F5 }, ["three o’clock"]={ 0x1F552 }, @@ -2426,6 +2676,7 @@ return { ["tongue"]={ 0x1F445 }, ["toolbox"]={ 0x1F9F0 }, ["tooth"]={ 0x1F9B7 }, + ["toothbrush"]={ 0x1FAA5 }, ["top arrow"]={ 0x1F51D }, ["top hat"]={ 0x1F3A9 }, ["tornado"]={ 0x1F32A, 0xFE0F }, @@ -2435,6 +2686,8 @@ return { ["train"]={ 0x1F686 }, ["tram"]={ 0x1F68A }, ["tram car"]={ 0x1F68B }, + ["transgender flag"]={ 0x1F3F3, 0xFE0F, 0x200D, 0x26A7, 0xFE0F }, + ["transgender symbol"]={ 0x26A7, 0xFE0F }, ["triangular flag"]={ 0x1F6A9 }, ["triangular ruler"]={ 0x1F4D0 }, ["trident emblem"]={ 0x1F531 }, @@ -2519,6 +2772,7 @@ return { ["whale"]={ 0x1F40B }, ["wheel of dharma"]={ 0x2638, 0xFE0F }, ["wheelchair symbol"]={ 0x267F }, + ["white cane"]={ 0x1F9AF }, ["white circle"]={ 0x26AA }, ["white exclamation mark"]={ 0x2755 }, ["white flag"]={ 0x1F3F3, 0xFE0F }, @@ -2533,6 +2787,7 @@ return { ["wilted flower"]={ 0x1F940 }, ["wind chime"]={ 0x1F390 }, ["wind face"]={ 0x1F32C, 0xFE0F }, + ["window"]={ 0x1FA9F }, ["wine glass"]={ 0x1F377 }, ["winking face"]={ 0x1F609 }, ["winking face with tongue"]={ 0x1F61C }, @@ -2660,6 +2915,12 @@ return { ["woman farmer: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F33E }, ["woman farmer: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F33E }, ["woman farmer: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F33E }, + ["woman feeding baby"]={ 0x1F469, 0x200D, 0x1F37C }, + ["woman feeding baby: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F37C }, + ["woman feeding baby: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F37C }, + ["woman feeding baby: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F37C }, + ["woman feeding baby: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F37C }, + ["woman feeding baby: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F37C }, ["woman firefighter"]={ 0x1F469, 0x200D, 0x1F692 }, ["woman firefighter: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F692 }, ["woman firefighter: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F692 }, @@ -2739,6 +3000,12 @@ return { ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo"]={ 0x1F935, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman judge"]={ 0x1F469, 0x200D, 0x2696, 0xFE0F }, ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, @@ -2931,12 +3198,18 @@ return { ["woman with headscarf: medium skin tone"]={ 0x1F9D5, 0x1F3FD }, ["woman with headscarf: medium-dark skin tone"]={ 0x1F9D5, 0x1F3FE }, ["woman with headscarf: medium-light skin tone"]={ 0x1F9D5, 0x1F3FC }, - ["woman with probing cane"]={ 0x1F469, 0x200D, 0x1F9AF }, - ["woman with probing cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF }, - ["woman with probing cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF }, + ["woman with veil"]={ 0x1F470, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: dark skin tone"]={ 0x1F470, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: light skin tone"]={ 0x1F470, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium skin tone"]={ 0x1F470, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman with white cane"]={ 0x1F469, 0x200D, 0x1F9AF }, + ["woman with white cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF }, + ["woman with white cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF }, + ["woman with white cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF }, + ["woman with white cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF }, + ["woman with white cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF }, ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640, 0xFE0F }, ["woman: bald"]={ 0x1F469, 0x200D, 0x1F9B2 }, ["woman: blond hair"]={ 0x1F471, 0x200D, 0x2640, 0xFE0F }, @@ -2984,20 +3257,32 @@ return { ["women holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: light skin tone"]={ 0x1F46D, 0x1F3FB }, + ["women holding hands: light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, + ["women holding hands: light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, + ["women holding hands: light skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium skin tone"]={ 0x1F46D, 0x1F3FD }, + ["women holding hands: medium skin tone, dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium-dark skin tone"]={ 0x1F46D, 0x1F3FE }, + ["women holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, ["women holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, ["women holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium-light skin tone"]={ 0x1F46D, 0x1F3FC }, + ["women holding hands: medium-light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium-light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women with bunny ears"]={ 0x1F46F, 0x200D, 0x2640, 0xFE0F }, ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640, 0xFE0F }, ["women’s room"]={ 0x1F6BA }, + ["wood"]={ 0x1FAB5 }, ["woozy face"]={ 0x1F974 }, ["world map"]={ 0x1F5FA, 0xFE0F }, + ["worm"]={ 0x1FAB1 }, ["worried face"]={ 0x1F61F }, ["wrapped gift"]={ 0x1F381 }, ["wrench"]={ 0x1F527 }, diff --git a/tex/context/base/mkiv/cont-fil.mkiv b/tex/context/base/mkiv/cont-fil.mkiv index 9257e2e1e..aa7d9ddb3 100644 --- a/tex/context/base/mkiv/cont-fil.mkiv +++ b/tex/context/base/mkiv/cont-fil.mkiv @@ -16,137 +16,142 @@ \writestatus{loading}{ConTeXt File Synonyms} -\definefilesynonym [chemics] [chemic] - -\definefilesynonym [unit] [units] - -\definefilesynonym [pstric] [pstricks] -\definefilesynonym [pstrick] [pstricks] - -\definefilesynonym [finance] [financ] - -\definefilesynonym [dir-make] [dir-01] -\definefilesynonym [dir-identify] [dir-05] - -\definefilesynonym [int-load] [set-11] -\definefilesynonym [int-make] [set-12] - - \definefilesynonym [fig-base] [fig-00] - \definefilesynonym [fig-make] [fig-01] - \definefilesynonym [fig-fake] [fig-02] - \definefilesynonym [fig-missing] [fig-06] - -\definefilesynonym [exi-interface] [exi-21] - - \definefilesynonym [res-make] [res-01] - \definefilesynonym [res-base] [res-04] - \definefilesynonym [res-crop] [res-07] - \definefilesynonym [res-trace] [res-08] - \definefilesynonym [res-log] [res-09] - \definefilesynonym [res-identify] [res-12] - - \definefilesynonym [med-show] [res-50] - -\definefilesynonym [pre-general] [pre-00] -\definefilesynonym [pre-01] [present-original] -\definefilesynonym [pre-original] [present-original] -\definefilesynonym [pre-02] [present-green] -\definefilesynonym [pre-green] [present-green] -\definefilesynonym [pre-03] [present-funny] -\definefilesynonym [pre-funny] [present-funny] -\definefilesynonym [pre-04] [present-colorful] -\definefilesynonym [pre-colorful] [present-colorful] -\definefilesynonym [pre-05] [present-fuzzy] -\definefilesynonym [pre-fuzzy] [present-fuzzy] -\definefilesynonym [pre-polish] [pre-06] -\definefilesynonym [pre-spider] [pre-07] -\definefilesynonym [pre-wonder] [pre-08] -\definefilesynonym [pre-09] [present-windows] -\definefilesynonym [pre-windows] [present-windows] -\definefilesynonym [pre-10] [present-grow] -\definefilesynonym [pre-grow] [present-grow] -\definefilesynonym [pre-11] [present-stack] -\definefilesynonym [pre-stack] [present-stack] -\definefilesynonym [pre-arrows] [pre-12] -\definefilesynonym [pre-writing] [pre-13] -\definefilesynonym [pre-split] [present-split] -\definefilesynonym [pre-14] [present-split] -\definefilesynonym [pre-balls] [present-balls] -\definefilesynonym [pre-15] [present-balls] -\definefilesynonym [pre-knot] [pre-16] -\definefilesynonym [pre-17] [present-weird] -\definefilesynonym [pre-weird] [present-weird] -\definefilesynonym [pre-shade] [pre-18] -\definefilesynonym [pre-organic] [pre-19] -\definefilesynonym [pre-speckle] [pre-20] -\definefilesynonym [pre-zoom] [pre-21] -\definefilesynonym [pre-cycle] [pre-22] -\definefilesynonym [pre-super] [pre-23] -%definefilesynonym [pre-more] [pre-24] -%definefilesynonym [pre-more] [pre-25] -\definefilesynonym [pre-more] [pre-26] -%definefilesynonym [pre-more] [pre-27] -%definefilesynonym [pre-more] [pre-28] -%definefilesynonym [pre-more] [pre-29] -%definefilesynonym [pre-more] [pre-30] -\definefilesynonym [pre-41] [present-tiles] -\definefilesynonym [pre-60] [present-stepwise] -\definefilesynonym [pre-stepwise] [present-stepwise] -\definefilesynonym [pre-61] [present-stepper] -\definefilesynonym [pre-stepper] [present-stepper] -\definefilesynonym [pre-62] [present-overlap] -\definefilesynonym [pre-69] [present-wobbling] -\definefilesynonym [pre-punk] [present-punk] -\definefilesynonym [pre-70] [present-punk] -\definefilesynonym [pre-random] [present-random] -\definefilesynonym [pre-71] [present-random] - -\definefilesynonym [abr-01] [abbreviations-pseudocaps] -\definefilesynonym [abr-02] [abbreviations-smallcaps] -\definefilesynonym [abr-03] [abbreviations-words] -\definefilesynonym [abr-04] [abbreviations-mixed] - -\definefilesynonym [art-01] [article-basic] -\definefilesynonym [article] [article-basic] -\definefilesynonym [mag-01] [magazine-basic] -\definefilesynonym [magazine] [magazine-basic] -\definefilesynonym [mod-01] [module-basic] -\definefilesynonym [module] [module-basic] - -\definefilesynonym [map-10] [maps] % for a while - -\definefilesynonym [mml] [mathml] -\definefilesynonym [cml] [chemml] - -\definefilesynonym [letter] [cor-01] -\definefilesynonym [memo] [cor-02] -\definefilesynonym [resume] [cor-03] - -\definefilesynonym [fnt-10] [fonts-complete] -\definefilesynonym [fnt-11] [fonts-system] -\definefilesynonym [fnt-20] [fonts-steps] -\definefilesynonym [fnt-21] [fonts-steps] -\definefilesynonym [fnt-22] [fonts-engines] -\definefilesynonym [fnt-23] [fonts-shapes] -\definefilesynonym [fnt-24] [fonts-cjk] -\definefilesynonym [fnt-25] [math-characters] -\definefilesynonym [fnt-28] [fonts-goodies] -\definefilesynonym [fnt-29] [fonts-shapes] -\definefilesynonym [fnt-31] [fonts-coverage] -\definefilesynonym [fnt-33] [math-coverage] - -\definefilesynonym [mat-10] [math-characters] -\definefilesynonym [mat-11] [math-characters] -\definefilesynonym [mat-12] [math-parameters] -\definefilesynonym [mat-20] [math-parameters] - -\definefilesynonym [syn-01] [syntax] - -\definefilesynonym [reg-01] [regimes-list] - -\definefilesynonym [set-11] [setups-basics] -\definefilesynonym [set-12] [setups-overview] -%definefilesynonym [set-13] [setups-proofing] -%definefilesynonym [set-15] [setups-generate] +\definefilesynonym [chemics] [chemic] + +\definefilesynonym [unit] [units] + +\definefilesynonym [pstric] [pstricks] +\definefilesynonym [pstrick] [pstricks] + +\definefilesynonym [finance] [financ] + +\definefilesynonym [dir-make] [dir-01] +\definefilesynonym [dir-identify] [dir-05] + +\definefilesynonym [int-load] [set-11] +\definefilesynonym [int-make] [set-12] + + \definefilesynonym [fig-base] [fig-00] + \definefilesynonym [fig-make] [fig-01] + \definefilesynonym [fig-fake] [fig-02] + \definefilesynonym [fig-missing] [fig-06] + + \definefilesynonym [exi-interface] [exi-21] + + \definefilesynonym [res-make] [res-01] + \definefilesynonym [res-base] [res-04] + \definefilesynonym [res-crop] [res-07] + \definefilesynonym [res-trace] [res-08] + \definefilesynonym [res-log] [res-09] + \definefilesynonym [res-identify] [res-12] + + \definefilesynonym [med-show] [res-50] + +\definefilesynonym [pre-general] [pre-00] +\definefilesynonym [pre-01] [present-original] +\definefilesynonym [pre-original] [present-original] +\definefilesynonym [pre-02] [present-green] +\definefilesynonym [pre-green] [present-green] +\definefilesynonym [pre-03] [present-funny] +\definefilesynonym [pre-funny] [present-funny] +\definefilesynonym [pre-04] [present-colorful] +\definefilesynonym [pre-colorful] [present-colorful] +\definefilesynonym [pre-05] [present-fuzzy] +\definefilesynonym [pre-fuzzy] [present-fuzzy] +\definefilesynonym [pre-polish] [pre-06] +\definefilesynonym [pre-spider] [pre-07] +\definefilesynonym [pre-wonder] [pre-08] +\definefilesynonym [pre-09] [present-windows] +\definefilesynonym [pre-windows] [present-windows] +\definefilesynonym [pre-10] [present-grow] +\definefilesynonym [pre-grow] [present-grow] +\definefilesynonym [pre-11] [present-stack] +\definefilesynonym [pre-stack] [present-stack] +\definefilesynonym [pre-arrows] [pre-12] +\definefilesynonym [pre-writing] [pre-13] +\definefilesynonym [pre-split] [present-split] +\definefilesynonym [pre-14] [present-split] +\definefilesynonym [pre-balls] [present-balls] +\definefilesynonym [pre-15] [present-balls] +\definefilesynonym [pre-knot] [pre-16] +\definefilesynonym [pre-17] [present-weird] +\definefilesynonym [pre-weird] [present-weird] +\definefilesynonym [pre-shade] [pre-18] +\definefilesynonym [pre-organic] [pre-19] +\definefilesynonym [pre-speckle] [pre-20] +\definefilesynonym [pre-zoom] [pre-21] +\definefilesynonym [pre-cycle] [pre-22] +\definefilesynonym [pre-super] [pre-23] +%definefilesynonym [pre-more] [pre-24] +%definefilesynonym [pre-more] [pre-25] +\definefilesynonym [pre-more] [pre-26] +%definefilesynonym [pre-more] [pre-27] +%definefilesynonym [pre-more] [pre-28] +%definefilesynonym [pre-more] [pre-29] +%definefilesynonym [pre-more] [pre-30] +\definefilesynonym [pre-41] [present-tiles] +\definefilesynonym [pre-60] [present-stepwise] +\definefilesynonym [pre-stepwise] [present-stepwise] +\definefilesynonym [pre-61] [present-stepper] +\definefilesynonym [pre-stepper] [present-stepper] +\definefilesynonym [pre-62] [present-overlap] +\definefilesynonym [pre-69] [present-wobbling] +\definefilesynonym [pre-punk] [present-punk] +\definefilesynonym [pre-70] [present-punk] +\definefilesynonym [pre-random] [present-random] +\definefilesynonym [pre-71] [present-random] + +\definefilesynonym [abr-01] [abbreviations-pseudocaps] +\definefilesynonym [abr-02] [abbreviations-smallcaps] +\definefilesynonym [abr-03] [abbreviations-words] +\definefilesynonym [abr-04] [abbreviations-mixed] + +\definefilesynonym [art-01] [article-basic] +\definefilesynonym [article] [article-basic] +\definefilesynonym [mag-01] [magazine-basic] +\definefilesynonym [magazine] [magazine-basic] +\definefilesynonym [mod-01] [module-basic] +\definefilesynonym [module] [module-basic] + +\definefilesynonym [map-10] [maps] % for a while + +\definefilesynonym [mml] [mathml] +\definefilesynonym [cml] [chemml] + +\definefilesynonym [letter] [cor-01] +\definefilesynonym [memo] [cor-02] +\definefilesynonym [resume] [cor-03] + +\definefilesynonym [fnt-10] [fonts-complete] +\definefilesynonym [fnt-11] [fonts-system] +\definefilesynonym [fnt-20] [fonts-steps] +\definefilesynonym [fnt-21] [fonts-steps] +\definefilesynonym [fnt-22] [fonts-engines] +\definefilesynonym [fnt-23] [fonts-shapes] +\definefilesynonym [fnt-24] [fonts-cjk] +\definefilesynonym [fnt-25] [math-characters] +\definefilesynonym [fnt-28] [fonts-goodies] +\definefilesynonym [fnt-29] [fonts-shapes] +\definefilesynonym [fnt-31] [fonts-coverage] +\definefilesynonym [fnt-33] [math-coverage] + +\definefilesynonym [mat-10] [math-characters] +\definefilesynonym [mat-11] [math-characters] +\definefilesynonym [mat-12] [math-parameters] +\definefilesynonym [mat-20] [math-parameters] + +\definefilesynonym [syn-01] [syntax] + +\definefilesynonym [reg-01] [regimes-list] + +\definefilesynonym [set-11] [setups-basics] +\definefilesynonym [set-12] [setups-overview] +%definefilesynonym [set-13] [setups-proofing] +%definefilesynonym [set-15] [setups-generate] + +\ifcase\contextlmtxmode \else + \definefilesynonym [ecmascript] [libs-imp-mujs] + \definefilesynonym [zint] [libs-imp-zint] +\fi \endinput diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 2cc2a1098..cd700391a 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.01.26 18:34} +\newcontextversion{2020.02.11 16:36} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index d4206a4e8..30389e598 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 1b4da4e96..ef3fddc3d 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/data-tmp.lua b/tex/context/base/mkiv/data-tmp.lua index bfced1e64..9b0117c15 100644 --- a/tex/context/base/mkiv/data-tmp.lua +++ b/tex/context/base/mkiv/data-tmp.lua @@ -364,7 +364,7 @@ function caches.is_writable(filepath,filename) return is_writable(tmaname) end -local saveoptions = { compact = true } +local saveoptions = { compact = true, accurate = not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname, tmcname = setluanames(filepath,filename) diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua index cc8b6bdbe..a4e36105d 100644 --- a/tex/context/base/mkiv/driv-shp.lua +++ b/tex/context/base/mkiv/driv-shp.lua @@ -381,6 +381,7 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r factor = 0 end end + if pos_r == righttoleft_code then pos_h = pos_h - width end @@ -390,6 +391,7 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r if vfcommands then flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? else + -- kind of messy that we do orientation here and offsets elsewhere local orientation = data.orientation if orientation and (orientation == 1 or orientation == 3) then local x = data.xoffset @@ -401,10 +403,10 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r pos_v = pos_v + y end pushorientation(orientation,pos_h,pos_v) - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) poporientation(orientation,pos_h,pos_v) else - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) end end return width, height, depth diff --git a/tex/context/base/mkiv/file-job.lua b/tex/context/base/mkiv/file-job.lua index 4b29f57ec..407c3c15d 100644 --- a/tex/context/base/mkiv/file-job.lua +++ b/tex/context/base/mkiv/file-job.lua @@ -326,6 +326,8 @@ end local suffixes = { mkvi = usetexfile, mkiv = usetexfile, + mklx = usetexfile, + mkxl = usetexfile, tex = usetexfile, luc = useluafile, lua = useluafile, diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index e42d20d4e..1bb63aa51 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -1139,6 +1139,7 @@ hashmethods.normal = function(list) m = m + 1 t[m] = k .. '=' .. tostring(v) end + sort(t) s[n] = k .. '={' .. concat(t,",") .. "}" else s[n] = k .. '=' .. tostring(v) diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index cbb81cdb7..bf14dd309 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -887,23 +887,6 @@ specifiers.definecontext = definecontext -- we extend the hasher: --- constructors.hashmethods.virtual = function(list) --- local s = { } --- local n = 0 --- for k, v in next, list do --- n = n + 1 --- s[n] = k -- no checking on k --- end --- if n > 0 then --- sort(s) --- for i=1,n do --- local k = s[i] --- s[i] = k .. '=' .. tostring(list[k]) --- end --- return concat(s,"+") --- end --- end - constructors.hashmethods.virtual = function(list) local s = { } local n = 0 @@ -924,6 +907,54 @@ constructors.hashmethods.virtual = function(list) end end +if not JITSUPPORTED then + + constructors.hashmethods.normal = function(list) + local s = { } + local n = 0 + for k, v in next, list do + if not k then + -- no need to add to hash + elseif k == "number" or k == "features" then + -- no need to add to hash (maybe we need a skip list) + else + n = n + 1 + if type(v) == "table" then + -- table.sequenced + local t = { } + local m = 0 + for k, v in next, v do + m = m + 1 + t[m] = format("%q=%q",k,v) + end + sort(t) + s[n] = format("%q={%s}",k,concat(t,",")) + else + s[n] = format("%q=%q",k,v) + end + end + end + if n > 0 then + sort(s) + return concat(s,"+") + end + end + + constructors.hashmethods.virtual = function(list) + local s = { } + local n = 0 + for k, v in next, list do + n = n + 1 + s[n] = format("%q=%q",k,v) + end + if n > 0 then + sort(s) + return concat(s,"+") + end + end + +end + -- end of redefine -- local withcache = { } -- concat might be less efficient than nested tables diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index 7777f9c6a..3058be37b 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -3237,7 +3237,8 @@ function readers.sbix(f,fontdata,specification) return b.ppem < a.ppem end end) - local glyphs = { } + local glyphs = { } + local delayed = CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 or fonts.handlers.typethree for i=1,nofstrikes do local strike = strikes[i] local strikeppem = strike.ppem @@ -3254,13 +3255,28 @@ function readers.sbix(f,fontdata,specification) local datasize = nextoffset - glyphoffset if datasize > 0 then setposition(f,strikeoffset + glyphoffset) + local x = readshort(f) + local y = readshort(f) + local tag = readtag(f) -- or just skip, we never needed it till now + local size = datasize - 8 + local data = nil + local offset = nil + if delayed then + offset = getposition(f) + data = nil + else + data = readstring(f,size) + size = nil + end shapes[i] = { - x = readshort(f), - y = readshort(f), - tag = readtag(f), -- maybe for tracing - data = readstring(f,datasize-8), - ppem = strikeppem, -- not used, for tracing - ppi = strikeppi, -- not used, for tracing + x = x, + y = y, + o = offset, + s = size, + data = data, + -- tag = tag, -- maybe for tracing + -- ppem = strikeppem, -- not used, for tracing + -- ppi = strikeppi, -- not used, for tracing } done = done + 1 if done == nofglyphs then @@ -3462,32 +3478,48 @@ do local default = { width = 0, height = 0 } local glyphs = fontdata.glyphs + local delayed = CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 or fonts.handlers.typethree for index, subtable in sortedhash(shapes) do if type(subtable) == "table" then local data = nil + local size = nil local metrics = default local format = subtable.format local offset = subtable.offsets[index] setposition(f,offset) if format == 17 then metrics = getsmallmetrics(f) - data = readstring(f,readulong(f)) + size = true elseif format == 18 then metrics = getbigmetrics(f) - data = readstring(f,readulong(f)) + size = true elseif format == 19 then metrics = subtable.metrics - data = readstring(f,readulong(f)) + size = true else -- forget about it end + if size then + size = readulong(f) + if delayed then + offset = getposition(f) + data = nil + else + offset = nil + data = readstring(f,size) + size = nil + end + else + offset = nil + end local x = metrics.width local y = metrics.height shapes[index] = { - -- maybe some metrics x = x, y = y, + o = offset, + s = size, data = data, } -- I'll look into this in more details when needed @@ -3498,12 +3530,11 @@ do local height = width * y/x glyph.boundingbox = { 0, 0, width, height } end - else shapes[index] = { x = 0, y = 0, - data = "", + data = "", -- or just nil } end end diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua index da02ab608..fe972114f 100644 --- a/tex/context/base/mkiv/font-mis.lua +++ b/tex/context/base/mkiv/font-mis.lua @@ -21,7 +21,7 @@ local readers = otf.readers if readers then - otf.version = otf.version or 3.110 + otf.version = otf.version or 3.111 otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true) function fonts.helpers.getfeatures(name,save) diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua index 77e1538f9..eef221e46 100644 --- a/tex/context/base/mkiv/font-ocl.lua +++ b/tex/context/base/mkiv/font-ocl.lua @@ -401,7 +401,7 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg -- The down and right will change too (we can move that elsewhere). We have -- a different treatment in lmtx but the next kind of works. These images are -- a mess anyway as in svg the bbox can be messed up absent). A png image - -- needs the x/y. I might normalize this once we moev to lmtx exlusively. + -- needs the x/y. I might normalize this once we move to lmtx exlusively. character.commands = { not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, -- lmtx (when we deal with depth in vfimage, currently disabled): diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua index 5d3bd4230..aff4cc8c8 100644 --- a/tex/context/base/mkiv/font-otl.lua +++ b/tex/context/base/mkiv/font-otl.lua @@ -52,7 +52,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.110 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 3.111 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otl", otf.version, true) otf.svgcache = containers.define("fonts", "svg", otf.version, true) otf.pngcache = containers.define("fonts", "png", otf.version, true) @@ -534,6 +534,9 @@ local converters = { } } +-- We can get differences between daylight saving etc ... but it makes no sense to +-- mess with trickery .. so be it when you use a different binary. + local function checkconversion(specification) local filename = specification.filename local converter = converters[lower(file.suffix(filename))] diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index 8394d19e7..64c7de567 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -637,6 +637,14 @@ function os.validdate(year,month,day) return year, month, day end +function os.date(fmt,...) + if not fmt then + -- otherwise differences between unix, mingw and msvc + fmt = "%Y-%m-%d %H:%M" + end + return date(fmt,...) +end + local osexit = os.exit local exitcode = nil diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua index 98b377bdc..c20bd4733 100644 --- a/tex/context/base/mkiv/l-table.lua +++ b/tex/context/base/mkiv/l-table.lua @@ -525,84 +525,15 @@ function table.fromhash(t) return hsh end -local noquotes, hexify, handle, compact, inline, functions, metacheck +local noquotes, hexify, handle, compact, inline, functions, metacheck, accurate local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while', - 'NaN', 'goto', + 'NaN', 'goto', 'const', } --- local function is_simple_table(t) --- if #t > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- end --- if n == #t then --- local tt, nt = { }, 0 --- for i=1,#t do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- nt = nt + 1 --- if hexify then --- tt[nt] = format("0x%X",v) --- else --- tt[nt] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- nt = nt + 1 --- tt[nt] = format("%q",v) --- elseif tv == "boolean" then --- nt = nt + 1 --- tt[nt] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - --- local function is_simple_table(t) --- local nt = #t --- if nt > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- -- if type(v) == "table" then --- -- return nil --- -- end --- end --- if n == nt then --- local tt = { } --- for i=1,nt do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- if hexify then --- tt[i] = format("0x%X",v) --- else --- tt[i] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- tt[i] = format("%q",v) --- elseif tv == "boolean" then --- tt[i] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - -local function is_simple_table(t,hexify) -- also used in util-tab so maybe public +local function is_simple_table(t,hexify,accurate) -- also used in util-tab so maybe public local nt = #t if nt > 0 then local n = 0 @@ -623,6 +554,8 @@ local function is_simple_table(t,hexify) -- also used in util-tab so maybe publi -- tt[i] = v -- not needed tostring(v) if hexify then tt[i] = format("0x%X",v) + elseif accurate then + tt[i] = format("%q",v) else tt[i] = v -- not needed tostring(v) end @@ -644,6 +577,8 @@ local function is_simple_table(t,hexify) -- also used in util-tab so maybe publi -- tt[i+1] = v -- not needed tostring(v) if hexify then tt[i+1] = format("0x%X",v) + elseif accurate then + tt[i+1] = format("%q",v) else tt[i+1] = v -- not needed tostring(v) end @@ -738,6 +673,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv == "number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) -- %.99g end @@ -747,7 +684,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v) == nil then handle(format("%s {},",depth)) elseif inline then -- and #t > 0 - local st = is_simple_table(v,hexify) + local st = is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -775,12 +712,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g end elseif tk == "boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g end @@ -789,12 +730,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) -- %.99g end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g end @@ -803,6 +748,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -820,6 +767,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -833,11 +782,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st = is_simple_table(v,hexify) + local st = is_simple_table(v,hexify,accurate) if st then if tk == "number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -860,6 +811,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -881,6 +834,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -899,6 +854,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -927,6 +884,7 @@ local function serialize(_handle,root,name,specification) -- handle wins if type(specification) == "table" then noquotes = specification.noquotes hexify = specification.hexify + accurate = specification.accurate handle = _handle or specification.handle or print functions = specification.functions compact = specification.compact diff --git a/tex/context/base/mkiv/libs-imp-mujs.lua b/tex/context/base/mkiv/libs-imp-mujs.lua new file mode 100644 index 000000000..264c8e531 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mujs.lua @@ -0,0 +1,126 @@ +if not modules then modules = { } end modules ['libs-imp-mujs'] = { + version = 1.001, + comment = "companion to luat-imp-mujs.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a +-- stepping stone to using \LUA. + +-- local ecmascript = optional.mujs.initialize("libmujs") +-- local execute = optional.mujs.execute + +local libname = "mujs" +local libfile = "libmujs" + +if package.loaded[libname] then + return package.loaded[libname] +end + +local mujslib = resolvers.libraries.validoptional(libname) + +if not mujslib then + return +end + +local files = { } +local openfile = io.open +local findfile = resolvers.findfile + +local mujs_execute = mujslib.execute +local mujs_dofile = mujslib.dofile +local mujs_reset = mujslib.reset + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + mujs_execute( + "var catcodes = { " .. + "'tex': " .. tex.texcatcodes .. "," .. + "'ctx': " .. tex.ctxcatcodes .. "," .. + "'prt': " .. tex.prtcatcodes .. "," .. + "'vrb': " .. tex.vrbcatcodes .. "," .. + "};" + ) + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +mujslib.setfindfile(findfile) + +mujslib.setopenfile(function(name) + local full = findfile(name) + if full then + local f = openfile(full,"rb") + if f then + for i=1,100 do + if not files[i] then + files[i] = f + return i + end + end + end + end +end) + +mujslib.setclosefile(function(id) + local f = files[id] + if f then + f:close() + files[id] = false + end +end) + +mujslib.setreadfile(function(id,how) + local f = files[id] + if f then + return (f:read(how or "*l")) + end +end) + +mujslib.setseekfile(function(id,whence,offset) + local f = files[id] + if f then + return (f:seek(whence,offset)) + end +end) + +local reporters = { + console = logs.reporter("mujs","console"), + report = logs.reporter("mujs","report"), +} + +mujslib.setconsole(function(category,name) + reporters[category](name) +end) + +local mujs = { + ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, + ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, + ["reset"] = function(n) if okay() then mujs_reset(n) end end, +} + +package.loaded[libname] = mujs + +optional.loaded.mujs = mujs + +interfaces.implement { + name = "ecmacode", + actions = mujs.execute, + arguments = "string", + public = true, +} + +interfaces.implement { + name = "ecmafile", + actions = mujs.dofile, + arguments = "string", + public = true, + protected = true, +} + +return mujs diff --git a/tex/context/base/mkiv/libs-imp-mujs.mkxl b/tex/context/base/mkiv/libs-imp-mujs.mkxl new file mode 100644 index 000000000..0f278dff5 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mujs.mkxl @@ -0,0 +1,121 @@ +%D \module +%D [ file=libs-imp-mujs, +%D version=2020.02.08, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=MuJS interpreter, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Just an experiment: +%D +%D \starttyping +%D http://mujs.com +%D \stoptyping + +\ifdefined\ecmacode + \expandafter \endinput +\fi + +\registerctxluafile{libs-imp-mujs}{} + +\unprotect + +% todo: environment + +\let\stopecmacode\relax + +\normalprotected\def\startecmacode % \stopecmacode + {\begingroup + \obeylualines + \obeyluatokens + \luat_start_ecma_code_indeed} + +\def\luat_start_ecma_code_indeed#1\stopecmacode + {\normalexpanded{\endgroup\noexpand\ecmacode{#1}}} + +\protect + +\continueifinputfile{libs-imp-mujs.mkxl} + +\usemodule[article-basic,abbreviations-logos] + +\starttext + +\startbuffer +\startluacode + local mujs = require("libs-imp-mujs") + + mujs.execute [[ + var MyMax = 1000; + ]] + + mujs.execute [[ + console("Example One!"); + texsprint("\\startpacked"); + for (var i = 1; i <= MyMax; i = i + 1) { + texprint( + "This is a buildbot compilation challenge for Mojca: " + .concat(Math.sqrt(i/MyMax)) + .concat("!\\par") + ); + } + texsprint("\\stoppacked"); + ]] + + -- mujs.execute [[ + -- something very bad: an error + -- ]] +\stopluacode + +\startecmacode + console("Example Two!"); + for (var i = 1; i <= MyMax; i = i + 1) { + texsprint( + "And an opportunity for Alan to attract highschool students to \\TeX: " + .concat(i) + .concat("! ") + ); + } +\stopecmacode + +\ecmacode { + console("Example Three!"); + texprint("And otherwise a way to prototype \\JAVASCRIPT\\ code in \\PDF.") +} + +\startecmacode + var f = File("libs-imp-mujs.mkxl","r"); + console(f); + // var l = f.read(400); + var l = f.read("*a"); + console(l); + f.close(); +\stopecmacode + +\startecmacode + console("Example Four!"); + texsprint("\\startMPcode " + .concat(' fill fullcircle scaled 6cm withcolor "darkred";') + .concat(' fill fullcircle scaled 4cm withcolor "darkgreen";') + .concat(' fill fullcircle scaled 2cm withcolor "darkblue";') + .concat("\\stopMPcode ") + ); +\stopecmacode + +\startluacode + context.startMPcode() + context('fill fullcircle scaled 6cm withcolor "middlecyan";') + context('fill fullcircle scaled 4cm withcolor "middlemagenta";') + context('fill fullcircle scaled 2cm withcolor "middleyellow";') + context.stopMPcode() +\stopluacode +\stopbuffer + +\typebuffer \page \getbuffer + +\stoptext diff --git a/tex/context/base/mkiv/libs-imp-mysql.lua b/tex/context/base/mkiv/libs-imp-mysql.lua index b3896acd4..3e938a6de 100644 --- a/tex/context/base/mkiv/libs-imp-mysql.lua +++ b/tex/context/base/mkiv/libs-imp-mysql.lua @@ -44,15 +44,20 @@ local validspecification = helpers.validspecification local preparetemplate = helpers.preparetemplate local querysplitter = helpers.querysplitter local cache = { } +local timeout -- = 3600 -- to be tested local function connect(specification) - return mysql_open( + local db = mysql_open( specification.database or "", specification.username or "", specification.password or "", specification.host or "", specification.port ) + if db and timeout then + mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) + end + return db end local function execute_once(specification,retry) @@ -110,13 +115,13 @@ local function execute_once(specification,retry) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end @@ -131,7 +136,7 @@ local function execute_once(specification,retry) for i=1,#query do local okay = mysql_execute(db,query[i],callback) if not okay then - if id and option == "retry" and i == 1 then + if id and retry and i == 1 then report("error: %s, retrying to connect",mysql_getmessage(db)) mysql_close(db) cache[id] = nil @@ -183,6 +188,23 @@ return function(cells) end ]] +-- return function(result) +-- if not result then +-- return { } +-- end +-- local nofrows = #result +-- if nofrows == 0 then +-- return { } +-- end +-- local target = { } -- no %s needed here +-- for i=1,nofrows do +-- target[%s] = { +-- %s +-- } +-- end +-- return result +-- end + local celltemplate = "cells[%s]" methods.mysql = { @@ -192,5 +214,7 @@ methods.mysql = { celltemplate = celltemplate, } -package.loaded["util-sql-imp-mysql"] = methods.mysql -package.loaded[libname] = methods.mysql +package.loaded["util-sql-imp-ffi"] = methods.mysql +package.loaded["util-sql-imp-mysql"] = methods.mysql +package.loaded["util-sql-imp-library"] = methods.mysql +package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkiv/libs-imp-postgress.lua b/tex/context/base/mkiv/libs-imp-postgress.lua index 5cd04e03b..629079b01 100644 --- a/tex/context/base/mkiv/libs-imp-postgress.lua +++ b/tex/context/base/mkiv/libs-imp-postgress.lua @@ -114,13 +114,13 @@ local function execute_once(specification,retry) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end @@ -135,7 +135,7 @@ local function execute_once(specification,retry) for i=1,#query do local okay = postgress_execute(db,query[i],callback) if not okay then - if id and option == "retry" and i == 1 then + if id and retry and i == 1 then report("error: %s, retrying to connect",postgress_getmessage(db)) postgress_close(db) cache[id] = nil diff --git a/tex/context/base/mkiv/libs-imp-sqlite.lua b/tex/context/base/mkiv/libs-imp-sqlite.lua index 15c3222ea..5d38986f3 100644 --- a/tex/context/base/mkiv/libs-imp-sqlite.lua +++ b/tex/context/base/mkiv/libs-imp-sqlite.lua @@ -119,13 +119,13 @@ local function execute(specification) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end diff --git a/tex/context/base/mkiv/libs-imp-zint.lua b/tex/context/base/mkiv/libs-imp-zint.lua index eef2cd605..2c346ae7d 100644 --- a/tex/context/base/mkiv/libs-imp-zint.lua +++ b/tex/context/base/mkiv/libs-imp-zint.lua @@ -78,7 +78,7 @@ local shown = false ----- f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] -function zint.execute(specification) +local function execute(specification) if okay() then local code = specification.code local text = specification.text @@ -146,3 +146,16 @@ function zint.execute(specification) end end end + +optional.loaded.zint = { execute = execute } + +interfaces.implement { + name = "zint", + actions = execute, + arguments = { + { + { "code" }, + { "text" }, + } + } +} diff --git a/tex/context/base/mkiv/libs-imp-zint.mkxl b/tex/context/base/mkiv/libs-imp-zint.mkxl index d7436a4a4..72ce8157e 100644 --- a/tex/context/base/mkiv/libs-imp-zint.mkxl +++ b/tex/context/base/mkiv/libs-imp-zint.mkxl @@ -35,7 +35,10 @@ [\c!alternative=,\c!text=,#1]% \scale [#1]% - {\ctxlua{utilities.zint.execute{code="\dummyparameter\c!alternative",text=\!!bs\dummyparameter\c!text\!!es}}}% + {\clf_zint + code {\dummyparameter\c!alternative} + text {\dummyparameter\c!text} + \relax} \egroup} \protect diff --git a/tex/context/base/mkiv/libs-ini.lua b/tex/context/base/mkiv/libs-ini.lua index 2422305f0..2bac3201d 100644 --- a/tex/context/base/mkiv/libs-ini.lua +++ b/tex/context/base/mkiv/libs-ini.lua @@ -106,6 +106,8 @@ resolvers.libraries = libraries local report = logs.reporter("optional") +if optional then optional.loaded = { } end + function libraries.validoptional(name) local thelib = optional and optional[name] if not thelib then @@ -152,6 +154,21 @@ function libraries.optionalloaded(name,libnames) end end +if FFISUPPORTED and ffi and ffi.load then + + local ffiload = ffi.load + + function ffi.load(name) + local full = name and foundlibraries[name] + if full then + return ffiload(full) + else + return ffiload(name) + end + end + +end + -- local patterns = { -- "libs-imp-%s.mkxl", -- "libs-imp-%s.mklx", diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua index 8db2ecaf1..4ffcfd8a8 100644 --- a/tex/context/base/mkiv/lpdf-emb.lua +++ b/tex/context/base/mkiv/lpdf-emb.lua @@ -1721,6 +1721,12 @@ do -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat -- reader crashes. We really need to add a notdef! + local files = utilities.files + local openfile = files.open + local closefile = files.close + local setposition = files.setposition + local readstring = files.readstring + function methods.png(filename,details) local properties = details.properties local pngshapes = properties.indexdata[1] @@ -1732,23 +1738,37 @@ do local nofglyphs = 0 local scale = 10 * parameters.size/parameters.designsize local factor = bpfactor / scale - local units = parameters.units / 1000 + -- local units = parameters.units -- / 1000 + local units = 1000 + local filehandle = openfile(details.filename,true) local function pngtopdf(glyph,data) - -- local width = data.width - local info = graphics.identifiers.png(glyph.data,"string") - info.enforcecmyk = pngshapes.enforcecmyk - local image = lpdf.injectors.png(info,"string") - embedimage(image) - nofglyphs = nofglyphs + 1 - local width = (data.width or 0) * factor - local xoffset = (glyph.x or 0) / units - local yoffset = (glyph.y or 0) / units - local name = f_glyph(nofglyphs) - xforms[name] = pdfreference(image.objnum) - local pdf = f_image_xy(width,xoffset,yoffset,name) - return pdf, width + -- local info = graphics.identifiers.png(glyph.data,"string") + local offset = glyph.o + local size = glyph.s + local pdfdata = nil + if offset and size then + setposition(filehandle,offset) + local blob = readstring(filehandle,size) + local info = graphics.identifiers.png(blob,"string") + info.enforcecmyk = pngshapes.enforcecmyk + local image = lpdf.injectors.png(info,"string") + local width = (data.width or 0) * factor + if image then + embedimage(image) + nofglyphs = nofglyphs + 1 + local xoffset = (glyph.x or 0) / units + local yoffset = (glyph.y or 0) / units + local name = f_glyph(nofglyphs) + xforms[name] = pdfreference(image.objnum) + pdfdata = f_image_xy(width,xoffset,yoffset,name) + end + end + return pdfdata or f_stream(width), width end local function closepng() + if filehandle then + closefile(filehandle) + end pngshapes = nil end local function getresources() diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua index a14df3eca..0ad0c4e5e 100644 --- a/tex/context/base/mkiv/lpdf-lmt.lua +++ b/tex/context/base/mkiv/lpdf-lmt.lua @@ -74,6 +74,7 @@ local pdf_form = pdfconstant("Form") local fonthashes = fonts.hashes local characters = fonthashes.characters +local descriptions = fonthashes.descriptions local parameters = fonthashes.parameters local properties = fonthashes.properties @@ -146,6 +147,7 @@ end -- fonts local fontcharacters +local fontdescriptions local fontparameters local fontproperties local usedcharacters = setmetatableindex("table") @@ -161,6 +163,7 @@ lpdf.usedcharacters = usedcharacters local function updatefontstate(font) fontcharacters = characters[font] + fontdescriptions = descriptions[font] fontparameters = parameters[font] fontproperties = properties[font] local size = fontparameters.size -- or bad news @@ -373,6 +376,32 @@ local flushcharacter do -- as fontparameters already has checked / set it we can also have a variable -- for it so + local naturalwidth = nil + + local naturalwidths = setmetatableindex(function(t,font) + local d = descriptions[font] + local c = characters[font] + local f = parameters[font].hfactor + local v = setmetatableindex(function(t,char) + local e = d and d[char] + local w = 0 + if e then + w = e.width + if w then + w = w * f + end + end + e = c[char] + if e then + w = e.width or 0 + end + t[char] = w + return w + end) + t[font] = v + return v + end) + local function setup_fontparameters(font,factor,f,e) local slant = fontparameters.slantfactor or 0 local extend = fontparameters.extendfactor or 1 @@ -401,6 +430,8 @@ local flushcharacter do if format == "opentype" or format == "type1" then fs = fs * 1000 / fontparameters.units -- can we avoid this ? end + -- + naturalwidth = naturalwidths[font] end -- This only saves a little on hz because there we switch a lot of @@ -512,7 +543,7 @@ local flushcharacter do local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) - flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then pdf_goto_textmode() setup_fontparameters(font,factor,f,e) @@ -523,12 +554,12 @@ local flushcharacter do end local move = calc_pdfpos(pos_h,pos_v) - if trace_threshold then - report( - "font %i, char %C, factor %i, width %p, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", - font,char,factor,width,naturalwidth,move,need_tm,pos_h,tj_delta,threshold,cw - ) - end + -- if trace_threshold then + -- report( + -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", + -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw + -- ) + -- end if move or need_tm then if not need_tm then @@ -569,7 +600,8 @@ local flushcharacter do end -- cw = cw + naturalwidth - cw = cw + width + -- cw = cw + width + cw = cw + naturalwidth[char] local index = data.index or char @@ -2407,67 +2439,69 @@ updaters.register("backend.update.pdf",function() end local function embedimage(specification) - lastindex = lastindex + 1 - index = lastindex - specification.index = index - local xobject = pdfdictionary { } - if not specification.notype then - xobject.Type = pdf_xobject - xobject.Subtype = pdf_form - xobject.FormType = 1 - end - local bbox = specification.bbox - if bbox and not specification.nobbox then - xobject.BBox = pdfarray { - bbox[1] * bpfactor, - bbox[2] * bpfactor, - bbox[3] * bpfactor, - bbox[4] * bpfactor, - } - end - xobject = xobject + specification.attr - if bbox and not specification.width then - specification.width = bbox[3] - end - if bbox and not specification.height then - specification.height = bbox[4] - end - local dict = xobject() - -- - nofobjects = nofobjects + 1 - local objnum = nofobjects - local nolength = specification.nolength - local stream = specification.stream or specification.string - -- - -- We cannot set type in native img so we need this hack or - -- otherwise we need to patch too much. Better that i write - -- a wrapper then. Anyway, it has to be done better: a key that - -- tells either or not to scale by xsize/ysize when flushing. - -- - if not specification.type then - local kind = specification.kind - if kind then - -- take that one - elseif attr and find(attr,"BBox") then - kind = img_stream - else - -- hack: a bitmap - kind = img_none + if specification then + lastindex = lastindex + 1 + index = lastindex + specification.index = index + local xobject = pdfdictionary { } + if not specification.notype then + xobject.Type = pdf_xobject + xobject.Subtype = pdf_form + xobject.FormType = 1 end - specification.type = kind - specification.kind = kind - end - local compress = compresslevel and compresslevel > 0 or nil - flushstreamobj(stream,objnum,dict,compress,nolength) - specification.objnum = objnum - specification.rotation = specification.rotation or 0 - specification.orientation = specification.orientation or 0 - specification.transform = specification.transform or 0 - specification.stream = nil - specification.attr = nil - specification.type = specification.kind or specification.type or img_none - indices[index] = specification -- better create a real specification - return specification + local bbox = specification.bbox + if bbox and not specification.nobbox then + xobject.BBox = pdfarray { + bbox[1] * bpfactor, + bbox[2] * bpfactor, + bbox[3] * bpfactor, + bbox[4] * bpfactor, + } + end + xobject = xobject + specification.attr + if bbox and not specification.width then + specification.width = bbox[3] + end + if bbox and not specification.height then + specification.height = bbox[4] + end + local dict = xobject() + -- + nofobjects = nofobjects + 1 + local objnum = nofobjects + local nolength = specification.nolength + local stream = specification.stream or specification.string + -- + -- We cannot set type in native img so we need this hack or + -- otherwise we need to patch too much. Better that i write + -- a wrapper then. Anyway, it has to be done better: a key that + -- tells either or not to scale by xsize/ysize when flushing. + -- + if not specification.type then + local kind = specification.kind + if kind then + -- take that one + elseif attr and find(attr,"BBox") then + kind = img_stream + else + -- hack: a bitmap + kind = img_none + end + specification.type = kind + specification.kind = kind + end + local compress = compresslevel and compresslevel > 0 or nil + flushstreamobj(stream,objnum,dict,compress,nolength) + specification.objnum = objnum + specification.rotation = specification.rotation or 0 + specification.orientation = specification.orientation or 0 + specification.transform = specification.transform or 0 + specification.stream = nil + specification.attr = nil + specification.type = specification.kind or specification.type or img_none + indices[index] = specification -- better create a real specification + return specification + end end codeinjections.embedimage = embedimage diff --git a/tex/context/base/mkiv/lpdf-wid.lua b/tex/context/base/mkiv/lpdf-wid.lua index b8648b32a..8e0a45a00 100644 --- a/tex/context/base/mkiv/lpdf-wid.lua +++ b/tex/context/base/mkiv/lpdf-wid.lua @@ -252,20 +252,25 @@ job.register('job.fileobjreferences.collected', tobesavedobjrefs, initializer) local function flushembeddedfiles() if enabled and next(filestreams) then local e = pdfarray() + local f = pdfarray() for tag, reference in sortedhash(filestreams) do if not reference then report_attachment("unreferenced file, tag %a",tag) --- elseif referenced[tag] == "hidden" then - elseif referenced[tag] ~= "hidden" then + elseif referenced[tag] == "hidden" then e[#e+1] = pdfstring(tag) e[#e+1] = reference -- already a reference + f[#f+1] = reference -- collect all file description references else - -- -- messy spec ... when annot not in named else twice in menu list acrobat + -- messy spec ... when annot not in named else twice in menu list acrobat + f[#f+1] = reference end end if #e > 0 then lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e }))) end + if #f > 0 then -- PDF/A-2|3: all associated files must have a relationship to the PDF document (global or part) + lpdf.addtocatalog("AF", pdfreference(pdfflushobject(f))) -- global (Catalog) + end end end @@ -430,6 +435,7 @@ function nodeinjections.attachfile(specification) else referenced[hash] = "annotation" local name, appearance = analyzesymbol(specification.symbol,attachment_symbols) + local flags = specification.flags or 0 -- to keep it expandable local d = pdfdictionary { Subtype = pdfconstant("FileAttachment"), FS = aref, @@ -442,7 +448,8 @@ function nodeinjections.attachfile(specification) CA = analyzetransparency(specification.transparencyvalue), AP = appearance, OC = analyzelayer(specification.layer), - F = pdfnull(), -- another rediculous need to satisfy validation + -- F = pdfnull(), -- another rediculous need to satisfy validation + F = (flags | 4) & (1023-1-2-32-256), -- set 3, clear 1,2,6,9; PDF 32000-1, p385 } local width = specification.width or 0 local height = specification.height or 0 @@ -534,7 +541,6 @@ function nodeinjections.comment(specification) -- brrr: seems to be done twice Name = name, NM = pdfstring("comment:"..nofcomments), AP = appearance, - F = pdfnull(), -- another rediculous need to satisfy validation } local width = specification.width or 0 local height = specification.height or 0 diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua index 51eab5a1d..3125495b4 100644 --- a/tex/context/base/mkiv/luat-cod.lua +++ b/tex/context/base/mkiv/luat-cod.lua @@ -137,10 +137,8 @@ if LUATEXENGINE == nil then end if LUATEXVERSION == nil then - LUATEXVERSION = status.luatex_revision LUATEXVERSION = status.luatex_version/100 - -- + tonumber(LUATEXVERSION)/1000 - + (tonumber(LUATEXVERSION) or (string.byte(LUATEXVERSION)-string.byte("a")+10))/1000 + + tonumber(status.luatex_revision)/10000 end if CONTEXTLMTXMODE == nil then diff --git a/tex/context/base/mkiv/luat-ini.lua b/tex/context/base/mkiv/luat-ini.lua index 332980013..cec0161e7 100644 --- a/tex/context/base/mkiv/luat-ini.lua +++ b/tex/context/base/mkiv/luat-ini.lua @@ -26,7 +26,7 @@ if not global then end LUATEXVERSION = status.luatex_version/100 - + tonumber(status.luatex_revision)/1000 + + tonumber(status.luatex_revision)/10000 LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv index c3bbd8e19..0ffd1dd40 100644 --- a/tex/context/base/mkiv/luat-lib.mkiv +++ b/tex/context/base/mkiv/luat-lib.mkiv @@ -73,9 +73,9 @@ \registerctxluafile{data-use}{} \registerctxluafile{data-aux}{} -\ifcase\contextlmtxmode - \registerctxluafile{util-lib}{} -\fi +% \ifcase\contextlmtxmode +% \registerctxluafile{util-lib}{} +% \fi \registerctxluafile{luat-cbk}{} \registerctxluafile{luat-run}{} diff --git a/tex/context/base/mkiv/m-gnuplot.mkxl b/tex/context/base/mkiv/m-gnuplot.mkxl new file mode 100644 index 000000000..2077b1741 --- /dev/null +++ b/tex/context/base/mkiv/m-gnuplot.mkxl @@ -0,0 +1,97 @@ +%D \module +%D [ file=m-gnuplot, +%D version=2020.02.10, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=Gnuplot, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This is a variant on the \GNUPLOT\ terminal code. At some point (when there is a +%D reason) I will make a proper environment that can be used for embedded code. + +\unexpanded\def\includegnuplotsvgfile[#1]% + {\hbox\bgroup + \ctxlua{metapost.startsvghashing()}% + \includesvgfile[#1]% + \ctxlua{metapost.stopsvghashing()}% + \egroup} + +\startluacode + +local modificationtime = lfs.modification +local longtostring = string.longtostring +local formatters = string.formatters +local expandfilename = dir.expandname +local isfile = lfs.isfile + +local runner = sandbox.registerrunner { + name = "gnuplot to svg", + program = "gnuplot", + template = longtostring [[ + -e "set output '%newname%'; set terminal svg" + "%oldname%" + ]], + checkers = { + oldname = "readable", + newname = "writable", + }, +} + +figures.programs.gnuplot = { + runner = runner, +} + +local function remap(specification) + local oldname = specification.fullname + if oldname then + local newname = file.replacesuffix(oldname,"svg") + local oldtime = modificationtime(oldname) or 0 + local newtime = modificationtime(newname) or 0 + if newtime == 0 or oldtime > newtime then + runner { + newname = expandfilename(newname), + oldname = expandfilename(oldname), + } + end + if isfile(newname) then + local only = file.nameonly(newname) + local name = formatters["svg-%s-inclusion"](only) + local code = formatters["\\includegnuplotsvgfile[%s]\\resetbuffer[%s]"](newname,name) + buffers.assign(name,code) + specification.format = "buffer" + specification.fullname = name + end + end + return specification +end + +figures.remappers.gp = { svg = remap } + +\stopluacode + +\continueifinputfile{m-gnuplot.mkxl} + +\startluacode +io.savedata("m-gnuplot-demo.gp", [[ +set format xy "$%g$" + +set title 'This is a plot of $y=\\sin(x)$' +set xlabel 'This is the $x$ axis' +set ylabel 'This is the $y$ axis' + +plot [0:6.28] [0:1] sin(x) +]]) +\stopluacode + +\starttext + + \externalfigure[m-gnuplot-demo.gp][conversion=svg,width=4cm] + + \externalfigure[m-gnuplot-demo.gp][conversion=svg,width=8cm] + +\stoptext diff --git a/tex/context/base/mkiv/m-zint.mkxl b/tex/context/base/mkiv/m-zint.mkxl deleted file mode 100644 index 7135126ba..000000000 --- a/tex/context/base/mkiv/m-zint.mkxl +++ /dev/null @@ -1,7 +0,0 @@ -% this is a stub: - -% \uselibrary[zint] - -\input libs-imp-zint.mkxl - -\endinput diff --git a/tex/context/base/mkiv/meta-imp-threesix.mkxl b/tex/context/base/mkiv/meta-imp-threesix.mkxl new file mode 100644 index 000000000..277aa85f7 --- /dev/null +++ b/tex/context/base/mkiv/meta-imp-threesix.mkxl @@ -0,0 +1,253 @@ +% not yet a module + +\startluacode + local gsub, utfbyte = string.gsub, utf.byte + + -- The font from DEK's facs9b.ps (I wish I was clever enough to understand all the good + -- stuff in there): + + local font36 = { + ["0"] = [[00111100 01111110 11000011 11000011 11000011 11000011 01111110 00111100]], + ["1"] = [[00011100 11111100 11101100 00001100 00001100 00001100 11111111 11111111]], + ["2"] = [[00111110 01110011 01110011 00000011 00001110 00111000 11110001 11111111]], + ["3"] = [[01111110 01100110 00000110 00111100 00000110 11100111 11100111 01111110]], + ["4"] = [[00001110 00011110 00110110 01100110 11111111 11111111 00000110 00001110]], + ["5"] = [[01111110 01111110 01000000 01111100 01000111 00000011 11000111 11111110]], + ["6"] = [[01111110 01100110 11000000 11011100 11100110 11000011 01100011 01111110]], + ["7"] = [[11111111 11111111 10000111 10001110 00011100 00011100 00011100 00011100]], + ["8"] = [[01111110 01100110 01100110 00111100 11000011 11000011 11000011 01111110]], + ["9"] = [[01111110 11000110 11000011 01100111 00111011 00000011 01100110 01111110]], + ["A"] = [[000110000 000111000 001111100 001101100 011001110 011111110 010000110 111100111]], + ["B"] = [[1111100 1110110 0110110 0111100 0110011 0110011 1110011 1111100]], + ["C"] = [[01111101 11110011 11100001 11100001 11100000 11100000 11100001 01111110]], + ["D"] = [[11111100 11100010 01100011 01100011 01100011 01100011 11100010 11111100]], + ["E"] = [[1111111 1110001 0110101 0111100 0110100 0110001 1110001 1111111]], + ["F"] = [[11111111 11100001 01100101 01111100 01100100 01100000 11111000 11111000]], + ["G"] = [[01111010 11100110 11100010 11100000 11100111 11100010 11100010 01111100]], + ["H"] = [[11100111 11100111 01000010 01111110 01000010 01000010 11100111 11100111]], + ["I"] = [[1111111 1111111 0011000 0011000 0011000 0011000 1111111 1111111]], + ["J"] = [[01111111 01111111 00000110 00000110 11110110 01100110 01100110 00111100]], + ["K"] = [[11101110 11100100 01101000 01110000 01111000 01101100 11100110 11101111]], + ["L"] = [[111111000 111111000 011000000 011000000 011000000 011000011 111000011 111111111]], + ["M"] = [[1100000011 1110000111 0111111110 0100110010 0100110010 0100000010 1100000011 1100000011]], + ["N"] = [[11000011 11100011 01110010 01111010 01011110 01001110 11100110 11100010]], + ["O"] = [[01111110 11000011 11000011 11000011 11000011 11000011 11000011 01111110]], + ["P"] = [[11111110 11100011 01100011 01111110 01100000 01100000 11111000 11111000]], + ["Q"] = [[01111100 11000110 11000110 11000110 11000110 11001110 11000110 01111101]], + ["R"] = [[11111100 11100110 01100110 01111100 01101000 01100100 11100010 11100111]], + ["S"] = [[01111110 11100001 11100001 01111000 00011110 10000111 11000011 10111110]], + ["T"] = [[1111111111 1100110011 1100110011 0000110000 0000110000 0000110000 0001111000 0001111000]], + ["U"] = [[111101111 111101111 011000010 011000010 011000010 011000010 011000010 001111100]], + ["V"] = [[11111000111 11111000111 01110000010 00110000100 00111000100 00011001000 00001101000 00001110000]], + ["W"] = [[111000000111 111000000111 110000000010 011000000100 011001000100 001101101000 001101101000 000110110000]], + ["X"] = [[1111001110 1111000110 0001101000 0000110000 0000110000 0001011000 0110001111 0111001111]], + ["Y"] = [[111100011 111100011 011000010 001110100 000111000 000011000 001111110 001111110]], + ["Z"] = [[11111111 10000111 00001110 00011100 00111000 01110000 11100001 11111111]], + } + + local f_code = string.formatters["ThreeSix(%s);"] + local replace = { ["0"] = "N;", ["1"] = "Y;", [" "] = "L;" } + + local function remap(str) + -- permit abundant spacing (bonus) + str = gsub(str,"%s+", " ") + -- remap what we got to macro calls + str = gsub(str,".",replace) + -- return the result + return str + end + + function MP.registerthreesix(name) + fonts.dropins.registerglyphs { + name = name, + units = 12, + usecolor = true, + preamble = "InitializeThreeSix;", + } + for u, v in table.sortedhash(font36) do + local ny = 8 + local nx = (#v - ny + 1) // ny + local height = ny * 1.1 - 0.1 + local width = nx * 1.1 - 0.1 + fonts.dropins.registerglyph { + category = name, + unicode = utfbyte(u), + width = width, + height = height, + code = f_code(remap(v)), + } + end + end + + MP.registerthreesix("fontthreesix") +\stopluacode + +% \startMPcalculation{simplefun} +% def InitializeThreeSix = +% save Y, N, L, S ; save dx, dy, nx, ny ; +% save shape, fillcolor, mypen, random, currentpen, spread, hoffset ; +% string shape, fillcolor, mypen ; boolean random ; pen currentpen ; +% dx := 11/10 ; +% dy := - 11/10 ; +% nx := - dx ; +% ny := 0 ; +% shape := getparameterdefault "mpsfont" "shape" "circle" ; +% random := hasoption "mpsfont" "random" "true" ; +% fillcolor := getparameterdefault "mpsfont" "color" "" ; +% mypen := getparameterdefault "mpsfont" "pen" "" ; +% spread := getparameterdefault "mpsfont" "spread" 0 ; +% hoffset := 12 * spread / 2 ; +% currentpen := pencircle +% if mypen = "fancy" : +% xscaled 1/20 yscaled 2/20 rotated 45 +% else : +% scaled 1/20 +% fi ; +% if shape == "square" : +% def S = +% unitsquare if random : randomized 1/10 fi +% shifted (nx,ny) +% enddef ; +% elseif shape = "diamond" : +% def S = +% unitdiamond if random : randomized 1/10 fi +% shifted (nx,ny) +% enddef ; +% else : +% def S = +% unitcircle if random : randomizedcontrols 1/20 fi +% shifted (nx,ny) +% enddef ; +% fi ; +% def N = +% nx := nx + dx ; +% draw S ; +% enddef ; +% if fillcolor = "random" : +% def Y = +% nx := nx + dx ; +% fillup S withcolor white randomized (2/3,2/3,2/3) ; +% enddef ; +% elseif fillcolor = "" : +% def Y = +% nx := nx + dx ; +% fillup S ; +% enddef ; +% else : +% def Y = +% nx := nx + dx ; +% fillup S withcolor fillcolor ; +% enddef ; +% fi ; +% def L = +% nx := - dx ; +% ny := ny + dy ; +% enddef ; +% enddef ; +% +% vardef ThreeSix (text code) = +% InitializeThreeSix ; +% draw image (code) shifted (hoffset,-ny) ; +% enddef ; +% \stopMPcalculation + +\startMPcalculation{simplefun} + def InitializeThreeSix = + save Y, N, L, S ; + % save dx, dy, nx, ny ; + save shape, fillcolor, mypen, random, threesixpen, spread, hoffset ; + string shape, fillcolor, mypen ; boolean random ; pen threesixpen ; + % dx := 11/10 ; + % dy := - 11/10 ; + % nx := - dx ; + % ny := 0 ; + shape := getparameterdefault "mpsfont" "shape" "circle" ; + random := hasoption "mpsfont" "random" "true" ; + fillcolor := getparameterdefault "mpsfont" "color" "" ; + mypen := getparameterdefault "mpsfont" "pen" "" ; + spread := getparameterdefault "mpsfont" "spread" 0 ; + hoffset := 12 * spread / 2 ; + threesixpen := pencircle + if mypen = "fancy" : + xscaled 1/20 yscaled 2/20 rotated 45 + else : + scaled 1/20 + fi ; + if shape == "square" : + def S = + unitsquare if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + elseif shape = "diamond" : + def S = + unitdiamond if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + else : + def S = + unitcircle if random : randomizedcontrols 1/20 fi + shifted (nx,ny) + enddef ; + fi ; + def N = + nx := nx + dx ; + draw S ; + enddef ; + if fillcolor = "random" : + def Y = + nx := nx + dx ; + fillup S withcolor white randomized (2/3,2/3,2/3) ; + enddef ; + elseif fillcolor = "" : + def Y = + nx := nx + dx ; + fillup S ; + enddef ; + else : + def Y = + nx := nx + dx ; + fillup S withcolor fillcolor ; + enddef ; + fi ; + def L = + nx := - dx ; + ny := ny + dy ; + enddef ; + enddef ; + + vardef ThreeSix (text code) = + save dx, dy, nx, ny ; + dx := 11/10 ; + dy := - 11/10 ; + nx := - dx ; + ny := 0 ; + pickup threesixpen ; + draw image (code) shifted (hoffset,-ny) ; + enddef ; +\stopMPcalculation + +\definefontfeature % black and white, with some spread + [fontthreesix] + [default] + [metapost=fontthreesix] + +\definefontfeature % color, with some spread + [fontthreesix-tweak] + [default] + [metapost={category=fontthreesix,spread=.1}] + +\definefontfeature % color, with some spread + [fontthreesix-color] + [default] + [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1}] + +\definefontfeature % color, tight + [fontthreesix-initial] + [metapost={category=fontthreesix,color=random,shape=circle}] % units? + +\definefont[DEKFontA][Serif*fontthreesix] +\definefont[DEKFontB][Serif*fontthreesix-color] +\definefont[DEKFontC][Serif*fontthreesix-initial] +\definefont[DEKFontD][Serif*fontthreesix-tweak] + +\endinput diff --git a/tex/context/base/mkiv/meta-tex.mkiv b/tex/context/base/mkiv/meta-tex.mkiv index 418ddc196..c580596f7 100644 --- a/tex/context/base/mkiv/meta-tex.mkiv +++ b/tex/context/base/mkiv/meta-tex.mkiv @@ -236,4 +236,7 @@ \unexpanded\def\svgsetlayer#1#2% {\setlayer[svgmps][\c!x=#1\onebasepoint,\c!y=#2\onebasepoint]} % {#3} +\unexpanded\def\svghashed#1% + {\clf_svghashed#1\relax} + \protect \endinput diff --git a/tex/context/base/mkiv/mlib-svg.lua b/tex/context/base/mkiv/mlib-svg.lua index b56c1fd54..f4b3117a6 100644 --- a/tex/context/base/mkiv/mlib-svg.lua +++ b/tex/context/base/mkiv/mlib-svg.lua @@ -75,24 +75,21 @@ if not modules then modules = { } end modules ['mlib-svg'] = { -- One can run into pretty crazy images, like lines that are fills being clipped -- to some width. That's the danger of hiding yourself behind an interface I guess. -local rawget, type, tonumber, tostring, next, setmetatable = rawget, type, tonumber, tostring, next, setmetatable +local rawget, rawset, type, tonumber, tostring, next, setmetatable = rawget, rawset, type, tonumber, tostring, next, setmetatable -local P, S, R, C, Ct, Cs, Cc, Cp, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Carg +local P, S, R, C, Ct, Cs, Cc, Cp, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cg, lpeg.Cf, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local pi, sin, cos, asin, sind, cosd, tan, abs, sqrt = math.pi, math.sin, math.cos, math.asin, math.sind, math.cosd, math.tan, math.abs, math.sqrt +local sqrt = math.sqrt local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash local gmatch, gsub, find, match, rep = string.gmatch, string.gsub, string.find, string.match, string.rep local formatters, fullstrip = string.formatters, string.fullstrip -local extract = bit32.extract local utfsplit, utfbyte = utf.split, utf.byte local xmlconvert, xmlcollected, xmlcount, xmlfirst, xmlroot = xml.convert, xml.collected, xml.count, xml.first, xml.root local xmltext, xmltextonly = xml.text, xml.textonly local css = xml.css or { } -- testing -local bpfactor = number.dimenfactors.bp - local function xmlinheritattributes(c,pa) local at = c.at local dt = c.dt @@ -134,6 +131,47 @@ local pathtracer = { ["fill-opacity"] = ".75", } +-- This is just an experiment. Todo: reset hash etc. Also implement +-- an option handler. + +local svghash = false do + + local svglast = 0 + local svglist = false + + local function checkhash(t,k) + local n = svglast + 1 + svglast = n + svglist[n] = k + t[k] = n + return n + end + + function metapost.startsvghashing() + svglast = 0 + svglist = { } + svghash = setmetatableindex(checkhash) + end + + function metapost.stopsvghashing() + svglast = 0 + svglist = false + svghash = false + end + + interfaces.implement { + name = "svghashed", + arguments = "integer", + actions = function(n) + local t = svglist and svglist[n] + if t then + context(t) + end + end + } + +end + -- We have quite some closures because otherwise we run into the local variable -- limitations. It doesn't always look pretty now, sorry. I'll clean up this mess -- some day (the usual nth iteration of code). @@ -149,6 +187,8 @@ local pathtracer = { local a2c do + local pi, sin, cos, tan, asin, abs = math.pi, math.sin, math.cos, math.tan, math.asin, math.abs + local d120 = (pi * 120) / 180 local pi2 = 2 * pi @@ -401,6 +441,8 @@ local rgbcomponents, withcolor, thecolor do local f_svggray = formatters['svggray(%.3N)'] local f_svgname = formatters['"%s"'] + local extract = bit32.extract + local triplets = setmetatableindex(function(t,k) -- we delay building all these strings local v = svgcolors[k] @@ -971,6 +1013,8 @@ local f_wrapped_stop = formatters[") shifted (0,%N) scaled %N ;"] local handletransform, handleviewbox do + local sind = math.sind + --todo: better lpeg local f_rotatedaround = formatters[" rotatedaround((%N,%N),%N)"] @@ -1017,7 +1061,7 @@ local handletransform, handleviewbox do local function skewx(x) if x then - return f_slanted_x(math.sind(-x)) + return f_slanted_x(sind(-x)) else return "" end @@ -1025,7 +1069,7 @@ local handletransform, handleviewbox do local function skewy(y) if y then - return f_slanted_y(math.sind(-y)) + return f_slanted_y(sind(-y)) else return "" end @@ -1035,24 +1079,34 @@ local handletransform, handleviewbox do return f_matrix(rx or 1, sx or 0, sy or 0, ry or 1, tx or 0, - (ty or 0)) end - -- how to deal with units here? + -- How to deal with units here? Anyway, order seems to matter. - local p_transform = Cs ( ( - P("translate") * p_numbers / translate -- maybe xy - + P("scale") * p_numbers / scale - + P("rotate") * p_numbers / rotate - + P("matrix") * p_numbers / matrix - + P("skewX") * p_numbers / skewx - + P("skewY") * p_numbers / skewy - -- + p_separator - + P(1)/"" - )^1) + local p_transform = Cf ( Ct("") * ( + lpegpatterns.whitespace^0 * Cg( + C("translate") * (p_numbers / translate) -- maybe xy + + C("scale") * (p_numbers / scale) + + C("rotate") * (p_numbers / rotate) + + C("matrix") * (p_numbers / matrix) + + C("skewX") * (p_numbers / skewx) + + C("skewY") * (p_numbers / skewy) + ) + )^1, rawset) handletransform = function(at) local t = at.transform if t then local e = lpegmatch(p_transform,t) - return s_transform_start, f_transform_stop(e), t + if e then + e = concat({ + e.rotate or "", + e.skewX or "", + e.skewY or "", + e.scale or "", + e.translate or "", + e.matrix or "", + }, " ") + return s_transform_start, f_transform_stop(e), t + end end end @@ -2340,6 +2394,7 @@ do local f_scaled = formatters["\\svgscaled{%N}{%s}{%s}{%s}"] local f_normal = formatters["\\svgnormal{%s}{%s}{%s}"] + local f_hashed = formatters["\\svghashed{%s}"] -- We move to the outer (x,y) and when we have an inner offset we -- (need to) compensate for that outer offset. @@ -2348,8 +2403,14 @@ do -- local f_text_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] -- local f_text_simple_svg = formatters['svgtext("%s")'] - local f_text_normal_svg = formatters['(textext.drt("%s") shifted (%N,%N))'] - local f_text_simple_svg = formatters['textext.drt("%s")'] + local anchors = { + ["start"] = "drt", + ["end"] = "dflt", + ["middle"] = "d", + } + + local f_text_normal_svg = formatters['(textext.%s("%s") shifted (%N,%N))'] + local f_text_simple_svg = formatters['textext.%s("%s")'] -- or just maptext @@ -2480,7 +2541,9 @@ do di = gsub(di,"%s+$","") end local chars = utfsplit(di) - if tx then + if svghash then + di = f_hashed(svghash[di]) + elseif tx then for i=1,#chars do chars[i] = f_poschar( (tx[i] or 0) - x, @@ -2540,6 +2603,7 @@ do v_fill = "black" end local color, opacity, invisible = fillproperties(v_fill,at) + local anchor = anchors[at["text-anchor"] or "start"] or "drt" local r = metapost.remappedtext(only) if r then if x == 0 and y == 0 then @@ -2567,9 +2631,9 @@ do result[#result+1] = s_stoplayer result = concat(result) if x == 0 and y == 0 then - result = f_text_simple_svg(result) + result = f_text_simple_svg(anchor,result) else - result = f_text_normal_svg(result,x,y) + result = f_text_normal_svg(anchor,result,x,y) end flushobject(result,at,color,opacity) if trace_text then @@ -2741,7 +2805,7 @@ do definitions = { } tagstyles = { } classstyles = { } - for s in xmlcollected(c,"/style") do + for s in xmlcollected(c,"style") do -- can also be in a def, so let's play safe handlestyle(c) end handlechains(c) @@ -2777,101 +2841,107 @@ end -- a bit more efficient, because we now go to mp and back which is kind of redundant, -- but for now it will do. -function metapost.includesvgfile(filename,offset) -- offset in sp - if lfs.isfile(filename) then +do + + local bpfactor = number.dimenfactors.bp + + function metapost.includesvgfile(filename,offset) -- offset in sp + if lfs.isfile(filename) then + context.startMPcode("doublefun") + context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) + context.stopMPcode() + end + end + + function metapost.includesvgbuffer(name,offset) -- offset in sp context.startMPcode("doublefun") - context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) + context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) context.stopMPcode() end -end - -function metapost.includesvgbuffer(name,offset) -- offset in sp - context.startMPcode("doublefun") - context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) - context.stopMPcode() -end -interfaces.implement { - name = "includesvgfile", - actions = metapost.includesvgfile, - arguments = { "string", "dimension" }, -} + interfaces.implement { + name = "includesvgfile", + actions = metapost.includesvgfile, + arguments = { "string", "dimension" }, + } -interfaces.implement { - name = "includesvgbuffer", - actions = metapost.includesvgbuffer, - arguments = { "string", "dimension" }, -} + interfaces.implement { + name = "includesvgbuffer", + actions = metapost.includesvgbuffer, + arguments = { "string", "dimension" }, + } -function metapost.showsvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local comment = data.comment - local offset = data.pageoffset - local index = data.index - local first = math.max(index or 1,1) - local last = math.min(index or #dd,#dd) - for i=first,last do - local d = setmetatableindex( { - data = dd[i], - comment = comment and i or false, - pageoffset = offset or nil, - }, data) - metapost.showsvgpage(d) - end - elseif data.method == "code" then - context.startMPcode(doublefun) - context(metapost.svgtomp(data)) - context.stopMPcode() - else - context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } - context(metapost.svgtomp(data)) + function metapost.showsvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then local comment = data.comment - if comment then - context("draw boundingbox currentpicture withcolor .6red ;") - context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) - end - context.stopMPpage() - end -end - -function metapost.typesvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local index = data.index - if index and index > 0 and index <= #dd then - data = dd[index] + local offset = data.pageoffset + local index = data.index + local first = math.max(index or 1,1) + local last = math.min(index or #dd,#dd) + for i=first,last do + local d = setmetatableindex( { + data = dd[i], + comment = comment and i or false, + pageoffset = offset or nil, + }, data) + metapost.showsvgpage(d) + end + elseif data.method == "code" then + context.startMPcode(doublefun) + context(metapost.svgtomp(data)) + context.stopMPcode() else - data = nil + context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } + context(metapost.svgtomp(data)) + local comment = data.comment + if comment then + context("draw boundingbox currentpicture withcolor .6red ;") + context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) + end + context.stopMPpage() end end - if type(data) == "string" and data ~= "" then - buffers.assign("svgpage",data) - context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) + + function metapost.typesvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then + local index = data.index + if index and index > 0 and index <= #dd then + data = dd[index] + else + data = nil + end + end + if type(data) == "string" and data ~= "" then + buffers.assign("svgpage",data) + context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) + end end -end -function metapost.svgtopdf(data,...) - local mps = metapost.svgtomp(data,...) - if mps then - -- todo: special instance, only basics needed - local pdf = metapost.simple("metafun",mps,true,false,"svg") - if pdf then - return pdf + function metapost.svgtopdf(data,...) + local mps = metapost.svgtomp(data,...) + if mps then + -- todo: special instance, only basics needed + local pdf = metapost.simple("metafun",mps,true,false,"svg") + if pdf then + return pdf + else + -- message + end else -- message end - else - -- message end + end do diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex b7c571975..e5fe90ad2 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 453fc01db..ac49b2139 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua index d2b1e9768..2ff87e21a 100644 --- a/tex/context/base/mkiv/tabl-xtb.lua +++ b/tex/context/base/mkiv/tabl-xtb.lua @@ -478,36 +478,50 @@ end function xtables.initialize_construct() local r = data.currentrow local c = data.currentcolumn + 1 + local settings = data.settings local rows = data.rows local row = rows[r] while row[c].span do -- can also be previous row ones c = c + 1 end data.currentcolumn = c - local widths = data.widths - local heights = data.heights - local depths = data.depths + local widths = data.widths + local heights = data.heights + local depths = data.depths + local distances = data.distances -- local drc = row[c] local wd = drc.wd local ht = drc.ht local dp = drc.dp + local nx = drc.nx - 1 + local ny = drc.ny - 1 -- local width = widths[c] local height = heights[r] local depth = depths[r] -- problem: can be the depth of a one liner -- - for x=1,drc.nx-1 do - width = width + widths[c+x] + local total = height + depth + -- + if nx > 0 then + for x=1,nx do + width = width + widths[c+x] + distances[c+x-1] + end + local distance = settings.columndistance + if distance ~= 0 then + width = width + nx * distance + end end -- - local total = height + depth - local ny = drc.ny - if ny > 1 then - for y=1,ny-1 do + if ny > 0 then + for y=1,ny do local nxt = r + y total = total + heights[nxt] + depths[nxt] end + local distance = settings.rowdistance + if distance ~= 0 then + total = total + ny * distance + end end -- texsetdimen("d_tabl_x_width",width) diff --git a/tex/context/base/mkiv/util-pck.lua b/tex/context/base/mkiv/util-pck.lua index b90853fb6..6af53f9eb 100644 --- a/tex/context/base/mkiv/util-pck.lua +++ b/tex/context/base/mkiv/util-pck.lua @@ -10,6 +10,7 @@ if not modules then modules = { } end modules ['util-pck'] = { local next, tostring, type = next, tostring, type local sort, concat = table.sort, table.concat +local format = string.format local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash utilities = utilities or { } @@ -17,14 +18,17 @@ utilities.packers = utilities.packers or { } local packers = utilities.packers packers.version = 1.01 +local fmt_kv = JITSUPPORTED and "%s=%s" or "%s=%q" +local fmt_kt = JITSUPPORTED and "%s={%s}" or "%s={%q}" + local function hashed(t) local s, ns = { }, 0 for k, v in next, t do ns = ns + 1 if type(v) == "table" then - s[ns] = k .. "={" .. hashed(v) .. "}" + s[ns] = format(fmt_kt,k,hashed(v)) else - s[ns] = k .. "=" .. tostring(v) + s[ns] = format(fmt_kv,k,v) end end sort(s) @@ -35,7 +39,7 @@ local function simplehashed(t) local s, ns = { }, 0 for k, v in next, t do ns = ns + 1 - s[ns] = k .. "=" .. v + s[ns] = format(fmt_kv,k,v) end sort(s) return concat(s,",") diff --git a/tex/context/base/mkiv/util-sql.lua b/tex/context/base/mkiv/util-sql.lua index 61f1f19fa..36f3eab19 100644 --- a/tex/context/base/mkiv/util-sql.lua +++ b/tex/context/base/mkiv/util-sql.lua @@ -116,12 +116,12 @@ if optional then library = "mysql", swiglib = "mysql", postgress = "postgress", - sqlite = "sqlite" - sqlite3 = "sqlite" + sqlite = "sqlite", + sqlite3 = "sqlite", } setmetatableindex(sql.methods,function(t,k) - local m = methods[k + local m = methods[k] if m then report_state("start loading method %a as %a",k,m) require("libs-imp-" .. m) diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index 68c9be586..4d23f88b7 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -701,14 +701,18 @@ local format_left = function(f) end end -local format_q = function() +local format_q = JITSUPPORTED and function() n = n + 1 -- lua 5.3 has a different q than lua 5.2 (which does a tostring on numbers) -- return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) -- return format("(a%s ~= nil and escapedquotes(tostring(a%s)) or '')",n,n) +end or function() + n = n + 1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end + local format_Q = function() -- fast escaping n = n + 1 -- return format("format('%%q',tostring(a%s))",n) diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua index 410292ca8..4dafb2acd 100644 --- a/tex/context/base/mkiv/util-tab.lua +++ b/tex/context/base/mkiv/util-tab.lua @@ -314,102 +314,177 @@ end -- best keep [%q] keys (as we have some in older applications i.e. saving user data (otherwise -- we also need to check for reserved words) -local f_hashed_string = formatters["[%Q]=%Q,"] -local f_hashed_number = formatters["[%Q]=%s,"] -local f_hashed_boolean = formatters["[%Q]=%l,"] -local f_hashed_table = formatters["[%Q]="] - -local f_indexed_string = formatters["[%s]=%Q,"] -local f_indexed_number = formatters["[%s]=%s,"] -local f_indexed_boolean = formatters["[%s]=%l,"] -local f_indexed_table = formatters["[%s]="] - -local f_ordered_string = formatters["%Q,"] -local f_ordered_number = formatters["%s,"] -local f_ordered_boolean = formatters["%l,"] - -function table.fastserialize(t,prefix) -- todo, move local function out - - -- prefix should contain the = - -- not sorted - -- only number and string indices (currently) - - local r = { type(prefix) == "string" and prefix or "return" } - local m = 1 - local function fastserialize(t,outer) -- no mixes - local n = #t - m = m + 1 - r[m] = "{" - if n > 0 then - local v = t[0] - if v then - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_indexed_string(0,v) - elseif tv == "number" then - m = m + 1 r[m] = f_indexed_number(0,v) - elseif tv == "table" then - m = m + 1 r[m] = f_indexed_table(0) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_indexed_boolean(0,v) +if JITSUPPORTED then + + local f_hashed_string = formatters["[%Q]=%Q,"] + local f_hashed_number = formatters["[%Q]=%s,"] + local f_hashed_boolean = formatters["[%Q]=%l,"] + local f_hashed_table = formatters["[%Q]="] + + local f_indexed_string = formatters["[%s]=%Q,"] + local f_indexed_number = formatters["[%s]=%s,"] + local f_indexed_boolean = formatters["[%s]=%l,"] + local f_indexed_table = formatters["[%s]="] + + local f_ordered_string = formatters["%Q,"] + local f_ordered_number = formatters["%s,"] + local f_ordered_boolean = formatters["%l,"] + + function table.fastserialize(t,prefix) -- todo, move local function out + + -- prefix should contain the = + -- not sorted + -- only number and string indices (currently) + + local r = { type(prefix) == "string" and prefix or "return" } + local m = 1 + local function fastserialize(t,outer) -- no mixes + local n = #t + m = m + 1 + r[m] = "{" + if n > 0 then + local v = t[0] + if v then + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(0,v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(0,v) + elseif tv == "table" then + m = m + 1 r[m] = f_indexed_table(0) + fastserialize(v) + m = m + 1 r[m] = f_indexed_table(0) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v = t[i] - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_ordered_string(v) - elseif tv == "number" then - m = m + 1 r[m] = f_ordered_number(v) - elseif tv == "table" then - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_ordered_boolean(v) + for i=1,n do + local v = t[i] + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_ordered_string(v) + elseif tv == "number" then + m = m + 1 r[m] = f_ordered_number(v) + elseif tv == "table" then + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_ordered_boolean(v) + end end end - end - -- hm, can't we avoid this ... lua should have a way to check if there - -- is a hash part - for k, v in next, t do - local tk = type(k) - if tk == "number" then - if k > n or k < 0 then + -- hm, can't we avoid this ... lua should have a way to check if there + -- is a hash part + for k, v in next, t do + local tk = type(k) + if tk == "number" then + if k > n or k < 0 then + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(k,v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(k,v) + elseif tv == "table" then + m = m + 1 r[m] = f_indexed_table(k) + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(k,v) + end + end + else local tv = type(v) if tv == "string" then - m = m + 1 r[m] = f_indexed_string(k,v) + m = m + 1 r[m] = f_hashed_string(k,v) elseif tv == "number" then - m = m + 1 r[m] = f_indexed_number(k,v) + m = m + 1 r[m] = f_hashed_number(k,v) elseif tv == "table" then - m = m + 1 r[m] = f_indexed_table(k) + m = m + 1 r[m] = f_hashed_table(k) fastserialize(v) elseif tv == "boolean" then - m = m + 1 r[m] = f_indexed_boolean(k,v) + m = m + 1 r[m] = f_hashed_boolean(k,v) end end + end + m = m + 1 + if outer then + r[m] = "}" else - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_hashed_string(k,v) - elseif tv == "number" then - m = m + 1 r[m] = f_hashed_number(k,v) - elseif tv == "table" then - m = m + 1 r[m] = f_hashed_table(k) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_hashed_boolean(k,v) - end + r[m] = "}," end + return r end - m = m + 1 - if outer then - r[m] = "}" - else - r[m] = "}," + return concat(fastserialize(t,true)) + end + +else + + local f_v = formatters["[%q]=%q,"] + local f_t = formatters["[%q]="] + local f_q = formatters["%q,"] + + function table.fastserialize(t,prefix) -- todo, move local function out + local r = { type(prefix) == "string" and prefix or "return" } + local m = 1 + local function fastserialize(t,outer) -- no mixes + local n = #t + m = m + 1 + r[m] = "{" + if n > 0 then + local v = t[0] + if v then + m = m + 1 + r[m] = "[0]='" + if type(v) == "table" then + fastserialize(v) + else + r[m] = format("%q,",v) + end + end + for i=1,n do + local v = t[i] + m = m + 1 + if type(v) == "table" then + r[m] = format("[%i]=",i) + fastserialize(v) + else + r[m] = format("[%i]=%q,",i,v) + end + end + end + -- hm, can't we avoid this ... lua should have a way to check if there + -- is a hash part + for k, v in next, t do + local tk = type(k) + if tk == "number" then + if k > n or k < 0 then + m = m + 1 + if type(v) == "table" then + r[m] = format("[%i]=",k) + fastserialize(v) + else + r[m] = format("[%i]=%q,",k,v) + end + end + else + m = m + 1 + if type(v) == "table" then + r[m] = format("[%q]=",k) + fastserialize(v) + else + r[m] = format("[%q]=%q,",k,v) + end + end + end + m = m + 1 + if outer then + r[m] = "}" + else + r[m] = "}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) + end function table.deserialize(str) @@ -533,34 +608,34 @@ end -- husayni.tma : 0.28 -> 0.19 local f_start_key_idx = formatters["%w{"] -local f_start_key_num = formatters["%w[%s]={"] +local f_start_key_num = JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str = formatters["%w[%q]={"] local f_start_key_boo = formatters["%w[%l]={"] local f_start_key_nop = formatters["%w{"] local f_stop = formatters["%w},"] -local f_key_num_value_num = formatters["%w[%s]=%s,"] -local f_key_str_value_num = formatters["%w[%Q]=%s,"] -local f_key_boo_value_num = formatters["%w[%l]=%s,"] +local f_key_num_value_num = JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num = JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num = JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] -local f_key_num_value_str = formatters["%w[%s]=%Q,"] +local f_key_num_value_str = JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str = formatters["%w[%Q]=%Q,"] local f_key_boo_value_str = formatters["%w[%l]=%Q,"] -local f_key_num_value_boo = formatters["%w[%s]=%l,"] +local f_key_num_value_boo = JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo = formatters["%w[%Q]=%l,"] local f_key_boo_value_boo = formatters["%w[%l]=%l,"] -local f_key_num_value_not = formatters["%w[%s]={},"] +local f_key_num_value_not = JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not = formatters["%w[%Q]={},"] local f_key_boo_value_not = formatters["%w[%l]={},"] -local f_key_num_value_seq = formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq = JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq = formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"] -local f_val_num = formatters["%w%s,"] +local f_val_num = JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str = formatters["%w%Q,"] local f_val_boo = formatters["%w%l,"] local f_val_not = formatters["%w{},"] @@ -573,8 +648,6 @@ local f_table_direct = formatters["{"] local f_table_entry = formatters["[%Q]={"] local f_table_finish = formatters["}"] ------ f_string = formatters["%q"] - local spaces = utilities.strings.newrepeater(" ") local original_serialize = table.serialize -- the extensive one, the one we started with diff --git a/tex/context/modules/common/s-abbreviations-logos.tex b/tex/context/modules/common/s-abbreviations-logos.tex index 9f1d5599e..11c5b9725 100644 --- a/tex/context/modules/common/s-abbreviations-logos.tex +++ b/tex/context/modules/common/s-abbreviations-logos.tex @@ -97,6 +97,7 @@ \logo [DVIWINDO] {dviwindo} \logo [EBCDIC] {ebcdic} \logo [EC] {ec} +\logo [ECMASCRIPT] {ecmascript} \logo [EIFFEL] {Eiffel} \logo [EMACS] {emacs} \logo [EMTEX] {em\TeXsuffix} diff --git a/tex/context/modules/mkiv/m-zint.mkiv b/tex/context/modules/mkiv/m-zint.mkiv deleted file mode 100644 index 4957c8461..000000000 --- a/tex/context/modules/mkiv/m-zint.mkiv +++ /dev/null @@ -1,112 +0,0 @@ -%D \module -%D [ file=m-zint, -%D version=2010.12.07, -%D title=\CONTEXT\ Extra Modules, -%D subtitle=Zint Barcode Generator, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D Using \type {zint} seems to be the easiest way to generate -%D (PDF417) barcodes so therefore we now have this module. There -%D are proper (also windows) binaries at: -%D -%D \starttyping -%D http://www.zint.org.uk -%D \stoptyping -%D -%D There is a bit more code than needed as we want to be able to -%D feed names. - -\startluacode - -moduledata.zint = { } - -local format, lower, gsub = string.format, string.lower, string.gsub -local patterns = lpeg.patterns - -local zint = "zint" -- '"c:/program files/zint/zint.exe"' -local defaultcode = "PDF417" - -local whitespace = patterns.whitespace -local spaces = whitespace^0 -local key = (spaces / "") * patterns.digit^0 * (patterns.colon * spaces / "") -local value = (whitespace / "" + (1 - key))^1 -local pattern = lpeg.Cf(lpeg.Ct("") * (lpeg.Cg((lpeg.Cs(key) / tonumber) * (lpeg.Cs(value) / lower)) + patterns.anything)^0,rawset) - -local reverse - -local function cleancode(code) - if not code or code == "" then - code = defaultcode - end - return lower(gsub(code," ","")) -end - -local function numberofcode(code) - if not reverse then - local types = os.resultof(format("%s --types",zint)) or "" - local formats = lpeg.match(pattern,types) - if not formats or not next(formats) then - return code - end - reverse = table.swapped(formats) or { } - end - code = cleancode(code) - return reverse[code] or code -end - -function moduledata.zint.generate(code,data,suffix,options) - if not data or data == "" then - data = "unset" - end - local code = cleancode(code) - local base = format("zint-%s-%s",code,md5.hex(data)) - local name = file.addsuffix(base,suffix or "eps") - if not lfs.isfile(name) then - local temp = file.addsuffix(base,"tmp") - local code = numberofcode(code) - logs.simple("using 'zint' to generate '%s'",base) - io.savedata(temp,data) - os.execute(format('%s --barcode=%s --output="%s" --input="%s" %s',zint,code,name,temp,options or "")) - os.remove(temp) - end - return name -end - -\stopluacode - -\unprotect - -\unexpanded\def\barcode[#1]% [alternative=,text=] - {\bgroup - \getdummyparameters - [\c!alternative=,\c!text=,#1]% - \externalfigure - [\cldcontext{moduledata.zint.generate("\dummyparameter\c!alternative",\!!bs\dummyparameter\c!text\!!es)}]% - [#1,\c!alternative=,\c!text=]% - \egroup} - -\protect - -\continueifinputfile{m-zint.mkiv} - -\starttext - - \externalfigure[\cldcontext{moduledata.zint.generate("PDF417",[[Hans Hagen]])}] - \blank - \externalfigure[\cldcontext{moduledata.zint.generate("PDF417","Ton Otten")}] - \blank - \externalfigure[\cldcontext{moduledata.zint.generate("ISBN","9789490688011")}] - \blank - \barcode[text=Does It Work?,width=\textwidth] - \blank - \barcode[alternative=isbn,text=9789490688011,width=3cm] - -\stoptext - - diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index ce2794cf3..cc61d0a18 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 01/26/20 18:34:44 +-- merge date : 2020-02-11 16:36 do -- begin closure to overcome local limits and interference @@ -1383,13 +1383,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -1408,6 +1408,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -1428,6 +1430,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -1499,6 +1503,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -1508,7 +1514,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -1536,12 +1542,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -1549,12 +1559,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -1563,6 +1577,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -1579,6 +1595,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -1591,11 +1609,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -1617,6 +1637,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -1636,6 +1658,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -1653,6 +1677,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -1676,6 +1702,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3493,9 +3520,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -9634,6 +9664,7 @@ hashmethods.normal=function(list) m=m+1 t[m]=k..'='..tostring(v) end + sort(t) s[n]=k..'={'..concat(t,",").."}" else s[n]=k..'='..tostring(v) @@ -20032,6 +20063,7 @@ function readers.sbix(f,fontdata,specification) end end) local glyphs={} + local delayed=CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 or fonts.handlers.typethree for i=1,nofstrikes do local strike=strikes[i] local strikeppem=strike.ppem @@ -20048,13 +20080,25 @@ function readers.sbix(f,fontdata,specification) local datasize=nextoffset-glyphoffset if datasize>0 then setposition(f,strikeoffset+glyphoffset) + local x=readshort(f) + local y=readshort(f) + local tag=readtag(f) + local size=datasize-8 + local data=nil + local offset=nil + if delayed then + offset=getposition(f) + data=nil + else + data=readstring(f,size) + size=nil + end shapes[i]={ - x=readshort(f), - y=readshort(f), - tag=readtag(f), - data=readstring(f,datasize-8), - ppem=strikeppem, - ppi=strikeppi, + x=x, + y=y, + o=offset, + s=size, + data=data, } done=done+1 if done==nofglyphs then @@ -20233,29 +20277,46 @@ do end local default={ width=0,height=0 } local glyphs=fontdata.glyphs + local delayed=CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 or fonts.handlers.typethree for index,subtable in sortedhash(shapes) do if type(subtable)=="table" then local data=nil + local size=nil local metrics=default local format=subtable.format local offset=subtable.offsets[index] setposition(f,offset) if format==17 then metrics=getsmallmetrics(f) - data=readstring(f,readulong(f)) + size=true elseif format==18 then metrics=getbigmetrics(f) - data=readstring(f,readulong(f)) + size=true elseif format==19 then metrics=subtable.metrics - data=readstring(f,readulong(f)) + size=true + else + end + if size then + size=readulong(f) + if delayed then + offset=getposition(f) + data=nil + else + offset=nil + data=readstring(f,size) + size=nil + end else + offset=nil end local x=metrics.width local y=metrics.height shapes[index]={ x=x, y=y, + o=offset, + s=size, data=data, } local glyph=glyphs[index] @@ -23251,7 +23312,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.110 +otf.version=3.111 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) otf.pngcache=containers.define("fonts","png",otf.version,true) diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index 85fe1ae97..9f45408b1 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -257,7 +257,9 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('font-vfc.lua') - -- This is the bulk of opentype code. + -- This is the bulk of opentype code. The color and variable font support (as for + -- emoji) can (and might) actually go away here because it has never been used + -- outside context so in retrospect there was no need for it being generic. loadmodule('font-otr.lua') loadmodule('font-oti.lua') diff --git a/web2c/contextcnf.lua b/web2c/contextcnf.lua index 842401af7..ba6597bf3 100644 --- a/web2c/contextcnf.lua +++ b/web2c/contextcnf.lua @@ -103,7 +103,7 @@ return { PYTHONINPUTS = ".;$TEXMF/scripts/context/python", RUBYINPUTS = ".;$TEXMF/scripts/context/ruby", LUAINPUTS = ".;$TEXINPUTS;$TEXMF/scripts/context/lua//;$TEXMF", - CLUAINPUTS = ".;$SELFAUTOLOC/lib/{context,$engine,luatex}/lua//", + CLUAINPUTS = ".;$SELFAUTOLOC/lib/$engine//", -- texmf-local/tex/generic/example/foo : -- |