Cover V01, I04
Article
Sidebar 1
Sidebar 2

nov92.tar


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.