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. 2977889f88SYuri Pankov * Copyright 2018 Nexenta Systems, Inc. 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> 41ae115bc7Smrj 42ae115bc7Smrj #if defined(_KERNEL) 437c478bd9Sstevel@tonic-gate #include <sys/systm.h> 447c478bd9Sstevel@tonic-gate #include <sys/debug.h> 45ae115bc7Smrj #elif !defined(_BOOT) 46ae115bc7Smrj #include <string.h> 47ae115bc7Smrj #endif 48ae115bc7Smrj 49ae115bc7Smrj #include "memcpy.h" 50ae115bc7Smrj #include "string.h" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 53ae115bc7Smrj * We don't need these for x86 boot or kmdb. 547c478bd9Sstevel@tonic-gate */ 55ae115bc7Smrj #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc)) 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c) 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Given a buffer 'buf' of size 'buflen', render as much of the string 617c478bd9Sstevel@tonic-gate * described by <fmt, args> as possible. The string will always be 627c478bd9Sstevel@tonic-gate * null-terminated, so the maximum string length is 'buflen - 1'. 637c478bd9Sstevel@tonic-gate * Returns the number of bytes that would be necessary to render the 647c478bd9Sstevel@tonic-gate * entire string, not including null terminator (just like vsnprintf(3S)). 657c478bd9Sstevel@tonic-gate * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * There is no support for floating point, and the C locale is assumed. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate size_t 707c478bd9Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs) 717c478bd9Sstevel@tonic-gate { 727c478bd9Sstevel@tonic-gate uint64_t ul, tmp; 737c478bd9Sstevel@tonic-gate char *bufp = buf; /* current buffer pointer */ 7477889f88SYuri Pankov char c, pad; 7577889f88SYuri Pankov int width, base, sign, num; 76186507a7Smyers int prec, h_count, l_count, dot_count; 77186507a7Smyers int pad_count, transfer_count, left_align; 787c478bd9Sstevel@tonic-gate char *digits, *sp, *bs; 797c478bd9Sstevel@tonic-gate char numbuf[65]; /* sufficient for a 64-bit binary value */ 8077889f88SYuri Pankov int numwidth; 817c478bd9Sstevel@tonic-gate va_list args; 827c478bd9Sstevel@tonic-gate 83584b574aSToomas Soome ul = 0; 84584b574aSToomas Soome bs = NULL; 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * Make a copy so that all our callers don't have to make a copy 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate va_copy(args, aargs); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if ((ssize_t)buflen < 0) 917c478bd9Sstevel@tonic-gate buflen = 0; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate while ((c = *fmt++) != '\0') { 947c478bd9Sstevel@tonic-gate if (c != '%') { 957c478bd9Sstevel@tonic-gate ADDCHAR(c); 967c478bd9Sstevel@tonic-gate continue; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 9977889f88SYuri Pankov width = prec = numwidth = 0; 100186507a7Smyers left_align = base = sign = 0; 101186507a7Smyers h_count = l_count = dot_count = 0; 102186507a7Smyers pad = ' '; 103186507a7Smyers digits = "0123456789abcdef"; 104186507a7Smyers next_fmt: 1057c478bd9Sstevel@tonic-gate if ((c = *fmt++) == '\0') 1067c478bd9Sstevel@tonic-gate break; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') { 1097c478bd9Sstevel@tonic-gate c += 'a' - 'A'; 1107c478bd9Sstevel@tonic-gate digits = "0123456789ABCDEF"; 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate switch (c) { 114186507a7Smyers case '-': 115186507a7Smyers left_align++; 116186507a7Smyers goto next_fmt; 117186507a7Smyers case '0': 118186507a7Smyers if (dot_count == 0) 119186507a7Smyers pad = '0'; 120186507a7Smyers /*FALLTHROUGH*/ 121186507a7Smyers case '1': 122186507a7Smyers case '2': 123186507a7Smyers case '3': 124186507a7Smyers case '4': 125186507a7Smyers case '5': 126186507a7Smyers case '6': 127186507a7Smyers case '7': 128186507a7Smyers case '8': 129186507a7Smyers case '9': 130186507a7Smyers num = 0; 131186507a7Smyers for (;;) { 132186507a7Smyers num = 10 * num + c - '0'; 133186507a7Smyers c = *fmt; 134186507a7Smyers if (c < '0' || c > '9') 135186507a7Smyers break; 136186507a7Smyers else 137186507a7Smyers fmt++; 138186507a7Smyers } 139186507a7Smyers if (dot_count > 0) 140186507a7Smyers prec = num; 141186507a7Smyers else 142186507a7Smyers width = num; 143186507a7Smyers 144186507a7Smyers goto next_fmt; 145186507a7Smyers case '.': 146186507a7Smyers dot_count++; 147186507a7Smyers goto next_fmt; 148186507a7Smyers case '*': 149049fa28aSdr146992 if (dot_count > 0) 150049fa28aSdr146992 prec = (int)va_arg(args, int); 151049fa28aSdr146992 else 152186507a7Smyers width = (int)va_arg(args, int); 153186507a7Smyers goto next_fmt; 154186507a7Smyers case 'l': 155186507a7Smyers l_count++; 156186507a7Smyers goto next_fmt; 157186507a7Smyers case 'h': 158186507a7Smyers h_count++; 159186507a7Smyers goto next_fmt; 1607c478bd9Sstevel@tonic-gate case 'd': 1617c478bd9Sstevel@tonic-gate sign = 1; 1627c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1637c478bd9Sstevel@tonic-gate case 'u': 1647c478bd9Sstevel@tonic-gate base = 10; 1657c478bd9Sstevel@tonic-gate break; 1667c478bd9Sstevel@tonic-gate case 'p': 167186507a7Smyers l_count = 1; 1687c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1697c478bd9Sstevel@tonic-gate case 'x': 1707c478bd9Sstevel@tonic-gate base = 16; 1717c478bd9Sstevel@tonic-gate break; 1727c478bd9Sstevel@tonic-gate case 'o': 1737c478bd9Sstevel@tonic-gate base = 8; 1747c478bd9Sstevel@tonic-gate break; 1757c478bd9Sstevel@tonic-gate case 'b': 176186507a7Smyers l_count = 0; 1777c478bd9Sstevel@tonic-gate base = 1; 1787c478bd9Sstevel@tonic-gate break; 1797c478bd9Sstevel@tonic-gate case 'c': 180fc77c268Smyers c = (char)va_arg(args, int); 181186507a7Smyers ADDCHAR(c); 1827c478bd9Sstevel@tonic-gate break; 1837c478bd9Sstevel@tonic-gate case 's': 1847c478bd9Sstevel@tonic-gate sp = va_arg(args, char *); 185186507a7Smyers if (sp == NULL) { 1867c478bd9Sstevel@tonic-gate sp = "<null string>"; 187186507a7Smyers /* avoid truncation */ 188186507a7Smyers prec = strlen(sp); 189186507a7Smyers } 190186507a7Smyers /* 191186507a7Smyers * Handle simple case specially to avoid 192186507a7Smyers * performance hit of strlen() 193186507a7Smyers */ 194186507a7Smyers if (prec == 0 && width == 0) { 1957c478bd9Sstevel@tonic-gate while ((c = *sp++) != 0) 1967c478bd9Sstevel@tonic-gate ADDCHAR(c); 1977c478bd9Sstevel@tonic-gate break; 198186507a7Smyers } 199186507a7Smyers if (prec > 0) { 2007637daddSmyers transfer_count = strnlen(sp, prec); 201186507a7Smyers /* widen field if too narrow */ 202186507a7Smyers if (prec > width) 203186507a7Smyers width = prec; 2047637daddSmyers } else 2057637daddSmyers transfer_count = strlen(sp); 206186507a7Smyers if (width > transfer_count) 207186507a7Smyers pad_count = width - transfer_count; 208186507a7Smyers else 209186507a7Smyers pad_count = 0; 210186507a7Smyers while ((!left_align) && (pad_count-- > 0)) 211186507a7Smyers ADDCHAR(' '); 212186507a7Smyers /* ADDCHAR() evaluates arg at most once */ 213186507a7Smyers while (transfer_count-- > 0) 214186507a7Smyers ADDCHAR(*sp++); 215186507a7Smyers while ((left_align) && (pad_count-- > 0)) 216186507a7Smyers ADDCHAR(' '); 217186507a7Smyers break; 2187c478bd9Sstevel@tonic-gate case '%': 2197c478bd9Sstevel@tonic-gate ADDCHAR('%'); 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (base == 0) 2247c478bd9Sstevel@tonic-gate continue; 2257c478bd9Sstevel@tonic-gate 226*3df2e8b2SRobert Mustacchi if (h_count == 0 && l_count == 0) { 227186507a7Smyers if (sign) 2287c478bd9Sstevel@tonic-gate ul = (int64_t)va_arg(args, int); 229186507a7Smyers else 230186507a7Smyers ul = (int64_t)va_arg(args, unsigned int); 231*3df2e8b2SRobert Mustacchi } else if (l_count > 1) { 232186507a7Smyers if (sign) 233186507a7Smyers ul = (int64_t)va_arg(args, int64_t); 234186507a7Smyers else 235186507a7Smyers ul = (int64_t)va_arg(args, uint64_t); 236*3df2e8b2SRobert Mustacchi } else if (l_count > 0) { 237186507a7Smyers if (sign) 2387c478bd9Sstevel@tonic-gate ul = (int64_t)va_arg(args, long); 2397c478bd9Sstevel@tonic-gate else 240186507a7Smyers ul = (int64_t)va_arg(args, unsigned long); 241*3df2e8b2SRobert Mustacchi } else if (h_count > 1) { 242186507a7Smyers if (sign) 243fc77c268Smyers ul = (int64_t)((char)va_arg(args, int)); 244186507a7Smyers else 245fc77c268Smyers ul = (int64_t)((unsigned char)va_arg(args, 246fc77c268Smyers int)); 247*3df2e8b2SRobert Mustacchi } else if (h_count > 0) { 248186507a7Smyers if (sign) 249fc77c268Smyers ul = (int64_t)((short)va_arg(args, int)); 250186507a7Smyers else 251fc77c268Smyers ul = (int64_t)((unsigned short)va_arg(args, 252fc77c268Smyers int)); 253*3df2e8b2SRobert Mustacchi } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if (sign && (int64_t)ul < 0) 2567c478bd9Sstevel@tonic-gate ul = -ul; 2577c478bd9Sstevel@tonic-gate else 2587c478bd9Sstevel@tonic-gate sign = 0; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if (c == 'b') { 2617c478bd9Sstevel@tonic-gate bs = va_arg(args, char *); 2627c478bd9Sstevel@tonic-gate base = *bs++; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 26577889f88SYuri Pankov /* 26677889f88SYuri Pankov * Fill in the number string buffer and calculate the 26777889f88SYuri Pankov * number string length. 26877889f88SYuri Pankov */ 2697c478bd9Sstevel@tonic-gate tmp = ul; 2707c478bd9Sstevel@tonic-gate sp = numbuf; 2717c478bd9Sstevel@tonic-gate do { 2727c478bd9Sstevel@tonic-gate *sp++ = digits[tmp % base]; 27377889f88SYuri Pankov numwidth++; 2747c478bd9Sstevel@tonic-gate } while ((tmp /= base) != 0); 2757c478bd9Sstevel@tonic-gate 27677889f88SYuri Pankov /* 27777889f88SYuri Pankov * Reduce the total field width by precision or the number 27877889f88SYuri Pankov * string length depending on which one is bigger, and sign. 27977889f88SYuri Pankov */ 28077889f88SYuri Pankov if (prec >= numwidth) 28177889f88SYuri Pankov width -= prec; 28277889f88SYuri Pankov else 28377889f88SYuri Pankov width -= numwidth; 28477889f88SYuri Pankov width -= sign; 28577889f88SYuri Pankov 28677889f88SYuri Pankov /* Add the sign if width is '0'-padded */ 28777889f88SYuri Pankov if (sign && pad == '0') 28877889f88SYuri Pankov ADDCHAR('-'); 28977889f88SYuri Pankov 29077889f88SYuri Pankov /* If not left-aligned, add the width padding */ 29177889f88SYuri Pankov if (!left_align) { 29277889f88SYuri Pankov while (width-- > 0) 29377889f88SYuri Pankov ADDCHAR(pad); 29477889f88SYuri Pankov } 29577889f88SYuri Pankov 29677889f88SYuri Pankov /* Add the sign if width is NOT '0'-padded */ 29777889f88SYuri Pankov if (sign && pad != '0') 29877889f88SYuri Pankov ADDCHAR('-'); 29977889f88SYuri Pankov 30077889f88SYuri Pankov /* Add the precision '0'-padding */ 30177889f88SYuri Pankov while (prec-- > numwidth) 30277889f88SYuri Pankov ADDCHAR('0'); 30377889f88SYuri Pankov 30477889f88SYuri Pankov /* Print out the number */ 3057c478bd9Sstevel@tonic-gate while (sp > numbuf) { 3067c478bd9Sstevel@tonic-gate sp--; 3077c478bd9Sstevel@tonic-gate ADDCHAR(*sp); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 31077889f88SYuri Pankov /* Add left-alignment padding */ 31177889f88SYuri Pankov while (width-- > 0) 312237b1f31SPatrick Mooney ADDCHAR(' '); 313237b1f31SPatrick Mooney 3147c478bd9Sstevel@tonic-gate if (c == 'b' && ul != 0) { 3157c478bd9Sstevel@tonic-gate int any = 0; 3167c478bd9Sstevel@tonic-gate c = *bs++; 3177c478bd9Sstevel@tonic-gate while (c != 0) { 3187c478bd9Sstevel@tonic-gate if (ul & (1 << (c - 1))) { 3197c478bd9Sstevel@tonic-gate if (any++ == 0) 3207c478bd9Sstevel@tonic-gate ADDCHAR('<'); 3217c478bd9Sstevel@tonic-gate while ((c = *bs++) >= 32) 3227c478bd9Sstevel@tonic-gate ADDCHAR(c); 3237c478bd9Sstevel@tonic-gate ADDCHAR(','); 3247c478bd9Sstevel@tonic-gate } else { 3257c478bd9Sstevel@tonic-gate while ((c = *bs++) >= 32) 3267c478bd9Sstevel@tonic-gate continue; 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate if (any) { 3307c478bd9Sstevel@tonic-gate bufp--; 3317c478bd9Sstevel@tonic-gate ADDCHAR('>'); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate if (bufp - buf < buflen) 3367c478bd9Sstevel@tonic-gate bufp[0] = c; 3377c478bd9Sstevel@tonic-gate else if (buflen != 0) 3387c478bd9Sstevel@tonic-gate buf[buflen - 1] = c; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate va_end(args); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate return (bufp - buf); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3453c5da275SMatthew Ahrens /*PRINTFLIKE3*/ 3467c478bd9Sstevel@tonic-gate size_t 3477c478bd9Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate va_list args; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate va_start(args, fmt); 3527c478bd9Sstevel@tonic-gate buflen = vsnprintf(buf, buflen, fmt, args); 3537c478bd9Sstevel@tonic-gate va_end(args); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate return (buflen); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 358ae115bc7Smrj #if defined(_BOOT) && defined(__sparc) 3597c478bd9Sstevel@tonic-gate /* 3607c478bd9Sstevel@tonic-gate * The sprintf() and vsprintf() routines aren't shared with the kernel because 3617c478bd9Sstevel@tonic-gate * the DDI mandates that they return the buffer rather than its length. 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 3647c478bd9Sstevel@tonic-gate int 3657c478bd9Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate va_list args; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate va_start(args, fmt); 3707c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 3717c478bd9Sstevel@tonic-gate va_end(args); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate return (strlen(buf)); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate int 3777c478bd9Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 3807c478bd9Sstevel@tonic-gate return (strlen(buf)); 3817c478bd9Sstevel@tonic-gate } 382ae115bc7Smrj #endif /* _BOOT && __sparc */ 3837c478bd9Sstevel@tonic-gate 384ae115bc7Smrj #endif /* !_KMDB && (!_BOOT || __sparc) */ 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate char * 3877c478bd9Sstevel@tonic-gate strcat(char *s1, const char *s2) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate char *os1 = s1; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate while (*s1++ != '\0') 3927c478bd9Sstevel@tonic-gate ; 3937c478bd9Sstevel@tonic-gate s1--; 3947c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 3957c478bd9Sstevel@tonic-gate ; 3967c478bd9Sstevel@tonic-gate return (os1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate char * 4007c478bd9Sstevel@tonic-gate strchr(const char *sp, int c) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate do { 4037c478bd9Sstevel@tonic-gate if (*sp == (char)c) 4047c478bd9Sstevel@tonic-gate return ((char *)sp); 4057c478bd9Sstevel@tonic-gate } while (*sp++); 4067c478bd9Sstevel@tonic-gate return (NULL); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate int 4107c478bd9Sstevel@tonic-gate strcmp(const char *s1, const char *s2) 4117c478bd9Sstevel@tonic-gate { 4127c478bd9Sstevel@tonic-gate while (*s1 == *s2++) 4137c478bd9Sstevel@tonic-gate if (*s1++ == '\0') 4147c478bd9Sstevel@tonic-gate return (0); 4157c478bd9Sstevel@tonic-gate return (*(unsigned char *)s1 - *(unsigned char *)--s2); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate int 4197c478bd9Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate if (s1 == s2) 4227c478bd9Sstevel@tonic-gate return (0); 4237c478bd9Sstevel@tonic-gate n++; 4247c478bd9Sstevel@tonic-gate while (--n != 0 && *s1 == *s2++) 4257c478bd9Sstevel@tonic-gate if (*s1++ == '\0') 4267c478bd9Sstevel@tonic-gate return (0); 4277c478bd9Sstevel@tonic-gate return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate static const char charmap[] = { 4317c478bd9Sstevel@tonic-gate '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 4327c478bd9Sstevel@tonic-gate '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 4337c478bd9Sstevel@tonic-gate '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 4347c478bd9Sstevel@tonic-gate '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 4357c478bd9Sstevel@tonic-gate '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 4367c478bd9Sstevel@tonic-gate '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 4377c478bd9Sstevel@tonic-gate '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 4387c478bd9Sstevel@tonic-gate '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 4397c478bd9Sstevel@tonic-gate '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 4407c478bd9Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 4417c478bd9Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 4427c478bd9Sstevel@tonic-gate '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 4437c478bd9Sstevel@tonic-gate '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 4447c478bd9Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 4457c478bd9Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 4467c478bd9Sstevel@tonic-gate '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 4477c478bd9Sstevel@tonic-gate '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', 4487c478bd9Sstevel@tonic-gate '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', 4497c478bd9Sstevel@tonic-gate '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', 4507c478bd9Sstevel@tonic-gate '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', 4517c478bd9Sstevel@tonic-gate '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', 4527c478bd9Sstevel@tonic-gate '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', 4537c478bd9Sstevel@tonic-gate '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', 4547c478bd9Sstevel@tonic-gate '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', 4557c478bd9Sstevel@tonic-gate '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', 4567c478bd9Sstevel@tonic-gate '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', 4577c478bd9Sstevel@tonic-gate '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', 4587c478bd9Sstevel@tonic-gate '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', 4597c478bd9Sstevel@tonic-gate '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 4607c478bd9Sstevel@tonic-gate '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 4617c478bd9Sstevel@tonic-gate '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 4627c478bd9Sstevel@tonic-gate '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', 4637c478bd9Sstevel@tonic-gate }; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate int 4667c478bd9Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2) 4677c478bd9Sstevel@tonic-gate { 4687c478bd9Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 4697c478bd9Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 4707c478bd9Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate while (cm[*us1] == cm[*us2++]) 4737c478bd9Sstevel@tonic-gate if (*us1++ == '\0') 4747c478bd9Sstevel@tonic-gate return (0); 4757c478bd9Sstevel@tonic-gate return (cm[*us1] - cm[*(us2 - 1)]); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate int 4797c478bd9Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n) 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 4827c478bd9Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 4837c478bd9Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate while (n != 0 && cm[*us1] == cm[*us2++]) { 4867c478bd9Sstevel@tonic-gate if (*us1++ == '\0') 4877c478bd9Sstevel@tonic-gate return (0); 4887c478bd9Sstevel@tonic-gate n--; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate char * 4947c478bd9Sstevel@tonic-gate strcpy(char *s1, const char *s2) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate char *os1 = s1; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 4997c478bd9Sstevel@tonic-gate ; 5007c478bd9Sstevel@tonic-gate return (os1); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate char * 5047c478bd9Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate char *os1 = s1; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate n++; 5097c478bd9Sstevel@tonic-gate while (--n != 0 && (*s1++ = *s2++) != '\0') 5107c478bd9Sstevel@tonic-gate ; 5117c478bd9Sstevel@tonic-gate if (n != 0) 5127c478bd9Sstevel@tonic-gate while (--n != 0) 5137c478bd9Sstevel@tonic-gate *s1++ = '\0'; 5147c478bd9Sstevel@tonic-gate return (os1); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate char * 5187c478bd9Sstevel@tonic-gate strrchr(const char *sp, int c) 5197c478bd9Sstevel@tonic-gate { 5207c478bd9Sstevel@tonic-gate char *r = NULL; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate do { 5237c478bd9Sstevel@tonic-gate if (*sp == (char)c) 5247c478bd9Sstevel@tonic-gate r = (char *)sp; 5257c478bd9Sstevel@tonic-gate } while (*sp++); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate return (r); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate char * 5317c478bd9Sstevel@tonic-gate strstr(const char *as1, const char *as2) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate const char *s1, *s2; 5347c478bd9Sstevel@tonic-gate const char *tptr; 5357c478bd9Sstevel@tonic-gate char c; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate s1 = as1; 5387c478bd9Sstevel@tonic-gate s2 = as2; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 5417c478bd9Sstevel@tonic-gate return ((char *)s1); 5427c478bd9Sstevel@tonic-gate c = *s2; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate while (*s1) 5457c478bd9Sstevel@tonic-gate if (*s1++ == c) { 5467c478bd9Sstevel@tonic-gate tptr = s1; 5477c478bd9Sstevel@tonic-gate while ((c = *++s2) == *s1++ && c) 5487c478bd9Sstevel@tonic-gate ; 5497c478bd9Sstevel@tonic-gate if (c == 0) 5507c478bd9Sstevel@tonic-gate return ((char *)tptr - 1); 5517c478bd9Sstevel@tonic-gate s1 = tptr; 5527c478bd9Sstevel@tonic-gate s2 = as2; 5537c478bd9Sstevel@tonic-gate c = *s2; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate return (NULL); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate char * 5607c478bd9Sstevel@tonic-gate strpbrk(const char *string, const char *brkset) 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate const char *p; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate do { 5657c478bd9Sstevel@tonic-gate for (p = brkset; *p != '\0' && *p != *string; ++p) 5667c478bd9Sstevel@tonic-gate ; 5677c478bd9Sstevel@tonic-gate if (*p != '\0') 5687c478bd9Sstevel@tonic-gate return ((char *)string); 5697c478bd9Sstevel@tonic-gate } while (*string++); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate return (NULL); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate char * 5757c478bd9Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n) 5767c478bd9Sstevel@tonic-gate { 5777c478bd9Sstevel@tonic-gate char *os1 = s1; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate n++; 5807c478bd9Sstevel@tonic-gate while (*s1++ != '\0') 5817c478bd9Sstevel@tonic-gate ; 5827c478bd9Sstevel@tonic-gate --s1; 5837c478bd9Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') { 5847c478bd9Sstevel@tonic-gate if (--n == 0) { 5857c478bd9Sstevel@tonic-gate s1[-1] = '\0'; 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate return (os1); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 5937c478bd9Sstevel@tonic-gate #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n)) 5947c478bd9Sstevel@tonic-gate #endif 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate size_t 5977c478bd9Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize) 5987c478bd9Sstevel@tonic-gate { 5997c478bd9Sstevel@tonic-gate char *df = dst; 6007c478bd9Sstevel@tonic-gate size_t left = dstsize; 6017c478bd9Sstevel@tonic-gate size_t l1; 6027c478bd9Sstevel@tonic-gate size_t l2 = strlen(src); 6037c478bd9Sstevel@tonic-gate size_t copied; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate while (left-- != 0 && *df != '\0') 6067c478bd9Sstevel@tonic-gate df++; 607ae115bc7Smrj /*LINTED: possible ptrdiff_t overflow*/ 608ae115bc7Smrj l1 = (size_t)(df - dst); 6097c478bd9Sstevel@tonic-gate if (dstsize == l1) 6107c478bd9Sstevel@tonic-gate return (l1 + l2); 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2; 6137c478bd9Sstevel@tonic-gate bcopy(src, dst + l1, copied); 6147c478bd9Sstevel@tonic-gate dst[l1+copied] = '\0'; 6157c478bd9Sstevel@tonic-gate return (l1 + l2); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate size_t 6197c478bd9Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len) 6207c478bd9Sstevel@tonic-gate { 6217c478bd9Sstevel@tonic-gate size_t slen = strlen(src); 6227c478bd9Sstevel@tonic-gate size_t copied; 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if (len == 0) 6257c478bd9Sstevel@tonic-gate return (slen); 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate if (slen >= len) 6287c478bd9Sstevel@tonic-gate copied = len - 1; 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate copied = slen; 6317c478bd9Sstevel@tonic-gate bcopy(src, dst, copied); 6327c478bd9Sstevel@tonic-gate dst[copied] = '\0'; 6337c478bd9Sstevel@tonic-gate return (slen); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate size_t 6377c478bd9Sstevel@tonic-gate strspn(const char *string, const char *charset) 6387c478bd9Sstevel@tonic-gate { 6397c478bd9Sstevel@tonic-gate const char *p, *q; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate for (q = string; *q != '\0'; ++q) { 6427c478bd9Sstevel@tonic-gate for (p = charset; *p != '\0' && *p != *q; ++p) 6437c478bd9Sstevel@tonic-gate ; 6447c478bd9Sstevel@tonic-gate if (*p == '\0') 6457c478bd9Sstevel@tonic-gate break; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 648ae115bc7Smrj /*LINTED: possible ptrdiff_t overflow*/ 649ae115bc7Smrj return ((size_t)(q - string)); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 652da6c28aaSamw size_t 653da6c28aaSamw strcspn(const char *string, const char *charset) 654da6c28aaSamw { 655da6c28aaSamw const char *p, *q; 656da6c28aaSamw 657da6c28aaSamw for (q = string; *q != '\0'; ++q) { 658da6c28aaSamw for (p = charset; *p != '\0' && *p != *q; ++p) 659da6c28aaSamw ; 660da6c28aaSamw if (*p != '\0') 661da6c28aaSamw break; 662da6c28aaSamw } 663da6c28aaSamw 664da6c28aaSamw /*LINTED E_PTRDIFF_OVERFLOW*/ 665da6c28aaSamw return ((size_t)(q - string)); 666da6c28aaSamw } 667da6c28aaSamw 668da6c28aaSamw /* 669da6c28aaSamw * strsep 670da6c28aaSamw * 671da6c28aaSamw * The strsep() function locates, in the string referenced by *stringp, the 672da6c28aaSamw * first occurrence of any character in the string delim (or the terminating 673da6c28aaSamw * `\0' character) and replaces it with a `\0'. The location of the next 674da6c28aaSamw * character after the delimiter character (or NULL, if the end of the 675da6c28aaSamw * string was reached) is stored in *stringp. The original value of 676da6c28aaSamw * *stringp is returned. 677da6c28aaSamw * 678da6c28aaSamw * If *stringp is initially NULL, strsep() returns NULL. 679b811a51aSVladimir Kotal * 680b811a51aSVladimir Kotal * NOTE: This instance is left for in-kernel use. Libraries and programs 681b811a51aSVladimir Kotal * should use strsep from libc. 682da6c28aaSamw */ 683da6c28aaSamw char * 684da6c28aaSamw strsep(char **stringp, const char *delim) 685da6c28aaSamw { 686da6c28aaSamw char *s; 687da6c28aaSamw const char *spanp; 688da6c28aaSamw int c, sc; 689da6c28aaSamw char *tok; 690da6c28aaSamw 691da6c28aaSamw if ((s = *stringp) == NULL) 692da6c28aaSamw return (NULL); 693da6c28aaSamw 694da6c28aaSamw for (tok = s; ; ) { 695da6c28aaSamw c = *s++; 696da6c28aaSamw spanp = delim; 697da6c28aaSamw do { 698da6c28aaSamw if ((sc = *spanp++) == c) { 699da6c28aaSamw if (c == 0) 700da6c28aaSamw s = NULL; 701da6c28aaSamw else 702da6c28aaSamw s[-1] = 0; 703da6c28aaSamw *stringp = s; 704da6c28aaSamw return (tok); 705da6c28aaSamw } 706da6c28aaSamw } while (sc != 0); 707da6c28aaSamw } 708da6c28aaSamw /* NOTREACHED */ 709da6c28aaSamw } 710da6c28aaSamw 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * Unless mentioned otherwise, all of the routines below should be added to 7137c478bd9Sstevel@tonic-gate * the Solaris DDI as necessary. For now, only provide them to standalone. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 7167c478bd9Sstevel@tonic-gate char * 7177c478bd9Sstevel@tonic-gate strtok(char *string, const char *sepset) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate char *p, *q, *r; 7207c478bd9Sstevel@tonic-gate static char *savept; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * Set `p' to our current location in the string. 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate p = (string == NULL) ? savept : string; 7267c478bd9Sstevel@tonic-gate if (p == NULL) 7277c478bd9Sstevel@tonic-gate return (NULL); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * Skip leading separators; bail if no tokens remain. 7317c478bd9Sstevel@tonic-gate */ 7327c478bd9Sstevel@tonic-gate q = p + strspn(p, sepset); 7337c478bd9Sstevel@tonic-gate if (*q == '\0') 7347c478bd9Sstevel@tonic-gate return (NULL); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* 7377c478bd9Sstevel@tonic-gate * Mark the end of the token and set `savept' for the next iteration. 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) 7407c478bd9Sstevel@tonic-gate savept = NULL; 7417c478bd9Sstevel@tonic-gate else { 7427c478bd9Sstevel@tonic-gate *r = '\0'; 7437c478bd9Sstevel@tonic-gate savept = ++r; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate return (q); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* 7507c478bd9Sstevel@tonic-gate * The strlen() routine isn't shared with the kernel because it has its own 7517c478bd9Sstevel@tonic-gate * hand-tuned assembly version. 7527c478bd9Sstevel@tonic-gate */ 7537c478bd9Sstevel@tonic-gate size_t 7547c478bd9Sstevel@tonic-gate strlen(const char *s) 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate size_t n = 0; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate while (*s++) 7597c478bd9Sstevel@tonic-gate n++; 7607c478bd9Sstevel@tonic-gate return (n); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate #endif /* _BOOT || _KMDB */ 7647c478bd9Sstevel@tonic-gate 7657637daddSmyers /* 7667637daddSmyers * Returns the number of non-NULL bytes in string argument, 7677637daddSmyers * but not more than maxlen. Does not look past str + maxlen. 7687637daddSmyers */ 7697637daddSmyers size_t 7707637daddSmyers strnlen(const char *s, size_t maxlen) 7717637daddSmyers { 7727637daddSmyers size_t n = 0; 7737637daddSmyers 7747637daddSmyers while (maxlen != 0 && *s != 0) { 7757637daddSmyers s++; 7767637daddSmyers maxlen--; 7777637daddSmyers n++; 7787637daddSmyers } 7797637daddSmyers 7807637daddSmyers return (n); 7817637daddSmyers } 7827637daddSmyers 7837637daddSmyers 7847c478bd9Sstevel@tonic-gate #ifdef _KERNEL 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * Check for a valid C identifier: 7877c478bd9Sstevel@tonic-gate * a letter or underscore, followed by 7887c478bd9Sstevel@tonic-gate * zero or more letters, digits and underscores. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate #define IS_ALPHA(c) \ 7947c478bd9Sstevel@tonic-gate (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate int 7977c478bd9Sstevel@tonic-gate strident_valid(const char *id) 7987c478bd9Sstevel@tonic-gate { 7997c478bd9Sstevel@tonic-gate int c = *id++; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 8027c478bd9Sstevel@tonic-gate return (0); 8037c478bd9Sstevel@tonic-gate while ((c = *id++) != 0) { 8047c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 8057c478bd9Sstevel@tonic-gate return (0); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate return (1); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* 8117c478bd9Sstevel@tonic-gate * Convert a string into a valid C identifier by replacing invalid 8127c478bd9Sstevel@tonic-gate * characters with '_'. Also makes sure the string is nul-terminated 8137c478bd9Sstevel@tonic-gate * and takes up at most n bytes. 8147c478bd9Sstevel@tonic-gate */ 8157c478bd9Sstevel@tonic-gate void 8167c478bd9Sstevel@tonic-gate strident_canon(char *s, size_t n) 8177c478bd9Sstevel@tonic-gate { 8187c478bd9Sstevel@tonic-gate char c; 8197c478bd9Sstevel@tonic-gate char *end = s + n - 1; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate ASSERT(n > 0); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate if ((c = *s) == 0) 8247c478bd9Sstevel@tonic-gate return; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 8277c478bd9Sstevel@tonic-gate *s = '_'; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate while (s < end && ((c = *(++s)) != 0)) { 8307c478bd9Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 8317c478bd9Sstevel@tonic-gate *s = '_'; 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate *s = 0; 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 837