xref: /illumos-gate/usr/src/common/util/string.c (revision 3c5da275)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5049fa28aSdr  * Common Development and Distribution License (the "License").
6049fa28aSdr  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227637daddSmyers  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24237b1f31SPatrick Mooney  * Copyright 2014 Joyent, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*3c5da275SMatthew Ahrens /*
28*3c5da275SMatthew Ahrens  * Copyright (c) 2016 by Delphix. All rights reserved.
29*3c5da275SMatthew Ahrens  */
30*3c5da275SMatthew Ahrens 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Implementations of the functions described in vsnprintf(3C) and string(3C),
337c478bd9Sstevel@tonic-gate  * for use by the kernel, the standalone, and kmdb.  Unless otherwise specified,
347c478bd9Sstevel@tonic-gate  * these functions match the section 3C manpages.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
384870e0a7SRichard PALO #include <sys/null.h>
397c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
40ae115bc7Smrj 
41ae115bc7Smrj #if defined(_KERNEL)
427c478bd9Sstevel@tonic-gate #include <sys/systm.h>
437c478bd9Sstevel@tonic-gate #include <sys/debug.h>
44ae115bc7Smrj #elif !defined(_BOOT)
45ae115bc7Smrj #include <string.h>
46ae115bc7Smrj #endif
47ae115bc7Smrj 
48ae115bc7Smrj #include "memcpy.h"
49ae115bc7Smrj #include "string.h"
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
52ae115bc7Smrj  * We don't need these for x86 boot or kmdb.
537c478bd9Sstevel@tonic-gate  */
54ae115bc7Smrj #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc))
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	ADDCHAR(c)	if (bufp++ - buf < buflen) bufp[-1] = (c)
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * Given a buffer 'buf' of size 'buflen', render as much of the string
607c478bd9Sstevel@tonic-gate  * described by <fmt, args> as possible.  The string will always be
617c478bd9Sstevel@tonic-gate  * null-terminated, so the maximum string length is 'buflen - 1'.
627c478bd9Sstevel@tonic-gate  * Returns the number of bytes that would be necessary to render the
637c478bd9Sstevel@tonic-gate  * entire string, not including null terminator (just like vsnprintf(3S)).
647c478bd9Sstevel@tonic-gate  * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1.
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  * There is no support for floating point, and the C locale is assumed.
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate size_t
697c478bd9Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate 	uint64_t ul, tmp;
727c478bd9Sstevel@tonic-gate 	char *bufp = buf;	/* current buffer pointer */
73186507a7Smyers 	int pad, width, base, sign, c, num;
74186507a7Smyers 	int prec, h_count, l_count, dot_count;
75186507a7Smyers 	int pad_count, transfer_count, left_align;
767c478bd9Sstevel@tonic-gate 	char *digits, *sp, *bs;
777c478bd9Sstevel@tonic-gate 	char numbuf[65];	/* sufficient for a 64-bit binary value */
787c478bd9Sstevel@tonic-gate 	va_list args;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	/*
817c478bd9Sstevel@tonic-gate 	 * Make a copy so that all our callers don't have to make a copy
827c478bd9Sstevel@tonic-gate 	 */
837c478bd9Sstevel@tonic-gate 	va_copy(args, aargs);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	if ((ssize_t)buflen < 0)
867c478bd9Sstevel@tonic-gate 		buflen = 0;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	while ((c = *fmt++) != '\0') {
897c478bd9Sstevel@tonic-gate 		if (c != '%') {
907c478bd9Sstevel@tonic-gate 			ADDCHAR(c);
917c478bd9Sstevel@tonic-gate 			continue;
927c478bd9Sstevel@tonic-gate 		}
937c478bd9Sstevel@tonic-gate 
94186507a7Smyers 		width = prec = 0;
95186507a7Smyers 		left_align = base = sign = 0;
96186507a7Smyers 		h_count = l_count = dot_count = 0;
97186507a7Smyers 		pad = ' ';
98186507a7Smyers 		digits = "0123456789abcdef";
99186507a7Smyers next_fmt:
1007c478bd9Sstevel@tonic-gate 		if ((c = *fmt++) == '\0')
1017c478bd9Sstevel@tonic-gate 			break;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 		if (c >= 'A' && c <= 'Z') {
1047c478bd9Sstevel@tonic-gate 			c += 'a' - 'A';
1057c478bd9Sstevel@tonic-gate 			digits = "0123456789ABCDEF";
1067c478bd9Sstevel@tonic-gate 		}
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 		switch (c) {
109186507a7Smyers 		case '-':
110186507a7Smyers 			left_align++;
111186507a7Smyers 			goto next_fmt;
112186507a7Smyers 		case '0':
113186507a7Smyers 			if (dot_count == 0)
114186507a7Smyers 				pad = '0';
115186507a7Smyers 			/*FALLTHROUGH*/
116186507a7Smyers 		case '1':
117186507a7Smyers 		case '2':
118186507a7Smyers 		case '3':
119186507a7Smyers 		case '4':
120186507a7Smyers 		case '5':
121186507a7Smyers 		case '6':
122186507a7Smyers 		case '7':
123186507a7Smyers 		case '8':
124186507a7Smyers 		case '9':
125186507a7Smyers 			num = 0;
126186507a7Smyers 			for (;;) {
127186507a7Smyers 				num = 10 * num + c - '0';
128186507a7Smyers 				c = *fmt;
129186507a7Smyers 				if (c < '0' || c > '9')
130186507a7Smyers 					break;
131186507a7Smyers 				else
132186507a7Smyers 					fmt++;
133186507a7Smyers 			}
134186507a7Smyers 			if (dot_count > 0)
135186507a7Smyers 				prec = num;
136186507a7Smyers 			else
137186507a7Smyers 				width = num;
138186507a7Smyers 
139186507a7Smyers 			goto next_fmt;
140186507a7Smyers 		case '.':
141186507a7Smyers 			dot_count++;
142186507a7Smyers 			goto next_fmt;
143186507a7Smyers 		case '*':
144049fa28aSdr 			if (dot_count > 0)
145049fa28aSdr 				prec = (int)va_arg(args, int);
146049fa28aSdr 			else
147049fa28aSdr 				width = (int)va_arg(args, int);
148186507a7Smyers 			goto next_fmt;
149186507a7Smyers 		case 'l':
150186507a7Smyers 			l_count++;
151186507a7Smyers 			goto next_fmt;
152186507a7Smyers 		case 'h':
153186507a7Smyers 			h_count++;
154186507a7Smyers 			goto next_fmt;
1557c478bd9Sstevel@tonic-gate 		case 'd':
1567c478bd9Sstevel@tonic-gate 			sign = 1;
1577c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
1587c478bd9Sstevel@tonic-gate 		case 'u':
1597c478bd9Sstevel@tonic-gate 			base = 10;
1607c478bd9Sstevel@tonic-gate 			break;
1617c478bd9Sstevel@tonic-gate 		case 'p':
162186507a7Smyers 			l_count = 1;
1637c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
1647c478bd9Sstevel@tonic-gate 		case 'x':
1657c478bd9Sstevel@tonic-gate 			base = 16;
1667c478bd9Sstevel@tonic-gate 			break;
1677c478bd9Sstevel@tonic-gate 		case 'o':
1687c478bd9Sstevel@tonic-gate 			base = 8;
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		case 'b':
171186507a7Smyers 			l_count = 0;
1727c478bd9Sstevel@tonic-gate 			base = 1;
1737c478bd9Sstevel@tonic-gate 			break;
1747c478bd9Sstevel@tonic-gate 		case 'c':
175fc77c268Smyers 			c = (char)va_arg(args, int);
176186507a7Smyers 			ADDCHAR(c);
1777c478bd9Sstevel@tonic-gate 			break;
1787c478bd9Sstevel@tonic-gate 		case 's':
1797c478bd9Sstevel@tonic-gate 			sp = va_arg(args, char *);
180186507a7Smyers 			if (sp == NULL) {
1817c478bd9Sstevel@tonic-gate 				sp = "<null string>";
182186507a7Smyers 				/* avoid truncation */
183186507a7Smyers 				prec = strlen(sp);
184186507a7Smyers 			}
185186507a7Smyers 			/*
186186507a7Smyers 			 * Handle simple case specially to avoid
187186507a7Smyers 			 * performance hit of strlen()
188186507a7Smyers 			 */
189186507a7Smyers 			if (prec == 0 && width == 0) {
190186507a7Smyers 				while ((c = *sp++) != 0)
191186507a7Smyers 					ADDCHAR(c);
192186507a7Smyers 				break;
193186507a7Smyers 			}
194186507a7Smyers 			if (prec > 0) {
1957637daddSmyers 				transfer_count = strnlen(sp, prec);
196186507a7Smyers 				/* widen field if too narrow */
197186507a7Smyers 				if (prec > width)
198186507a7Smyers 					width = prec;
1997637daddSmyers 			} else
2007637daddSmyers 				transfer_count = strlen(sp);
201186507a7Smyers 			if (width > transfer_count)
202186507a7Smyers 				pad_count = width - transfer_count;
203186507a7Smyers 			else
204186507a7Smyers 				pad_count = 0;
205186507a7Smyers 			while ((!left_align) && (pad_count-- > 0))
206186507a7Smyers 				ADDCHAR(' ');
207186507a7Smyers 			/* ADDCHAR() evaluates arg at most once */
208186507a7Smyers 			while (transfer_count-- > 0)
209186507a7Smyers 				ADDCHAR(*sp++);
210186507a7Smyers 			while ((left_align) && (pad_count-- > 0))
211186507a7Smyers 				ADDCHAR(' ');
2127c478bd9Sstevel@tonic-gate 			break;
2137c478bd9Sstevel@tonic-gate 		case '%':
2147c478bd9Sstevel@tonic-gate 			ADDCHAR('%');
2157c478bd9Sstevel@tonic-gate 			break;
2167c478bd9Sstevel@tonic-gate 		}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 		if (base == 0)
2197c478bd9Sstevel@tonic-gate 			continue;
2207c478bd9Sstevel@tonic-gate 
221186507a7Smyers 		if (h_count == 0 && l_count == 0)
222186507a7Smyers 			if (sign)
223186507a7Smyers 				ul = (int64_t)va_arg(args, int);
224186507a7Smyers 			else
225186507a7Smyers 				ul = (int64_t)va_arg(args, unsigned int);
226186507a7Smyers 		else if (l_count > 1)
227186507a7Smyers 			if (sign)
228186507a7Smyers 				ul = (int64_t)va_arg(args, int64_t);
229186507a7Smyers 			else
230186507a7Smyers 				ul = (int64_t)va_arg(args, uint64_t);
231186507a7Smyers 		else if (l_count > 0)
232186507a7Smyers 			if (sign)
233186507a7Smyers 				ul = (int64_t)va_arg(args, long);
234186507a7Smyers 			else
235186507a7Smyers 				ul = (int64_t)va_arg(args, unsigned long);
236186507a7Smyers 		else if (h_count > 1)
237186507a7Smyers 			if (sign)
238fc77c268Smyers 				ul = (int64_t)((char)va_arg(args, int));
239186507a7Smyers 			else
240fc77c268Smyers 				ul = (int64_t)((unsigned char)va_arg(args,
241fc77c268Smyers 				    int));
242186507a7Smyers 		else if (h_count > 0)
243186507a7Smyers 			if (sign)
244fc77c268Smyers 				ul = (int64_t)((short)va_arg(args, int));
245186507a7Smyers 			else
246fc77c268Smyers 				ul = (int64_t)((unsigned short)va_arg(args,
247fc77c268Smyers 				    int));
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		if (sign && (int64_t)ul < 0)
2507c478bd9Sstevel@tonic-gate 			ul = -ul;
2517c478bd9Sstevel@tonic-gate 		else
2527c478bd9Sstevel@tonic-gate 			sign = 0;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		if (c == 'b') {
2557c478bd9Sstevel@tonic-gate 			bs = va_arg(args, char *);
2567c478bd9Sstevel@tonic-gate 			base = *bs++;
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 
259186507a7Smyers 		/* avoid repeated division if width is 0 */
260186507a7Smyers 		if (width > 0) {
261186507a7Smyers 			tmp = ul;
262186507a7Smyers 			do {
263186507a7Smyers 				width--;
264186507a7Smyers 			} while ((tmp /= base) != 0);
265186507a7Smyers 		}
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		if (sign && pad == '0')
2687c478bd9Sstevel@tonic-gate 			ADDCHAR('-');
269237b1f31SPatrick Mooney 		while ((!left_align) && (width-- > sign))
2707c478bd9Sstevel@tonic-gate 			ADDCHAR(pad);
2717c478bd9Sstevel@tonic-gate 		if (sign && pad == ' ')
2727c478bd9Sstevel@tonic-gate 			ADDCHAR('-');
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 		sp = numbuf;
2757c478bd9Sstevel@tonic-gate 		tmp = ul;
2767c478bd9Sstevel@tonic-gate 		do {
2777c478bd9Sstevel@tonic-gate 			*sp++ = digits[tmp % base];
2787c478bd9Sstevel@tonic-gate 		} while ((tmp /= base) != 0);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 		while (sp > numbuf) {
2817c478bd9Sstevel@tonic-gate 			sp--;
2827c478bd9Sstevel@tonic-gate 			ADDCHAR(*sp);
2837c478bd9Sstevel@tonic-gate 		}
2847c478bd9Sstevel@tonic-gate 
285237b1f31SPatrick Mooney 		/* add left-alignment padding */
286237b1f31SPatrick Mooney 		while (width-- > sign)
287237b1f31SPatrick Mooney 			ADDCHAR(' ');
288237b1f31SPatrick Mooney 
2897c478bd9Sstevel@tonic-gate 		if (c == 'b' && ul != 0) {
2907c478bd9Sstevel@tonic-gate 			int any = 0;
2917c478bd9Sstevel@tonic-gate 			c = *bs++;
2927c478bd9Sstevel@tonic-gate 			while (c != 0) {
2937c478bd9Sstevel@tonic-gate 				if (ul & (1 << (c - 1))) {
2947c478bd9Sstevel@tonic-gate 					if (any++ == 0)
2957c478bd9Sstevel@tonic-gate 						ADDCHAR('<');
2967c478bd9Sstevel@tonic-gate 					while ((c = *bs++) >= 32)
2977c478bd9Sstevel@tonic-gate 						ADDCHAR(c);
2987c478bd9Sstevel@tonic-gate 					ADDCHAR(',');
2997c478bd9Sstevel@tonic-gate 				} else {
3007c478bd9Sstevel@tonic-gate 					while ((c = *bs++) >= 32)
3017c478bd9Sstevel@tonic-gate 						continue;
3027c478bd9Sstevel@tonic-gate 				}
3037c478bd9Sstevel@tonic-gate 			}
3047c478bd9Sstevel@tonic-gate 			if (any) {
3057c478bd9Sstevel@tonic-gate 				bufp--;
3067c478bd9Sstevel@tonic-gate 				ADDCHAR('>');
3077c478bd9Sstevel@tonic-gate 			}
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 	if (bufp - buf < buflen)
3117c478bd9Sstevel@tonic-gate 		bufp[0] = c;
3127c478bd9Sstevel@tonic-gate 	else if (buflen != 0)
3137c478bd9Sstevel@tonic-gate 		buf[buflen - 1] = c;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	va_end(args);
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	return (bufp - buf);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
320*3c5da275SMatthew Ahrens /*PRINTFLIKE3*/
3217c478bd9Sstevel@tonic-gate size_t
3227c478bd9Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	va_list args;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
3277c478bd9Sstevel@tonic-gate 	buflen = vsnprintf(buf, buflen, fmt, args);
3287c478bd9Sstevel@tonic-gate 	va_end(args);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	return (buflen);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
333ae115bc7Smrj #if defined(_BOOT) && defined(__sparc)
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate  * The sprintf() and vsprintf() routines aren't shared with the kernel because
3367c478bd9Sstevel@tonic-gate  * the DDI mandates that they return the buffer rather than its length.
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
3397c478bd9Sstevel@tonic-gate int
3407c478bd9Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	va_list args;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
3457c478bd9Sstevel@tonic-gate 	(void) vsnprintf(buf, INT_MAX, fmt, args);
3467c478bd9Sstevel@tonic-gate 	va_end(args);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	return (strlen(buf));
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate int
3527c478bd9Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args)
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate 	(void) vsnprintf(buf, INT_MAX, fmt, args);
3557c478bd9Sstevel@tonic-gate 	return (strlen(buf));
3567c478bd9Sstevel@tonic-gate }
357ae115bc7Smrj #endif /* _BOOT && __sparc */
3587c478bd9Sstevel@tonic-gate 
359ae115bc7Smrj #endif /* !_KMDB && (!_BOOT || __sparc) */
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate char *
3627c478bd9Sstevel@tonic-gate strcat(char *s1, const char *s2)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	char *os1 = s1;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	while (*s1++ != '\0')
3677c478bd9Sstevel@tonic-gate 		;
3687c478bd9Sstevel@tonic-gate 	s1--;
3697c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0')
3707c478bd9Sstevel@tonic-gate 		;
3717c478bd9Sstevel@tonic-gate 	return (os1);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate char *
3757c478bd9Sstevel@tonic-gate strchr(const char *sp, int c)
3767c478bd9Sstevel@tonic-gate {
3777c478bd9Sstevel@tonic-gate 	do {
3787c478bd9Sstevel@tonic-gate 		if (*sp == (char)c)
3797c478bd9Sstevel@tonic-gate 			return ((char *)sp);
3807c478bd9Sstevel@tonic-gate 	} while (*sp++);
3817c478bd9Sstevel@tonic-gate 	return (NULL);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate int
3857c478bd9Sstevel@tonic-gate strcmp(const char *s1, const char *s2)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate 	while (*s1 == *s2++)
3887c478bd9Sstevel@tonic-gate 		if (*s1++ == '\0')
3897c478bd9Sstevel@tonic-gate 			return (0);
3907c478bd9Sstevel@tonic-gate 	return (*(unsigned char *)s1 - *(unsigned char *)--s2);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate int
3947c478bd9Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 	if (s1 == s2)
3977c478bd9Sstevel@tonic-gate 		return (0);
3987c478bd9Sstevel@tonic-gate 	n++;
3997c478bd9Sstevel@tonic-gate 	while (--n != 0 && *s1 == *s2++)
4007c478bd9Sstevel@tonic-gate 		if (*s1++ == '\0')
4017c478bd9Sstevel@tonic-gate 			return (0);
4027c478bd9Sstevel@tonic-gate 	return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2);
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate static const char charmap[] = {
4067c478bd9Sstevel@tonic-gate 	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
4077c478bd9Sstevel@tonic-gate 	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
4087c478bd9Sstevel@tonic-gate 	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
4097c478bd9Sstevel@tonic-gate 	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
4107c478bd9Sstevel@tonic-gate 	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
4117c478bd9Sstevel@tonic-gate 	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
4127c478bd9Sstevel@tonic-gate 	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
4137c478bd9Sstevel@tonic-gate 	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
4147c478bd9Sstevel@tonic-gate 	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4157c478bd9Sstevel@tonic-gate 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4167c478bd9Sstevel@tonic-gate 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4177c478bd9Sstevel@tonic-gate 	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
4187c478bd9Sstevel@tonic-gate 	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4197c478bd9Sstevel@tonic-gate 	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4207c478bd9Sstevel@tonic-gate 	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4217c478bd9Sstevel@tonic-gate 	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
4227c478bd9Sstevel@tonic-gate 	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
4237c478bd9Sstevel@tonic-gate 	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
4247c478bd9Sstevel@tonic-gate 	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
4257c478bd9Sstevel@tonic-gate 	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
4267c478bd9Sstevel@tonic-gate 	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
4277c478bd9Sstevel@tonic-gate 	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
4287c478bd9Sstevel@tonic-gate 	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
4297c478bd9Sstevel@tonic-gate 	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
4307c478bd9Sstevel@tonic-gate 	'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
4317c478bd9Sstevel@tonic-gate 	'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
4327c478bd9Sstevel@tonic-gate 	'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
4337c478bd9Sstevel@tonic-gate 	'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
4347c478bd9Sstevel@tonic-gate 	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
4357c478bd9Sstevel@tonic-gate 	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
4367c478bd9Sstevel@tonic-gate 	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
4377c478bd9Sstevel@tonic-gate 	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
4387c478bd9Sstevel@tonic-gate };
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate int
4417c478bd9Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	const unsigned char *cm = (const unsigned char *)charmap;
4447c478bd9Sstevel@tonic-gate 	const unsigned char *us1 = (const unsigned char *)s1;
4457c478bd9Sstevel@tonic-gate 	const unsigned char *us2 = (const unsigned char *)s2;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	while (cm[*us1] == cm[*us2++])
4487c478bd9Sstevel@tonic-gate 		if (*us1++ == '\0')
4497c478bd9Sstevel@tonic-gate 			return (0);
4507c478bd9Sstevel@tonic-gate 	return (cm[*us1] - cm[*(us2 - 1)]);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate int
4547c478bd9Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	const unsigned char *cm = (const unsigned char *)charmap;
4577c478bd9Sstevel@tonic-gate 	const unsigned char *us1 = (const unsigned char *)s1;
4587c478bd9Sstevel@tonic-gate 	const unsigned char *us2 = (const unsigned char *)s2;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	while (n != 0 && cm[*us1] == cm[*us2++]) {
4617c478bd9Sstevel@tonic-gate 		if (*us1++ == '\0')
4627c478bd9Sstevel@tonic-gate 			return (0);
4637c478bd9Sstevel@tonic-gate 		n--;
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 	return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate char *
4697c478bd9Sstevel@tonic-gate strcpy(char *s1, const char *s2)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	char *os1 = s1;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0')
4747c478bd9Sstevel@tonic-gate 		;
4757c478bd9Sstevel@tonic-gate 	return (os1);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate char *
4797c478bd9Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate 	char *os1 = s1;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	n++;
4847c478bd9Sstevel@tonic-gate 	while (--n != 0 && (*s1++ = *s2++) != '\0')
4857c478bd9Sstevel@tonic-gate 		;
4867c478bd9Sstevel@tonic-gate 	if (n != 0)
4877c478bd9Sstevel@tonic-gate 		while (--n != 0)
4887c478bd9Sstevel@tonic-gate 			*s1++ = '\0';
4897c478bd9Sstevel@tonic-gate 	return (os1);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate char *
4937c478bd9Sstevel@tonic-gate strrchr(const char *sp, int c)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	char *r = NULL;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	do {
4987c478bd9Sstevel@tonic-gate 		if (*sp == (char)c)
4997c478bd9Sstevel@tonic-gate 			r = (char *)sp;
5007c478bd9Sstevel@tonic-gate 	} while (*sp++);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	return (r);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate char *
5067c478bd9Sstevel@tonic-gate strstr(const char *as1, const char *as2)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	const char *s1, *s2;
5097c478bd9Sstevel@tonic-gate 	const char *tptr;
5107c478bd9Sstevel@tonic-gate 	char c;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	s1 = as1;
5137c478bd9Sstevel@tonic-gate 	s2 = as2;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (s2 == NULL || *s2 == '\0')
5167c478bd9Sstevel@tonic-gate 		return ((char *)s1);
5177c478bd9Sstevel@tonic-gate 	c = *s2;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	while (*s1)
5207c478bd9Sstevel@tonic-gate 		if (*s1++ == c) {
5217c478bd9Sstevel@tonic-gate 			tptr = s1;
5227c478bd9Sstevel@tonic-gate 			while ((c = *++s2) == *s1++ && c)
5237c478bd9Sstevel@tonic-gate 				;
5247c478bd9Sstevel@tonic-gate 			if (c == 0)
5257c478bd9Sstevel@tonic-gate 				return ((char *)tptr - 1);
5267c478bd9Sstevel@tonic-gate 			s1 = tptr;
5277c478bd9Sstevel@tonic-gate 			s2 = as2;
5287c478bd9Sstevel@tonic-gate 			c = *s2;
5297c478bd9Sstevel@tonic-gate 		}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	return (NULL);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate char *
5357c478bd9Sstevel@tonic-gate strpbrk(const char *string, const char *brkset)
5367c478bd9Sstevel@tonic-gate {
5377c478bd9Sstevel@tonic-gate 	const char *p;
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	do {
5407c478bd9Sstevel@tonic-gate 		for (p = brkset; *p != '\0' && *p != *string; ++p)
5417c478bd9Sstevel@tonic-gate 			;
5427c478bd9Sstevel@tonic-gate 		if (*p != '\0')
5437c478bd9Sstevel@tonic-gate 			return ((char *)string);
5447c478bd9Sstevel@tonic-gate 	} while (*string++);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	return (NULL);
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate char *
5507c478bd9Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n)
5517c478bd9Sstevel@tonic-gate {
5527c478bd9Sstevel@tonic-gate 	char *os1 = s1;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	n++;
5557c478bd9Sstevel@tonic-gate 	while (*s1++ != '\0')
5567c478bd9Sstevel@tonic-gate 		;
5577c478bd9Sstevel@tonic-gate 	--s1;
5587c478bd9Sstevel@tonic-gate 	while ((*s1++ = *s2++) != '\0') {
5597c478bd9Sstevel@tonic-gate 		if (--n == 0) {
5607c478bd9Sstevel@tonic-gate 			s1[-1] = '\0';
5617c478bd9Sstevel@tonic-gate 			break;
5627c478bd9Sstevel@tonic-gate 		}
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	return (os1);
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
5687c478bd9Sstevel@tonic-gate #define	bcopy(src, dst, n)	(void) memcpy((dst), (src), (n))
5697c478bd9Sstevel@tonic-gate #endif
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate size_t
5727c478bd9Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize)
5737c478bd9Sstevel@tonic-gate {
5747c478bd9Sstevel@tonic-gate 	char *df = dst;
5757c478bd9Sstevel@tonic-gate 	size_t left = dstsize;
5767c478bd9Sstevel@tonic-gate 	size_t l1;
5777c478bd9Sstevel@tonic-gate 	size_t l2 = strlen(src);
5787c478bd9Sstevel@tonic-gate 	size_t copied;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	while (left-- != 0 && *df != '\0')
5817c478bd9Sstevel@tonic-gate 		df++;
582ae115bc7Smrj 	/*LINTED: possible ptrdiff_t overflow*/
583ae115bc7Smrj 	l1 = (size_t)(df - dst);
5847c478bd9Sstevel@tonic-gate 	if (dstsize == l1)
5857c478bd9Sstevel@tonic-gate 		return (l1 + l2);
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2;
5887c478bd9Sstevel@tonic-gate 	bcopy(src, dst + l1, copied);
5897c478bd9Sstevel@tonic-gate 	dst[l1+copied] = '\0';
5907c478bd9Sstevel@tonic-gate 	return (l1 + l2);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate size_t
5947c478bd9Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len)
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	size_t slen = strlen(src);
5977c478bd9Sstevel@tonic-gate 	size_t copied;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	if (len == 0)
6007c478bd9Sstevel@tonic-gate 		return (slen);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	if (slen >= len)
6037c478bd9Sstevel@tonic-gate 		copied = len - 1;
6047c478bd9Sstevel@tonic-gate 	else
6057c478bd9Sstevel@tonic-gate 		copied = slen;
6067c478bd9Sstevel@tonic-gate 	bcopy(src, dst, copied);
6077c478bd9Sstevel@tonic-gate 	dst[copied] = '\0';
6087c478bd9Sstevel@tonic-gate 	return (slen);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate size_t
6127c478bd9Sstevel@tonic-gate strspn(const char *string, const char *charset)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate 	const char *p, *q;
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	for (q = string; *q != '\0'; ++q) {
6177c478bd9Sstevel@tonic-gate 		for (p = charset; *p != '\0' && *p != *q; ++p)
6187c478bd9Sstevel@tonic-gate 			;
6197c478bd9Sstevel@tonic-gate 		if (*p == '\0')
6207c478bd9Sstevel@tonic-gate 			break;
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
623ae115bc7Smrj 	/*LINTED: possible ptrdiff_t overflow*/
624ae115bc7Smrj 	return ((size_t)(q - string));
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
627da6c28aaSamw size_t
628da6c28aaSamw strcspn(const char *string, const char *charset)
629da6c28aaSamw {
630da6c28aaSamw 	const char *p, *q;
631da6c28aaSamw 
632da6c28aaSamw 	for (q = string; *q != '\0'; ++q) {
633da6c28aaSamw 		for (p = charset; *p != '\0' && *p != *q; ++p)
634da6c28aaSamw 			;
635da6c28aaSamw 		if (*p != '\0')
636da6c28aaSamw 			break;
637da6c28aaSamw 	}
638da6c28aaSamw 
639da6c28aaSamw 	/*LINTED E_PTRDIFF_OVERFLOW*/
640da6c28aaSamw 	return ((size_t)(q - string));
641da6c28aaSamw }
642da6c28aaSamw 
643da6c28aaSamw /*
644da6c28aaSamw  * strsep
645da6c28aaSamw  *
646da6c28aaSamw  * The strsep() function locates, in the string referenced by *stringp, the
647da6c28aaSamw  * first occurrence of any character in the string delim (or the terminating
648da6c28aaSamw  * `\0' character) and replaces it with a `\0'.  The location of the next
649da6c28aaSamw  * character after the delimiter character (or NULL, if the end of the
650da6c28aaSamw  * string was reached) is stored in *stringp.  The original value of
651da6c28aaSamw  * *stringp is returned.
652da6c28aaSamw  *
653da6c28aaSamw  * If *stringp is initially NULL, strsep() returns NULL.
654b811a51aSVladimir Kotal  *
655b811a51aSVladimir Kotal  * NOTE: This instance is left for in-kernel use. Libraries and programs
656b811a51aSVladimir Kotal  *       should use strsep from libc.
657da6c28aaSamw  */
658da6c28aaSamw char *
659da6c28aaSamw strsep(char **stringp, const char *delim)
660da6c28aaSamw {
661da6c28aaSamw 	char *s;
662da6c28aaSamw 	const char *spanp;
663da6c28aaSamw 	int c, sc;
664da6c28aaSamw 	char *tok;
665da6c28aaSamw 
666da6c28aaSamw 	if ((s = *stringp) == NULL)
667da6c28aaSamw 		return (NULL);
668da6c28aaSamw 
669da6c28aaSamw 	for (tok = s; ; ) {
670da6c28aaSamw 		c = *s++;
671da6c28aaSamw 		spanp = delim;
672da6c28aaSamw 		do {
673da6c28aaSamw 			if ((sc = *spanp++) == c) {
674da6c28aaSamw 				if (c == 0)
675da6c28aaSamw 					s = NULL;
676da6c28aaSamw 				else
677da6c28aaSamw 					s[-1] = 0;
678da6c28aaSamw 				*stringp = s;
679da6c28aaSamw 				return (tok);
680da6c28aaSamw 			}
681da6c28aaSamw 		} while (sc != 0);
682da6c28aaSamw 	}
683da6c28aaSamw 	/* NOTREACHED */
684da6c28aaSamw }
685da6c28aaSamw 
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate  * Unless mentioned otherwise, all of the routines below should be added to
6887c478bd9Sstevel@tonic-gate  * the Solaris DDI as necessary.  For now, only provide them to standalone.
6897c478bd9Sstevel@tonic-gate  */
6907c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
6917c478bd9Sstevel@tonic-gate char *
6927c478bd9Sstevel@tonic-gate strtok(char *string, const char *sepset)
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate 	char		*p, *q, *r;
6957c478bd9Sstevel@tonic-gate 	static char	*savept;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	/*
6987c478bd9Sstevel@tonic-gate 	 * Set `p' to our current location in the string.
6997c478bd9Sstevel@tonic-gate 	 */
7007c478bd9Sstevel@tonic-gate 	p = (string == NULL) ? savept : string;
7017c478bd9Sstevel@tonic-gate 	if (p == NULL)
7027c478bd9Sstevel@tonic-gate 		return (NULL);
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/*
7057c478bd9Sstevel@tonic-gate 	 * Skip leading separators; bail if no tokens remain.
7067c478bd9Sstevel@tonic-gate 	 */
7077c478bd9Sstevel@tonic-gate 	q = p + strspn(p, sepset);
7087c478bd9Sstevel@tonic-gate 	if (*q == '\0')
7097c478bd9Sstevel@tonic-gate 		return (NULL);
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	/*
7127c478bd9Sstevel@tonic-gate 	 * Mark the end of the token and set `savept' for the next iteration.
7137c478bd9Sstevel@tonic-gate 	 */
7147c478bd9Sstevel@tonic-gate 	if ((r = strpbrk(q, sepset)) == NULL)
7157c478bd9Sstevel@tonic-gate 		savept = NULL;
7167c478bd9Sstevel@tonic-gate 	else {
7177c478bd9Sstevel@tonic-gate 		*r = '\0';
7187c478bd9Sstevel@tonic-gate 		savept = ++r;
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	return (q);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /*
7257c478bd9Sstevel@tonic-gate  * The strlen() routine isn't shared with the kernel because it has its own
7267c478bd9Sstevel@tonic-gate  * hand-tuned assembly version.
7277c478bd9Sstevel@tonic-gate  */
7287c478bd9Sstevel@tonic-gate size_t
7297c478bd9Sstevel@tonic-gate strlen(const char *s)
7307c478bd9Sstevel@tonic-gate {
7317c478bd9Sstevel@tonic-gate 	size_t n = 0;
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	while (*s++)
7347c478bd9Sstevel@tonic-gate 		n++;
7357c478bd9Sstevel@tonic-gate 	return (n);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate #endif /* _BOOT || _KMDB */
7397c478bd9Sstevel@tonic-gate 
7407637daddSmyers /*
7417637daddSmyers  * Returns the number of non-NULL bytes in string argument,
7427637daddSmyers  * but not more than maxlen.  Does not look past str + maxlen.
7437637daddSmyers  */
7447637daddSmyers size_t
7457637daddSmyers strnlen(const char *s, size_t maxlen)
7467637daddSmyers {
7477637daddSmyers 	size_t n = 0;
7487637daddSmyers 
7497637daddSmyers 	while (maxlen != 0 && *s != 0) {
7507637daddSmyers 		s++;
7517637daddSmyers 		maxlen--;
7527637daddSmyers 		n++;
7537637daddSmyers 	}
7547637daddSmyers 
7557637daddSmyers 	return (n);
7567637daddSmyers }
7577637daddSmyers 
7587637daddSmyers 
7597c478bd9Sstevel@tonic-gate #ifdef _KERNEL
7607c478bd9Sstevel@tonic-gate /*
7617c478bd9Sstevel@tonic-gate  * Check for a valid C identifier:
7627c478bd9Sstevel@tonic-gate  *	a letter or underscore, followed by
7637c478bd9Sstevel@tonic-gate  *	zero or more letters, digits and underscores.
7647c478bd9Sstevel@tonic-gate  */
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate #define	IS_DIGIT(c)	((c) >= '0' && (c) <= '9')
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate #define	IS_ALPHA(c)	\
7697c478bd9Sstevel@tonic-gate 	(((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate int
7727c478bd9Sstevel@tonic-gate strident_valid(const char *id)
7737c478bd9Sstevel@tonic-gate {
7747c478bd9Sstevel@tonic-gate 	int c = *id++;
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	if (!IS_ALPHA(c) && c != '_')
7777c478bd9Sstevel@tonic-gate 		return (0);
7787c478bd9Sstevel@tonic-gate 	while ((c = *id++) != 0) {
7797c478bd9Sstevel@tonic-gate 		if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
7807c478bd9Sstevel@tonic-gate 			return (0);
7817c478bd9Sstevel@tonic-gate 	}
7827c478bd9Sstevel@tonic-gate 	return (1);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate  * Convert a string into a valid C identifier by replacing invalid
7877c478bd9Sstevel@tonic-gate  * characters with '_'.  Also makes sure the string is nul-terminated
7887c478bd9Sstevel@tonic-gate  * and takes up at most n bytes.
7897c478bd9Sstevel@tonic-gate  */
7907c478bd9Sstevel@tonic-gate void
7917c478bd9Sstevel@tonic-gate strident_canon(char *s, size_t n)
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate 	char c;
7947c478bd9Sstevel@tonic-gate 	char *end = s + n - 1;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	ASSERT(n > 0);
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	if ((c = *s) == 0)
7997c478bd9Sstevel@tonic-gate 		return;
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	if (!IS_ALPHA(c) && c != '_')
8027c478bd9Sstevel@tonic-gate 		*s = '_';
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	while (s < end && ((c = *(++s)) != 0)) {
8057c478bd9Sstevel@tonic-gate 		if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
8067c478bd9Sstevel@tonic-gate 			*s = '_';
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 	*s = 0;
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
812