version 1.1, 2010/05/16 19:08:11 |
version 1.31, 2011/08/18 08:58:44 |
|
|
.\" $Id$ |
.\" $Id$ |
.\" |
.\" |
.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> |
.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> |
|
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org> |
.\" |
.\" |
.\" Permission to use, copy, modify, and distribute this software for any |
.\" Permission to use, copy, modify, and distribute this software for any |
.\" purpose with or without fee is hereby granted, provided that the above |
.\" purpose with or without fee is hereby granted, provided that the above |
|
|
.Os |
.Os |
.Sh NAME |
.Sh NAME |
.Nm roff |
.Nm roff |
.Nd roff language reference |
.Nd roff language reference for mandoc |
.Sh DESCRIPTION |
.Sh DESCRIPTION |
The |
The |
.Nm roff |
.Nm roff |
language is a general-purpose text-formatting language. The purpose of |
language is a general purpose text formatting language. |
this document is to consistently describe those language constructs |
In particular, it serves as the basis for the |
accepted by the |
.Xr mdoc 7 |
|
and |
|
.Xr man 7 |
|
manual formatting macro languages. |
|
This manual describes the subset of the |
|
.Nm |
|
language accepted by the |
.Xr mandoc 1 |
.Xr mandoc 1 |
utility. It is a work in progress. |
utility. |
.Pp |
.Pp |
An |
Input lines beginning with the control characters |
.Nm |
.Sq \&. |
document follows simple rules: lines beginning with the control |
|
characters |
|
.Sq \. |
|
or |
or |
.Sq \(aq |
.Sq \(aq |
are parsed for macros. Other lines are interpreted within the scope of |
are parsed for requests and macros. |
prior macros: |
These define the document structure, change the processing state |
.Bd -literal -offset indent |
and manipulate the formatting. |
\&.xx Macro lines change control state. |
Some requests and macros also produce formatted output, |
Other lines are interpreted within the current state. |
while others do not. |
.Ed |
.Pp |
|
All other input lines provide free-form text to be printed; |
|
the formatting of free-form text depends on the respective |
|
processing context. |
.Sh LANGUAGE SYNTAX |
.Sh LANGUAGE SYNTAX |
.Nm |
.Nm |
documents may contain only graphable 7-bit ASCII characters, the space |
documents may contain only graphable 7-bit ASCII characters, the space |
character, and, in certain circumstances, the tab character. All |
character, and, in certain circumstances, the tab character. |
manuals must have |
To produce other characters in the output, use the escape sequences |
.Ux |
documented in the |
line terminators. |
.Xr mandoc_char 7 |
|
manual. |
|
.Sh REQUEST SYNTAX |
|
A request or macro line consists of: |
|
.Pp |
|
.Bl -enum -compact |
|
.It |
|
the control character |
|
.Sq \&. |
|
or |
|
.Sq \(aq |
|
at the beginning of the line, |
|
.It |
|
optionally an arbitrary amount of whitespace, |
|
.It |
|
the name of the request or the macro, which is one word of arbitrary |
|
length, terminated by whitespace, |
|
.It |
|
and zero or more arguments delimited by whitespace. |
|
.El |
|
.Pp |
|
Thus, the following request lines are all equivalent: |
|
.Bd -literal -offset indent |
|
\&.ig end |
|
\&.ig end |
|
\&. ig end |
|
.Ed |
.Sh MACRO SYNTAX |
.Sh MACRO SYNTAX |
Macros are arbitrary in length and begin with a control character , |
Macros can be defined by the |
.Sq \. |
.Sx \&de |
|
request. |
|
When called, they follow the same syntax as requests, except that |
|
macro arguments may optionally be quoted by enclosing them |
|
in double quote characters |
|
.Pq Sq \(dq . |
|
To be recognized as the beginning of a quoted argument, the opening |
|
quote character must be preceded by a space character. |
|
.Pp |
|
A quoted argument may contain whitespace, and pairs of double quote |
|
characters |
|
.Pq Sq Qq |
|
resolve to single double quote characters. |
|
A quoted argument extends to the next double quote character that is not |
|
part of a pair, or to the end of the input line, whichever comes earlier. |
|
Leaving out the terminating double quote character at the end of the line |
|
is discouraged. |
|
For clarity, if more arguments follow on the same input line, |
|
it is recommended to follow the terminating double quote character |
|
by a space character; in case the next character after the terminating |
|
double quote character is anything else, it is regarded as the beginning |
|
of the next, unquoted argument. |
|
.Pp |
|
Both in quoted and unquoted arguments, pairs of backslashes |
|
.Pq Sq \e\e |
|
resolve to single backslashes. |
|
In unquoted arguments, space characters can alternatively be included |
|
by preceding them with a backslash |
|
.Pq Sq \e\~ , |
|
but quoting is usually better for clarity. |
|
.Sh REQUEST REFERENCE |
|
The |
|
.Xr mandoc 1 |
|
.Nm |
|
parser recognizes the following requests. |
|
Note that the |
|
.Nm |
|
language defines many more requests not implemented in |
|
.Xr mandoc 1 . |
|
.Ss \&ad |
|
Set line adjustment mode. |
|
This line-scoped request is intended to have one argument to select |
|
normal, left, right, or center adjustment for subsequent text. |
|
Currently, it is ignored including its arguments, |
|
and the number of arguments is not checked. |
|
.Ss \&am |
|
Append to a macro definition. |
|
The syntax of this request is the same as that of |
|
.Sx \&de . |
|
It is currently ignored by |
|
.Xr mandoc 1 , |
|
as are its children. |
|
.Ss \&ami |
|
Append to a macro definition, specifying the macro name indirectly. |
|
The syntax of this request is the same as that of |
|
.Sx \&dei . |
|
It is currently ignored by |
|
.Xr mandoc 1 , |
|
as are its children. |
|
.Ss \&am1 |
|
Append to a macro definition, switching roff compatibility mode off |
|
during macro execution. |
|
The syntax of this request is the same as that of |
|
.Sx \&de1 . |
|
It is currently ignored by |
|
.Xr mandoc 1 , |
|
as are its children. |
|
.Ss \&de |
|
Define a |
|
.Nm |
|
macro. |
|
Its syntax can be either |
|
.Bd -literal -offset indent |
|
.Pf . Cm \&de Ar name |
|
.Ar macro definition |
|
\&.. |
|
.Ed |
|
.Pp |
or |
or |
.Sq \(aq , |
|
at the beginning of the line. |
|
An arbitrary amount of whitespace may sit between the control character |
|
and the macro name. |
|
Thus, the following are equivalent: |
|
.Bd -literal -offset indent |
.Bd -literal -offset indent |
\&.if |
.Pf . Cm \&de Ar name Ar end |
\&.\ \ \ \&if |
.Ar macro definition |
|
.Pf . Ar end |
.Ed |
.Ed |
.Sh REFERENCE |
.Pp |
This section is a canonical reference of all macros, arranged |
Both forms define or redefine the macro |
alphabetically. |
.Ar name |
|
to represent the |
|
.Ar macro definition , |
|
which may consist of one or more input lines, including the newline |
|
characters terminating each line, optionally containing calls to |
|
.Nm |
|
requests, |
|
.Nm |
|
macros or high-level macros like |
|
.Xr man 7 |
|
or |
|
.Xr mdoc 7 |
|
macros, whichever applies to the document in question. |
|
.Pp |
|
Specifying a custom |
|
.Ar end |
|
macro works in the same way as for |
|
.Sx \&ig ; |
|
namely, the call to |
|
.Sq Pf . Ar end |
|
first ends the |
|
.Ar macro definition , |
|
and after that, it is also evaluated as a |
|
.Nm |
|
request or |
|
.Nm |
|
macro, but not as a high-level macro. |
|
.Pp |
|
The macro can be invoked later using the syntax |
|
.Pp |
|
.D1 Pf . Ar name Op Ar argument Op Ar argument ... |
|
.Pp |
|
Regarding argument parsing, see |
|
.Sx MACRO SYNTAX |
|
above. |
|
.Pp |
|
The line invoking the macro will be replaced |
|
in the input stream by the |
|
.Ar macro definition , |
|
replacing all occurrences of |
|
.No \e\e$ Ns Ar N , |
|
where |
|
.Ar N |
|
is a digit, by the |
|
.Ar N Ns th Ar argument . |
|
For example, |
|
.Bd -literal -offset indent |
|
\&.de ZN |
|
\efI\e^\e\e$1\e^\efP\e\e$2 |
|
\&.. |
|
\&.ZN XtFree . |
|
.Ed |
|
.Pp |
|
produces |
|
.Pp |
|
.D1 \efI\e^XtFree\e^\efP. |
|
.Pp |
|
in the input stream, and thus in the output: \fI\^XtFree\^\fP. |
|
.Pp |
|
Since macros and user-defined strings share a common string table, |
|
defining a macro |
|
.Ar name |
|
clobbers the user-defined string |
|
.Ar name , |
|
and the |
|
.Ar macro definition |
|
can also be printed using the |
|
.Sq \e* |
|
string interpolation syntax described below |
|
.Sx ds , |
|
but this is rarely useful because every macro definition contains at least |
|
one explicit newline character. |
|
.Pp |
|
In order to prevent endless recursion, both groff and |
|
.Xr mandoc 1 |
|
limit the stack depth for expanding macros and strings |
|
to a large, but finite number. |
|
Do not rely on the exact value of this limit. |
|
.Ss \&dei |
|
Define a |
|
.Nm |
|
macro, specifying the macro name indirectly. |
|
The syntax of this request is the same as that of |
|
.Sx \&de . |
|
It is currently ignored by |
|
.Xr mandoc 1 , |
|
as are its children. |
|
.Ss \&de1 |
|
Define a |
|
.Nm |
|
macro that will be executed with |
|
.Nm |
|
compatibility mode switched off during macro execution. |
|
This is a GNU extension not available in traditional |
|
.Nm |
|
implementations and not even in older versions of groff. |
|
Since |
|
.Xr mandoc 1 |
|
does not implement |
|
.Nm |
|
compatibility mode at all, it handles this request as an alias for |
|
.Sx \&de . |
|
.Ss \&ds |
|
Define a user-defined string. |
|
Its syntax is as follows: |
|
.Pp |
|
.D1 Pf . Cm \&ds Ar name Oo \(dq Oc Ns Ar string |
|
.Pp |
|
The |
|
.Ar name |
|
and |
|
.Ar string |
|
arguments are space-separated. |
|
If the |
|
.Ar string |
|
begins with a double-quote character, that character will not be part |
|
of the string. |
|
All remaining characters on the input line form the |
|
.Ar string , |
|
including whitespace and double-quote characters, even trailing ones. |
|
.Pp |
|
The |
|
.Ar string |
|
can be interpolated into subsequent text by using |
|
.No \e* Ns Bq Ar name |
|
for a |
|
.Ar name |
|
of arbitrary length, or \e*(NN or \e*N if the length of |
|
.Ar name |
|
is two or one characters, respectively. |
|
Interpolation can be prevented by escaping the leading backslash; |
|
that is, an asterisk preceded by an even number of backslashes |
|
does not trigger string interpolation. |
|
.Pp |
|
Since user-defined strings and macros share a common string table, |
|
defining a string |
|
.Ar name |
|
clobbers the macro |
|
.Ar name , |
|
and the |
|
.Ar name |
|
used for defining a string can also be invoked as a macro, |
|
in which case the following input line will be appended to the |
|
.Ar string , |
|
forming a new input line passed to the |
|
.Nm |
|
parser. |
|
For example, |
|
.Bd -literal -offset indent |
|
\&.ds badidea .S |
|
\&.badidea |
|
H SYNOPSIS |
|
.Ed |
|
.Pp |
|
invokes the |
|
.Cm SH |
|
macro when used in a |
|
.Xr man 7 |
|
document. |
|
Such abuse is of course strongly discouraged. |
|
.Ss \&el |
|
The |
|
.Qq else |
|
half of an if/else conditional. |
|
Pops a result off the stack of conditional evaluations pushed by |
|
.Sx \&ie |
|
and uses it as its conditional. |
|
If no stack entries are present (e.g., due to no prior |
|
.Sx \&ie |
|
calls) |
|
then false is assumed. |
|
The syntax of this request is similar to |
|
.Sx \&if |
|
except that the conditional is missing. |
|
.Ss \&EN |
|
End an equation block. |
|
See |
|
.Sx \&EQ . |
|
.Ss \&EQ |
|
Begin an equation block. |
|
See |
|
.Xr eqn 7 |
|
for a description of the equation language. |
|
.Ss \&hy |
|
Set automatic hyphenation mode. |
|
This line-scoped request is currently ignored. |
|
.Ss \&ie |
|
The |
|
.Qq if |
|
half of an if/else conditional. |
|
The result of the conditional is pushed into a stack used by subsequent |
|
invocations of |
|
.Sx \&el , |
|
which may be separated by any intervening input (or not exist at all). |
|
Its syntax is equivalent to |
|
.Sx \&if . |
.Ss \&if |
.Ss \&if |
Begins a conditional. |
Begins a conditional. |
Has the following syntax: |
Right now, the conditional evaluates to true |
|
if and only if it starts with the letter |
|
.Sy n , |
|
indicating processing in nroff style as opposed to troff style. |
|
If a conditional is false, its children are not processed, but are |
|
syntactically interpreted to preserve the integrity of the input |
|
document. |
|
Thus, |
.Pp |
.Pp |
.Bd -literal -offset indent -compact |
.D1 \&.if t .ig |
|
.Pp |
|
will discard the |
|
.Sq \&.ig , |
|
which may lead to interesting results, but |
|
.Pp |
|
.D1 \&.if t .if t \e{\e |
|
.Pp |
|
will continue to syntactically interpret to the block close of the final |
|
conditional. |
|
Sub-conditionals, in this case, obviously inherit the truth value of |
|
the parent. |
|
This request has the following syntax: |
|
.Bd -literal -offset indent |
\&.if COND \e{\e |
\&.if COND \e{\e |
BODY... |
BODY... |
\&.\e} |
\&.\e} |
.Ed |
.Ed |
.Bd -literal -offset indent -compact |
.Bd -literal -offset indent |
\&.if COND \e{ BODY |
\&.if COND \e{ BODY |
|
BODY... \e} |
|
.Ed |
|
.Bd -literal -offset indent |
|
\&.if COND \e{ BODY |
BODY... |
BODY... |
\&.\e} |
\&.\e} |
.Ed |
.Ed |
.Bd -literal -offset indent -compact |
.Bd -literal -offset indent |
\&.if COND \e |
\&.if COND \e |
BODY |
BODY |
.Ed |
.Ed |
.Pp |
.Pp |
COND is a conditional (TODO: document). |
COND is a conditional statement. |
|
roff allows for complicated conditionals; mandoc is much simpler. |
|
At this time, mandoc supports only |
|
.Sq n , |
|
evaluating to true; |
|
and |
|
.Sq t , |
|
.Sq e , |
|
and |
|
.Sq o , |
|
evaluating to false. |
|
All other invocations are read up to the next end of line or space and |
|
evaluate as false. |
.Pp |
.Pp |
If the BODY section is begun by an escaped brace |
If the BODY section is begun by an escaped brace |
.Sq \e{ , |
.Sq \e{ , |
scope continues until a closing-brace macro |
scope continues until a closing-brace escape sequence |
.Sq \.\e} . |
.Sq \.\e} . |
If the BODY is not enclosed in braces, scope continues until the next |
If the BODY is not enclosed in braces, scope continues until |
macro or word. |
the end of the line. |
If the COND is followed by a BODY on the same line, whether after a |
If the COND is followed by a BODY on the same line, whether after a |
brace or not, then macros |
brace or not, then requests and macros |
.Em must |
.Em must |
begin with a control character. |
begin with a control character. |
It is generally more intuitive, in this case, to write |
It is generally more intuitive, in this case, to write |
|
|
\&.\e} |
\&.\e} |
.Ed |
.Ed |
.Pp |
.Pp |
than having the macro follow as |
than having the request or macro follow as |
.Pp |
.Pp |
.D1 \&.if COND \e{ .foo |
.D1 \&.if COND \e{ .foo |
.Pp |
.Pp |
The scope of a conditional is always parsed, but only executed if the |
The scope of a conditional is always parsed, but only executed if the |
conditional evaluates to true. |
conditional evaluates to true. |
.Pp |
.Pp |
Note that text subsequent a |
Note that the |
.Sq \e} |
.Sq \e} |
is discarded. |
is converted into a zero-width escape sequence if not passed as a |
|
standalone macro |
|
.Sq \&.\e} . |
|
For example, |
|
.Pp |
|
.D1 \&.Fl a \e} b |
|
.Pp |
|
will result in |
|
.Sq \e} |
|
being considered an argument of the |
|
.Sq \&Fl |
|
macro. |
.Ss \&ig |
.Ss \&ig |
Ignore input until a |
Ignore input. |
.Sq \.\. |
Its syntax can be either |
macro is encountered on its own line. |
.Bd -literal -offset indent |
Note that text subsequent the |
.Pf . Cm \&ig |
.Sq \.\. |
.Ar ignored text |
is discarded. |
\&.. |
.Sh AUTHORS |
.Ed |
|
.Pp |
|
or |
|
.Bd -literal -offset indent |
|
.Pf . Cm \&ig Ar end |
|
.Ar ignored text |
|
.Pf . Ar end |
|
.Ed |
|
.Pp |
|
In the first case, input is ignored until a |
|
.Sq \&.. |
|
request is encountered on its own line. |
|
In the second case, input is ignored until the specified |
|
.Sq Pf . Ar end |
|
macro is encountered. |
|
Do not use the escape character |
|
.Sq \e |
|
anywhere in the definition of |
|
.Ar end ; |
|
it would cause very strange behaviour. |
|
.Pp |
|
When the |
|
.Ar end |
|
macro is a roff request or a roff macro, like in |
|
.Pp |
|
.D1 \&.ig if |
|
.Pp |
|
the subsequent invocation of |
|
.Sx \&if |
|
will first terminate the |
|
.Ar ignored text , |
|
then be invoked as usual. |
|
Otherwise, it only terminates the |
|
.Ar ignored text , |
|
and arguments following it or the |
|
.Sq \&.. |
|
request are discarded. |
|
.Ss \&ne |
|
Declare the need for the specified minimum vertical space |
|
before the next trap or the bottom of the page. |
|
This line-scoped request is currently ignored. |
|
.Ss \&nh |
|
Turn off automatic hyphenation mode. |
|
This line-scoped request is currently ignored. |
|
.Ss \&rm |
|
Remove a request, macro or string. |
|
This request is intended to have one argument, |
|
the name of the request, macro or string to be undefined. |
|
Currently, it is ignored including its arguments, |
|
and the number of arguments is not checked. |
|
.Ss \&nr |
|
Define a register. |
|
A register is an arbitrary string value that defines some sort of state, |
|
which influences parsing and/or formatting. |
|
Its syntax is as follows: |
|
.Pp |
|
.D1 Pf \. Cm \&nr Ar name Ar value |
|
.Pp |
The |
The |
|
.Ar value |
|
may, at the moment, only be an integer. |
|
So far, only the following register |
|
.Ar name |
|
is recognised: |
|
.Bl -tag -width Ds |
|
.It Cm nS |
|
If set to a positive integer value, certain |
|
.Xr mdoc 7 |
|
macros will behave in the same way as in the |
|
.Em SYNOPSIS |
|
section. |
|
If set to 0, these macros will behave in the same way as outside the |
|
.Em SYNOPSIS |
|
section, even when called within the |
|
.Em SYNOPSIS |
|
section itself. |
|
Note that starting a new |
|
.Xr mdoc 7 |
|
section with the |
|
.Cm \&Sh |
|
macro will reset this register. |
|
.El |
|
.Ss \&ns |
|
Turn on no-space mode. |
|
This line-scoped request is intended to take no arguments. |
|
Currently, it is ignored including its arguments, |
|
and the number of arguments is not checked. |
|
.Ss \&ps |
|
Change point size. |
|
This line-scoped request is intended to take one numerical argument. |
|
Currently, it is ignored including its arguments, |
|
and the number of arguments is not checked. |
|
.Ss \&so |
|
Include a source file. |
|
Its syntax is as follows: |
|
.Pp |
|
.D1 Pf \. Cm \&so Ar file |
|
.Pp |
|
The |
|
.Ar file |
|
will be read and its contents processed as input in place of the |
|
.Sq \&.so |
|
request line. |
|
To avoid inadvertent inclusion of unrelated files, |
|
.Xr mandoc 1 |
|
only accepts relative paths not containing the strings |
|
.Qq ../ |
|
and |
|
.Qq /.. . |
|
.Ss \&ta |
|
Set tab stops. |
|
This line-scoped request can take an arbitrary number of arguments. |
|
Currently, it is ignored including its arguments. |
|
.Ss \&tr |
|
Output character translation. |
|
Its syntax is as follows: |
|
.Pp |
|
.D1 Pf \. Cm \&tr Ar [ab]+ |
|
.Pp |
|
Pairs of |
|
.Ar ab |
|
characters are replaced |
|
.Ar ( a |
|
for |
|
.Ar b ) . |
|
Replacement (or origin) characters may also be character escapes; thus, |
|
.Pp |
|
.Dl tr \e(xx\e(yy |
|
.Pp |
|
replaces all invocations of \e(xx with \e(yy. |
|
.Ss \&T& |
|
Re-start a table layout, retaining the options of the prior table |
|
invocation. |
|
See |
|
.Sx \&TS . |
|
.Ss \&TE |
|
End a table context. |
|
See |
|
.Sx \&TS . |
|
.Ss \&TS |
|
Begin a table, which formats input in aligned rows and columns. |
|
See |
|
.Xr tbl 7 |
|
for a description of the tbl language. |
|
.Sh COMPATIBILITY |
|
This section documents compatibility between mandoc and other other |
.Nm |
.Nm |
|
implementations, at this time limited to GNU troff |
|
.Pq Qq groff . |
|
The term |
|
.Qq historic groff |
|
refers to groff version 1.15. |
|
.Pp |
|
.Bl -dash -compact |
|
.It |
|
In mandoc, the |
|
.Sx \&EQ , |
|
.Sx \&TE , |
|
.Sx \&TS , |
|
and |
|
.Sx \&T& , |
|
macros are considered regular macros. |
|
In all other |
|
.Nm |
|
implementations, these are special macros that must be specified without |
|
spacing between the control character (which must be a period) and the |
|
macro name. |
|
.It |
|
The |
|
.Cm nS |
|
register is only compatible with OpenBSD's groff-1.15. |
|
.It |
|
Historic groff did not accept white-space before a custom |
|
.Ar end |
|
macro for the |
|
.Sx \&ig |
|
request. |
|
.It |
|
The |
|
.Sx \&if |
|
and family would print funny white-spaces with historic groff when |
|
using the next-line syntax. |
|
.El |
|
.Sh SEE ALSO |
|
.Xr mandoc 1 , |
|
.Xr eqn 7 , |
|
.Xr man 7 , |
|
.Xr mandoc_char 7 , |
|
.Xr mdoc 7 , |
|
.Xr tbl 7 |
|
.Rs |
|
.%A Joseph F. Ossanna |
|
.%A Brian W. Kernighan |
|
.%I AT&T Bell Laboratories |
|
.%T Troff User's Manual |
|
.%R Computing Science Technical Report |
|
.%N 54 |
|
.%C Murray Hill, New Jersey |
|
.%D 1976 and 1992 |
|
.%U http://www.kohala.com/start/troff/cstr54.ps |
|
.Re |
|
.Rs |
|
.%A Joseph F. Ossanna |
|
.%A Brian W. Kernighan |
|
.%A Gunnar Ritter |
|
.%T Heirloom Documentation Tools Nroff/Troff User's Manual |
|
.%D September 17, 2007 |
|
.%U http://heirloom.sourceforge.net/doctools/troff.pdf |
|
.Re |
|
.Sh HISTORY |
|
The RUNOFF typesetting system was written in PL/1 for the CTSS |
|
operating system by Jerome ("Jerry") E. Saltzer in 1961. |
|
It was first used as the main documentation tool by Multics since 1963. |
|
Robert ("Bob") H. Morris ported it to the GE-635 and called it |
|
.Nm , |
|
Doug McIlroy rewrote it in BCPL in 1969, |
|
Joseph F. Ossanna rewrote it in PDP-11 assembly in 1973, |
|
and Brian W. Kernighan rewrote it in C in 1975. |
|
.Sh AUTHORS |
|
.An -nosplit |
|
This |
|
.Nm |
reference was written by |
reference was written by |
.An Kristaps Dzonsons Aq kristaps@bsd.lv . |
.An Kristaps Dzonsons , |
|
.Mt kristaps@bsd.lv ; |
|
and |
|
.An Ingo Schwarze , |
|
.Mt schwarze@openbsd.org . |