├── .editorconfig ├── .gitignore ├── Makefile ├── UNLICENSE.txt ├── mutilate.sed ├── ono.tmac └── t ├── 0-includes.roff ├── 1-monospace.roff ├── 2-ascii-chars.roff ├── 3-underlines.roff ├── 4-code-blocks.roff ├── 5-arg-lists.roff ├── 6.1-string-length.roff ├── 6.2-string-slugs.roff ├── 6.3-string-foreach.roff ├── 6.4-string-concat.roff ├── 7-case.roff ├── 8.1-anchor-ids.roff ├── 8.2-anchor-args.roff ├── 9.1-hyperlinks.roff ├── 9.2-hyperlinks.roff └── debug-utils.roff /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = false 8 | indent_style = tab 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | Desktop.ini 4 | node_modules 5 | package-lock.json 6 | .nyc_output 7 | ._* 8 | .\#* 9 | \#*\# 10 | *~ 11 | *.log 12 | *.lock 13 | [._]*.s[a-v][a-z] 14 | [._]*.sw[a-p] 15 | [._]s[a-v][a-z] 16 | [._]sw[a-p] 17 | /test.* 18 | 19 | # Project-specific 20 | /*.cat 21 | /*.dit 22 | /*.ditroff 23 | /*.htm 24 | /*.html 25 | /*.out 26 | /*.pdf 27 | /*.ps 28 | *.bytes 29 | tmac.ono 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: pack 2 | 3 | minify: tmac.ono 4 | pack: tmac.ono.bytes 5 | 6 | # Compress and optimise Mono for use in otroff (PDP-11/Unix v7) 7 | tmac.ono: ono.tmac 8 | sed -f ./mutilate.sed $^ > $@ 9 | 10 | # Generate a pre-POSIX sh(1) script for copy+pasting into SIMH 11 | tmac.ono.bytes: tmac.ono 12 | printf 'rm -f tmac.ono\n' > $@ 13 | while IFS= read -r line; do \ 14 | printf %s "$$line" \ 15 | | od -b \ 16 | | sed 's/^[0-7]* *//' \ 17 | | dc -e '8i[c?z0> tmac.ono /' >> $@ 19 | chmod +x $@ 20 | 21 | # Wipe generated files 22 | clean: 23 | rm -f tmac.ono 24 | rm -f tmac.ono.bytes 25 | 26 | .PHONY: clean 27 | -------------------------------------------------------------------------------- /UNLICENSE.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /mutilate.sed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sed -f 2 | 3 | # 4 | # Produces an optimised version of Mono for use with SIMH-emulated otroff. 5 | # Output is stripped of comments, whitespace, and regions of code specific 6 | # to mandoc(1) or modern Troff implementations like Groff. 7 | # 8 | # Assumes POSIX basic regular expressions are in-use (sed(1) without `-E`). 9 | # 10 | 11 | 1 { 12 | n 13 | a\ 14 | .\\" Generated from https://git.io/JimMJ by `mutilate.sed' 15 | } 16 | 17 | /[.'[:blank:]]\\"/ s/[[:blank:]]*\\".*//g 18 | /^[.'][[:blank:]]/ s/[[:blank:]]\{1,\}// 19 | /^[.'][[:blank:]]*$/ D 20 | 21 | # Expand line continuations 22 | /^[.'].*[^\\]\\$/ { 23 | N 24 | s/\\\n\([.']\{0,1\}\)[[:blank:]]*/\1/ 25 | } 26 | 27 | # Ad hoc optimisations 28 | /^[.'][[:blank:]]*el[[:blank:]]*/ s/[[:blank:]]\{1,\}/ /g 29 | /^[.'][[:blank:]]*i[ef][[:blank:]]/ s/[[:blank:]]\{1,\}/ /g 30 | /^[.'][[:blank:]]*[iel]\{2\}[[:blank:]]/ { 31 | s/^\(.\)[[:blank:]]*ie[[:blank:]]*/\1ie / 32 | s/^\(.\)[[:blank:]]*el[[:blank:]]*/\1el / 33 | s/^\(.\)[[:blank:]]*if[[:blank:]]*/\1if / 34 | } 35 | 36 | # Cull some unreachable code 37 | /^[.']if '\\\*(\$0'mandoc' \\{\.de UL/, /^\.\\}$/ d 38 | /^[.']if '\\\*(\$0'mandoc' \\{\.de 4@$/, /^\.rm 4@-mandoc$/ d 39 | /^[.']rr 4@-mandoc-index$/, /^\.\\}$/ d 40 | /^[.']if '\\\*(\$0'groff' \\{\.length \\\\\$1 \\\\\$2$/, /^\.\\}$/ d 41 | -------------------------------------------------------------------------------- /ono.tmac: -------------------------------------------------------------------------------- 1 | .\" -*- nroff -*- vim:set ft=nroff fdm=marker: 2 | . 3 | .\" $0: Flavour of troff(1) processing the document 4 | .ds $0 unknown 5 | .ft R 6 | .ie \n(.f=0 .ds $0 mandoc 7 | .el \{\ 8 | . ft 9 | . ie 0<>1 .ds $0 heirloom 10 | . el .ie \w,\X'# Ignore',>0 .ds $0 otroff 11 | . el .ie !'\n[.s]'\n(.s' \{\ 12 | . ds $0 ditroff 13 | . if \n(.C=1 .do ds $0 groff 14 | . \} 15 | . el .if \n(.g=1 .ds $0 groff 16 | .\} 17 | . 18 | . 19 | .\"==============================[ CHARACTERS ]============================={{{1 20 | . 21 | .\" ASCII characters which are harder to typeset than you'd think 22 | .ie '\*($0'heirloom' \{\ 23 | . ds ^ \U'5E' 24 | . ds ~ \U'7E' 25 | . ds ' \U'27' 26 | . ds - \U'2D' 27 | . if !'\*(.T'html' .if t .ds - \(hy 28 | .\} 29 | .el .ie '\*($0'otroff' \{\ 30 | . ds ^ ^ 31 | . ds ~ ~ 32 | . ds ' ' 33 | . ds - \(hy 34 | .\} 35 | .el .ie n \{\ 36 | . ds ^ \N'94' 37 | . ds ~ \N'126' 38 | . ds ' \N'39' 39 | . ds - \N'45' 40 | .\} 41 | .el \{\ 42 | . ds ^ \N'0' 43 | . ds ~ \N'1' 44 | . ds ' \N'8' 45 | . ds - \N'45' 46 | .\} 47 | . 48 | . 49 | .\"================================[ FONTS ]================================{{{1 50 | . 51 | .\" Adaptive monospace fonts. Provides the author with improved control over the 52 | .\" appearance of literal text in both terminal output and typeset documents. 53 | .\" 54 | .\" Mono nroff(1) troff(1) Use for... 55 | .\" ------------------------------------------------------------------------ 56 | .\" \*(CW \fR \f(CR Cosmetic effects, literal values 57 | .\" \*(C? \fI \f(CW Argument names, variable names 58 | .\" \*(C! \fB \f(CR Literal text 59 | .\" \*(CI \f(CI \f(CI Italic monospace 60 | .\" \*(CB \f(CB \f(CB Bold monospace 61 | .\" \*(CE \f(BI \f[CBI] Bold and italic monospace 62 | .\" ------------------------------------------------------------------------ 63 | .ie t \{\ 64 | . ds C? \\f(CR 65 | . ds C! \\f(CR 66 | . ds CW \\f(CR 67 | . ds CI \\f(CI 68 | . ds CB \\f(CB 69 | . ie \\n(.g .ds CE \\f[CBI] 70 | . el .ds CE \\f(CB 71 | .\} 72 | .el \{\ 73 | . ds C? \\fI 74 | . ds C! \\fB 75 | . ds CW \\f1 76 | . ds CI \\fI 77 | . ds CB \\fB 78 | . ds CE \\f(BI 79 | .\} 80 | . 81 | .\" .FONT -- Set typeface, point-size and vertical spacing simultaneously. 82 | .\" 83 | .\" TODO: Allow size argument to be omitted if name is obviously non-numeric. 84 | .\" 85 | .\" Usage: 86 | .\" .FONT [SIZE] [NAME] 87 | .\" .FO NT [SIZE] [NAME] 88 | .\" 89 | .\" Examples: 90 | .\" .FONT 1.5 Helvetica 91 | .\" .FONT 12p 92 | .\" 93 | .de FONT 94 | . FO \\$1 \\$2 95 | . . 96 | . ig NT 97 | . NT 98 | .. 99 | .de FO \" Called in compatibility-mode 100 | . ie 'NT'\\$1' \ 101 | . FO \\$2 \\$3 102 | . el \{\ 103 | . ps \\$1 104 | . vs \\$1 105 | . if !''\\$2' .ft \\$2 106 | ' \} 107 | .. 108 | . 109 | . 110 | .\"================================[ DATES ]================================{{{1 111 | . 112 | .\" Current year 113 | .nr YR 1900+\n(yr 114 | . 115 | .\" Full month names 116 | .ie \n(mo=1 .ds %M January 117 | .el .ie \n(mo=2 .ds %M February 118 | .el .ie \n(mo=3 .ds %M March 119 | .el .ie \n(mo=4 .ds %M April 120 | .el .ie \n(mo=5 .ds %M May 121 | .el .ie \n(mo=6 .ds %M June 122 | .el .ie \n(mo=7 .ds %M July 123 | .el .ie \n(mo=8 .ds %M August 124 | .el .ie \n(mo=9 .ds %M September 125 | .el .ie \n(mo=10 .ds %M October 126 | .el .ie \n(mo=11 .ds %M November 127 | .el .if \n(mo=12 .ds %M December 128 | . 129 | .\" Abbreviated month names 130 | .ie \n(mo=1 .ds %m Jan 131 | .el .ie \n(mo=2 .ds %m Feb 132 | .el .ie \n(mo=3 .ds %m Mar 133 | .el .ie \n(mo=4 .ds %m Apr 134 | .el .ie \n(mo=5 .ds %m May 135 | .el .ie \n(mo=6 .ds %m Jun 136 | .el .ie \n(mo=7 .ds %m Jul 137 | .el .ie \n(mo=8 .ds %m Aug 138 | .el .ie \n(mo=9 .ds %m Sep 139 | .el .ie \n(mo=10 .ds %m Oct 140 | .el .ie \n(mo=11 .ds %m Nov 141 | .el .if \n(mo=12 .ds %m Dec 142 | . 143 | .\" Day of the week (Full) 144 | .ie \n(dw=1 .ds %D Sunday 145 | .el .ie \n(dw=2 .ds %D Monday 146 | .el .ie \n(dw=3 .ds %D Tuesday 147 | .el .ie \n(dw=4 .ds %D Wednesday 148 | .el .ie \n(dw=5 .ds %D Thursday 149 | .el .ie \n(dw=6 .ds %D Friday 150 | .el .if \n(dw=7 .ds %D Saturday 151 | . 152 | .\" Day of the week (Abbreviated) 153 | .ie \n(dw=1 .ds %d Sun 154 | .el .ie \n(dw=2 .ds %d Mon 155 | .el .ie \n(dw=3 .ds %d Tue 156 | .el .ie \n(dw=4 .ds %d Wed 157 | .el .ie \n(dw=5 .ds %d Thu 158 | .el .ie \n(dw=6 .ds %d Fri 159 | .el .if \n(dw=7 .ds %d Sat 160 | . 161 | .\" Day of the month with ordinal suffix: 1st, 2nd, 3rd... 162 | .ie ((\n(dy>10)&(\n(dy<20)) .ds dy \n(dyth 163 | .el .ie (\n(dy%10)=1 .ds dy \n(dyst 164 | .el .ie (\n(dy%10)=2 .ds dy \n(dynd 165 | .el .ie (\n(dy%10)=3 .ds dy \n(dyrd 166 | .el .ds dy \n(dyth 167 | . 168 | . 169 | .\"===========================[ UNDERLINED TEXT ]==========================={{{1 170 | . 171 | .\" .UL -- Proper underlined text. 172 | .\" 173 | .\" TODO: Deal with grotty(1) v1.23's "-i" (and "-r") switches. 174 | .\" 175 | .\" Usage: 176 | .\" .UL [TEXT] 177 | .\" .UL [TEXT] [AFFIX] 178 | .\" .UL [PREFIX] [TEXT] [AFFIX] 179 | .\" 180 | .\" Uses: 181 | .\" \*($0 182 | .\" 183 | .\" Clobbers: 184 | .\" \*(U^B \*(U^C \*(U^E 185 | .\" \n(U^B 186 | .\" 187 | .\" Bugs: 188 | .\" - Line-wrapping produces ugly underlines stretching to the left margin of 189 | .\" the page: continuous underlining should be restricted to interword gaps 190 | .\" - Underline drawn too closely to character baseline in troff(1) 191 | .de UL 192 | ' \" Temporarily disable no-fill mode 193 | ' nr U 0 194 | ' if \\n(.u=0 \{\ 195 | ' nr U 1 196 | ' fi 197 | ' \} 198 | ' 199 | ' \" Resolve argument order 200 | ' ds U \\$1 201 | ' ds U \\$2 202 | ' ds U \\$3 203 | ' if \\n(.$<3 \{\ 204 | ' ds U \& 205 | ' ds U \\$1 206 | ' ds U \&\\$2 207 | ' \} 208 | ' 209 | ' \" Nroff 210 | ' ie n \{\ 211 | \\*(U 212 | ' cu 1 213 | \h'-1n'\\*(U\h'-1n' 214 | \\*(U 215 | ' \} 216 | ' 217 | ' \" Troff 218 | ' el \{\ 219 | ' ie '\\*($0'otroff' \\*(U\l'\w,\\*(U,u\(ul'\h'-\w,\\*(U,u'\\*(U\\*(U 220 | ' el \\*(U\D'l \w,\\*(U,u 0u'\h'-\w,\\*(U,u'\\*(U\\*(U 221 | ' \} 222 | ' 223 | ' \" Restore no-fill mode 224 | ' if \\n(U=1 \{\ 225 | ' rr U 226 | . nf 227 | ' \} 228 | ' 229 | ' \" Clean up 230 | ' rm U 231 | ' rm U 232 | ' rm U 233 | .. 234 | . 235 | '\" Spoon-feed mandoc(1), which doesn't grok underlines or macros very well 236 | .if '\*($0'mandoc' \{\ 237 | .de UL 238 | . ie \\n(.$=1 \\fI\\$1\\fP 239 | . el .ie \\n(.$=2 \\fI\\$1\\fP\\$2 240 | . el .ie \\n(.$>2 \\$1\\fI\\$2\\fP\\$3 241 | .. 242 | .\} 243 | . 244 | . 245 | .\" ============================[ CODE BLOCKS ]============================={{{1 246 | . 247 | .\" Current block's indentation amount. Must be above zero. 248 | .nr `` 0 249 | . 250 | .\" .`` -- Indented code block, optionally tagged with a format identifier. 251 | .\" 252 | .\" Usage: 253 | .\" .`` [SYNTAX] [INDENT 6m] 254 | .\" \& Contents 255 | .\" .`` 256 | .\" 257 | .\" Examples: 258 | .\" .`` js 259 | .\" import {readLines} from "eal/index.mjs"; 260 | .\" .`` 261 | .\" 262 | .\" Modifies: 263 | .\" \n(`` -- Set to INDENT parameter (or 6m if omitted) 264 | .\" 265 | .\" Clobbers: 266 | .\" \*(`^B 267 | .de `` 268 | ' \" Begin block 269 | ' ie !\\n(`` \{\ 270 | . br 271 | ' ie \\$2>1 'nr `` \\$2 272 | ' el 'nr `` 6 273 | ' in +\\n(``n 274 | ' de ` >> 275 | ' in -\\n(`` 276 | ' ft \\n(.f 277 | ' if \\n(.u 'fi 278 | ' hy 279 | ' lg 1 280 | ' do hy \\n[.hy] 281 | ' do lg \\n[.lg] 282 | ' do kern \\n[.kern] 283 | . >> 284 | ' nf 285 | ' nh 286 | ' lg 0 287 | ' ft CW 288 | ' do kern 0 289 | ' do if \n[.meta]=1 \X'meta: begin code \\$1' 290 | ' tr `\`'\*'^\*^~\*~-\*- 291 | ' \} 292 | ' 293 | ' \" End block 294 | ' el \{\ 295 | ' tr ``''^^~~-- 296 | ' do if \n[.meta]=1 \X'meta: end code' 297 | ' ` 298 | ' rm ` 299 | ' rr `` 300 | . br 301 | ' \} 302 | .. 303 | . 304 | . 305 | .\" ===============================[ LISTS ]================================{{{1 306 | .\" Macros for marking up lists, both ordered and unordered. 307 | . 308 | .nr [[ 0 \" List level 309 | .nr [~ 6n \" List indent 310 | .nr * 1 \" List counter 311 | .nr *~ 1 \" Marker offset 312 | .ds *% \(bu \" Marker string 313 | . 314 | .\" .* -- Begin a list item. May be used outside of a .[[ call. 315 | .\" 316 | .\" Usage: 317 | .\" .* Item A 318 | .\" .* Item B 319 | .\" . br 320 | .\" Nested list: 321 | .\" . [[ 322 | .\" . * Nested list item 1 323 | .\" . * Nested list item 2 324 | .\" . * ... 325 | .\" . ]] 326 | .\" Some sidenote about the list. 327 | .\" .* Item C, etc 328 | .\" 329 | .\" Modifies: 330 | .\" \n* -- Increments counter register 331 | .\" 332 | .\" Clobbers: 333 | .\" \*(*^B 334 | .de * 335 | . br 336 | \h'-\\n(*~u-\\w,\\*(*%,u'\\*(*%\h'\\n(*~u'\*($* 337 | . ds * \\g* 338 | . af * 1 339 | . nr * \\n*+1 340 | . af * \\*(* 341 | . rm * 342 | .. 343 | . 344 | .\" .[[ -- Begin list. 345 | .\" 346 | .\" Modifies: 347 | .\" \n([[ -- Increments and decrements the level of nesting. 348 | .\" \n* -- Resets counter register 349 | .\" .]] -- Temporarily redefined whilst list is open 350 | .\" 351 | .\" Clobbers: 352 | .\" \*([^E \*(^E{0..9a..zA..Z} 353 | .\" \n([^E 354 | .de [[ 355 | . \" Compute an internal ID for the current depth 356 | . ie \\n([[<10 .ds [ \\n([[ 357 | . el \{\ 358 | . ie \\n([[<36 \{\ 359 | . nr [ \\n([[-9 360 | . af [ a 361 | . ds [ \\n([ 362 | . \} 363 | . el .ie \\n([[<62 \{\ 364 | . nr [ \\n([[-35 365 | . af [ A 366 | . ds [ \\n([ 367 | . \} 368 | . \" 61 levels of nesting is enough 369 | . el .ds [ Z 370 | . rr [ 371 | . \} 372 | . 373 | . \" Save format of counter register 374 | . ds * \\g* 375 | . af * 1 376 | . 377 | . \" Define callback to recover current state 378 | . rn ]] \\*([ 379 | . de ]] >> 380 | . nr [[ \\n([[-1 381 | . nr * \\n* 382 | . af * \\*(* 383 | . ds *% \\\*(*% 384 | . in \\n(.iu 385 | . rn \\*([ ]] 386 | . >> 387 | . 388 | . \" Apply new state 389 | . nr [[ \\n([[+1 390 | . nr * 1 391 | . af * \\*(* 392 | . in +\\n([~u 393 | . rm * 394 | . rm [ 395 | .. 396 | . 397 | . 398 | .\" ========================[ STRING MANIPULATION ]========================={{{1 399 | . 400 | .\" .$# -- Store the character count of $2 in register $1 401 | .\" 402 | .\" Usage: 403 | .\" .$# [OUT-NR] [TEXT] 404 | .\" 405 | .\" Uses: 406 | .\" \*$0 407 | .de $# 408 | . if '\*($0'groff' \{\ 409 | . length \\$1 \\$2 410 | . return 411 | . \} 412 | . ft CW 413 | . cs \\n(.f 36 414 | . nr \\$1 \\w'\\$2'/\\w'X' 415 | . cs \\n(.f 416 | . ft 417 | .. 418 | . 419 | .\" .=~ -- Define string $1 containing $2 with active character translations applied. 420 | .\" 421 | .\" Usage: 422 | .\" .=~ [NAME] [TEXT] 423 | .\" 424 | .\" Example: 425 | .\" .tr AaBbCcXxYyZz- 426 | .\" .=~ A-Z "ABC-XYZ" 427 | .\" \*[A-Z] => abc xyz 428 | .\" 429 | .\" Clobbers: 430 | .\" \*(=^C \*(=^E 431 | .de =~ 432 | . de = >> 433 | . ds \\$1 \\\\$1 434 | . >> 435 | . di = 436 | . tr .=" 437 | . br 438 | \!  \\$2 439 | . br 440 | . tr  441 | . di 442 | . = 443 | . rm = = 444 | .. 445 | . 446 | .\" .~- -- Convert a string to a format suitable for an internal identifier. 447 | .\" 448 | .\" Usage: 449 | .\" .~- [OUT-STR] [TEXT] 450 | .\" 451 | .\" Example: 452 | .\" .~- xy " Here's an ""ID"" string ++1 2 3_4 5 6 7 8 9" 453 | .\" \*(xy => heres-an-id-string-1-2-3-4-5-6-7-8-9 454 | .\" 455 | .\" Uses: 456 | .\" .,+ .=~ 457 | .\" 458 | .\" Clobbers: 459 | .\" \*(~^B \*(~^C 460 | .\" 461 | .\" Bugs: 462 | .\" - Heirloom Doctools breaks when passed strings with embedded quotes 463 | .\" - Strings with spaces shouldn't be truncated to first 9 substrings 464 | .de ~- 465 | . ds ~ \\$2 466 | . ,+ ~ "\\*(~" - 467 | . 468 | . \" Strip unwanted characters 469 | . tr ' " \(aq \(lq \(rq \(oq \(cq \(aa \(ga 470 | . tr " ! # $ % & ( ) * + , . / : ; < = > ? @ [ \e ] ^ ` { | } ~ 471 | . =~ ~ "\\*(~ 472 | . tr ''""\(aq\(aq\(lq\(lq\(rq\(rq\(oq\(oq\(cq\(cq\(aa\(aa\(ga\(ga 473 | . tr !!##$$%%&&(())**++,,..//::;;<<==>>??@@[[\e\e]]^^``{{||}}~~ 474 | . 475 | . \" Replace punctuation with dashes 476 | . tr \(hy-\(mi-\(en-\(em-_- 477 | . tr AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz 478 | . tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz 479 | . ,+ ~ "\\*(~ 480 | . =~ ~ \\*(~ 481 | . tr \--\(mi\(mi\(en\(en\(em\(em__ 482 | . tr AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ 483 | . 484 | . ds \\$1 \\*(~ 485 | . rm ~ 486 | .. 487 | . 488 | .\" .,+ -- Concatenate the elements of a space-delimited list. 489 | .\" 490 | .\" Usage: 491 | .\" .,+ [OUT-STR] [LIST] [SEPARATOR] 492 | .\" 493 | .\" Example: 494 | .\" .,+ XY "Foo Bar Baz" : 495 | .\" \*(XY => Foo:Bar:Baz 496 | .\" 497 | .\" Uses: 498 | .\" .4@ 499 | .\" 500 | .\" Clobbers: 501 | .\" \*(,^B 502 | .de ,+ 503 | . ds \\$1 504 | . de , >> 505 | . if \\\\$2>1 .as \\$1 \\$3 506 | . as \\$1 \\\\$1 507 | . >> 508 | . 4@ "\\$2" , 509 | . rm , 510 | .. 511 | . 512 | .\" .4@ -- Execute a macro for each item in a space-delimited list. 513 | .\" 514 | .\" For each entry, the macro is called once with three arguments: 515 | .\" $1 = The element in question 516 | .\" $2 = Its index of appearance (counted from 1, not 0) 517 | .\" $3 = Total number of elements in the list being processed 518 | .\" 519 | .\" Usage: 520 | .\" .4@ [LIST] [MACRO] 521 | .\" 522 | .\" Example: 523 | .\" .de XY 524 | .\" \\$2/\\$3: \\$1 525 | .\" .br 526 | .\" .. 527 | .\" .4@ "Foo Bar Baz" XY 528 | .\" Output: 529 | .\" 1/3: Foo 530 | .\" 2/3: Bar 531 | .\" 3/3: Baz 532 | .\" 533 | .\" Uses: 534 | .\" .ev 1 535 | .\" 536 | .\" Modifies: 537 | .\" .in -- Set to \n(.H in environment 1 (ditroff/otroff only) 538 | .\" 539 | .\" Clobbers: 540 | .\" \*(4^B \*(4^C \*(4^E \*(4^F \*(4\a \*(^B4 \*(^C4 \*(^F4 541 | .\" \n(4^B \n(4^C \n(4^E \n(4^F \n(4\a \n(^B4 \n(^C4 \n(^F4 542 | .de 4@ 543 | . 544 | . \" Heirloom Doctools freaks when needlessly pushing/popping environment 545 | . if !'\*($0'ditroff' .if !'\*($0'otroff' \{\ 546 | . do als 4 ev 547 | . ig @@ 548 | . \} 549 | . de 4 >> 550 | . ie \\\\$1 \{\ 551 | . if !\\\\n(.iu=\\n(.Hu \{\ 552 | . ev \\\\$1 553 | . in \\n(.Hu 554 | . \} 555 | . \} 556 | . el .if \\\\n(.iu=\\n(.Hu .ev 557 | . >> 558 | . ig @@ 559 | . @@ 560 | . 561 | . \" Toggle line "squeezing" 562 | . do aln .hy 4 563 | . do aln .warn 4 564 | . de 4 >> 565 | . ec 566 | . ie \\\\$1 \{\ 567 | . 4 1 568 | . na 569 | . nh 570 | . fi 571 | . ll \\n(.Hu 572 | . do warn 0 573 | . nr 4 1 574 | . \} 575 | . el .if \\\\n(4=1 \{\ 576 | . nr 4 0 577 | . ad \\n(.j 578 | . ll \\n(.lu 579 | . if \\n(.u=0 .nf 580 | . hy 581 | . do hy \\n(4 582 | . do warn \\n(4 583 | . 4 584 | . \} 585 | . >> 586 | . 4 1 587 | . 588 | . \" Sanity checks 589 | . ds 4 \\$1 590 | . if !\w'\\*(4' .ig << \" Empty list 591 | . if '\\$2'' .ig << \" Missing argument 592 | . 593 | . \" Compute total number of entries 594 | . di 4 595 | \\$1 596 | . br 597 | . nr 4 \\n(.d/\\n(.v 598 | . di 599 | . 600 | . \" Output collected from callback invocations 601 | . di 4 602 | . di 603 | . nr 4 0 \" Flag indicating that output was generated 604 | . 605 | . \" Callback wrapper 606 | . de 4 >> 607 | . 4 608 | . nr 4 \\\\n(4 609 | ' da 4 610 | ' if \\\\n(.$>0 '\\$2 \\\\$1 \\\\n+(4 \\n(4 611 | ' if \\\\n(.$>1 '\\$2 \\\\$2 \\\\n+(4 \\n(4 612 | ' if \\\\n(.$>2 '\\$2 \\\\$3 \\\\n+(4 \\n(4 613 | ' if \\\\n(.$>3 '\\$2 \\\\$4 \\\\n+(4 \\n(4 614 | ' if \\\\n(.$>4 '\\$2 \\\\$5 \\\\n+(4 \\n(4 615 | ' if \\\\n(.$>5 '\\$2 \\\\$6 \\\\n+(4 \\n(4 616 | ' if \\\\n(.$>6 '\\$2 \\\\$7 \\\\n+(4 \\n(4 617 | ' if \\\\n(.$>7 '\\$2 \\\\$8 \\\\n+(4 \\n(4 618 | ' if \\\\n(.$>8 '\\$2 \\\\$9 \\\\n+(4 \\n(4 619 | ' if !(\\\\n(.h=\\n(.h):(\\\\n(.d=\\n(.d) .nr 4 1 620 | ' if (\\\\n(4=1)&(\\\\n(4>=\\n(4) .br 621 | ' da 622 | ' if \\\\n(4=\\\\n(4 .nr 4 2 623 | . 4 1 624 | . ec  625 | . >> 626 | . 627 | . \" Diversion trap handler 628 | . de 4 >> 629 | . nr 4 0 630 | . ec 631 | . 4 632 | . ec  633 | .4  634 | . >> 635 | . 636 | . \" Iterate through blocks of 9 entries at a time 637 | . de 4 >> 638 | . if \\\\n(4<=\\n(4 .if !(\\\\n(4=9)&(\\n(4=9) \{\ 639 | . 4 1 640 | . nr 4 \\\\n(4 641 | . if !\\\\n(4=\\n(4 \{\ 642 | . nr 4 1 643 | . di 4 644 | . ie \\\\n(4>0 \{\ 645 | . dt \\\\n(4 4 646 | . ec  \} 647 | . el .4 648 | \\$1 649 | . br 650 | . di 651 | . ec 652 | . 653 | . \" Start next cycle 654 | . if \\\\n(4=0 .if !\\\\n(4=2 \{\ 655 | . 4 656 | . 4 657 | . \} 658 | . \} 659 | . \} 660 | . >> 661 | . 662 | . \" Repurpose line-count register for tracking iteration index 663 | . nr 4 0 1 664 | . 665 | . \" Conceal junk output in a throwaway diversion 666 | . di 4 667 | . 4 668 | . br 669 | . di 670 | . 671 | . \" Safety net 672 | . ig << 673 | . << 674 | . 675 | . \" Clean up 676 | . 4 677 | . rm 4 4 4 4 4 4 4 678 | . rr 4 4 4 4 4 4 4 679 | . 680 | . \" Print output buffered from callbacks, if any 681 | . if \\n(4=1 .4 682 | . rm 4 683 | . rr 4 684 | .. 685 | . 686 | .\" Spoon-feed mandoc(1) with a diversion-free variant 687 | .if '\*($0'mandoc' \{\ 688 | .de 4@ 689 | . de 4@-mandoc >> 690 | . nr 4@-mandoc-index 0 1 691 | . nr 4@-mandoc-total \\\\n(.$ 692 | . >> 693 | . 4@-mandoc \\$1 694 | . de 4@-mandoc >> 695 | . if \\\\n(.$>0 \{\ 696 | . \\$2 \\\\$1 \\\\n+[4@-mandoc-index] \\n[4@-mandoc-total] 697 | . shift 698 | . 4@-mandoc \\\\$* 699 | . \} 700 | . >> 701 | . 4@-mandoc \\$1 702 | . rm 4@-mandoc 703 | . rr 4@-mandoc-index 704 | . rr 4@-mandoc-total 705 | .. 706 | .\} 707 | . 708 | . 709 | .\" ===========================[ COMPATIBILITY ]============================{{{1 710 | . 711 | .\" Crude shims for $* and $@, used internally by Mono. 712 | .\" Doesn't support inline expansion; i.e., stuff like: 713 | .\" 714 | .\" .XY a \\*($* b 715 | .\" 716 | .\" Clobbers: \n($* \n($@ 717 | .\" \*($* \*($@ 718 | .\" 719 | . 720 | .nr $* 0 721 | .nr $@ 0 722 | .de $* 723 | . if !'\\$*'1 2 3' .nr $* 1 724 | . if !'\\$@'"1" "2" "3"' .nr $@ 1 725 | .. 726 | .$* 1 2 3 727 | .ds $* \\\\$* 728 | .ds $@ \\\\$@ 729 | .if \n($*=1 \{ .de $* 730 | \c 731 | \.ie \\\\n(.$=1 \\\\$1\c 732 | \.el .ie \\\\n(.$=2 \\\\$1 \\\\$2\c 733 | \.el .ie \\\\n(.$=3 \\\\$1 \\\\$2 \\\\$3\c 734 | \.el .ie \\\\n(.$=4 \\\\$1 \\\\$2 \\\\$3 \\\\$4\c 735 | \.el .ie \\\\n(.$=5 \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5\c 736 | \.el .ie \\\\n(.$=6 \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5 \\\\$6\c 737 | \.el .ie \\\\n(.$=7 \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5 \\\\$6 \\\\$7\c 738 | \.el .ie \\\\n(.$=8 \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5 \\\\$6 \\\\$7 \\\\$8\c 739 | \.el .if \\\\n(.$>8 \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5 \\\\$6 \\\\$7 \\\\$8 \\\\$9\c 740 | .. \} 741 | .if \n($@=1 \{ .de $@ 742 | \c 743 | \.ie \\\\n(.$=1 \&"\\\\$1"\c 744 | \.el .ie \\\\n(.$=2 \&"\\\\$1" "\\\\$2"\c 745 | \.el .ie \\\\n(.$=3 \&"\\\\$1" "\\\\$2" "\\\\$3"\c 746 | \.el .ie \\\\n(.$=4 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4"\c 747 | \.el .ie \\\\n(.$=5 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4" "\\\\$5"\c 748 | \.el .ie \\\\n(.$=6 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4" "\\\\$5" "\\\\$6"\c 749 | \.el .ie \\\\n(.$=7 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4" "\\\\$5" "\\\\$6" "\\\\$7"\c 750 | \.el .ie \\\\n(.$=8 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4" "\\\\$5" "\\\\$6" "\\\\$7" "\\\\$8"\c 751 | \.el .if \\\\n(.$>8 \&"\\\\$1" "\\\\$2" "\\\\$3" "\\\\$4" "\\\\$5" "\\\\$6" "\\\\$7" "\\\\$8" "\\\\$9"\c 752 | .. \} 753 | .rr $* 754 | .rr $@ 755 | . 756 | . 757 | .\" ==========================[ CASE CONVERSION ]==========================={{{1 758 | . 759 | .\" .!! -- Print arguments in uppercase. 760 | .\" 761 | .\" If the first argument is \&, the second argument is interpreted 762 | .\" as the name of a string (or diversion) to convert the casing of. 763 | .\" 764 | .\" Usage: 765 | .\" .!! [TEXT] 766 | .\" .!! \& [VAR-NAME] 767 | .\" 768 | .\" Example: 769 | .\" .!! Synopsis 770 | .\" .!! See also 771 | .\" .!! \& doc:title 772 | .\" 773 | .\" Uses: 774 | .\" \*($* 775 | .\" 776 | .\" Clobbers: 777 | .\" \*(!^B 778 | .\" \n(!^B 779 | .de !! 780 | . \" Use Groff's .stringup request if available 781 | . if d stringup \{\ 782 | . if '\&'\\$1' .if d \\$2 \{\ 783 | . stringup \\$2 784 | . return 785 | . \} 786 | . ds ! \\$* 787 | . stringup ! 788 | \&\\*(! 789 | . rm ! 790 | . return 791 | . \} 792 | . 793 | . \" Modify by reference 794 | . if '\&'\\$1' .if d \\$2 \{\ 795 | . nr ! 1 796 | . di ! 797 | . \} 798 | . tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ 799 | . tr \(*a\(*A\(*b\(*B\(*g\(*G\(*d\(*D\(*e\(*E\(*z\(*Z\(*y\(*Y\(*h\(*H\(*i\(*I\(*k\(*K\(*l\(*L\(*m\(*M 800 | . tr \(*n\(*N\(*c\(*C\(*o\(*O\(*p\(*P\(*r\(*R\(*s\(*S\(*t\(*T\(*u\(*U\(*f\(*F\(*x\(*X\(*q\(*Q\(*w\(*W 801 | \*($* 802 | . tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz 803 | . tr \(*a\(*a\(*b\(*b\(*g\(*g\(*d\(*d\(*e\(*e\(*z\(*z\(*y\(*y\(*h\(*h\(*i\(*i\(*k\(*k\(*l\(*l\(*m\(*m 804 | . tr \(*n\(*n\(*c\(*c\(*o\(*o\(*p\(*p\(*r\(*r\(*s\(*s\(*t\(*t\(*u\(*u\(*f\(*f\(*x\(*x\(*q\(*q\(*w\(*w 805 | . if \\n(!=1 .di 806 | . rr ! 807 | .. 808 | . 809 | .\" '.. -- Print arguments in lowercase. 810 | .\" 811 | .\" Usage: 812 | .\" '.. [TEXT] 813 | .\" '.. \& [VAR-NAME] 814 | .\" 815 | .\" Example: 816 | .\" '.. LOUD NOISES 817 | .\" '.. \& DOC*TITLE 818 | .\" 819 | .\" Uses: 820 | .\" \*($* 821 | .\" 822 | .\" Clobbers: 823 | .\" \*(!^B 824 | .\" \n(!^B 825 | .de .. 826 | . \" Use Groff's .stringdown request if available 827 | . if d stringdown \{\ 828 | . if '\&'\\$1' .if d \\$2 \{\ 829 | . stringdown \\$2 830 | . return 831 | . \} 832 | . ds ! \\$* 833 | . stringdown ! 834 | \&\\*(! 835 | . rm ! 836 | . return 837 | . \} 838 | . 839 | . \" Modify by reference 840 | . if '\&'\\$1' .if d \\$2 \{\ 841 | . nr ! 2 842 | . di ! 843 | . \} 844 | . tr AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz 845 | . tr \(*A\(*a\(*B\(*b\(*G\(*g\(*D\(*d\(*E\(*e\(*Z\(*z\(*Y\(*y\(*H\(*h\(*I\(*i\(*K\(*k\(*L\(*l\(*M\(*m 846 | . tr \(*N\(*n\(*C\(*c\(*O\(*o\(*P\(*p\(*R\(*r\(*S\(*s\(*T\(*t\(*U\(*u\(*F\(*f\(*X\(*x\(*Q\(*q\(*W\(*w 847 | \*($* 848 | . tr AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ 849 | . tr \(*A\(*A\(*B\(*B\(*G\(*G\(*D\(*D\(*E\(*E\(*Z\(*Z\(*Y\(*Y\(*H\(*H\(*I\(*I\(*K\(*K\(*L\(*L\(*M\(*M 850 | . tr \(*N\(*N\(*C\(*C\(*O\(*O\(*P\(*P\(*R\(*R\(*S\(*S\(*T\(*T\(*U\(*U\(*F\(*F\(*X\(*X\(*Q\(*Q\(*W\(*W 851 | . if \\n(!=2 .di 852 | . nr ! 1 853 | .. 854 | . 855 | . 856 | .\" ================================[ MAPS ]================================{{{1 857 | .\" Basic key/value hash structures in pure Roff. 858 | .\" 859 | .\" Provides a means of storing values under names longer than 2 characters, 860 | .\" but makes no assumptions about compatibility mode and/or implementation. 861 | . 862 | .\" Counter used when generating IDs automatically 863 | .nr # 1 864 | . 865 | .\" .?# -- Set register $3 to 1 if a key named $2 exists in $1 866 | .\" 867 | .\" Usage: 868 | .\" .?# [MAP-NAME] [KEY] [OUT-NR] 869 | .\" 870 | .\" Examples: 871 | .\" .?# COLOURS red HAVE-RED? 872 | .\" \n[HAVE-RED?] => 1 873 | .de ?# 874 | . if !'\\$3'' .rr \\$3 875 | .. 876 | . 877 | .\" .#? -- Set register $3 to 1 if $1 has an entry with a value of $2. 878 | .\" 879 | .\" Usage: 880 | .\" .#? [MAP-NAME] [VALUE] [OUT-NR] 881 | .\" 882 | .\" Examples: 883 | .\" .#? COLOURS "#ff0000" HAVE-RED? 884 | .\" \n[HAVE-RED?] => 1 885 | .de #? 886 | . if !'\\$3'' .rr \\$3 887 | .. 888 | . 889 | .\" .#< -- Retrieve an entry named $2 stored in $1. 890 | .\" 891 | .\" Usage: 892 | .\" .#< [MAP-NAME] [KEY] [OUT-STR] 893 | .\" 894 | .\" Example: 895 | .\" .#< COLOURS red HEX-CODE 896 | .\" \*[HEX-CODE] => "#ff0000" 897 | .de #< 898 | . if !'\\$3'' .rm \\$3 899 | .. 900 | . 901 | .\" .#> -- Store an entry in $1 named $2 with value $3. 902 | .\" 903 | .\" Usage: 904 | .\" .#> [MAP-NAME] [KEY] [VALUE] 905 | .\" 906 | .\" Example: 907 | .\" .#> COLOURS red "#ff0000" 908 | .de #> 909 | . am ?# >> 910 | . if '\\\\$1'\\$1' .if '\\\\$2'\\$2' .nr \\\\$3 1 911 | . >> 912 | . am #? >> 913 | . if '\\\\$1'\\$1' .if '\\\\$2'\\$3' .nr \\\\$3 1 914 | . >> 915 | . am #< >> 916 | . if '\\\\$1'\\$1' .if '\\\\$2'\\$2' .ds \\\\$3 \\$3 917 | . >> 918 | .. 919 | . 920 | .\" .#+ -- Assign a unique identifier to $1 921 | .\" 922 | .\" Usage: 923 | .\" .#+ [VALUE] [ID] [OUT-STR] 924 | .\" 925 | .\" Clobbers: 926 | .\" \n($? 927 | .de #+ 928 | . #? ID "\\$2" $? 929 | . 930 | . \" ID already exists 931 | . ie \\n($?=1 \{\ 932 | . #? ID "\\$2-\\n(#" $? 933 | . 934 | . \" Suffixed ID exists too; increment and try again 935 | . ie \\n($?=1 \{\ 936 | . nr # \\n(#+1 937 | . #+ "\\$1" "\\$2" 938 | . \} 939 | . 940 | . \" This suffix is free; use it 941 | . el \{\ 942 | . #> ID "\\$1" "\\$2-\\n(#" 943 | . if !'\\$3'' .#< ID "\\$1" \\$3 944 | . \} 945 | . \} 946 | . 947 | . \" ID not yet allocated; use it 948 | . el \{\ 949 | . #> ID "\\$1" "\\$2" 950 | . if !'\\$3'' .#< ID "\\$1" \\$3 951 | . \} 952 | . 953 | . \" Clean up 954 | . rr $? 955 | .. 956 | . 957 | . 958 | .\"==============================[ HYPERLINKS ]============================={{{1 959 | . 960 | .\" Strings inserted before and after links rendered by non-interactive mediums 961 | .if n .ds [_ \fI 962 | .if n .ds _] \fP 963 | . 964 | .\" .[ -- Format-agnostic hyperlinks. 965 | .\" 966 | .\" Usage: 967 | .\" .[ [TEXT] "](" [URL] ")" [AFFIX] 968 | .\" .[ [TEXT] "]<" [EMAIL] ">" [AFFIX] 969 | .\" .[ [TEXT] "][" [ANCHOR] "]" [AFFIX] 970 | .\" .[ [URL] "]()" [AFFIX] 971 | .\" .[ [EMAIL] "]<>" [AFFIX] 972 | .\" .[ [ANCHOR] "][]" [AFFIX] 973 | .\" .[ [ANCHOR] "]" [AFFIX] 974 | .\" 975 | .\" Examples: 976 | .\" .[ eBay ]( https://ebay.com ) 977 | .\" .[ Contact ]< contact@author.com > 978 | .\" .[ Term ][ term-id ] \" See .# 979 | .\" 980 | .\" Trailing punctuation using the affix parameter: 981 | .\" .[ Details ]( " (visit " http://url " for more information)" ) , 982 | .\" .[ Term-ID ][ " (q.v. " term-id ", section 3.2)" ] , 983 | .\" .[ "Send an e-mail" ]< " to " email@address.com "" > . 984 | .\" 985 | .\" Shorthand forms: 986 | .\" .[ https://ebay.com ]() \" Same as .[ https://ebay.com ]( https://ebay.com ) 987 | .\" .[ foo@bar.com ]<> \" Same as .[ foo@bar.com ]< foo@bar.com > 988 | .\" .[ Term ][] \" Same as .[ Term ][ Term ] 989 | .\" .[ Term ] \" As above 990 | .\" 991 | .\" Uses: 992 | .\" \*([_ 993 | .\" \*(_] 994 | .\" 995 | .\" TODO: 996 | .\" * Support Heirloom Doctools' dpost(1) and dhtml(1) 997 | .\" * Support Neatroff's neatpdf(1) 998 | . 999 | .\" Printed/non-interactive 1000 | .de [ 1001 | . if ']('\\$2' \{\ 1002 | . if !'\\$3'\\$1' .if !'\\$3'\\$1/' \ 1003 | . if !'\\$3'http://\\$1' .if !'\\$3'http://\\$1/' \ 1004 | . if !'\\$3'https://\\$1' .if !'\\$3'https://\\$1/' \ 1005 | . if !'\\$3'mailto:\\$1' \{\ 1006 | . ie ')'\\$6' \&\\$1\\$3\\$4\\$5\\$7 1007 | . el \&\\$1 (\\*([_\\$3\\*(_])\\$5 1008 | . ig >> 1009 | . \} 1010 | \&\\*([_\\$1\\*(_]\\$5 1011 | . ig >> 1012 | . >> 1013 | . \} 1014 | . if ']['\\$2' \{\ 1015 | . ie ']'\\$6' \&\\$1\\$3\\$4\\$5\\$7 1016 | . el \&\\$1\\$5 1017 | . \} 1018 | . if ']<'\\$2' \{\ 1019 | . ie '\\$1'\\$3' \&\\*([_\\$1\\*(_]\\$5 1020 | . el .ie '>'\\$6' \&\\$1\\$3\\$4\\$5\\$7 1021 | . el \&\\$1 <\\*([_\\$3\\*(_]>\\$5 1022 | . \} 1023 | . if '\\$2']<>' \&\\*([_\\$1\\*(_]\\$3 1024 | . if '\\$2']()' \&\\*([_\\$1\\*(_]\\$3 1025 | . if '\\$2'][]' \&\\$1\\$3 1026 | . if '\\$2']' \&\\$1\\$3 1027 | .. 1028 | . 1029 | .\" HTML: Groff 1030 | .nop .if r ps4html .rm [ \" HACK: Fix pre-grohtml(1) 1031 | .if '\*(.T'html' \{ .de [ 1032 | . if ']('\\$2' \{\ 1033 | . ie ')'\\$6' \X'html:'\\$1\X'html:'\\$7 1034 | . el \X'html:'\\$1\X'html:'\\$5 \} 1035 | . if ']['\\$2' \{\ 1036 | . ie ']'\\$6' \X'html:'\\$1\X'html:'\\$7 1037 | . el \X'html:'\\$1\X'html:'\\$5 \} 1038 | . if ']<'\\$2' \{\ 1039 | . ie '>'\\$6' \X'html:'\\$1\X'html:'\\$7 1040 | . el \X'html:'\\$1\X'html:'\\$5 \} 1041 | . if '\\$2']<>' \X'html:'\\$1\X'html:'\\$3 1042 | . if '\\$2']()' \X'html:'\\$1\X'html:'\\$3 1043 | . if '\\$2'][]' \X'html:'\\$1\X'html:'\\$3 1044 | . if '\\$2']' \X'html:'\\$1\X'html:'\\$3 1045 | .. \} 1046 | . 1047 | .\" PDF: Groff 1048 | .if '\*(.T'pdf' \{ .de [ 1049 | . if ']('\\$2' \{\ 1050 | . ie ')'\\$6' .nop .pdfhref W -A \&\\$7 -D "\\$4" -- \\$1 1051 | . el .nop .pdfhref W -A \&\\$5 -D "\\$3" -- \\$1 \} 1052 | . if ']['\\$2' \{\ 1053 | . ie ']'\\$6' .nop .pdfhref L -A \&\\$7 -D "\\$4" -- \\$1 1054 | . el .nop .pdfhref L -A \&\\$5 -D "\\$3" -- \\$1 \} 1055 | . if ']<'\\$2' \{\ 1056 | . ie '>'\\$6' .nop .pdfhref W -A \&\\$7 -D "mailto:\\$4" -- \\$1 1057 | . el .nop .pdfhref W -A \&\\$5 -D "mailto:\\$3" -- \\$1 \} 1058 | . if '\\$2']<>' .nop .pdfhref L -A \&\\$3 -D "mailto:\\$1" -- \\$1 1059 | . if '\\$2']()' .nop .pdfhref W -A \&\\$3 -D "\\$1" -- \\$1 1060 | . if '\\$2'][]' .nop .pdfhref L -A \&\\$3 -D "\\$1" -- \\$1 1061 | . if '\\$2']' .nop .pdfhref L -A \&\\$3 -D "\\$1" -- \\$1 \} 1062 | .. \} 1063 | . 1064 | . 1065 | .\" ==============================[ ANCHORS ]==============================={{{1 1066 | . 1067 | .\" Outline level (PDF only) 1068 | .nr #L 0 1069 | . 1070 | .\" .# -- Declare a named destination such as a heading, symbol definition, 1071 | .\" navigation landmark, or anything else that needs to be referenced 1072 | .\" or linked to from somewhere. Contributes to the document outline; 1073 | .\" i.e., menus, tables of contents, PDF outlines, etc. 1074 | .\" 1075 | .\" Usage: 1076 | .\" .# [TEXT] [ID] [AFFIX] 1077 | .\" 1078 | .\" Derive ID from $1 using the .#+ and .~- macros: 1079 | .\" .# [TEXT-AND-ID] 1080 | .\" .# [TEXT-AND-ID] "" [AFFIX] 1081 | .\" 1082 | .\" Examples: 1083 | .\" .# SYNOPSIS: 1084 | .\" .# "Related links" see-also \" Text that differs noticeably from ID 1085 | .\" .# "" hidden-anchor 1086 | .\" 1087 | .\" Uses: 1088 | .\" \*($0 1089 | .\" \n(#L 1090 | .\" 1091 | .\" Clobbers: 1092 | .\" \*(#^B 1093 | .\" 1094 | .\" Modifies: 1095 | .\" \*[PDFBOOKMARK.VIEW] 1096 | .\" \*[PDFHREF.VIEW] 1097 | . 1098 | .\" Header 1099 | .de # 1100 | . if \\n(.$=0 .ig >> 1101 | . ie !'\\$2'' .~- # "\\$2" 1102 | . el \\n(.$=1 .~- # "\\$1" 1103 | . #+ "\\$1" "\\*(#" # 1104 | .. 1105 | . 1106 | .\" Body: Heirloom Doctools 1107 | .ie '\*($0'heirloom' \{ .am # 1108 | . ie '\\$1'' \\A'\\*(#'\\$3 1109 | . el \\A'\\*(#'\\X'PDFMark: Bookmark \\n(#L \\$1'\\$1\\$3 1110 | .. \} 1111 | .el \{\ 1112 | . 1113 | .\" Body: Printed/non-interactive 1114 | .if !'\*(.T'html' \{\ 1115 | .if !'\*(.T'pdf' \{\ 1116 | .am # 1117 | . if !'\\$1\\$3'' \&\\$1\\$3 1118 | .. \}\} 1119 | . 1120 | .\" Body: HTML 1121 | .nop .if r ps4html .rm # \" HACK: Fix pre-grohtml(1) 1122 | .if '\*(.T'html' \{ .am # 1123 | . ie '\\$1\\$3'' \X'html:'\c 1124 | . el \X'html:'\\$1\X'html:'\\$3 1125 | .. \} 1126 | . 1127 | .\" Body: PDF 1128 | .if '\*(.T'pdf' \{\ 1129 | .nop .ds PDFBOOKMARK.VIEW /XYZ 0 \\n[PDFPAGE.Y] u 0 1130 | .nop .ds PDFHREF.VIEW /XYZ 0 \\n[PDFPAGE.Y] u 0 1131 | .am # 1132 | . ie '\\$1'' .pdfhref M -N "\\*(#" 1133 | . el .pdfhref O -T "\\*(#" \\n(#L "\\$1" 1134 | . if !'\\$1\\$3'' \&\\$1\\$3 1135 | .. \} 1136 | . 1137 | .\} 1138 | .\" Footer 1139 | .am # 1140 | . rm # 1141 | . ig >> 1142 | . >> 1143 | .. 1144 | -------------------------------------------------------------------------------- /t/0-includes.roff: -------------------------------------------------------------------------------- 1 | .ds ^ circumflex or caret 2 | .ds ~ tidle 3 | .ds ' apostrophe 4 | .ds - hyphen or dash. Take your pick. 5 | .nf 6 | .so ono.tmac 7 | ^ is a \*^ 8 | ~ is a \*~ 9 | \&' is an \*' 10 | - is a \*- 11 | -------------------------------------------------------------------------------- /t/1-monospace.roff: -------------------------------------------------------------------------------- 1 | '\" t 2 | .so ./ono.tmac 3 | .TS 4 | l l l . 5 | Mono nroff troff 6 | = 7 | \*(CW\e*(CW\fP \fR\efR\fP \f(CR\ef(CR\fP 8 | \*(C?\e*(C?\fP \fI\efI\fP \f(CW\ef(CW\fP 9 | \*(C!\e*(C!\fP \fB\efB\fP \f(CR\ef(CR\fP 10 | \*(CI\e*(CI\fP \f(CI\ef(CI\fP \f(CI\ef(CI\fP 11 | \*(CB\e*(CB\fP \f(CB\ef(CB\fP \f(CB\ef(CB\fP 12 | \*(CE\e*(CE\fP \f(BI\ef(BI\fP \f[CBI]\ef[CBI]\fP 13 | .TE 14 | . 15 | '\" vim: ts=10 16 | -------------------------------------------------------------------------------- /t/2-ascii-chars.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | .if t \{\ 3 | . ps 30p 4 | . vs 30p 5 | . sp 3m 6 | .\} 7 | .nf 8 | \&\*' Single-quote 9 | \&\*- Dash 10 | \&\*~ Tilde 11 | \&\*^ Caret 12 | .ft CW 13 | \&\*' Single-quote 14 | \&\*- Dash 15 | \&\*~ Tilde 16 | \&\*^ Caret 17 | -------------------------------------------------------------------------------- /t/3-underlines.roff: -------------------------------------------------------------------------------- 1 | .so ono.tmac 2 | . 3 | ABC 4 | .UL "FOO BAR BAZ" 5 | XYZ 6 | .sp 2 7 | . 8 | ABC 9 | .UL "FOO BAR COMMA" , 10 | XYZ 11 | .sp 2 12 | . 13 | ABC 14 | .UL [ "THIS HAS BRACKETS" ] 15 | XYZ 16 | .sp 2 17 | . 18 | . 19 | .sp 2 20 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. 21 | Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 22 | Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. 23 | Nisi ut aliquip ex ea commodo consequat. 24 | .UL "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur." 25 | Excepteur sint occaecat cupidatat non proident. 26 | Sunt in culpa qui officia deserunt mollit anim id est laborum. 27 | -------------------------------------------------------------------------------- /t/4-code-blocks.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | Before 4 | .`` js 5 | let foo = new Foo("bar"); 6 | foo.toString(); // Comment 7 | .`` 8 | After 9 | . 10 | .sp 2 11 | Before 12 | .`` js 10 13 | if(true){ 14 | \& return 1; 15 | } 16 | .`` 17 | After 18 | -------------------------------------------------------------------------------- /t/5-arg-lists.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .de XY 4 | Arguments: [\*($*] 5 | .br 6 | Quoted arguments: [\*($@] 7 | .sp 8 | .. 9 | . 10 | .ce 1 11 | \f(BIFILLED\fP 12 | .br 13 | <<< 14 | .XY 15 | .XY AAA 16 | .XY AAA BBB 17 | .XY AAA BBB CCC 18 | .XY AAA BBB CCC DDD 19 | .XY AAA BBB CCC DDD EEE 20 | .XY AAA BBB CCC DDD EEE FFF 21 | .XY AAA BBB CCC DDD EEE FFF GGG 22 | .XY AAA BBB CCC DDD EEE FFF GGG HHH 23 | .XY AAA BBB CCC DDD EEE FFF GGG HHH III 24 | .XY AAA BBB CCC DDD EEE FFF GGG HHH III JJJ 25 | >>> 26 | .sp 2 27 | . 28 | .ce 1 29 | \f(BIUNFILLED\fP 30 | .nf 31 | <<< 32 | .XY 33 | .XY AAA 34 | .XY AAA BBB 35 | .XY AAA BBB CCC 36 | .XY AAA BBB CCC DDD 37 | .XY AAA BBB CCC DDD EEE 38 | .XY AAA BBB CCC DDD EEE FFF 39 | .XY AAA BBB CCC DDD EEE FFF GGG 40 | .XY AAA BBB CCC DDD EEE FFF GGG HHH 41 | .XY AAA BBB CCC DDD EEE FFF GGG HHH III 42 | .XY AAA BBB CCC DDD EEE FFF GGG HHH III JJJ 43 | >>> 44 | -------------------------------------------------------------------------------- /t/6.1-string-length.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .ds AZ ABCDEFGHIJKLMNOPQRSTUVWXYZ 4 | .$# xy \*(AZ 5 | There are \n(xy letters in the Latin alphabet. 6 | .sp 1 7 | . 8 | .ds AZ Arizona 9 | .$# xy \*(AZ 10 | The name "\*(AZ" is \n(xy letters long. 11 | .sp 1 12 | . 13 | .ds AZ I 14 | .$# xy \*(AZ 15 | The word "\*(AZ" has only \n(xy letter. 16 | -------------------------------------------------------------------------------- /t/6.2-string-slugs.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .~- xy "Foo bar" 4 | .ie 'foo-bar'\*(xy' Yes 5 | .el No: [\*(xy] 6 | .br 7 | . 8 | .~- xy " (Here's) an ID string. M8 " 9 | .ie 'heres-an-id-string-m8'\*(xy' Yes 10 | .el No: [\*(xy] 11 | .br 12 | . 13 | .\" FIXME 14 | .~- xy " Here's an ""ID"" string ++1 2 3_4 5 6 7 8 9" 15 | .ie '\*(xy'heres-an-id-string-1-2-3-4-5-6-7-8-9' Yes 16 | .el No: [\*(xy] 17 | .br 18 | -------------------------------------------------------------------------------- /t/6.3-string-foreach.roff: -------------------------------------------------------------------------------- 1 | .mso ono.tmac 2 | .nf 3 | . 4 | .de + 5 | . as _ \\$1 6 | .. 7 | . 8 | .ds _ 9 | .4@ ".1" + 10 | [\*_] 11 | . 12 | .ds _ 13 | .4@ ".1 .2" + 14 | [\*_] 15 | . 16 | .ds _ 17 | .4@ ".1 .2 .3" + 18 | [\*_] 19 | . 20 | .ds _ 21 | .4@ ".1 .2 .3 .4" + 22 | [\*_] 23 | . 24 | .ds _ 25 | .4@ ".1 .2 .3 .4 .5" + 26 | [\*_] 27 | . 28 | .ds _ 29 | .4@ ".1 .2 .3 .4 .5 .6" + 30 | [\*_] 31 | . 32 | .ds _ 33 | .4@ ".1 .2 .3 .4 .5 .6 .7" + 34 | [\*_] 35 | . 36 | .ds _ 37 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8" + 38 | [\*_] 39 | . 40 | .ds _ 41 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9" + 42 | [\*_] 43 | . 44 | .ds _ 45 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10" + 46 | [\*_] 47 | . 48 | .ds _ 49 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11" + 50 | [\*_] 51 | . 52 | .ds _ 53 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12" + 54 | [\*_] 55 | . 56 | .ds _ 57 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13" + 58 | [\*_] 59 | . 60 | .ds _ 61 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14" + 62 | [\*_] 63 | . 64 | .ds _ 65 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15" + 66 | [\*_] 67 | . 68 | .ds _ 69 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16" + 70 | [\*_] 71 | . 72 | .ds _ 73 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17" + 74 | [\*_] 75 | . 76 | .ds _ 77 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17 .18" + 78 | [\*_] 79 | . 80 | .ds _ 81 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17 .18 .19" + 82 | [\*_] 83 | . 84 | .ds _ 85 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17 .18 .19 .20" + 86 | [\*_] 87 | . 88 | .ds _ 89 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17 .18 .19 .20 .21" + 90 | [\*_] 91 | . 92 | .ds _ 93 | .4@ ".1 .2 .3 .4 .5 .6 .7 .8 .9 .10 .11 .12 .13 .14 .15 .16 .17 .18 .19 .20 .21 .22" + 94 | [\*_] 95 | -------------------------------------------------------------------------------- /t/6.4-string-concat.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .,+ XY "Foo Bar Baz" 4 | . 5 | .ie '\*(XY'FooBarBaz' Yes 6 | .el No: \*(XY 7 | . 8 | .,+ XY " Foo Bar Baz " - 9 | .ie '\*(XY'Foo-Bar-Baz' Yes 10 | .el No: \*(XY 11 | . 12 | .,+ XY " Foo Bar Baz " . 13 | .ie '\*(XY'Foo.Bar.Baz' Yes 14 | .el No: \*(XY 15 | . 16 | .,+ N 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 | .ie '\*N'1-2-3-4-5-6-7-8-9-10-11-12-13-14-15' Yes 18 | .el No: \*N 19 | -------------------------------------------------------------------------------- /t/7-case.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .de $ == 4 | .\" Latin 5 | Arguments printed without case-conversion. 6 | .!! Arguments printed in uppercase. 7 | ... Arguments printed in lowercase. 8 | . 9 | .\" Greek 10 | \(*M\(*y \(*t\(*r\(*o\(*p\(*o\(*p\(*o\(*i\(*y\(*m\(*e\(*n\(*o \(*e\(*l\(*l\(*y\(*n\(*i\(*k\(*o. 11 | .!! \(*K\(*e\(*f\(*a\(*l\(*a\(*i\(*a \(*E\(*l\(*l\(*y\(*n\(*i\(*k\(*a. 12 | ... \(*P\(*e\(*z\(*a \(*E\(*l\(*l\(*y\(*n\(*i\(*k\(*a. 13 | . 14 | .\" Both at once 15 | Latin & \(*E\(*l\(*l\(*y\(*n\(*i\(*k\(*a. 16 | .!! Latin & \(*E\(*l\(*l\(*y\(*n\(*i\(*k\(*a. 17 | ... Latin & \(*E\(*l\(*l\(*y\(*n\(*i\(*k\(*a. 18 | .== 19 | . 20 | .nf 21 | .$ 22 | .sp 23 | .fi 24 | .$ 25 | -------------------------------------------------------------------------------- /t/8.1-anchor-ids.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .nf 4 | .#+ "A) Foo" foo 5 | .#> "A) Foo" id 6 | \*(id === foo 7 | . 8 | .#+ "B) Bar" 9 | .#> "B) Bar" id 10 | \*(id === id 11 | . 12 | .#+ "C) Baz" 13 | .#> "C) Baz" id 14 | \*(id === id-1 15 | . 16 | .#+ "D) Qux" foo 17 | .#> "D) Qux" id 18 | \*(id === foo-1 19 | . 20 | .#+ "E) Qul" foo 21 | .#> "E) Qul" id 22 | \*(id === foo-2 23 | . 24 | .#+ "F) Fax" foo-3 25 | .#> "F) Fax" id 26 | \*(id === foo-3 27 | . 28 | .#+ "G) Gaz" foo 29 | .#> "G) Gaz" id 30 | \*(id === foo-4 31 | . 32 | foo === \c 33 | .#> "A) Foo" 34 | -------------------------------------------------------------------------------- /t/8.2-anchor-args.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | .\" HACK: Make vertical offset of PDF bookmarks easier to notice/test 4 | .if t \{\ 5 | . blm br 6 | . de br 7 | . sp 5 8 | . . 9 | .. \} 10 | . 11 | .nf 12 | .# \" No arguments 13 | Ignored. 14 | 15 | .# Text 16 | Display $1, generate ID automatically using \en(## register. 17 | 18 | .# Text id 19 | Display $1, use $2 for ID. 20 | 21 | .# Text id affix 22 | Display the concatenation of $1 and $3, use $2 for ID. 23 | 24 | .# "" hidden-anchor 25 | If PDF, insert a named destination without an outline entry. 26 | If HTML, insert without any following whitespace. 27 | Ignored in every other format. 28 | -------------------------------------------------------------------------------- /t/9.1-hyperlinks.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | . 3 | Before 4 | .[ Foo ]( https://foo.com ) , 5 | .[ bar.com ]( https://bar.com ) , 6 | .[ .toUpperCase() ][ String.prototype.toUpperCase ] , 7 | and 8 | .[ Baz ] . 9 | After 10 | . 11 | .bp 12 | .# String.prototype.toUpperCase 13 | The \*(CBtoUpperCase()\fP method returns the calling string value converted to uppercase. 14 | . 15 | .bp 16 | .# Baz 17 | At least it's not foo. 18 | -------------------------------------------------------------------------------- /t/9.2-hyperlinks.roff: -------------------------------------------------------------------------------- 1 | .so ./ono.tmac 2 | .nf 3 | . 4 | .[ https://url1.com ]() , 5 | .[ "https://url2.com" ]() , 6 | .[ https://url3.com/bad\ filename ]() , 7 | .[ "https://url4.com/worse\ file""name" ]() . 8 | . 9 | .[ email1@address ]<> , 10 | .[ "email2@address" ]<> , 11 | .[ email3@bad\ address ]<> , 12 | .[ "email4@bad\ add""ress" ]<> . 13 | . 14 | .[ anchor-id1 ][] , 15 | .[ anchor-id2 ][] , 16 | .[ "ancho""r\ id3" ][] , 17 | .[ anchor-id4 ] , 18 | .[ anchor\ id5 ] , 19 | .[ "ancho""r\ id6" ] . 20 | . 21 | . 22 | .[ Link\~1 ]( https://url1.com ) , 23 | .[ "Link 2" ]( "https://url2.com" ) , 24 | .[ Link\ 3 ]( https://ur\ l3.com ) . 25 | . 26 | .[ Anchor\~1 ][ anchor1-id ] , 27 | .[ "Anchor 2" ][ "anchor2-id" ] , 28 | .[ Anchor\ 3 ][ anchor3\ id ] . 29 | . 30 | .[ E-mail\~1 ]< email1@address > , 31 | .[ "E-mail 2" ]< "email2@address" > , 32 | .[ E-mail\ 3 ]< email3@\ address > . 33 | . 34 | . 35 | .\" Realistic examples 36 | .[ Details ]( " (visit " http://url " for more information)" ) , 37 | .[ Term-ID ][ " (q.v. " term-id ", section 3.2)" ] , 38 | .[ "Send an e-mail" ]< " to " email@address.com "" > . 39 | -------------------------------------------------------------------------------- /t/debug-utils.roff: -------------------------------------------------------------------------------- 1 | .\" .? -- Print arguments in an unambiguous fashion 2 | .de ? 3 | . tm \\n(.$ argument(s) 4 | . if !'\\$1'\\$1' \ 5 | . tm NOT strings! 6 | . if \\n(.$>0 .tm $1 = \\$1 7 | . if \\n(.$>1 .tm $2 = \\$2 8 | . if \\n(.$>2 .tm $3 = \\$3 9 | . if \\n(.$>3 .tm $4 = \\$4 10 | . if \\n(.$>4 .tm $5 = \\$5 11 | . if \\n(.$>5 .tm $6 = \\$6 12 | . if \\n(.$>6 .tm $7 = \\$7 13 | . if \\n(.$>7 .tm $8 = \\$8 14 | . if \\n(.$>8 .tm $9 = \\$9 15 | .. 16 | . 17 | .\"