dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / common / util / string.c
blob26e5744485397c60c15d0d24cb1a8c7c1ea9b25a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
38 #include <sys/null.h>
39 #include <sys/varargs.h>
41 #if defined(_KERNEL)
42 #include <sys/systm.h>
43 #include <sys/debug.h>
44 #elif !defined(_BOOT)
45 #include <string.h>
46 #endif
48 #include "memcpy.h"
49 #include "string.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.
68 size_t
69 vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
71 uint64_t ul, tmp;
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 */
78 va_list args;
81 * Make a copy so that all our callers don't have to make a copy
83 va_copy(args, aargs);
85 if ((ssize_t)buflen < 0)
86 buflen = 0;
88 while ((c = *fmt++) != '\0') {
89 if (c != '%') {
90 ADDCHAR(c);
91 continue;
94 width = prec = 0;
95 left_align = base = sign = 0;
96 h_count = l_count = dot_count = 0;
97 pad = ' ';
98 digits = "0123456789abcdef";
99 next_fmt:
100 if ((c = *fmt++) == '\0')
101 break;
103 if (c >= 'A' && c <= 'Z') {
104 c += 'a' - 'A';
105 digits = "0123456789ABCDEF";
108 switch (c) {
109 case '-':
110 left_align++;
111 goto next_fmt;
112 case '0':
113 if (dot_count == 0)
114 pad = '0';
115 /*FALLTHROUGH*/
116 case '1':
117 case '2':
118 case '3':
119 case '4':
120 case '5':
121 case '6':
122 case '7':
123 case '8':
124 case '9':
125 num = 0;
126 for (;;) {
127 num = 10 * num + c - '0';
128 c = *fmt;
129 if (c < '0' || c > '9')
130 break;
131 else
132 fmt++;
134 if (dot_count > 0)
135 prec = num;
136 else
137 width = num;
139 goto next_fmt;
140 case '.':
141 dot_count++;
142 goto next_fmt;
143 case '*':
144 if (dot_count > 0)
145 prec = (int)va_arg(args, int);
146 else
147 width = (int)va_arg(args, int);
148 goto next_fmt;
149 case 'l':
150 l_count++;
151 goto next_fmt;
152 case 'h':
153 h_count++;
154 goto next_fmt;
155 case 'd':
156 sign = 1;
157 /*FALLTHROUGH*/
158 case 'u':
159 base = 10;
160 break;
161 case 'p':
162 l_count = 1;
163 /*FALLTHROUGH*/
164 case 'x':
165 base = 16;
166 break;
167 case 'o':
168 base = 8;
169 break;
170 case 'b':
171 l_count = 0;
172 base = 1;
173 break;
174 case 'c':
175 c = (char)va_arg(args, int);
176 ADDCHAR(c);
177 break;
178 case 's':
179 sp = va_arg(args, char *);
180 if (sp == NULL) {
181 sp = "<null string>";
182 /* avoid truncation */
183 prec = strlen(sp);
186 * Handle simple case specially to avoid
187 * performance hit of strlen()
189 if (prec == 0 && width == 0) {
190 while ((c = *sp++) != 0)
191 ADDCHAR(c);
192 break;
194 if (prec > 0) {
195 transfer_count = strnlen(sp, prec);
196 /* widen field if too narrow */
197 if (prec > width)
198 width = prec;
199 } else
200 transfer_count = strlen(sp);
201 if (width > transfer_count)
202 pad_count = width - transfer_count;
203 else
204 pad_count = 0;
205 while ((!left_align) && (pad_count-- > 0))
206 ADDCHAR(' ');
207 /* ADDCHAR() evaluates arg at most once */
208 while (transfer_count-- > 0)
209 ADDCHAR(*sp++);
210 while ((left_align) && (pad_count-- > 0))
211 ADDCHAR(' ');
212 break;
213 case '%':
214 ADDCHAR('%');
215 break;
218 if (base == 0)
219 continue;
221 if (h_count == 0 && l_count == 0)
222 if (sign)
223 ul = (int64_t)va_arg(args, int);
224 else
225 ul = (int64_t)va_arg(args, unsigned int);
226 else if (l_count > 1)
227 if (sign)
228 ul = (int64_t)va_arg(args, int64_t);
229 else
230 ul = (int64_t)va_arg(args, uint64_t);
231 else if (l_count > 0)
232 if (sign)
233 ul = (int64_t)va_arg(args, long);
234 else
235 ul = (int64_t)va_arg(args, unsigned long);
236 else if (h_count > 1)
237 if (sign)
238 ul = (int64_t)((char)va_arg(args, int));
239 else
240 ul = (int64_t)((unsigned char)va_arg(args,
241 int));
242 else if (h_count > 0)
243 if (sign)
244 ul = (int64_t)((short)va_arg(args, int));
245 else
246 ul = (int64_t)((unsigned short)va_arg(args,
247 int));
249 if (sign && (int64_t)ul < 0)
250 ul = -ul;
251 else
252 sign = 0;
254 if (c == 'b') {
255 bs = va_arg(args, char *);
256 base = *bs++;
259 /* avoid repeated division if width is 0 */
260 if (width > 0) {
261 tmp = ul;
262 do {
263 width--;
264 } while ((tmp /= base) != 0);
267 if (sign && pad == '0')
268 ADDCHAR('-');
269 while ((!left_align) && (width-- > sign))
270 ADDCHAR(pad);
271 if (sign && pad == ' ')
272 ADDCHAR('-');
274 sp = numbuf;
275 tmp = ul;
276 do {
277 *sp++ = digits[tmp % base];
278 } while ((tmp /= base) != 0);
280 while (sp > numbuf) {
281 sp--;
282 ADDCHAR(*sp);
285 /* add left-alignment padding */
286 while (width-- > sign)
287 ADDCHAR(' ');
289 if (c == 'b' && ul != 0) {
290 int any = 0;
291 c = *bs++;
292 while (c != 0) {
293 if (ul & (1 << (c - 1))) {
294 if (any++ == 0)
295 ADDCHAR('<');
296 while ((c = *bs++) >= 32)
297 ADDCHAR(c);
298 ADDCHAR(',');
299 } else {
300 while ((c = *bs++) >= 32)
301 continue;
304 if (any) {
305 bufp--;
306 ADDCHAR('>');
310 if (bufp - buf < buflen)
311 bufp[0] = c;
312 else if (buflen != 0)
313 buf[buflen - 1] = c;
315 va_end(args);
317 return (bufp - buf);
320 /*PRINTFLIKE3*/
321 size_t
322 snprintf(char *buf, size_t buflen, const char *fmt, ...)
324 va_list args;
326 va_start(args, fmt);
327 buflen = vsnprintf(buf, buflen, fmt, args);
328 va_end(args);
330 return (buflen);
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.
338 /*PRINTFLIKE2*/
340 sprintf(char *buf, const char *fmt, ...)
342 va_list args;
344 va_start(args, fmt);
345 (void) vsnprintf(buf, INT_MAX, fmt, args);
346 va_end(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) */
361 char *
362 strcat(char *s1, const char *s2)
364 char *os1 = s1;
366 while (*s1++ != '\0')
368 s1--;
369 while ((*s1++ = *s2++) != '\0')
371 return (os1);
374 char *
375 strchr(const char *sp, int c)
377 do {
378 if (*sp == (char)c)
379 return ((char *)sp);
380 } while (*sp++);
381 return (NULL);
385 strcmp(const char *s1, const char *s2)
387 while (*s1 == *s2++)
388 if (*s1++ == '\0')
389 return (0);
390 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
394 strncmp(const char *s1, const char *s2, size_t n)
396 if (s1 == s2)
397 return (0);
398 n++;
399 while (--n != 0 && *s1 == *s2++)
400 if (*s1++ == '\0')
401 return (0);
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++])
448 if (*us1++ == '\0')
449 return (0);
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++]) {
461 if (*us1++ == '\0')
462 return (0);
463 n--;
465 return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]);
468 char *
469 strcpy(char *s1, const char *s2)
471 char *os1 = s1;
473 while ((*s1++ = *s2++) != '\0')
475 return (os1);
478 char *
479 strncpy(char *s1, const char *s2, size_t n)
481 char *os1 = s1;
483 n++;
484 while (--n != 0 && (*s1++ = *s2++) != '\0')
486 if (n != 0)
487 while (--n != 0)
488 *s1++ = '\0';
489 return (os1);
492 char *
493 strrchr(const char *sp, int c)
495 char *r = NULL;
497 do {
498 if (*sp == (char)c)
499 r = (char *)sp;
500 } while (*sp++);
502 return (r);
505 char *
506 strstr(const char *as1, const char *as2)
508 const char *s1, *s2;
509 const char *tptr;
510 char c;
512 s1 = as1;
513 s2 = as2;
515 if (s2 == NULL || *s2 == '\0')
516 return ((char *)s1);
517 c = *s2;
519 while (*s1)
520 if (*s1++ == c) {
521 tptr = s1;
522 while ((c = *++s2) == *s1++ && c)
524 if (c == 0)
525 return ((char *)tptr - 1);
526 s1 = tptr;
527 s2 = as2;
528 c = *s2;
531 return (NULL);
534 char *
535 strpbrk(const char *string, const char *brkset)
537 const char *p;
539 do {
540 for (p = brkset; *p != '\0' && *p != *string; ++p)
542 if (*p != '\0')
543 return ((char *)string);
544 } while (*string++);
546 return (NULL);
549 char *
550 strncat(char *s1, const char *s2, size_t n)
552 char *os1 = s1;
554 n++;
555 while (*s1++ != '\0')
557 --s1;
558 while ((*s1++ = *s2++) != '\0') {
559 if (--n == 0) {
560 s1[-1] = '\0';
561 break;
564 return (os1);
567 #if defined(_BOOT) || defined(_KMDB)
568 #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n))
569 #endif
571 size_t
572 strlcat(char *dst, const char *src, size_t dstsize)
574 char *df = dst;
575 size_t left = dstsize;
576 size_t l1;
577 size_t l2 = strlen(src);
578 size_t copied;
580 while (left-- != 0 && *df != '\0')
581 df++;
582 /*LINTED: possible ptrdiff_t overflow*/
583 l1 = (size_t)(df - dst);
584 if (dstsize == l1)
585 return (l1 + l2);
587 copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2;
588 bcopy(src, dst + l1, copied);
589 dst[l1+copied] = '\0';
590 return (l1 + l2);
593 size_t
594 strlcpy(char *dst, const char *src, size_t len)
596 size_t slen = strlen(src);
597 size_t copied;
599 if (len == 0)
600 return (slen);
602 if (slen >= len)
603 copied = len - 1;
604 else
605 copied = slen;
606 bcopy(src, dst, copied);
607 dst[copied] = '\0';
608 return (slen);
611 size_t
612 strspn(const char *string, const char *charset)
614 const char *p, *q;
616 for (q = string; *q != '\0'; ++q) {
617 for (p = charset; *p != '\0' && *p != *q; ++p)
619 if (*p == '\0')
620 break;
623 /*LINTED: possible ptrdiff_t overflow*/
624 return ((size_t)(q - string));
627 size_t
628 strcspn(const char *string, const char *charset)
630 const char *p, *q;
632 for (q = string; *q != '\0'; ++q) {
633 for (p = charset; *p != '\0' && *p != *q; ++p)
635 if (*p != '\0')
636 break;
639 /*LINTED E_PTRDIFF_OVERFLOW*/
640 return ((size_t)(q - string));
644 * strsep
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.
658 char *
659 strsep(char **stringp, const char *delim)
661 char *s;
662 const char *spanp;
663 int c, sc;
664 char *tok;
666 if ((s = *stringp) == NULL)
667 return (NULL);
669 for (tok = s; ; ) {
670 c = *s++;
671 spanp = delim;
672 do {
673 if ((sc = *spanp++) == c) {
674 if (c == 0)
675 s = NULL;
676 else
677 s[-1] = 0;
678 *stringp = s;
679 return (tok);
681 } while (sc != 0);
683 /* NOTREACHED */
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)
691 char *
692 strtok(char *string, const char *sepset)
694 char *p, *q, *r;
695 static char *savept;
698 * Set `p' to our current location in the string.
700 p = (string == NULL) ? savept : string;
701 if (p == NULL)
702 return (NULL);
705 * Skip leading separators; bail if no tokens remain.
707 q = p + strspn(p, sepset);
708 if (*q == '\0')
709 return (NULL);
712 * Mark the end of the token and set `savept' for the next iteration.
714 if ((r = strpbrk(q, sepset)) == NULL)
715 savept = NULL;
716 else {
717 *r = '\0';
718 savept = ++r;
721 return (q);
725 * The strlen() routine isn't shared with the kernel because it has its own
726 * hand-tuned assembly version.
728 size_t
729 strlen(const char *s)
731 size_t n = 0;
733 while (*s++)
734 n++;
735 return (n);
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.
744 size_t
745 strnlen(const char *s, size_t maxlen)
747 size_t n = 0;
749 while (maxlen != 0 && *s != 0) {
750 s++;
751 maxlen--;
752 n++;
755 return (n);
759 #ifdef _KERNEL
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)
774 int c = *id++;
776 if (!IS_ALPHA(c) && c != '_')
777 return (0);
778 while ((c = *id++) != 0) {
779 if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
780 return (0);
782 return (1);
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.
790 void
791 strident_canon(char *s, size_t n)
793 char c;
794 char *end = s + n - 1;
796 ASSERT(n > 0);
798 if ((c = *s) == 0)
799 return;
801 if (!IS_ALPHA(c) && c != '_')
802 *s = '_';
804 while (s < end && ((c = *(++s)) != 0)) {
805 if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_')
806 *s = '_';
808 *s = 0;
811 #endif /* _KERNEL */