File: groff.info, Node: Operators in Conditionals, Next: if-then, Prev: Conditionals_and_Loops.php">Conditionals and Loops, Up: Conditionals_and_Loops.php">Conditionals and Loops 5.23.1 Operators in Conditionals -------------------------------- In 'if', 'ie', and 'while' requests, in addition to the numeric expressions described in *note Numeric Expressions::, several Boolean operators are available; the members of this expanded class are termed "conditional expressions". 'c GLYPH' True if GLYPH is available, where GLYPH is an ordinary character, a special character '\(XX' or '\[XXX]', '\N'XXX'', or has been defined by any of the 'char', 'fchar', 'fschar', or 'schar' requests. 'd NAME' True if a string, macro, diversion, or request called NAME exists. 'e' True if the current page is even-numbered. 'F FONT' True if FONT exists. FONT is handled as if it were opened with the 'ft' request (that is, font translation and styles are applied), without actually mounting it. 'm COLOR' True if COLOR is defined. 'n' True if the document is being processed in 'nroff' mode. *Note troff and nroff Modes::. 'o' True if the current page is odd-numbered. 'r REGISTER' True if REGISTER exists. 'S STYLE' True if STYLE is available for the current font family. Font translation is applied. 't' True if the document is being processed in 'troff' mode. *Note troff and nroff Modes::. 'v' Always false. This condition is recognized only for compatibility with certain other 'troff' implementations.(1) (*note Operators in Conditionals-Footnote-1::) If the first argument to an 'if', 'ie', or 'while' request begins with a non-alphanumeric character apart from '!' (see below); it performs an output comparison test. (2) (*note Operators in Conditionals-Footnote-2::) ''XXX'YYY'' True if formatting the comparands XXX and YYY produces the same output commands. The delimiter need not be a neutral apostrophe: the output comparison operator accepts the same delimiters as most escape sequences; see *note Delimiters::. This "output comparison operator" formats XXX and YYY in separate environments; after the comparison, the resulting data are discarded. .ie "|"\fR|\fP" true .el false => true The resulting glyph properties, including font family, style, size, and slant, must match, but not necessarily the requests and/or escape sequences used to obtain them. In the previous example, '|' and '\fR|\fP' result in '|' glyphs in the same typefaces at the same positions, so the comparands are equal. If '.ft I' had been added before the '.ie', they would differ: the first '|' would produce an italic '|', not a roman one. Motions must match in orientation and magnitude to within the applicable horizontal and vertical motion quanta of the device, after rounding. '.if "\u\d"\v'0'"' is false even though both comparands result in zero net motion, because motions are not interpreted or optimized but sent as-is to the output.(3) (*note Operators in Conditionals-Footnote-3::) On the other hand, '.if "\d"\v'0.5m'"' is true, because '\d' is defined as a downward motion of one-half em.(4) (*note Operators in Conditionals-Footnote-4::) Surround the comparands with '\?' to avoid formatting them; this causes them to be compared character by character, as with string comparisons in other programming languages. .ie "\?|\?"\?\fR|\fP\?" true .el false => false Since comparands protected with '\?' are read in copy mode (*note Copy Mode::), they need not even be valid 'groff' syntax. The escape character is still lexically recognized, however, and consumes the next character. .ds a \[ .ds b \[ .if '\?\*a\?'\?\*b\?' a and b equivalent .if '\?\\?'\?\\?' backslashes equivalent => a and b equivalent The above operators can't be combined with most others, but a leading '!', not followed immediately by spaces or tabs, complements an expression. .nr x 1 .ie !r x register x is not defined .el register x is defined => register x is defined Spaces and tabs are optional immediately after the 'c', 'd', 'F', 'm', 'r', and 'S' operators, but right after '!', they end the predicate and the conditional evaluates true.(5) (*note Operators in Conditionals-Footnote-5::) .nr x 1 .ie ! r x register x is not defined .el register x is defined => r x register x is not defined The unexpected 'r x' in the output is a clue that our conditional was not interpreted as we planned, but matters may not always be so obvious.