Sidebar: terminfo Parameter Operators
When printer command strings come along, they are usually
encoded
following the ANSI/ISO standards for character control
functions (I
refer to the ISO 6429 Standard). However, that encoding
technique
is not usually followed by printers, just as not all
terminals use
the same control codes for any single function. There
must be a way
within the terminfo definition to translate from the
input
format (ANSI/ISO) delivered to the device through terminfo
into the output format used by the printer or terminal.
terminfo provides a simple language for handling these
parameters.
There are two issues that tend to make this language
a bit difficult
to read until you get used to them: the operators are
somewhat cryptic,
and they use Reverse Polish Notation (RPN).
The operators are a little cryptic because they are
formed from a
percent (%) followed by a single character to identify
which operator
is being used. Stringing these brief operators together
tends to make
the resulting string difficult to read. As with complex
regular expressions,
though, the best approach to understanding them is to
take them one
at a time, reading from left to right. This can be complicated
for
some people by the use of RPN.
Also known as postfix notation, RPN puts the operator
after the operands,
so the familiar infix notation, "2 + 3", would
be rewritten
in RPN as "2, 3 +". The advantage of RPN for
implementing
a simple language is that parentheses and order of operation
are irrelevant,
so a straightforward left-to-right parsing can be done.
For instance,
think about the infix expression "2 + 3 * 4",
which, to come
up with the correct answer, must be solved as "2
+ (3 * 4)".
The precedence of multiplication over addition supersedes
the left
to right evaluation, so parentheses are not strictly
needed. (This
is a simple but revealing test of a calculator to see
if it does arithmetic
correctly. The cheap ones don't.) But, an expression
parser would
have to know this precedence to solve the problem correctly.
With
postfix, either you rearrange the problem so that simple
left-to-right
evaluation delivers the correct answer, "3, 4 *
2 +", or the
operators are arranged in the order that they are to
be executed,
"2, 3, 4, * +". RPN extensively uses a stack
to store its
operands and answers. Of the previous two examples,
the first one
pushes 3, then 4, onto the stack, then pops those two
to perform the
multiplication, after which it pushes the result. Then,
2 is pushed,
after which the previous result is popped with the 2
to perform the
addition. The second example pushes all three constants,
then pops
the last two to perform the multiplication, pushing
the result, and
then pops the result and the first number to perform
the addition.
Results are always pushed.
The stack-oriented operation of RPN must be kept in
mind when putting
together parameter expressions used by terminfo. To
use a parameter
or other value, it must first be pushed onto the stack,
and then something
else pops it off later, usually to print it. Almost
every operator
either pushes or pops something. Following is a list
of the terminfo
parameter operators. The word "parameter"
refers to a particular
value accompanying the ANSI/ISO input command, such
as a row or column
number, or a quantity to move up, down, left, or right.]
%p[1-9] -- Push parameter number 1-9 as
specified. %p1 pushes parameter 1.
%'char' -- Push the single character constant
contained within the apostrophes. %'X' pushes a capital
X.
%{num} -- Push the single decimal constant
contained within the braces. %{17} pushes the value
17.
%P[a-z] -- Pop a value into the dynamic
variable named a-z as specified. %Pv creates a variable
that
can be used within this expression named v and pops
a value
into that variable.
%P[A-Z] -- Pop a value into the static variable
named A-Z as specified. %PA creates a variable that
can be
used by other expressions named A and pops a value into
that
variable.
%g[a-z] -- Push the value in the dynamic
variable named a-z as specified. %gb gets the value
currently
stored in b and pushes it.
%g[A-Z] -- Push the value in the static
variable named A-Z as specified. %gA gets the value
currently
in A and pushes it.
%i -- Increment the first or both the first
and second parameters. This is used by any ANSI terminals
with parameters
that begin with 1 instead of 0.
%+ -- Pop two integer operands, add them,
and push the result.
%- -- Pop two, subtract, and push result.
%* -- Pop two, multiply, and push result.
%/ -- Pop two, divide, and push quotient.
%m -- Pop two, divide, and push remainder.
%~ -- Pop one, binary NOT, push result.
%& -- Pop two, binary AND, push result.
%| -- Pop two, binary OR, push result.
%^ -- Pop two, binary XOR, push result.
%= -- Pop two, compare equal, push truth:
1 if TRUE, and 0 if FALSE.
%<< -- Pop two, compare less-than, push truth.
%>> -- Pop two, compare greater-than, push
truth.
%! -- Pop one, logical NOT, push
truth.
%A -- Pop two, logical AND, push
truth.
%O -- Pop two, logical OR, push truth.
%c -- Pop one, output it in character form.
%l (percent-ell) -- Pop a string, calculate
and push the length.
&$149;%[[:]flags][width[.precision]][doxXs] -- Works
as a limited printf(3S). Pop and print formatted. The
flags
are `-' for left justification within the width; `+'
for forcing all numeric values to have a sign character;
a space character
for forcing a space in front of a positive number; and
`#'
for forcing octal values to output with a leading "0"
and
hexadecimal values to output with a leading "0x"
or "0X".
The flags are optional, but if `-' or `+' are used,
a colon (:) must precede them, making %:- and %:+
to prevent confusion with the %- and %+ operators.
(Of course, the colon makes them look like funny faces
with strange
hats.) The width and precision are optional. Width specifies
a minimum
field width within which the value, if shorter, will
be right justified.
Precision must always be preceded with a period. It
specifies the
minimum number of digits to be output for numbers and
the maximum
quantity of characters to output for strings. Finally,
one of the
letters d (decimal), o (octal), x (hexadecimal
with lowercase a-f), X (hexadecimal with uppercase A-F),
or
s (string) must be specified. %5.3d pops a value and
prints it in decimal, right-justified within a 5-character
field,
showing a minimum of three digits. %:-5.3d does the
same,
but left justifies instead. %:-20.15s pops a string
and
prints it left-justified in a 20-character field, but
first truncates
it to 15 characters in length. %:-20s prints it left-justified
in a field of 20 with no truncation, and %s prints without
regard to field width.
%? expr %t truepart %e falsepart %; -- IF...THEN...ELSE
conditional expression. The %? is the IF, followed by
an expression
(formed of other operators) to be tested. If the condition
is true,
whatever follows the %t (up to the %e) is executed.
If false, the %t part is skipped and whatever follows
the %e
(up to the %;) part is executed. The %; terminates the
entire conditional expression. Another condition may
follow the %e,
which allows yet another %t and %e combination to follow.
As many of these else conditions may follow as needed.
The last %e
must be executable body, not another condition.
%% -- Output a percent symbol.
\E -- Escape character. May also use \e.
\n -- Newline character.
\l -- (backslash-ell) Linefeed character.
\r -- Carriage return character.
\t -- Backspace character.
\f -- Formfeed character.
\s -- Space character. This is used instead
of simply typing a space because the space is a terminfo
command
separator. No spaces can be embedded within a single
command.
^x -- Control character, where x
is any appropriate character. ^G is the ASCII bell.
Remember that the difference between a binary operator
and a logical one is that the binary operator operates
on the individual
operands' bits, while the logical one treats the operands
as truth
values, where zero is FALSE, and anything non-zero is
TRUE.
Also recall the Boolean logic operators NOT (reverse
the bits
or the truth), AND (TRUE only when both operands are
true), OR (FALSE only when both operands are false),
and XOR (TRUE when the bits or truths are different).
The binary AND is used to turn off selected bits, the
binary
OR is used to turn on bits, and the XOR is used to change
bits.
|