xref: /onnv-gate/usr/src/lib/libsum/common/sumlib.c (revision 12068:08a39a083754)
18462SApril.Chin@Sun.COM /***********************************************************************
28462SApril.Chin@Sun.COM *                                                                      *
38462SApril.Chin@Sun.COM *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1996-2010 AT&T Intellectual Property          *
58462SApril.Chin@Sun.COM *                      and is licensed under the                       *
68462SApril.Chin@Sun.COM *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
88462SApril.Chin@Sun.COM *                                                                      *
98462SApril.Chin@Sun.COM *                A copy of the License is available at                 *
108462SApril.Chin@Sun.COM *            http://www.opensource.org/licenses/cpl1.0.txt             *
118462SApril.Chin@Sun.COM *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
128462SApril.Chin@Sun.COM *                                                                      *
138462SApril.Chin@Sun.COM *              Information and Software Systems Research               *
148462SApril.Chin@Sun.COM *                            AT&T Research                             *
158462SApril.Chin@Sun.COM *                           Florham Park NJ                            *
168462SApril.Chin@Sun.COM *                                                                      *
178462SApril.Chin@Sun.COM *                 Glenn Fowler <gsf@research.att.com>                  *
188462SApril.Chin@Sun.COM *                                                                      *
198462SApril.Chin@Sun.COM ***********************************************************************/
208462SApril.Chin@Sun.COM #pragma prototyped
218462SApril.Chin@Sun.COM /*
228462SApril.Chin@Sun.COM  * Glenn Fowler
238462SApril.Chin@Sun.COM  * AT&T Research
248462SApril.Chin@Sun.COM  *
258462SApril.Chin@Sun.COM  * man this is sum library
268462SApril.Chin@Sun.COM  */
278462SApril.Chin@Sun.COM 
2810898Sroland.mainz@nrubsig.org static const char id[] = "\n@(#)$Id: sumlib (AT&T Research) 2009-09-28 $\0\n";
298462SApril.Chin@Sun.COM 
308462SApril.Chin@Sun.COM #define _SUM_PRIVATE_	\
318462SApril.Chin@Sun.COM 			struct Method_s*	method;	\
328462SApril.Chin@Sun.COM 			uintmax_t		total_count;	\
338462SApril.Chin@Sun.COM 			uintmax_t		total_size;	\
348462SApril.Chin@Sun.COM 			uintmax_t		size;
358462SApril.Chin@Sun.COM 
368462SApril.Chin@Sun.COM #include <sum.h>
378462SApril.Chin@Sun.COM #include <ctype.h>
388462SApril.Chin@Sun.COM #include <swap.h>
398462SApril.Chin@Sun.COM #include <hashpart.h>
408462SApril.Chin@Sun.COM 
418462SApril.Chin@Sun.COM #define SCALE(n,m)	(((n)+(m)-1)/(m))
428462SApril.Chin@Sun.COM 
438462SApril.Chin@Sun.COM typedef struct Method_s
448462SApril.Chin@Sun.COM {
458462SApril.Chin@Sun.COM 	const char*	match;
468462SApril.Chin@Sun.COM 	const char*	description;
478462SApril.Chin@Sun.COM 	const char*	options;
488462SApril.Chin@Sun.COM 	Sum_t*		(*open)(const struct Method_s*, const char*);
498462SApril.Chin@Sun.COM 	int		(*init)(Sum_t*);
508462SApril.Chin@Sun.COM 	int		(*block)(Sum_t*, const void*, size_t);
518462SApril.Chin@Sun.COM 	int		(*data)(Sum_t*, Sumdata_t*);
528462SApril.Chin@Sun.COM 	int		(*print)(Sum_t*, Sfio_t*, int, size_t);
538462SApril.Chin@Sun.COM 	int		(*done)(Sum_t*);
548462SApril.Chin@Sun.COM 	int		scale;
558462SApril.Chin@Sun.COM } Method_t;
568462SApril.Chin@Sun.COM 
578462SApril.Chin@Sun.COM typedef struct Map_s
588462SApril.Chin@Sun.COM {
598462SApril.Chin@Sun.COM 	const char*	match;
608462SApril.Chin@Sun.COM 	const char*	description;
618462SApril.Chin@Sun.COM 	const char*	map;
628462SApril.Chin@Sun.COM } Map_t;
638462SApril.Chin@Sun.COM 
648462SApril.Chin@Sun.COM /*
658462SApril.Chin@Sun.COM  * 16 and 32 bit common code
668462SApril.Chin@Sun.COM  */
678462SApril.Chin@Sun.COM 
688462SApril.Chin@Sun.COM #define _INTEGRAL_PRIVATE_ \
698462SApril.Chin@Sun.COM 	uint32_t	sum; \
708462SApril.Chin@Sun.COM 	uint32_t	total_sum;
718462SApril.Chin@Sun.COM 
728462SApril.Chin@Sun.COM typedef struct Integral_s
738462SApril.Chin@Sun.COM {
748462SApril.Chin@Sun.COM 	_SUM_PUBLIC_
758462SApril.Chin@Sun.COM 	_SUM_PRIVATE_
768462SApril.Chin@Sun.COM 	_INTEGRAL_PRIVATE_
778462SApril.Chin@Sun.COM } Integral_t;
788462SApril.Chin@Sun.COM 
798462SApril.Chin@Sun.COM static Sum_t*
long_open(const Method_t * method,const char * name)808462SApril.Chin@Sun.COM long_open(const Method_t* method, const char* name)
818462SApril.Chin@Sun.COM {
828462SApril.Chin@Sun.COM 	Integral_t*	p;
838462SApril.Chin@Sun.COM 
848462SApril.Chin@Sun.COM 	if (p = newof(0, Integral_t, 1, 0))
858462SApril.Chin@Sun.COM 	{
868462SApril.Chin@Sun.COM 		p->method = (Method_t*)method;
878462SApril.Chin@Sun.COM 		p->name = name;
888462SApril.Chin@Sun.COM 	}
898462SApril.Chin@Sun.COM 	return (Sum_t*)p;
908462SApril.Chin@Sun.COM }
918462SApril.Chin@Sun.COM 
928462SApril.Chin@Sun.COM static int
long_init(Sum_t * p)938462SApril.Chin@Sun.COM long_init(Sum_t* p)
948462SApril.Chin@Sun.COM {
958462SApril.Chin@Sun.COM 	((Integral_t*)p)->sum = 0;
968462SApril.Chin@Sun.COM 	return 0;
978462SApril.Chin@Sun.COM }
988462SApril.Chin@Sun.COM 
998462SApril.Chin@Sun.COM static int
long_done(Sum_t * p)1008462SApril.Chin@Sun.COM long_done(Sum_t* p)
1018462SApril.Chin@Sun.COM {
1028462SApril.Chin@Sun.COM 	register Integral_t*	x = (Integral_t*)p;
1038462SApril.Chin@Sun.COM 
1048462SApril.Chin@Sun.COM 	x->total_sum ^= (x->sum &= 0xffffffff);
1058462SApril.Chin@Sun.COM 	return 0;
1068462SApril.Chin@Sun.COM }
1078462SApril.Chin@Sun.COM 
1088462SApril.Chin@Sun.COM static int
short_done(Sum_t * p)1098462SApril.Chin@Sun.COM short_done(Sum_t* p)
1108462SApril.Chin@Sun.COM {
1118462SApril.Chin@Sun.COM 	register Integral_t*	x = (Integral_t*)p;
1128462SApril.Chin@Sun.COM 
1138462SApril.Chin@Sun.COM 	x->total_sum ^= (x->sum &= 0xffff);
1148462SApril.Chin@Sun.COM 	return 0;
1158462SApril.Chin@Sun.COM }
1168462SApril.Chin@Sun.COM 
1178462SApril.Chin@Sun.COM static int
long_print(Sum_t * p,Sfio_t * sp,register int flags,size_t scale)1188462SApril.Chin@Sun.COM long_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
1198462SApril.Chin@Sun.COM {
1208462SApril.Chin@Sun.COM 	register Integral_t*	x = (Integral_t*)p;
1218462SApril.Chin@Sun.COM 	register uint32_t	c;
1228462SApril.Chin@Sun.COM 	register uintmax_t	z;
1238462SApril.Chin@Sun.COM 	register size_t		n;
1248462SApril.Chin@Sun.COM 
1258462SApril.Chin@Sun.COM 	c = (flags & SUM_TOTAL) ? x->total_sum : x->sum;
1268462SApril.Chin@Sun.COM 	sfprintf(sp, "%.*I*u", (flags & SUM_LEGACY) ? 5 : 1, sizeof(c), c);
1278462SApril.Chin@Sun.COM 	if (flags & SUM_SIZE)
1288462SApril.Chin@Sun.COM 	{
1298462SApril.Chin@Sun.COM 		z = (flags & SUM_TOTAL) ? x->total_size : x->size;
1308462SApril.Chin@Sun.COM 		if ((flags & SUM_SCALE) && ((n = scale) || (n = x->method->scale)))
1318462SApril.Chin@Sun.COM 			z = SCALE(z, n);
1328462SApril.Chin@Sun.COM 		sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(z), z);
1338462SApril.Chin@Sun.COM 	}
1348462SApril.Chin@Sun.COM 	if (flags & SUM_TOTAL)
1358462SApril.Chin@Sun.COM 		sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(x->total_count), x->total_count);
1368462SApril.Chin@Sun.COM 	return 0;
1378462SApril.Chin@Sun.COM }
1388462SApril.Chin@Sun.COM 
1398462SApril.Chin@Sun.COM static int
long_data(Sum_t * p,Sumdata_t * data)1408462SApril.Chin@Sun.COM long_data(Sum_t* p, Sumdata_t* data)
1418462SApril.Chin@Sun.COM {
1428462SApril.Chin@Sun.COM 	register Integral_t*	x = (Integral_t*)p;
1438462SApril.Chin@Sun.COM 
1448462SApril.Chin@Sun.COM 	data->size = sizeof(data->num);
1458462SApril.Chin@Sun.COM 	data->num = x->sum;
1468462SApril.Chin@Sun.COM 	data->buf = 0;
1478462SApril.Chin@Sun.COM 	return 0;
1488462SApril.Chin@Sun.COM }
1498462SApril.Chin@Sun.COM 
1508462SApril.Chin@Sun.COM #include "FEATURE/sum"
1518462SApril.Chin@Sun.COM 
1528462SApril.Chin@Sun.COM #include "sum-att.c"
1538462SApril.Chin@Sun.COM #include "sum-ast4.c"
1548462SApril.Chin@Sun.COM #include "sum-bsd.c"
1558462SApril.Chin@Sun.COM #include "sum-crc.c"
1568462SApril.Chin@Sun.COM #include "sum-prng.c"
1578462SApril.Chin@Sun.COM 
1588462SApril.Chin@Sun.COM #if _LIB_md && _lib_MD5Init && _hdr_md5 && _lib_SHA2Init && _hdr_sha2
1598462SApril.Chin@Sun.COM 
1608462SApril.Chin@Sun.COM #include "sum-lmd.c"
1618462SApril.Chin@Sun.COM 
1628462SApril.Chin@Sun.COM #else
1638462SApril.Chin@Sun.COM 
1648462SApril.Chin@Sun.COM #include "sum-md5.c"
1658462SApril.Chin@Sun.COM #include "sum-sha1.c"
1668462SApril.Chin@Sun.COM #include "sum-sha2.c"
1678462SApril.Chin@Sun.COM 
1688462SApril.Chin@Sun.COM #endif
1698462SApril.Chin@Sun.COM 
1708462SApril.Chin@Sun.COM /*
1718462SApril.Chin@Sun.COM  * now the library interface
1728462SApril.Chin@Sun.COM  */
1738462SApril.Chin@Sun.COM 
1748462SApril.Chin@Sun.COM #undef	METHOD		/* solaris <sys/localedef.h>! */
1758462SApril.Chin@Sun.COM #define METHOD(x)	x##_match,x##_description,x##_options,x##_open,x##_init,x##_block,x##_data,x##_print,x##_done,x##_scale
1768462SApril.Chin@Sun.COM 
1778462SApril.Chin@Sun.COM static const Method_t	methods[] =
1788462SApril.Chin@Sun.COM {
1798462SApril.Chin@Sun.COM 	METHOD(att),
1808462SApril.Chin@Sun.COM 	METHOD(ast4),
1818462SApril.Chin@Sun.COM 	METHOD(bsd),
1828462SApril.Chin@Sun.COM 	METHOD(crc),
1838462SApril.Chin@Sun.COM 	METHOD(prng),
1848462SApril.Chin@Sun.COM #ifdef md4_description
1858462SApril.Chin@Sun.COM 	METHOD(md4),
1868462SApril.Chin@Sun.COM #endif
1878462SApril.Chin@Sun.COM #ifdef md5_description
1888462SApril.Chin@Sun.COM 	METHOD(md5),
1898462SApril.Chin@Sun.COM #endif
1908462SApril.Chin@Sun.COM #ifdef sha1_description
1918462SApril.Chin@Sun.COM 	METHOD(sha1),
1928462SApril.Chin@Sun.COM #endif
1938462SApril.Chin@Sun.COM #ifdef sha256_description
1948462SApril.Chin@Sun.COM 	METHOD(sha256),
1958462SApril.Chin@Sun.COM #endif
1968462SApril.Chin@Sun.COM #ifdef sha384_description
1978462SApril.Chin@Sun.COM 	METHOD(sha384),
1988462SApril.Chin@Sun.COM #endif
1998462SApril.Chin@Sun.COM #ifdef sha512_description
2008462SApril.Chin@Sun.COM 	METHOD(sha512),
2018462SApril.Chin@Sun.COM #endif
2028462SApril.Chin@Sun.COM };
2038462SApril.Chin@Sun.COM 
2048462SApril.Chin@Sun.COM static const Map_t	maps[] =
2058462SApril.Chin@Sun.COM {
2068462SApril.Chin@Sun.COM 	{
2078462SApril.Chin@Sun.COM 		"posix|cksum|std|standard",
2088462SApril.Chin@Sun.COM 		"The posix 1003.2-1992 32 bit crc checksum. This is the"
2098462SApril.Chin@Sun.COM 		" default \bcksum\b(1)  method.",
2108462SApril.Chin@Sun.COM 		"crc-0x04c11db7-rotate-done-size"
2118462SApril.Chin@Sun.COM 	},
2128462SApril.Chin@Sun.COM 	{
2138462SApril.Chin@Sun.COM 		"zip",
2148462SApril.Chin@Sun.COM 		"The \bzip\b(1) crc.",
2158462SApril.Chin@Sun.COM 		"crc-0xedb88320-init-done"
2168462SApril.Chin@Sun.COM 	},
2178462SApril.Chin@Sun.COM 	{
2188462SApril.Chin@Sun.COM 		"fddi",
2198462SApril.Chin@Sun.COM 		"The FDDI crc.",
2208462SApril.Chin@Sun.COM 		"crc-0xedb88320-size=0xcc55cc55"
2218462SApril.Chin@Sun.COM 	},
2228462SApril.Chin@Sun.COM 	{
2238462SApril.Chin@Sun.COM 		"fnv|fnv1",
2248462SApril.Chin@Sun.COM 		"The Fowler-Noll-Vo 32 bit PRNG hash with non-zero"
2258462SApril.Chin@Sun.COM 		" initializer (FNV-1).",
2268462SApril.Chin@Sun.COM 		"prng-0x01000193-init=0x811c9dc5"
2278462SApril.Chin@Sun.COM 	},
2288462SApril.Chin@Sun.COM 	{
2298462SApril.Chin@Sun.COM 		"ast|strsum",
2308462SApril.Chin@Sun.COM 		"The \bast\b \bstrsum\b(3) PRNG hash.",
2318462SApril.Chin@Sun.COM 		"prng-0x63c63cd9-add=0x9c39c33d"
2328462SApril.Chin@Sun.COM 	},
2338462SApril.Chin@Sun.COM };
2348462SApril.Chin@Sun.COM 
2358462SApril.Chin@Sun.COM /*
23610898Sroland.mainz@nrubsig.org  * simple alternation prefix match
23710898Sroland.mainz@nrubsig.org  */
23810898Sroland.mainz@nrubsig.org 
23910898Sroland.mainz@nrubsig.org static int
match(register const char * s,register const char * p)24010898Sroland.mainz@nrubsig.org match(register const char* s, register const char* p)
24110898Sroland.mainz@nrubsig.org {
24210898Sroland.mainz@nrubsig.org 	register const char*	b = s;
24310898Sroland.mainz@nrubsig.org 
24410898Sroland.mainz@nrubsig.org 	for (;;)
24510898Sroland.mainz@nrubsig.org 	{
24610898Sroland.mainz@nrubsig.org 		do
24710898Sroland.mainz@nrubsig.org 		{
24810898Sroland.mainz@nrubsig.org 			if (*p == '|' || *p == 0)
24910898Sroland.mainz@nrubsig.org 				return 1;
25010898Sroland.mainz@nrubsig.org 		} while (*s++ == *p++);
25110898Sroland.mainz@nrubsig.org 		for (;;)
25210898Sroland.mainz@nrubsig.org 		{
25310898Sroland.mainz@nrubsig.org 			switch (*p++)
25410898Sroland.mainz@nrubsig.org 			{
25510898Sroland.mainz@nrubsig.org 			case 0:
25610898Sroland.mainz@nrubsig.org 				return 0;
25710898Sroland.mainz@nrubsig.org 			case '|':
25810898Sroland.mainz@nrubsig.org 				break;
25910898Sroland.mainz@nrubsig.org 			default:
26010898Sroland.mainz@nrubsig.org 				continue;
26110898Sroland.mainz@nrubsig.org 			}
26210898Sroland.mainz@nrubsig.org 			break;
26310898Sroland.mainz@nrubsig.org 		}
26410898Sroland.mainz@nrubsig.org 		s = b;
26510898Sroland.mainz@nrubsig.org 	}
26610898Sroland.mainz@nrubsig.org 	return 0;
26710898Sroland.mainz@nrubsig.org }
26810898Sroland.mainz@nrubsig.org 
26910898Sroland.mainz@nrubsig.org /*
2708462SApril.Chin@Sun.COM  * open sum method name
2718462SApril.Chin@Sun.COM  */
2728462SApril.Chin@Sun.COM 
2738462SApril.Chin@Sun.COM Sum_t*
sumopen(register const char * name)2748462SApril.Chin@Sun.COM sumopen(register const char* name)
2758462SApril.Chin@Sun.COM {
2768462SApril.Chin@Sun.COM 	register int	n;
2778462SApril.Chin@Sun.COM 
2788462SApril.Chin@Sun.COM 	if (!name || !name[0] || name[0] == '-' && !name[1])
2798462SApril.Chin@Sun.COM 		name = "default";
2808462SApril.Chin@Sun.COM 	for (n = 0; n < elementsof(maps); n++)
28110898Sroland.mainz@nrubsig.org 		if (match(name, maps[n].match))
2828462SApril.Chin@Sun.COM 		{
2838462SApril.Chin@Sun.COM 			name = maps[n].map;
2848462SApril.Chin@Sun.COM 			break;
2858462SApril.Chin@Sun.COM 		}
2868462SApril.Chin@Sun.COM 	for (n = 0; n < elementsof(methods); n++)
28710898Sroland.mainz@nrubsig.org 		if (match(name, methods[n].match))
2888462SApril.Chin@Sun.COM 			return (*methods[n].open)(&methods[n], name);
2898462SApril.Chin@Sun.COM 	return 0;
2908462SApril.Chin@Sun.COM }
2918462SApril.Chin@Sun.COM 
2928462SApril.Chin@Sun.COM /*
2938462SApril.Chin@Sun.COM  * initialize for a new run of blocks
2948462SApril.Chin@Sun.COM  */
2958462SApril.Chin@Sun.COM 
2968462SApril.Chin@Sun.COM int
suminit(Sum_t * p)2978462SApril.Chin@Sun.COM suminit(Sum_t* p)
2988462SApril.Chin@Sun.COM {
2998462SApril.Chin@Sun.COM 	p->size = 0;
3008462SApril.Chin@Sun.COM 	return (*p->method->init)(p);
3018462SApril.Chin@Sun.COM }
3028462SApril.Chin@Sun.COM 
3038462SApril.Chin@Sun.COM /*
3048462SApril.Chin@Sun.COM  * compute the running sum on buf
3058462SApril.Chin@Sun.COM  */
3068462SApril.Chin@Sun.COM 
3078462SApril.Chin@Sun.COM int
sumblock(Sum_t * p,const void * buf,size_t siz)3088462SApril.Chin@Sun.COM sumblock(Sum_t* p, const void* buf, size_t siz)
3098462SApril.Chin@Sun.COM {
3108462SApril.Chin@Sun.COM 	p->size += siz;
3118462SApril.Chin@Sun.COM 	return (*p->method->block)(p, buf, siz);
3128462SApril.Chin@Sun.COM }
3138462SApril.Chin@Sun.COM 
3148462SApril.Chin@Sun.COM /*
3158462SApril.Chin@Sun.COM  * done with this run of blocks
3168462SApril.Chin@Sun.COM  */
3178462SApril.Chin@Sun.COM 
3188462SApril.Chin@Sun.COM int
sumdone(Sum_t * p)3198462SApril.Chin@Sun.COM sumdone(Sum_t* p)
3208462SApril.Chin@Sun.COM {
3218462SApril.Chin@Sun.COM 	p->total_count++;
3228462SApril.Chin@Sun.COM 	p->total_size += p->size;
3238462SApril.Chin@Sun.COM 	return (*p->method->done)(p);
3248462SApril.Chin@Sun.COM }
3258462SApril.Chin@Sun.COM 
3268462SApril.Chin@Sun.COM /*
3278462SApril.Chin@Sun.COM  * print the sum [size] on sp
3288462SApril.Chin@Sun.COM  */
3298462SApril.Chin@Sun.COM 
3308462SApril.Chin@Sun.COM int
sumprint(Sum_t * p,Sfio_t * sp,int flags,size_t scale)3318462SApril.Chin@Sun.COM sumprint(Sum_t* p, Sfio_t* sp, int flags, size_t scale)
3328462SApril.Chin@Sun.COM {
3338462SApril.Chin@Sun.COM 	return (*p->method->print)(p, sp, flags, scale);
3348462SApril.Chin@Sun.COM }
3358462SApril.Chin@Sun.COM 
3368462SApril.Chin@Sun.COM /*
3378462SApril.Chin@Sun.COM  * return the current sum (internal) data
3388462SApril.Chin@Sun.COM  */
3398462SApril.Chin@Sun.COM 
3408462SApril.Chin@Sun.COM int
sumdata(Sum_t * p,Sumdata_t * d)3418462SApril.Chin@Sun.COM sumdata(Sum_t* p, Sumdata_t* d)
3428462SApril.Chin@Sun.COM {
3438462SApril.Chin@Sun.COM 	return (*p->method->data)(p, d);
3448462SApril.Chin@Sun.COM }
3458462SApril.Chin@Sun.COM 
3468462SApril.Chin@Sun.COM /*
3478462SApril.Chin@Sun.COM  * close an open sum handle
3488462SApril.Chin@Sun.COM  */
3498462SApril.Chin@Sun.COM 
3508462SApril.Chin@Sun.COM int
sumclose(Sum_t * p)3518462SApril.Chin@Sun.COM sumclose(Sum_t* p)
3528462SApril.Chin@Sun.COM {
3538462SApril.Chin@Sun.COM 	free(p);
3548462SApril.Chin@Sun.COM 	return 0;
3558462SApril.Chin@Sun.COM }
3568462SApril.Chin@Sun.COM 
3578462SApril.Chin@Sun.COM /*
3588462SApril.Chin@Sun.COM  * print the checksum method optget(3) usage on sp and return the length
3598462SApril.Chin@Sun.COM  */
3608462SApril.Chin@Sun.COM 
3618462SApril.Chin@Sun.COM int
sumusage(Sfio_t * sp)3628462SApril.Chin@Sun.COM sumusage(Sfio_t* sp)
3638462SApril.Chin@Sun.COM {
3648462SApril.Chin@Sun.COM 	register int	i;
3658462SApril.Chin@Sun.COM 	register int	n;
3668462SApril.Chin@Sun.COM 
3678462SApril.Chin@Sun.COM 	for (i = n = 0; i < elementsof(methods); i++)
3688462SApril.Chin@Sun.COM 	{
3698462SApril.Chin@Sun.COM 		n += sfprintf(sp, "[+%s?%s]", methods[i].match, methods[i].description);
3708462SApril.Chin@Sun.COM 		if (methods[i].options)
3718462SApril.Chin@Sun.COM 			n += sfprintf(sp, "{\n%s\n}", methods[i].options);
3728462SApril.Chin@Sun.COM 	}
3738462SApril.Chin@Sun.COM 	for (i = 0; i < elementsof(maps); i++)
3748462SApril.Chin@Sun.COM 		n += sfprintf(sp, "[+%s?%s Shorthand for \b%s\b.]", maps[i].match, maps[i].description, maps[i].map);
3758462SApril.Chin@Sun.COM 	return n;
3768462SApril.Chin@Sun.COM }
377