boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

vsnprintf.c (7315B)


      1 /* -*-comment-start: "//";comment-end:""-*-
      2  * GNU Mes --- Maxwell Equations of Software
      3  * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
      4  *
      5  * This file is part of GNU Mes.
      6  *
      7  * GNU Mes is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 3 of the License, or (at
     10  * your option) any later version.
     11  *
     12  * GNU Mes is distributed in the hope that it will be useful, but
     13  * WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include <mes/lib.h>
     22 #include <ctype.h>
     23 #include <stdarg.h>
     24 #include <string.h>
     25 
     26 int
     27 vsnprintf (char *str, size_t size, char const *format, va_list ap)
     28 {
     29   char const *p = format;
     30   int count = 0;
     31   char c;
     32   while (*p)
     33     if (*p != '%')
     34       {
     35         c = *p++;
     36         if (count < size)
     37           *str++ = c;
     38         count++;
     39       }
     40     else
     41       {
     42         p++;
     43         c = *p;
     44         int left_p = 0;
     45         int precision = -1;
     46         int width = -1;
     47         if (c == '-')
     48           {
     49             left_p = 1;
     50             c = *++p;
     51           }
     52         char pad = ' ';
     53         if (c == ' ')
     54           {
     55             pad = c;
     56             c = *p++;
     57           }
     58         if (c == '0')
     59           {
     60             pad = c;
     61             c = *p++;
     62           }
     63         if (c >= '0' && c <= '9')
     64           {
     65             width = abtol (&p, 10);
     66             c = *p;
     67           }
     68         else if (c == '*')
     69           {
     70             width = va_arg (ap, long);
     71             c = *++p;
     72           }
     73         if (c == '.')
     74           {
     75             c = *++p;
     76             if (c >= '0' && c <= '9')
     77               {
     78                 precision = abtol (&p, 10);
     79                 c = *p;
     80               }
     81             else if (c == '*')
     82               {
     83                 precision = va_arg (ap, long);
     84                 c = *++p;
     85               }
     86           }
     87         if (c == 'l')
     88           c = *++p;
     89         if (c == 'l')
     90           c = *++p;
     91         if (c == 'l')
     92           {
     93             eputs ("vsnprintf: skipping second: l\n");
     94             c = *++p;
     95           }
     96         switch (c)
     97           {
     98           case '%':
     99             {
    100               if (count < size)
    101                 *str++ = *p;
    102               count++;
    103               break;
    104             }
    105           case 'c':
    106             {
    107               c = va_arg (ap, long);
    108               if (count < size)
    109                 *str++ = c;
    110               count++;
    111               break;
    112             }
    113           case 'd':
    114           case 'i':
    115           case 'o':
    116           case 'u':
    117           case 'x':
    118           case 'X':
    119             {
    120               long d = va_arg (ap, long);
    121               int base = c == 'o' ? 8 : c == 'x' || c == 'X' ? 16 : 10;
    122               char *s = ntoab (d, base, c != 'u' && c != 'x' && c != 'X');
    123               if (c == 'X')
    124                 strupr (s);
    125               int length = strlen (s);
    126               if (precision == -1)
    127                 precision = length;
    128               if (!left_p)
    129                 {
    130                   while (width-- > precision)
    131                     {
    132                       if (count < size)
    133                         *str++ = pad;
    134                       count++;
    135                     }
    136                   while (precision > length)
    137                     {
    138                       if (count < size)
    139                         *str++ = '0';
    140                       precision--;
    141                       width--;
    142                       count++;
    143                     }
    144                 }
    145               while (*s)
    146                 {
    147                   if (precision-- <= 0)
    148                     break;
    149                   width--;
    150                   c = *s++;
    151                   if (count < size)
    152                     *str++ = c;
    153                   count++;
    154                 }
    155               while (width > 0)
    156                 {
    157                   width--;
    158                   if (count < size)
    159                     *str++ = pad;
    160                   count++;
    161                 }
    162               break;
    163             }
    164           case 's':
    165             {
    166               char *s = va_arg (ap, char *);
    167               int length = s ? strlen (s) : 0;
    168               if (precision == -1)
    169                 precision = length;
    170               if (!left_p)
    171                 {
    172                   while (width-- > precision)
    173                     {
    174                       if (count < size)
    175                         *str++ = pad;
    176                       count++;
    177                     }
    178                   while (width > length)
    179                     {
    180                       if (count < size)
    181                         *str++ = ' ';
    182                       precision--;
    183                       width--;
    184                       count++;
    185                     }
    186                 }
    187               while (s && *s)
    188                 {
    189                   if (precision-- <= 0)
    190                     break;
    191                   width--;
    192                   c = *s++;
    193                   if (count < size)
    194                     *str++ = c;
    195                   count++;
    196                 }
    197               while (width > 0)
    198                 {
    199                   width--;
    200                   if (count < size)
    201                     *str++ = pad;
    202                   count++;
    203                 }
    204               break;
    205             }
    206           case 'f':
    207           case 'e':
    208           case 'E':
    209           case 'g':
    210           case 'G':
    211             {
    212               double d = va_arg8 (ap, double);
    213               char *s = dtoab (d, 10, 1);
    214               if (c == 'E' || c == 'G')
    215                 strupr (s);
    216               int length = strlen (s);
    217               if (precision == -1)
    218                 precision = length;
    219               if (!left_p)
    220                 {
    221                   while (width-- > precision)
    222                     {
    223                       if (count < size)
    224                         *str++ = pad;
    225                       count++;
    226                     }
    227                   while (precision > length)
    228                     {
    229                       if (count < size)
    230                         *str++ = ' ';
    231                       precision--;
    232                       width--;
    233                       count++;
    234                     }
    235                 }
    236               while (*s)
    237                 {
    238                   if (precision-- <= 0)
    239                     break;
    240                   width--;
    241                   c = *s++;
    242                   if (count < size)
    243                     *str++ = c;
    244                   count++;
    245                 }
    246               while (width > 0)
    247                 {
    248                   width--;
    249                   if (count < size)
    250                     *str++ = pad;
    251                   count++;
    252                 }
    253               break;
    254             }
    255           case 'n':
    256             {
    257               int *n = va_arg (ap, int *);
    258               *n = count;
    259               break;
    260             }
    261           default:
    262             {
    263               eputs ("vsnprintf: not supported: %:");
    264               eputc (c);
    265               eputs ("\n");
    266               p++;
    267             }
    268           }
    269         p++;
    270       }
    271   va_end (ap);
    272   if (count < size)
    273     *str = 0;
    274   return count;
    275 }