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