Annotation of mandoc/roff.7, Revision 1.30
1.30 ! kristaps 1: .\" $Id: roff.7,v 1.29 2011/05/24 15:22:14 kristaps Exp $
1.1 kristaps 2: .\"
3: .\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
1.12 schwarze 4: .\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: .\"
6: .\" Permission to use, copy, modify, and distribute this software for any
7: .\" purpose with or without fee is hereby granted, provided that the above
8: .\" copyright notice and this permission notice appear in all copies.
9: .\"
10: .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: .\"
1.30 ! kristaps 18: .Dd $Mdocdate: May 24 2011 $
1.1 kristaps 19: .Dt ROFF 7
20: .Os
21: .Sh NAME
22: .Nm roff
1.17 schwarze 23: .Nd roff language reference for mandoc
1.1 kristaps 24: .Sh DESCRIPTION
25: The
26: .Nm roff
1.17 schwarze 27: language is a general purpose text formatting language.
28: In particular, it serves as the basis for the
29: .Xr mdoc 7
30: and
31: .Xr man 7
32: manual formatting macro languages.
33: This manual describes the subset of the
34: .Nm
35: language accepted by the
1.1 kristaps 36: .Xr mandoc 1
1.17 schwarze 37: utility.
1.1 kristaps 38: .Pp
1.17 schwarze 39: Input lines beginning with the control characters
40: .Sq \&.
1.1 kristaps 41: or
42: .Sq \(aq
1.15 kristaps 43: are parsed for requests and macros.
1.17 schwarze 44: These define the document structure, change the processing state
45: and manipulate the formatting.
46: Some requests and macros also produce formatted output,
47: while others do not.
48: .Pp
49: All other input lines provide free-form text to be printed;
50: the formatting of free-form text depends on the respective
51: processing context.
1.1 kristaps 52: .Sh LANGUAGE SYNTAX
53: .Nm
54: documents may contain only graphable 7-bit ASCII characters, the space
1.17 schwarze 55: character, and, in certain circumstances, the tab character.
56: To produce other characters in the output, use the escape sequences
57: documented in the
58: .Xr mandoc_char 7
59: manual.
60: .Sh REQUEST SYNTAX
61: A request or macro line consists of:
62: .Pp
63: .Bl -enum -compact
64: .It
65: the control character
66: .Sq \&.
1.1 kristaps 67: or
1.17 schwarze 68: .Sq \(aq
69: at the beginning of the line,
70: .It
71: optionally an arbitrary amount of whitespace,
72: .It
73: the name of the request or the macro, which is one word of arbitrary
74: length, terminated by whitespace,
75: .It
76: and zero or more arguments delimited by whitespace.
77: .El
78: .Pp
79: Thus, the following request lines are all equivalent:
1.1 kristaps 80: .Bd -literal -offset indent
1.17 schwarze 81: \&.ig end
82: \&.ig end
83: \&. ig end
1.1 kristaps 84: .Ed
1.24 schwarze 85: .Sh MACRO SYNTAX
86: Macros can be defined by the
87: .Sx \&de
88: request.
89: When called, they follow the same syntax as requests, except that
90: macro arguments may optionally be quoted by enclosing them
91: in double quote characters
92: .Pq Sq \(dq .
93: To be recognized as the beginning of a quoted argument, the opening
94: quote character must be preceded by a space character.
95: .Pp
96: A quoted argument may contain whitespace, and pairs of double quote
97: characters
98: .Pq Sq Qq
99: resolve to single double quote characters.
100: A quoted argument extends to the next double quote character that is not
101: part of a pair, or to the end of the input line, whichever comes earlier.
102: Leaving out the terminating double quote character at the end of the line
103: is discouraged.
104: For clarity, if more arguments follow on the same input line,
105: it is recommended to follow the terminating double quote character
106: by a space character; in case the next character after the terminating
107: double quote character is anything else, it is regarded as the beginning
108: of the next, unquoted argument.
109: .Pp
110: Both in quoted and unquoted arguments, pairs of backslashes
111: .Pq Sq \e\e
112: resolve to single backslashes.
113: In unquoted arguments, space characters can alternatively be included
114: by preceding them with a backslash
115: .Pq Sq \e\~ ,
116: but quoting is usually better for clarity.
1.15 kristaps 117: .Sh REQUEST REFERENCE
1.17 schwarze 118: The
1.15 kristaps 119: .Xr mandoc 1
120: .Nm
1.17 schwarze 121: parser recognizes the following requests.
122: Note that the
1.15 kristaps 123: .Nm
1.17 schwarze 124: language defines many more requests not implemented in
1.15 kristaps 125: .Xr mandoc 1 .
126: .Ss \&ad
127: Set line adjustment mode.
128: This line-scoped request is intended to have one argument to select
129: normal, left, right, or center adjustment for subsequent text.
130: Currently, it is ignored including its arguments,
131: and the number of arguments is not checked.
1.3 kristaps 132: .Ss \&am
1.15 kristaps 133: Append to a macro definition.
134: The syntax of this request is the same as that of
135: .Sx \&de .
136: It is currently ignored by
137: .Xr mandoc 1 ,
138: as are its children.
1.3 kristaps 139: .Ss \&ami
1.15 kristaps 140: Append to a macro definition, specifying the macro name indirectly.
141: The syntax of this request is the same as that of
142: .Sx \&dei .
143: It is currently ignored by
144: .Xr mandoc 1 ,
145: as are its children.
1.3 kristaps 146: .Ss \&am1
1.15 kristaps 147: Append to a macro definition, switching roff compatibility mode off
148: during macro execution.
149: The syntax of this request is the same as that of
150: .Sx \&de1 .
151: It is currently ignored by
152: .Xr mandoc 1 ,
153: as are its children.
1.3 kristaps 154: .Ss \&de
1.17 schwarze 155: Define a
1.15 kristaps 156: .Nm
157: macro.
158: Its syntax can be either
159: .Bd -literal -offset indent
160: .Pf . Cm \&de Ar name
161: .Ar macro definition
162: \&..
163: .Ed
164: .Pp
165: or
166: .Bd -literal -offset indent
167: .Pf . Cm \&de Ar name Ar end
168: .Ar macro definition
169: .Pf . Ar end
170: .Ed
171: .Pp
172: Both forms define or redefine the macro
173: .Ar name
174: to represent the
175: .Ar macro definition ,
176: which may consist of one or more input lines, including the newline
177: characters terminating each line, optionally containing calls to
178: .Nm
179: requests,
180: .Nm
181: macros or high-level macros like
182: .Xr man 7
183: or
184: .Xr mdoc 7
185: macros, whichever applies to the document in question.
186: .Pp
187: Specifying a custom
188: .Ar end
189: macro works in the same way as for
190: .Sx \&ig ;
191: namely, the call to
192: .Sq Pf . Ar end
193: first ends the
194: .Ar macro definition ,
195: and after that, it is also evaluated as a
196: .Nm
197: request or
198: .Nm
199: macro, but not as a high-level macro.
200: .Pp
1.17 schwarze 201: The macro can be invoked later using the syntax
1.15 kristaps 202: .Pp
203: .D1 Pf . Ar name Op Ar argument Op Ar argument ...
204: .Pp
1.24 schwarze 205: Regarding argument parsing, see
206: .Sx MACRO SYNTAX
207: above.
1.15 kristaps 208: .Pp
1.17 schwarze 209: The line invoking the macro will be replaced
1.15 kristaps 210: in the input stream by the
211: .Ar macro definition ,
212: replacing all occurrences of
213: .No \e\e$ Ns Ar N ,
1.17 schwarze 214: where
1.15 kristaps 215: .Ar N
216: is a digit, by the
217: .Ar N Ns th Ar argument .
218: For example,
219: .Bd -literal -offset indent
220: \&.de ZN
221: \efI\e^\e\e$1\e^\efP\e\e$2
222: \&..
223: \&.ZN XtFree .
224: .Ed
225: .Pp
226: produces
227: .Pp
228: .D1 \efI\e^XtFree\e^\efP.
229: .Pp
230: in the input stream, and thus in the output: \fI\^XtFree\^\fP.
231: .Pp
1.17 schwarze 232: Since macros and user-defined strings share a common string table,
1.15 kristaps 233: defining a macro
234: .Ar name
235: clobbers the user-defined string
236: .Ar name ,
237: and the
238: .Ar macro definition
239: can also be printed using the
240: .Sq \e*
241: string interpolation syntax described below
242: .Sx ds ,
243: but this is rarely useful because every macro definition contains at least
244: one explicit newline character.
1.16 schwarze 245: .Pp
246: In order to prevent endless recursion, both groff and
247: .Xr mandoc 1
248: limit the stack depth for expanding macros and strings
249: to a large, but finite number.
250: Do not rely on the exact value of this limit.
1.3 kristaps 251: .Ss \&dei
1.17 schwarze 252: Define a
1.15 kristaps 253: .Nm
254: macro, specifying the macro name indirectly.
1.17 schwarze 255: The syntax of this request is the same as that of
1.15 kristaps 256: .Sx \&de .
257: It is currently ignored by
258: .Xr mandoc 1 ,
259: as are its children.
260: .Ss \&de1
1.17 schwarze 261: Define a
1.15 kristaps 262: .Nm
263: macro that will be executed with
264: .Nm
265: compatibility mode switched off during macro execution.
266: This is a GNU extension not available in traditional
267: .Nm
268: implementations and not even in older versions of groff.
269: Since
270: .Xr mandoc 1
271: does not implement
272: .Nm
1.17 schwarze 273: compatibility mode at all, it handles this request as an alias for
1.15 kristaps 274: .Sx \&de .
1.6 schwarze 275: .Ss \&ds
1.15 kristaps 276: Define a user-defined string.
1.13 kristaps 277: Its syntax is as follows:
278: .Pp
1.15 kristaps 279: .D1 Pf . Cm \&ds Ar name Oo \(dq Oc Ns Ar string
1.13 kristaps 280: .Pp
281: The
1.15 kristaps 282: .Ar name
1.13 kristaps 283: and
1.15 kristaps 284: .Ar string
285: arguments are space-separated.
286: If the
287: .Ar string
288: begins with a double-quote character, that character will not be part
289: of the string.
290: All remaining characters on the input line form the
291: .Ar string ,
292: including whitespace and double-quote characters, even trailing ones.
293: .Pp
1.13 kristaps 294: The
1.15 kristaps 295: .Ar string
296: can be interpolated into subsequent text by using
297: .No \e* Ns Bq Ar name
298: for a
299: .Ar name
300: of arbitrary length, or \e*(NN or \e*N if the length of
301: .Ar name
302: is two or one characters, respectively.
1.17 schwarze 303: Interpolation can be prevented by escaping the leading backslash;
304: that is, an asterisk preceded by an even number of backslashes
305: does not trigger string interpolation.
1.15 kristaps 306: .Pp
307: Since user-defined strings and macros share a common string table,
308: defining a string
309: .Ar name
1.17 schwarze 310: clobbers the macro
1.15 kristaps 311: .Ar name ,
312: and the
313: .Ar name
314: used for defining a string can also be invoked as a macro,
315: in which case the following input line will be appended to the
316: .Ar string ,
317: forming a new input line passed to the
318: .Nm
319: parser.
320: For example,
321: .Bd -literal -offset indent
322: \&.ds badidea .S
323: \&.badidea
324: H SYNOPSIS
325: .Ed
326: .Pp
327: invokes the
328: .Cm SH
329: macro when used in a
330: .Xr man 7
331: document.
332: Such abuse is of course strongly discouraged.
1.5 kristaps 333: .Ss \&el
334: The
335: .Qq else
336: half of an if/else conditional.
337: Pops a result off the stack of conditional evaluations pushed by
338: .Sx \&ie
339: and uses it as its conditional.
340: If no stack entries are present (e.g., due to no prior
341: .Sx \&ie
342: calls)
343: then false is assumed.
1.17 schwarze 344: The syntax of this request is similar to
1.5 kristaps 345: .Sx \&if
346: except that the conditional is missing.
1.27 kristaps 347: .Ss \&EN
348: End an equation block.
349: See
350: .Sx \&EQ .
351: .Ss \&EQ
352: Begin an equation block.
353: See
354: .Xr eqn 7
355: for a description of the equation language.
1.15 kristaps 356: .Ss \&hy
357: Set automatic hyphenation mode.
358: This line-scoped request is currently ignored.
1.5 kristaps 359: .Ss \&ie
360: The
361: .Qq if
362: half of an if/else conditional.
363: The result of the conditional is pushed into a stack used by subsequent
364: invocations of
365: .Sx \&el ,
366: which may be separated by any intervening input (or not exist at all).
367: Its syntax is equivalent to
368: .Sx \&if .
1.1 kristaps 369: .Ss \&if
1.7 schwarze 370: Begins a conditional.
371: Right now, the conditional evaluates to true
372: if and only if it starts with the letter
373: .Sy n ,
1.17 schwarze 374: indicating processing in nroff style as opposed to troff style.
1.3 kristaps 375: If a conditional is false, its children are not processed, but are
376: syntactically interpreted to preserve the integrity of the input
377: document.
378: Thus,
379: .Pp
1.17 schwarze 380: .D1 \&.if t .ig
1.3 kristaps 381: .Pp
382: will discard the
383: .Sq \&.ig ,
384: which may lead to interesting results, but
385: .Pp
1.17 schwarze 386: .D1 \&.if t .if t \e{\e
1.3 kristaps 387: .Pp
388: will continue to syntactically interpret to the block close of the final
389: conditional.
390: Sub-conditionals, in this case, obviously inherit the truth value of
391: the parent.
1.17 schwarze 392: This request has the following syntax:
393: .Bd -literal -offset indent
1.1 kristaps 394: \&.if COND \e{\e
395: BODY...
396: \&.\e}
397: .Ed
1.17 schwarze 398: .Bd -literal -offset indent
1.1 kristaps 399: \&.if COND \e{ BODY
1.2 kristaps 400: BODY... \e}
401: .Ed
1.17 schwarze 402: .Bd -literal -offset indent
1.2 kristaps 403: \&.if COND \e{ BODY
1.1 kristaps 404: BODY...
405: \&.\e}
406: .Ed
1.17 schwarze 407: .Bd -literal -offset indent
1.1 kristaps 408: \&.if COND \e
409: BODY
410: .Ed
411: .Pp
1.9 kristaps 412: COND is a conditional statement.
413: roff allows for complicated conditionals; mandoc is much simpler.
414: At this time, mandoc supports only
415: .Sq n ,
416: evaluating to true;
417: and
418: .Sq t ,
419: .Sq e ,
420: and
421: .Sq o ,
422: evaluating to false.
423: All other invocations are read up to the next end of line or space and
424: evaluate as false.
1.1 kristaps 425: .Pp
426: If the BODY section is begun by an escaped brace
427: .Sq \e{ ,
1.17 schwarze 428: scope continues until a closing-brace escape sequence
1.1 kristaps 429: .Sq \.\e} .
1.17 schwarze 430: If the BODY is not enclosed in braces, scope continues until
431: the end of the line.
1.1 kristaps 432: If the COND is followed by a BODY on the same line, whether after a
1.17 schwarze 433: brace or not, then requests and macros
1.1 kristaps 434: .Em must
435: begin with a control character.
436: It is generally more intuitive, in this case, to write
437: .Bd -literal -offset indent
438: \&.if COND \e{\e
439: \&.foo
440: bar
441: \&.\e}
442: .Ed
443: .Pp
1.17 schwarze 444: than having the request or macro follow as
1.1 kristaps 445: .Pp
446: .D1 \&.if COND \e{ .foo
447: .Pp
448: The scope of a conditional is always parsed, but only executed if the
449: conditional evaluates to true.
450: .Pp
1.29 kristaps 451: Note that the
1.1 kristaps 452: .Sq \e}
1.29 kristaps 453: is converted into a zero-width escape sequence if not passed as a
454: standalone macro
455: .Sq \&.\e} .
456: For example,
457: .Pp
458: .D1 \&.Fl a \e} b
459: .Pp
460: will result in
1.8 kristaps 461: .Sq \e}
1.29 kristaps 462: being considered an argument of the
463: .Sq \&Fl
464: macro.
1.1 kristaps 465: .Ss \&ig
1.2 kristaps 466: Ignore input.
1.15 kristaps 467: Its syntax can be either
468: .Bd -literal -offset indent
469: .Pf . Cm \&ig
470: .Ar ignored text
1.2 kristaps 471: \&..
472: .Ed
1.15 kristaps 473: .Pp
474: or
475: .Bd -literal -offset indent
476: .Pf . Cm \&ig Ar end
477: .Ar ignored text
478: .Pf . Ar end
1.2 kristaps 479: .Ed
480: .Pp
481: In the first case, input is ignored until a
482: .Sq \&..
1.17 schwarze 483: request is encountered on its own line.
1.15 kristaps 484: In the second case, input is ignored until the specified
485: .Sq Pf . Ar end
486: macro is encountered.
487: Do not use the escape character
1.2 kristaps 488: .Sq \e
1.15 kristaps 489: anywhere in the definition of
490: .Ar end ;
491: it would cause very strange behaviour.
492: .Pp
493: When the
494: .Ar end
495: macro is a roff request or a roff macro, like in
1.2 kristaps 496: .Pp
497: .D1 \&.ig if
498: .Pp
499: the subsequent invocation of
500: .Sx \&if
1.15 kristaps 501: will first terminate the
502: .Ar ignored text ,
503: then be invoked as usual.
504: Otherwise, it only terminates the
505: .Ar ignored text ,
506: and arguments following it or the
507: .Sq \&..
1.17 schwarze 508: request are discarded.
1.15 kristaps 509: .Ss \&ne
510: Declare the need for the specified minimum vertical space
511: before the next trap or the bottom of the page.
512: This line-scoped request is currently ignored.
513: .Ss \&nh
514: Turn off automatic hyphenation mode.
515: This line-scoped request is currently ignored.
1.6 schwarze 516: .Ss \&rm
517: Remove a request, macro or string.
1.15 kristaps 518: This request is intended to have one argument,
1.6 schwarze 519: the name of the request, macro or string to be undefined.
520: Currently, it is ignored including its arguments,
521: and the number of arguments is not checked.
1.10 kristaps 522: .Ss \&nr
523: Define a register.
524: A register is an arbitrary string value that defines some sort of state,
525: which influences parsing and/or formatting.
526: Its syntax is as follows:
527: .Pp
1.15 kristaps 528: .D1 Pf \. Cm \&nr Ar name Ar value
1.10 kristaps 529: .Pp
530: The
1.15 kristaps 531: .Ar value
1.10 kristaps 532: may, at the moment, only be an integer.
1.15 kristaps 533: So far, only the following register
534: .Ar name
535: is recognised:
1.10 kristaps 536: .Bl -tag -width Ds
537: .It Cm nS
538: If set to a positive integer value, certain
539: .Xr mdoc 7
1.17 schwarze 540: macros will behave in the same way as in the
1.10 kristaps 541: .Em SYNOPSIS
1.11 kristaps 542: section.
1.17 schwarze 543: If set to 0, these macros will behave in the same way as outside the
544: .Em SYNOPSIS
545: section, even when called within the
1.10 kristaps 546: .Em SYNOPSIS
1.17 schwarze 547: section itself.
548: Note that starting a new
1.11 kristaps 549: .Xr mdoc 7
1.17 schwarze 550: section with the
551: .Cm \&Sh
552: macro will reset this register.
1.10 kristaps 553: .El
1.26 schwarze 554: .Ss \&ns
555: Turn on no-space mode.
556: This line-scoped request is intended to take no arguments.
557: Currently, it is ignored including its arguments,
558: and the number of arguments is not checked.
559: .Ss \&ps
560: Change point size.
561: This line-scoped request is intended to take one numerical argument.
562: Currently, it is ignored including its arguments,
563: and the number of arguments is not checked.
1.15 kristaps 564: .Ss \&so
565: Include a source file.
566: Its syntax is as follows:
567: .Pp
568: .D1 Pf \. Cm \&so Ar file
569: .Pp
570: The
571: .Ar file
572: will be read and its contents processed as input in place of the
573: .Sq \&.so
574: request line.
1.28 kristaps 575: To avoid inadvertent inclusion of unrelated files,
1.15 kristaps 576: .Xr mandoc 1
577: only accepts relative paths not containing the strings
578: .Qq ../
579: and
580: .Qq /.. .
1.26 schwarze 581: .Ss \&ta
582: Set tab stops.
583: This line-scoped request can take an arbitrary number of arguments.
584: Currently, it is ignored including its arguments.
1.6 schwarze 585: .Ss \&tr
586: Output character translation.
1.30 ! kristaps 587: Its syntax is as follows:
! 588: .Pp
! 589: .D1 Pf \. Cm \&tr Ar [ab]+
! 590: .Pp
! 591: Pairs of
! 592: .Ar ab
! 593: characters are replaced
! 594: .Ar ( a
! 595: for
! 596: .Ar b ) .
! 597: Replacement (or origin) characters may also be character escapes; thus,
! 598: .Pp
! 599: .Dl tr \e(xx\e(yy
! 600: .Pp
! 601: replaces all invocations of \e(xx with \e(yy.
1.20 kristaps 602: .Ss \&T&
603: Re-start a table layout, retaining the options of the prior table
604: invocation.
605: See
606: .Sx \&TS .
607: .Ss \&TE
608: End a table context.
609: See
610: .Sx \&TS .
611: .Ss \&TS
612: Begin a table, which formats input in aligned rows and columns.
1.23 kristaps 613: See
614: .Xr tbl 7
615: for a description of the tbl language.
1.2 kristaps 616: .Sh COMPATIBILITY
617: This section documents compatibility between mandoc and other other
1.17 schwarze 618: .Nm
619: implementations, at this time limited to GNU troff
1.2 kristaps 620: .Pq Qq groff .
621: The term
622: .Qq historic groff
1.17 schwarze 623: refers to groff version 1.15.
1.2 kristaps 624: .Pp
625: .Bl -dash -compact
1.10 kristaps 626: .It
1.27 kristaps 627: In mandoc, the
628: .Sx \&EQ ,
629: .Sx \&TE ,
630: .Sx \&TS ,
631: and
632: .Sx \&T& ,
633: macros are considered regular macros.
634: In all other
635: .Nm
636: implementations, these are special macros that must be specified without
637: spacing between the control character (which must be a period) and the
638: macro name.
639: .It
1.10 kristaps 640: The
641: .Cm nS
1.17 schwarze 642: register is only compatible with OpenBSD's groff-1.15.
1.2 kristaps 643: .It
1.17 schwarze 644: Historic groff did not accept white-space before a custom
645: .Ar end
646: macro for the
1.2 kristaps 647: .Sx \&ig
1.17 schwarze 648: request.
1.4 kristaps 649: .It
650: The
651: .Sx \&if
652: and family would print funny white-spaces with historic groff when
1.17 schwarze 653: using the next-line syntax.
1.2 kristaps 654: .El
1.17 schwarze 655: .Sh SEE ALSO
656: .Xr mandoc 1 ,
1.27 kristaps 657: .Xr eqn 7 ,
1.17 schwarze 658: .Xr man 7 ,
659: .Xr mandoc_char 7 ,
1.23 kristaps 660: .Xr mdoc 7 ,
661: .Xr tbl 7
1.17 schwarze 662: .Rs
663: .%A Joseph F. Ossanna
664: .%A Brian W. Kernighan
665: .%I AT&T Bell Laboratories
666: .%T Troff User's Manual
667: .%R Computing Science Technical Report
668: .%N 54
669: .%C Murray Hill, New Jersey
670: .%D 1976 and 1992
671: .%U http://www.kohala.com/start/troff/cstr54.ps
672: .Re
673: .Rs
674: .%A Joseph F. Ossanna
675: .%A Brian W. Kernighan
676: .%A Gunnar Ritter
677: .%T Heirloom Documentation Tools Nroff/Troff User's Manual
678: .%D September 17, 2007
679: .%U http://heirloom.sourceforge.net/doctools/troff.pdf
680: .Re
681: .Sh HISTORY
682: The RUNOFF typesetting system was written in PL/1 for the CTSS
683: operating system by Jerome ("Jerry") E. Saltzer in 1961.
684: It was first used as the main documentation tool by Multics since 1963.
685: Robert ("Bob") H. Morris ported it to the GE-635 and called it
686: .Nm ,
687: Doug McIlroy rewrote it in BCPL in 1969,
688: Joseph F. Ossanna rewrote it in PDP-11 assembly in 1973,
689: and Brian W. Kernighan rewrote it in C in 1975.
1.1 kristaps 690: .Sh AUTHORS
1.15 kristaps 691: .An -nosplit
692: This partial
1.1 kristaps 693: .Nm
694: reference was written by
1.15 kristaps 695: .An Kristaps Dzonsons Aq kristaps@bsd.lv
696: and
697: .An Ingo Schwarze Aq schwarze@openbsd.org .
CVSweb