boot2

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

vfprintf.c (6589B)


      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 <stdarg.h>
     23 #include <stdio.h>
     24 #include <string.h>
     25 
     26 int
     27 vfprintf (FILE * f, char const *format, va_list ap)
     28 {
     29   int fd = (long) f;
     30   char const *p = format;
     31   int count = 0;
     32   while (*p)
     33     if (*p != '%')
     34       {
     35         count++;
     36         fputc (*p++, f);
     37       }
     38     else
     39       {
     40         p++;
     41         char c = *p;
     42         int left_p = 0;
     43         int precision = -1;
     44         int width = -1;
     45         if (c == '-')
     46           {
     47             left_p = 1;
     48             c = *++p;
     49           }
     50         char pad = ' ';
     51         if (c == ' ')
     52           {
     53             pad = c;
     54             c = *p++;
     55           }
     56         if (c == '0')
     57           {
     58             pad = c;
     59             c = *p++;
     60           }
     61         if (c >= '0' && c <= '9')
     62           {
     63             width = abtol (&p, 10);
     64             c = *p;
     65           }
     66         else if (c == '*')
     67           {
     68             width = va_arg (ap, int);
     69             c = *++p;
     70           }
     71         if (c == '.')
     72           {
     73             c = *++p;
     74             if (c >= '0' && c <= '9')
     75               {
     76                 precision = abtol (&p, 10);
     77                 c = *p;
     78               }
     79             else if (c == '*')
     80               {
     81                 precision = va_arg (ap, int);
     82                 c = *++p;
     83               }
     84           }
     85         if (c == 'l')
     86           c = *++p;
     87         if (c == 'l')
     88           {
     89             eputs ("vfprintf: skipping second: l\n");
     90             c = *++p;
     91           }
     92         switch (c)
     93           {
     94           case '%':
     95             {
     96               fputc (*p, f);
     97               count++;
     98               break;
     99             }
    100           case 'c':
    101             {
    102               char _c;
    103               _c = va_arg (ap, long);
    104               fputc (_c, f);
    105               break;
    106             }
    107           case 'd':
    108           case 'i':
    109           case 'o':
    110           case 'u':
    111           case 'x':
    112           case 'X':
    113             {
    114               long d = va_arg (ap, long);
    115               int base = c == 'o' ? 8 : c == 'x' || c == 'X' ? 16 : 10;
    116               char *s = ntoab (d, base, c != 'u' && c != 'x' && c != 'X');
    117               if (c == 'X')
    118                 strupr (s);
    119               int length = strlen (s);
    120               if (precision == -1)
    121                 precision = length;
    122               if (!left_p)
    123                 {
    124                   while (width-- > precision)
    125                     {
    126                       fputc (pad, f);
    127                       count++;
    128                     }
    129                   while (precision > length)
    130                     {
    131                       fputc ('0', f);
    132                       precision--;
    133                       width--;
    134                       count++;
    135                     }
    136                 }
    137               while (*s)
    138                 {
    139                   if (precision-- <= 0)
    140                     break;
    141                   width--;
    142                   fputc (*s++, f);
    143                   count++;
    144                 }
    145               while (width > 0)
    146                 {
    147                   width--;
    148                   fputc (pad, f);
    149                   count++;
    150                 }
    151               break;
    152             }
    153           case 's':
    154             {
    155               char *s = va_arg (ap, char *);
    156               int length = strlen (s);
    157               if (precision == -1)
    158                 precision = length;
    159               if (!left_p)
    160                 {
    161                   while (width-- > precision)
    162                     {
    163                       fputc (pad, f);
    164                       count++;
    165                     }
    166                   while (precision > length)
    167                     {
    168                       fputc (' ', f);
    169                       precision--;
    170                       width--;
    171                       count++;
    172                     }
    173                 }
    174               while (*s)
    175                 {
    176                   if (precision-- <= 0)
    177                     break;
    178                   width--;
    179                   fputc (*s++, f);
    180                   count++;
    181                 }
    182               while (width > 0)
    183                 {
    184                   width--;
    185                   fputc (pad, f);
    186                   count++;
    187                 }
    188               break;
    189             }
    190           case 'f':
    191           case 'e':
    192           case 'E':
    193           case 'g':
    194           case 'G':
    195             {
    196               double d = va_arg8 (ap, double);
    197               char *s = dtoab (d, 10, 1);
    198               if (c == 'E' || c == 'G')
    199                 strupr (s);
    200               int length = strlen (s);
    201               if (precision == -1)
    202                 precision = length;
    203               if (!left_p)
    204                 {
    205                   while (width-- > precision)
    206                     {
    207                       fputc (pad, f);
    208                       count++;
    209                     }
    210                   while (precision > length)
    211                     {
    212                       fputc (' ', f);
    213                       precision--;
    214                       width--;
    215                       count++;
    216                     }
    217                 }
    218               while (*s)
    219                 {
    220                   if (precision-- <= 0)
    221                     break;
    222                   width--;
    223                   fputc (*s++, f);
    224                   count++;
    225                 }
    226               while (width > 0)
    227                 {
    228                   width--;
    229                   fputc (pad, f);
    230                   count++;
    231                 }
    232               break;
    233             }
    234           case 'n':
    235             {
    236               int *n = va_arg (ap, int *);
    237               *n = count;
    238               break;
    239             }
    240           default:
    241             {
    242               eputs ("vfprintf: not supported: %:");
    243               eputc (c);
    244               eputs ("\n");
    245               p++;
    246             }
    247           }
    248         p++;
    249       }
    250   va_end (ap);
    251   return 0;
    252 }