terminalc++14ncursesterminfotermcap

`%l` encoding in terminfo parameterized strings


I am implementing a parser in C++ for parameterized strings(which are used for specifying some terminal capabilities for a terminal). Then I came across this % encoding on the man page of terminfo:

                                 %l   push strlen(pop)

So, my question is, that whenever we are pushing anything onto the stack, it is when any these following % encodings are encountered:

%p[1-9]        push ith parm
%’c’           push char constant c
%{nn}          push decimal constant nn
%l             push strlen(pop)
%+ %− %* %/ %m (arithmetic):   push(pop integer2 op pop integer1)
%& %| %^ (bit operations):     push(pop integer2 op pop integer1)
%= %> %< (logical operations): push(pop integer2 op pop integer1)
%A %O (logical operations):    and, or
%! %~ (unary operations):      push(op pop)

And whenever these are encountered and their results are computed and when the results are about to be pushed onto the stack, then either an integer(including 0 or 1 for bool results) or a character are going to be pushed onto the stack, then does %l encoding mean any or none of the following:

So, my question is what does %l push strlen(pop) mean, which length is it talking about ?

Bonus question: Is the way to pop a string in case of parameterized strings of terminfo (in the 2nd bullet point mentioned above), correct ?

Edit: As pointed by Thomas Dickey, now I am referring to this man page of terminfo.


Solution

  • Notwithstanding the page title "Linux Manpages Online", the manual page referred to is Solaris (SVr4), which was obsoleted by X/Open Curses. Neither gives the necessary details; ncurses' interpretation fills in the details:

    Actually, ncurses uses two passes over the capability string:

    1. In the first pass (see _nc_tparm_analyze in source-code), it steps through the string to see which parameter would be pushed onto the stack, and when it sees a %l or %s, marks that position in an array p_is_s[] as a string.
    2. Then in the second pass, ncurses uses _nc_tparm_internal (shared by varargs- and a fixed-length argument list functions tiparm and tparm, respectively). Using the array, it knows whether to handle a zero-parameter as a numeric zero, or an empty string. Referring to the source-code, if asked to pop a string where a number was given (or if nothing remains on the stack), ncurses passes back an empty string.

    All of that relies upon a correct call to tparm, since there is no portable way to determine the number of parameters passed to a function, nor actually their types. Unlike printf, there is no help from the compiler. But if the parameter list matches the capability string, ncurses will (probably...) match it. SVr4 curses does not do this (see for example tparm.c on illumos-gate).

    In the given example, %p1%l

    That number on the stack can be used in a calculation, e.g.,

    %p1%l%{1}%+
    

    to add 1 to it (pushing the result onto the stack), or just used (nothing on the stack) by formatting a number with %d, etc.

    To output a string and its length, again suppose the string is the first parameter, then you can refer to it more than once in the capability string like this

    %p1%l%d:%p1%s
    

    to output a string's length, a colon (:) separator and the string itself. The "output" of tparm is of course another string, intended to be printed using putp or tputs because it may have embedded padding information (see Output Functions in the terminfo function manual page).

    The operations defined for terminfo came from SVr4, which was officially announced in 1988, though in practice it took several years to become an actuality. There are no operations defined for string concatenation or substrings; applications have to do that sort of thing for themselves. What terminfo does is to parameterize the numbers, and (not quite as an afterthought) provide for inserting strings in appropriate places.