6 This file is part of groff, the GNU roff type-setting system.
8 Copyright (C) 2005, 2006 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 2, or (at your option) any later
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 groff; see the file COPYING. If not, write to the Free
23 Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
35 .\" ******************************************************************
36 .\" ** Some macros and default settings needed by hdtbl **
37 .\" ******************************************************************
40 .\" Utility macro: .getarg <key> ...
42 .\" Get macro argument. This macro searches <key> in the
43 .\" remaining arguments and assigns its value to a string
44 .\" register named <key>. The following syntax forms are
47 .\" <key>=<val> Assign <val> to string <key>.
48 .\" <val> must not contain spaces.
49 .\" <key>='<val>' Assign <val> to string <key>.
50 .\" <val> can contain spaces.
51 .\" <key>= Assign `=' to string <key>.
52 .\" <key> Assign `key' to string <key>.
54 .\" After return, the string `args' contains the remaining
57 .\" Example: With the definition of string `foo' as
59 .\" .ds foo aaa=xxx bbb ccc='yyy zzz' ddd= eee
61 .\" a call to `getarg' with
63 .\" .getarg ccc \*[foo]
65 .\" sets string `ccc' to value `yyy zzz'. The string `args'
66 .\" now contains `aaa=xxx bbb ddd= eee'. An additional call
69 .\" .getarg ddd \*[args]
71 .\" sets string `ddd' to value `=', and `args' contains
72 .\" `aaa=xxx bbb eee'.
89 . if (\\n[*] > \\n[**]) \{\
90 . as args " "\\*[**]"\" value too short, repeat
93 . substring * 0 (\\n[*] - 1)
94 . \" The surrounding \? escapes emulate string comparison.
95 . ie !"\?\\*[$1]\?"\?\\*[*]\?" \{\
96 . as args " "\\*[**]"\" key not found, repeat
100 . ie "\?\\*[**]\?"\?\\*[$1]\?" \
101 . ds \\*[$1] \\*[$1]\" return key as string
103 . ie "\?\\*[**]\?"\?\\*[$1]=\?" \
104 . ds \\*[$1] =\" return `='
106 . substring ** (\\n[*] + 1) -1
110 . \" check whether value starts with quote
111 . if "\?\\*[*]\?"\?'\?" \{\
116 . \" search final quote
117 . ie "\?\\*[*]\?"\?'\?" \
120 . as \\*[$1] \\*[**] \" not found, append argument
123 . ds ** \\$1\" get next argument
128 . if "\?\\*[*]\?"\?'\?" \{\
130 . break \" break if no final quote
133 . as \\*[$1] \\*[**] \" otherwise append and repeat
137 . as \\*[$1] \\*[**]\"
148 .\" Utility macro: .index <string1> <string2>
150 .\" Check whether <string2> is a substring of <string2> and
151 .\" return its position in number register `index', starting
152 .\" with 1. If not found, return 0. If <string2> is empty,
153 .\" set `index' to -999.
164 . while (\\n+[*] < \\n[**]) \{\
166 . substring * \\n[*] (\\n[*] + \\n[$2] - 1)
167 . \" The surrounding \? escapes emulate string comparison.
168 . if "\?\\*[*]\?"\?\\$2\?" \
172 . ie (\\n[*] == \\n[**]) \
175 . nr index (\\n[*] + 1)
179 .\" ******************************************************************
180 .\" ******** non-accumulating space .SP [v] **********
182 .\" ** nl vor erster Seite -1, oben auf Seite 0 resp. tH **
183 .\" ** .k nach .sp oder .br 0, **
184 .\" ** sonst Laenge der angefangenen Zeile **
185 .\" ** Der Merker M# fuer vorangegangenes .SP wird in .HM am **
186 .\" ** Seitenanfang zurueckgesetzt. **
187 .\" ** ganz richtig ist .sp + .br = .br + .sp = .sp **
188 .\" ******************************************************************
191 . br \" start very first page
192 . nr * \\n[.p] \" save current page length
195 . pl +1 \" without arg increase page length by 1v
197 . pl +\\$1 \" otherwise use \\$1
199 . nr ** (\\n[.p] - \\n[*]) \" ** now holds arg for .SP in base units
200 . pl \\n[*]u \" restore page length
202 . \" we do nothing at start of new page or column
203 . if ((\\n[nl] - \\n[tH]) & (\\n[nl] - \\n[<<]) : \\n[.k]) \{\
204 . ie ((\\n[.d] - \\n[M#]) : \\n[.k]) \{\
205 . sp \\n[**]u \" execute .sp
206 . nr S# \\n[**] \" store ** in S#
209 . if (\\n[**] - \\n[S#]) \{\
210 . sp (\\n[**]u - \\n[S#]u)\" emit difference to previous .SP
211 . nr S# \\n[**] \" store ** in S#
214 . nr M# \\n[.d] \" store vertical position .d in M#
219 .\" ******************************************************************
220 .\" ** Perform all arguments once **
221 .\" ** P1 is nestable **
222 .\" ******************************************************************
224 . \" `while' command is about five times faster than recursion!
232 .\" ******************************************************************
233 .\" ** Hilfsmakro zum Einstellen von Schriftgroesse und **
234 .\" ** Zeilenabstand, bezogen auf Anfangswerte \n[s] und \n[v] **
235 .\" ** sowie fuer Hyphenation: **
236 .\" ** .pv s v hy# hart; macht .br **
237 .\" ** Bei 4. Argument setzen der Register s und v und hy. **
238 .\" ** Fuer angefangene Zeile die vorgefundenen Einstellungen **
239 .\" ******************************************************************
244 . ps (\\n[s]u * \\$1z / 1z)
247 . vs (\\n[v]u * \\$2p / 1p)
249 . vs (\\n[v]u * \\$1p / 1p)
264 .\" ******************************************************************
265 .\" ** Hilfsmakros pop/pops/popr (pop stackelement): **
266 .\" ** pop or popr: pop register **
267 .\" ** pops: pop string **
268 .\" ** .pop[s|r] reg|string stackname **
269 .\" ** reg|string: name of reg/string to get the **
270 .\" ** popped element **
271 .\" ** stack: name of stack **
272 .\" ******************************************************************
275 . ds \\$2 \\$4\" pop first stackelement
279 . ds $3 \\$3\" remember stackname
280 . shift 4 \" shift four args
282 . ds \\*[$3] "\\$@\" fill stack with remaining elements
286 . *pop \\$0 \\$1 \\$2 \\*[\\$2]
293 .\" ******************************************************************
294 .\" ** processs diversion **
295 .\" ******************************************************************
298 . nf \" diversion is already formatted - output it unchanged
299 . \\$1 \" output the diversion ...
300 . rm \\$1 \" ... and remove it
302 . fi \" reactivate formatting
306 .\" ******************************************************************
307 .\" ** Some macros and the page setup used by the examples **
308 .\" ******************************************************************
310 .\" ******************************************************************
311 .\" ** some of the following macros use system commands **
312 .\" ** and are therefore `unsafe': they need the `-U' argument **
313 .\" ** when calling groff/troff **
314 .\" ******************************************************************
316 .\" ******************************************************************
317 .\" ** Header macro for the examples **
318 .\" ******************************************************************
320 . nr *w* (17 * \w
\a\\$*
\a / 10 + 4n)
330 "width=(\\n[*w*]+4n)<?\n[.l]"
338 .\" ******************************************************************
339 .\" ** Utility macro for the date, requires UNIX date. **
340 .\" ** after return string *date contains the date in the **
341 .\" ** standard form of the Unix date-command, **
342 .\" ** for example "Sun Dec 5 22:27:57 2004" **
343 .\" ******************************************************************
345 . pso bash -c "echo -n .ds *date\ ;date"
350 .\" ******************************************************************
351 .\" ** Utility macro for time measurement, requires UNIX date **
352 .\" ** .time s[tart]|[end] **
353 .\" ** .time start: **
354 .\" ** reg *time gets the start-time (seconds) **
355 .\" ** .time [end]: **
356 .\" ** reg *time gets the difference of the **
357 .\" ** end- and start-time (seconds) **
358 .\" ******************************************************************
363 . pso bash -c "echo -n .nr *time 0+;date +%s"
365 . pso bash -c "echo -n .nr *time -;date +%s"
366 . nr *time 0-\\n[*time]
367 . tm elapsed time: \\n[*time] seconds
372 .\" ******************************************************************
373 .\" ** Perform n-times all the arbitrary arguments **
374 .\" ** .PN n a2 a3 ... **
375 .\" ** PN is nestable **
376 .\" ******************************************************************
379 . nr PN\\n[*pn] (\\$1 + 1) 1
382 . while \\n-[PN\\n[*pn]] \
389 .\" Utility macro: .d2x decimal_number [base [string_name]]
391 .\" Convert `decimal_number' to another base `base' (in the
392 .\" range 1..16) and store the result in string `string_name'.
393 .\" If `base' is missing or empty, convert to a hexadecimal
394 .\" number. If `string_name' is missing or empty, return value
395 .\" in string `hex#', otherwise return the value in both
396 .\" `string_name' and `hex#'.
398 .\" The base value 1 is handled specially: The returned
399 .\" string contains the character `|' `decimal_number' times
400 .\" (for example, input value 4 yields `||||').
421 . tm \\n[.F]:\\n[.c]: invalid or missing first argument
422 . tm1 " usage: `.d2x decimal_number [base [string_name]]'
432 . nr dec# (-\\n[dec#])
436 . tm \\n[.F]:\\n[.c]: invalid base `\\$2'
438 . ie ((\\$2 < 1) : (\\$2 > 16)) \
439 . tm \\n[.F]:\\n[.c]: invalid base `\\$2'
448 . ie (\\n[b#] == 1) \{\
454 . while (\\n[dec#] - \\n[xb#]) \{\
455 . nr xb# (\\n[xb#] * \\n[b#])
459 . while (\\n+[i#] < \\n[j#]) \{\
460 . nr ** (\\n[dec#] / \\n[xb#])
461 . as hex# \\*[d2x-\\n[**]]\"
462 . nr dec# (\\n[dec#] - (\\n[xb#] * \\n[**]))
463 . nr xb# (\\n[xb#] / \\n[b#])
467 . \" strip leading zero, if any
471 . substring hex# 1 -1
474 . ds hex# -\\*[hex#]\"
478 . tm \\n[.F]:\\n[.c]: invalid string name `\\$3'
480 . ds \\$3 \\*[hex#]\"
485 .\" Utility macro: .random#
486 .\" .random-seed seed1 seed2
488 .\" Return pseudo-random numbers in the range 0..0xFFFFFF,
489 .\" represented as the concatenation of `#' and six
490 .\" hexadecimal digits, in the string `#random'. The
491 .\" macro `random-seed' can be used to set seed values,
492 .\" which should be integers in the range 1..2147483562 and
493 .\" 1..2147483398 for `seed1' and `seed2', respectively
494 .\" (the macro applies a modulo operation to assure this
495 .\" range). If `random-seed' isn't called the registers
496 .\" `seconds', `minutes', `hours', `dy', `mo', `year', and
497 .\" `$$' are used to compute it.
499 .\" The used generator is presented in L'Ecuyer's 1988 paper
500 .\" `Efficient and Portable Combined Random Number
501 .\" Generators', which combines two Multiplicative Linear
502 .\" Congruential Generators (MLCGs) to achieve a period of
511 .ds random-s1 \n[minutes]\n[seconds]\n[$$]\n[hours]\"
513 .substring random-s1 0 8
515 .nr random-s1 (\*[random-s1] % 2147483562)
516 .nr random-s2 \n[dy]\n[year]\n[mo]
520 . if !(\\n[.$] == 2) \{\
521 . tm1 "random-seed: Invalid number of arguments.
522 . tm1 " usage: `.random-seed seed1 seed2'
526 . nr random-s1 (\\$1 % 2147483562)
527 . nr random-s2 (\\$2 % 2147483398)
532 . nr * (\\n[random-s1] / 53668)
533 . nr random-s1 (40014 * (\\n[random-s1] - (\\n[*] * 53668)) \
535 . if !\\n[random-s1] \
536 . nr random-s1 +2147483563
538 . nr * (\\n[random-s2] / 52774)
539 . nr random-s2 (40692 * (\\n[random-s2] - (\\n[*] * 52774)) \
541 . if !\\n[random-s2] \
542 . nr random-s2 +2147483399
544 . nr * (\\n[random-s1] - \\n[random-s2])
548 . \" reduce the result to the leftmost 24 bits
549 . nr * (\\n[*] / 128)
552 . ds hex# 000000\\*[hex#]\"
554 . ds #random #\\*[hex#]\"
558 .\" ******************************************************************
559 .\" ** minimal Page setup **
560 .\" ******************************************************************
565 .nr l 6.6i \" set text width
567 .nr o 2c \" set offset
569 .nr p 29.7c \" set paper length (A4)
571 .nr tH 1i \" set top margin
580 . sp |.5i \" print header in top margin
589 . sp |(\\n[p]u - .5i) \" print footer in bottom margin
596 . rm BM \" no page number at bottom of last page
598 . if !"\\*[t*kept]"" \{\
599 . tm1 "hdtbl: Not all tables have been printed.
600 . tm1 " Add `.bp' at the end of your document.
602 . if !"\\*[t*held]"" \{\
603 . tm1 "hdtbl: There are held tables which haven't been printed.
604 . tm1 " Add `.t*free' at the end of your document.
607 . tm hdtbl: Missing `.ETB' macro at end of document.
618 .mso hdtbl.tmac\" load table macros