4200001 #include <stdint.h>
4200002 #include <stdbool.h>
4200003 #include <stdlib.h>
4200004 #include <string.h>
4200005 #include <stdio.h>
4200006 //----------------------------------------------------------
4200007 static size_t uimaxtoa (uintmax_t integer,
4200008 char *buffer, int base,
4200009 int uppercase, size_t size);
4200010 static size_t imaxtoa (intmax_t integer, char *buffer,
4200011 int base, int uppercase,
4200012 size_t size);
4200013 static size_t simaxtoa (intmax_t integer, char *buffer,
4200014 int base, int uppercase,
4200015 size_t size);
4200016 static size_t uimaxtoa_fill (uintmax_t integer,
4200017 char *buffer, int base,
4200018 int uppercase, int width,
4200019 int filler, int max);
4200020 static size_t imaxtoa_fill (intmax_t integer,
4200021 char *buffer, int base,
4200022 int uppercase, int width,
4200023 int filler, int max);
4200024 static size_t simaxtoa_fill (intmax_t integer,
4200025 char *buffer, int base,
4200026 int uppercase, int width,
4200027 int filler, int max);
4200028 static size_t strtostr_fill (char *string,
4200029 char *buffer, int width,
4200030 int filler, int max);
4200031 //----------------------------------------------------------
4200032 int
4200033 vsnprintf (char *restrict string, size_t size,
4200034 const char *restrict format, va_list ap)
4200035 {
4200036 //
4200037 // We produce at most `size-1' characters, + '\0'.
4200038 // `size' is used also as the max size for internal
4200039 // strings, but only if it is not too big.
4200040 //
4200041 int f = 0;
4200042 int s = 0;
4200043 int remain = size - 1;
4200044 //
4200045 bool specifier = 0;
4200046 bool specifier_flags = 0;
4200047 bool specifier_width = 0;
4200048 bool specifier_precision = 0;
4200049 bool specifier_type = 0;
4200050 //
4200051 bool flag_plus = 0;
4200052 bool flag_minus = 0;
4200053 bool flag_space = 0;
4200054 bool flag_alternate = 0;
4200055 bool flag_zero = 0;
4200056 //
4200057 int alignment;
4200058 int filler;
4200059 //
4200060 intmax_t value_i;
4200061 uintmax_t value_ui;
4200062 char *value_cp;
4200063 //
4200064 size_t width;
4200065 size_t precision;
4200066 size_t str_size =
4200067 (size > (BUFSIZ / 2) ? (BUFSIZ / 2) : size);
4200068 char width_string[str_size];
4200069 char precision_string[str_size];
4200070 int w;
4200071 int p;
4200072 //
4200073 width_string[0] = '\0';
4200074 precision_string[0] = '\0';
4200075 //
4200076 while (format[f] != 0 && s < (size - 1))
4200077 {
4200078 if (!specifier)
4200079 {
4200080 // ------------------- The context is not
4200081 // inside a specifier.
4200082 if (format[f] != '%')
4200083 {
4200084 string[s] = format[f];
4200085 s++;
4200086 remain--;
4200087 f++;
4200088 continue;
4200089 }
4200090 if (format[f] == '%' && format[f + 1] == '%')
4200091 {
4200092 string[s] = '%';
4200093 f++;
4200094 f++;
4200095 s++;
4200096 remain--;
4200097 continue;
4200098 }
4200099 if (format[f] == '%')
4200100 {
4200101 f++;
4200102 specifier = 1;
4200103 specifier_flags = 1;
4200104 continue;
4200105 }
4200106 }
4200107 //
4200108 if (specifier && specifier_flags)
4200109 {
4200110 // ------------------- The context is inside
4200111 // specifier flags.
4200112 if (format[f] == '+')
4200113 {
4200114 flag_plus = 1;
4200115 f++;
4200116 continue;
4200117 }
4200118 else if (format[f] == '-')
4200119 {
4200120 flag_minus = 1;
4200121 f++;
4200122 continue;
4200123 }
4200124 else if (format[f] == ' ')
4200125 {
4200126 flag_space = 1;
4200127 f++;
4200128 continue;
4200129 }
4200130 else if (format[f] == '#')
4200131 {
4200132 flag_alternate = 1;
4200133 f++;
4200134 continue;
4200135 }
4200136 else if (format[f] == '0')
4200137 {
4200138 flag_zero = 1;
4200139 f++;
4200140 continue;
4200141 }
4200142 else
4200143 {
4200144 specifier_flags = 0;
4200145 specifier_width = 1;
4200146 }
4200147 }
4200148 //
4200149 if (specifier && specifier_width)
4200150 {
4200151 // ------------------- The context is inside
4200152 // specifier width.
4200153 for (w = 0;
4200154 format[f] >= '0' && format[f] <= '9'
4200155 && w < str_size; w++)
4200156 {
4200157 width_string[w] = format[f];
4200158 f++;
4200159 }
4200160 width_string[w] = '\0';
4200161
4200162 specifier_width = 0;
4200163
4200164 if (format[f] == '.')
4200165 {
4200166 specifier_precision = 1;
4200167 f++;
4200168 }
4200169 else
4200170 {
4200171 specifier_precision = 0;
4200172 specifier_type = 1;
4200173 }
4200174 }
4200175 //
4200176 if (specifier && specifier_precision)
4200177 {
4200178 // --------------- The context is inside
4200179 // specifier precision.
4200180 for (p = 0;
4200181 format[f] >= '0' && format[f] <= '9'
4200182 && p < str_size; p++)
4200183 {
4200184 precision_string[p] = format[f];
4200185 p++;
4200186 }
4200187 precision_string[p] = '\0';
4200188
4200189 specifier_precision = 0;
4200190 specifier_type = 1;
4200191 }
4200192 //
4200193 if (specifier && specifier_type)
4200194 {
4200195 // -------------------- The context is
4200196 // inside specifier type.
4200197 width = atoi (width_string);
4200198 precision = atoi (precision_string);
4200199 filler = ' ';
4200200 if (flag_zero)
4200201 filler = '0';
4200202 if (flag_space)
4200203 filler = ' ';
4200204 alignment = width;
4200205 if (flag_minus)
4200206 {
4200207 alignment = -alignment;
4200208 filler = ' '; // The filler
4200209 // character cannot
4200210 // be zero, so it is black.
4200211 }
4200212 //
4200213 if (format[f] == 'h' && format[f + 1] == 'h')
4200214 {
4200215 if (format[f + 2] == 'd'
4200216 || format[f + 2] == 'i')
4200217 {
4200218 // ----------------------------
4200219 // signed char, base 10.
4200220 value_i = va_arg (ap, int);
4200221 if (flag_plus)
4200222 {
4200223 s +=
4200224 simaxtoa_fill (value_i,
4200225 &string[s], 10,
4200226 0, alignment,
4200227 filler, remain);
4200228 }
4200229 else
4200230 {
4200231 s +=
4200232 imaxtoa_fill (value_i,
4200233 &string[s], 10,
4200234 0, alignment,
4200235 filler, remain);
4200236 }
4200237 f += 3;
4200238 }
4200239 else if (format[f + 2] == 'u')
4200240 {
4200241 // --------------------------
4200242 // unsigned char, base 10.
4200243 value_ui = va_arg (ap, unsigned int);
4200244 s +=
4200245 uimaxtoa_fill (value_ui,
4200246 &string[s], 10, 0,
4200247 alignment, filler,
4200248 remain);
4200249 f += 3;
4200250 }
4200251 else if (format[f + 2] == 'o')
4200252 {
4200253 // ---------------------------
4200254 // unsigned char, base 8.
4200255 value_ui = va_arg (ap, unsigned int);
4200256 s +=
4200257 uimaxtoa_fill (value_ui,
4200258 &string[s], 8, 0,
4200259 alignment, filler,
4200260 remain);
4200261 f += 3;
4200262 }
4200263 else if (format[f + 2] == 'x')
4200264 {
4200265 // --------------------------
4200266 // unsigned char, base 16.
4200267 value_ui = va_arg (ap, unsigned int);
4200268 s +=
4200269 uimaxtoa_fill (value_ui,
4200270 &string[s], 16, 0,
4200271 alignment, filler,
4200272 remain);
4200273 f += 3;
4200274 }
4200275 else if (format[f + 2] == 'X')
4200276 {
4200277 // --------------------------
4200278 // unsigned char, base 16.
4200279 value_ui = va_arg (ap, unsigned int);
4200280 s +=
4200281 uimaxtoa_fill (value_ui,
4200282 &string[s], 16, 1,
4200283 alignment, filler,
4200284 remain);
4200285 f += 3;
4200286 }
4200287 else if (format[f + 2] == 'b')
4200288 {
4200289 // --------------- unsigned char,
4200290 // base 2 (extention).
4200291 value_ui = va_arg (ap, unsigned int);
4200292 s +=
4200293 uimaxtoa_fill (value_ui,
4200294 &string[s], 2, 0,
4200295 alignment, filler,
4200296 remain);
4200297 f += 3;
4200298 }
4200299 else
4200300 {
4200301 // ---------------- unsupported or
4200302 // unknown specifier.
4200303 f += 2;
4200304 }
4200305 }
4200306 else if (format[f] == 'h')
4200307 {
4200308 if (format[f + 1] == 'd'
4200309 || format[f + 1] == 'i')
4200310 {
4200311 // ------------------------------
4200312 // short int, base 10.
4200313 value_i = va_arg (ap, int);
4200314 if (flag_plus)
4200315 {
4200316 s +=
4200317 simaxtoa_fill (value_i,
4200318 &string[s], 10,
4200319 0, alignment,
4200320 filler, remain);
4200321 }
4200322 else
4200323 {
4200324 s +=
4200325 imaxtoa_fill (value_i,
4200326 &string[s], 10,
4200327 0, alignment,
4200328 filler, remain);
4200329 }
4200330 f += 2;
4200331 }
4200332 else if (format[f + 1] == 'u')
4200333 {
4200334 // --------------------- unsigned
4200335 // short int, base 10.
4200336 value_ui = va_arg (ap, unsigned int);
4200337 s +=
4200338 uimaxtoa_fill (value_ui,
4200339 &string[s], 10, 0,
4200340 alignment, filler,
4200341 remain);
4200342 f += 2;
4200343 }
4200344 else if (format[f + 1] == 'o')
4200345 {
4200346 // ---------------------- unsigned
4200347 // short int, base 8.
4200348 value_ui = va_arg (ap, unsigned int);
4200349 s +=
4200350 uimaxtoa_fill (value_ui,
4200351 &string[s], 8, 0,
4200352 alignment, filler,
4200353 remain);
4200354 f += 2;
4200355 }
4200356 else if (format[f + 1] == 'x')
4200357 {
4200358 // --------------------- unsigned
4200359 // short int, base 16.
4200360 value_ui = va_arg (ap, unsigned int);
4200361 s +=
4200362 uimaxtoa_fill (value_ui,
4200363 &string[s], 16, 0,
4200364 alignment, filler,
4200365 remain);
4200366 f += 2;
4200367 }
4200368 else if (format[f + 1] == 'X')
4200369 {
4200370 // --------------------- unsigned
4200371 // short int, base 16.
4200372 value_ui = va_arg (ap, unsigned int);
4200373 s +=
4200374 uimaxtoa_fill (value_ui,
4200375 &string[s], 16, 1,
4200376 alignment, filler,
4200377 remain);
4200378 f += 2;
4200379 }
4200380 else if (format[f + 1] == 'b')
4200381 {
4200382 // ---------- unsigned short int,
4200383 // base 2 (extention).
4200384 value_ui = va_arg (ap, unsigned int);
4200385 s +=
4200386 uimaxtoa_fill (value_ui,
4200387 &string[s], 2, 0,
4200388 alignment, filler,
4200389 remain);
4200390 f += 2;
4200391 }
4200392 else
4200393 {
4200394 // ---------------- unsupported or
4200395 // unknown specifier.
4200396 f += 1;
4200397 }
4200398 }
4200399 else if (format[f] == 'l' && format[f + 1] != 'l')
4200400 {
4200401 if (format[f + 1] == 'd'
4200402 || format[f + 1] == 'i')
4200403 {
4200404 // --------------------------------
4200405 // long int base 10.
4200406 value_i = va_arg (ap, long int);
4200407 if (flag_plus)
4200408 {
4200409 s +=
4200410 simaxtoa_fill (value_i,
4200411 &string[s], 10,
4200412 0, alignment,
4200413 filler, remain);
4200414 }
4200415 else
4200416 {
4200417 s +=
4200418 imaxtoa_fill (value_i,
4200419 &string[s], 10,
4200420 0, alignment,
4200421 filler, remain);
4200422 }
4200423 f += 2;
4200424 }
4200425 else if (format[f + 1] == 'u')
4200426 {
4200427 // ----------------------- Unsigned
4200428 // long int base 10.
4200429 value_ui = va_arg (ap, unsigned long int);
4200430 s +=
4200431 uimaxtoa_fill (value_ui,
4200432 &string[s], 10, 0,
4200433 alignment, filler,
4200434 remain);
4200435 f += 2;
4200436 }
4200437 else if (format[f + 1] == 'o')
4200438 {
4200439 // ------------------------ Unsigned
4200440 // long int base 8.
4200441 value_ui = va_arg (ap, unsigned long int);
4200442 s +=
4200443 uimaxtoa_fill (value_ui,
4200444 &string[s], 8, 0,
4200445 alignment, filler,
4200446 remain);
4200447 f += 2;
4200448 }
4200449 else if (format[f + 1] == 'x')
4200450 {
4200451 // ----------------------- Unsigned
4200452 // long int base 16.
4200453 value_ui = va_arg (ap, unsigned long int);
4200454 s +=
4200455 uimaxtoa_fill (value_ui,
4200456 &string[s], 16, 0,
4200457 alignment, filler,
4200458 remain);
4200459 f += 2;
4200460 }
4200461 else if (format[f + 1] == 'X')
4200462 {
4200463 // ----------------------- Unsigned
4200464 // long int base 16.
4200465 value_ui = va_arg (ap, unsigned long int);
4200466 s +=
4200467 uimaxtoa_fill (value_ui,
4200468 &string[s], 16, 1,
4200469 alignment, filler,
4200470 remain);
4200471 f += 2;
4200472 }
4200473 else if (format[f + 1] == 'b')
4200474 {
4200475 // ------------ Unsigned long int
4200476 // base 2 (extention).
4200477 value_ui = va_arg (ap, unsigned long int);
4200478 s +=
4200479 uimaxtoa_fill (value_ui,
4200480 &string[s], 2, 0,
4200481 alignment, filler,
4200482 remain);
4200483 f += 2;
4200484 }
4200485 else
4200486 {
4200487 // ---------------- unsupported or
4200488 // unknown specifier.
4200489 f += 1;
4200490 }
4200491 }
4200492 else if (format[f] == 'l' && format[f + 1] == 'l')
4200493 {
4200494 if (format[f + 2] == 'd'
4200495 || format[f + 2] == 'i')
4200496 {
4200497 // --------------------------------
4200498 // long int base 10.
4200499 value_i = va_arg (ap, long long int);
4200500 if (flag_plus)
4200501 {
4200502 s +=
4200503 simaxtoa_fill (value_i,
4200504 &string[s], 10,
4200505 0, alignment,
4200506 filler, remain);
4200507 }
4200508 else
4200509 {
4200510 s +=
4200511 imaxtoa_fill (value_i,
4200512 &string[s], 10,
4200513 0, alignment,
4200514 filler, remain);
4200515 }
4200516 f += 3;
4200517 }
4200518 else if (format[f + 2] == 'u')
4200519 {
4200520 // ----------------------- Unsigned
4200521 // long int base 10.
4200522 value_ui =
4200523 va_arg (ap, unsigned long long int);
4200524 s +=
4200525 uimaxtoa_fill (value_ui,
4200526 &string[s], 10, 0,
4200527 alignment, filler,
4200528 remain);
4200529 f += 3;
4200530 }
4200531 else if (format[f + 2] == 'o')
4200532 {
4200533 // ------------------------ Unsigned
4200534 // long int base 8.
4200535 value_ui =
4200536 va_arg (ap, unsigned long long int);
4200537 s +=
4200538 uimaxtoa_fill (value_ui,
4200539 &string[s], 8, 0,
4200540 alignment, filler,
4200541 remain);
4200542 f += 3;
4200543 }
4200544 else if (format[f + 2] == 'x')
4200545 {
4200546 // ----------------------- Unsigned
4200547 // long int base 16.
4200548 value_ui =
4200549 va_arg (ap, unsigned long long int);
4200550 s +=
4200551 uimaxtoa_fill (value_ui,
4200552 &string[s], 16, 0,
4200553 alignment, filler,
4200554 remain);
4200555 f += 3;
4200556 }
4200557 else if (format[f + 2] == 'X')
4200558 {
4200559 // ----------------------- Unsigned
4200560 // long int base 16.
4200561 value_ui =
4200562 va_arg (ap, unsigned long long int);
4200563 s +=
4200564 uimaxtoa_fill (value_ui,
4200565 &string[s], 16, 1,
4200566 alignment, filler,
4200567 remain);
4200568 f += 3;
4200569 }
4200570 else if (format[f + 2] == 'b')
4200571 {
4200572 // ------------ Unsigned long int
4200573 // base 2 (extention).
4200574 value_ui =
4200575 va_arg (ap, unsigned long long int);
4200576 s +=
4200577 uimaxtoa_fill (value_ui,
4200578 &string[s], 2, 0,
4200579 alignment, filler,
4200580 remain);
4200581 f += 3;
4200582 }
4200583 else
4200584 {
4200585 // ---------------- unsupported or
4200586 // unknown specifier.
4200587 f += 2;
4200588 }
4200589 }
4200590 else if (format[f] == 'j')
4200591 {
4200592 if (format[f + 1] == 'd'
4200593 || format[f + 1] == 'i')
4200594 {
4200595 // --------------------------------
4200596 // intmax_t base 10.
4200597 value_i = va_arg (ap, intmax_t);
4200598 if (flag_plus)
4200599 {
4200600 s +=
4200601 simaxtoa_fill (value_i,
4200602 &string[s], 10,
4200603 0, alignment,
4200604 filler, remain);
4200605 }
4200606 else
4200607 {
4200608 s +=
4200609 imaxtoa_fill (value_i,
4200610 &string[s], 10,
4200611 0, alignment,
4200612 filler, remain);
4200613 }
4200614 f += 2;
4200615 }
4200616 else if (format[f + 1] == 'u')
4200617 {
4200618 // -------------------------------
4200619 // uintmax_t base 10.
4200620 value_ui = va_arg (ap, uintmax_t);
4200621 s +=
4200622 uimaxtoa_fill (value_ui,
4200623 &string[s], 10, 0,
4200624 alignment, filler,
4200625 remain);
4200626 f += 2;
4200627 }
4200628 else if (format[f + 1] == 'o')
4200629 {
4200630 // --------------------------------
4200631 // uintmax_t base 8.
4200632 value_ui = va_arg (ap, uintmax_t);
4200633 s +=
4200634 uimaxtoa_fill (value_ui,
4200635 &string[s], 8, 0,
4200636 alignment, filler,
4200637 remain);
4200638 f += 2;
4200639 }
4200640 else if (format[f + 1] == 'x')
4200641 {
4200642 // -------------------------------
4200643 // uintmax_t base 16.
4200644 value_ui = va_arg (ap, uintmax_t);
4200645 s +=
4200646 uimaxtoa_fill (value_ui,
4200647 &string[s], 16, 0,
4200648 alignment, filler,
4200649 remain);
4200650 f += 2;
4200651 }
4200652 else if (format[f + 1] == 'X')
4200653 {
4200654 // -------------------------------
4200655 // uintmax_t base 16.
4200656 value_ui = va_arg (ap, uintmax_t);
4200657 s +=
4200658 uimaxtoa_fill (value_ui,
4200659 &string[s], 16, 1,
4200660 alignment, filler,
4200661 remain);
4200662 f += 2;
4200663 }
4200664 else if (format[f + 1] == 'b')
4200665 {
4200666 // -------------------- uintmax_t
4200667 // base 2 (extention).
4200668 value_ui = va_arg (ap, uintmax_t);
4200669 s +=
4200670 uimaxtoa_fill (value_ui,
4200671 &string[s], 2, 0,
4200672 alignment, filler,
4200673 remain);
4200674 f += 2;
4200675 }
4200676 else
4200677 {
4200678 // ---------------- unsupported or
4200679 // unknown specifier.
4200680 f += 1;
4200681 }
4200682 }
4200683 else if (format[f] == 'z')
4200684 {
4200685 if (format[f + 1] == 'd'
4200686 || format[f + 1] == 'i'
4200687 || format[f + 1] == 'i')
4200688 {
4200689 // ----------------- size_t base 10.
4200690 value_ui = va_arg (ap, unsigned long int);
4200691 s +=
4200692 uimaxtoa_fill (value_ui,
4200693 &string[s], 10, 0,
4200694 alignment, filler,
4200695 remain);
4200696 f += 2;
4200697 }
4200698 else if (format[f + 1] == 'o')
4200699 {
4200700 // ------------------ size_t base 8.
4200701 value_ui = va_arg (ap, unsigned long int);
4200702 s +=
4200703 uimaxtoa_fill (value_ui,
4200704 &string[s], 8, 0,
4200705 alignment, filler,
4200706 remain);
4200707 f += 2;
4200708 }
4200709 else if (format[f + 1] == 'x')
4200710 {
4200711 // ----------------- size_t base 16.
4200712 value_ui = va_arg (ap, unsigned long int);
4200713 s +=
4200714 uimaxtoa_fill (value_ui,
4200715 &string[s], 16, 0,
4200716 alignment, filler,
4200717 remain);
4200718 f += 2;
4200719 }
4200720 else if (format[f + 1] == 'X')
4200721 {
4200722 // ----------------- size_t base 16.
4200723 value_ui = va_arg (ap, unsigned long int);
4200724 s +=
4200725 uimaxtoa_fill (value_ui,
4200726 &string[s], 16, 1,
4200727 alignment, filler,
4200728 remain);
4200729 f += 2;
4200730 }
4200731 else if (format[f + 1] == 'b')
4200732 {
4200733 // ----------------------- size_t
4200734 // base 2 (extention).
4200735 value_ui = va_arg (ap, unsigned long int);
4200736 s +=
4200737 uimaxtoa_fill (value_ui,
4200738 &string[s], 2, 0,
4200739 alignment, filler,
4200740 remain);
4200741 f += 2;
4200742 }
4200743 else
4200744 {
4200745 // ---------------- unsupported or
4200746 // unknown specifier.
4200747 f += 1;
4200748 }
4200749 }
4200750 else if (format[f] == 't')
4200751 {
4200752 if (format[f + 1] == 'd'
4200753 || format[f + 1] == 'i')
4200754 {
4200755 // -------------------------------
4200756 // ptrdiff_t base 10.
4200757 value_i = va_arg (ap, long int);
4200758 if (flag_plus)
4200759 {
4200760 s +=
4200761 simaxtoa_fill (value_i,
4200762 &string[s], 10,
4200763 0, alignment,
4200764 filler, remain);
4200765 }
4200766 else
4200767 {
4200768 s +=
4200769 imaxtoa_fill (value_i,
4200770 &string[s], 10,
4200771 0, alignment,
4200772 filler, remain);
4200773 }
4200774 f += 2;
4200775 }
4200776 else if (format[f + 1] == 'u')
4200777 {
4200778 // ----------------- ptrdiff_t base
4200779 // 10, without sign.
4200780 value_ui = va_arg (ap, unsigned long int);
4200781 s +=
4200782 uimaxtoa_fill (value_ui,
4200783 &string[s], 10, 0,
4200784 alignment, filler,
4200785 remain);
4200786 f += 2;
4200787 }
4200788 else if (format[f + 1] == 'o')
4200789 {
4200790 // ------------------ ptrdiff_t base
4200791 // 8, without sign.
4200792 value_ui = va_arg (ap, unsigned long int);
4200793 s +=
4200794 uimaxtoa_fill (value_ui,
4200795 &string[s], 8, 0,
4200796 alignment, filler,
4200797 remain);
4200798 f += 2;
4200799 }
4200800 else if (format[f + 1] == 'x')
4200801 {
4200802 // ----------------- ptrdiff_t base
4200803 // 16, without sign.
4200804 value_ui = va_arg (ap, unsigned long int);
4200805 s +=
4200806 uimaxtoa_fill (value_ui,
4200807 &string[s], 16, 0,
4200808 alignment, filler,
4200809 remain);
4200810 f += 2;
4200811 }
4200812 else if (format[f + 1] == 'X')
4200813 {
4200814 // ----------------- ptrdiff_t base
4200815 // 16, without sign.
4200816 value_ui = va_arg (ap, unsigned long int);
4200817 s +=
4200818 uimaxtoa_fill (value_ui,
4200819 &string[s], 16, 1,
4200820 alignment, filler,
4200821 remain);
4200822 f += 2;
4200823 }
4200824 else if (format[f + 1] == 'b')
4200825 {
4200826 // ------ ptrdiff_t base 2, without
4200827 // sign (extention).
4200828 value_ui = va_arg (ap, unsigned long int);
4200829 s +=
4200830 uimaxtoa_fill (value_ui,
4200831 &string[s], 2, 0,
4200832 alignment, filler,
4200833 remain);
4200834 f += 2;
4200835 }
4200836 else
4200837 {
4200838 // ---------------- unsupported or
4200839 // unknown specifier.
4200840 f += 1;
4200841 }
4200842 }
4200843 if (format[f] == 'd' || format[f] == 'i')
4200844 {
4200845 // ------------------------ int base 10.
4200846 value_i = va_arg (ap, int);
4200847 if (flag_plus)
4200848 {
4200849 s +=
4200850 simaxtoa_fill (value_i, &string[s],
4200851 10, 0, alignment,
4200852 filler, remain);
4200853 }
4200854 else
4200855 {
4200856 s +=
4200857 imaxtoa_fill (value_i, &string[s],
4200858 10, 0, alignment,
4200859 filler, remain);
4200860 }
4200861 f += 1;
4200862 }
4200863 else if (format[f] == 'u')
4200864 {
4200865 // --------------------------------
4200866 // unsigned int base 10.
4200867 value_ui = va_arg (ap, unsigned int);
4200868 s +=
4200869 uimaxtoa_fill (value_ui, &string[s],
4200870 10, 0, alignment,
4200871 filler, remain);
4200872 f += 1;
4200873 }
4200874 else if (format[f] == 'o')
4200875 {
4200876 // ---------------- unsigned int base 8.
4200877 value_ui = va_arg (ap, unsigned int);
4200878 s +=
4200879 uimaxtoa_fill (value_ui, &string[s], 8,
4200880 0, alignment, filler,
4200881 remain);
4200882 f += 1;
4200883 }
4200884 else if (format[f] == 'x')
4200885 {
4200886 // --------------------------------
4200887 // unsigned int base 16.
4200888 value_ui = va_arg (ap, unsigned int);
4200889 s +=
4200890 uimaxtoa_fill (value_ui, &string[s],
4200891 16, 0, alignment,
4200892 filler, remain);
4200893 f += 1;
4200894 }
4200895 else if (format[f] == 'X')
4200896 {
4200897 // --------------------------------
4200898 // unsigned int base 16.
4200899 value_ui = va_arg (ap, unsigned int);
4200900 s +=
4200901 uimaxtoa_fill (value_ui, &string[s],
4200902 16, 1, alignment,
4200903 filler, remain);
4200904 f += 1;
4200905 }
4200906 else if (format[f] == 'b')
4200907 {
4200908 // --------------------- unsigned int
4200909 // base 2 (extention).
4200910 value_ui = va_arg (ap, unsigned int);
4200911 s +=
4200912 uimaxtoa_fill (value_ui, &string[s], 2,
4200913 0, alignment, filler,
4200914 remain);
4200915 f += 1;
4200916 }
4200917 else if (format[f] == 'c')
4200918 {
4200919 // ---------------------- unsigned char.
4200920 value_ui = va_arg (ap, unsigned int);
4200921 string[s] = (char) value_ui;
4200922 s += 1;
4200923 f += 1;
4200924 }
4200925 else if (format[f] == 's')
4200926 {
4200927 // ----------------------------- string.
4200928 value_cp = va_arg (ap, char *);
4200929 filler = ' ';
4200930
4200931 s +=
4200932 strtostr_fill (value_cp, &string[s],
4200933 alignment, filler, remain);
4200934 f += 1;
4200935 }
4200936 else
4200937 {
4200938 // -------------------- unsupported or
4200939 // unknown specifier.
4200940 ;
4200941 }
4200942 // -----------------------------------------
4200943 // End of specifier.
4200944 // -----------------------------------------
4200945 width_string[0] = '\0';
4200946 precision_string[0] = '\0';
4200947
4200948 specifier = 0;
4200949 specifier_flags = 0;
4200950 specifier_width = 0;
4200951 specifier_precision = 0;
4200952 specifier_type = 0;
4200953
4200954 flag_plus = 0;
4200955 flag_minus = 0;
4200956 flag_space = 0;
4200957 flag_alternate = 0;
4200958 flag_zero = 0;
4200959 }
4200960 }
4200961 string[s] = '\0';
4200962 return s;
4200963 }
4200964
4200965 //----------------------------------------------------------
4200966 // Static functions.
4200967 //----------------------------------------------------------
4200968 static size_t
4200969 uimaxtoa (uintmax_t integer, char *buffer, int base,
4200970 int uppercase, size_t size)
4200971 {
4200972 // -------------------------------------------------
4200973 // Convert a maximum rank integer into a string.
4200974 // -------------------------------------------------
4200975
4200976 uintmax_t integer_copy = integer;
4200977 size_t digits;
4200978 int b;
4200979 unsigned char remainder;
4200980
4200981 for (digits = 0; integer_copy > 0; digits++)
4200982 {
4200983 integer_copy = integer_copy / base;
4200984 }
4200985
4200986 if (buffer == NULL && integer == 0)
4200987 return 1;
4200988 if (buffer == NULL && integer > 0)
4200989 return digits;
4200990
4200991 if (integer == 0)
4200992 {
4200993 buffer[0] = '0';
4200994 buffer[1] = '\0';
4200995 return 1;
4200996 }
4200997 //
4200998 // Fix the maximum number of digits.
4200999 //
4201000 if (size > 0 && digits > size)
4201001 digits = size;
4201002 //
4201003 *(buffer + digits) = '\0'; // End of string.
4201004
4201005 for (b = digits - 1; integer != 0 && b >= 0; b--)
4201006 {
4201007 remainder = integer % base;
4201008 integer = integer / base;
4201009
4201010 if (remainder <= 9)
4201011 {
4201012 *(buffer + b) = remainder + '0';
4201013 }
4201014 else
4201015 {
4201016 if (uppercase)
4201017 {
4201018 *(buffer + b) = remainder - 10 + 'A';
4201019 }
4201020 else
4201021 {
4201022 *(buffer + b) = remainder - 10 + 'a';
4201023 }
4201024 }
4201025 }
4201026 return digits;
4201027 }
4201028
4201029 //----------------------------------------------------------
4201030 static size_t
4201031 imaxtoa (intmax_t integer, char *buffer, int base,
4201032 int uppercase, size_t size)
4201033 {
4201034 // -------------------------------------------------
4201035 // Convert a maximum rank integer with sign into a
4201036 // string.
4201037 // -------------------------------------------------
4201038
4201039 if (integer >= 0)
4201040 {
4201041 return uimaxtoa (integer, buffer, base,
4201042 uppercase, size);
4201043 }
4201044 //
4201045 // At this point, there is a negative number, less
4201046 // than zero.
4201047 //
4201048 if (buffer == NULL)
4201049 {
4201050 return uimaxtoa (-integer, NULL, base, uppercase,
4201051 size) + 1;
4201052 }
4201053
4201054 *buffer = '-'; // The minus sign is needed at
4201055 // the beginning.
4201056 if (size == 1)
4201057 {
4201058 *(buffer + 1) = '\0';
4201059 return 1;
4201060 }
4201061 else
4201062 {
4201063 return uimaxtoa (-integer, buffer + 1, base,
4201064 uppercase, size - 1) + 1;
4201065 }
4201066 }
4201067
4201068 //----------------------------------------------------------
4201069 static size_t
4201070 simaxtoa (intmax_t integer, char *buffer, int base,
4201071 int uppercase, size_t size)
4201072 {
4201073 // -------------------------------------------------
4201074 // Convert a maximum rank integer with sign into a
4201075 // string, placing
4201076 // the sign also if it is positive.
4201077 // -------------------------------------------------
4201078
4201079 if (buffer == NULL && integer >= 0)
4201080 {
4201081 return uimaxtoa (integer, NULL, base, uppercase,
4201082 size) + 1;
4201083 }
4201084
4201085 if (buffer == NULL && integer < 0)
4201086 {
4201087 return uimaxtoa (-integer, NULL, base, uppercase,
4201088 size) + 1;
4201089 }
4201090 //
4201091 // At this point, `buffer' is different from NULL.
4201092 //
4201093 if (integer >= 0)
4201094 {
4201095 *buffer = '+';
4201096 }
4201097 else
4201098 {
4201099 *buffer = '-';
4201100 }
4201101
4201102 if (size == 1)
4201103 {
4201104 *(buffer + 1) = '\0';
4201105 return 1;
4201106 }
4201107
4201108 if (integer >= 0)
4201109 {
4201110 return uimaxtoa (integer, buffer + 1, base,
4201111 uppercase, size - 1) + 1;
4201112 }
4201113 else
4201114 {
4201115 return uimaxtoa (-integer, buffer + 1, base,
4201116 uppercase, size - 1) + 1;
4201117 }
4201118 }
4201119
4201120 //----------------------------------------------------------
4201121 static size_t
4201122 uimaxtoa_fill (uintmax_t integer, char *buffer,
4201123 int base, int uppercase, int width,
4201124 int filler, int max)
4201125 {
4201126 // -------------------------------------------------
4201127 // Convert a maximum rank integer without sign into
4201128 // a string,
4201129 // takeing care of the alignment.
4201130 // -------------------------------------------------
4201131
4201132 size_t size_i;
4201133 size_t size_f;
4201134
4201135 if (max < 0)
4201136 return 0; // «max» deve essere un valore
4201137 // positivo.
4201138
4201139 size_i = uimaxtoa (integer, NULL, base, uppercase, 0);
4201140
4201141 if (width > 0 && max > 0 && width > max)
4201142 width = max;
4201143 if (width < 0 && -max < 0 && width < -max)
4201144 width = -max;
4201145
4201146 if (size_i > abs (width))
4201147 {
4201148 return uimaxtoa (integer, buffer, base,
4201149 uppercase, abs (width));
4201150 }
4201151
4201152 if (width == 0 && max > 0)
4201153 {
4201154 return uimaxtoa (integer, buffer, base,
4201155 uppercase, max);
4201156 }
4201157
4201158 if (width == 0)
4201159 {
4201160 return uimaxtoa (integer, buffer, base,
4201161 uppercase, abs (width));
4201162 }
4201163 //
4201164 // size_i <= abs (width).
4201165 //
4201166 size_f = abs (width) - size_i;
4201167
4201168 if (width < 0)
4201169 {
4201170 // Left alignment.
4201171 uimaxtoa (integer, buffer, base, uppercase, 0);
4201172 memset (buffer + size_i, filler, size_f);
4201173 }
4201174 else
4201175 {
4201176 // Right alignment.
4201177 memset (buffer, filler, size_f);
4201178 uimaxtoa (integer, buffer + size_f, base,
4201179 uppercase, 0);
4201180 }
4201181 *(buffer + abs (width)) = '\0';
4201182
4201183 return abs (width);
4201184 }
4201185
4201186 //----------------------------------------------------------
4201187 static size_t
4201188 imaxtoa_fill (intmax_t integer, char *buffer, int base,
4201189 int uppercase, int width, int filler, int max)
4201190 {
4201191 // -------------------------------------------------
4201192 // Convert a maximum rank integer with sign into a
4201193 // string,
4201194 // takeing care of the alignment.
4201195 // -------------------------------------------------
4201196
4201197 size_t size_i;
4201198 size_t size_f;
4201199
4201200 if (max < 0)
4201201 return 0; // `max' must be a positive value.
4201202
4201203 size_i = imaxtoa (integer, NULL, base, uppercase, 0);
4201204
4201205 if (width > 0 && max > 0 && width > max)
4201206 width = max;
4201207 if (width < 0 && -max < 0 && width < -max)
4201208 width = -max;
4201209
4201210 if (size_i > abs (width))
4201211 {
4201212 return imaxtoa (integer, buffer, base, uppercase,
4201213 abs (width));
4201214 }
4201215
4201216 if (width == 0 && max > 0)
4201217 {
4201218 return imaxtoa (integer, buffer, base, uppercase,
4201219 max);
4201220 }
4201221
4201222 if (width == 0)
4201223 {
4201224 return imaxtoa (integer, buffer, base, uppercase,
4201225 abs (width));
4201226 }
4201227
4201228 // size_i <= abs (width).
4201229
4201230 size_f = abs (width) - size_i;
4201231
4201232 if (width < 0)
4201233 {
4201234 // Left alignment.
4201235 imaxtoa (integer, buffer, base, uppercase, 0);
4201236 memset (buffer + size_i, filler, size_f);
4201237 }
4201238 else
4201239 {
4201240 // Right alignment.
4201241 memset (buffer, filler, size_f);
4201242 imaxtoa (integer, buffer + size_f, base,
4201243 uppercase, 0);
4201244 }
4201245 *(buffer + abs (width)) = '\0';
4201246
4201247 return abs (width);
4201248 }
4201249
4201250 //----------------------------------------------------------
4201251 static size_t
4201252 simaxtoa_fill (intmax_t integer, char *buffer,
4201253 int base, int uppercase, int width,
4201254 int filler, int max)
4201255 {
4201256 // -------------------------------------------------
4201257 // Convert a maximum rank integer with sign into a
4201258 // string,
4201259 // placing the sign also if it is positive and
4201260 // takeing care of the
4201261 // alignment.
4201262 // -------------------------------------------------
4201263
4201264 size_t size_i;
4201265 size_t size_f;
4201266
4201267 if (max < 0)
4201268 return 0; // `max' must be a positive value.
4201269
4201270 size_i = simaxtoa (integer, NULL, base, uppercase, 0);
4201271
4201272 if (width > 0 && max > 0 && width > max)
4201273 width = max;
4201274 if (width < 0 && -max < 0 && width < -max)
4201275 width = -max;
4201276
4201277 if (size_i > abs (width))
4201278 {
4201279 return simaxtoa (integer, buffer, base,
4201280 uppercase, abs (width));
4201281 }
4201282
4201283 if (width == 0 && max > 0)
4201284 {
4201285 return simaxtoa (integer, buffer, base,
4201286 uppercase, max);
4201287 }
4201288
4201289 if (width == 0)
4201290 {
4201291 return simaxtoa (integer, buffer, base,
4201292 uppercase, abs (width));
4201293 }
4201294 //
4201295 // size_i <= abs (width).
4201296 //
4201297 size_f = abs (width) - size_i;
4201298
4201299 if (width < 0)
4201300 {
4201301 // Left alignment.
4201302 simaxtoa (integer, buffer, base, uppercase, 0);
4201303 memset (buffer + size_i, filler, size_f);
4201304 }
4201305 else
4201306 {
4201307 // Right alignment.
4201308 memset (buffer, filler, size_f);
4201309 simaxtoa (integer, buffer + size_f, base,
4201310 uppercase, 0);
4201311 }
4201312 *(buffer + abs (width)) = '\0';
4201313
4201314 return abs (width);
4201315 }
4201316
4201317 //----------------------------------------------------------
4201318 static size_t
4201319 strtostr_fill (char *string, char *buffer, int width,
4201320 int filler, int max)
4201321 {
4201322 // -------------------------------------------------
4201323 // Transfer a string with care for the alignment.
4201324 // -------------------------------------------------
4201325
4201326 size_t size_s;
4201327 size_t size_f;
4201328
4201329 if (max < 0)
4201330 return 0; // `max' must be a positive value.
4201331
4201332 size_s = strlen (string);
4201333
4201334 if (width > 0 && max > 0 && width > max)
4201335 width = max;
4201336 if (width < 0 && -max < 0 && width < -max)
4201337 width = -max;
4201338
4201339 if (width != 0 && size_s > abs (width))
4201340 {
4201341 memcpy (buffer, string, abs (width));
4201342 buffer[width] = '\0';
4201343 return width;
4201344 }
4201345
4201346 if (width == 0 && max > 0 && size_s > max)
4201347 {
4201348 memcpy (buffer, string, max);
4201349 buffer[max] = '\0';
4201350 return max;
4201351 }
4201352
4201353 if (width == 0 && max > 0 && size_s < max)
4201354 {
4201355 memcpy (buffer, string, size_s);
4201356 buffer[size_s] = '\0';
4201357 return size_s;
4201358 }
4201359 //
4201360 // width =! 0
4201361 // size_s <= abs (width)
4201362 //
4201363 size_f = abs (width) - size_s;
4201364
4201365 if (width < 0)
4201366 {
4201367 // Right alignment.
4201368 memset (buffer, filler, size_f);
4201369 strncpy (buffer + size_f, string, size_s);
4201370 }
4201371 else
4201372 {
4201373 // Left alignment.
4201374 strncpy (buffer, string, size_s);
4201375 memset (buffer + size_s, filler, size_f);
4201376 }
4201377 *(buffer + abs (width)) = '\0';
4201378
4201379 return abs (width);
4201380 }
|