| 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 }
 |