| 283 | static int convert(UINTMAX_T, char *, size_t, int, int); |
| 284 | |
| 285 | int vsnprintf(char *str, size_t size, const char *format, va_list args) |
| 286 | { |
| 287 | if (!format) |
| 288 | return 0; |
| 289 | |
| 290 | INTMAX_T value; |
| 291 | unsigned char cvalue; |
| 292 | const char *strvalue; |
| 293 | INTMAX_T *intmaxptr; |
| 294 | PTRDIFF_T *ptrdiffptr; |
| 295 | SSIZE_T *sizeptr; |
| 296 | LLONG *llongptr; |
| 297 | long int *longptr; |
| 298 | int *intptr; |
| 299 | short int *shortptr; |
| 300 | signed char *charptr; |
| 301 | size_t len = 0; |
| 302 | int overflow = 0; |
| 303 | int base = 0; |
| 304 | int cflags = 0; |
| 305 | int flags = 0; |
| 306 | int width = 0; |
| 307 | int precision = -1; |
| 308 | int state = PRINT_S_DEFAULT; |
| 309 | char ch = *format++; |
| 310 | |
| 311 | /* |
| 312 | * C99 says: "If `n' is zero, nothing is written, and `s' may be a null |
| 313 | * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer |
| 314 | * even if a size larger than zero was specified. At least NetBSD's |
| 315 | * snprintf(3) does the same, as well as other versions of this file. |
| 316 | * (Though some of these versions will write to a non-NULL buffer even |
| 317 | * if a size of zero was specified, which violates the standard.) |
| 318 | */ |
| 319 | if ((str == NULL) && (size != 0)) |
| 320 | size = 0; |
| 321 | |
| 322 | while (ch != '\0') |
| 323 | switch (state) { |
| 324 | case PRINT_S_DEFAULT: |
| 325 | if (ch == '%') |
| 326 | state = PRINT_S_FLAGS; |
| 327 | else |
| 328 | OUTCHAR(str, len, size, ch); |
| 329 | ch = *format++; |
| 330 | break; |
| 331 | case PRINT_S_FLAGS: |
| 332 | switch (ch) { |
| 333 | case '-': |
| 334 | flags |= PRINT_F_MINUS; |
| 335 | ch = *format++; |
| 336 | break; |
| 337 | case '+': |
| 338 | flags |= PRINT_F_PLUS; |
| 339 | ch = *format++; |
| 340 | break; |
| 341 | case ' ': |
| 342 | flags |= PRINT_F_SPACE; |