.\"	-*-	mode: roff	-*-
.ig

hdmisc.tmac

This file is part of groff, the GNU roff type-setting system.

Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.

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 <http://www.gnu.org/licenses/>.

..
.
.
.\" %beginstrip%
.
.if d getarg \
.  nx
.
.
.\"	******************************************************************
.\"	**	Some macros and default settings needed by hdtbl	**
.\"	******************************************************************
.
.
.\"	Utility macro:	.getarg <key> ...
.\"
.\"		Get macro argument.  This macro searches <key> in the
.\"		remaining arguments and assigns its value to a string
.\"		register named <key>.  The following syntax forms are
.\"		recognized.
.\"
.\"			<key>=<val>	Assign <val> to string <key>.
.\"					<val> must not contain spaces.
.\"			<key>='<val>'	Assign <val> to string <key>.
.\"					<val> can contain spaces.
.\"			<key>=		Assign `=' to string <key>.
.\"			<key>		Assign `key' to string <key>.
.\"
.\"		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 <string1> <string2>
.\"
.\"		Check whether <string2> is a substring of <string2> and
.\"		return its position in number register `index', starting
.\"		with 1.  If not found, return 0.  If <string2> 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)<?\n[.l]"
.  TR .TD
.  P1 \\$*
.  ETB
.  SP
..
.
.
.\"	******************************************************************
.\"	**	Utility macro for the date, requires UNIX date.		**
.\"	**	after return string *date contains the date in the	**
.\"	**	standard form of the Unix date-command,			**
.\"	**	for example "Sun Dec  5 22:27:57     2004"		**
.\"	******************************************************************
.de date
.  pso bash -c "echo -n .ds *date\ ;date"
.  tm \\*[*date] ***
..
.
.
.\"	******************************************************************
.\"	**	Utility macro for time measurement, requires UNIX date	**
.\"	**	.time s[tart]|[end]					**
.\"	**		.time start:					**
.\"	**			reg *time gets the start-time (seconds) **
.\"	**		.time [end]:					**
.\"	**			reg *time gets the difference of the	**
.\"	**				end- and start-time (seconds)	**
.\"	******************************************************************
.de time
.  ds * \\$1\"
.  substring * 0 0
.  ie "\\*[*]"s" \
.    pso bash -c "echo -n .nr *time 0+;date +%s"
.  el \{\
.   pso bash -c "echo -n .nr *time -;date +%s"
.   nr *time 0-\\n[*time]
.   tm elapsed time: \\n[*time] seconds
.  \}
..
.
.
.\"	******************************************************************
.\"	**		Perform n-times all the arbitrary arguments	**
.\"	**		.PN n a2 a3 ...					**
.\"	**			PN is nestable				**
.\"	******************************************************************
.de PN
.  nr *pn +1
.  nr PN\\n[*pn] (\\$1 + 1) 1
.  shift
.
.  while \\n-[PN\\n[*pn]] \
.    P1 \\$@
.
.  nr *pn -1
..
.
.
.\"	Utility macro:	.d2x decimal_number [base [string_name]]
.\"
.\"		Convert `decimal_number' to another base `base' (in the
.\"		range 1..16) and store the result in string `string_name'.
.\"		If `base' is missing or empty, convert to a hexadecimal
.\"		number.  If `string_name' is missing or empty, return value
.\"		in string `hex#', otherwise return the value in both
.\"		`string_name' and `hex#'.
.\"
.\"		The base value 1 is handled specially: The returned
.\"		string contains the character `|' `decimal_number' times
.\"		(for example, input value 4 yields `||||').
.ds d2x-0 0\"
.ds d2x-1 1\"
.ds d2x-2 2\"
.ds d2x-3 3\"
.ds d2x-4 4\"
.ds d2x-5 5\"
.ds d2x-6 6\"
.ds d2x-7 7\"
.ds d2x-8 8\"
.ds d2x-9 9\"
.ds d2x-10 A\"
.ds d2x-11 B\"
.ds d2x-12 C\"
.ds d2x-13 D\"
.ds d2x-14 E\"
.ds d2x-15 F\"
.
.
.de d2x
.  if !\B\\$1 \{\
.    tm \\n[.F]:\\n[.c]: invalid or missing first argument
.    tm1 "     usage: `.d2x decimal_number [base [string_name]]'
.    return
.  \}
.
.  nr i# (-1) 1
.  nr j# 1
.  ds hex#
.  nr dec# (\\$1) 1
.
.  if !\\$1 \
.    nr dec# (-\\n[dec#])
.
.  ie !"\\$2"" \{\
.    ie !\B\\$2 \
.      tm \\n[.F]:\\n[.c]: invalid base `\\$2'
.    el \
.      ie ((\\$2 < 1) : (\\$2 > 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
