.\" -*- mode: roff -*- .ig hdmisc.tmac This file is part of groff, the GNU roff type-setting system. Copyright (C) 2005, 2006 Free Software Foundation, Inc. written by Joachim Walsdorff . groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . .. . . .\" %beginstrip% . .if d getarg \ . nx . . .\" ****************************************************************** .\" ** Some macros and default settings needed by hdtbl ** .\" ****************************************************************** . . .\" Utility macro: .getarg ... .\" .\" Get macro argument. This macro searches in the .\" remaining arguments and assigns its value to a string .\" register named . The following syntax forms are .\" recognized. .\" .\" = Assign to string . .\" must not contain spaces. .\" ='' Assign to string . .\" can contain spaces. .\" = Assign `=' to string . .\" Assign `key' to string . .\" .\" After return, the string `args' contains the remaining .\" arguments. .\" .\" Example: With the definition of string `foo' as .\" .\" .ds foo aaa=xxx bbb ccc='yyy zzz' ddd= eee .\" .\" a call to `getarg' with .\" .\" .getarg ccc \*[foo] .\" .\" sets string `ccc' to value `yyy zzz'. The string `args' .\" now contains `aaa=xxx bbb ddd= eee'. An additional call .\" like .\" .\" .getarg ddd \*[args] .\" .\" sets string `ddd' to value `=', and `args' contains .\" `aaa=xxx bbb eee'. .de getarg . ds \\$1 . ds args . . if (\\n[.$] < 2) \ . return . . ds $1 \\$1\" . shift . . length * \\*[$1] . while \\n[.$] \{\ . ds * "\\$1\" . ds ** "\\$1\" . length ** \\*[**] . shift . if (\\n[*] > \\n[**]) \{\ . as args " "\\*[**]"\" value too short, repeat . continue . \} . substring * 0 (\\n[*] - 1) . \" The surrounding \? escapes emulate string comparison. . ie !"\?\\*[$1]\?"\?\\*[*]\?" \{\ . as args " "\\*[**]"\" key not found, repeat . continue . \} . el \{\ . ie "\?\\*[**]\?"\?\\*[$1]\?" \ . ds \\*[$1] \\*[$1]\" return key as string . el \{\ . ie "\?\\*[**]\?"\?\\*[$1]=\?" \ . ds \\*[$1] =\" return `=' . el \{\ . substring ** (\\n[*] + 1) -1 . ds * \\*[**]\" . substring * 0 0 . . \" check whether value starts with quote . if "\?\\*[*]\?"\?'\?" \{\ . substring ** 1 -1 . ds * \\*[**]\" . substring * -1 -1 . . \" search final quote . ie "\?\\*[*]\?"\?'\?" \ . substring ** 0 -2 . el \{\ . as \\*[$1] \\*[**] \" not found, append argument . . while 1 \{\ . ds ** \\$1\" get next argument . ds * \\$1\" . shift . substring * -1 -1 . . if "\?\\*[*]\?"\?'\?" \{\ . substring ** 0 -2 . break \" break if no final quote . \} . . as \\*[$1] \\*[**] \" otherwise append and repeat . \} . \}\} . . as \\*[$1] \\*[**]\" . \} . . as args " \\$@\" . \}\} . . return . \} .. . . .\" Utility macro: .index .\" .\" Check whether is a substring of and .\" return its position in number register `index', starting .\" with 1. If not found, return 0. If is empty, .\" set `index' to -999. .de index . if "\\$2"" \{\ . nr index -999 . return . \} . . length ** \\$1 . length $2 \\$2 . nr * 0-1 1 . . while (\\n+[*] < \\n[**]) \{\ . ds * \\$1\" . substring * \\n[*] (\\n[*] + \\n[$2] - 1) . \" The surrounding \? escapes emulate string comparison. . if "\?\\*[*]\?"\?\\$2\?" \ . break . \} . . ie (\\n[*] == \\n[**]) \ . nr index 0 . el \ . nr index (\\n[*] + 1) .. . . .\" ****************************************************************** .\" ******** non-accumulating space .SP [v] ********** .\" ** ** .\" ** nl vor erster Seite -1, oben auf Seite 0 resp. tH ** .\" ** .k nach .sp oder .br 0, ** .\" ** sonst Laenge der angefangenen Zeile ** .\" ** Der Merker M# fuer vorangegangenes .SP wird in .HM am ** .\" ** Seitenanfang zurueckgesetzt. ** .\" ** ganz richtig ist .sp + .br = .br + .sp = .sp ** .\" ****************************************************************** .de SP . if (\\n[nl] < 0) \ . br \" start very first page . nr * \\n[.p] \" save current page length . . ie "\\$1"" \ . pl +1 \" without arg increase page length by 1v . el \ . pl +\\$1 \" otherwise use \\$1 . . nr ** (\\n[.p] - \\n[*]) \" ** now holds arg for .SP in base units . pl \\n[*]u \" restore page length . . \" we do nothing at start of new page or column . if ((\\n[nl] - \\n[tH]) & (\\n[nl] - \\n[<<]) : \\n[.k]) \{\ . ie ((\\n[.d] - \\n[M#]) : \\n[.k]) \{\ . sp \\n[**]u \" execute .sp . nr S# \\n[**] \" store ** in S# . \} . el \{\ . if (\\n[**] - \\n[S#]) \{\ . sp (\\n[**]u - \\n[S#]u)\" emit difference to previous .SP . nr S# \\n[**] \" store ** in S# . \}\} . . nr M# \\n[.d] \" store vertical position .d in M# . \} .. . . .\" ****************************************************************** .\" ** Perform all arguments once ** .\" ** P1 is nestable ** .\" ****************************************************************** .de P1 . \" `while' command is about five times faster than recursion! . while \\n[.$] \{\ . nop \\$1 . shift . \} .. . . .\" ****************************************************************** .\" ** Hilfsmakro zum Einstellen von Schriftgroesse und ** .\" ** Zeilenabstand, bezogen auf Anfangswerte \n[s] und \n[v] ** .\" ** sowie fuer Hyphenation: ** .\" ** .pv s v hy# hart; macht .br ** .\" ** Bei 4. Argument setzen der Register s und v und hy. ** .\" ** Fuer angefangene Zeile die vorgefundenen Einstellungen ** .\" ****************************************************************** .de pv . br . . if \\n[.$] \ . ps (\\n[s]u * \\$1z / 1z) . . ie (\\n[.$] - 1) \ . vs (\\n[v]u * \\$2p / 1p) . el \{\ . vs (\\n[v]u * \\$1p / 1p) . return . \} . . if !""\\$3" \ . hy \\$3 . . if !""\\$4" \{\ . nr v \\n[.v] . nr s \\n[.ps] . nr hy \\n[.hy] . \} .. . . .\" ****************************************************************** .\" ** Hilfsmakros pop/pops/popr (pop stackelement): ** .\" ** pop or popr: pop register ** .\" ** pops: pop string ** .\" ** .pop[s|r] reg|string stackname ** .\" ** reg|string: name of reg/string to get the ** .\" ** popped element ** .\" ** stack: name of stack ** .\" ****************************************************************** .de *pop . ie "\\$1"pops" \ . ds \\$2 \\$4\" pop first stackelement . el \ . nr \\$2 \\$4 . . ds $3 \\$3\" remember stackname . shift 4 \" shift four args . . ds \\*[$3] "\\$@\" fill stack with remaining elements .. . .de pop . *pop \\$0 \\$1 \\$2 \\*[\\$2] .. . .als popr pop .als pops pop . . .\" ****************************************************************** .\" ** processs diversion ** .\" ****************************************************************** .de DI . nr * \\n[.u] . nf \" diversion is already formatted - output it unchanged . \\$1 \" output the diversion ... . rm \\$1 \" ... and remove it . if \\n[*] \ . fi \" reactivate formatting .. . . .\" ****************************************************************** .\" ** Some macros and the page setup used by the examples ** .\" ****************************************************************** . .\" ****************************************************************** .\" ** some of the following macros use system commands ** .\" ** and are therefore `unsafe': they need the `-U' argument ** .\" ** when calling groff/troff ** .\" ****************************************************************** . .\" ****************************************************************** .\" ** Header macro for the examples ** .\" ****************************************************************** .de H . nr *w* (17 * \w\\$* / 10 + 4n) . TBL border=1n \ bc=yellow \ bgc=red4 \ fgc=yellow \ csp=0 \ fst=TB \ "fsz=1.7 1.5" \ hal=c \ tal=c \ "width=(\\n[*w*]+4n) 16)) \ . tm \\n[.F]:\\n[.c]: invalid base `\\$2' . el \ . nr b# \\$2 . \}\} . el \ . nr b# 16 . . nr xb# 1 . . ie (\\n[b#] == 1) \{\ . nr dec# +1 . while \\n-[dec#] \ . as hex# |\" . \} . el \{\ . while (\\n[dec#] - \\n[xb#]) \{\ . nr xb# (\\n[xb#] * \\n[b#]) . nr j# +1 . \} . . while (\\n+[i#] < \\n[j#]) \{\ . nr ** (\\n[dec#] / \\n[xb#]) . as hex# \\*[d2x-\\n[**]]\" . nr dec# (\\n[dec#] - (\\n[xb#] * \\n[**])) . nr xb# (\\n[xb#] / \\n[b#]) . \} . \} . . \" strip leading zero, if any . ds * \\*[hex#]\" . substring * 0 0 . if "\\*[*]"0" \ . substring hex# 1 -1 . . if (\\$1 < 0) \ . ds hex# -\\*[hex#]\" . . if !"\\$3"" \{\ . ie !\A\\$3 \ . tm \\n[.F]:\\n[.c]: invalid string name `\\$3' . el \ . ds \\$3 \\*[hex#]\" . \} .. . . .\" Utility macro: .random# .\" .random-seed seed1 seed2 .\" .\" Return pseudo-random numbers in the range 0..0xFFFFFF, .\" represented as the concatenation of `#' and six .\" hexadecimal digits, in the string `#random'. The .\" macro `random-seed' can be used to set seed values, .\" which should be integers in the range 1..2147483562 and .\" 1..2147483398 for `seed1' and `seed2', respectively .\" (the macro applies a modulo operation to assure this .\" range). If `random-seed' isn't called the registers .\" `seconds', `minutes', `hours', `dy', `mo', `year', and .\" `$$' are used to compute it. .\" .\" The used generator is presented in L'Ecuyer's 1988 paper .\" `Efficient and Portable Combined Random Number .\" Generators', which combines two Multiplicative Linear .\" Congruential Generators (MLCGs) to achieve a period of .\" 2.3*10^18. .af hours 00 .af minutes 00 .af seconds 00 .af year 0000 .af mo 00 .af dy 00 . .ds random-s1 \n[minutes]\n[seconds]\n[$$]\n[hours]\" .\" prevent overflow .substring random-s1 0 8 . .nr random-s1 (\*[random-s1] % 2147483562) .nr random-s2 \n[dy]\n[year]\n[mo] . . .de random-seed . if !(\\n[.$] == 2) \{\ . tm1 "random-seed: Invalid number of arguments. . tm1 " usage: `.random-seed seed1 seed2' . return . \} . . nr random-s1 (\\$1 % 2147483562) . nr random-s2 (\\$2 % 2147483398) .. . . .de random# . nr * (\\n[random-s1] / 53668) . nr random-s1 (40014 * (\\n[random-s1] - (\\n[*] * 53668)) \ - (\\n[*] * 12211)) . if !\\n[random-s1] \ . nr random-s1 +2147483563 . . nr * (\\n[random-s2] / 52774) . nr random-s2 (40692 * (\\n[random-s2] - (\\n[*] * 52774)) \ - (\\n[*] * 3791)) . if !\\n[random-s2] \ . nr random-s2 +2147483399 . . nr * (\\n[random-s1] - \\n[random-s2]) . if (\\n[*] < 1) \ . nr * +2147483562 . . \" reduce the result to the leftmost 24 bits . nr * (\\n[*] / 128) . . d2x \\n[*] . ds hex# 000000\\*[hex#]\" . substring hex# -6 . ds #random #\\*[hex#]\" .. . . .\" ****************************************************************** .\" ** minimal Page setup ** .\" ****************************************************************** . .nr s \n[.ps] .nr v \n[.v] .pv 1.2 1.2 "" X .nr l 6.6i \" set text width .ll \n[l]u .nr o 2c \" set offset .po \n[o]u .nr p 29.7c \" set paper length (A4) .pl \n[p]u .nr tH 1i \" set top margin .sp |\n[tH]u . .ev 99 .lt \n[l]u .ev . . .de HM . sp |.5i \" print header in top margin . tl \\*[t*HM] . sp |\\n[tH]u . ev .. . . .de BM . ev 99 . sp |(\\n[p]u - .5i) \" print footer in bottom margin . tl \\*[t*BM] . bp .. . . .de EM . rm BM \" no page number at bottom of last page . . if !"\\*[t*kept]"" \{\ . tm1 "hdtbl: Not all tables have been printed. . tm1 " Add `.bp' at the end of your document. . \} . if !"\\*[t*held]"" \{\ . tm1 "hdtbl: There are held tables which haven't been printed. . tm1 " Add `.t*free' at the end of your document. . \} . if \\n[t*#] \ . tm hdtbl: Missing `.ETB' macro at end of document. .. . . .em EM . .if "\n[.m]"" \ . gcolor black .if "\n[.M]"" \ . fcolor white . .mso hdtbl.tmac\" load table macros . .\" EOF