1 // SPDX-License-Identifier: GPL-2.0-or-later 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 2 /* 3 * Copyright (C) Paul Mackerras 1997. 3 * Copyright (C) Paul Mackerras 1997. 4 */ 4 */ 5 #include <linux/string.h> 5 #include <linux/string.h> 6 #include <linux/stdarg.h> 6 #include <linux/stdarg.h> 7 7 8 size_t strnlen(const char * s, size_t count) 8 size_t strnlen(const char * s, size_t count) 9 { 9 { 10 const char *sc; 10 const char *sc; 11 11 12 for (sc = s; count-- && *sc != '\0'; + 12 for (sc = s; count-- && *sc != '\0'; ++sc) 13 /* nothing */; 13 /* nothing */; 14 return sc - s; 14 return sc - s; 15 } 15 } 16 16 17 # define do_div(n, base) ({ 17 # define do_div(n, base) ({ \ 18 unsigned int __base = (base); 18 unsigned int __base = (base); \ 19 unsigned int __rem; 19 unsigned int __rem; \ 20 __rem = ((unsigned long long)(n)) % __ 20 __rem = ((unsigned long long)(n)) % __base; \ 21 (n) = ((unsigned long long)(n)) / __ba 21 (n) = ((unsigned long long)(n)) / __base; \ 22 __rem; 22 __rem; \ 23 }) 23 }) 24 24 25 25 26 static int skip_atoi(const char **s) 26 static int skip_atoi(const char **s) 27 { 27 { 28 int i, c; 28 int i, c; 29 29 30 for (i = 0; '' <= (c = **s) && c <= '9 30 for (i = 0; '' <= (c = **s) && c <= '9'; ++*s) 31 i = i*10 + c - ''; 31 i = i*10 + c - ''; 32 return i; 32 return i; 33 } 33 } 34 34 35 #define ZEROPAD 1 /* pad with ze 35 #define ZEROPAD 1 /* pad with zero */ 36 #define SIGN 2 /* unsigned/si 36 #define SIGN 2 /* unsigned/signed long */ 37 #define PLUS 4 /* show plus * 37 #define PLUS 4 /* show plus */ 38 #define SPACE 8 /* space if pl 38 #define SPACE 8 /* space if plus */ 39 #define LEFT 16 /* left justif 39 #define LEFT 16 /* left justified */ 40 #define SPECIAL 32 /* 0x */ 40 #define SPECIAL 32 /* 0x */ 41 #define LARGE 64 /* use 'ABCDEF 41 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 42 42 43 static char * number(char * str, unsigned long 43 static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) 44 { 44 { 45 char c, sign, tmp[66]; 45 char c, sign, tmp[66]; 46 const char *digits = "0123456789abcdef 46 const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 47 int i; 47 int i; 48 48 49 if (type & LARGE) 49 if (type & LARGE) 50 digits = "0123456789ABCDEFGHIJ 50 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 51 if (type & LEFT) 51 if (type & LEFT) 52 type &= ~ZEROPAD; 52 type &= ~ZEROPAD; 53 if (base < 2 || base > 36) 53 if (base < 2 || base > 36) 54 return 0; 54 return 0; 55 c = (type & ZEROPAD) ? '' : ' '; 55 c = (type & ZEROPAD) ? '' : ' '; 56 sign = 0; 56 sign = 0; 57 if (type & SIGN) { 57 if (type & SIGN) { 58 if ((signed long long)num < 0) 58 if ((signed long long)num < 0) { 59 sign = '-'; 59 sign = '-'; 60 num = - (signed long l 60 num = - (signed long long)num; 61 size--; 61 size--; 62 } else if (type & PLUS) { 62 } else if (type & PLUS) { 63 sign = '+'; 63 sign = '+'; 64 size--; 64 size--; 65 } else if (type & SPACE) { 65 } else if (type & SPACE) { 66 sign = ' '; 66 sign = ' '; 67 size--; 67 size--; 68 } 68 } 69 } 69 } 70 if (type & SPECIAL) { 70 if (type & SPECIAL) { 71 if (base == 16) 71 if (base == 16) 72 size -= 2; 72 size -= 2; 73 else if (base == 8) 73 else if (base == 8) 74 size--; 74 size--; 75 } 75 } 76 i = 0; 76 i = 0; 77 if (num == 0) 77 if (num == 0) 78 tmp[i++]=''; 78 tmp[i++]=''; 79 else while (num != 0) { 79 else while (num != 0) { 80 tmp[i++] = digits[do_div(num, 80 tmp[i++] = digits[do_div(num, base)]; 81 } 81 } 82 if (i > precision) 82 if (i > precision) 83 precision = i; 83 precision = i; 84 size -= precision; 84 size -= precision; 85 if (!(type&(ZEROPAD+LEFT))) 85 if (!(type&(ZEROPAD+LEFT))) 86 while (size-- > 0) 86 while (size-- > 0) 87 *str++ = ' '; 87 *str++ = ' '; 88 if (sign) 88 if (sign) 89 *str++ = sign; 89 *str++ = sign; 90 if (type & SPECIAL) { 90 if (type & SPECIAL) { 91 if (base==8) 91 if (base==8) 92 *str++ = ''; 92 *str++ = ''; 93 else if (base == 16) { 93 else if (base == 16) { 94 *str++ = ''; 94 *str++ = ''; 95 *str++ = digits[33]; 95 *str++ = digits[33]; 96 } 96 } 97 } 97 } 98 if (!(type & LEFT)) 98 if (!(type & LEFT)) 99 while (size-- > 0) 99 while (size-- > 0) 100 *str++ = c; 100 *str++ = c; 101 while (i < precision--) 101 while (i < precision--) 102 *str++ = ''; 102 *str++ = ''; 103 while (i-- > 0) 103 while (i-- > 0) 104 *str++ = tmp[i]; 104 *str++ = tmp[i]; 105 while (size-- > 0) 105 while (size-- > 0) 106 *str++ = ' '; 106 *str++ = ' '; 107 return str; 107 return str; 108 } 108 } 109 109 110 int vsprintf(char *buf, const char *fmt, va_li 110 int vsprintf(char *buf, const char *fmt, va_list args) 111 { 111 { 112 int len; 112 int len; 113 unsigned long long num; 113 unsigned long long num; 114 int i, base; 114 int i, base; 115 char * str; 115 char * str; 116 const char *s; 116 const char *s; 117 117 118 int flags; /* flags to nu 118 int flags; /* flags to number() */ 119 119 120 int field_width; /* width of ou 120 int field_width; /* width of output field */ 121 int precision; /* min. # of d 121 int precision; /* min. # of digits for integers; max 122 number of c 122 number of chars for from string */ 123 int qualifier; /* 'h', 'l', o 123 int qualifier; /* 'h', 'l', or 'L' for integer fields */ 124 /* 'z' support 124 /* 'z' support added 23/7/1999 S.H. */ 125 /* 'z' changed 125 /* 'z' changed to 'Z' --davidm 1/25/99 */ 126 126 127 127 128 for (str = buf ; *fmt ; ++fmt) { 128 for (str = buf ; *fmt ; ++fmt) { 129 if (*fmt != '%') { 129 if (*fmt != '%') { 130 *str++ = *fmt; 130 *str++ = *fmt; 131 continue; 131 continue; 132 } 132 } 133 133 134 /* process flags */ 134 /* process flags */ 135 flags = 0; 135 flags = 0; 136 repeat: 136 repeat: 137 ++fmt; /* thi 137 ++fmt; /* this also skips first '%' */ 138 switch (*fmt) { 138 switch (*fmt) { 139 case '-': flag 139 case '-': flags |= LEFT; goto repeat; 140 case '+': flag 140 case '+': flags |= PLUS; goto repeat; 141 case ' ': flag 141 case ' ': flags |= SPACE; goto repeat; 142 case '#': flag 142 case '#': flags |= SPECIAL; goto repeat; 143 case '': flags 143 case '': flags |= ZEROPAD; goto repeat; 144 } 144 } 145 145 146 /* get field width */ 146 /* get field width */ 147 field_width = -1; 147 field_width = -1; 148 if ('' <= *fmt && *fmt <= '9') 148 if ('' <= *fmt && *fmt <= '9') 149 field_width = skip_ato 149 field_width = skip_atoi(&fmt); 150 else if (*fmt == '*') { 150 else if (*fmt == '*') { 151 ++fmt; 151 ++fmt; 152 /* it's the next argum 152 /* it's the next argument */ 153 field_width = va_arg(a 153 field_width = va_arg(args, int); 154 if (field_width < 0) { 154 if (field_width < 0) { 155 field_width = 155 field_width = -field_width; 156 flags |= LEFT; 156 flags |= LEFT; 157 } 157 } 158 } 158 } 159 159 160 /* get the precision */ 160 /* get the precision */ 161 precision = -1; 161 precision = -1; 162 if (*fmt == '.') { 162 if (*fmt == '.') { 163 ++fmt; 163 ++fmt; 164 if ('' <= *fmt && *fmt 164 if ('' <= *fmt && *fmt <= '9') 165 precision = sk 165 precision = skip_atoi(&fmt); 166 else if (*fmt == '*') 166 else if (*fmt == '*') { 167 ++fmt; 167 ++fmt; 168 /* it's the ne 168 /* it's the next argument */ 169 precision = va 169 precision = va_arg(args, int); 170 } 170 } 171 if (precision < 0) 171 if (precision < 0) 172 precision = 0; 172 precision = 0; 173 } 173 } 174 174 175 /* get the conversion qualifie 175 /* get the conversion qualifier */ 176 qualifier = -1; 176 qualifier = -1; 177 if (*fmt == 'l' && *(fmt + 1) 177 if (*fmt == 'l' && *(fmt + 1) == 'l') { 178 qualifier = 'q'; 178 qualifier = 'q'; 179 fmt += 2; 179 fmt += 2; 180 } else if (*fmt == 'h' || *fmt 180 } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' 181 || *fmt == 'Z') { 181 || *fmt == 'Z') { 182 qualifier = *fmt; 182 qualifier = *fmt; 183 ++fmt; 183 ++fmt; 184 } 184 } 185 185 186 /* default base */ 186 /* default base */ 187 base = 10; 187 base = 10; 188 188 189 switch (*fmt) { 189 switch (*fmt) { 190 case 'c': 190 case 'c': 191 if (!(flags & LEFT)) 191 if (!(flags & LEFT)) 192 while (--field 192 while (--field_width > 0) 193 *str++ 193 *str++ = ' '; 194 *str++ = (unsigned cha 194 *str++ = (unsigned char) va_arg(args, int); 195 while (--field_width > 195 while (--field_width > 0) 196 *str++ = ' '; 196 *str++ = ' '; 197 continue; 197 continue; 198 198 199 case 's': 199 case 's': 200 s = va_arg(args, char 200 s = va_arg(args, char *); 201 if (!s) 201 if (!s) 202 s = "<NULL>"; 202 s = "<NULL>"; 203 203 204 len = strnlen(s, preci 204 len = strnlen(s, precision); 205 205 206 if (!(flags & LEFT)) 206 if (!(flags & LEFT)) 207 while (len < f 207 while (len < field_width--) 208 *str++ 208 *str++ = ' '; 209 for (i = 0; i < len; + 209 for (i = 0; i < len; ++i) 210 *str++ = *s++; 210 *str++ = *s++; 211 while (len < field_wid 211 while (len < field_width--) 212 *str++ = ' '; 212 *str++ = ' '; 213 continue; 213 continue; 214 214 215 case 'p': 215 case 'p': 216 if (field_width == -1) 216 if (field_width == -1) { 217 field_width = 217 field_width = 2*sizeof(void *); 218 flags |= ZEROP 218 flags |= ZEROPAD; 219 } 219 } 220 str = number(str, 220 str = number(str, 221 (unsigned long 221 (unsigned long) va_arg(args, void *), 16, 222 field_width, p 222 field_width, precision, flags); 223 continue; 223 continue; 224 224 225 225 226 case 'n': 226 case 'n': 227 if (qualifier == 'l') 227 if (qualifier == 'l') { 228 long * ip = va 228 long * ip = va_arg(args, long *); 229 *ip = (str - b 229 *ip = (str - buf); 230 } else if (qualifier = 230 } else if (qualifier == 'Z') { 231 size_t * ip = 231 size_t * ip = va_arg(args, size_t *); 232 *ip = (str - b 232 *ip = (str - buf); 233 } else { 233 } else { 234 int * ip = va_ 234 int * ip = va_arg(args, int *); 235 *ip = (str - b 235 *ip = (str - buf); 236 } 236 } 237 continue; 237 continue; 238 238 239 case '%': 239 case '%': 240 *str++ = '%'; 240 *str++ = '%'; 241 continue; 241 continue; 242 242 243 /* integer number formats - se 243 /* integer number formats - set up the flags and "break" */ 244 case 'o': 244 case 'o': 245 base = 8; 245 base = 8; 246 break; 246 break; 247 247 248 case 'X': 248 case 'X': 249 flags |= LARGE; 249 flags |= LARGE; 250 case 'x': 250 case 'x': 251 base = 16; 251 base = 16; 252 break; 252 break; 253 253 254 case 'd': 254 case 'd': 255 case 'i': 255 case 'i': 256 flags |= SIGN; 256 flags |= SIGN; 257 case 'u': 257 case 'u': 258 break; 258 break; 259 259 260 default: 260 default: 261 *str++ = '%'; 261 *str++ = '%'; 262 if (*fmt) 262 if (*fmt) 263 *str++ = *fmt; 263 *str++ = *fmt; 264 else 264 else 265 --fmt; 265 --fmt; 266 continue; 266 continue; 267 } 267 } 268 if (qualifier == 'l') { 268 if (qualifier == 'l') { 269 num = va_arg(args, uns 269 num = va_arg(args, unsigned long); 270 if (flags & SIGN) 270 if (flags & SIGN) 271 num = (signed 271 num = (signed long) num; 272 } else if (qualifier == 'q') { 272 } else if (qualifier == 'q') { 273 num = va_arg(args, uns 273 num = va_arg(args, unsigned long long); 274 if (flags & SIGN) 274 if (flags & SIGN) 275 num = (signed 275 num = (signed long long) num; 276 } else if (qualifier == 'Z') { 276 } else if (qualifier == 'Z') { 277 num = va_arg(args, siz 277 num = va_arg(args, size_t); 278 } else if (qualifier == 'h') { 278 } else if (qualifier == 'h') { 279 num = (unsigned short) 279 num = (unsigned short) va_arg(args, int); 280 if (flags & SIGN) 280 if (flags & SIGN) 281 num = (signed 281 num = (signed short) num; 282 } else { 282 } else { 283 num = va_arg(args, uns 283 num = va_arg(args, unsigned int); 284 if (flags & SIGN) 284 if (flags & SIGN) 285 num = (signed 285 num = (signed int) num; 286 } 286 } 287 str = number(str, num, base, f 287 str = number(str, num, base, field_width, precision, flags); 288 } 288 } 289 *str = '\0'; 289 *str = '\0'; 290 return str-buf; 290 return str-buf; 291 } 291 } 292 292 293 int sprintf(char * buf, const char *fmt, ...) 293 int sprintf(char * buf, const char *fmt, ...) 294 { 294 { 295 va_list args; 295 va_list args; 296 int i; 296 int i; 297 297 298 va_start(args, fmt); 298 va_start(args, fmt); 299 i = vsprintf(buf, fmt, args); 299 i = vsprintf(buf, fmt, args); 300 va_end(args); 300 va_end(args); 301 return i; 301 return i; 302 } 302 } 303 303
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.