4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2014 Joyent, Inc. All rights reserved.
28 * Copyright (c) 2016 by Delphix. All rights reserved.
32 * Implementations of the functions described in vsnprintf(3C) and string(3C),
33 * for use by the kernel, the standalone, and kmdb. Unless otherwise specified,
34 * these functions match the section 3C manpages.
37 #include <sys/types.h>
39 #include <sys/varargs.h>
42 #include <sys/systm.h>
43 #include <sys/debug.h>
52 * We don't need these for x86 boot or kmdb.
54 #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc))
56 #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c)
59 * Given a buffer 'buf' of size 'buflen', render as much of the string
60 * described by <fmt, args> as possible. The string will always be
61 * null-terminated, so the maximum string length is 'buflen - 1'.
62 * Returns the number of bytes that would be necessary to render the
63 * entire string, not including null terminator (just like vsnprintf(3S)).
64 * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1.
66 * There is no support for floating point, and the C locale is assumed.
69 vsnprintf(char *buf
, size_t buflen
, const char *fmt
, va_list aargs
)
72 char *bufp
= buf
; /* current buffer pointer */
73 int pad
, width
, base
, sign
, c
, num
;
74 int prec
, h_count
, l_count
, dot_count
;
75 int pad_count
, transfer_count
, left_align
;
76 char *digits
, *sp
, *bs
;
77 char numbuf
[65]; /* sufficient for a 64-bit binary value */
81 * Make a copy so that all our callers don't have to make a copy
85 if ((ssize_t
)buflen
< 0)
88 while ((c
= *fmt
++) != '\0') {
95 left_align
= base
= sign
= 0;
96 h_count
= l_count
= dot_count
= 0;
98 digits
= "0123456789abcdef";
100 if ((c
= *fmt
++) == '\0')
103 if (c
>= 'A' && c
<= 'Z') {
105 digits
= "0123456789ABCDEF";
127 num
= 10 * num
+ c
- '0';
129 if (c
< '0' || c
> '9')
145 prec
= (int)va_arg(args
, int);
147 width
= (int)va_arg(args
, int);
175 c
= (char)va_arg(args
, int);
179 sp
= va_arg(args
, char *);
181 sp
= "<null string>";
182 /* avoid truncation */
186 * Handle simple case specially to avoid
187 * performance hit of strlen()
189 if (prec
== 0 && width
== 0) {
190 while ((c
= *sp
++) != 0)
195 transfer_count
= strnlen(sp
, prec
);
196 /* widen field if too narrow */
200 transfer_count
= strlen(sp
);
201 if (width
> transfer_count
)
202 pad_count
= width
- transfer_count
;
205 while ((!left_align
) && (pad_count
-- > 0))
207 /* ADDCHAR() evaluates arg at most once */
208 while (transfer_count
-- > 0)
210 while ((left_align
) && (pad_count
-- > 0))
221 if (h_count
== 0 && l_count
== 0)
223 ul
= (int64_t)va_arg(args
, int);
225 ul
= (int64_t)va_arg(args
, unsigned int);
226 else if (l_count
> 1)
228 ul
= (int64_t)va_arg(args
, int64_t);
230 ul
= (int64_t)va_arg(args
, uint64_t);
231 else if (l_count
> 0)
233 ul
= (int64_t)va_arg(args
, long);
235 ul
= (int64_t)va_arg(args
, unsigned long);
236 else if (h_count
> 1)
238 ul
= (int64_t)((char)va_arg(args
, int));
240 ul
= (int64_t)((unsigned char)va_arg(args
,
242 else if (h_count
> 0)
244 ul
= (int64_t)((short)va_arg(args
, int));
246 ul
= (int64_t)((unsigned short)va_arg(args
,
249 if (sign
&& (int64_t)ul
< 0)
255 bs
= va_arg(args
, char *);
259 /* avoid repeated division if width is 0 */
264 } while ((tmp
/= base
) != 0);
267 if (sign
&& pad
== '0')
269 while ((!left_align
) && (width
-- > sign
))
271 if (sign
&& pad
== ' ')
277 *sp
++ = digits
[tmp
% base
];
278 } while ((tmp
/= base
) != 0);
280 while (sp
> numbuf
) {
285 /* add left-alignment padding */
286 while (width
-- > sign
)
289 if (c
== 'b' && ul
!= 0) {
293 if (ul
& (1 << (c
- 1))) {
296 while ((c
= *bs
++) >= 32)
300 while ((c
= *bs
++) >= 32)
310 if (bufp
- buf
< buflen
)
312 else if (buflen
!= 0)
322 snprintf(char *buf
, size_t buflen
, const char *fmt
, ...)
327 buflen
= vsnprintf(buf
, buflen
, fmt
, args
);
333 #if defined(_BOOT) && defined(__sparc)
335 * The sprintf() and vsprintf() routines aren't shared with the kernel because
336 * the DDI mandates that they return the buffer rather than its length.
340 sprintf(char *buf
, const char *fmt
, ...)
345 (void) vsnprintf(buf
, INT_MAX
, fmt
, args
);
348 return (strlen(buf
));
352 vsprintf(char *buf
, const char *fmt
, va_list args
)
354 (void) vsnprintf(buf
, INT_MAX
, fmt
, args
);
355 return (strlen(buf
));
357 #endif /* _BOOT && __sparc */
359 #endif /* !_KMDB && (!_BOOT || __sparc) */
362 strcat(char *s1
, const char *s2
)
366 while (*s1
++ != '\0')
369 while ((*s1
++ = *s2
++) != '\0')
375 strchr(const char *sp
, int c
)
385 strcmp(const char *s1
, const char *s2
)
390 return (*(unsigned char *)s1
- *(unsigned char *)--s2
);
394 strncmp(const char *s1
, const char *s2
, size_t n
)
399 while (--n
!= 0 && *s1
== *s2
++)
402 return ((n
== 0) ? 0 : *(unsigned char *)s1
- *(unsigned char *)--s2
);
405 static const char charmap
[] = {
406 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
407 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
408 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
409 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
410 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
411 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
412 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
413 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
414 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
415 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
416 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
417 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
418 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
419 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
420 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
421 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
422 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
423 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
424 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
425 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
426 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
427 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
428 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
429 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
430 '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
431 '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
432 '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
433 '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
434 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
435 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
436 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
437 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
441 strcasecmp(const char *s1
, const char *s2
)
443 const unsigned char *cm
= (const unsigned char *)charmap
;
444 const unsigned char *us1
= (const unsigned char *)s1
;
445 const unsigned char *us2
= (const unsigned char *)s2
;
447 while (cm
[*us1
] == cm
[*us2
++])
450 return (cm
[*us1
] - cm
[*(us2
- 1)]);
454 strncasecmp(const char *s1
, const char *s2
, size_t n
)
456 const unsigned char *cm
= (const unsigned char *)charmap
;
457 const unsigned char *us1
= (const unsigned char *)s1
;
458 const unsigned char *us2
= (const unsigned char *)s2
;
460 while (n
!= 0 && cm
[*us1
] == cm
[*us2
++]) {
465 return (n
== 0 ? 0 : cm
[*us1
] - cm
[*(us2
- 1)]);
469 strcpy(char *s1
, const char *s2
)
473 while ((*s1
++ = *s2
++) != '\0')
479 strncpy(char *s1
, const char *s2
, size_t n
)
484 while (--n
!= 0 && (*s1
++ = *s2
++) != '\0')
493 strrchr(const char *sp
, int c
)
506 strstr(const char *as1
, const char *as2
)
515 if (s2
== NULL
|| *s2
== '\0')
522 while ((c
= *++s2
) == *s1
++ && c
)
525 return ((char *)tptr
- 1);
535 strpbrk(const char *string
, const char *brkset
)
540 for (p
= brkset
; *p
!= '\0' && *p
!= *string
; ++p
)
543 return ((char *)string
);
550 strncat(char *s1
, const char *s2
, size_t n
)
555 while (*s1
++ != '\0')
558 while ((*s1
++ = *s2
++) != '\0') {
567 #if defined(_BOOT) || defined(_KMDB)
568 #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n))
572 strlcat(char *dst
, const char *src
, size_t dstsize
)
575 size_t left
= dstsize
;
577 size_t l2
= strlen(src
);
580 while (left
-- != 0 && *df
!= '\0')
582 /*LINTED: possible ptrdiff_t overflow*/
583 l1
= (size_t)(df
- dst
);
587 copied
= l1
+ l2
>= dstsize
? dstsize
- l1
- 1 : l2
;
588 bcopy(src
, dst
+ l1
, copied
);
589 dst
[l1
+copied
] = '\0';
594 strlcpy(char *dst
, const char *src
, size_t len
)
596 size_t slen
= strlen(src
);
606 bcopy(src
, dst
, copied
);
612 strspn(const char *string
, const char *charset
)
616 for (q
= string
; *q
!= '\0'; ++q
) {
617 for (p
= charset
; *p
!= '\0' && *p
!= *q
; ++p
)
623 /*LINTED: possible ptrdiff_t overflow*/
624 return ((size_t)(q
- string
));
628 strcspn(const char *string
, const char *charset
)
632 for (q
= string
; *q
!= '\0'; ++q
) {
633 for (p
= charset
; *p
!= '\0' && *p
!= *q
; ++p
)
639 /*LINTED E_PTRDIFF_OVERFLOW*/
640 return ((size_t)(q
- string
));
646 * The strsep() function locates, in the string referenced by *stringp, the
647 * first occurrence of any character in the string delim (or the terminating
648 * `\0' character) and replaces it with a `\0'. The location of the next
649 * character after the delimiter character (or NULL, if the end of the
650 * string was reached) is stored in *stringp. The original value of
651 * *stringp is returned.
653 * If *stringp is initially NULL, strsep() returns NULL.
655 * NOTE: This instance is left for in-kernel use. Libraries and programs
656 * should use strsep from libc.
659 strsep(char **stringp
, const char *delim
)
666 if ((s
= *stringp
) == NULL
)
673 if ((sc
= *spanp
++) == c
) {
687 * Unless mentioned otherwise, all of the routines below should be added to
688 * the Solaris DDI as necessary. For now, only provide them to standalone.
690 #if defined(_BOOT) || defined(_KMDB)
692 strtok(char *string
, const char *sepset
)
698 * Set `p' to our current location in the string.
700 p
= (string
== NULL
) ? savept
: string
;
705 * Skip leading separators; bail if no tokens remain.
707 q
= p
+ strspn(p
, sepset
);
712 * Mark the end of the token and set `savept' for the next iteration.
714 if ((r
= strpbrk(q
, sepset
)) == NULL
)
725 * The strlen() routine isn't shared with the kernel because it has its own
726 * hand-tuned assembly version.
729 strlen(const char *s
)
738 #endif /* _BOOT || _KMDB */
741 * Returns the number of non-NULL bytes in string argument,
742 * but not more than maxlen. Does not look past str + maxlen.
745 strnlen(const char *s
, size_t maxlen
)
749 while (maxlen
!= 0 && *s
!= 0) {
761 * Check for a valid C identifier:
762 * a letter or underscore, followed by
763 * zero or more letters, digits and underscores.
766 #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
768 #define IS_ALPHA(c) \
769 (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
772 strident_valid(const char *id
)
776 if (!IS_ALPHA(c
) && c
!= '_')
778 while ((c
= *id
++) != 0) {
779 if (!IS_ALPHA(c
) && !IS_DIGIT(c
) && c
!= '_')
786 * Convert a string into a valid C identifier by replacing invalid
787 * characters with '_'. Also makes sure the string is nul-terminated
788 * and takes up at most n bytes.
791 strident_canon(char *s
, size_t n
)
794 char *end
= s
+ n
- 1;
801 if (!IS_ALPHA(c
) && c
!= '_')
804 while (s
< end
&& ((c
= *(++s
)) != 0)) {
805 if (!IS_ALPHA(c
) && !IS_DIGIT(c
) && c
!= '_')