6 This file is part of groff, the GNU roff type-setting system.
8 Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
9 written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.
11 groff is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 groff is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 .\" ******************************************************************
34 .\" ** Some macros and default settings needed by hdtbl **
35 .\" ******************************************************************
38 .\" Utility macro: .getarg <key> ...
40 .\" Get macro argument. This macro searches <key> in the
41 .\" remaining arguments and assigns its value to a string
42 .\" register named <key>. The following syntax forms are
45 .\" <key>=<val> Assign <val> to string <key>.
46 .\" <val> must not contain spaces.
47 .\" <key>='<val>' Assign <val> to string <key>.
48 .\" <val> can contain spaces.
49 .\" <key>= Assign `=' to string <key>.
50 .\" <key> Assign `key' to string <key>.
52 .\" After return, the string `args' contains the remaining
55 .\" Example: With the definition of string `foo' as
57 .\" .ds foo aaa=xxx bbb ccc='yyy zzz' ddd= eee
59 .\" a call to `getarg' with
61 .\" .getarg ccc \*[foo]
63 .\" sets string `ccc' to value `yyy zzz'. The string `args'
64 .\" now contains `aaa=xxx bbb ddd= eee'. An additional call
67 .\" .getarg ddd \*[args]
69 .\" sets string `ddd' to value `=', and `args' contains
70 .\" `aaa=xxx bbb eee'.
87 . if (\\n[*] > \\n[**]) \{\
88 . as args " "\\*[**]"\" value too short, repeat
91 . substring * 0 (\\n[*] - 1)
92 . \" The surrounding \? escapes emulate string comparison.
93 . ie !"\?\\*[$1]\?"\?\\*[*]\?" \{\
94 . as args " "\\*[**]"\" key not found, repeat
98 . ie "\?\\*[**]\?"\?\\*[$1]\?" \
99 . ds \\*[$1] \\*[$1]\" return key as string
101 . ie "\?\\*[**]\?"\?\\*[$1]=\?" \
102 . ds \\*[$1] =\" return `='
104 . substring ** (\\n[*] + 1) -1
108 . \" check whether value starts with quote
109 . if "\?\\*[*]\?"\?'\?" \{\
114 . \" search final quote
115 . ie "\?\\*[*]\?"\?'\?" \
118 . as \\*[$1] \\*[**] \" not found, append argument
121 . ds ** \\$1\" get next argument
126 . if "\?\\*[*]\?"\?'\?" \{\
128 . break \" break if no final quote
131 . as \\*[$1] \\*[**] \" otherwise append and repeat
135 . as \\*[$1] \\*[**]\"
146 .\" Utility macro: .index <string1> <string2>
148 .\" Check whether <string2> is a substring of <string2> and
149 .\" return its position in number register `index', starting
150 .\" with 1. If not found, return 0. If <string2> is empty,
151 .\" set `index' to -999.
162 . while (\\n+[*] < \\n[**]) \{\
164 . substring * \\n[*] (\\n[*] + \\n[$2] - 1)
165 . \" The surrounding \? escapes emulate string comparison.
166 . if "\?\\*[*]\?"\?\\$2\?" \
170 . ie (\\n[*] == \\n[**]) \
173 . nr index (\\n[*] + 1)
177 .\" ******************************************************************
178 .\" ******** non-accumulating space .SP [v] **********
180 .\" ** nl vor erster Seite -1, oben auf Seite 0 resp. tH **
181 .\" ** .k nach .sp oder .br 0, **
182 .\" ** sonst Laenge der angefangenen Zeile **
183 .\" ** Der Merker M# fuer vorangegangenes .SP wird in .HM am **
184 .\" ** Seitenanfang zurueckgesetzt. **
185 .\" ** ganz richtig ist .sp + .br = .br + .sp = .sp **
186 .\" ******************************************************************
189 . br \" start very first page
190 . nr * \\n[.p] \" save current page length
193 . pl +1 \" without arg increase page length by 1v
195 . pl +\\$1 \" otherwise use \\$1
197 . nr ** (\\n[.p] - \\n[*]) \" ** now holds arg for .SP in base units
198 . pl \\n[*]u \" restore page length
200 . \" we do nothing at start of new page or column
201 . if ((\\n[nl] - \\n[tH]) & (\\n[nl] - \\n[<<]) : \\n[.k]) \{\
202 . ie ((\\n[.d] - \\n[M#]) : \\n[.k]) \{\
203 . sp \\n[**]u \" execute .sp
204 . nr S# \\n[**] \" store ** in S#
207 . if (\\n[**] - \\n[S#]) \{\
208 . sp (\\n[**]u - \\n[S#]u)\" emit difference to previous .SP
209 . nr S# \\n[**] \" store ** in S#
212 . nr M# \\n[.d] \" store vertical position .d in M#
217 .\" ******************************************************************
218 .\" ** Perform all arguments once **
219 .\" ** P1 is nestable **
220 .\" ******************************************************************
222 . \" `while' command is about five times faster than recursion!
230 .\" ******************************************************************
231 .\" ** Hilfsmakro zum Einstellen von Schriftgroesse und **
232 .\" ** Zeilenabstand, bezogen auf Anfangswerte \n[s] und \n[v] **
233 .\" ** sowie fuer Hyphenation: **
234 .\" ** .pv s v hy# hart; macht .br **
235 .\" ** Bei 4. Argument setzen der Register s und v und hy. **
236 .\" ** Fuer angefangene Zeile die vorgefundenen Einstellungen **
237 .\" ******************************************************************
242 . ps (\\n[s]u * \\$1z / 1z)
245 . vs (\\n[v]u * \\$2p / 1p)
247 . vs (\\n[v]u * \\$1p / 1p)
262 .\" ******************************************************************
263 .\" ** Hilfsmakros pop/pops/popr (pop stackelement): **
264 .\" ** pop or popr: pop register **
265 .\" ** pops: pop string **
266 .\" ** .pop[s|r] reg|string stackname **
267 .\" ** reg|string: name of reg/string to get the **
268 .\" ** popped element **
269 .\" ** stack: name of stack **
270 .\" ******************************************************************
273 . ds \\$2 \\$4\" pop first stackelement
277 . ds $3 \\$3\" remember stackname
278 . shift 4 \" shift four args
280 . ds \\*[$3] "\\$@\" fill stack with remaining elements
284 . *pop \\$0 \\$1 \\$2 \\*[\\$2]
291 .\" ******************************************************************
292 .\" ** processs diversion **
293 .\" ******************************************************************
296 . nf \" diversion is already formatted - output it unchanged
297 . \\$1 \" output the diversion ...
298 . rm \\$1 \" ... and remove it
300 . fi \" reactivate formatting
304 .\" ******************************************************************
305 .\" ** Some macros and the page setup used by the examples **
306 .\" ******************************************************************
308 .\" ******************************************************************
309 .\" ** some of the following macros use system commands **
310 .\" ** and are therefore `unsafe': they need the `-U' argument **
311 .\" ** when calling groff/troff **
312 .\" ******************************************************************
314 .\" ******************************************************************
315 .\" ** Header macro for the examples **
316 .\" ******************************************************************
318 . nr *w* (17 * \w
\a\\$*
\a / 10 + 4n)
328 "width=(\\n[*w*]+4n)<?\n[.l]"
336 .\" ******************************************************************
337 .\" ** Utility macro for the date, requires UNIX date. **
338 .\" ** after return string *date contains the date in the **
339 .\" ** standard form of the Unix date-command, **
340 .\" ** for example "Sun Dec 5 22:27:57 2004" **
341 .\" ******************************************************************
343 . pso bash -c "echo -n .ds *date\ ;date"
348 .\" ******************************************************************
349 .\" ** Utility macro for time measurement, requires UNIX date **
350 .\" ** .time s[tart]|[end] **
351 .\" ** .time start: **
352 .\" ** reg *time gets the start-time (seconds) **
353 .\" ** .time [end]: **
354 .\" ** reg *time gets the difference of the **
355 .\" ** end- and start-time (seconds) **
356 .\" ******************************************************************
361 . pso bash -c "echo -n .nr *time 0+;date +%s"
363 . pso bash -c "echo -n .nr *time -;date +%s"
364 . nr *time 0-\\n[*time]
365 . tm elapsed time: \\n[*time] seconds
370 .\" ******************************************************************
371 .\" ** Perform n-times all the arbitrary arguments **
372 .\" ** .PN n a2 a3 ... **
373 .\" ** PN is nestable **
374 .\" ******************************************************************
377 . nr PN\\n[*pn] (\\$1 + 1) 1
380 . while \\n-[PN\\n[*pn]] \
387 .\" Utility macro: .d2x decimal_number [base [string_name]]
389 .\" Convert `decimal_number' to another base `base' (in the
390 .\" range 1..16) and store the result in string `string_name'.
391 .\" If `base' is missing or empty, convert to a hexadecimal
392 .\" number. If `string_name' is missing or empty, return value
393 .\" in string `hex#', otherwise return the value in both
394 .\" `string_name' and `hex#'.
396 .\" The base value 1 is handled specially: The returned
397 .\" string contains the character `|' `decimal_number' times
398 .\" (for example, input value 4 yields `||||').
419 . tm \\n[.F]:\\n[.c]: invalid or missing first argument
420 . tm1 " usage: `.d2x decimal_number [base [string_name]]'
430 . nr dec# (-\\n[dec#])
434 . tm \\n[.F]:\\n[.c]: invalid base `\\$2'
436 . ie ((\\$2 < 1) : (\\$2 > 16)) \
437 . tm \\n[.F]:\\n[.c]: invalid base `\\$2'
446 . ie (\\n[b#] == 1) \{\
452 . while (\\n[dec#] - \\n[xb#]) \{\
453 . nr xb# (\\n[xb#] * \\n[b#])
457 . while (\\n+[i#] < \\n[j#]) \{\
458 . nr ** (\\n[dec#] / \\n[xb#])
459 . as hex# \\*[d2x-\\n[**]]\"
460 . nr dec# (\\n[dec#] - (\\n[xb#] * \\n[**]))
461 . nr xb# (\\n[xb#] / \\n[b#])
465 . \" strip leading zero, if any
469 . substring hex# 1 -1
472 . ds hex# -\\*[hex#]\"
476 . tm \\n[.F]:\\n[.c]: invalid string name `\\$3'
478 . ds \\$3 \\*[hex#]\"
483 .\" Utility macro: .random#
484 .\" .random-seed seed1 seed2
486 .\" Return pseudo-random numbers in the range 0..0xFFFFFF,
487 .\" represented as the concatenation of `#' and six
488 .\" hexadecimal digits, in the string `#random'. The
489 .\" macro `random-seed' can be used to set seed values,
490 .\" which should be integers in the range 1..2147483562 and
491 .\" 1..2147483398 for `seed1' and `seed2', respectively
492 .\" (the macro applies a modulo operation to assure this
493 .\" range). If `random-seed' isn't called the registers
494 .\" `seconds', `minutes', `hours', `dy', `mo', `year', and
495 .\" `$$' are used to compute it.
497 .\" The used generator is presented in L'Ecuyer's 1988 paper
498 .\" `Efficient and Portable Combined Random Number
499 .\" Generators', which combines two Multiplicative Linear
500 .\" Congruential Generators (MLCGs) to achieve a period of
509 .ds random-s1 \n[minutes]\n[seconds]\n[$$]\n[hours]\"
511 .substring random-s1 0 8
513 .nr random-s1 (\*[random-s1] % 2147483562)
514 .nr random-s2 \n[dy]\n[year]\n[mo]
518 . if !(\\n[.$] == 2) \{\
519 . tm1 "random-seed: Invalid number of arguments.
520 . tm1 " usage: `.random-seed seed1 seed2'
524 . nr random-s1 (\\$1 % 2147483562)
525 . nr random-s2 (\\$2 % 2147483398)
530 . nr * (\\n[random-s1] / 53668)
531 . nr random-s1 (40014 * (\\n[random-s1] - (\\n[*] * 53668)) \
533 . if !\\n[random-s1] \
534 . nr random-s1 +2147483563
536 . nr * (\\n[random-s2] / 52774)
537 . nr random-s2 (40692 * (\\n[random-s2] - (\\n[*] * 52774)) \
539 . if !\\n[random-s2] \
540 . nr random-s2 +2147483399
542 . nr * (\\n[random-s1] - \\n[random-s2])
546 . \" reduce the result to the leftmost 24 bits
547 . nr * (\\n[*] / 128)
550 . ds hex# 000000\\*[hex#]\"
552 . ds #random #\\*[hex#]\"
556 .\" ******************************************************************
557 .\" ** minimal Page setup **
558 .\" ******************************************************************
563 .nr l 6.6i \" set text width
565 .nr o 2c \" set offset
567 .nr p 29.7c \" set paper length (A4)
569 .nr tH 1i \" set top margin
578 . sp |.5i \" print header in top margin
587 . sp |(\\n[p]u - .5i) \" print footer in bottom margin
594 . rm BM \" no page number at bottom of last page
596 . if !"\\*[t*kept]"" \{\
597 . tm1 "hdtbl: Not all tables have been printed.
598 . tm1 " Add `.bp' at the end of your document.
600 . if !"\\*[t*held]"" \{\
601 . tm1 "hdtbl: There are held tables which haven't been printed.
602 . tm1 " Add `.t*free' at the end of your document.
605 . tm hdtbl: Missing `.ETB' macro at end of document.
616 .mso hdtbl.tmac\" load table macros