[Dev-luatex] Issues with settex() and glue

Michal Vlasák lahcim8 at gmail.com
Sat Aug 28 21:46:16 CEST 2021


as part of [1] I also noticed that, the "settex" function (used as
metamethod for the "tex" table and for "tex.set") doesn't work for glue
specified by (up to) five values case. There are multiple issues.

Firstly this is the Lua stack when this function is called
(i = lua_gettop()):

    tex.set("global", "parskip", 1, 2, 3, 4, 5)
     i-6      i-5       i-4  i-3  i-2  i-1  i
    "global" "parskip"  1    2    3    4    5

The function essentially doesn't do anything for the five number glue
case, because of the outer most check:

    if (lua_type(L, i - 1) == LUA_TSTRING) {

Even if it did, it wouldn't respect the "global" setting, because it is
checked like this:

    if (i == 3 && (lua_type(L,1) == LUA_TSTRING)) {
        const char *s = lua_tostring(L, 1);
        if (lua_key_eq(s,global))

And even then, it would try to use values beyond the top of the stack:

    width(value) = lua_roundnumber(L,i);
    if (i > 1) { stretch(value) = lua_roundnumber(L,i+1); }
    if (i > 3) { shrink(value) = lua_roundnumber(L,i+2); }
    if (i > 4) { stretch_order(value) = lua_tointeger(L,i+3); }
    if (i > 5) { shrink_order(value) = lua_tointeger(L,i+4); }

The manual also mentions the 5 value case twice in the same paragraph:

    --- a/manual/luatex-tex.tex
    +++ b/manual/luatex-tex.tex
    @@ -271,9 +271,7 @@
     \type {tex.get} you get the width of the glue and when you pass \type {true} you
     get all five values. Otherwise you get a node which is a copy of the internal
     value so you are responsible for its freeing at the \LUA\ end. When you set a
    -glue quantity you can either pass a \nod {glue_spec} or upto five numbers. If
    -you pass \type {true} to \type {get} you get 5 values returned for a glue and
    -when you pass \type {false} you only get the width returned.
    +glue quantity you can either pass a \nod {glue_spec} or upto five numbers.

And then the contradicts itself: Glue parameters
    The glue parameters accept and return a userdata object that
    represents a glue_spec node.

I tried to fix the issues, but the "settex" function is also complicated
by the fact, that it also is a __newindex metamethod of the tex table,
which means that its stack can also look like this:

    tex.parskip = n
    i-2  i-1       i
    tex "parskip"  n

So one can't easily just index from the the bottom.

Also the line:

    int a = isglobal;

in the glue case would deserve a comment, since it is subtle, but
required for define() to work properly (it looks at the variable called
"a"). I would prefer something like:

    int a = isglobal; /* for define() */

In the end I am not even sure how to handle the issues. I leave it to
the more experienced.

Kind regards,
Michal Vlasák

[1]: https://mailman.ntg.nl/pipermail/dev-luatex/2021-August/006542.html

More information about the dev-luatex mailing list