From cc6d486ffa3fad4ffb698ad5ccbd5c5f4ebc6a00 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Fri, 5 May 2023 19:33:15 +0200 Subject: 2023-05-05 18:39:00 --- .../general/manuals/lowlevel-alignments.pdf | Bin 74661 -> 81652 bytes .../documents/general/manuals/lowlevel-boxes.pdf | Bin 87679 -> 87671 bytes .../documents/general/manuals/lowlevel-buffers.pdf | Bin 0 -> 58361 bytes .../general/manuals/lowlevel-characters.pdf | Bin 48469 -> 48441 bytes .../general/manuals/lowlevel-conditionals.pdf | Bin 96046 -> 96425 bytes .../general/manuals/lowlevel-expansion.pdf | Bin 86301 -> 86574 bytes .../general/manuals/lowlevel-grouping.pdf | Bin 28200 -> 28352 bytes .../documents/general/manuals/lowlevel-inserts.pdf | Bin 38122 -> 38859 bytes .../general/manuals/lowlevel-localboxes.pdf | Bin 0 -> 61705 bytes .../documents/general/manuals/lowlevel-loops.pdf | Bin 44159 -> 43942 bytes .../documents/general/manuals/lowlevel-macros.pdf | Bin 88216 -> 88829 bytes .../documents/general/manuals/lowlevel-marks.pdf | Bin 62989 -> 63346 bytes .../general/manuals/lowlevel-paragraphs.pdf | Bin 296883 -> 296768 bytes .../general/manuals/lowlevel-registers.pdf | Bin 43739 -> 46958 bytes .../documents/general/manuals/lowlevel-scope.pdf | Bin 44386 -> 44359 bytes .../general/manuals/lowlevel-security.pdf | Bin 40571 -> 40613 bytes .../documents/general/manuals/lowlevel-tokens.pdf | Bin 0 -> 68803 bytes doc/context/documents/general/manuals/lowlevel.pdf | Bin 657745 -> 837278 bytes .../sources/general/manuals/details/detcow.mp | 2 - .../general/manuals/lowlevel/lowlevel-tokens.tex | 540 +++++++++++++++++ .../sources/general/manuals/lowlevel/lowlevel.tex | 1 + .../general/manuals/luatex/luatex-fonts.tex | 5 +- .../general/manuals/luatex/luatex-languages.tex | 2 +- .../sources/general/manuals/luatex/luatex-lua.tex | 154 +++-- .../manuals/luatex/luatex-modifications.tex | 2 +- .../general/manuals/luatex/luatex-nodes.tex | 12 +- .../sources/general/manuals/luatex/luatex.tex | 2 +- .../sources/general/manuals/metafun/gracht.mp | 2 - .../sources/general/manuals/metafun/mycow.mp | 2 - scripts/context/lua/mtx-ctan.lua | 83 ++- scripts/context/lua/mtx-install-tikz.lua | 162 +++++ scripts/context/lua/mtx-install.lua | 6 +- scripts/context/lua/mtx-update.lua | 6 +- scripts/context/lua/mtxrun.lua | 20 +- scripts/context/stubs/mswin/mtxrun.lua | 20 +- scripts/context/stubs/unix/mtxrun | 20 +- scripts/context/stubs/win64/mtxrun.lua | 20 +- source/luametatex/build.sh | 6 +- source/luametatex/source/luacore/readme.txt | 2 +- source/luametatex/source/luaoptional/lmtoptional.c | 2 +- source/luametatex/source/tex/texcommands.c | 12 +- source/luametatex/source/tex/texscanning.c | 18 +- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/lang-def.mkiv | 5 +- tex/context/base/mkiv/lang-txt.lua | 363 +++++++----- tex/context/base/mkiv/phys-dim.lua | 8 +- tex/context/base/mkiv/publ-imp-apa.lua | 35 +- tex/context/base/mkiv/publ-imp-apa.mkvi | 65 +- tex/context/base/mkiv/status-files.pdf | Bin 24650 -> 24657 bytes tex/context/base/mkiv/status-lua.pdf | Bin 271361 -> 271357 bytes tex/context/base/mkiv/util-sac.lua | 12 +- tex/context/base/mkiv/util-sbx.lua | 2 +- tex/context/base/mkxl/cont-new.mkxl | 2 +- tex/context/base/mkxl/context.mkxl | 2 +- tex/context/base/mkxl/data-sch.lmt | 312 ++++++++++ tex/context/base/mkxl/data-vir.lmt | 29 +- tex/context/base/mkxl/lang-def.mkxl | 2 +- tex/context/base/mkxl/lpdf-img.lmt | 12 + tex/context/base/mkxl/luat-lib.mkxl | 4 +- tex/context/base/mkxl/math-ini.mkxl | 4 +- tex/context/base/mkxl/phys-dim.lmt | 4 +- tex/context/base/mkxl/util-sbx.lmt | 658 +++++++++++++++++++++ tex/context/modules/mkxl/m-tikz.mkxl | 42 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 2 +- 67 files changed, 2314 insertions(+), 358 deletions(-) create mode 100644 doc/context/documents/general/manuals/lowlevel-buffers.pdf create mode 100644 doc/context/documents/general/manuals/lowlevel-localboxes.pdf create mode 100644 doc/context/documents/general/manuals/lowlevel-tokens.pdf create mode 100644 doc/context/sources/general/manuals/lowlevel/lowlevel-tokens.tex create mode 100644 scripts/context/lua/mtx-install-tikz.lua create mode 100644 tex/context/base/mkxl/data-sch.lmt create mode 100644 tex/context/base/mkxl/util-sbx.lmt diff --git a/doc/context/documents/general/manuals/lowlevel-alignments.pdf b/doc/context/documents/general/manuals/lowlevel-alignments.pdf index 86b9a60b1..1dcc320c7 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-alignments.pdf and b/doc/context/documents/general/manuals/lowlevel-alignments.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-boxes.pdf b/doc/context/documents/general/manuals/lowlevel-boxes.pdf index 028519623..76c08681e 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-boxes.pdf and b/doc/context/documents/general/manuals/lowlevel-boxes.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-buffers.pdf b/doc/context/documents/general/manuals/lowlevel-buffers.pdf new file mode 100644 index 000000000..dc8ca068f Binary files /dev/null and b/doc/context/documents/general/manuals/lowlevel-buffers.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-characters.pdf b/doc/context/documents/general/manuals/lowlevel-characters.pdf index 13867666b..4c7944820 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-characters.pdf and b/doc/context/documents/general/manuals/lowlevel-characters.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-conditionals.pdf b/doc/context/documents/general/manuals/lowlevel-conditionals.pdf index 251ccc758..4522e6717 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-conditionals.pdf and b/doc/context/documents/general/manuals/lowlevel-conditionals.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-expansion.pdf b/doc/context/documents/general/manuals/lowlevel-expansion.pdf index d9f2528bc..e390e4122 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-expansion.pdf and b/doc/context/documents/general/manuals/lowlevel-expansion.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-grouping.pdf b/doc/context/documents/general/manuals/lowlevel-grouping.pdf index 316edda67..1289c7502 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-grouping.pdf and b/doc/context/documents/general/manuals/lowlevel-grouping.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-inserts.pdf b/doc/context/documents/general/manuals/lowlevel-inserts.pdf index d305899c1..d5b875944 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-inserts.pdf and b/doc/context/documents/general/manuals/lowlevel-inserts.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-localboxes.pdf b/doc/context/documents/general/manuals/lowlevel-localboxes.pdf new file mode 100644 index 000000000..c92ed00cd Binary files /dev/null and b/doc/context/documents/general/manuals/lowlevel-localboxes.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-loops.pdf b/doc/context/documents/general/manuals/lowlevel-loops.pdf index 83620457c..48a619793 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-loops.pdf and b/doc/context/documents/general/manuals/lowlevel-loops.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-macros.pdf b/doc/context/documents/general/manuals/lowlevel-macros.pdf index 5b3bcae14..a33a3b659 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-macros.pdf and b/doc/context/documents/general/manuals/lowlevel-macros.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-marks.pdf b/doc/context/documents/general/manuals/lowlevel-marks.pdf index a00a7f2ae..4e59f11b8 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-marks.pdf and b/doc/context/documents/general/manuals/lowlevel-marks.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-paragraphs.pdf b/doc/context/documents/general/manuals/lowlevel-paragraphs.pdf index 9115642ad..11c70780f 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-paragraphs.pdf and b/doc/context/documents/general/manuals/lowlevel-paragraphs.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-registers.pdf b/doc/context/documents/general/manuals/lowlevel-registers.pdf index 5c5400ec6..9b0b5a7cb 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-registers.pdf and b/doc/context/documents/general/manuals/lowlevel-registers.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-scope.pdf b/doc/context/documents/general/manuals/lowlevel-scope.pdf index d5b628396..66c00d983 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-scope.pdf and b/doc/context/documents/general/manuals/lowlevel-scope.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-security.pdf b/doc/context/documents/general/manuals/lowlevel-security.pdf index d4c7d871c..26a195e9f 100644 Binary files a/doc/context/documents/general/manuals/lowlevel-security.pdf and b/doc/context/documents/general/manuals/lowlevel-security.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel-tokens.pdf b/doc/context/documents/general/manuals/lowlevel-tokens.pdf new file mode 100644 index 000000000..03eaa7f81 Binary files /dev/null and b/doc/context/documents/general/manuals/lowlevel-tokens.pdf differ diff --git a/doc/context/documents/general/manuals/lowlevel.pdf b/doc/context/documents/general/manuals/lowlevel.pdf index 8290f2118..16c3f91c4 100644 Binary files a/doc/context/documents/general/manuals/lowlevel.pdf and b/doc/context/documents/general/manuals/lowlevel.pdf differ diff --git a/doc/context/sources/general/manuals/details/detcow.mp b/doc/context/sources/general/manuals/details/detcow.mp index 18fc570e5..4713e6036 100644 --- a/doc/context/sources/general/manuals/details/detcow.mp +++ b/doc/context/sources/general/manuals/details/detcow.mp @@ -1,6 +1,4 @@ % Converted from PostScript(TM) to MetaPost by pstoedit -% -% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa % MetaPost backend contributed by Scott Pakin % pstoedit is Copyright (C) 1993 - 1999 Wolfgang Glunz diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel-tokens.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel-tokens.tex new file mode 100644 index 000000000..483b4a8dc --- /dev/null +++ b/doc/context/sources/general/manuals/lowlevel/lowlevel-tokens.tex @@ -0,0 +1,540 @@ +% language=us runpath=texruns:manuals/lowlevel + +\environment lowlevel-style + +\usemodule[system-tokens] + +\startdocument + [title=tokens, + color=middleblue] + +\startsectionlevel[title=Introduction] + +Most users don't need to know anything about tokens but it happens that when \TEX +ies meet in person (users group meetings), or online (support platforms) there +always seem to pop up folks who love token speak. When you try to explain +something to a user it makes sense to talk in terms of characters but then those +token speakers can jump in and start correcting you. In the past I have been +puzzled by this because, when one can write a decent macro that does the job +well, it really doesn't matter if one knows about tokens. Of course one should +never make the assumption that token speakers really know \TEX\ that well or can +come up with better solutions than users but that is another matter. \footnote +{Talking about fashion: it would be more impressive to talk about \TEX\ and +friends as a software stack than calling it a distribution. Today, it's all about +marketing.} + +That said, because in documents about \TEX\ the word \quote {token} does pop up I +will try to give a little insight here. But for using \TEX\ it's mostly +irrelevant. The descriptions below for sure won't match the proper token speak +criteria which is why at a presentation for the 2020 user meeting I used the +title \quotation {Tokens as I see them.} + +\stopsectionlevel + +\startsectionlevel[title=What are tokens] + +Both the words \quote {node} and \quote {token} are quite common in programming +and also rather old which is proven by the fact that they also are used in the +\TEX\ source. A node is a storage container that is part of a linked list. When +you input the characters \type {tex} the three characters become part of the +current linked list. They become \quote {character} nodes (or in \LUATEX\ speak +\quote {glyph} nodes) with properties like the font and the character referred +to. But before that happens, the three characters in the input \type {t}, \type +{e} and \type {x}, are interpreted as in this case being just that: characters. +When you enter \type {\TeX} the input processors first sees a backslash and +because that has a special meaning in \TEX\ it will read following characters and +when done does a lookup in it's internal hash table to see what it actually is: a +macro that assembled the word \TEX\ in uppercase with special kerning and a +shifted (therefore boxed) \quote {E}. When you enter \type {$} \TEX\ will look +ahead for a second one in order to determine display math, push back the found +token when there is no match and then enter inline math mode. + +A token is internally just a 32 bit number that encodes what \TEX\ has seen. It +is the assembled token that travels through the system, get stored, interpreted +and often discarded afterwards. So, the character \quote {e} in our example gets +tagged as such and encoded in this number in a way that the intention can be +derived later on. + +Now, the way \TEX\ looks at these tokens can differ. In some cases it will just +look at this (32 bit) number, for instance when checking for a specific token, +which is fast, but sometimes it needs to know some detail. The mentioned integer +actually encodes a command (opcode) and a so called char code (operand). The +second name is somewhat confusing because in many cases that code is not +representing a character but that is not that relevant here. When you look at the +source code of a \TEX\ engine it is enough to know that a char can also be a sub +command. + +\startlinecorrection[blank] + \setupTABLE[each][align=middle] + \setupTABLE[c][1][width=44mm] + \setupTABLE[c][2][width=4em] + \setupTABLE[c][3][width=11mm] + \setupTABLE[c][4][width=33mm] + \bTABLE + \bTR + \bTD token \eTD + \bTD[frame=off] = \eTD + \bTD cmd \eTD + \bTD chr \eTD + \eTR + \eTABLE +\stoplinecorrection + +Back to the three characters: these become tokens where the command code +indicates that it is a letter and the char code stores what letter we have at +hand and in the case of \LUATEX\ and \LUAMETATEX\ these are \UNICODE\ values. +Contrary to the traditional 8 bit \TEX\ engine, in the \UNICODE\ engines an \UTF\ +sequence is read, but these multiple bytes still become one number that will be +encoded in the token number. In order to determine that something is a letter the +engine has to be told (which is what a macro package does when it sets up the +engine). For instance, digits are so called other characters and the backslash is +called escape. Every \TEX\ user knows that curly braces are special and so are +dollar symbols and hashes. If this rings a bell, and you relate this to catcodes, +you can indeed assume that the command codes of these tokens have the same +numbers as the catcodes. Given that \UNICODE\ has plenty of characters slots you +can imagine that combining 16 catcode commands with all the possible \UNICODE\ +values makes a large repertoire of tokens. + +There are more commands than the 16 basic characters related ones, in +\LUAMETATEX\ we have just over 150 command codes (\LUATEX\ has a few more but +they are also organized differently). Each of these codes can have a sub +command, For instance the primitives \type {\vbox} and \type {\hbox} are both a +\type {make_box_cmd} (we use the symbolic name here) and in \LUAMETATEX\ the +first one has sub command code 9 (\type {vbox_code}) and the second one has code +10 (\type {hbox_code}). There are twelve primitives that are in the same +category. The many primitives that make up the core of the engine are grouped in +a way that permits processing similar ones with one function and also makes it +possible to distinguish between the way commands are handled, for instance with +respect to expansion. + +Now, before we move on it is important to know that al these codes are in fact +abstract numbers. Although it is quite likely that engines that are derived from +each other have similar numbers (just more) this is not the case for \LUAMETATEX. +Because the internals have been opened up (even more than in \LUATEX) the command +and char codes have been reorganized in a such a way that exposure is consistent. +We could not use some of the reuse and remap tricks that the other engines use +because it would simply be too confusing (and demand real in depth knowledge of +the internals). This is also the reason why development took some time. You +probably won't notice it from the current source but it was a very stepwise +process. We not only had to make sure that all kept working (\CONTEXT\ \LMTX\ and +\LUAMETATEX\ were pretty useable during the process), but also had to +(re)consider intermediate choices. + +So, input is converted into tokens, in most cases one|-|by|-|one. When a token is +assembled, it either gets stored (deliberately or as part of some look ahead +scanning), or it immediately gets (what is called:) expanded. Depending on what +the command is, some action is triggered. For instance, a character gets appended +to the node list immediately. An \type {\hbox} command will start assembling a +box which its own node list that then gets some treatment: if this primitive was a +follow up on \type {\setbox} it will get stored, otherwise it might end up in the +current node list as so called hlist node. Commands that relate to registers have +\type {0xFFFF} char codes because that is how many registers we have per category. + +When a token gets stored for later processing it becomes part of a larger data +structure, a so called memory word. These memory words are taken from a large +pool of words and they store a token and additional properties. The info field +contains the token value, the mentioned command and char. When there is no linked +list, the link can actually be used to store a value, something that in +\LUAMETATEX\ we actually do. + +\startlinecorrection[blank] + \setupTABLE[each][align=middle] + \setupTABLE[c][1][width=8mm] + \setupTABLE[c][2][width=64mm] + \setupTABLE[c][3][width=64mm] + \bTABLE + \bTR \bTD 1 \eTD \bTD info \eTD \bTD link \eTD \eTR + \bTR \bTD 2 \eTD \bTD info \eTD \bTD link \eTD \eTR + \bTR \bTD 3 \eTD \bTD info \eTD \bTD link \eTD \eTR + \bTR \bTD n \eTD \bTD info \eTD \bTD link \eTD \eTR + \eTABLE +\stoplinecorrection + +When for instance we say \typ {\toks 0 {tex}} the scanner sees an escape, +followed by 4 letters (\type {toks}) and the escape triggers a lookup of the +primitive (or macro or \unknown) with that name, in this case a primitive +assignment command. The found primitive (its property gets stored in the token) +triggers scanning for a number and when that is successful scanning of a brace +delimited token list starts. The three characters become three letter tokens and +these are a linked list of the mentioned memory words. This list then gets stored +in token register zero. The input sequence \typ {\the \toks 0} will push back a +copy of this list into the input. + +In addition to the token memory pool, there is also a table of equivalents. That +one is part of a larger table of memory words where \TEX\ stores all it needs to +store. The 16 groups of character commands are virtual, storing these makes no +sense, so the first real entries are all these registers (count, dimension, skip, +box, etc). The rest is taken up by possible hash entries. + +\startlinecorrection[blank] + \bTABLE + \bTR \bTD[ny=4] main hash \eTD \bTD null control sequence \eTD \eTR + \bTR \bTD 128K hash entries \eTD \eTR + \bTR \bTD frozen control sequences \eTD \eTR + \bTR \bTD special sequences (undefined) \eTD \eTR + \bTR \bTD[ny=7] registers \eTD \bTD 17 internal & 64K user glues \eTD \eTR + \bTR \bTD 4 internal & 64K user mu glues \eTD \eTR + \bTR \bTD 12 internal & 64K user tokens \eTD \eTR + \bTR \bTD 2 internal & 64K user boxes \eTD \eTR + \bTR \bTD 116 internal & 64K user integers \eTD \eTR + \bTR \bTD 0 internal & 64K user attribute \eTD \eTR + \bTR \bTD 22 internal & 64K user dimensions \eTD \eTR + \bTR \bTD specifications \eTD \bTD 5 internal & 0 user \eTD \eTR + \bTR \bTD extra hash \eTD \bTD additional entries (grows dynamic) \eTD \eTR + \eTABLE +\stoplinecorrection + +So, a letter token \type {t} is just that, a token. A token referring to a register +is again just a number, but its char code points to a slot in the equivalents table. +A macro, which we haven't discussed yet, is actually just a token list. When a name +lookup happens the hash table is consulted and that one runs in parallel to part of the +table of equivalents. When there is a match, the corresponding entry in the equivalents +table points to a token list. + +\startlinecorrection[blank] + \setupTABLE[each][align=middle] + \setupTABLE[c][1][width=16mm] + \setupTABLE[c][2][width=64mm] + \setupTABLE[c][3][width=64mm] + \bTABLE + \bTR \bTD 1 \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \bTR \bTD 2 \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \bTR \bTD n \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \bTR \bTD n + 1 \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \bTR \bTD n + 2 \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \bTR \bTD n + m \eTD \bTD string index \eTD \bTD equivalents or (next > n) index \eTD \eTR + \eTABLE +\stoplinecorrection + +It sounds complex and it actually also is somewhat complex. It is not made easier +by the fact that we also track information related to grouping (saving and +restoring), need reference counts for copies of macros and token lists, sometimes +store information directly instead of via links to token lists, etc. And again +one cannot compare \LUAMETATEX\ with the other engines. Because we did away with +some of the limitations of the traditional engine we not only could save some +memory but in the end also simplify matters (we're 32/64 bit after all). On the one +hand some traditional speedups were removed but these have been compensated by +improvements elsewhere, so overall processing is more efficient. + +\startlinecorrection[blank] + \setupTABLE[each][align=middle] + \setupTABLE[c][1][width=8mm] + \setupTABLE[c][2][width=32mm] + \setupTABLE[c][3][width=16mm] + \setupTABLE[c][4][width=16mm] + \setupTABLE[c][5][width=64mm] + \bTABLE + \bTR \bTD 1 \eTD \bTD level \eTD \bTD type \eTD \bTD flag \eTD \bTD value \eTD \eTR + \bTR \bTD 2 \eTD \bTD level \eTD \bTD type \eTD \bTD flag \eTD \bTD value \eTD \eTR + \bTR \bTD 3 \eTD \bTD level \eTD \bTD type \eTD \bTD flag \eTD \bTD value \eTD \eTR + \bTR \bTD n \eTD \bTD level \eTD \bTD type \eTD \bTD flag \eTD \bTD value \eTD \eTR + \eTABLE +\stoplinecorrection + +So, here \LUAMETATEX\ differs from other engines because it combines two tables, +which is possible because we have at least 32 bits. There are at most \type +{0xFFFF} levels but we need at most \type {0xFF} types. in \LUAMETATEX\ macros +can have extra properties (flags) and these also need one byte. Contrary to the +other engines, \type {\protected} macros are native and have their own command +code, but \type {\tolerant} macros duplicate that (so we have four distinct macro +commands). All other properties, like the \type {\permanent} ones are stored in +the flags. + +Because a macro starts with a reference count we have some room in the info field +to store information about it having arguments or not. It is these details that +make \LUAMETATEX\ a bit more efficient in terms of memory usage and performance +than its ancestor \LUATEX. But as with the other changes, it was a very stepwise +process in order to keep the system compatible and working. + +\stopsectionlevel + +\startsectionlevel[title=Some implementation details] + +Sometimes there is a special head token at the start. This makes for easier +appending of extra tokens. In traditional \TEX\ node lists are forward linked, in +\LUATEX\ they are double linked \footnote {On the agenda of \LUAMETATEX\ is to +use this property in the underlying code, that doesn't yet profit from this and +therefore keep previous pointers in store.}. Token lists are always forward +linked. Shared token lists use the head node for a reference count. + +For various reasons original \TEX\ uses global variables temporary lists. This is +for instance needed when we expand (nested) and need to report issues. But in +\LUATEX\ we often just serialize lists and using local variables makes more +sense. One of the first things done in \LUAMETATEX\ was to group all global +variables in (still global) structures but well isolated. That also made it +possible to actually get rid of some globals. + +Because \TEX\ had to run on machines that we nowadays consider rather limited, it +had to be sparse and efficient. There are quite some optimizations to limit code +and memory consumption. The engine also does its own memory management. Freed +token memory words are collected in a cache and reused but they can get scattered +which is not that bad, apart from maybe cache hits. In \LUAMETATEX\ we stay as +close to original \TEX\ as possible but there have been some improvements. The +\LUA\ interfaces force us to occasionally divert from the original, and that in +fact might lead to some retrofit but the original documentation still mostly +applies. However, keep in mind that in \LUATEX\ we store much more in nodes (each +has a prev pointer and an attribute list pointer and for instance glyph nodes +have some 20 extra fields compared to traditional \TEX\ character nodes). + +\stopsectionlevel + +\startsectionlevel[title=Other data management] + +There is plenty going on in \TEX\ when it processes your input, just to mention a +few: + +\startitemize[packed] +\startitem Grouping is handled by a nesting stack. \stopitem +\startitem Nested conditionals (\type {\if...}) have their own stack. \stopitem +\startitem The values before assignments are saved on the save stack. \stopitem +\startitem Also other local changes (housekeeping) ends up in the save stack. \stopitem +\startitem Token lists and macro aliases have references pointers (reuse). \stopitem +\startitem Attributes, being linked node lists, have their own management. \stopitem +\stopitemize + +In all these subsystems tokens or references to tokens can play a role. Reading a +single character from the input can trigger a lot of action. A curly brace tagged +as begin group command will push the grouping level and from then on registers +and some other quantities that are changed will be stored on the save stack +so that after the group ends they can be restored. When primitives take keywords, +and no match happens, tokens are pushed back into the input which introduces a +new input level (also some stack). When numbers are read a token that represents +no digit is pushed back too and macro packages use numbers and dimensions a lot. +It is a surprise that \TEX\ is so fast. + +\stopsectionlevel + +\startsectionlevel[title=Macros] + +There is a distinction between primitives, the build in commands, and macros, the +commands defined by users. A primitive relates to a command code and char code +but macros are, unless they are made an alias to something else, like a \type +{\countdef} or \type {\let} does, basically pointers to a token list. There is +some additional data stored that makes it possible to parse and grab arguments. + +When we have a control sequence (macro) \type {\controlsequence} the name is +looked up in the hash table. When found its value will point to the table of +equivalents. As mentioned, that table keeps track of the cmd and points to a +token list (the meaning). We saw that this table also stores the current level +of grouping and flags. + +If we say, in the input, \typ {\hbox to 10pt {x\hss}}, the box is assembled as we +go and when it is appended to the current node list there are no tokens left. +When scanning this, the engine literally sees a backslash and the four letters +\type {hbox}. However when we have this: + +\starttyping[option=TEX] +\def\MyMacro{\hbox to 10pt {x\hss}} +\stoptyping + +the \type {\hbox} has become one memory word which has a token representing the +\type {\hbox} primitive plus a link to the next token. The space after a control +sequence is gobbled so the next two tokens, again stored in a linked memory word, +are letter tokens, followed by two other and two letter tokens for the +dimensions. Then we have a space, a brace, a letter, a primitive and a brace. The +about 20 characters in the input became a dozen memory words each two times four +bytes, so in terms of memory usage we end up with quite a bit more. However, when +\TEX\ runs over that list it only has to interpret the token values because the +scanning and conversion already happened. So, the space that a macro takes is +more than compensated by efficient reprocessing. + +\stopsectionlevel + +\startsectionlevel[title=Looking at tokens] + +When you say \type {\tracingall} you will see what the engine does: read input, +expand primitives and macros, typesetting etc.\ You might need to set \type +{\tracingonline} to get a bit more output on the console. One way to look at +macros is to use the \type {\meaning} command, so if we have: + +\startbuffer[definition] +\permanent\protected\def\MyMacro#1#2{Do #1 or #2!} +\stopbuffer + +\startbuffer[meaning] +\meaning \MyMacro +\meaningless\MyMacro +\meaningfull\MyMacro +\stopbuffer + +\typebuffer[definition][option=TEX] + +we can say this: + +\typebuffer[meaning][option=TEX] + +and get: + +{\getbuffer[definition]\startlines\tttf \getbuffer[meaning]\stoplines} + +You get less when you ask for the meaning of a primitive, just its name. The +\type {\meaningfull} primitive gives the most information. In \LUAMETATEX\ +protected macros are first class commands: they have their own command code. In +the other engines they are just regular macros with an initial token indicating +that they are protected. There are specific command codes for \type {\outer} and +\type {\long} macros but we dropped that in \LUAMETATEX . Instead we have \type +{\tolerant} macros but that's another story. The flags that were mentioned can +mark macros in a way that permits overload protection as well as some special +treatment in otherwise tricky cases (like alignments). The overload related flags +permits a rather granular way to prevent users from redefining macros and such. +They are set via prefixes, and add to that repertoire: we have 14 prefixes but +only some eight deal with flags (we can add more if really needed). The probably +most wel known prefix is \type {\global} and that one will not become a flag: it +has immediate effect. + +For the above definition, the \type {\showluatokens} command will show a meaning +on the console. + +\starttyping[option=TEX] +\showluatokens\MyMacro +\stoptyping + +% {\getbuffer[definition]\getbuffer} + +This gives the next list, where the first column is the address of the token, the +second one the command code, and the third one the char code. When there are +arguments involved, the list of what needs to get matched is shown. + +\starttyping +permanent protected control sequence: MyMacro +501263 19 49 match argument 1 +501087 19 50 match argument 2 +385528 20 0 end match +-------------- +501090 11 68 letter D (U+00044) + 30833 11 111 letter o (U+0006F) +500776 10 32 spacer +385540 21 1 parameter reference +112057 10 32 spacer +431886 11 111 letter o (U+0006F) + 30830 11 114 letter r (U+00072) + 30805 10 32 spacer +500787 21 2 parameter reference +213412 12 33 other char ! (U+00021) +\stoptyping + +In the next subsections I will give some examples. This time we use +helper defined in a module: + +\starttyping[option=TEX] +\usemodule[system-tokens] +\stoptyping + +\startsectionlevel[title=Example 1: in the input] + +\startbuffer +\luatokentable{1 \bf{2} 3\what {!}} +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 2: in the input] + +\startbuffer +\luatokentable{a \the\scratchcounter b \the\parindent \hbox to 10pt{x}} +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 3: user registers] + +\startbuffer +\scratchtoks{foo \framed{\red 123}456} + +\luatokentable\scratchtoks +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 4: internal variables] + +\startbuffer +\luatokentable\everypar +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 5: macro definitions] + +\startbuffer +\protected\def\whatever#1[#2](#3)\relax + {oeps #1 and #2 & #3 done ## error} + +\luatokentable\whatever +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 6: commands] + +\startbuffer +\luatokentable\startitemize +\luatokentable\stopitemize +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer} + +\stopsectionlevel + +\startsectionlevel[title=Example 7: commands] + +\startbuffer +\luatokentable\doifelse +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer } + +\stopsectionlevel + +\startsectionlevel[title=Example 8: nothing] + +\startbuffer +\luatokentable\relax +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer } + +\stopsectionlevel + +\startsectionlevel[title=Example 9: hashes] + +\startbuffer +\edef\foo#1#2{(#1)(\letterhash)(#2)} \luatokentable\foo +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer } + +\stopsectionlevel + +\startsectionlevel[title=Example 10: nesting] + +\startbuffer +\def\foo#1{\def\foo##1{(#1)(##1)}} \luatokentable\foo +\stopbuffer + +\typebuffer[option=TEX] \blank[line] {\switchtobodyfont[8pt] \getbuffer } + +\stopsectionlevel + +\startsectionlevel[title=Remark] + +In all these examples the numbers are to be seen as abstractions. Some command +codes and sub command codes might change as the engine evolves. This is why the +\LUAMETATEX\ engine has lots of \LUA\ functions that provide information about +what number represents what command. + +\stopsectionlevel + +\stopsectionlevel + +\stopdocument diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel.tex index 2d6898835..8f58e16c1 100644 --- a/doc/context/sources/general/manuals/lowlevel/lowlevel.tex +++ b/doc/context/sources/general/manuals/lowlevel/lowlevel.tex @@ -39,6 +39,7 @@ \startsectionlevel[title=Loops] \component [lowlevel-loops] \stopsectionlevel \startsectionlevel[title=Tokens] \component [lowlevel-tokens] \stopsectionlevel \startsectionlevel[title=Buffers] \component [lowlevel-buffers] \stopsectionlevel + % \startsectionlevel[title=Accuracy] \component [lowlevel-accuracy] \stopsectionlevel \stoptext diff --git a/doc/context/sources/general/manuals/luatex/luatex-fonts.tex b/doc/context/sources/general/manuals/luatex/luatex-fonts.tex index b0921c70c..cfbc9c32f 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-fonts.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-fonts.tex @@ -728,12 +728,13 @@ font.setfont( n, f) Note that at the moment, each access to the \type {font.fonts} or call to \type {font.getfont} creates a \LUA\ table for the whole font unless you cached it. +If you want a copy of the internal data you can use \type {font.getcopy}: \startfunctioncall -
f = font.getfont( n) +
f = font.getcopy( n) \stopfunctioncall -So, this one will return a table of the parameters as known to \TEX. These can be +This one will return a table of the parameters as known to \TEX. These can be different from the ones in the cached table: \startfunctioncall diff --git a/doc/context/sources/general/manuals/luatex/luatex-languages.tex b/doc/context/sources/general/manuals/luatex/luatex-languages.tex index b3f96d247..9b32fffd3 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-languages.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-languages.tex @@ -369,7 +369,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 diff --git a/doc/context/sources/general/manuals/luatex/luatex-lua.tex b/doc/context/sources/general/manuals/luatex/luatex-lua.tex index 976505189..3b2f9b1a7 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-lua.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-lua.tex @@ -68,40 +68,41 @@ similar fashion as the other \TEX\ engines. Some options are accepted but have n consequence. The following command|-|line options are understood: \starttabulate[|l|p|] -\DB commandline argument \BC explanation \NC \NR +\DB commandline argument \BC explanation \NC \NR \TB -\NC \type{--credits} \NC display credits and exit \NC \NR -\NC \type{--debug-format} \NC enable format debugging \NC \NR -\NC \type{--draftmode} \NC switch on draft mode i.e.\ generate no output in \PDF\ mode \NC \NR -\NC \type{--[no-]file-line-error} \NC disable/enable \type {file:line:error} style messages \NC \NR -\NC \type{--[no-]file-line-error-style} \NC aliases of \type {--[no-]file-line-error} \NC \NR -\NC \type{--fmt=FORMAT} \NC load the format file \type {FORMAT} \NC\NR -\NC \type{--halt-on-error} \NC stop processing at the first error\NC \NR -\NC \type{--help} \NC display help and exit \NC\NR -\NC \type{--ini} \NC be \type {iniluatex}, for dumping formats \NC\NR -\NC \type{--interaction=STRING} \NC set interaction mode: \type {batchmode}, \type {nonstopmode}, - \type {scrollmode} or \type {errorstopmode} \NC \NR -\NC \type{--jobname=STRING} \NC set the job name to \type {STRING} \NC \NR -\NC \type{--kpathsea-debug=NUMBER} \NC set path searching debugging flags according to the bits of - \type {NUMBER} \NC \NR -\NC \type{--lua=FILE} \NC load and execute a \LUA\ initialization script \NC\NR -\NC \type{--[no-]mktex=FMT} \NC disable/enable \type {mktexFMT} generation with \type {FMT} is - \type {tex} or \type {tfm} \NC \NR -\NC \type{--nosocket} \NC disable the \LUA\ socket library \NC\NR -\NC \type{--output-comment=STRING} \NC use \type {STRING} for \DVI\ file comment instead of date (no - effect for \PDF) \NC \NR -\NC \type{--output-directory=DIR} \NC use \type {DIR} as the directory to write files to \NC \NR -\NC \type{--output-format=FORMAT} \NC use \type {FORMAT} for job output; \type {FORMAT} is \type {dvi} - or \type {pdf} \NC \NR -\NC \type{--progname=STRING} \NC set the program name to \type {STRING} \NC \NR -\NC \type{--recorder} \NC enable filename recorder \NC \NR -\NC \type{--safer} \NC disable easily exploitable \LUA\ commands \NC\NR -\NC \type{--[no-]shell-escape} \NC disable/enable system calls \NC \NR -\NC \type{--shell-restricted} \NC restrict system calls to a list of commands given in \type - {texmf.cnf} \NC \NR -\NC \type{--synctex=NUMBER} \NC enable \type {synctex} \NC \NR -\NC \type{--utc} \NC use utc times when applicable \NC \NR -\NC \type{--version} \NC display version and exit \NC \NR +\NC \type{--credits} \NC display credits and exit \NC \NR +\NC \type{--debug-format} \NC enable format debugging \NC \NR +\NC \type{--draftmode} \NC switch on draft mode i.e.\ generate no output in \PDF\ mode \NC \NR +\NC \type{--[no-]file-line-error} \NC disable/enable \type {file:line:error} style messages \NC \NR +\NC \type{--[no-]file-line-error-style} \NC aliases of \type {--[no-]file-line-error} \NC \NR +\NC \type{--fmt=FORMAT} \NC load the format file \type {FORMAT} \NC\NR +\NC \type{--halt-on-error} \NC stop processing at the first error\NC \NR +\NC \type{--help} \NC display help and exit \NC\NR +\NC \type{--ini} \NC be \type {iniluatex}, for dumping formats \NC\NR +\NC \type{--interaction=STRING} \NC set interaction mode: \type {batchmode}, \type {nonstopmode}, + \type {scrollmode} or \type {errorstopmode} \NC \NR +\NC \type{--jobname=STRING} \NC set the job name to \type {STRING} \NC \NR +\NC \type{--kpathsea-debug=NUMBER} \NC set path searching debugging flags according to the bits of + \type {NUMBER} \NC \NR +\NC \type{--lua=FILE} \NC load and execute a \LUA\ initialization script \NC\NR +\NC \type{--[no-]mktex=FMT} \NC disable/enable \type {mktexFMT} generation with \type {FMT} is + \type {tex} or \type {tfm} \NC \NR +\NC \type{--nosocket} or \type{--no-socket} \NC disable the \LUA\ socket library \NC\NR +\NC \type{--socket} \NC enable the \LUA\ socket library \NC\NR +\NC \type{--output-comment=STRING} \NC use \type {STRING} for \DVI\ file comment instead of date (no + effect for \PDF) \NC \NR +\NC \type{--output-directory=DIR} \NC use \type {DIR} as the directory to write files to \NC \NR +\NC \type{--output-format=FORMAT} \NC use \type {FORMAT} for job output; \type {FORMAT} is \type {dvi} + or \type {pdf} \NC \NR +\NC \type{--progname=STRING} \NC set the program name to \type {STRING} \NC \NR +\NC \type{--recorder} \NC enable filename recorder \NC \NR +\NC \type{--safer} \NC disable easily exploitable \LUA\ commands \NC\NR +\NC \type{--[no-]shell-escape} \NC disable/enable system calls \NC \NR +\NC \type{--shell-restricted} \NC restrict system calls to a list of commands given in \type + {texmf.cnf} \NC \NR +\NC \type{--synctex=NUMBER} \NC enable \type {synctex} \NC \NR +\NC \type{--utc} \NC use utc times when applicable \NC \NR +\NC \type{--version} \NC display version and exit \NC \NR \LL \stoptabulate @@ -146,10 +147,10 @@ in the following order: \startitem First, it will parse the command line as usual, but it will only interpret a - small subset of the options immediately: \type {--safer}, \type {--nosocket}, - \type {--[no-]shell-escape}, \type {--enable-write18}, \type - {--disable-write18}, \type {--shell-restricted}, \type {--help}, \type - {--version}, and \type {--credits}. + small subset of the options immediately: \type {--safer}, \type {--nosocket} + (\type {--no-socket}), \type {--socket}, \type {--[no-]shell-escape}, \type + {--enable-write18}, \type {--disable-write18}, \type {--shell-restricted}, + \type {--help}, \type {--version}, and \type {--credits}. \stopitem \startitem @@ -169,7 +170,8 @@ in the following order: \starttabulate[|c|l|] \DB library \BC functions \NC \NR \TB - \NC \type {os} \NC \type {execute} \type {exec} \type {spawn} \type {setenv} + \NC \type {os} \NC \type {execute} \type {exec} \type{kpsepopen} + \type {spawn} \type {setenv} \type {rename} \type {remove} \type {tmpdir} \NC \NR \NC \type {io} \NC \type {popen} \type {output} \type {tmpfile} \NC \NR \NC \type {lfs} \NC \type {rmdir} \type {mkdir} \type {chdir} \type {lock} @@ -181,6 +183,9 @@ in the following order: Furthermore, it disables loading of compiled \LUA\ libraries and it makes \type {io.open()} fail on files that are opened for anything besides reading. + + Finally, it disables the \type {socket} library unconditionally (but not the + \type {mime} library which is always available). \stopitem \startitem @@ -193,13 +198,24 @@ in the following order: os.setlocale(nil,nil) \stoptyping - The \type {--nosocket} option makes the socket library unavailable, so that \LUA\ - cannot use networking. + The \type {--nosocket} (\type {--no-socket}) option makes the socket library + unavailable, so that \LUA\ cannot use networking; the \type {--socket} option + makes the socket library available. + + The switches \type {--[no-]shell-escape}, \type {--[enable|disable]-write18}, + and \type {--shell-restricted} have the same effects as in \PDFTEX, and + additionally make \type {io.popen()}, \type {os.execute}, \type {os.exec}, + \type {os.kpsepopen} and \type {os.spawn} adhere to the requested option. + + By default the socket library is not enabled: one can enable it with with + \type {--socket} or with \type {--shell-escape} (but without \type + {--shell-restricted}) and disable it with \type {--nosocket} (\type + {--no-socket}) or unconditionally with \type {--safer}. + + In case of conflictual options, the most restrictive wins. + + The \type{mime} library is always available. - The switches \type {--[no-]shell-escape}, \type {--[enable|disable]-write18}, and - \type {--shell-restricted} have the same effects as in \PDFTEX, and additionally - make \type {io.popen()}, \type {os.execute}, \type {os.exec} and \type {os.spawn} - adhere to the requested option. \stopitem \startitem @@ -319,8 +335,8 @@ of the module itself). \startsubsection[title={Executing programs}] -In keeping with the other \TEX|-|like programs in \TEXLIVE, the two \LUA\ functions -\type {os.execute} and \type {io.popen}, as well as the two new functions \type +In keeping with the other \TEX|-|like programs in \TEXLIVE, the \LUA\ functions +\type {os.execute}, \type{os.kpsepopen} and \type {io.popen}, as well as the two new functions \type {os.exec} and \type {os.spawn} that are explained below, take the value of \type {shell_escape} and|/|or \type {shell_escape_commands} in account. Whenever \LUATEX\ is run with the assumed intention to typeset a document (and by that we @@ -339,7 +355,7 @@ be done with \type {lfs.attributes}. The additional function \type {lfs.shortname} takes a file name and returns its short name on \type {win32} platforms. Finally, for non|-|\type {win32} platforms only, we provided \type {lfs.readlink} that takes an existing symbolic link as argument and returns its -name. However, the \type library evolved so we have dropped these in favour of +name. However, the \type {lfs} library evolved so we have dropped these in favour of pure \LUA\ variants. The \type {shortname} helper is obsolete and now just returns the name. @@ -372,7 +388,7 @@ piecemeal: \libidx {string} {utfvalues}, \libidx {string} {utfcharacters}, \type {string.utfcharacters(s)}: a string with a single \UTF-8 token in it \stopitem \startitem - \type {string.cWharacters(s)}: a string containing one byte + \type {string.characters(s)}: a string containing one byte \stopitem \startitem \type {string.characterpairs(s)}: two strings each containing one byte or an @@ -421,7 +437,7 @@ and \libidx {string} {utflength}. the given code points \stopitem \startitem - \type {string.utflength(s)}: returns the length oif the given string + \type {string.utflength(s)}: returns the length of the given string \stopitem \stopitemize @@ -432,10 +448,14 @@ used as building blocks for other helpers. \startsubsection[title={Extra \type {os} library functions}] -The \type {os} library has a few extra functions and variables: \libidx {os} -{selfdir}, \libidx {os} {exec}, \libidx {os} {spawn}, \libidx {os} {setenv}, -\libidx {os} {env}, \libidx {os} {gettimeofday}, \libidx {os} {times}, \libidx -{os} {tmpdir}, \libidx {os} {type}, \libidx {os} {name} and \libidx {os} {uname}, +The \type {os} library has a few extra functions and +variables: \libidx {os} {selfdir}, \libidx {os} {exec}, +\libidx {os} {kpsepopen}, +\libidx {os} {socketgettime}, \libidx {os} {socketsleep}, +\libidx {os} {spawn}, \libidx {os} {setenv}, +\libidx {os} {env}, \libidx {os} {gettimeofday}, \libidx {os} {times}, +\libidx {os} {sleep}, \libidx {os} {tmpdir}, \libidx {os} {type}, +\libidx {os} {name} and \libidx {os} {uname},{os} {uname}, that we will discuss here. \startitemize @@ -495,6 +515,18 @@ that we will discuss here. \TEXLUA. \stopitem +\startitem + \type {os.kpsepopen(commandline,[opt])} is similar to \type {io.popen} + but with a preliminary check of the commandline; + if the check is ok then the return value is the same as in \type{io.popen}; + Otherwise it will return the two values \type {nil} and \type {error}. +\stopitem + +\startitem + \type {os.socketgettime} and \type {os.socketsleep} are the same as for + \type{socket.gettime} and \type{socket.sleep} but they are always available. +\stopitem + \startitem \type {os.spawn(commandline)} is a returning version of \type {os.exec}, with otherwise identical calling conventions. @@ -522,19 +554,29 @@ that we will discuss here. \stopitem \startitem - \type {os.times()}returns the current process times according to \ the + \type {os.times()}returns the current process times according to the \UNIX\ C library function \quote {times}. This function is not available on the \MSWINDOWS\ and \SUNOS\ platforms, so do not use this function for portable documents. \stopitem \startitem - \type {os.tmpdir()} creates a directory in the \quote {current directory} + \type {os.sleep(interval[, unit])} suspends the execution of the current run for + a given number of seconds. If the optional argument \type {unit} is present, the + function waits \type {interval / units} seconds. \type {os.sleep(1, 1000)} + for example pauses the program for one millisecond. +\stopitem + +\startitem + \type {os.tmpdir([template])} creates a directory in the \quote {current directory} with the name \type {luatex.XXXXXX} where the \type {X}-es are replaced by a unique string. The function also returns this string, so you can \type {lfs.chdir()} into it, or \type {nil} if it failed to create the directory. The user is responsible for cleaning up at the end of the run, it does not - happen automatically. + happen automatically. You can also use your own \type {template} for the name + of the temporary folder. However, the passed string must end with six capital + \type {X}-es. For example, the template \type {tmp.XXXXXX} could result in the + folder name \type {tmp.vX3gPo}. \stopitem \startitem diff --git a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex index 3bd23ff27..d28bc4fda 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex @@ -1148,7 +1148,7 @@ so a separate grouping related stack is used. A side effect is that there can be paragraphs with only a local par node followed by direction synchronization nodes. Paragraphs like that are seen as empty paragraphs and therefore ignored. Because \type {\noindent} doesn't inject anything but a \type {\indent} injects -an box, paragraphs with only an indent and directions are handles ad paragraphs +an box, paragraphs with only an indent and directions are handled as paragraphs with content. \stopsubsection diff --git a/doc/context/sources/general/manuals/luatex/luatex-nodes.tex b/doc/context/sources/general/manuals/luatex/luatex-nodes.tex index 8eb980629..a57ed98b2 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-nodes.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-nodes.tex @@ -962,7 +962,7 @@ what you generate. \NC \type{width} \NC number \NC the width (not used in calculations) \NC \NR \NC \type{height} \NC number \NC the height (not used in calculations) \NC \NR \NC \type{depth} \NC number \NC the depth (not used in calculations) \NC \NR -\NC \type{objnum} \NC number \NC the referenced \PDF\ (structure) object number \NC \NR +\NC \type{objnum} \NC number \NC the referenced \PDF\ object number \NC \NR \NC \type{data} \NC string \NC the annotation data \NC \NR \LL \stoptabulate @@ -1005,7 +1005,7 @@ what you generate. \NC \NC string \NC the destination name \NC \NR \NC \type{dest_type} \NC number \NC type of destination \NC \NR \NC \type{xyz_zoom} \NC number \NC the zoom factor (times 1000) \NC \NR -\NC \type{objnum} \NC number \NC the \PDF\ object number \NC \NR +\NC \type{objnum} \NC number \NC the \PDF\ object number; for structure references the \PDF\ object number of the linked structure element \NC \NR \LL \stoptabulate @@ -1251,8 +1251,8 @@ This converts a single type name to its internal numeric representation. \libindex {subtype} If the argument is a number, then the next function converts an internal numeric -numeric representation to an external string representation. Otherwise, it will -return the string \type {node} if the object represents a node, and \type {nil} +representation to an external string representation. Otherwise, it will return +the string \type {node} if the object represents a node, and \type {nil} otherwise. \startfunctioncall @@ -1321,8 +1321,8 @@ creates a node at the \TEX\ level. \libindex{flush_node} \libindex{flush_list} -The next one removes the node \type {n} from \TEX's memory. Be careful: no checks -are done on whether this node is still pointed to from a register or some \type +The next one removes the node \type {n} from \TEX's memory. Be careful: no checks are +done on whether this node is still pointed to from a register or some \type {next} field: it is up to you to make sure that the internal data structures remain correct. diff --git a/doc/context/sources/general/manuals/luatex/luatex.tex b/doc/context/sources/general/manuals/luatex/luatex.tex index 6031b7c5f..2dd4a8bf1 100644 --- a/doc/context/sources/general/manuals/luatex/luatex.tex +++ b/doc/context/sources/general/manuals/luatex/luatex.tex @@ -73,7 +73,7 @@ \startdocument [manual=Lua\TeX, status=stable, - version=1.10] + version=1.16] \startnotmode[*export] \component luatex-titlepage diff --git a/doc/context/sources/general/manuals/metafun/gracht.mp b/doc/context/sources/general/manuals/metafun/gracht.mp index 5076c729a..8f6ea4b4b 100644 --- a/doc/context/sources/general/manuals/metafun/gracht.mp +++ b/doc/context/sources/general/manuals/metafun/gracht.mp @@ -1,6 +1,4 @@ % Converted from PostScript(TM) to MetaPost by pstoedit -% -% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa % MetaPost backend contributed by Scott Pakin % pstoedit is Copyright (C) 1993 - 1999 Wolfgang Glunz diff --git a/doc/context/sources/general/manuals/metafun/mycow.mp b/doc/context/sources/general/manuals/metafun/mycow.mp index 24c3e0f7d..c0d7b3d0a 100644 --- a/doc/context/sources/general/manuals/metafun/mycow.mp +++ b/doc/context/sources/general/manuals/metafun/mycow.mp @@ -1,6 +1,4 @@ % Converted from PostScript(TM) to MetaPost by pstoedit -% -% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa % MetaPost backend contributed by Scott Pakin % pstoedit is Copyright (C) 1993 - 1999 Wolfgang Glunz diff --git a/scripts/context/lua/mtx-ctan.lua b/scripts/context/lua/mtx-ctan.lua index 798a2da02..6de51caa3 100644 --- a/scripts/context/lua/mtx-ctan.lua +++ b/scripts/context/lua/mtx-ctan.lua @@ -34,9 +34,9 @@ local helpinfo = [[ - list available packages - list available topics - show details about package + list available packages [--field=key|name|caption] + list available topics [--field=key|name|details] + show details about package use this pattern, otherwise first argument @@ -71,7 +71,7 @@ local shaped = characters and characters.shaped or lower -- what is the url to fetch a zip -- We cannot use the socket library because we don't compile that massive amount of --- ssl code into lua(meta)tex. aybe some day one fo these small embedded libraries +-- ssl code into lua(meta)tex. Maybe some day one fo these small embedded libraries -- makes sense but there are so many changes in all that security stuff that it -- defeats long term stability of the ecosystem anyway ... just like some of my old -- devices suddenly are no longer accessible with modern browsers I expect it to @@ -185,7 +185,7 @@ scripts.ctan.details = json and -- report("key : %s",data.key or "-") report("name : %s",data.name or "-") report("caption : %s",data.caption or "-") - report("path : %s",data.ctan.path or "-") + report("path : %s",data.ctan and data.ctan.path or "-") report("") end end @@ -207,7 +207,7 @@ or scripts.ctan.packages = json and - function(pattern) + function(pattern,field) local data = validdata(fetched("packages")) if data then local found = { @@ -216,9 +216,26 @@ scripts.ctan.packages = json and } pattern = checkedpattern(pattern) for i=1,#data do - local entry = data[i] - if strfound(pattern,entry.caption) then - found[#found+1] = { entry.key, entry.name, entry.caption } + local entry = data[i] + local key = entry.key + local name = entry.name + local caption = entry.caption + local where + if field == "name" then + where = name + elseif field == "caption" then + where = caption + elseif field == "key" then + where = key + end + if where then + if strfound(pattern,where) then + found[#found+1] = { key, name, caption } + end + else + if strfound(pattern,name) or strfound(pattern,caption) then + found[#found+1] = { key, name, caption } + end end end showresult(found) @@ -256,9 +273,27 @@ scripts.ctan.topics = json and } pattern = checkedpattern(pattern) for i=1,#data do - local entry = data[i] - if strfound(pattern,entry.details) then - found[#found+1] = { entry.key or entry.name, entry.details } -- inconsistency between json and xml + -- inconsistency between json and xml + local entry = data[i] + local key = entry.key + local name = entry.name + local details = entry.details + local where + if field == "name" then + where = name or key + elseif field == "details" then + where = details + elseif field == "key" then + where = key or name + end + if where then + if strfound(pattern,where) then + found[#found+1] = { key or name, details } + end + else + if strfound(pattern,name) or strfound(pattern,details) then + found[#found+1] = { key or name, details } + end end end showresult(found) @@ -292,9 +327,20 @@ local function whatever() report("") end +-- scripts.ctan.packages(environment.argument("pattern") or environment.files[1]) +-- scripts.ctan.packages("font") +-- scripts.ctan.details("tex") +-- scripts.ctan.details("ipaex") + +-- scripts.ctan.packages("Półtawskiego") +-- scripts.ctan.packages("Poltawskiego") + +-- scripts.ctan.topics("font") +-- scripts.ctan.topics() + if environment.argument("packages") then whatever() - scripts.ctan.packages(environment.argument("pattern") or environment.files[1]) + scripts.ctan.packages(environment.argument("pattern") or environment.files[1], environment.argument("field")) elseif environment.argument("topics") then whatever() scripts.ctan.topics(environment.argument("pattern") or environment.files[1]) @@ -306,14 +352,3 @@ elseif environment.argument("exporthelp") then else application.help() end - --- scripts.ctan.packages(environment.argument("pattern") or environment.files[1]) --- scripts.ctan.packages("font") --- scripts.ctan.details("tex") --- scripts.ctan.details("ipaex") - --- scripts.ctan.packages("Półtawskiego") --- scripts.ctan.packages("Poltawskiego") - --- scripts.ctan.topics("font") --- scripts.ctan.topics() diff --git a/scripts/context/lua/mtx-install-tikz.lua b/scripts/context/lua/mtx-install-tikz.lua new file mode 100644 index 000000000..74a292241 --- /dev/null +++ b/scripts/context/lua/mtx-install-tikz.lua @@ -0,0 +1,162 @@ +if not modules then modules = { } end modules ['mtx-install-tikz'] = { + version = 1.234, + comment = "companion to mtxrun.lua", + author = "Hans Hagen", + copyright = "ConTeXt Development Team", + license = "see context related readme files" +} + +-- Installing tikz is a bit tricky because there are many packages involved and it's +-- sort of impossible to derive from the names what to include in the installation. +-- I tried to use the ctan scrips we ship but there is no way to reliably derive a +-- set from the topics or packages using the web api (there are also some +-- inconsistencies between the jkson and xml interfaces that will not be fixed). A +-- wildcard pull of everything tikz/pgf is likely to fail or at least gives files we +-- don't want and/or need, the solution is to be specific. +-- +-- We use curl and not the built in socket library because all kind of ssl and +-- redirection can kick in and who know how it evolves. +-- +-- We use the context unzipper because we cannot be sure if unzip is present on the +-- system. In many cases windows, linux and osx installations lack it by default. +-- +-- This script has no help info etc as it's a rather dumb downloader. One can always +-- do a better job than this suboptimal quick hack. Let me know if I forget to wipe +-- something. +-- +-- mtxrun --script install-tikz +-- +-- It should be run in the tex root and will quit when there is no texmf-context +-- path found. The modules path will be created when absent. + +local okay, curl = pcall(require,"libs-imp-curl") + +local fetched = curl and curl.fetch and function(str) + local data, message = curl.fetch { + url = str, + followlocation = true, + sslverifyhost = false, + sslverifypeer = false, + } + if not data then + report("some error: %s",message) + end + return data +end or function(str) + -- So, no redirect to http, which means that we cannot use the built in socket + -- library. What if the client is happy with http? + local data = os.resultof("curl -sSL " .. str) + return data +end + +local ctanurl = "https://mirrors.ctan.org/install" +local tmpzipfile = "temp.zip" +local checkdir = "texmf-context" +local targetdir = "texmf-modules" + +local report = logs.reporter("install") + +scripts = scripts or { } +scripts.ctan = scripts.ctan or { } + +function scripts.ctan.install(list) + if type(list) ~= "table"then + report("unknown specification") + end + local zips = list.zips + local wipes = list.wipes + if type(zips) ~= "table" or type(wipes) ~= "table" then + report("incomplete specification") + elseif not lfs.isdir(checkdir) then + report("unknown subdirectory %a",checkdir) + elseif not dir.mkdirs(targetdir) then + report("unable to create %a",targetdir) + elseif not lfs.chdir(targetdir) then + report("unable to go into %a",targetdir) + else + report("installing into %a",targetdir) + for i=1,#zips do + local where = ctanurl .. "/" .. zips[i] + local data = fetched(where) + if string.find(data,"^PK") then + io.savedata(tmpzipfile,data) + report("from %a",where) + report("into %a",targetdir) + utilities.zipfiles.unzipdir { + zipname = tmpzipfile, + path = ".", + verbose = "steps", + } + os.remove(tmpzipfile) + else + report("unknown %a",where) + end + end + + local function wiper(wipes) + for i=1,#wipes do + local s = wipes[i] + if type(s) == "table" then + wiper(s) + elseif type(s) == "string" then + local t = dir.glob(s) + report("wiping %i files in %a",#t,s) + for i=1,#t do + os.remove(t[i]) + end + end + end + end + + wiper(wipes) + + report("renewing file database") + resolvers.renewcache() + resolvers.load() + end +end + +local function wipers(s) + return { + "tex/context/third/" ..s.. "/**", + "doc/context/third/" ..s.. "/**", + "source/context/third/" ..s.. "/**", + + "tex/context/" ..s.. "/**", + "doc/context/" ..s.. "/**", + "source/context/" ..s.. "/**", + + "scripts/" ..s.. "/**", + } +end + +local defaults = { + "tex/latex/**", + "tex/plain/**", + + "doc/latex/**", + "doc/plain/**", + "doc/generic/**", + + "source/latex/**", + "source/plain/**", + "source/generic/**", +} + +local lists = { + tikz = { + zips = { + "graphics/pgf/base/pgf.tds.zip", + "graphics/pgf/contrib/pgfplots.tds.zip", + "graphics/pgf/contrib/circuitikz.tds.zip", + }, + wipes = { + wipers("pgf"), + wipers("pgfplots"), + wipers("circuitikz"), + defaults, + } + }, +} + +scripts.ctan.install(lists.tikz) diff --git a/scripts/context/lua/mtx-install.lua b/scripts/context/lua/mtx-install.lua index 7efd8f5ed..4b5901282 100644 --- a/scripts/context/lua/mtx-install.lua +++ b/scripts/context/lua/mtx-install.lua @@ -124,9 +124,9 @@ local platforms = { -- ["linux-armhf"] = "linux-armhf", -- - ["openbsd"] = "openbsd7.2", - ["openbsd-i386"] = "openbsd7.2", - ["openbsd-amd64"] = "openbsd7.2-amd64", + ["openbsd"] = "openbsd7.3", + ["openbsd-i386"] = "openbsd7.3", + ["openbsd-amd64"] = "openbsd7.3-amd64", -- ["freebsd"] = "freebsd", ["freebsd-i386"] = "freebsd", diff --git a/scripts/context/lua/mtx-update.lua b/scripts/context/lua/mtx-update.lua index daf23eb09..19e3e6865 100644 --- a/scripts/context/lua/mtx-update.lua +++ b/scripts/context/lua/mtx-update.lua @@ -178,9 +178,9 @@ update.platforms = { -- ["linux-armhf"] = "linux-armhf", -- - ["openbsd"] = "openbsd7.2", - ["openbsd-i386"] = "openbsd7.2", - ["openbsd-amd64"] = "openbsd7.2-amd64", + ["openbsd"] = "openbsd7.3", + ["openbsd-i386"] = "openbsd7.3", + ["openbsd-amd64"] = "openbsd7.3-amd64", -- ["freebsd"] = "freebsd", ["freebsd-i386"] = "freebsd", diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 513576743..f8ef74110 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -8666,7 +8666,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 14071, stripped down to: 10417 +-- original size: 14107, stripped down to: 10453 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -9145,13 +9145,13 @@ if bit32 and not streams.tocardinal1 then local extract=bit32.extract local char=string.char streams.tocardinal1=char - function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal2(n) return char(extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end streams.tocardinal1le=char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end if not streams.readcstring then local readchar=streams.readchar @@ -14803,7 +14803,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sbx"] = package.loaded["util-sbx"] or true --- original size: 21145, stripped down to: 13271 +-- original size: 21146, stripped down to: 13272 if not modules then modules={} end modules ['util-sbx']={ version=1.001, @@ -15113,7 +15113,7 @@ local runners={ if trace then report("resultof: %s",command) end - local handle=iopopen(command,"r") + local handle=iopopen(command,"rb") if handle then local result=handle:read("*all") or "" handle:close() @@ -26138,7 +26138,7 @@ 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 libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1037548 +-- original bytes : 1037585 -- stripped bytes : 408686 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 513576743..f8ef74110 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -8666,7 +8666,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 14071, stripped down to: 10417 +-- original size: 14107, stripped down to: 10453 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -9145,13 +9145,13 @@ if bit32 and not streams.tocardinal1 then local extract=bit32.extract local char=string.char streams.tocardinal1=char - function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal2(n) return char(extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end streams.tocardinal1le=char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end if not streams.readcstring then local readchar=streams.readchar @@ -14803,7 +14803,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sbx"] = package.loaded["util-sbx"] or true --- original size: 21145, stripped down to: 13271 +-- original size: 21146, stripped down to: 13272 if not modules then modules={} end modules ['util-sbx']={ version=1.001, @@ -15113,7 +15113,7 @@ local runners={ if trace then report("resultof: %s",command) end - local handle=iopopen(command,"r") + local handle=iopopen(command,"rb") if handle then local result=handle:read("*all") or "" handle:close() @@ -26138,7 +26138,7 @@ 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 libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1037548 +-- original bytes : 1037585 -- stripped bytes : 408686 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 513576743..f8ef74110 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -8666,7 +8666,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 14071, stripped down to: 10417 +-- original size: 14107, stripped down to: 10453 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -9145,13 +9145,13 @@ if bit32 and not streams.tocardinal1 then local extract=bit32.extract local char=string.char streams.tocardinal1=char - function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal2(n) return char(extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end streams.tocardinal1le=char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end if not streams.readcstring then local readchar=streams.readchar @@ -14803,7 +14803,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sbx"] = package.loaded["util-sbx"] or true --- original size: 21145, stripped down to: 13271 +-- original size: 21146, stripped down to: 13272 if not modules then modules={} end modules ['util-sbx']={ version=1.001, @@ -15113,7 +15113,7 @@ local runners={ if trace then report("resultof: %s",command) end - local handle=iopopen(command,"r") + local handle=iopopen(command,"rb") if handle then local result=handle:read("*all") or "" handle:close() @@ -26138,7 +26138,7 @@ 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 libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1037548 +-- original bytes : 1037585 -- stripped bytes : 408686 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index 513576743..f8ef74110 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -8666,7 +8666,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 14071, stripped down to: 10417 +-- original size: 14107, stripped down to: 10453 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -9145,13 +9145,13 @@ if bit32 and not streams.tocardinal1 then local extract=bit32.extract local char=string.char streams.tocardinal1=char - function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal2(n) return char(extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end streams.tocardinal1le=char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end if not streams.readcstring then local readchar=streams.readchar @@ -14803,7 +14803,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sbx"] = package.loaded["util-sbx"] or true --- original size: 21145, stripped down to: 13271 +-- original size: 21146, stripped down to: 13272 if not modules then modules={} end modules ['util-sbx']={ version=1.001, @@ -15113,7 +15113,7 @@ local runners={ if trace then report("resultof: %s",command) end - local handle=iopopen(command,"r") + local handle=iopopen(command,"rb") if handle then local result=handle:read("*all") or "" handle:close() @@ -26138,7 +26138,7 @@ 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 libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1037548 +-- original bytes : 1037585 -- stripped bytes : 408686 -- end library merge diff --git a/source/luametatex/build.sh b/source/luametatex/build.sh index a8a834a7c..612092e7a 100644 --- a/source/luametatex/build.sh +++ b/source/luametatex/build.sh @@ -20,9 +20,9 @@ #NINJA=$(which ninja); #if (NINJA) then -# NINJA="-G Ninja" -#else - NINJA="" +# NINJA="-G Ninja" +#else + NINJA="" #fi if [ "$1" = "mingw-64" ] || [ "$1" = "mingw64" ] || [ "$1" = "mingw" ] || [ "$1" == "--mingw64" ] diff --git a/source/luametatex/source/luacore/readme.txt b/source/luametatex/source/luacore/readme.txt index 89d39cb6d..23eb77311 100644 --- a/source/luametatex/source/luacore/readme.txt +++ b/source/luametatex/source/luacore/readme.txt @@ -3,7 +3,7 @@ About luasocket and luasec: Till mid 2021 we had the luasec code in the source tree but it was not used yet. It requires openssl which is pretty large and we need a bunch of header files. In order to compile luasec we need openssl headers and unfortunately there are a few included files that one need to -make. This create a depedency unless we make a few simple ones; after all we only need it for +make. This create a dependency unless we make a few simple ones; after all we only need it for a few platforms. I couldn't locate a neutral header set so it never came to compilation (I started making a set myself but could not motivate myself to finish it). We could use it as optional library (which then demands a bit different interface). But, no matter what we diff --git a/source/luametatex/source/luaoptional/lmtoptional.c b/source/luametatex/source/luaoptional/lmtoptional.c index 0cfbd166c..819cfc3ea 100644 --- a/source/luametatex/source/luaoptional/lmtoptional.c +++ b/source/luametatex/source/luaoptional/lmtoptional.c @@ -7,7 +7,7 @@ /*tex - We don't want the binary top explode and have depdencies that will kill this project in the + We don't want the binary to explode and have depdencies that will kill this project in the end. So, we provide optionals: these are loaded lazy and libraries need to be present in the tree. They are unofficial and not supported in the sense that ConTeXt doesn't depend on them. diff --git a/source/luametatex/source/tex/texcommands.c b/source/luametatex/source/tex/texcommands.c index 91e6d75b8..3529f24d2 100644 --- a/source/luametatex/source/tex/texcommands.c +++ b/source/luametatex/source/tex/texcommands.c @@ -313,16 +313,16 @@ void tex_initialize_commands(void) tex_primitive(tex_command, "accent", accent_cmd, normal_code, 0); - /*tex These three can go in one cmd: */ + /*tex These three times two can go in one cmd: */ tex_primitive(tex_command, "advance", arithmic_cmd, advance_code, 0); tex_primitive(tex_command, "divide", arithmic_cmd, divide_code, 0); tex_primitive(tex_command, "multiply", arithmic_cmd, multiply_code, 0); - tex_primitive(tex_command, "advanceby", arithmic_cmd, advance_by_code, 0); - tex_primitive(tex_command, "divideby", arithmic_cmd, divide_by_code, 0); - tex_primitive(tex_command, "multiplyby", arithmic_cmd, multiply_by_code, 0); - /* tex_primitive(tex_command, "advancebyplusone", arithmic_cmd, advance_by_plus_one_code, 0); */ - /* tex_primitive(tex_command, "advancebyminusone", arithmic_cmd, advance_by_minus_one_code, 0); */ + tex_primitive(luatex_command, "advanceby", arithmic_cmd, advance_by_code, 0); + tex_primitive(luatex_command, "divideby", arithmic_cmd, divide_by_code, 0); + tex_primitive(luatex_command, "multiplyby", arithmic_cmd, multiply_by_code, 0); + /* tex_primitive(luatex_command, "advancebyplusone", arithmic_cmd, advance_by_plus_one_code, 0); */ + /* tex_primitive(luatex_command, "advancebyminusone", arithmic_cmd, advance_by_minus_one_code, 0); */ /*tex We combined the after thingies into one category:*/ diff --git a/source/luametatex/source/tex/texscanning.c b/source/luametatex/source/tex/texscanning.c index 8ae7090cf..c4f9b0c56 100644 --- a/source/luametatex/source/tex/texscanning.c +++ b/source/luametatex/source/tex/texscanning.c @@ -2427,9 +2427,9 @@ static void tex_aux_scan_dimen_unknown_unit_error(void) { tex_handle_error( normal_error_type, "Illegal unit of measure (pt inserted)", - "Dimensions can be in units of em, ex, in, pt, pc, cm, mm, dd, cc, bp, dk, or\n" - "sp; but yours is a new one! I'll assume that you meant to say pt, for printer's\n" - "points. two letters." + "Dimensions can be in units of em, ex, sp, cm, mm, es, ts, pt, bp, dk, pc, dd\n" + "cc or in; but yours is a new one! I'll assume that you meant to say pt, for\n" + "printer's points: two letters." ); } @@ -2437,8 +2437,8 @@ static void tex_aux_scan_dimen_out_of_range_error(void) { tex_handle_error( normal_error_type, "Dimension too large", - "I can't work with sizes bigger than about 19 feet. Continue and I'll use the\n" - "largest value I can." + "I can't work with sizes bigger than about 575 cm (230 es). Continue and I'll\n" + "use the largest value I can (16383 pt)." ); } @@ -2482,6 +2482,14 @@ typedef enum scanned_unit { to Knuth, the basis of this new revolutionary system is the potrzebie, which equals the thickness of Mad issue 26, or 2.2633484517438173216473 mm [...]. + We also provide alternatives for the inch: the |es| and |ts|, two units dedicated to women + (Edith and Tove) that come close to the inch but are more metric. Their values have been + carefully callibrated at the 2023 BachoTeX meeting and a report will be published in the + proceedings as well as TUGboat (medio 2023). + + An additional |eu| has been introduced as a multiplier for |ts| that defaults to 10 which makes + one |eu| default to one |es|. + */ static int tex_aux_scan_unit(halfword *num, halfword *denom, halfword *value, halfword *order) diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 1b418833b..b19283ff1 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{2023.04.27 16:54} +\newcontextversion{2023.05.05 18: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 5f1fbaa04..f5ef6f059 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{2023.04.27 16:54} +\edef\contextversion{2023.05.05 18:36} %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index cbe448fc7..a3bc4164e 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{2023.04.27 16:54} +\newcontextversion{2023.05.05 18:36} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 7c3567153..1ef4503ab 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -49,7 +49,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2023.04.27 16:54} +\edef\contextversion{2023.05.05 18:36} %D Kind of special: diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv index 19f431ebf..7ec4b722e 100644 --- a/tex/context/base/mkiv/lang-def.mkiv +++ b/tex/context/base/mkiv/lang-def.mkiv @@ -273,7 +273,7 @@ [\s!hy] [\c!spacing=\v!packed, \c!leftsentence=\endash, % *sentences not confirmed - \c!rightsentence=\endash, + \c!rightsentence=\endash, \c!leftsubsentence=\endash, \c!rightsubsentence=\endash, \c!leftquote=\guilsingleleft, @@ -781,7 +781,8 @@ \c!rightquote=\upperrightsingleninequote, \c!leftquotation=\upperleftdoublesixquote, \c!rightquotation=\upperrightdoubleninequote, - \c!date={\v!year,\space,\v!month,\space,\v!day}] + \c!date={\v!day,\space,\v!month,\space,\v!year}] + \installlanguage[\s!pt-br][\c!default=\s!pt] % Brazil \installlanguage[\s!es-es][\c!default=\s!es] % Spain diff --git a/tex/context/base/mkiv/lang-txt.lua b/tex/context/base/mkiv/lang-txt.lua index 668d48eb6..c41936dac 100644 --- a/tex/context/base/mkiv/lang-txt.lua +++ b/tex/context/base/mkiv/lang-txt.lua @@ -49,14 +49,14 @@ if not modules then modules = { } end modules ['lang-txt'] = { -- nn Norwegian Hans Fredrik Nordhaug, ... -- nl Dutch Hans Hagen -- pl Polish Grzegorz Sapijaszko (2011) --- pt Portuguese Pedro F. M. Mendonça +-- pt Portuguese Pedro F. M. Mendonça; additions Joana Sophia Bogas Carneiro (2023) -- ro Romanian Dan Seracu, ... -- ru Russian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ... -- sk Slovak Tomáš Hála (2012, 2022) -- sl Slovenian Mojca Miklavec -- sr Serbian Ivan Pešić (2020) -- sr-latn Serbian Ivan Pešić (2020) --- sv Swedish ... +-- sv Swedish ...; additions Edith and Mikael Sundqvist (2023) -- tk Turkish Tobias Burnus -- tr Turkmen Nazar Annagurban -- ua Ukrainian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ... @@ -69,6 +69,11 @@ if not modules then modules = { } end modules ['lang-txt'] = { -- thinspace == sixperemspace = 0x2006 -- print("!"..utf.char(0x2006).."!") +-- Will be done when needed: +-- (TH) editor|editors:mnem missing +-- (HH) save memory at functions +-- (MS) btx settings for sv + languages = languages or { } local languages = languages @@ -84,7 +89,7 @@ data.labels={ ["be"]="У", ["bg"]="в", ["ca"]="En", - ["cs"]={ "In", "V" }, + ["cs"]="In", ["de"]="In", ["en"]="In", ["eo"]="En", @@ -93,7 +98,7 @@ data.labels={ ["fr"]="Dans", ["hy"]="Մեջ", ["mk"]="во", - ["sk"]={ "In", "V" }, + ["sk"]="In", ["sr"]="У", ["sr-latn"]="U", }, @@ -113,6 +118,7 @@ data.labels={ ["hy"]="Համար", ["mk"]="Број", ["nl"]="Nummer", + ["pt"]="Numero", ["sk"]="Číslo", ["sr"]="Број", ["sr-latn"]="Broj", @@ -134,6 +140,7 @@ data.labels={ ["hy"]="Ծավալ", ["mk"]="Том", ["nl"]="Deel", + ["pt"]="Volume", ["sk"]="Zväzok", ["sr"]="Том", ["sr-latn"]="Tom", @@ -156,6 +163,7 @@ data.labels={ ["it"]="e", ["mk"]="и", ["nl"]="en", + ["pt"]="e", ["sk"]="a", ["sr"]="и", ["sr-latn"]="i", @@ -166,7 +174,7 @@ data.labels={ ["be"]="Выданне", ["bg"]="издание", ["ca"]="Edició", - ["cs"]="Vydání", + ["cs"]="vydání", ["de"]="Auflage", ["en"]="edition", ["eo"]="eldono", @@ -179,17 +187,18 @@ data.labels={ ["it"]="edizione", ["mk"]="издание", ["nl"]="editie", - ["sk"]="Vydanie", + ["pt"]="edicao", + ["sk"]="vydanie", ["sr"]="издање", ["sr-latn"]="izdanje", }, }, ["editor"]={ ["labels"]={ - ["be"]="Рэдактар", + ["be"]="реэдактар", ["bg"]="редактор", - ["ca"]="Editor", - ["cs"]="Editor", + ["ca"]="editor", + ["cs"]="editor", ["de"]="Herausgeber", ["en"]="editor", ["eo"]="eldonisto", @@ -200,29 +209,24 @@ data.labels={ ["hy"]="խմբագիր", ["it"]="a cura di", ["mk"]="уредник", - ["sk"]="Editor", + ["pt"]="editor", + ["sk"]="editor", ["sr"]="уредник", ["sr-latn"]="urednik", }, }, ["editor:f"]={ ["labels"]={ - ["cs"]="Editorka", - ["sk"]="Editorka", - }, - }, - ["editor:m"]={ - ["labels"]={ - ["cs"]="Editor", - ["sk"]="Editor", + ["cs"]="editorka", + ["sk"]="editorka", }, }, ["editors"]={ ["labels"]={ - ["be"]="Рэдактары", + ["be"]="рэдактары", ["bg"]="редактори", - ["ca"]="Editors", - ["cs"]="Editoři", + ["ca"]="editors", + ["cs"]="editoři", ["de"]="Herausgeber", ["en"]="editors", ["eo"]="eldonistoj", @@ -232,21 +236,16 @@ data.labels={ ["hy"]="խմբագիրներ", ["it"]="a cura di", ["mk"]="уредници", - ["sk"]="Editori", + ["pt"]="editores", + ["sk"]="editori", ["sr"]="уредници", ["sr-latn"]="urednici", }, }, ["editors:f"]={ ["labels"]={ - ["cs"]="Editorky", - ["sk"]="Editorky", - }, - }, - ["editors:m"]={ - ["labels"]={ - ["cs"]="Editoři", - ["sk"]="Editori", + ["cs"]="editorky", + ["sk"]="editorky", }, }, ["in"]={ @@ -263,6 +262,7 @@ data.labels={ ["fr"]="dans", ["hy"]="մեջ", ["mk"]="во", + ["pt"]="em", ["sk"]="v", ["sr"]="у", ["sr-latn"]="u", @@ -286,6 +286,7 @@ data.labels={ ["it"]="Tesi di laurea", ["mk"]="Магистерска дисертација", ["nl"]="Masterproef", + ["pt"]="Tese de mestrado", ["sk"]="Diplomová práca", ["sr"]="Мастер дисертација", ["sr-latn"]="Master disertacija", @@ -307,6 +308,7 @@ data.labels={ ["hy"]="համար", ["mk"]="број", ["nl"]="nummer", + ["pt"]="numero", ["sk"]="číslo", ["sr"]="број", ["sr-latn"]="broj", @@ -326,6 +328,7 @@ data.labels={ ["hy"]="-ից", ["mk"]="од", ["nl"]="van", + ["pt"]="de", ["sk"]="z", ["sr"]="од", ["sr-latn"]="od", @@ -334,7 +337,7 @@ data.labels={ ["others"]={ ["labels"]={ ["ca"]="et al.", - ["cs"]={ "a~kol.", "et al."}, + ["cs"]="a~kol.", ["de"]="et al.", ["en"]="et al.", ["eo"]="aliaj", @@ -343,7 +346,8 @@ data.labels={ ["fr"]="et al.", ["hy"]="եւ այլն", ["mk"]="и др.", - ["sk"]={ "a~kol.", "et al."}, + ["pt"]="etc", + ["sk"]="a~kol.", ["sr"]="и др.", ["sr-latn"]="i dr.", }, @@ -362,6 +366,7 @@ data.labels={ ["fr"]="p.", ["hy"]="էջ", ["mk"]="стр.", + ["pt"]="p", ["sk"]="s.", ["sr"]="стр.", ["sr-latn"]="str.", @@ -384,6 +389,7 @@ data.labels={ ["hy"]="էջեր", ["mk"]="страници", ["nl"]="paginas", + ["pt"]="paginas", ["sk"]="strany", ["sr"]="страницa", ["sr-latn"]="stranica", @@ -406,6 +412,7 @@ data.labels={ ["it"]="Brevetto", ["mk"]="Патент", ["nl"]="Octrooi", + ["pt"]="Patente", ["sk"]="Patent", ["sr"]="Патент", ["sr-latn"]="Patent", @@ -428,6 +435,7 @@ data.labels={ ["it"]="Tesi di dottorato", ["mk"]="Докторска дисертација", ["nl"]="Proefschrift", + ["pt"]="Tese de douturamento", ["sk"]="Dizertačná práca", ["sr"]="Докторска дисертација", ["sr-latn"]="Doktorska disertacija", @@ -445,6 +453,7 @@ data.labels={ ["fa"]="صص", ["hy"]="էջ", ["mk"]="стр.", + ["pt"]="pp", ["sk"]="s.", ["sr"]="стр.", ["sr-latn"]="str.", @@ -468,6 +477,7 @@ data.labels={ ["it"]="Relazione tecnica", ["mk"]="Технички извештај", ["nl"]="Technisch rapport", + ["pt"]="Reporte tecnico", ["sk"]="Technická zpráva", ["sr"]="Технички извештај", ["sr-latn"]="Tehnički izveštaj", @@ -489,6 +499,7 @@ data.labels={ ["hy"]="ծավալ", ["mk"]="том", ["nl"]="deel", + ["pt"]="volume", ["sk"]="zväzok", ["sr"]="том", ["sr-latn"]="tom", @@ -511,6 +522,7 @@ data.labels={ ["it"]="con", ["mk"]="со", ["nl"]="met", + ["pt"]="com", ["sk"]="s", ["sr"]="са", ["sr-latn"]="sa", @@ -527,9 +539,11 @@ data.labels={ ["es"]="Pr", ["hy"]="P", ["mk"]="P", + ["pt"]="Pr", ["sk"]="P", ["sr"]="P", ["sr-latn"]="P", + ["sv"]="Pr", }, }, ["arccos"]={ @@ -543,9 +557,11 @@ data.labels={ ["hy"]="arccos", ["mk"]="arccos", ["pl"]="arc\\sixperemspace cos", + ["pt"]="arccos", ["sk"]="arccos", ["sr"]="arccos", ["sr-latn"]="arccos", + ["sv"]="arccos", }, }, ["arccosh"]={ @@ -559,9 +575,11 @@ data.labels={ ["hy"]="arccosh", ["mk"]="arccosh", ["pl"]="arc\\sixperemspace cosh", + ["pt"]="arccosh", ["sk"]="arccosh", ["sr"]="arccosh", ["sr-latn"]="arccosh", + ["sv"]="arcosh", }, }, ["arccot"]={ @@ -575,9 +593,11 @@ data.labels={ ["hy"]="arcctg", ["mk"]="arccotg", ["pl"]="arc\\sixperemspace ctg", + ["pt"]="arccot", ["sk"]="arccotg", ["sr"]="arcctg", ["sr-latn"]="arcctg", + ["sv"]="arccot", }, }, ["arcsin"]={ @@ -591,9 +611,11 @@ data.labels={ ["hy"]="arcsin", ["mk"]="arcsin", ["pl"]="arc\\sixperemspace sin", + ["pt"]="arcsin", ["sk"]="arcsin", ["sr"]="arcsin", ["sr-latn"]="arcsin", + ["sv"]="arcsin", }, }, ["arcsinh"]={ @@ -607,9 +629,11 @@ data.labels={ ["hy"]="arcsinh", ["mk"]="arcsinh", ["pl"]="arc\\sixperemspace sinh", + ["pt"]="arcsinh", ["sk"]="arcsinh", ["sr"]="arcsinh", ["sr-latn"]="arcsinh", + ["sv"]="arsinh", }, }, ["arctan"]={ @@ -623,9 +647,11 @@ data.labels={ ["hy"]="arctan", ["mk"]="arctg", ["pl"]="arc\\sixperemspace tg", + ["pt"]="arctan", ["sk"]="arctg", ["sr"]="arctg", ["sr-latn"]="arctg", + ["sv"]="arctan", }, }, ["arctanh"]={ @@ -639,9 +665,11 @@ data.labels={ ["hy"]="arctanh", ["mk"]="arctgh", ["pl"]="arc\\sixperemspace tgh", + ["pt"]="arctanh", ["sk"]="arctgh", ["sr"]="arctgh", ["sr-latn"]="arctgh", + ["sv"]="artanh", }, }, ["arg"]={ @@ -653,9 +681,11 @@ data.labels={ ["es"]="arg", ["hy"]="arg", ["mk"]="arg", + ["pt"]="arg", ["sk"]="arg", ["sr"]="arg", ["sr-latn"]="arg", + ["sv"]="arg", }, }, ["cos"]={ @@ -667,9 +697,11 @@ data.labels={ ["es"]="cos", ["hy"]="cos", ["mk"]="cos", + ["pt"]="cos", ["sk"]="cos", ["sr"]="cos", ["sr-latn"]="cos", + ["sv"]="cos", }, }, ["cosh"]={ @@ -681,9 +713,11 @@ data.labels={ ["es"]="cosh", ["hy"]="cosh", ["mk"]="cosh", + ["pt"]="cosh", ["sk"]="cosh", ["sr"]="cosh", ["sr-latn"]="cosh", + ["sv"]="cosh", }, }, ["cot"]={ @@ -697,9 +731,11 @@ data.labels={ ["hy"]="cot", ["mk"]="ctg", ["pl"]="ctg", + ["pt"]="cot", ["sk"]="cotg", ["sr"]="ctg", ["sr-latn"]="ctg", + ["sv"]="cot", }, }, ["coth"]={ @@ -711,9 +747,11 @@ data.labels={ ["es"]="coth", ["hy"]="coth", ["mk"]="ctgh", + ["pt"]="coth", ["sk"]="cotgh", ["sr"]="ctgh", ["sr-latn"]="ctgh", + ["sv"]="coth", }, }, ["csc"]={ @@ -725,28 +763,13 @@ data.labels={ ["es"]="csc", ["hy"]="csc", ["mk"]="cosec", + ["pt"]="csc", ["sk"]="cosec", ["sr"]="cosec", ["sr-latn"]="cosec", + ["sv"]="csc", }, }, ---[[ ["ctg"]={ - ["labels"]={ - ["ca"]="cot", - ["cs"]="cotg", - ["en"]="cot", - ["eo"]="cotan", - ["es"]="cot", - ["hr"]="ctg", - ["hy"]="cot", - ["mk"]="ctg", - ["pl"]="ctg", - ["sk"]="cotg", - ["sr"]="ctg", - ["sr-latn"]="ctg", - }, - }, ---]] ["deg"]={ ["labels"]={ ["ca"]="gr", @@ -756,9 +779,11 @@ data.labels={ ["es"]="gr", ["hy"]="deg", ["mk"]="deg", + ["pt"]="deg", ["sk"]="deg", ["sr"]="deg", ["sr-latn"]="deg", + ["sv"]="deg", }, }, ["det"]={ @@ -769,9 +794,11 @@ data.labels={ ["eo"]="det", ["es"]="det", ["hy"]="det", + ["pt"]="det", ["sk"]="det", ["sr"]="det", ["sr-latn"]="det", + ["sv"]="det", }, }, ["diff"]={ @@ -781,7 +808,9 @@ data.labels={ ["en"]="d", ["eo"]="dif", ["hy"]="d", + ["pt"]="d", ["sk"]="d", + ["sv"]="d", }, }, ["dim"]={ @@ -793,9 +822,11 @@ data.labels={ ["es"]="dim", ["hy"]="dim", ["mk"]="dim", + ["pt"]="dim", ["sk"]="dim", ["sr"]="dim", ["sr-latn"]="dim", + ["sv"]="dim", }, }, ["exp"]={ @@ -806,9 +837,11 @@ data.labels={ ["eo"]="eksp", ["es"]="exp", ["hy"]="exp", + ["pt"]="exp", ["sk"]="exp", ["sr"]="exp", ["sr-latn"]="exp", + ["sv"]="exp", }, }, ["gcd"]={ @@ -823,9 +856,11 @@ data.labels={ ["hy"]="ԱԸԲ", ["mk"]="НЗД", ["nl"]="ggd", + ["pt"]="gcd", ["sk"]="NSD", ["sr"]="НЗД", ["sr-latn"]="NZD", + ["sv"]="sgd", }, }, ["hom"]={ @@ -836,7 +871,9 @@ data.labels={ ["eo"]="hom", ["es"]="hom", ["hy"]="հոմ", + ["pt"]="hom", ["sk"]="Hom", + ["sv"]="hom", }, }, ["inf"]={ @@ -848,9 +885,11 @@ data.labels={ ["es"]="inf", ["hy"]="inf", ["mk"]="inf", + ["pt"]="inf", ["sk"]="inf", ["sr"]="inf", ["sr-latn"]="inf", + ["sv"]="inf", }, }, ["injlim"]={ @@ -861,9 +900,11 @@ data.labels={ ["eo"]="", ["es"]="lím\\sixperemspace iny", ["hy"]="inj\\sixperemspace lim", + ["pt"]="inj\\sixperemspace lim", ["sk"]="inj\\sixperemspace lim", ["sr"]="inj\\sixperemspace lim", ["sr-latn"]="inj\\sixperemspace lim", + ["sv"]="inj\\sixperemspace lim", }, }, ["inv"]={ @@ -875,9 +916,11 @@ data.labels={ ["es"]="inv", ["hy"]="inv", ["mk"]="inv", + ["pt"]="inv", ["sk"]="inv", ["sr"]="inv", ["sr-latn"]="inv", + ["sv"]="inv", }, }, ["ker"]={ @@ -888,9 +931,11 @@ data.labels={ ["eo"]="", ["es"]="Ker", ["hy"]="ker", + ["pt"]="ker", ["sk"]="ker", ["sr"]="ker", ["sr-latn"]="ker", + ["sv"]="ker", }, }, ["lcm"]={ @@ -905,9 +950,11 @@ data.labels={ ["hy"]="աըբ", ["mk"]="НЗС", ["nl"]="kgv", + ["pt"]="lcm", ["sk"]="NSN", ["sr"]="НЗС", ["sr-latn"]="NZS", + ["sv"]="lcm", }, }, ["lg"]={ @@ -921,9 +968,11 @@ data.labels={ ["fr"]="log", ["hy"]="lg", ["mk"]="lg", + ["pt"]="lg", ["sk"]="log", ["sr"]="lg", ["sr-latn"]="lg", + ["sv"]="lg", }, }, ["lim"]={ @@ -935,9 +984,11 @@ data.labels={ ["es"]="lím", ["hy"]="lim", ["mk"]="lim", + ["pt"]="lim", ["sk"]="lim", ["sr"]="lim", ["sr-latn"]="lim", + ["sv"]="lim", }, }, ["liminf"]={ @@ -949,9 +1000,11 @@ data.labels={ ["es"]="lím\\sixperemspace inf", ["hy"]="lim\\sixperemspace infs", ["mk"]="lim\\sixperemspace inf", + ["pt"]="lim\\sixperemspace inf", ["sk"]="lim\\sixperemspace inf", ["sr"]="lim\\sixperemspace inf", ["sr-latn"]="lim\\sixperemspace inf", + ["sv"]="lim\\sixperemspace inf", }, }, ["limsup"]={ @@ -963,9 +1016,11 @@ data.labels={ ["es"]="lím\\sixperemspace sup", ["hy"]="lim\\sixperemspace sup", ["mk"]="lim\\sixperemspace sup", + ["pt"]="lim\\sixperemspace sup", ["sk"]="lim\\sixperemspace sup", ["sr"]="lim\\sixperemspace sup", ["sr-latn"]="lim\\sixperemspace sup", + ["sv"]="lim\\sixperemspace sup", }, }, ["ln"]={ @@ -977,9 +1032,11 @@ data.labels={ ["es"]="ln", ["hy"]="ln", ["mk"]="ln", + ["pt"]="ln", ["sk"]="ln", ["sr"]="ln", ["sr-latn"]="ln", + ["sv"]="ln", }, }, ["log"]={ @@ -991,9 +1048,11 @@ data.labels={ ["es"]="log", ["hy"]="log", ["mk"]="log", + ["pt"]="log", ["sk"]="log", ["sr"]="log", ["sr-latn"]="log", + ["sv"]="log", }, }, ["max"]={ @@ -1006,15 +1065,17 @@ data.labels={ ["fi"]="max", ["hy"]="max", ["mk"]="max", + ["pt"]="max", ["sk"]="max", ["sr"]="max", ["sr-latn"]="max", + ["sv"]="max", }, }, ["median"]={ ["labels"]={ + ["comment"]=[[ cs+sk: \tilde won't work]], ["ca"]="mitjana", - -- ["cs"]="\\tilde", -- won't work ["cs"]="Me", ["en"]="median", ["eo"]="mediano", @@ -1022,10 +1083,11 @@ data.labels={ ["fi"]="mediaani", ["fr"]="médiane", ["hy"]="միջին", - -- ["sk"]="\\tilde", -- won't work + ["pt"]="median", ["sk"]="Med", ["sr"]="median", ["sr-latn"]="median", + ["sv"]="median", }, }, ["min"]={ @@ -1038,9 +1100,11 @@ data.labels={ ["fi"]="min", ["hy"]="min", ["mk"]="min", + ["pt"]="min", ["sk"]="min", ["sr"]="min", ["sr-latn"]="min", + ["sv"]="min", }, }, ["mod"]={ @@ -1053,9 +1117,11 @@ data.labels={ ["fi"]="mod", ["hy"]="mod", ["mk"]="mod", + ["pt"]="mod", ["sk"]="mod", ["sr"]="mod", ["sr-latn"]="mod", + ["sv"]="mod", }, }, ["projlim"]={ @@ -1066,9 +1132,11 @@ data.labels={ ["eo"]="", ["es"]="lím\\sixperemspace proy", ["hy"]="proj\\sixperemspace lim", + ["pt"]="proj\\sixperemspace lim", ["sk"]="proj\\sixperemspace lim", ["sr"]="proj\\sixperemspace lim", ["sr-latn"]="proj\\sixperemspace lim", + ["sv"]="proj\\sixperemspace lim", }, }, ["sec"]={ @@ -1081,9 +1149,11 @@ data.labels={ ["fi"]="sek", ["hy"]="sec", ["mk"]="sec", + ["pt"]="sec", ["sk"]="sec", ["sr"]="sec", ["sr-latn"]="sec", + ["sv"]="sec", }, }, ["sin"]={ @@ -1096,9 +1166,11 @@ data.labels={ ["fi"]="sin", ["hy"]="sin", ["mk"]="sin", + ["pt"]="sen", ["sk"]="sin", ["sr"]="sin", ["sr-latn"]="sin", + ["sv"]="sin", }, }, ["sinh"]={ @@ -1110,9 +1182,11 @@ data.labels={ ["es"]="senh", ["hy"]="sinh", ["mk"]="sinh", + ["pt"]="sinh", ["sk"]="sinh", ["sr"]="sinh", ["sr-latn"]="sinh", + ["sv"]="sinh", }, }, ["sup"]={ @@ -1123,9 +1197,11 @@ data.labels={ ["es"]="sup", ["hy"]="sup", ["mk"]="sup", + ["pt"]="sup", ["sk"]="sup", ["sr"]="sup", ["sr-latn"]="sup", + ["sv"]="sup", }, }, ["tan"]={ @@ -1138,9 +1214,11 @@ data.labels={ ["hy"]="tan", ["mk"]="tg", ["pl"]="tg", + ["pt"]="tan", ["sk"]="tg", ["sr"]="tg", ["sr-latn"]="tg", + ["sv"]="tan", }, }, ["tanh"]={ @@ -1151,18 +1229,15 @@ data.labels={ ["es"]="tanh", ["hy"]="tanh", ["mk"]="tgh", + ["pt"]="tanh", ["sk"]="tgh", ["sr"]="tgh", ["sr-latn"]="tgh", + ["sv"]="tanh", }, }, }, ["texts"]={ - ["demo-texts"]={ - ["labels"]={ - ["en"]={ "demo-1", "demo-2" }, - }, - }, ["and"]={ ["labels"]={ ["af"]="", @@ -1189,13 +1264,13 @@ data.labels={ ["nl"]=" en ", ["nn"]="", ["pl"]=" i ", - ["pt"]="", + ["pt"]=" e ", ["ro"]="", ["ru"]="", ["sk"]=" a ", ["sl"]="", ["sr"]=" и ", - ["sv"]="", + ["sv"]=" och ", ["tk"]="", ["tr"]="", ["ua"]="", @@ -1207,18 +1282,18 @@ data.labels={ ["labels"]={ ["af"]="Bylae ", ["ar"]="ملحق ", - ["be"]="Апендыцыт", + ["be"]="Апендыцыт ", ["ca"]="Apèndix ", ["cn"]="附录 ", ["cs"]="Příloha ", ["da"]="Bilag ", ["de"]="Anhang ", ["en"]="Appendix ", - ["eo"]="Anekso", + ["eo"]="Anekso ", ["es"]="Apéndice ", ["et"]="Lisa ", ["fa"]="پیوست ", - ["fi"]="liite", + ["fi"]="Liite ", ["fr"]="Annexe ", ["gr"]="Παράρτημα ", ["hr"]="Dodatak ", @@ -1234,14 +1309,14 @@ data.labels={ ["nl"]="", ["nn"]="Tillegg ", ["pl"]="Dodatek ", - ["pt"]="", + ["pt"]="Apendice ", ["ro"]="", ["ru"]="", ["sk"]="Príloha ", ["sl"]="Dodatek ", ["sr"]="Додатак ", ["sr-latn"]="Dodatak ", - ["sv"]="", + ["sv"]="Bilaga ", ["tk"]="Goşmaça ", ["tr"]="", ["ua"]="", @@ -1348,16 +1423,16 @@ data.labels={ ["labels"]={ ["af"]="", ["ar"]="في صفحة ", - ["ca"]="a la pagina", + ["ca"]="a la pagina ", ["cs"]="na straně ", ["da"]="på side ", ["de"]="auf Seite ", ["en"]="at page ", - ["eo"]="je paĝo", + ["eo"]="je paĝo ", ["es"]="en la página ", ["et"]="leheküljel ", ["fa"]="در صفحه ", - ["fi"]="sivulla", + ["fi"]="sivulla ", ["fr"]="à la page ", ["gr"]="", ["hr"]="na stranici ", @@ -1371,7 +1446,7 @@ data.labels={ ["nl"]="op pagina ", ["nn"]="på side ", ["pl"]="na stronie ", - ["pt"]="", + ["pt"]="na pagina", ["ro"]="", ["ru"]="на странице ", ["sk"]="na strane ", @@ -1495,13 +1570,13 @@ data.labels={ ["da"]="", ["de"]="Kapitel ", ["en"]="Chapter ", - ["eo"]="Ĉapitro", + ["eo"]="Ĉapitro ", ["es"]="Capítulo ", ["et"]="Peatükk ", ["fa"]="فصل ", ["fi"]="luku", ["fr"]="Chapitre ", - ["gr"]="Κεφάλαιο", + ["gr"]="Κεφάλαιο ", ["hr"]="Poglavlje ", ["hu"]={ "", " fejezet" }, ["hy"]="Գլուխ ", @@ -1515,15 +1590,15 @@ data.labels={ ["nl"]="", ["nn"]="", ["pl"]="Rozdział ", - ["pt"]="", + ["pt"]="Capitulo ", ["ro"]="", ["ru"]="", ["sk"]="Kapitola ", ["sl"]="Poglavje ", ["sr"]="Глава ", ["sr-latn"]="Glava ", - ["sv"]="", - ["tk"]="Bap", + ["sv"]="Kapitel ", + ["tk"]="Bap ", ["tr"]="", ["ua"]="", ["vi"]="Chương ", @@ -1557,25 +1632,31 @@ data.labels={ ["nl"]=" (vervolgd)", ["nn"]="", ["pl"]="", - ["pt"]="", + ["pt"]=" (continua)", ["ro"]="", ["ru"]="", ["sk"]=" (pokračovanie)", ["sl"]="", ["sr"]=" (наставак)", ["sr-latn"]=" (nastavak)", - ["sv"]="", + ["sv"]=" (forts.)", ["tk"]="", ["tr"]="", ["ua"]="", ["vi"]="", }, }, + ["day:genetiv"]={ + ["labels"]={ + ["cs"]="dne", + ["sk"]="dňa", + }, + }, ["day"]={ ["labels"]={ ["bg"]="ден", ["ca"]="dia", - ["cs"]="den", -- {"den", "dne" } + ["cs"]="den", ["de"]="Tag", ["en"]="day", ["eo"]="tago", @@ -1587,9 +1668,11 @@ data.labels={ ["kr"]="일", ["mk"]="ден", ["nl"]="dag", - ["sk"]="deň", -- {"deň", "dňa" } + ["pt"]="dia", + ["sk"]="deň", ["sr"]="дан", ["sr-latn"]="dan", + ["sv"]="dag", }, }, ["december"]={ @@ -1788,8 +1871,8 @@ data.labels={ ["labels"]={ ["af"]="Figuur ", ["ar"]="شكل ", - ["be"]="Малюнак", - ["bg"]="Фигура", + ["be"]="Малюнак ", + ["bg"]="Фигура ", ["ca"]="Figura ", ["cn"]="图 ", ["cs"]="Obrázek ", @@ -1802,7 +1885,7 @@ data.labels={ ["fa"]="شکل ", ["fi"]="Kuva ", ["fr"]="Figure ", - ["gr"]="Σχήμα", + ["gr"]="Σχήμα ", ["hr"]="Slika ", ["hu"]={ "", " ábra" }, ["hy"]="Նկար ", @@ -1824,7 +1907,7 @@ data.labels={ ["sr"]="Слика ", ["sr-latn"]="Slika ", ["sv"]="Figur ", - ["tk"]="Surat", + ["tk"]="Surat ", ["tr"]="Şekil ", ["ua"]="Малюнок ", ["vi"]="Hình ", @@ -1838,7 +1921,9 @@ data.labels={ ["eo"]="sekvv", ["fr"]=hairspace .. "sqq", ["hy"]="ff.", + ["pt"]="seg", ["sk"]="násl.", + ["sv"]="ff.", }, }, ["following:singular"]={ @@ -1849,7 +1934,9 @@ data.labels={ ["eo"]="sekv", ["fr"]=hairspace .. "sq", ["hy"]="f.", + ["pt"]="seg", ["sk"]="násl.", + ["sv"]="f.", }, }, ["followingpage"]={ @@ -1867,9 +1954,11 @@ data.labels={ ["hy"]="Հաջորդ էջում", ["mk"]="на следната страница", ["nl"]="op een volgende bladzijde", + ["pt"]="pagina seguinte", ["sk"]="na nasledujúcej strane", ["sr"]="на следећој страници", ["sr-latn"]="na sledećoj stranici", + ["sv"]="på nästa sida", }, }, ["friday"]={ @@ -1947,16 +2036,16 @@ data.labels={ ["da"]="Grafik ", ["de"]="Grafik ", ["en"]="Graphic ", - ["eo"]="Grafiko", + ["eo"]="Grafiko ", ["es"]="Gráfico ", ["et"]="Pilt ", ["fa"]="طرح ", ["fi"]="Grafiikka ", ["fr"]="Illustration ", - ["gr"]="Γραφικό", + ["gr"]="Γραφικό ", ["hr"]="Slika ", ["hu"]={ "", " kép" }, - ["hy"]="Գրաֆ", + ["hy"]="Գրաֆ ", ["it"]="Grafico ", ["ja"]="イラスト", ["la"]="Typus ", @@ -1974,10 +2063,10 @@ data.labels={ ["sr"]="График ", ["sr-latn"]="Grafik ", ["sv"]="Grafik ", - ["tk"]="Grafik", - ["tr"]="Grafik", + ["tk"]="Grafik ", + ["tr"]="Grafik ", ["ua"]="График ", - ["vi"]="Đồ thị", + ["vi"]="Đồ thị ", }, }, ["hencefore"]={ @@ -1986,10 +2075,10 @@ data.labels={ ["ar"]="كما وضحنا سابقا", ["be"]="гл. вышэй", ["bg"]="виж по-горе", - ["ca"]="com es mostra dalt ", + ["ca"]="com es mostra dalt", ["cs"]="viz výše", ["da"]="se foroven", - ["de"]="siehe oben", -- better "oben"? + ["de"]="siehe oben", ["en"]="as we show above", ["eo"]="laŭsupre", ["es"]="como se muestra arriba", @@ -2010,7 +2099,7 @@ data.labels={ ["nl"]="hierboven", ["nn"]="som vist over", ["pl"]="jak pokazano wyżej", - ["pt"]="", + ["pt"]="como mostrado em cima", ["ro"]="", ["ru"]="см. выше", ["sk"]="pozri hore", @@ -2033,7 +2122,7 @@ data.labels={ ["ca"]="com es mostra baix", ["cs"]="viz níže", ["da"]="se forneden", - ["de"]="siehe unten", -- better "nachstehend"? + ["de"]="siehe unten", ["en"]="as we show below", ["eo"]="laŭsube", ["es"]="como se muestra abajo", @@ -2054,7 +2143,7 @@ data.labels={ ["nl"]="hieronder", ["nn"]="som vist under", ["pl"]="jak pokazano niżej", - ["pt"]="", + ["pt"]="como mostrado em baixo", ["ro"]="", ["ru"]="см. ниже", ["sk"]="pozri ďalej", @@ -2080,15 +2169,15 @@ data.labels={ ["da"]="Intermezzo ", ["de"]="Intermezzo ", ["en"]="Intermezzo ", - ["eo"]="Intermezo", + ["eo"]="Intermezo ", ["es"]="Intermedio ", ["et"]="Vahemäng ", ["fi"]="Intermezzo ", ["fr"]="Intermède ", - ["gr"]="Παύση", + ["gr"]="Παύση ", ["hr"]="Intermeco ", ["hu"]={ "", " intermezzo" }, - ["hy"]="Ինտերմեցո", + ["hy"]="Ինտերմեցո ", ["it"]="Intermezzo ", ["ja"]="間奏曲", ["kr"]="간주곡", @@ -2107,10 +2196,10 @@ data.labels={ ["sr"]="Дигресија ", ["sr-latn"]="Digresija ", ["sv"]="Intermezzo ", - ["tk"]="Arakesme", + ["tk"]="Arakesme ", ["tr"]="", ["ua"]="Вставка ", - ["vi"]="intermezzo", + ["vi"]="Intermezzo ", }, }, ["january"]={ @@ -2423,7 +2512,7 @@ data.labels={ ["fa"]="سطر ", ["fi"]="rivi ", ["fr"]="ligne ", - ["gr"]="Γραμμή", + ["gr"]="Γραμμή ", ["hr"]="redak ", ["hu"]={ "", " sor" }, ["hy"]="Տող ", @@ -2445,7 +2534,7 @@ data.labels={ ["sr"]="линија ", ["sr-latn"]="linija ", ["sv"]="rad ", - ["tk"]="setir", + ["tk"]="setir ", ["tr"]="satır ", ["ua"]="рядок ", ["vi"]="dòng ", @@ -2469,7 +2558,7 @@ data.labels={ ["fa"]="سطرهای ", ["fi"]="rivie ", ["fr"]="lignes ", - ["gr"]="Γραμμές", + ["gr"]="Γραμμές ", ["hr"]="retci ", ["hu"]="sorok ", ["hy"]="Տողեր ", @@ -2491,7 +2580,7 @@ data.labels={ ["sr"]="линије ", ["sr-latn"]="linije ", ["sv"]="rader ", - ["tk"]="setirler", + ["tk"]="setirler ", ["tr"]="satırlar ", ["ua"]="рядки ", ["vi"]="dòng ", @@ -2759,6 +2848,7 @@ data.labels={ ["be"]="месяц", ["bg"]="месец", ["ca"]="mes", + ["cs"]="měsíc", ["de"]="Monat", ["en"]="month", ["eo"]="monato", @@ -2771,8 +2861,11 @@ data.labels={ ["kr"]="월", ["mk"]="месец", ["nl"]="maand", + ["pt"]="mes", + ["sk"]="mesiac", ["sr"]="месец", ["sr-latn"]="mesec", + ["sv"]="månad", }, }, ["november"]={ @@ -2973,7 +3066,7 @@ data.labels={ ["af"]="", ["ar"]="صفحة ", ["be"]="старонка ", - ["bg"]="страна", + ["bg"]="страна ", ["ca"]="pagina ", ["cs"]="strana ", ["da"]="Side ", @@ -2983,7 +3076,7 @@ data.labels={ ["es"]="página ", ["et"]="lehekülg ", ["fa"]="صفحه ", - ["fi"]="Sivu", + ["fi"]="Sivu ", ["fr"]="page ", ["gr"]="", ["hr"]="stranica ", @@ -2998,7 +3091,7 @@ data.labels={ ["nl"]="pagina ", ["nn"]="side ", ["pl"]="strona ", - ["pt"]="", + ["pt"]="pagina ", ["ro"]="", ["ru"]="страница ", ["sk"]="strana ", @@ -3030,7 +3123,7 @@ data.labels={ ["fa"]="قسمت ", ["fi"]="Osa ", ["fr"]="Partie ", - ["gr"]="Μέρος", + ["gr"]="Μέρος ", ["hr"]="Dio ", ["hu"]={ "", " rész" }, ["hy"]="Մաս ", @@ -3039,10 +3132,9 @@ data.labels={ ["kr"]={ "제", "부" }, ["la"]="Pars ", ["lt"]={ "", " dalis" }, - ["mk"]="Дел ", ["nb"]="Del ", ["nl"]="Deel ", - ["nn"]="Del", + ["nn"]="Del ", ["pl"]="Część ", ["pt"]="Parte ", ["ro"]="Partea ", @@ -3052,7 +3144,7 @@ data.labels={ ["sr"]="Део ", ["sr-latn"]="Deo ", ["sv"]="Del ", - ["tk"]="Bölüm", + ["tk"]="Bölüm ", ["tr"]="Cilt ", ["ua"]="Частина ", ["vi"]="Phần ", @@ -3060,9 +3152,10 @@ data.labels={ }, ["precedingpage"]={ ["labels"]={ + ["comment"]=[[ "auf der vorigen Seite" ok, but not "auf einer vorigen Seite" ]], ["ca"]="en una pagina anterior", ["cs"]="na předchozí straně", - ["de"]="oben", -- "auf der vorigen Seite" ok, but not "auf einer vorigen Seite" + ["de"]="oben", ["en"]="on a preceding page", ["eo"]="sur antaŭa paĝo", ["es"]="en la pagina anterior", @@ -3073,9 +3166,11 @@ data.labels={ ["hy"]="նախորդ էջ", ["mk"]="на претходната страница", ["nl"]="op een voorgaande bladzijde", + ["pt"]="na seguinte pagina", ["sk"]="na predchádzajúcej strane", ["sr"]="на претходној страници", ["sr-latn"]="na prethodnoj stranici", + ["sv"]="på föregående sida", }, }, ["saturday"]={ @@ -3151,14 +3246,14 @@ data.labels={ ["cs"]="Sekce ", ["da"]="", ["de"]="Abschnitt ", - ["en"]="Section", + ["en"]="Section ", ["eo"]="Sekcio ", ["es"]="Sección ", ["et"]="jaos ", ["fa"]="بخش ", - ["fi"]="Osio", + ["fi"]="Osio ", ["fr"]="Section ", - ["gr"]="Ενότητα", + ["gr"]="Ενότητα ", ["hr"]="Odjeljak ", ["hu"]="Fejezet ", ["hy"]="Բաժին ", @@ -3179,7 +3274,7 @@ data.labels={ ["sl"]="", ["sr"]="Одељак ", ["sr-latn"]="Odeljak ", - ["sv"]="", + ["sv"]="Avsnitt", ["tk"]="", ["tr"]="", ["ua"]="", @@ -3191,7 +3286,7 @@ data.labels={ ["af"]="", ["ar"]="انظر ", ["be"]="гл. ", - ["bg"]="погледни", + ["bg"]="погледни ", ["ca"]="vore ", ["cs"]="viz ", ["da"]="se ", @@ -3201,7 +3296,7 @@ data.labels={ ["es"]="ver: ", ["et"]="vaadake ", ["fa"]="نگاه کنید به ", - ["fi"]="Katso", + ["fi"]="katso ", ["fr"]="cf. ", ["gr"]="", ["hr"]="vidi ", @@ -3216,7 +3311,7 @@ data.labels={ ["nl"]="zie ", ["nn"]="sjå ", ["pl"]="patrz ", - ["pt"]="", + ["pt"]="ver ", ["ro"]="", ["ru"]="см. ", ["sk"]="pozri ", @@ -3337,14 +3432,14 @@ data.labels={ ["cs"]="Podsekce ", ["da"]="", ["de"]="Unterabschnitt ", - ["en"]="Subsection", + ["en"]="Subsection ", ["eo"]="Subsekcio ", ["es"]="Subsección ", ["et"]="alajaotis ", ["fa"]="زیربخش ", ["fi"]="Alajakso", ["fr"]="Soussection ", - ["gr"]="Υπόενότητα", + ["gr"]="Υπόενότητα ", ["hr"]="Pododjeljak ", ["hu"]="Alfejezet ", ["hy"]=" Ենթաբաժին ", @@ -3357,14 +3452,14 @@ data.labels={ ["nl"]="", ["nn"]="", ["pl"]="Podpodrozdział ", - ["pt"]="", + ["pt"]="Subsecçao ", ["ro"]="", ["ru"]="", ["sk"]="Podsekcia ", ["sl"]="", ["sr"]="Пододељак ", ["sr-latn"]="Pododeljak ", - ["sv"]="", + ["sv"]="Underavsnitt", ["tk"]="", ["tr"]="", ["ua"]="", @@ -3382,12 +3477,12 @@ data.labels={ ["cs"]="Podpodsekce ", ["da"]="", ["de"]="Unterunterabschnitt ", - ["en"]="Subsubsection", + ["en"]="Subsubsection ", ["eo"]="Subsubsekcio ", ["es"]="Subsubsección ", ["et"]="alamjaotis ", ["fa"]="زیرزیربخش ", - ["fi"]="Alakohta", + ["fi"]="Alakohta ", ["fr"]="Soussoussection ", ["gr"]="", ["hr"]="Podpododjeljak ", @@ -3402,14 +3497,14 @@ data.labels={ ["nl"]="", ["nn"]="", ["pl"]="", - ["pt"]="", + ["pt"]="Subsubsecçao ", ["ro"]="", ["ru"]="", ["sk"]="Podpodsekcia ", ["sl"]="", ["sr"]="Подпододељак ", ["sr-latn"]="Podpododeljak ", - ["sv"]="", + ["sv"]="Underunderavsnitt", ["tk"]="", ["tr"]="", ["ua"]="", @@ -3426,13 +3521,13 @@ data.labels={ ["cn"]="", ["cs"]="Podpodpodsekce ", ["da"]="", - ["de"]="Unterunterunterabschnitt", - ["en"]="Subsubsubsection", + ["de"]="Unterunterunterabschnitt ", + ["en"]="Subsubsubsection ", ["eo"]="Subsubsubsekcio ", ["es"]="Subsubsubsección ", ["et"]="", ["fa"]="زیرزیرزیربخش ", - ["fi"]="Ala-alakohta", + ["fi"]="Ala-alakohta ", ["fr"]="Soussoussoussection ", ["gr"]="", ["hr"]="Podpodpododjeljak ", @@ -3447,7 +3542,7 @@ data.labels={ ["nl"]="", ["nn"]="", ["pl"]="", - ["pt"]="", + ["pt"]="Subsubsubsecçao ", ["ro"]="", ["ru"]="", ["sk"]="Podpodpodsekcia ", @@ -3541,7 +3636,7 @@ data.labels={ ["fa"]="جدول ", ["fi"]="Taulukko ", ["fr"]="Tableau ", - ["gr"]="Πίνακας", + ["gr"]="Πίνακας ", ["hr"]="Tablica ", ["hu"]={ "", " táblázat" }, ["hy"]="Աղյուսակ ", @@ -3563,7 +3658,7 @@ data.labels={ ["sr"]="Табела ", ["sr-latn"]="Tabela ", ["sv"]="Tabell ", - ["tk"]="Tablisa", + ["tk"]="Tablisa ", ["tr"]="Tablo ", ["ua"]="Таблиця ", ["vi"]="Bảng ", @@ -3775,9 +3870,11 @@ data.labels={ ["kr"]="년", ["mk"]="година", ["nl"]="jaar", + ["pt"]="ano", ["sk"]="rok", ["sr"]="година", ["sr-latn"]="godina", + ["sv"]="år", }, }, }, @@ -3790,7 +3887,7 @@ data.labels={ ["bg"]="Съкращения", ["ca"]="Abreviacions", ["cn"]="缩略语", - ["cs"]="Seznam zkratek", --"Zkratky" + ["cs"]="Seznam zkratek", ["da"]="Forkortelser", ["de"]="Abkürzungen", ["en"]="Abbreviations", @@ -3817,7 +3914,7 @@ data.labels={ ["pt"]="Abreviaturas", ["ro"]="Abrevieri", ["ru"]="Список сокращений", - ["sk"]="Zoznam skratiek", -- "Skratky" + ["sk"]="Zoznam skratiek", ["sl"]="Kratice", ["sr"]="Скраћенице", ["sr-latn"]="Skraćenice", @@ -4129,14 +4226,14 @@ data.labels={ ["nl"]="Literatuur", ["nn"]="", ["pl"]="Bibliografia", - ["pt"]="", + ["pt"]="Referencias", ["ro"]="", ["ru"]="", ["sk"]="Literatúra", ["sl"]="Literatura", ["sr"]="Литература", ["sr-latn"]="Literatura", - ["sv"]="", + ["sv"]="Litteraturförteckning", ["tk"]="", ["tr"]="", ["ua"]="", diff --git a/tex/context/base/mkiv/phys-dim.lua b/tex/context/base/mkiv/phys-dim.lua index 91803e4fd..fa9f3f308 100644 --- a/tex/context/base/mkiv/phys-dim.lua +++ b/tex/context/base/mkiv/phys-dim.lua @@ -452,7 +452,7 @@ local short_units = { -- I'm not sure about casing s = "second", g = "gram", n = "newton", - v = "volt", + V = "volt", t = "tonne", l = "liter", -- w = "watt", @@ -460,6 +460,12 @@ local short_units = { -- I'm not sure about casing -- a = "ampere", A = "ampere", + Ω = "ohm", + +-- C = "coulomb", -- needs checking with (c)enti +-- K = "kelvin", -- needs checking with (k)ilo +-- N = "newton", -- needs checking with (n)ewton + min = "minute", [utfchar(0x2103)] = "celsius", diff --git a/tex/context/base/mkiv/publ-imp-apa.lua b/tex/context/base/mkiv/publ-imp-apa.lua index 65dee0717..6e0520e10 100644 --- a/tex/context/base/mkiv/publ-imp-apa.lua +++ b/tex/context/base/mkiv/publ-imp-apa.lua @@ -95,14 +95,11 @@ categories.article = { "year", "subtitle", "type", "file", "journal", "volume", "number", "pages", - "doi", "note", + "doi", "issn", "note", -- APA ignores this: -- -- "month", -- - -- fields defined in jabref but presently ignored: - -- - -- "issn", }, } @@ -120,7 +117,7 @@ categories.magazine = { "subtitle", "type", "file", "number", "month", "day", - "doi", "note", + "doi", "issn", "note", }, } @@ -142,7 +139,7 @@ categories.periodical = { "subtitle", "file", "series", "volume", "number", "month", "organization", - "doi", "note", + "doi", "issn", "note", }, } @@ -157,7 +154,7 @@ categories.standard = { "author", "year", "title", "subtitle", - "doi", "note", + "doi", "isbn", "note", }, optional = { "withauthor", "translator", @@ -181,7 +178,7 @@ categories.book = { "subtitle", "type", "file", "editionset", "series", "address", - "doi", "note", + "doi", "isbn", "note", "abstract", }, } @@ -208,7 +205,7 @@ categories.inbook = { "editionset", "series", "month", "address", - "doi", "note", + "doi", "isbn", "note", }, } @@ -236,7 +233,7 @@ categories.incollection = { -- APA ignores this: "chapter", "month", "address", - "doi", "note", + "doi", "isbn", "note", }, } @@ -257,7 +254,7 @@ categories.booklet = { "year", "month", "subtitle", "type", "file", "address", - "doi", "note", + "doi", "isbn", "note", }, } @@ -281,7 +278,7 @@ categories.proceedings = { "editionset", "series", "month", "address", - "doi", "note", + "doi", "isbn", "note", }, } @@ -296,7 +293,7 @@ categories.inproceedings = { "month", "edition", "series", "address", "organization", - "doi", "note", + "doi", "isbn", "note", }, } @@ -320,7 +317,7 @@ categories.thesis = { "subtitle", "file", "month", "address", - "doi", "note", + "doi", "isbn", "note", }, } @@ -338,7 +335,7 @@ categories.mastersthesis = { "subtitle", "file", "month", "address", - "doi", "note", + "doi", "isbn", "note", }, } categories.phdthesis = categories.mastersthesis @@ -365,7 +362,7 @@ categories.techreport = { "subtitle", "file", "editionset", "month", - "doi", "note", + "doi", "isbn", "note", }, } @@ -387,7 +384,7 @@ categories.manual = { "address", "subtitle", "file", "editionset", "month", "year", - "doi", "note", + "doi", "isbn", "note", -- "abstract", }, } @@ -515,7 +512,7 @@ categories.misc = { "title", "subtitle", "file", "year", "month", "howpublished", - "doi", "note", + "doi", "isbn", "note", }, } @@ -533,7 +530,7 @@ categories.other = { optional = { "withauthor", "translator", "subtitle", "file", - "doi", "note", + "doi", "isbn", "note", }, } diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi index c4ea0a7f0..b8038bd96 100644 --- a/tex/context/base/mkiv/publ-imp-apa.mkvi +++ b/tex/context/base/mkiv/publ-imp-apa.mkvi @@ -112,6 +112,14 @@ [apa:\s!list:doi] [apa:\s!list] +\definebtx + [apa:\s!list:isbn] + [apa:\s!list] + +\definebtx + [apa:\s!list:issn] + [apa:\s!list] + \definebtx [apa:\s!list:\s!page] [apa:\s!list] @@ -520,6 +528,14 @@ [apa:\s!cite:doi] [apa:\s!cite:url] +\definebtx + [apa:\s!cite:isbn] + [apa:\s!cite] + +\definebtx + [apa:\s!cite:issn] + [apa:\s!cite] + \definebtx [apa:\s!cite:num] [apa:\s!cite] @@ -879,6 +895,11 @@ \endgroup % which namespace? %\doif{\btxparameter{translate}}\v!yes { + % + % An option is unnecessary because the translated title + % only gets placed if the user includes a title:xx field + % for the entry - not standard for bibtex... + % \texdefinition{btx:apa:translated-title}{#title} %} \btxstopstyleandcolor @@ -888,7 +909,7 @@ \setmode{btx:apa:title-placed} % we make the title active, opening "file" \btxdoifelse {file} { - \texdefinition{btx:format:goto} + \texdefinition{btx:format:inject} {url(file:\btxflush{file})} { \texdefinition{btx:apa:composed-title}{title} @@ -1050,7 +1071,8 @@ \starttexdefinition mutable protected btx:apa:authoryear % we make the authoryear active, pointing to the citation - \texdefinition{btx:format:gotointernal} + \texdefinition{btx:format:inject} + {internal(\currentbtxinternal)} { \doifelsesetups{apa:list:sameauthor} { \btxdoifelsesameasprevious {author} { @@ -1139,7 +1161,12 @@ } \btxdoif {edition} { \texdefinition{btx:apa:leftparenthesis-or-comma} - \btxflush{edition} + % the edition= field is often language-dependent + % (i.e. second, 2nd, revised, etc.) + % so we handle an optional edition:xx= field: + \btxdoifelse {edition:\mainbtxlanguage} + {\btxflush{edition:\mainbtxlanguage}} + {\btxflush{edition}} \btxspace \btxlabeltext{apa:edition} } @@ -1260,11 +1287,15 @@ \starttexdefinition mutable protected btx:apa:url \begingroup \setbreakpoints[doi] - \texdefinition {btx:format:goto} { - url(\btxflush{url}) - } { + \ifconditional\btxinteractive + \goto { + \hyphenatedurl{\btxflush{url}} + } [ + url(\btxflush{url}) + ] + \else \hyphenatedurl{\btxflush{url}} - } + \fi \endgroup \stoptexdefinition @@ -1273,11 +1304,15 @@ \starttexdefinition mutable protected btx:apa:doi \begingroup \setbreakpoints[doi] - \texdefinition {btx:format:goto} { - url(http://dx.doi.org/\btxflush{doi}) - } { + \ifconditional\btxinteractive + \goto { + \hyphenatedurl{doi:\btxflush{doi}} + } [ + url(http://dx.doi.org/\btxflush{doi}) + ] + \else \hyphenatedurl{doi:\btxflush{doi}} - } + \fi \endgroup \stoptexdefinition @@ -1300,6 +1335,14 @@ \btxspace \texdefinition{btx:apa:doi} } + \btxdoif {issn} { + \btxspace + issn\colon\btxflush{issn} + } + \btxdoif {isbn} { + \btxspace + isbn\colon\btxflush{isbn} + } \texdefinition{btx:apa:note} \removeunwantedspaces \stoptexdefinition diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index dddda9577..d4b423224 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 087e77bf3..ee377dae7 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua index 36daef816..9d2e8356d 100644 --- a/tex/context/base/mkiv/util-sac.lua +++ b/tex/context/base/mkiv/util-sac.lua @@ -551,14 +551,14 @@ if bit32 and not streams.tocardinal1 then local char = string.char streams.tocardinal1 = char - function streams.tocardinal2(n) return char(extract( 8,8),extract( 0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract( 8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal2(n) return char(extract(n, 8,8),extract(n, 0,8)) end + function streams.tocardinal3(n) return char(extract(n,16,8),extract(n, 8,8),extract(n,0,8)) end + function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end streams.tocardinal1le = char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end + function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end + function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end + function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end end diff --git a/tex/context/base/mkiv/util-sbx.lua b/tex/context/base/mkiv/util-sbx.lua index 066ca3023..65f6703ae 100644 --- a/tex/context/base/mkiv/util-sbx.lua +++ b/tex/context/base/mkiv/util-sbx.lua @@ -394,7 +394,7 @@ local runners = { if trace then report("resultof: %s",command) end - local handle = iopopen(command,"r") -- already has flush + local handle = iopopen(command,"rb") -- already has flush if handle then local result = handle:read("*all") or "" handle:close() diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 23dc6bbef..030a373aa 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2023.04.27 16:54} +\newcontextversion{2023.05.05 18:36} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 9ee1d3803..4cfa73091 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2023.04.27 16:54} +\immutable\edef\contextversion{2023.05.05 18:36} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/data-sch.lmt b/tex/context/base/mkxl/data-sch.lmt new file mode 100644 index 000000000..36f89040c --- /dev/null +++ b/tex/context/base/mkxl/data-sch.lmt @@ -0,0 +1,312 @@ +if not modules then modules = { } end modules ['data-sch'] = { + 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" +} + +local load, tonumber, require = load, tonumber, require +local gsub, format = string.gsub, string.format +local savedata = io.savedata +local sortedhash, concat = table.sortedhash, table.concat +local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders +local addsuffix, suffix, splitbase = file.addsuffix, file.suffix, file.splitbase +local md5hex = md5.hex +local removefile, renamefile, fileexists = os.remove, os.rename, io.exists + +-- todo: more locals + +local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end) +local report_schemes = logs.reporter("resolvers","schemes") + +local http = require("socket.http") +local ltn12 = require("ltn12") + +if mbox then mbox = nil end -- useless and even bugged (helper overwrites lib) + +local resolvers = resolvers +local schemes = resolvers.schemes or { } +resolvers.schemes = schemes + +local cleaners = { } +schemes.cleaners = cleaners + +local threshold = 24 * 60 * 60 +local inmemory = false +local uselibrary = false + +directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end) +directives.register("schemes.inmemory", function(v) inmemory = v end) +directives.register("schemes.uselibrary", function(v) uselibrary = v end) + +function cleaners.none(specification) + return specification.original +end + +-- function cleaners.strip(specification) +-- -- todo: only keep suffix periods, so after the last +-- return (gsub(specification.original,"[^%a%d%.]+","-")) -- so we keep periods +-- end + +function cleaners.strip(specification) -- keep suffixes + local path, name = splitbase(specification.original) + if path == "" then + return (gsub(name,"[^%a%d%.]+","-")) + else + return (gsub((gsub(path,"%.","-") .. "-" .. name),"[^%a%d%.]+","-")) + end +end + +function cleaners.md5(specification) + return addsuffix(md5hex(specification.original),suffix(specification.path)) +end + +local cleaner = cleaners.strip + +directives.register("schemes.cleanmethod", function(v) cleaner = cleaners[v] or cleaners.strip end) + +function resolvers.schemes.cleanname(specification) + local hash = cleaner(specification) + if trace_schemes then + report_schemes("hashing %a to %a",specification.original,hash) + end + return hash +end + +local cached = { } +local loaded = { } +local reused = { } +local thresholds = { } +local handlers = { } + +local function fetcher(report) + if uselibrary then + local curl = require("curl") or require("libs-imp-curl") -- we have curl preloaded + local fetch = curl and curl.fetch + if fetch then + return function(str) + local data, message = fetch { + url = str, + followlocation = true, + sslverifyhost = false, + sslverifypeer = false, + } + if not data then + report("some error: %s",message) + end + return data + end + end + end +end + +local runner = sandbox.registerrunner { + name = "to file curl resolver", + method = "execute", + program = "curl", + template = '--silent --insecure --create-dirs --output "%cachename%" "%original%"', + internal = function(specification) + local fetch = fetcher(specification.reporter) + return fetch and function(name,program,template,checkers,defaults,variables,reporter,finalized) + local data = fetch(variables.original) + savedata(variables.cachename,data or "") + end + end, + checkers = { + cachename = "cache", + original = "url", + } +} + +local memrunner = sandbox.registerrunner { + name = "in memory curl resolver", + method = "resultof", + program = "curl", + template = '--silent --insecure "%original%"', + internal = function(specification) + local fetch = fetcher(specification.reporter) + return fetch and function(name,program,template,checkers,defaults,variables,reporter,finalized) + return fetch(variables.original) or "" + end + end, + checkers = { + original = "url", + } +} + +local function fetch(specification) + local original = specification.original + local scheme = specification.scheme + local cleanname = schemes.cleanname(specification) + if inmemory then + statistics.starttiming(schemes) + local cachename = resolvers.savers.virtualname(cleanname) + local handler = handlers[scheme] + -- if handler and not uselibrary then + if handler then -- internal sockets are twice as fast as library + if trace_schemes then + report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in") + end + logs.flush() + handler(specification,cachename) + else + if trace_schemes then + report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl") + end + logs.flush() + local result = memrunner { + original = original, + } + resolvers.savers.directvirtual(cachename,result,true) -- persistent + end + loaded[scheme] = loaded[scheme] + 1 + statistics.stoptiming(schemes) + return cachename + else + local cachename = caches.setfirstwritablefile(cleanname,"schemes") + if not cached[original] or threshold == 0 then + statistics.starttiming(schemes) + if threshold == 0 or not fileexists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then + -- removefile(cachename) + cached[original] = cachename + local handler = handlers[scheme] + if handler then + if trace_schemes then + report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in") + end + logs.flush() + handler(specification,cachename) + else + if trace_schemes then + report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl") + end + logs.flush() + runner { + original = original, + cachename = cachename, + } + end + end + if fileexists(cachename) then + cached[original] = cachename + if trace_schemes then + report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename) + end + else + cached[original] = "" + if trace_schemes then + report_schemes("using missing %a, protocol %a",original,scheme) + end + end + loaded[scheme] = loaded[scheme] + 1 + statistics.stoptiming(schemes) + else + if trace_schemes then + report_schemes("reusing %a, protocol %a",original,scheme) + end + reused[scheme] = reused[scheme] + 1 + end + return cached[original] + end +end + +local function finder(specification,filetype) + return resolvers.methodhandler("finders",fetch(specification),filetype) +end + +local opener = openers.file +local loader = loaders.file + +local function install(scheme,handler,newthreshold) + handlers [scheme] = handler + loaded [scheme] = 0 + reused [scheme] = 0 + finders [scheme] = finder + openers [scheme] = opener + loaders [scheme] = loader + thresholds[scheme] = newthreshold or threshold +end + +schemes.install = install + +local function http_handler(specification,cachename) + if inmemory then + local result = { } + local status, message = http.request { + url = specification.original, + sink = ltn12.sink.table(result) + } + resolvers.savers.directvirtual(cachename,concat(result),true) -- persistent + else + local tempname = cachename .. ".tmp" + local handle = io.open(tempname,"wb") + local status, message = http.request { + url = specification.original, + sink = ltn12.sink.file(handle) + } + if not status then + removefile(tempname) + else + removefile(cachename) + renamefile(tempname,cachename) + end + end + return cachename +end + +install('http',http_handler) +install('https') -- see pod +install('ftp') + +statistics.register("scheme handling time", function() + local l, r, nl, nr = { }, { }, 0, 0 + for k, v in sortedhash(loaded) do + if v > 0 then + nl = nl + 1 + l[nl] = k .. ":" .. v + end + end + for k, v in sortedhash(reused) do + if v > 0 then + nr = nr + 1 + r[nr] = k .. ":" .. v + end + end + local n = nl + nr + if n > 0 then + if nl == 0 then l = { "none" } end + if nr == 0 then r = { "none" } end + return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s", + statistics.elapsedtime(schemes), n, threshold, concat(l," "), concat(l," ")) + else + return nil + end +end) + +-- We provide a few more helpers: + +----- http = require("socket.http") +local httprequest = http.request +local toquery = url.toquery + +local function fetchstring(url,data) + local q = data and toquery(data) + if q then + url = url .. "?" .. q + end + local reply = httprequest(url) + return reply -- just one argument +end + +schemes.fetchstring = fetchstring + +function schemes.fetchtable(url,data) + local reply = fetchstring(url,data) + if reply then + local s = load("return " .. reply) + if s then + return s() + end + end +end diff --git a/tex/context/base/mkxl/data-vir.lmt b/tex/context/base/mkxl/data-vir.lmt index b78211fc9..75a8c68c0 100644 --- a/tex/context/base/mkxl/data-vir.lmt +++ b/tex/context/base/mkxl/data-vir.lmt @@ -20,26 +20,42 @@ local savers = resolvers.savers local cleaners = resolvers.cleaners local data = { } +local keep = { } local n = 0 -- hm, number can be query local f_virtual_n = formatters["virtual://%s.%s"] local f_virtual_y = formatters["virtual://%s-%s.%s"] -function savers.virtual(specification,content,suffix) +local function virtualname(specification,suffix) n = n + 1 -- one number for all namespaces local path = type(specification) == "table" and specification.path or specification if type(path) ~= "string" or path == "" then path = "virtualfile" end - local filename = suffix and f_virtual_y(path,n,suffix) or f_virtual_n(path,n) + return suffix and f_virtual_y(path,n,suffix) or f_virtual_n(path,n) +end + +local function directvirtual(filename,content,persistent) + if not content then + content = "" + end if trace_virtual then - report_virtual("saver: file %a saved",filename) + report_virtual("saver: file %a saved, size %i",filename,#content) end - data[filename] = content + data[filename] = content or "" + keep[filename] = persistent return filename end +function savers.virtual(specification,content,suffix) + return directvirtual(virtualname(specification,suffix),content) +end + +savers.virtualname = virtualname +savers.directvirtual = directvirtual + function cleaners.virtual(filename) data[filename] = nil + keep[filename] = nil end local finders = resolvers.finders @@ -94,7 +110,10 @@ function loaders.virtual(specification) if trace_virtual then report_virtual("loader: file %a loaded",original) end - data[original] = nil + if not keep[original] then + data[original] = nil + keep[original] = nil + end return true, d, #d end if trace_virtual then diff --git a/tex/context/base/mkxl/lang-def.mkxl b/tex/context/base/mkxl/lang-def.mkxl index 04215a779..192c9c6f9 100644 --- a/tex/context/base/mkxl/lang-def.mkxl +++ b/tex/context/base/mkxl/lang-def.mkxl @@ -798,7 +798,7 @@ \c!rightquote=\upperrightsingleninequote, \c!leftquotation=\upperleftdoublesixquote, \c!rightquotation=\upperrightdoubleninequote, - \c!date={\v!year,\space,\v!month,\space,\v!day}] + \c!date={\v!day,\space,\v!month,\space,\v!year}] \installlanguage[\s!pt-br][\c!default=\s!pt] % Brazil \installlanguage[\s!es-es][\c!default=\s!es] % Spain diff --git a/tex/context/base/mkxl/lpdf-img.lmt b/tex/context/base/mkxl/lpdf-img.lmt index c241ccdb7..e7dc663d6 100644 --- a/tex/context/base/mkxl/lpdf-img.lmt +++ b/tex/context/base/mkxl/lpdf-img.lmt @@ -67,6 +67,7 @@ local zlibcompress = xzip.compress local zlibdecompress = xzip.decompress local trace = false +local cleanvirtual = resolvers.cleaners.virtual -- false -- for now local report_jpg = logs.reporter("graphics","jpg") local report_jp2 = logs.reporter("graphics","jp2") @@ -74,6 +75,8 @@ local report_png = logs.reporter("graphics","png") trackers.register("graphics.backend", function(v) trace = v end) +directives.register("graphics.cleanvirtuals", function(v) cleanvirtual = v and resolvers.cleaners.virtual or false end) + local injectors = { } lpdf.injectors = injectors @@ -158,6 +161,9 @@ do if trace then report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content) end + if cleanvirtual then + cleanvirtual(filename) + end return createimage { bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate transform = specification.transform, @@ -197,6 +203,9 @@ do if trace then report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content) end + if cleanvirtual then + cleanvirtual(filename) + end return createimage { bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate transform = specification.transform, @@ -1211,6 +1220,9 @@ do end local width = specification.width or xsize * 65536 local height = specification.height or ysize * 65536 + if cleanvirtual then + cleanvirtual(filename) + end return createimage { bbox = { 0, 0, width/xsize, height/ysize }, -- mandate transform = specification.transform, diff --git a/tex/context/base/mkxl/luat-lib.mkxl b/tex/context/base/mkxl/luat-lib.mkxl index cb161cafa..d701fd293 100644 --- a/tex/context/base/mkxl/luat-lib.mkxl +++ b/tex/context/base/mkxl/luat-lib.mkxl @@ -34,7 +34,7 @@ \registerctxluafile{util-sta}{} -\registerctxluafile{util-sbx}{} % needs tracker and templates +\registerctxluafile{util-sbx}{autosuffix} % needs tracker and templates \registerctxluafile{util-soc-imp-reset} {} \registerctxluafile{util-soc-imp-socket} {} @@ -66,7 +66,7 @@ \registerctxluafile{data-dec}{} \registerctxluafile{data-tar}{} %registerctxluafile{data-crl}{} -\registerctxluafile{data-sch}{} +\registerctxluafile{data-sch}{autosuffix} \registerctxluafile{data-tre}{} \registerctxluafile{data-lua}{} \registerctxluafile{data-ctx}{} diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index 2529890d7..f9b733d9c 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -4587,8 +4587,8 @@ \def\math_axis_inject_indeed#1% {\srule - \s!height \dimexpr\scratchdimentwo+\scratchdimenone\relax - \s!depth -\dimexpr\scratchdimentwo-\scratchdimenone\relax + \s!height \dimexpr(\scratchdimentwo+\scratchdimenone)*\c_math_m_scaled/\plusthousand\relax + \s!depth -\dimexpr(\scratchdimentwo-\scratchdimenone)*\c_math_m_scaled/\plusthousand\relax \s!attr \mathaxisattribute#1% \relax} diff --git a/tex/context/base/mkxl/phys-dim.lmt b/tex/context/base/mkxl/phys-dim.lmt index 8575962e9..d3b6f80ba 100644 --- a/tex/context/base/mkxl/phys-dim.lmt +++ b/tex/context/base/mkxl/phys-dim.lmt @@ -464,7 +464,7 @@ local short_units = { -- I'm not sure about casing s = "second", g = "gram", n = "newton", - v = "volt", + V = "volt", t = "tonne", l = "liter", -- w = "watt", @@ -472,6 +472,8 @@ local short_units = { -- I'm not sure about casing -- a = "ampere", A = "ampere", + Ω = "ohm", + -- C = "coulomb", -- needs checking with (c)enti -- K = "kelvin", -- needs checking with (k)ilo -- N = "newton", -- needs checking with (n)ewton diff --git a/tex/context/base/mkxl/util-sbx.lmt b/tex/context/base/mkxl/util-sbx.lmt new file mode 100644 index 000000000..b48d4a9f6 --- /dev/null +++ b/tex/context/base/mkxl/util-sbx.lmt @@ -0,0 +1,658 @@ +if not modules then modules = { } end modules ['util-sbx'] = { + 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" +} + +-- Note: we use expandname and collapsepath and these use chdir which is overloaded +-- so we need to use originals there. Just something to keep in mind. This is old +-- code that I might need to upgrade to fit lmtx better. I'll stepwise also try to +-- integrate e.g. curl and graphicmagick a bit more natural. Some code below can +-- be simplified because we don't share any longer with luatex. + +if not sandbox then require("l-sandbox") end -- for testing + +local next, type = next, type + +local replace = utilities.templates.replace +local collapsepath = file.collapsepath +local expandname = dir.expandname +local sortedhash = table.sortedhash +local lpegmatch = lpeg.match +local platform = os.type +local P, S, C = lpeg.P, lpeg.S, lpeg.C +local gsub = string.gsub +local lower = string.lower +local find = string.find +local concat = string.concat +local unquoted = string.unquoted +local optionalquoted = string.optionalquoted +local basename = file.basename +local nameonly = file.nameonly + +local sandbox = sandbox +local validroots = { } +local validrunners = { } +local validbinaries = true -- all permitted +local validlibraries = true -- all permitted +local validators = { } +local finalized = nil +local trace = false + +local p_validroot = nil +local p_split = lpeg.firstofsplit(" ") + +local report = logs.reporter("sandbox") + +trackers.register("sandbox",function(v) trace = v end) -- often too late anyway + +sandbox.setreporter(report) + +sandbox.finalizer { + category = "files", + action = function() + finalized = true + end +} + +local function registerroot(root,what) -- what == read|write + if finalized then + report("roots are already finalized") + else + if type(root) == "table" then + root, what = root[1], root[2] + end + if type(root) == "string" and root ~= "" then + root = collapsepath(expandname(root)) + if what == "r" or what == "ro" or what == "readable" then + what = "read" + elseif what == "w" or what == "wo" or what == "writable" then + what = "write" + end + -- true: read & write | false: read + validroots[root] = what == "write" or false + end + end +end + +sandbox.finalizer { + category = "files", + action = function() -- initializers can set the path + if p_validroot then + report("roots are already initialized") + else + sandbox.registerroot(".","write") -- always ok + -- also register texmf as read + for name in sortedhash(validroots) do + if p_validroot then + p_validroot = P(name) + p_validroot + else + p_validroot = P(name) + end + end + p_validroot = p_validroot / validroots + end + end +} + +local function registerbinary(name) + if finalized then + report("binaries are already finalized") + elseif type(name) == "string" and name ~= "" then + if not validbinaries then + return + end + if validbinaries == true then + validbinaries = { [name] = true } + else + validbinaries[name] = true + end + elseif name == true then + validbinaries = { } + end +end + +local function registerlibrary(name) + if finalized then + report("libraries are already finalized") + elseif type(name) == "string" and name ~= "" then + if not validlibraries then + return + end + if validlibraries == true then + validlibraries = { [nameonly(name)] = true } + else + validlibraries[nameonly(name)] = true + end + elseif name == true then + validlibraries = { } + end +end + +-- begin of validators + +local p_write = S("wa") p_write = (1 - p_write)^0 * p_write +local p_path = S("\\/~$%:") p_path = (1 - p_path )^0 * p_path -- be easy on other arguments + +local function normalized(name) -- only used in executers + if platform == "windows" then + name = gsub(name,"/","\\") + end + return name +end + +function sandbox.possiblepath(name) + return lpegmatch(p_path,name) and true or false +end + +local filenamelogger = false + +function sandbox.setfilenamelogger(l) + filenamelogger = type(l) == "function" and l or false +end + +local function validfilename(name,what) + if p_validroot and type(name) == "string" and lpegmatch(p_path,name) then + local asked = collapsepath(expandname(name)) + -- if platform == "windows" then + -- asked = lower(asked) -- we assume ascii names + -- end + local okay = lpegmatch(p_validroot,asked) + if okay == true then + -- read and write access + if filenamelogger then + filenamelogger(name,"w",asked,true) + end + return name + elseif okay == false then + -- read only access + if not what then + -- no further argument to io.open so a readonly case + if filenamelogger then + filenamelogger(name,"r",asked,true) + end + return name + elseif lpegmatch(p_write,what) then + if filenamelogger then + filenamelogger(name,"w",asked,false) + end + return -- we want write access + else + if filenamelogger then + filenamelogger(name,"r",asked,true) + end + return name + end + elseif filenamelogger then + filenamelogger(name,"*",name,false) + end + else + return name + end +end + +local function readable(name,finalized) +-- if platform == "windows" then -- yes or no +-- name = lower(name) -- we assume ascii names +-- end + return validfilename(name,"r") +end + +local function normalizedreadable(name,finalized) +-- if platform == "windows" then -- yes or no +-- name = lower(name) -- we assume ascii names +-- end + local valid = validfilename(name,"r") + if valid then + return normalized(valid) + end +end + +local function writeable(name,finalized) +-- if platform == "windows" then +-- name = lower(name) -- we assume ascii names +-- end + return validfilename(name,"w") +end + +local function normalizedwriteable(name,finalized) +-- if platform == "windows" then +-- name = lower(name) -- we assume ascii names +-- end + local valid = validfilename(name,"w") + if valid then + return normalized(valid) + end +end + +validators.readable = readable +validators.writeable = normalizedwriteable +validators.normalizedreadable = normalizedreadable +validators.normalizedwriteable = writeable +validators.filename = readable + +table.setmetatableindex(validators,function(t,k) + if k then + t[k] = readable + end + return readable +end) + +-- function validators.verbose(s) +-- return s +-- end + +function validators.string(s,finalized) + -- can be used to prevent filename checking (todo: only when registered) + if finalized and suspicious(s) then + return "" + else + return s + end +end + +function validators.cache(s) + if finalized then + return basename(s) + else + return s + end +end + +function validators.url(s) + if finalized and find("^file:") then + return "" + else + return s + end +end + +-- end of validators + +local function filehandlerone(action,one,...) + local checkedone = validfilename(one) + if checkedone then + return action(one,...) + else + -- report("file %a is unreachable",one) + end +end + +local function filehandlertwo(action,one,two,...) + local checkedone = validfilename(one) + if checkedone then + local checkedtwo = validfilename(two) + if checkedtwo then + return action(one,two,...) + else + -- report("file %a is unreachable",two) + end + else + -- report("file %a is unreachable",one) + end +end + +local function iohandler(action,one,...) + if type(one) == "string" then + local checkedone = validfilename(one) + if checkedone then + return action(one,...) + end + elseif one then + return action(one,...) + else + return action() + end +end + +-- runners can be strings or tables +-- +-- os.execute : string +-- os.exec : string or table with program in [0|1] -- no longer there +-- os.spawn : string or table with program in [0|1] -- no longer there +-- +-- our execute: registered program with specification + +local osexecute = sandbox.original(os.execute) +local iopopen = sandbox.original(io.popen) +local reported = { } + +local function validcommand(name,program,template,checkers,defaults,variables,reporter,strict) + if validbinaries ~= false and (validbinaries == true or validbinaries[program]) then + local binpath = nil + if variables then + for variable, value in next, variables do + local chktype = checkers[variable] + if chktype == "verbose" then + -- for now, we will have a "flags" checker + else + local checker = validators[chktype] + if checker and type(value) == "string" then + value = checker(unquoted(value),strict) + if value then + variables[variable] = optionalquoted(value) + else + report("variable %a with value %a fails the check",variable,value) + return + end + else + report("variable %a has no checker",variable) + return + end + end + end + for variable, default in next, defaults do + local value = variables[variable] + if not value or value == "" then + local chktype = checkers[variable] + if chktype == "verbose" then + -- for now, we will have a "flags" checker + elseif type(default) == "string" then + local checker = validators[chktype] + if checker then + default = checker(unquoted(default),strict) + if default then + variables[variable] = optionalquoted(default) + else + report("variable %a with default %a fails the check",variable,default) + return + end + end + end + end + end + binpath = variables.binarypath + end + if type(binpath) == "string" and binpath ~= "" then + -- this works on the console but not from e.g. scite + -- program = '"' .. binpath .. "/" .. program .. '"' + program = binpath .. "/" .. program + end + local command = program .. " " .. replace(template,variables) + if reporter then + reporter("executing runner %a: %s",name,command) + elseif trace then + report("executing runner %a: %s",name,command) + end + return command + elseif not reported[name] then + report("executing program %a of runner %a is not permitted",program,name) + reported[name] = true + end +end + +local runners = { + -- + -- name,program,template,checkers,variables,reporter + -- + resultof = function(...) + local command = validcommand(...) + if command then + if trace then + report("resultof: %s",command) + end + local handle = iopopen(command,"rb") -- already has flush + if handle then + local result = handle:read("*all") or "" + handle:close() + return result + end + end + end, + execute = function(...) + local command = validcommand(...) + if command then + if trace then + report("execute: %s",command) + end + local okay = osexecute(command) + return okay + end + end, + pipeto = function(...) + local command = validcommand(...) + if command then + if trace then + report("pipeto: %s",command) + end + return iopopen(command,"w") -- already has flush + end + end, +} + +function sandbox.registerrunner(specification) + if type(specification) == "string" then + local wrapped = validrunners[specification] + inspect(table.sortedkeys(validrunners)) + if wrapped then + return wrapped + else + report("unknown predefined runner %a",specification) + return + end + end + if type(specification) ~= "table" then + report("specification should be a table (or string)") + return + end + local name = specification.name + if type(name) ~= "string" then + report("invalid name, string expected",name) + return + end + if validrunners[name] then + report("invalid name, runner %a already defined",name) + return + end + local program = specification.program + if type(program) == "string" then + -- common for all platforms + elseif type(program) == "table" then + program = program[platform] or program.default or program.unix + end + if type(program) ~= "string" or program == "" then + report("invalid runner %a specified for platform %a",name,platform) + return + end + local template = specification.template + if not template then + report("missing template for runner %a",name) + return + end + local method = specification.method or "execute" + local checkers = specification.checkers or { } + local defaults = specification.defaults or { } + local internal = specification.internal + local runner = runners[method] + if runner then + local finalized = finalized -- so, the current situation is frozen + local internalized = false + local wrapped = function(variables) + if internal and not internalized then + -- So internal returns a function but can also just return false in which + -- case we fallback in the runner; this permits optional library support. + internal = internal(specification) + if type(internal) ~= "function" then + internal = false + end + internalized = true + end + return (internal or runner)(name,program,template,checkers,defaults,variables,specification.reporter,finalized) + end + validrunners[name] = wrapped + return wrapped + else + validrunners[name] = nil + report("invalid method for runner %a",name) + end +end + +function sandbox.getrunner(name) + return name and validrunners[name] +end + +local function suspicious(str) + return (find(str,"[/\\]") or find(command,"..",1,true)) and true or false +end + +local function binaryrunner(action,command,...) + if validbinaries == false then + -- nothing permitted + report("no binaries permitted, ignoring command: %s",command) + return + end + if type(command) ~= "string" then + -- we only handle strings, maybe some day tables + report("command should be a string") + return + end + local program = lpegmatch(p_split,command) + if not program or program == "" then + report("unable to filter binary from command: %s",command) + return + end + if validbinaries == true then + -- everything permitted + elseif not validbinaries[program] then + report("binary not permitted, ignoring command: %s",command) + return + elseif suspicious(command) then + report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command) + return + end + return action(command,...) +end + +local function dummyrunner(action,command,...) + if type(command) == "table" then + command = concat(command," ",command[0] and 0 or 1) + end + report("ignoring command: %s",command) +end + +sandbox.filehandlerone = filehandlerone +sandbox.filehandlertwo = filehandlertwo +sandbox.iohandler = iohandler + +do + + local library = optional.library + local foreign = optional.foreign + local reported = { } + local libraryload = library.load + local foreignload = foreign.load + + function library.load(name,...) + if validlibraries == false then + -- all blocked + elseif validlibraries == true then + -- all permitted + return libraryload(name,...) + elseif validlibraries[nameonly(name)] then + -- 'name' permitted + return libraryload(name,...) + else + -- 'name' not permitted + end + if not reported[name] then + report("using library %a is not permitted",name) + reported[name] = true + end + return nil + end + + function foreign.load(name,...) + if validlibraries == false then + -- all blocked + elseif validlibraries == true then + -- all permitted + return foreignload(name,...) + elseif validlibraries[nameonly(name)] then + -- 'name' permitted + return foreignload(name,...) + else + -- 'name' not permitted + end + if not reported[name] then + report("using foreign %a is not permitted",name) + reported[name] = true + end + return nil + end + + -- we can do this in the engine: a one time flag + + function sandbox.disablelibraries() + validlibraries = false + library.load = function() end + foreign.load = function() end + end + + function sandbox.disablerunners() + validbinaries = false + end + +end + +------------------- + +local overload = sandbox.overload +local register = sandbox.register + + overload(loadfile, filehandlerone,"loadfile") -- todo + +if io then + overload(io.open, filehandlerone,"io.open") + overload(io.popen, binaryrunner, "io.popen") + overload(io.input, iohandler, "io.input") + overload(io.output, iohandler, "io.output") + overload(io.lines, filehandlerone,"io.lines") +end + +if os then + overload(os.execute, binaryrunner, "os.execute") + overload(os.spawn, dummyrunner, "os.spawn") -- no longer there + overload(os.exec, dummyrunner, "os.exec") -- no longer there + overload(os.resultof, binaryrunner, "os.resultof") + overload(os.pipeto, binaryrunner, "os.pipeto") + overload(os.rename, filehandlertwo,"os.rename") + overload(os.remove, filehandlerone,"os.remove") +end + +if lfs then + overload(lfs.chdir, filehandlerone,"lfs.chdir") + overload(lfs.mkdir, filehandlerone,"lfs.mkdir") + overload(lfs.rmdir, filehandlerone,"lfs.rmdir") + overload(lfs.isfile, filehandlerone,"lfs.isfile") + overload(lfs.isdir, filehandlerone,"lfs.isdir") + overload(lfs.attributes, filehandlerone,"lfs.attributes") + overload(lfs.dir, filehandlerone,"lfs.dir") + overload(lfs.lock_dir, filehandlerone,"lfs.lock_dir") + overload(lfs.touch, filehandlerone,"lfs.touch") + overload(lfs.link, filehandlertwo,"lfs.link") + overload(lfs.setmode, filehandlerone,"lfs.setmode") + overload(lfs.readlink, filehandlerone,"lfs.readlink") + overload(lfs.shortname, filehandlerone,"lfs.shortname") + overload(lfs.symlinkattributes,filehandlerone,"lfs.symlinkattributes") +end + +-- these are used later on + +if zip then + zip.open = register(zip.open, filehandlerone,"zip.open") +end + +sandbox.registerroot = registerroot +sandbox.registerbinary = registerbinary +sandbox.registerlibrary = registerlibrary +sandbox.validfilename = validfilename + +-- not used in a normal mkiv run : os.spawn = os.execute +-- not used in a normal mkiv run : os.exec = os.exec + +-- print(io.open("test.log")) +-- sandbox.enable() +-- print(io.open("test.log")) +-- print(io.open("t:/test.log")) diff --git a/tex/context/modules/mkxl/m-tikz.mkxl b/tex/context/modules/mkxl/m-tikz.mkxl index e79806ca9..29ef764c9 100644 --- a/tex/context/modules/mkxl/m-tikz.mkxl +++ b/tex/context/modules/mkxl/m-tikz.mkxl @@ -36,17 +36,36 @@ \protect \fi +\newcatcodetable \tikzcatcodes + +\startcatcodetable \tikzcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\circumflexasciicode \superscriptcatcode + \catcode\underscoreasciicode \subscriptcatcode + \catcode\ampersandasciicode \alignmentcatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode \endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode \othercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \othercatcode +\stopcatcodetable + \permanent\protected\def\starttikzinput {\pushoverloadmode \pushcatcodetable - \setcatcodetable\texcatcodes + \setcatcodetable\tikzcatcodes \pushmacro\meaning \let\meaning\meaningless - \catcode`\@=11\relax - \catcode`\|=13\relax % was 12 < texlive 2023 - \catcode`\!=12\relax - \catcode`\~=13\relax % needed >= texlive 2023 - % \catcode`\$= 3\relax \autoparagraphmode\zerocount} \permanent\protected\def\stoptikzinput @@ -89,6 +108,7 @@ \permanent\protected\def\starttikzpicture {\dontleavehmode \hcontainer\bgroup + \setcatcodetable\tikzcatcodes \the\everytikzpicture \autoparagraphmode\zerocount \pushmacro\meaning @@ -125,8 +145,9 @@ \let\startpgfinterruptpicture \pgfinterruptpicture \let\stoppgfinterruptpicture \endpgfinterruptpicture \let\startpgfinterruptboundingbox\pgfinterruptboundinbox \let\stoppgfinterruptboudingbox\endpgfinterruptboundingbox -\let\normalusepgfmodule\usepgfmodule -\let\normalusepgflibrary\usepgflibrary +\let\normalusepgfmodule \usepgfmodule +\let\normalusepgflibrary \usepgflibrary +\let\normalusetikzlibrary\usetikzlibrary \tolerant\protected\def\usepgfmodule[#1]#;#2% somehow both variants are used {\starttikzinput @@ -138,6 +159,11 @@ \normalusepgflibrary[#1#2]% \stoptikzinput} +\tolerant\protected\def\usetikzlibrary[#1]#;#2% somehow both variants are used + {\starttikzinput + \normalusetikzlibrary[#1#2]% + \stoptikzinput} + \usepgfmodule[shapes] \usepgfmodule[plot] \usepgfmodule[matrix] diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 917ab1b94..5441fa004 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 : 2023-04-27 16:54 +-- merge date : 2023-05-05 18:36 do -- begin closure to overcome local limits and interference -- cgit v1.2.3