xref: /titanic_53/usr/src/common/util/string.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Implementations of the functions described in vsnprintf(3C) and string(3C),
31*7c478bd9Sstevel@tonic-gate  * for use by the kernel, the standalone, and kmdb.  Unless otherwise specified,
32*7c478bd9Sstevel@tonic-gate  * these functions match the section 3C manpages.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
37*7c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
38*7c478bd9Sstevel@tonic-gate #include <string.h>
39*7c478bd9Sstevel@tonic-gate #else
40*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
41*7c478bd9Sstevel@tonic-gate #endif
42*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
43*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
44*7c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  * kmdb has its own *printf routines, and thus doesn't need these versions too.
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate #if !defined(_KMDB)
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #define	ADDCHAR(c)	if (bufp++ - buf < buflen) bufp[-1] = (c)
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate /*
54*7c478bd9Sstevel@tonic-gate  * Given a buffer 'buf' of size 'buflen', render as much of the string
55*7c478bd9Sstevel@tonic-gate  * described by <fmt, args> as possible.  The string will always be
56*7c478bd9Sstevel@tonic-gate  * null-terminated, so the maximum string length is 'buflen - 1'.
57*7c478bd9Sstevel@tonic-gate  * Returns the number of bytes that would be necessary to render the
58*7c478bd9Sstevel@tonic-gate  * entire string, not including null terminator (just like vsnprintf(3S)).
59*7c478bd9Sstevel@tonic-gate  * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1.
60*7c478bd9Sstevel@tonic-gate  *
61*7c478bd9Sstevel@tonic-gate  * There is no support for floating point, and the C locale is assumed.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate size_t
64*7c478bd9Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate 	uint64_t ul, tmp;
67*7c478bd9Sstevel@tonic-gate 	char *bufp = buf;	/* current buffer pointer */
68*7c478bd9Sstevel@tonic-gate 	int pad, width, ells, base, sign, c;
69*7c478bd9Sstevel@tonic-gate 	char *digits, *sp, *bs;
70*7c478bd9Sstevel@tonic-gate 	char numbuf[65];	/* sufficient for a 64-bit binary value */
71*7c478bd9Sstevel@tonic-gate 	va_list args;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 	/*
74*7c478bd9Sstevel@tonic-gate 	 * Make a copy so that all our callers don't have to make a copy
75*7c478bd9Sstevel@tonic-gate 	 */
76*7c478bd9Sstevel@tonic-gate 	va_copy(args, aargs);
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	if ((ssize_t)buflen < 0)
79*7c478bd9Sstevel@tonic-gate 		buflen = 0;
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	while ((c = *fmt++) != '\0') {
82*7c478bd9Sstevel@tonic-gate 		if (c != '%') {
83*7c478bd9Sstevel@tonic-gate 			ADDCHAR(c);
84*7c478bd9Sstevel@tonic-gate 			continue;
85*7c478bd9Sstevel@tonic-gate 		}
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 		if ((c = *fmt++) == '\0')
88*7c478bd9Sstevel@tonic-gate 			break;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 		for (pad = ' '; c == '0'; c = *fmt++)
91*7c478bd9Sstevel@tonic-gate 			pad = '0';
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 		for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
94*7c478bd9Sstevel@tonic-gate 			width = width * 10 + c - '0';
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 		for (ells = 0; c == 'l'; c = *fmt++)
97*7c478bd9Sstevel@tonic-gate 			ells++;
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 		digits = "0123456789abcdef";
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 		if (c >= 'A' && c <= 'Z') {
102*7c478bd9Sstevel@tonic-gate 			c += 'a' - 'A';
103*7c478bd9Sstevel@tonic-gate 			digits = "0123456789ABCDEF";
104*7c478bd9Sstevel@tonic-gate 		}
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 		base = sign = 0;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 		switch (c) {
109*7c478bd9Sstevel@tonic-gate 		case 'd':
110*7c478bd9Sstevel@tonic-gate 			sign = 1;
111*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
112*7c478bd9Sstevel@tonic-gate 		case 'u':
113*7c478bd9Sstevel@tonic-gate 			base = 10;
114*7c478bd9Sstevel@tonic-gate 			break;
115*7c478bd9Sstevel@tonic-gate 		case 'p':
116*7c478bd9Sstevel@tonic-gate 			ells = 1;
117*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
118*7c478bd9Sstevel@tonic-gate 		case 'x':
119*7c478bd9Sstevel@tonic-gate 			base = 16;
120*7c478bd9Sstevel@tonic-gate 			break;
121*7c478bd9Sstevel@tonic-gate 		case 'o':
122*7c478bd9Sstevel@tonic-gate 			base = 8;
123*7c478bd9Sstevel@tonic-gate 			break;
124*7c478bd9Sstevel@tonic-gate 		case 'b':
125*7c478bd9Sstevel@tonic-gate 			ells = 0;
126*7c478bd9Sstevel@tonic-gate 			base = 1;
127*7c478bd9Sstevel@tonic-gate 			break;
128*7c478bd9Sstevel@tonic-gate 		case 'c':
129*7c478bd9Sstevel@tonic-gate 			ul = (int64_t)va_arg(args, int);
130*7c478bd9Sstevel@tonic-gate 			ADDCHAR((int)ul & 0xff);
131*7c478bd9Sstevel@tonic-gate 			break;
132*7c478bd9Sstevel@tonic-gate 		case 's':
133*7c478bd9Sstevel@tonic-gate 			sp = va_arg(args, char *);
134*7c478bd9Sstevel@tonic-gate 			if (sp == NULL)
135*7c478bd9Sstevel@tonic-gate 				sp = "<null string>";
136*7c478bd9Sstevel@tonic-gate 			while ((c = *sp++) != 0)
137*7c478bd9Sstevel@tonic-gate 				ADDCHAR(c);
138*7c478bd9Sstevel@tonic-gate 			break;
139*7c478bd9Sstevel@tonic-gate 		case '%':
140*7c478bd9Sstevel@tonic-gate 			ADDCHAR('%');
141*7c478bd9Sstevel@tonic-gate 			break;
142*7c478bd9Sstevel@tonic-gate 		}
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 		if (base == 0)
145*7c478bd9Sstevel@tonic-gate 			continue;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		if (ells == 0)
148*7c478bd9Sstevel@tonic-gate 			ul = (int64_t)va_arg(args, int);
149*7c478bd9Sstevel@tonic-gate 		else if (ells == 1)
150*7c478bd9Sstevel@tonic-gate 			ul = (int64_t)va_arg(args, long);
151*7c478bd9Sstevel@tonic-gate 		else
152*7c478bd9Sstevel@tonic-gate 			ul = (int64_t)va_arg(args, int64_t);
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		if (sign && (int64_t)ul < 0)
155*7c478bd9Sstevel@tonic-gate 			ul = -ul;
156*7c478bd9Sstevel@tonic-gate 		else
157*7c478bd9Sstevel@tonic-gate 			sign = 0;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 		if (ells < 8 / sizeof (long))
160*7c478bd9Sstevel@tonic-gate 			ul &= 0xffffffffU;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 		if (c == 'b') {
163*7c478bd9Sstevel@tonic-gate 			bs = va_arg(args, char *);
164*7c478bd9Sstevel@tonic-gate 			base = *bs++;
165*7c478bd9Sstevel@tonic-gate 		}
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 		tmp = ul;
168*7c478bd9Sstevel@tonic-gate 		do {
169*7c478bd9Sstevel@tonic-gate 			width--;
170*7c478bd9Sstevel@tonic-gate 		} while ((tmp /= base) != 0);
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 		if (sign && pad == '0')
173*7c478bd9Sstevel@tonic-gate 			ADDCHAR('-');
174*7c478bd9Sstevel@tonic-gate 		while (width-- > sign)
175*7c478bd9Sstevel@tonic-gate 			ADDCHAR(pad);
176*7c478bd9Sstevel@tonic-gate 		if (sign && pad == ' ')
177*7c478bd9Sstevel@tonic-gate 			ADDCHAR('-');
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 		sp = numbuf;
180*7c478bd9Sstevel@tonic-gate 		tmp = ul;
181*7c478bd9Sstevel@tonic-gate 		do {
182*7c478bd9Sstevel@tonic-gate 			*sp++ = digits[tmp % base];
183*7c478bd9Sstevel@tonic-gate 		} while ((tmp /= base) != 0);
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		while (sp > numbuf) {
186*7c478bd9Sstevel@tonic-gate 			sp--;
187*7c478bd9Sstevel@tonic-gate 			ADDCHAR(*sp);
188*7c478bd9Sstevel@tonic-gate 		}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 		if (c == 'b' && ul != 0) {
191*7c478bd9Sstevel@tonic-gate 			int any = 0;
192*7c478bd9Sstevel@tonic-gate 			c = *bs++;
193*7c478bd9Sstevel@tonic-gate 			while (c != 0) {
194*7c478bd9Sstevel@tonic-gate 				if (ul & (1 << (c - 1))) {
195*7c478bd9Sstevel@tonic-gate 					if (any++ == 0)
196*7c478bd9Sstevel@tonic-gate 						ADDCHAR('<');
197*7c478bd9Sstevel@tonic-gate 					while ((c = *bs++) >= 32)
198*7c478bd9Sstevel@tonic-gate 						ADDCHAR(c);
199*7c478bd9Sstevel@tonic-gate 					ADDCHAR(',');
200*7c478bd9Sstevel@tonic-gate 				} else {
201*7c478bd9Sstevel@tonic-gate 					while ((c = *bs++) >= 32)
202*7c478bd9Sstevel@tonic-gate 						continue;
203*7c478bd9Sstevel@tonic-gate 				}
204*7c478bd9Sstevel@tonic-gate 			}
205*7c478bd9Sstevel@tonic-gate 			if (any) {
206*7c478bd9Sstevel@tonic-gate 				bufp--;
207*7c478bd9Sstevel@tonic-gate 				ADDCHAR('>');
208*7c478bd9Sstevel@tonic-gate 			}
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 	if (bufp - buf < buflen)
212*7c478bd9Sstevel@tonic-gate 		bufp[0] = c;
213*7c478bd9Sstevel@tonic-gate 	else if (buflen != 0)
214*7c478bd9Sstevel@tonic-gate 		buf[buflen - 1] = c;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	va_end(args);
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	return (bufp - buf);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
222*7c478bd9Sstevel@tonic-gate size_t
223*7c478bd9Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...)
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	va_list args;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
228*7c478bd9Sstevel@tonic-gate 	buflen = vsnprintf(buf, buflen, fmt, args);
229*7c478bd9Sstevel@tonic-gate 	va_end(args);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	return (buflen);
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate #if defined(_BOOT)
235*7c478bd9Sstevel@tonic-gate /*
236*7c478bd9Sstevel@tonic-gate  * The sprintf() and vsprintf() routines aren't shared with the kernel because
237*7c478bd9Sstevel@tonic-gate  * the DDI mandates that they return the buffer rather than its length.
238*7c478bd9Sstevel@tonic-gate  */
239*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
240*7c478bd9Sstevel@tonic-gate int
241*7c478bd9Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...)
242*7c478bd9Sstevel@tonic-gate {
243*7c478bd9Sstevel@tonic-gate 	va_list args;
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
246*7c478bd9Sstevel@tonic-gate 	(void) vsnprintf(buf, INT_MAX, fmt, args);
247*7c478bd9Sstevel@tonic-gate 	va_end(args);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	return (strlen(buf));
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate int
253*7c478bd9Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	(void) vsnprintf(buf, INT_MAX, fmt, args);
256*7c478bd9Sstevel@tonic-gate 	return (strlen(buf));
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate #endif
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate #endif /* !_KMDB */
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate char *
263*7c478bd9Sstevel@tonic-gate strcat(char *s1, const char *s2)
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	char *os1 = s1;
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	while (*s1++ != '\0')
268*7c478bd9Sstevel@tonic-gate 		;
269*7c478bd9Sstevel@tonic-gate 	s1--;
270*7c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0')
271*7c478bd9Sstevel@tonic-gate 		;
272*7c478bd9Sstevel@tonic-gate 	return (os1);
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate char *
276*7c478bd9Sstevel@tonic-gate strchr(const char *sp, int c)
277*7c478bd9Sstevel@tonic-gate {
278*7c478bd9Sstevel@tonic-gate 	do {
279*7c478bd9Sstevel@tonic-gate 		if (*sp == (char)c)
280*7c478bd9Sstevel@tonic-gate 			return ((char *)sp);
281*7c478bd9Sstevel@tonic-gate 	} while (*sp++);
282*7c478bd9Sstevel@tonic-gate 	return (NULL);
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate int
286*7c478bd9Sstevel@tonic-gate strcmp(const char *s1, const char *s2)
287*7c478bd9Sstevel@tonic-gate {
288*7c478bd9Sstevel@tonic-gate 	while (*s1 == *s2++)
289*7c478bd9Sstevel@tonic-gate 		if (*s1++ == '\0')
290*7c478bd9Sstevel@tonic-gate 			return (0);
291*7c478bd9Sstevel@tonic-gate 	return (*(unsigned char *)s1 - *(unsigned char *)--s2);
292*7c478bd9Sstevel@tonic-gate }
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate int
295*7c478bd9Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n)
296*7c478bd9Sstevel@tonic-gate {
297*7c478bd9Sstevel@tonic-gate 	if (s1 == s2)
298*7c478bd9Sstevel@tonic-gate 		return (0);
299*7c478bd9Sstevel@tonic-gate 	n++;
300*7c478bd9Sstevel@tonic-gate 	while (--n != 0 && *s1 == *s2++)
301*7c478bd9Sstevel@tonic-gate 		if (*s1++ == '\0')
302*7c478bd9Sstevel@tonic-gate 			return (0);
303*7c478bd9Sstevel@tonic-gate 	return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2);
304*7c478bd9Sstevel@tonic-gate }
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate static const char charmap[] = {
307*7c478bd9Sstevel@tonic-gate 	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
308*7c478bd9Sstevel@tonic-gate 	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
309*7c478bd9Sstevel@tonic-gate 	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
310*7c478bd9Sstevel@tonic-gate 	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
311*7c478bd9Sstevel@tonic-gate 	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
312*7c478bd9Sstevel@tonic-gate 	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
313*7c478bd9Sstevel@tonic-gate 	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
314*7c478bd9Sstevel@tonic-gate 	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
315*7c478bd9Sstevel@tonic-gate 	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
316*7c478bd9Sstevel@tonic-gate 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
317*7c478bd9Sstevel@tonic-gate 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
318*7c478bd9Sstevel@tonic-gate 	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
319*7c478bd9Sstevel@tonic-gate 	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
320*7c478bd9Sstevel@tonic-gate 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
321*7c478bd9Sstevel@tonic-gate 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
322*7c478bd9Sstevel@tonic-gate 	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
323*7c478bd9Sstevel@tonic-gate 	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
324*7c478bd9Sstevel@tonic-gate 	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
325*7c478bd9Sstevel@tonic-gate 	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
326*7c478bd9Sstevel@tonic-gate 	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
327*7c478bd9Sstevel@tonic-gate 	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
328*7c478bd9Sstevel@tonic-gate 	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
329*7c478bd9Sstevel@tonic-gate 	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
330*7c478bd9Sstevel@tonic-gate 	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
331*7c478bd9Sstevel@tonic-gate 	'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
332*7c478bd9Sstevel@tonic-gate 	'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
333*7c478bd9Sstevel@tonic-gate 	'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
334*7c478bd9Sstevel@tonic-gate 	'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
335*7c478bd9Sstevel@tonic-gate 	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
336*7c478bd9Sstevel@tonic-gate 	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
337*7c478bd9Sstevel@tonic-gate 	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
338*7c478bd9Sstevel@tonic-gate 	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
339*7c478bd9Sstevel@tonic-gate };
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate int
342*7c478bd9Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2)
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 	const unsigned char *cm = (const unsigned char *)charmap;
345*7c478bd9Sstevel@tonic-gate 	const unsigned char *us1 = (const unsigned char *)s1;
346*7c478bd9Sstevel@tonic-gate 	const unsigned char *us2 = (const unsigned char *)s2;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	while (cm[*us1] == cm[*us2++])
349*7c478bd9Sstevel@tonic-gate 		if (*us1++ == '\0')
350*7c478bd9Sstevel@tonic-gate 			return (0);
351*7c478bd9Sstevel@tonic-gate 	return (cm[*us1] - cm[*(us2 - 1)]);
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate int
355*7c478bd9Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	const unsigned char *cm = (const unsigned char *)charmap;
358*7c478bd9Sstevel@tonic-gate 	const unsigned char *us1 = (const unsigned char *)s1;
359*7c478bd9Sstevel@tonic-gate 	const unsigned char *us2 = (const unsigned char *)s2;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	while (n != 0 && cm[*us1] == cm[*us2++]) {
362*7c478bd9Sstevel@tonic-gate 		if (*us1++ == '\0')
363*7c478bd9Sstevel@tonic-gate 			return (0);
364*7c478bd9Sstevel@tonic-gate 		n--;
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 	return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate char *
370*7c478bd9Sstevel@tonic-gate strcpy(char *s1, const char *s2)
371*7c478bd9Sstevel@tonic-gate {
372*7c478bd9Sstevel@tonic-gate 	char *os1 = s1;
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0')
375*7c478bd9Sstevel@tonic-gate 		;
376*7c478bd9Sstevel@tonic-gate 	return (os1);
377*7c478bd9Sstevel@tonic-gate }
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate char *
380*7c478bd9Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n)
381*7c478bd9Sstevel@tonic-gate {
382*7c478bd9Sstevel@tonic-gate 	char *os1 = s1;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	n++;
385*7c478bd9Sstevel@tonic-gate 	while (--n != 0 && (*s1++ = *s2++) != '\0')
386*7c478bd9Sstevel@tonic-gate 		;
387*7c478bd9Sstevel@tonic-gate 	if (n != 0)
388*7c478bd9Sstevel@tonic-gate 		while (--n != 0)
389*7c478bd9Sstevel@tonic-gate 			*s1++ = '\0';
390*7c478bd9Sstevel@tonic-gate 	return (os1);
391*7c478bd9Sstevel@tonic-gate }
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate char *
394*7c478bd9Sstevel@tonic-gate strrchr(const char *sp, int c)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate 	char *r = NULL;
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	do {
399*7c478bd9Sstevel@tonic-gate 		if (*sp == (char)c)
400*7c478bd9Sstevel@tonic-gate 			r = (char *)sp;
401*7c478bd9Sstevel@tonic-gate 	} while (*sp++);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	return (r);
404*7c478bd9Sstevel@tonic-gate }
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate char *
407*7c478bd9Sstevel@tonic-gate strstr(const char *as1, const char *as2)
408*7c478bd9Sstevel@tonic-gate {
409*7c478bd9Sstevel@tonic-gate 	const char *s1, *s2;
410*7c478bd9Sstevel@tonic-gate 	const char *tptr;
411*7c478bd9Sstevel@tonic-gate 	char c;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	s1 = as1;
414*7c478bd9Sstevel@tonic-gate 	s2 = as2;
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	if (s2 == NULL || *s2 == '\0')
417*7c478bd9Sstevel@tonic-gate 		return ((char *)s1);
418*7c478bd9Sstevel@tonic-gate 	c = *s2;
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	while (*s1)
421*7c478bd9Sstevel@tonic-gate 		if (*s1++ == c) {
422*7c478bd9Sstevel@tonic-gate 			tptr = s1;
423*7c478bd9Sstevel@tonic-gate 			while ((c = *++s2) == *s1++ && c)
424*7c478bd9Sstevel@tonic-gate 				;
425*7c478bd9Sstevel@tonic-gate 			if (c == 0)
426*7c478bd9Sstevel@tonic-gate 				return ((char *)tptr - 1);
427*7c478bd9Sstevel@tonic-gate 			s1 = tptr;
428*7c478bd9Sstevel@tonic-gate 			s2 = as2;
429*7c478bd9Sstevel@tonic-gate 			c = *s2;
430*7c478bd9Sstevel@tonic-gate 		}
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	return (NULL);
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate char *
436*7c478bd9Sstevel@tonic-gate strpbrk(const char *string, const char *brkset)
437*7c478bd9Sstevel@tonic-gate {
438*7c478bd9Sstevel@tonic-gate 	const char *p;
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	do {
441*7c478bd9Sstevel@tonic-gate 		for (p = brkset; *p != '\0' && *p != *string; ++p)
442*7c478bd9Sstevel@tonic-gate 			;
443*7c478bd9Sstevel@tonic-gate 		if (*p != '\0')
444*7c478bd9Sstevel@tonic-gate 			return ((char *)string);
445*7c478bd9Sstevel@tonic-gate 	} while (*string++);
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	return (NULL);
448*7c478bd9Sstevel@tonic-gate }
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate char *
451*7c478bd9Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n)
452*7c478bd9Sstevel@tonic-gate {
453*7c478bd9Sstevel@tonic-gate 	char *os1 = s1;
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	n++;
456*7c478bd9Sstevel@tonic-gate 	while (*s1++ != '\0')
457*7c478bd9Sstevel@tonic-gate 		;
458*7c478bd9Sstevel@tonic-gate 	--s1;
459*7c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0') {
460*7c478bd9Sstevel@tonic-gate 		if (--n == 0) {
461*7c478bd9Sstevel@tonic-gate 			s1[-1] = '\0';
462*7c478bd9Sstevel@tonic-gate 			break;
463*7c478bd9Sstevel@tonic-gate 		}
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 	return (os1);
466*7c478bd9Sstevel@tonic-gate }
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
469*7c478bd9Sstevel@tonic-gate #define	bcopy(src, dst, n)	(void) memcpy((dst), (src), (n))
470*7c478bd9Sstevel@tonic-gate #endif
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate size_t
473*7c478bd9Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize)
474*7c478bd9Sstevel@tonic-gate {
475*7c478bd9Sstevel@tonic-gate 	char *df = dst;
476*7c478bd9Sstevel@tonic-gate 	size_t left = dstsize;
477*7c478bd9Sstevel@tonic-gate 	size_t l1;
478*7c478bd9Sstevel@tonic-gate 	size_t l2 = strlen(src);
479*7c478bd9Sstevel@tonic-gate 	size_t copied;
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	while (left-- != 0 && *df != '\0')
482*7c478bd9Sstevel@tonic-gate 		df++;
483*7c478bd9Sstevel@tonic-gate 	l1 = df - dst;
484*7c478bd9Sstevel@tonic-gate 	if (dstsize == l1)
485*7c478bd9Sstevel@tonic-gate 		return (l1 + l2);
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2;
488*7c478bd9Sstevel@tonic-gate 	bcopy(src, dst + l1, copied);
489*7c478bd9Sstevel@tonic-gate 	dst[l1+copied] = '\0';
490*7c478bd9Sstevel@tonic-gate 	return (l1 + l2);
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate size_t
494*7c478bd9Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len)
495*7c478bd9Sstevel@tonic-gate {
496*7c478bd9Sstevel@tonic-gate 	size_t slen = strlen(src);
497*7c478bd9Sstevel@tonic-gate 	size_t copied;
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	if (len == 0)
500*7c478bd9Sstevel@tonic-gate 		return (slen);
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	if (slen >= len)
503*7c478bd9Sstevel@tonic-gate 		copied = len - 1;
504*7c478bd9Sstevel@tonic-gate 	else
505*7c478bd9Sstevel@tonic-gate 		copied = slen;
506*7c478bd9Sstevel@tonic-gate 	bcopy(src, dst, copied);
507*7c478bd9Sstevel@tonic-gate 	dst[copied] = '\0';
508*7c478bd9Sstevel@tonic-gate 	return (slen);
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate size_t
512*7c478bd9Sstevel@tonic-gate strspn(const char *string, const char *charset)
513*7c478bd9Sstevel@tonic-gate {
514*7c478bd9Sstevel@tonic-gate 	const char *p, *q;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	for (q = string; *q != '\0'; ++q) {
517*7c478bd9Sstevel@tonic-gate 		for (p = charset; *p != '\0' && *p != *q; ++p)
518*7c478bd9Sstevel@tonic-gate 			;
519*7c478bd9Sstevel@tonic-gate 		if (*p == '\0')
520*7c478bd9Sstevel@tonic-gate 			break;
521*7c478bd9Sstevel@tonic-gate 	}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	return (q - string);
524*7c478bd9Sstevel@tonic-gate }
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate /*
527*7c478bd9Sstevel@tonic-gate  * Unless mentioned otherwise, all of the routines below should be added to
528*7c478bd9Sstevel@tonic-gate  * the Solaris DDI as necessary.  For now, only provide them to standalone.
529*7c478bd9Sstevel@tonic-gate  */
530*7c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
531*7c478bd9Sstevel@tonic-gate char *
532*7c478bd9Sstevel@tonic-gate strtok(char *string, const char *sepset)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate 	char		*p, *q, *r;
535*7c478bd9Sstevel@tonic-gate 	static char	*savept;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	/*
538*7c478bd9Sstevel@tonic-gate 	 * Set `p' to our current location in the string.
539*7c478bd9Sstevel@tonic-gate 	 */
540*7c478bd9Sstevel@tonic-gate 	p = (string == NULL) ? savept : string;
541*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
542*7c478bd9Sstevel@tonic-gate 		return (NULL);
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	/*
545*7c478bd9Sstevel@tonic-gate 	 * Skip leading separators; bail if no tokens remain.
546*7c478bd9Sstevel@tonic-gate 	 */
547*7c478bd9Sstevel@tonic-gate 	q = p + strspn(p, sepset);
548*7c478bd9Sstevel@tonic-gate 	if (*q == '\0')
549*7c478bd9Sstevel@tonic-gate 		return (NULL);
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 	/*
552*7c478bd9Sstevel@tonic-gate 	 * Mark the end of the token and set `savept' for the next iteration.
553*7c478bd9Sstevel@tonic-gate 	 */
554*7c478bd9Sstevel@tonic-gate 	if ((r = strpbrk(q, sepset)) == NULL)
555*7c478bd9Sstevel@tonic-gate 		savept = NULL;
556*7c478bd9Sstevel@tonic-gate 	else {
557*7c478bd9Sstevel@tonic-gate 		*r = '\0';
558*7c478bd9Sstevel@tonic-gate 		savept = ++r;
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	return (q);
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate /*
565*7c478bd9Sstevel@tonic-gate  * The strlen() routine isn't shared with the kernel because it has its own
566*7c478bd9Sstevel@tonic-gate  * hand-tuned assembly version.
567*7c478bd9Sstevel@tonic-gate  */
568*7c478bd9Sstevel@tonic-gate size_t
569*7c478bd9Sstevel@tonic-gate strlen(const char *s)
570*7c478bd9Sstevel@tonic-gate {
571*7c478bd9Sstevel@tonic-gate 	size_t n = 0;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	while (*s++)
574*7c478bd9Sstevel@tonic-gate 		n++;
575*7c478bd9Sstevel@tonic-gate 	return (n);
576*7c478bd9Sstevel@tonic-gate }
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate #endif /* _BOOT || _KMDB */
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate #ifdef _KERNEL
581*7c478bd9Sstevel@tonic-gate /*
582*7c478bd9Sstevel@tonic-gate  * Check for a valid C identifier:
583*7c478bd9Sstevel@tonic-gate  *	a letter or underscore, followed by
584*7c478bd9Sstevel@tonic-gate  *	zero or more letters, digits and underscores.
585*7c478bd9Sstevel@tonic-gate  */
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate #define	IS_DIGIT(c)	((c) >= '0' && (c) <= '9')
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate #define	IS_ALPHA(c)	\
590*7c478bd9Sstevel@tonic-gate 	(((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate int
593*7c478bd9Sstevel@tonic-gate strident_valid(const char *id)
594*7c478bd9Sstevel@tonic-gate {
595*7c478bd9Sstevel@tonic-gate 	int c = *id++;
596*7c478bd9Sstevel@tonic-gate 
597*7c478bd9Sstevel@tonic-gate 	if (!IS_ALPHA(c) && c != '_')
598*7c478bd9Sstevel@tonic-gate 		return (0);
599*7c478bd9Sstevel@tonic-gate 	while ((c = *id++) != 0) {
600*7c478bd9Sstevel@tonic-gate 		if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
601*7c478bd9Sstevel@tonic-gate 			return (0);
602*7c478bd9Sstevel@tonic-gate 	}
603*7c478bd9Sstevel@tonic-gate 	return (1);
604*7c478bd9Sstevel@tonic-gate }
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate /*
607*7c478bd9Sstevel@tonic-gate  * Convert a string into a valid C identifier by replacing invalid
608*7c478bd9Sstevel@tonic-gate  * characters with '_'.  Also makes sure the string is nul-terminated
609*7c478bd9Sstevel@tonic-gate  * and takes up at most n bytes.
610*7c478bd9Sstevel@tonic-gate  */
611*7c478bd9Sstevel@tonic-gate void
612*7c478bd9Sstevel@tonic-gate strident_canon(char *s, size_t n)
613*7c478bd9Sstevel@tonic-gate {
614*7c478bd9Sstevel@tonic-gate 	char c;
615*7c478bd9Sstevel@tonic-gate 	char *end = s + n - 1;
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	ASSERT(n > 0);
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	if ((c = *s) == 0)
620*7c478bd9Sstevel@tonic-gate 		return;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	if (!IS_ALPHA(c) && c != '_')
623*7c478bd9Sstevel@tonic-gate 		*s = '_';
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	while (s < end && ((c = *(++s)) != 0)) {
626*7c478bd9Sstevel@tonic-gate 		if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
627*7c478bd9Sstevel@tonic-gate 			*s = '_';
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 	*s = 0;
630*7c478bd9Sstevel@tonic-gate }
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
633