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
5049fa28aSdr146992 * Common Development and Distribution License (the "License").
6049fa28aSdr146992 * 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
277c478bd9Sstevel@tonic-gate /*
283c5da275SMatthew Ahrens * Copyright (c) 2016 by Delphix. All rights reserved.
2929219719SEnyew Tan * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
303c5da275SMatthew Ahrens */
313c5da275SMatthew Ahrens
323c5da275SMatthew Ahrens /*
337c478bd9Sstevel@tonic-gate * Implementations of the functions described in vsnprintf(3C) and string(3C),
347c478bd9Sstevel@tonic-gate * for use by the kernel, the standalone, and kmdb. Unless otherwise specified,
357c478bd9Sstevel@tonic-gate * these functions match the section 3C manpages.
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
394870e0a7SRichard PALO #include <sys/null.h>
407c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
41*6c97897bSToomas Soome #include <sys/stdbool.h>
42ae115bc7Smrj
43ae115bc7Smrj #if defined(_KERNEL)
447c478bd9Sstevel@tonic-gate #include <sys/systm.h>
457c478bd9Sstevel@tonic-gate #include <sys/debug.h>
46ae115bc7Smrj #elif !defined(_BOOT)
47ae115bc7Smrj #include <string.h>
48ae115bc7Smrj #endif
49ae115bc7Smrj
50ae115bc7Smrj #include "memcpy.h"
51ae115bc7Smrj #include "string.h"
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate /*
54ae115bc7Smrj * We don't need these for x86 boot or kmdb.
557c478bd9Sstevel@tonic-gate */
56ae115bc7Smrj #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc))
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c)
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * Given a buffer 'buf' of size 'buflen', render as much of the string
627c478bd9Sstevel@tonic-gate * described by <fmt, args> as possible. The string will always be
637c478bd9Sstevel@tonic-gate * null-terminated, so the maximum string length is 'buflen - 1'.
647c478bd9Sstevel@tonic-gate * Returns the number of bytes that would be necessary to render the
65bbf21555SRichard Lowe * entire string, not including null terminator (just like vsnprintf(3C)).
667c478bd9Sstevel@tonic-gate * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1.
677c478bd9Sstevel@tonic-gate *
687c478bd9Sstevel@tonic-gate * There is no support for floating point, and the C locale is assumed.
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate size_t
vsnprintf(char * buf,size_t buflen,const char * fmt,va_list aargs)717c478bd9Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
727c478bd9Sstevel@tonic-gate {
73*6c97897bSToomas Soome uintmax_t ul, tmp;
747c478bd9Sstevel@tonic-gate char *bufp = buf; /* current buffer pointer */
7577889f88SYuri Pankov char c, pad;
7677889f88SYuri Pankov int width, base, sign, num;
77186507a7Smyers int prec, h_count, l_count, dot_count;
78*6c97897bSToomas Soome bool zflag, jflag;
79186507a7Smyers int pad_count, transfer_count, left_align;
807c478bd9Sstevel@tonic-gate char *digits, *sp, *bs;
817c478bd9Sstevel@tonic-gate char numbuf[65]; /* sufficient for a 64-bit binary value */
8277889f88SYuri Pankov int numwidth;
837c478bd9Sstevel@tonic-gate va_list args;
847c478bd9Sstevel@tonic-gate
85584b574aSToomas Soome ul = 0;
86584b574aSToomas Soome bs = NULL;
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate * Make a copy so that all our callers don't have to make a copy
897c478bd9Sstevel@tonic-gate */
907c478bd9Sstevel@tonic-gate va_copy(args, aargs);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate if ((ssize_t)buflen < 0)
937c478bd9Sstevel@tonic-gate buflen = 0;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate while ((c = *fmt++) != '\0') {
967c478bd9Sstevel@tonic-gate if (c != '%') {
977c478bd9Sstevel@tonic-gate ADDCHAR(c);
987c478bd9Sstevel@tonic-gate continue;
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
101*6c97897bSToomas Soome zflag = jflag = false;
10277889f88SYuri Pankov width = prec = numwidth = 0;
103186507a7Smyers left_align = base = sign = 0;
104186507a7Smyers h_count = l_count = dot_count = 0;
105186507a7Smyers pad = ' ';
106186507a7Smyers digits = "0123456789abcdef";
107186507a7Smyers next_fmt:
1087c478bd9Sstevel@tonic-gate if ((c = *fmt++) == '\0')
1097c478bd9Sstevel@tonic-gate break;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') {
1127c478bd9Sstevel@tonic-gate c += 'a' - 'A';
1137c478bd9Sstevel@tonic-gate digits = "0123456789ABCDEF";
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate switch (c) {
117186507a7Smyers case '-':
118186507a7Smyers left_align++;
119186507a7Smyers goto next_fmt;
120186507a7Smyers case '0':
121186507a7Smyers if (dot_count == 0)
122186507a7Smyers pad = '0';
123186507a7Smyers /*FALLTHROUGH*/
124186507a7Smyers case '1':
125186507a7Smyers case '2':
126186507a7Smyers case '3':
127186507a7Smyers case '4':
128186507a7Smyers case '5':
129186507a7Smyers case '6':
130186507a7Smyers case '7':
131186507a7Smyers case '8':
132186507a7Smyers case '9':
133186507a7Smyers num = 0;
134186507a7Smyers for (;;) {
135186507a7Smyers num = 10 * num + c - '0';
136186507a7Smyers c = *fmt;
137186507a7Smyers if (c < '0' || c > '9')
138186507a7Smyers break;
139186507a7Smyers else
140186507a7Smyers fmt++;
141186507a7Smyers }
142186507a7Smyers if (dot_count > 0)
143186507a7Smyers prec = num;
144186507a7Smyers else
145186507a7Smyers width = num;
146186507a7Smyers
147186507a7Smyers goto next_fmt;
148186507a7Smyers case '.':
149186507a7Smyers dot_count++;
150186507a7Smyers goto next_fmt;
151186507a7Smyers case '*':
152049fa28aSdr146992 if (dot_count > 0)
153049fa28aSdr146992 prec = (int)va_arg(args, int);
154049fa28aSdr146992 else
155186507a7Smyers width = (int)va_arg(args, int);
156186507a7Smyers goto next_fmt;
157186507a7Smyers case 'l':
158186507a7Smyers l_count++;
159186507a7Smyers goto next_fmt;
160186507a7Smyers case 'h':
161186507a7Smyers h_count++;
162186507a7Smyers goto next_fmt;
163*6c97897bSToomas Soome case 'j':
164*6c97897bSToomas Soome jflag = true;
165*6c97897bSToomas Soome goto next_fmt;
1667c478bd9Sstevel@tonic-gate case 'd':
1677c478bd9Sstevel@tonic-gate sign = 1;
1687c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
1697c478bd9Sstevel@tonic-gate case 'u':
1707c478bd9Sstevel@tonic-gate base = 10;
1717c478bd9Sstevel@tonic-gate break;
1727c478bd9Sstevel@tonic-gate case 'p':
173186507a7Smyers l_count = 1;
1747c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
1757c478bd9Sstevel@tonic-gate case 'x':
1767c478bd9Sstevel@tonic-gate base = 16;
1777c478bd9Sstevel@tonic-gate break;
1787c478bd9Sstevel@tonic-gate case 'o':
1797c478bd9Sstevel@tonic-gate base = 8;
1807c478bd9Sstevel@tonic-gate break;
1817c478bd9Sstevel@tonic-gate case 'b':
182186507a7Smyers l_count = 0;
1837c478bd9Sstevel@tonic-gate base = 1;
1847c478bd9Sstevel@tonic-gate break;
1857c478bd9Sstevel@tonic-gate case 'c':
186fc77c268Smyers c = (char)va_arg(args, int);
187186507a7Smyers ADDCHAR(c);
1887c478bd9Sstevel@tonic-gate break;
1897c478bd9Sstevel@tonic-gate case 's':
1907c478bd9Sstevel@tonic-gate sp = va_arg(args, char *);
191186507a7Smyers if (sp == NULL) {
1927c478bd9Sstevel@tonic-gate sp = "<null string>";
193186507a7Smyers /* avoid truncation */
194186507a7Smyers prec = strlen(sp);
195186507a7Smyers }
196186507a7Smyers /*
197186507a7Smyers * Handle simple case specially to avoid
198186507a7Smyers * performance hit of strlen()
199186507a7Smyers */
200186507a7Smyers if (prec == 0 && width == 0) {
2017c478bd9Sstevel@tonic-gate while ((c = *sp++) != 0)
2027c478bd9Sstevel@tonic-gate ADDCHAR(c);
2037c478bd9Sstevel@tonic-gate break;
204186507a7Smyers }
205186507a7Smyers if (prec > 0) {
2067637daddSmyers transfer_count = strnlen(sp, prec);
207186507a7Smyers /* widen field if too narrow */
208186507a7Smyers if (prec > width)
209186507a7Smyers width = prec;
2107637daddSmyers } else
2117637daddSmyers transfer_count = strlen(sp);
212186507a7Smyers if (width > transfer_count)
213186507a7Smyers pad_count = width - transfer_count;
214186507a7Smyers else
215186507a7Smyers pad_count = 0;
216186507a7Smyers while ((!left_align) && (pad_count-- > 0))
217186507a7Smyers ADDCHAR(' ');
218186507a7Smyers /* ADDCHAR() evaluates arg at most once */
219186507a7Smyers while (transfer_count-- > 0)
220186507a7Smyers ADDCHAR(*sp++);
221186507a7Smyers while ((left_align) && (pad_count-- > 0))
222186507a7Smyers ADDCHAR(' ');
223186507a7Smyers break;
224*6c97897bSToomas Soome case 'z':
225*6c97897bSToomas Soome zflag = true;
226*6c97897bSToomas Soome goto next_fmt;
2277c478bd9Sstevel@tonic-gate case '%':
2287c478bd9Sstevel@tonic-gate ADDCHAR('%');
2297c478bd9Sstevel@tonic-gate break;
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate if (base == 0)
2337c478bd9Sstevel@tonic-gate continue;
2347c478bd9Sstevel@tonic-gate
235*6c97897bSToomas Soome if (jflag) {
236186507a7Smyers if (sign)
237*6c97897bSToomas Soome ul = va_arg(args, intmax_t);
238186507a7Smyers else
239*6c97897bSToomas Soome ul = va_arg(args, uintmax_t);
240*6c97897bSToomas Soome } else if (zflag) {
241*6c97897bSToomas Soome if (sign)
242*6c97897bSToomas Soome ul = va_arg(args, ssize_t);
243*6c97897bSToomas Soome else
244*6c97897bSToomas Soome ul = va_arg(args, size_t);
245*6c97897bSToomas Soome } else if (h_count == 0 && l_count == 0) {
246*6c97897bSToomas Soome if (sign)
247*6c97897bSToomas Soome ul = va_arg(args, int);
248*6c97897bSToomas Soome else
249*6c97897bSToomas Soome ul = va_arg(args, unsigned int);
2503df2e8b2SRobert Mustacchi } else if (l_count > 1) {
251186507a7Smyers if (sign)
252*6c97897bSToomas Soome ul = va_arg(args, int64_t);
253186507a7Smyers else
254*6c97897bSToomas Soome ul = va_arg(args, uint64_t);
2553df2e8b2SRobert Mustacchi } else if (l_count > 0) {
256186507a7Smyers if (sign)
257*6c97897bSToomas Soome ul = va_arg(args, long);
2587c478bd9Sstevel@tonic-gate else
259*6c97897bSToomas Soome ul = va_arg(args, unsigned long);
2603df2e8b2SRobert Mustacchi } else if (h_count > 1) {
261186507a7Smyers if (sign)
262*6c97897bSToomas Soome ul = (signed char)va_arg(args, int);
263186507a7Smyers else
264*6c97897bSToomas Soome ul = (unsigned char)va_arg(args, int);
2653df2e8b2SRobert Mustacchi } else if (h_count > 0) {
266186507a7Smyers if (sign)
267*6c97897bSToomas Soome ul = (short)va_arg(args, int);
268186507a7Smyers else
269*6c97897bSToomas Soome ul = (unsigned short)va_arg(args, int);
2703df2e8b2SRobert Mustacchi }
2717c478bd9Sstevel@tonic-gate
272*6c97897bSToomas Soome if (sign && (intmax_t)ul < 0)
2737c478bd9Sstevel@tonic-gate ul = -ul;
2747c478bd9Sstevel@tonic-gate else
2757c478bd9Sstevel@tonic-gate sign = 0;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate if (c == 'b') {
2787c478bd9Sstevel@tonic-gate bs = va_arg(args, char *);
2797c478bd9Sstevel@tonic-gate base = *bs++;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate
28277889f88SYuri Pankov /*
28377889f88SYuri Pankov * Fill in the number string buffer and calculate the
28477889f88SYuri Pankov * number string length.
28577889f88SYuri Pankov */
2867c478bd9Sstevel@tonic-gate tmp = ul;
2877c478bd9Sstevel@tonic-gate sp = numbuf;
2887c478bd9Sstevel@tonic-gate do {
2897c478bd9Sstevel@tonic-gate *sp++ = digits[tmp % base];
29077889f88SYuri Pankov numwidth++;
2917c478bd9Sstevel@tonic-gate } while ((tmp /= base) != 0);
2927c478bd9Sstevel@tonic-gate
29377889f88SYuri Pankov /*
29477889f88SYuri Pankov * Reduce the total field width by precision or the number
29577889f88SYuri Pankov * string length depending on which one is bigger, and sign.
29677889f88SYuri Pankov */
29777889f88SYuri Pankov if (prec >= numwidth)
29877889f88SYuri Pankov width -= prec;
29977889f88SYuri Pankov else
30077889f88SYuri Pankov width -= numwidth;
30177889f88SYuri Pankov width -= sign;
30277889f88SYuri Pankov
30377889f88SYuri Pankov /* Add the sign if width is '0'-padded */
30477889f88SYuri Pankov if (sign && pad == '0')
30577889f88SYuri Pankov ADDCHAR('-');
30677889f88SYuri Pankov
30777889f88SYuri Pankov /* If not left-aligned, add the width padding */
30877889f88SYuri Pankov if (!left_align) {
30977889f88SYuri Pankov while (width-- > 0)
31077889f88SYuri Pankov ADDCHAR(pad);
31177889f88SYuri Pankov }
31277889f88SYuri Pankov
31377889f88SYuri Pankov /* Add the sign if width is NOT '0'-padded */
31477889f88SYuri Pankov if (sign && pad != '0')
31577889f88SYuri Pankov ADDCHAR('-');
31677889f88SYuri Pankov
31777889f88SYuri Pankov /* Add the precision '0'-padding */
31877889f88SYuri Pankov while (prec-- > numwidth)
31977889f88SYuri Pankov ADDCHAR('0');
32077889f88SYuri Pankov
32177889f88SYuri Pankov /* Print out the number */
3227c478bd9Sstevel@tonic-gate while (sp > numbuf) {
3237c478bd9Sstevel@tonic-gate sp--;
3247c478bd9Sstevel@tonic-gate ADDCHAR(*sp);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
32777889f88SYuri Pankov /* Add left-alignment padding */
32877889f88SYuri Pankov while (width-- > 0)
329237b1f31SPatrick Mooney ADDCHAR(' ');
330237b1f31SPatrick Mooney
3317c478bd9Sstevel@tonic-gate if (c == 'b' && ul != 0) {
3327c478bd9Sstevel@tonic-gate int any = 0;
3337c478bd9Sstevel@tonic-gate c = *bs++;
3347c478bd9Sstevel@tonic-gate while (c != 0) {
3357c478bd9Sstevel@tonic-gate if (ul & (1 << (c - 1))) {
3367c478bd9Sstevel@tonic-gate if (any++ == 0)
3377c478bd9Sstevel@tonic-gate ADDCHAR('<');
338c3b39789SHans Rosenfeld while ((c = *bs++) > 32)
3397c478bd9Sstevel@tonic-gate ADDCHAR(c);
3407c478bd9Sstevel@tonic-gate ADDCHAR(',');
3417c478bd9Sstevel@tonic-gate } else {
342c3b39789SHans Rosenfeld while ((c = *bs++) > 32)
3437c478bd9Sstevel@tonic-gate continue;
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate if (any) {
3477c478bd9Sstevel@tonic-gate bufp--;
3487c478bd9Sstevel@tonic-gate ADDCHAR('>');
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate if (bufp - buf < buflen)
3537c478bd9Sstevel@tonic-gate bufp[0] = c;
3547c478bd9Sstevel@tonic-gate else if (buflen != 0)
3557c478bd9Sstevel@tonic-gate buf[buflen - 1] = c;
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate va_end(args);
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate return (bufp - buf);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
3623c5da275SMatthew Ahrens /*PRINTFLIKE3*/
3637c478bd9Sstevel@tonic-gate size_t
snprintf(char * buf,size_t buflen,const char * fmt,...)3647c478bd9Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate va_list args;
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate va_start(args, fmt);
3697c478bd9Sstevel@tonic-gate buflen = vsnprintf(buf, buflen, fmt, args);
3707c478bd9Sstevel@tonic-gate va_end(args);
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate return (buflen);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
375ae115bc7Smrj #if defined(_BOOT) && defined(__sparc)
3767c478bd9Sstevel@tonic-gate /*
3777c478bd9Sstevel@tonic-gate * The sprintf() and vsprintf() routines aren't shared with the kernel because
3787c478bd9Sstevel@tonic-gate * the DDI mandates that they return the buffer rather than its length.
3797c478bd9Sstevel@tonic-gate */
3807c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
3817c478bd9Sstevel@tonic-gate int
sprintf(char * buf,const char * fmt,...)3827c478bd9Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate va_list args;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate va_start(args, fmt);
3877c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args);
3887c478bd9Sstevel@tonic-gate va_end(args);
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate return (strlen(buf));
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate int
vsprintf(char * buf,const char * fmt,va_list args)3947c478bd9Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args);
3977c478bd9Sstevel@tonic-gate return (strlen(buf));
3987c478bd9Sstevel@tonic-gate }
399ae115bc7Smrj #endif /* _BOOT && __sparc */
4007c478bd9Sstevel@tonic-gate
401ae115bc7Smrj #endif /* !_KMDB && (!_BOOT || __sparc) */
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate char *
strcat(char * s1,const char * s2)4047c478bd9Sstevel@tonic-gate strcat(char *s1, const char *s2)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate char *os1 = s1;
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate while (*s1++ != '\0')
4097c478bd9Sstevel@tonic-gate ;
4107c478bd9Sstevel@tonic-gate s1--;
4117c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0')
4127c478bd9Sstevel@tonic-gate ;
4137c478bd9Sstevel@tonic-gate return (os1);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate char *
strchr(const char * sp,int c)4177c478bd9Sstevel@tonic-gate strchr(const char *sp, int c)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate do {
4207c478bd9Sstevel@tonic-gate if (*sp == (char)c)
4217c478bd9Sstevel@tonic-gate return ((char *)sp);
4227c478bd9Sstevel@tonic-gate } while (*sp++);
4237c478bd9Sstevel@tonic-gate return (NULL);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate int
strcmp(const char * s1,const char * s2)4277c478bd9Sstevel@tonic-gate strcmp(const char *s1, const char *s2)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate while (*s1 == *s2++)
4307c478bd9Sstevel@tonic-gate if (*s1++ == '\0')
4317c478bd9Sstevel@tonic-gate return (0);
4327c478bd9Sstevel@tonic-gate return (*(unsigned char *)s1 - *(unsigned char *)--s2);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate int
strncmp(const char * s1,const char * s2,size_t n)4367c478bd9Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate if (s1 == s2)
4397c478bd9Sstevel@tonic-gate return (0);
4407c478bd9Sstevel@tonic-gate n++;
4417c478bd9Sstevel@tonic-gate while (--n != 0 && *s1 == *s2++)
4427c478bd9Sstevel@tonic-gate if (*s1++ == '\0')
4437c478bd9Sstevel@tonic-gate return (0);
4447c478bd9Sstevel@tonic-gate return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2);
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate static const char charmap[] = {
4487c478bd9Sstevel@tonic-gate '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
4497c478bd9Sstevel@tonic-gate '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
4507c478bd9Sstevel@tonic-gate '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
4517c478bd9Sstevel@tonic-gate '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
4527c478bd9Sstevel@tonic-gate '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
4537c478bd9Sstevel@tonic-gate '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
4547c478bd9Sstevel@tonic-gate '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
4557c478bd9Sstevel@tonic-gate '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
4567c478bd9Sstevel@tonic-gate '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4577c478bd9Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4587c478bd9Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4597c478bd9Sstevel@tonic-gate '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
4607c478bd9Sstevel@tonic-gate '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
4617c478bd9Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
4627c478bd9Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
4637c478bd9Sstevel@tonic-gate '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
4647c478bd9Sstevel@tonic-gate '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
4657c478bd9Sstevel@tonic-gate '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
4667c478bd9Sstevel@tonic-gate '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
4677c478bd9Sstevel@tonic-gate '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
4687c478bd9Sstevel@tonic-gate '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
4697c478bd9Sstevel@tonic-gate '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
4707c478bd9Sstevel@tonic-gate '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
4717c478bd9Sstevel@tonic-gate '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
4727c478bd9Sstevel@tonic-gate '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
4737c478bd9Sstevel@tonic-gate '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
4747c478bd9Sstevel@tonic-gate '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
4757c478bd9Sstevel@tonic-gate '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
4767c478bd9Sstevel@tonic-gate '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
4777c478bd9Sstevel@tonic-gate '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
4787c478bd9Sstevel@tonic-gate '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
4797c478bd9Sstevel@tonic-gate '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
4807c478bd9Sstevel@tonic-gate };
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate int
strcasecmp(const char * s1,const char * s2)4837c478bd9Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap;
4867c478bd9Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1;
4877c478bd9Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2;
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate while (cm[*us1] == cm[*us2++])
4907c478bd9Sstevel@tonic-gate if (*us1++ == '\0')
4917c478bd9Sstevel@tonic-gate return (0);
4927c478bd9Sstevel@tonic-gate return (cm[*us1] - cm[*(us2 - 1)]);
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate int
strncasecmp(const char * s1,const char * s2,size_t n)4967c478bd9Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n)
4977c478bd9Sstevel@tonic-gate {
4987c478bd9Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap;
4997c478bd9Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1;
5007c478bd9Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate while (n != 0 && cm[*us1] == cm[*us2++]) {
5037c478bd9Sstevel@tonic-gate if (*us1++ == '\0')
5047c478bd9Sstevel@tonic-gate return (0);
5057c478bd9Sstevel@tonic-gate n--;
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate char *
strcpy(char * s1,const char * s2)5117c478bd9Sstevel@tonic-gate strcpy(char *s1, const char *s2)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate char *os1 = s1;
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0')
5167c478bd9Sstevel@tonic-gate ;
5177c478bd9Sstevel@tonic-gate return (os1);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate char *
strncpy(char * s1,const char * s2,size_t n)5217c478bd9Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n)
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate char *os1 = s1;
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate n++;
5267c478bd9Sstevel@tonic-gate while (--n != 0 && (*s1++ = *s2++) != '\0')
5277c478bd9Sstevel@tonic-gate ;
5287c478bd9Sstevel@tonic-gate if (n != 0)
5297c478bd9Sstevel@tonic-gate while (--n != 0)
5307c478bd9Sstevel@tonic-gate *s1++ = '\0';
5317c478bd9Sstevel@tonic-gate return (os1);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate char *
strrchr(const char * sp,int c)5357c478bd9Sstevel@tonic-gate strrchr(const char *sp, int c)
5367c478bd9Sstevel@tonic-gate {
5377c478bd9Sstevel@tonic-gate char *r = NULL;
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate do {
5407c478bd9Sstevel@tonic-gate if (*sp == (char)c)
5417c478bd9Sstevel@tonic-gate r = (char *)sp;
5427c478bd9Sstevel@tonic-gate } while (*sp++);
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate return (r);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate char *
strstr(const char * as1,const char * as2)5487c478bd9Sstevel@tonic-gate strstr(const char *as1, const char *as2)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate const char *s1, *s2;
5517c478bd9Sstevel@tonic-gate const char *tptr;
5527c478bd9Sstevel@tonic-gate char c;
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate s1 = as1;
5557c478bd9Sstevel@tonic-gate s2 = as2;
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0')
5587c478bd9Sstevel@tonic-gate return ((char *)s1);
5597c478bd9Sstevel@tonic-gate c = *s2;
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate while (*s1)
5627c478bd9Sstevel@tonic-gate if (*s1++ == c) {
5637c478bd9Sstevel@tonic-gate tptr = s1;
5647c478bd9Sstevel@tonic-gate while ((c = *++s2) == *s1++ && c)
5657c478bd9Sstevel@tonic-gate ;
5667c478bd9Sstevel@tonic-gate if (c == 0)
5677c478bd9Sstevel@tonic-gate return ((char *)tptr - 1);
5687c478bd9Sstevel@tonic-gate s1 = tptr;
5697c478bd9Sstevel@tonic-gate s2 = as2;
5707c478bd9Sstevel@tonic-gate c = *s2;
5717c478bd9Sstevel@tonic-gate }
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate return (NULL);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate char *
strpbrk(const char * string,const char * brkset)5777c478bd9Sstevel@tonic-gate strpbrk(const char *string, const char *brkset)
5787c478bd9Sstevel@tonic-gate {
5797c478bd9Sstevel@tonic-gate const char *p;
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate do {
5827c478bd9Sstevel@tonic-gate for (p = brkset; *p != '\0' && *p != *string; ++p)
5837c478bd9Sstevel@tonic-gate ;
5847c478bd9Sstevel@tonic-gate if (*p != '\0')
5857c478bd9Sstevel@tonic-gate return ((char *)string);
5867c478bd9Sstevel@tonic-gate } while (*string++);
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate return (NULL);
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate char *
strncat(char * s1,const char * s2,size_t n)5927c478bd9Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n)
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate char *os1 = s1;
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate n++;
5977c478bd9Sstevel@tonic-gate while (*s1++ != '\0')
5987c478bd9Sstevel@tonic-gate ;
5997c478bd9Sstevel@tonic-gate --s1;
6007c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') {
6017c478bd9Sstevel@tonic-gate if (--n == 0) {
6027c478bd9Sstevel@tonic-gate s1[-1] = '\0';
6037c478bd9Sstevel@tonic-gate break;
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate return (os1);
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
6107c478bd9Sstevel@tonic-gate #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n))
6117c478bd9Sstevel@tonic-gate #endif
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate size_t
strlcat(char * dst,const char * src,size_t dstsize)6147c478bd9Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize)
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate char *df = dst;
6177c478bd9Sstevel@tonic-gate size_t left = dstsize;
6187c478bd9Sstevel@tonic-gate size_t l1;
6197c478bd9Sstevel@tonic-gate size_t l2 = strlen(src);
6207c478bd9Sstevel@tonic-gate size_t copied;
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate while (left-- != 0 && *df != '\0')
6237c478bd9Sstevel@tonic-gate df++;
624ae115bc7Smrj /*LINTED: possible ptrdiff_t overflow*/
625ae115bc7Smrj l1 = (size_t)(df - dst);
6267c478bd9Sstevel@tonic-gate if (dstsize == l1)
6277c478bd9Sstevel@tonic-gate return (l1 + l2);
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2;
6307c478bd9Sstevel@tonic-gate bcopy(src, dst + l1, copied);
6317c478bd9Sstevel@tonic-gate dst[l1+copied] = '\0';
6327c478bd9Sstevel@tonic-gate return (l1 + l2);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate size_t
strlcpy(char * dst,const char * src,size_t len)6367c478bd9Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate size_t slen = strlen(src);
6397c478bd9Sstevel@tonic-gate size_t copied;
6407c478bd9Sstevel@tonic-gate
6417c478bd9Sstevel@tonic-gate if (len == 0)
6427c478bd9Sstevel@tonic-gate return (slen);
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate if (slen >= len)
6457c478bd9Sstevel@tonic-gate copied = len - 1;
6467c478bd9Sstevel@tonic-gate else
6477c478bd9Sstevel@tonic-gate copied = slen;
6487c478bd9Sstevel@tonic-gate bcopy(src, dst, copied);
6497c478bd9Sstevel@tonic-gate dst[copied] = '\0';
6507c478bd9Sstevel@tonic-gate return (slen);
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate size_t
strspn(const char * string,const char * charset)6547c478bd9Sstevel@tonic-gate strspn(const char *string, const char *charset)
6557c478bd9Sstevel@tonic-gate {
6567c478bd9Sstevel@tonic-gate const char *p, *q;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate for (q = string; *q != '\0'; ++q) {
6597c478bd9Sstevel@tonic-gate for (p = charset; *p != '\0' && *p != *q; ++p)
6607c478bd9Sstevel@tonic-gate ;
6617c478bd9Sstevel@tonic-gate if (*p == '\0')
6627c478bd9Sstevel@tonic-gate break;
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
665ae115bc7Smrj /*LINTED: possible ptrdiff_t overflow*/
666ae115bc7Smrj return ((size_t)(q - string));
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate
669da6c28aaSamw size_t
strcspn(const char * string,const char * charset)670da6c28aaSamw strcspn(const char *string, const char *charset)
671da6c28aaSamw {
672da6c28aaSamw const char *p, *q;
673da6c28aaSamw
674da6c28aaSamw for (q = string; *q != '\0'; ++q) {
675da6c28aaSamw for (p = charset; *p != '\0' && *p != *q; ++p)
676da6c28aaSamw ;
677da6c28aaSamw if (*p != '\0')
678da6c28aaSamw break;
679da6c28aaSamw }
680da6c28aaSamw
681da6c28aaSamw /*LINTED E_PTRDIFF_OVERFLOW*/
682da6c28aaSamw return ((size_t)(q - string));
683da6c28aaSamw }
684da6c28aaSamw
685da6c28aaSamw /*
686da6c28aaSamw * strsep
687da6c28aaSamw *
688da6c28aaSamw * The strsep() function locates, in the string referenced by *stringp, the
689da6c28aaSamw * first occurrence of any character in the string delim (or the terminating
690da6c28aaSamw * `\0' character) and replaces it with a `\0'. The location of the next
691da6c28aaSamw * character after the delimiter character (or NULL, if the end of the
692da6c28aaSamw * string was reached) is stored in *stringp. The original value of
693da6c28aaSamw * *stringp is returned.
694da6c28aaSamw *
695da6c28aaSamw * If *stringp is initially NULL, strsep() returns NULL.
696b811a51aSVladimir Kotal *
697b811a51aSVladimir Kotal * NOTE: This instance is left for in-kernel use. Libraries and programs
698b811a51aSVladimir Kotal * should use strsep from libc.
699da6c28aaSamw */
700da6c28aaSamw char *
strsep(char ** stringp,const char * delim)701da6c28aaSamw strsep(char **stringp, const char *delim)
702da6c28aaSamw {
703da6c28aaSamw char *s;
704da6c28aaSamw const char *spanp;
705da6c28aaSamw int c, sc;
706da6c28aaSamw char *tok;
707da6c28aaSamw
708da6c28aaSamw if ((s = *stringp) == NULL)
709da6c28aaSamw return (NULL);
710da6c28aaSamw
711da6c28aaSamw for (tok = s; ; ) {
712da6c28aaSamw c = *s++;
713da6c28aaSamw spanp = delim;
714da6c28aaSamw do {
715da6c28aaSamw if ((sc = *spanp++) == c) {
716da6c28aaSamw if (c == 0)
717da6c28aaSamw s = NULL;
718da6c28aaSamw else
719da6c28aaSamw s[-1] = 0;
720da6c28aaSamw *stringp = s;
721da6c28aaSamw return (tok);
722da6c28aaSamw }
723da6c28aaSamw } while (sc != 0);
724da6c28aaSamw }
725da6c28aaSamw /* NOTREACHED */
726da6c28aaSamw }
727da6c28aaSamw
7287c478bd9Sstevel@tonic-gate /*
72929219719SEnyew Tan * strtok_r
73029219719SEnyew Tan *
73129219719SEnyew Tan * uses strpbrk and strspn to break string into tokens on
73229219719SEnyew Tan * sequentially subsequent calls. returns NULL when no
73329219719SEnyew Tan * non-separator characters remain.
73429219719SEnyew Tan * `subsequent' calls are calls with first argument NULL.
73529219719SEnyew Tan */
73629219719SEnyew Tan char *
strtok_r(char * string,const char * sepset,char ** lasts)73729219719SEnyew Tan strtok_r(char *string, const char *sepset, char **lasts)
73829219719SEnyew Tan {
73929219719SEnyew Tan char *q, *r;
74029219719SEnyew Tan
74129219719SEnyew Tan /* first or subsequent call */
74229219719SEnyew Tan if (string == NULL)
74329219719SEnyew Tan string = *lasts;
74429219719SEnyew Tan
74529219719SEnyew Tan if (string == NULL) /* return if no tokens remaining */
74629219719SEnyew Tan return (NULL);
74729219719SEnyew Tan
74829219719SEnyew Tan q = string + strspn(string, sepset); /* skip leading separators */
74929219719SEnyew Tan
75029219719SEnyew Tan if (*q == '\0') /* return if no tokens remaining */
75129219719SEnyew Tan return (NULL);
75229219719SEnyew Tan
75329219719SEnyew Tan if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */
75429219719SEnyew Tan *lasts = NULL; /* indicate this is last token */
75529219719SEnyew Tan } else {
75629219719SEnyew Tan *r = '\0';
75729219719SEnyew Tan *lasts = r + 1;
75829219719SEnyew Tan }
75929219719SEnyew Tan return (q);
76029219719SEnyew Tan }
76129219719SEnyew Tan
76229219719SEnyew Tan /*
7637c478bd9Sstevel@tonic-gate * Unless mentioned otherwise, all of the routines below should be added to
7647c478bd9Sstevel@tonic-gate * the Solaris DDI as necessary. For now, only provide them to standalone.
7657c478bd9Sstevel@tonic-gate */
7667c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB)
7677c478bd9Sstevel@tonic-gate char *
strtok(char * string,const char * sepset)7687c478bd9Sstevel@tonic-gate strtok(char *string, const char *sepset)
7697c478bd9Sstevel@tonic-gate {
7707c478bd9Sstevel@tonic-gate char *p, *q, *r;
7717c478bd9Sstevel@tonic-gate static char *savept;
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate /*
7747c478bd9Sstevel@tonic-gate * Set `p' to our current location in the string.
7757c478bd9Sstevel@tonic-gate */
7767c478bd9Sstevel@tonic-gate p = (string == NULL) ? savept : string;
7777c478bd9Sstevel@tonic-gate if (p == NULL)
7787c478bd9Sstevel@tonic-gate return (NULL);
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate /*
7817c478bd9Sstevel@tonic-gate * Skip leading separators; bail if no tokens remain.
7827c478bd9Sstevel@tonic-gate */
7837c478bd9Sstevel@tonic-gate q = p + strspn(p, sepset);
7847c478bd9Sstevel@tonic-gate if (*q == '\0')
7857c478bd9Sstevel@tonic-gate return (NULL);
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate * Mark the end of the token and set `savept' for the next iteration.
7897c478bd9Sstevel@tonic-gate */
7907c478bd9Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL)
7917c478bd9Sstevel@tonic-gate savept = NULL;
7927c478bd9Sstevel@tonic-gate else {
7937c478bd9Sstevel@tonic-gate *r = '\0';
7947c478bd9Sstevel@tonic-gate savept = ++r;
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate return (q);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate * The strlen() routine isn't shared with the kernel because it has its own
8027c478bd9Sstevel@tonic-gate * hand-tuned assembly version.
8037c478bd9Sstevel@tonic-gate */
8047c478bd9Sstevel@tonic-gate size_t
strlen(const char * s)8057c478bd9Sstevel@tonic-gate strlen(const char *s)
8067c478bd9Sstevel@tonic-gate {
8077c478bd9Sstevel@tonic-gate size_t n = 0;
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate while (*s++)
8107c478bd9Sstevel@tonic-gate n++;
8117c478bd9Sstevel@tonic-gate return (n);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate #endif /* _BOOT || _KMDB */
8157c478bd9Sstevel@tonic-gate
8167637daddSmyers /*
8177637daddSmyers * Returns the number of non-NULL bytes in string argument,
8187637daddSmyers * but not more than maxlen. Does not look past str + maxlen.
8197637daddSmyers */
8207637daddSmyers size_t
strnlen(const char * s,size_t maxlen)8217637daddSmyers strnlen(const char *s, size_t maxlen)
8227637daddSmyers {
8237637daddSmyers size_t n = 0;
8247637daddSmyers
8257637daddSmyers while (maxlen != 0 && *s != 0) {
8267637daddSmyers s++;
8277637daddSmyers maxlen--;
8287637daddSmyers n++;
8297637daddSmyers }
8307637daddSmyers
8317637daddSmyers return (n);
8327637daddSmyers }
8337637daddSmyers
8347637daddSmyers
8357c478bd9Sstevel@tonic-gate #ifdef _KERNEL
8367c478bd9Sstevel@tonic-gate /*
8377c478bd9Sstevel@tonic-gate * Check for a valid C identifier:
8387c478bd9Sstevel@tonic-gate * a letter or underscore, followed by
8397c478bd9Sstevel@tonic-gate * zero or more letters, digits and underscores.
8407c478bd9Sstevel@tonic-gate */
8417c478bd9Sstevel@tonic-gate
8427c478bd9Sstevel@tonic-gate #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate #define IS_ALPHA(c) \
8457c478bd9Sstevel@tonic-gate (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate int
strident_valid(const char * id)8487c478bd9Sstevel@tonic-gate strident_valid(const char *id)
8497c478bd9Sstevel@tonic-gate {
8507c478bd9Sstevel@tonic-gate int c = *id++;
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_')
8537c478bd9Sstevel@tonic-gate return (0);
8547c478bd9Sstevel@tonic-gate while ((c = *id++) != 0) {
8557c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
8567c478bd9Sstevel@tonic-gate return (0);
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate return (1);
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate * Convert a string into a valid C identifier by replacing invalid
8637c478bd9Sstevel@tonic-gate * characters with '_'. Also makes sure the string is nul-terminated
8647c478bd9Sstevel@tonic-gate * and takes up at most n bytes.
8657c478bd9Sstevel@tonic-gate */
8667c478bd9Sstevel@tonic-gate void
strident_canon(char * s,size_t n)8677c478bd9Sstevel@tonic-gate strident_canon(char *s, size_t n)
8687c478bd9Sstevel@tonic-gate {
8697c478bd9Sstevel@tonic-gate char c;
8707c478bd9Sstevel@tonic-gate char *end = s + n - 1;
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate ASSERT(n > 0);
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate if ((c = *s) == 0)
8757c478bd9Sstevel@tonic-gate return;
8767c478bd9Sstevel@tonic-gate
8777c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_')
8787c478bd9Sstevel@tonic-gate *s = '_';
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate while (s < end && ((c = *(++s)) != 0)) {
8817c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
8827c478bd9Sstevel@tonic-gate *s = '_';
8837c478bd9Sstevel@tonic-gate }
8847c478bd9Sstevel@tonic-gate *s = 0;
8857c478bd9Sstevel@tonic-gate }
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
888