Changes in / [c7c6afd:240b2e4] in mainline


Ignore:
Files:
8 added
2 deleted
20 edited

Legend:

Unmodified
Added
Removed
  • boot/arch/arm32/meson.build

    rc7c6afd r240b2e4  
    6666        'src/putchar.c',
    6767        '../../../common/stdc/mem.c',
    68         '../../../common/printf/printf_core.c',
    6968        '../../genarch/src/division.c',
     69        '../../generic/src/printf_core.c',
    7070        '../../generic/src/vprintf.c',
    7171        '../../generic/src/printf.c',
  • boot/arch/arm64/meson.build

    rc7c6afd r240b2e4  
    4949        'src/relocate.c',
    5050        '../../../common/stdc/mem.c',
    51         '../../../common/printf/printf_core.c',
    5251        '../../genarch/src/efi.c',
    5352        '../../generic/src/gzip.c',
     
    5655        '../../generic/src/payload.c',
    5756        '../../generic/src/printf.c',
     57        '../../generic/src/printf_core.c',
    5858        '../../../common/str.c',
    5959        '../../generic/src/tar.c',
  • boot/arch/ia64/meson.build

    rc7c6afd r240b2e4  
    4545        '../../genarch/src/division.c',
    4646        '../../generic/src/balloc.c',
    47         '../../../common/printf/printf_core.c',
     47        '../../generic/src/printf_core.c',
    4848        '../../generic/src/vprintf.c',
    4949        '../../generic/src/printf.c',
  • boot/arch/mips32/meson.build

    rc7c6afd r240b2e4  
    4545        '../../genarch/src/division.c',
    4646        '../../genarch/src/multiplication.c',
    47         '../../../common/printf/printf_core.c',
     47        '../../generic/src/printf_core.c',
    4848        '../../generic/src/vprintf.c',
    4949        '../../generic/src/printf.c',
  • boot/arch/ppc32/meson.build

    rc7c6afd r240b2e4  
    4343        '../../genarch/src/multiplication.c',
    4444        '../../generic/src/balloc.c',
    45         '../../../common/printf/printf_core.c',
     45        '../../generic/src/printf_core.c',
    4646        '../../generic/src/vprintf.c',
    4747        '../../generic/src/printf.c',
  • boot/arch/riscv64/meson.build

    rc7c6afd r240b2e4  
    3939
    4040        '../../../common/stdc/mem.c',
    41         '../../../common/printf/printf_core.c',
     41        '../../generic/src/printf_core.c',
    4242        '../../generic/src/vprintf.c',
    4343        '../../generic/src/printf.c',
  • boot/arch/sparc64/meson.build

    rc7c6afd r240b2e4  
    4141        '../../genarch/src/ofw_tree.c',
    4242        '../../generic/src/balloc.c',
    43         '../../../common/printf/printf_core.c',
     43        '../../generic/src/printf_core.c',
    4444        '../../generic/src/vprintf.c',
    4545        '../../generic/src/printf.c',
  • boot/generic/include/macros.h

    rc7c6afd r240b2e4  
    3434
    3535#define min(a, b)  ((a) < (b) ? (a) : (b))
    36 #define max(a, b)  ((a) > (b) ? (a) : (b))
    3736
    3837#define isdigit(d)  (((d) >= '0') && ((d) <= '9'))
  • boot/generic/src/vprintf.c

    rc7c6afd r240b2e4  
    3636#include <str.h>
    3737
    38 static errno_t vprintf_str_write(const char *str, size_t size, void *data)
     38static int vprintf_str_write(const char *str, size_t size, void *data)
    3939{
    4040        size_t offset = 0;
     41        size_t chars = 0;
    4142
    42         while (offset < size)
     43        while (offset < size) {
    4344                putuchar(str_decode(str, &offset, size));
     45                chars++;
     46        }
    4447
    45         return EOK;
     48        return chars;
    4649}
    4750
     
    6871        };
    6972
    70         return printf_core(fmt, &ps, ap);
     73        int ret = printf_core(fmt, &ps, ap);
     74
     75        return ret;
    7176}
    7277
  • common/include/printf_core.h

    rc7c6afd r240b2e4  
    3636#define _LIBC_PRINTF_CORE_H_
    3737
    38 #include <errno.h>
     38#include <stddef.h>
    3939#include <stdarg.h>
    40 #include <stddef.h>
    4140#include <uchar.h>
    4241
    4342/** Structure for specifying output methods for different printf clones. */
    4443typedef struct {
    45         /*
    46          * String output function, returns EOK on success.
    47          * Only returns an error when an irrecoverable failure occurs and
    48          * the string cannot be fully output.
    49          */
    50         errno_t (*write)(const char *, size_t, void *);
     44        /* String output function, returns number of printed characters or EOF */
     45        int (*str_write)(const char *, size_t, void *);
     46
     47        /* Wide string output function, returns number of printed characters or EOF */
     48        int (*wstr_write)(const char32_t *, size_t, void *);
    5149
    5250        /* User data - output stream specification, state, locks, etc. */
  • common/printf/printf_core.c

    rc7c6afd r240b2e4  
    33 * Copyright (c) 2006 Josef Cejka
    44 * Copyright (c) 2009 Martin Decky
    5  * Copyright (c) 2025 Jiří Zárevúcky
    65 * All rights reserved.
    76 *
     
    3837 */
    3938
    40 #include <_bits/uchar.h>
    41 #include <_bits/wint_t.h>
     39#include <stdio.h>
     40#include <stddef.h>
     41#include <stdlib.h>
     42#include <printf_core.h>
     43#include <ctype.h>
     44#include <str.h>
    4245#include <assert.h>
    43 #include <ctype.h>
    44 #include <errno.h>
    45 #include <limits.h>
    4646#include <macros.h>
    47 #include <printf_core.h>
    48 #include <stddef.h>
    49 #include <stdint.h>
    50 #include <stdlib.h>
    51 #include <str.h>
     47#include <uchar.h>
    5248
    5349/* Disable float support in kernel, because we usually disable floating operations there. */
     
    9288
    9389/**
    94  * Buffer big enough for 64-bit number printed in base 2.
    95  */
    96 #define PRINT_NUMBER_BUFFER_SIZE  64
     90 * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0
     91 * to terminate string... (last one is only for better testing end of buffer by
     92 * zero-filling subroutine)
     93 */
     94#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
    9795
    9896/** Get signed or unsigned integer argument */
     
    124122        PrintfQualifierLongLong,
    125123        PrintfQualifierPointer,
     124        PrintfQualifierSize,
     125        PrintfQualifierMax
    126126} qualifier_t;
    127127
    128 static const char _digits_small[] = "0123456789abcdef";
    129 static const char _digits_big[] = "0123456789ABCDEF";
    130 
    131 static const char _nullstr[] = "(NULL)";
    132 static const char _replacement[] = u8"�";
    133 static const char _spaces[] = "                                               ";
    134 static const char _zeros[] = "000000000000000000000000000000000000000000000000";
    135 
    136 static void _set_errno(errno_t rc)
    137 {
    138         #ifdef errno
    139         errno = rc;
    140         #endif
    141 }
    142 
    143 static size_t _utf8_bytes(char32_t c)
    144 {
    145         if (c < 0x80)
    146                 return 1;
    147 
    148         if (c < 0x800)
    149                 return 2;
    150 
    151         if (c < 0xD800)
    152                 return 3;
    153 
    154         /* Surrogate code points, invalid in UTF-32. */
    155         if (c < 0xE000)
    156                 return sizeof(_replacement) - 1;
    157 
    158         if (c < 0x10000)
    159                 return 3;
    160 
    161         if (c < 0x110000)
    162                 return 4;
    163 
    164         /* Invalid character. */
    165         return sizeof(_replacement) - 1;
    166 }
    167 
    168 /** Counts characters and utf8 bytes in a wide string up to a byte limit.
    169  * @param max_bytes    Byte length limit for string's utf8 conversion.
    170  * @param[out] len     The number of wide characters
    171  * @return  Number of utf8 bytes that the first *len characters in the string
    172  *          will convert to. Will always be less than max_bytes.
    173  */
    174 static size_t _utf8_wstr_bytes_len(char32_t *s, size_t max_bytes, size_t *len)
    175 {
    176         size_t bytes = 0;
    177         size_t i;
    178 
    179         for (i = 0; bytes < max_bytes && s[i]; i++) {
    180                 size_t next = _utf8_bytes(s[i]);
    181                 if (max_bytes - bytes < next)
    182                         break;
    183 
    184                 bytes += next;
    185         }
    186 
    187         *len = i;
    188         return bytes;
    189 }
    190 
    191 #define TRY(expr) ({ errno_t rc = (expr); if (rc != EOK) return rc; })
    192 
    193 static inline void _saturating_add(size_t *a, size_t b)
    194 {
    195         size_t s = *a + b;
    196         /* Only works because size_t is unsigned. */
    197         *a = (s < b) ? SIZE_MAX : s;
    198 }
    199 
    200 static errno_t _write_bytes(const char *buf, size_t n, printf_spec_t *ps,
    201     size_t *written_bytes)
    202 {
    203         errno_t rc = ps->write(buf, n, ps->data);
    204         if (rc != EOK)
    205                 return rc;
    206 
    207         _saturating_add(written_bytes, n);
    208         return EOK;
    209 }
    210 
    211 /** Write one UTF-32 character. */
    212 static errno_t _write_uchar(char32_t ch, printf_spec_t *ps,
    213     size_t *written_bytes)
    214 {
    215         char utf8[4];
    216         size_t offset = 0;
    217 
    218         if (chr_encode(ch, utf8, &offset, sizeof(utf8)) == EOK)
    219                 return _write_bytes(utf8, offset, ps, written_bytes);
    220 
    221         /* Invalid character. */
    222         return _write_bytes(_replacement, sizeof(_replacement) - 1, ps, written_bytes);
    223 }
    224 
    225 /** Write n UTF-32 characters. */
    226 static errno_t _write_chars(const char32_t *buf, size_t n, printf_spec_t *ps,
    227     size_t *written_bytes)
    228 {
    229         for (size_t i = 0; i < n; i++)
    230                 TRY(_write_uchar(buf[i], ps, written_bytes));
    231 
    232         return EOK;
    233 }
    234 
    235 static errno_t _write_char(char c, printf_spec_t *ps, size_t *written_bytes)
    236 {
    237         return _write_bytes(&c, 1, ps, written_bytes);
    238 }
    239 
    240 static errno_t _write_spaces(size_t n, printf_spec_t *ps, size_t *written_bytes)
    241 {
    242         size_t max_spaces = sizeof(_spaces) - 1;
    243 
    244         while (n > max_spaces) {
    245                 TRY(_write_bytes(_spaces, max_spaces, ps, written_bytes));
    246                 n -= max_spaces;
    247         }
    248 
    249         return _write_bytes(_spaces, n, ps, written_bytes);
    250 }
    251 
    252 static errno_t _write_zeros(size_t n, printf_spec_t *ps, size_t *written_bytes)
    253 {
    254         size_t max_zeros = sizeof(_zeros) - 1;
    255 
    256         while (n > max_zeros) {
    257                 TRY(_write_bytes(_zeros, max_zeros, ps, written_bytes));
    258                 n -= max_zeros;
    259         }
    260 
    261         return _write_bytes(_zeros, n, ps, written_bytes);
     128static const char *nullstr = "(NULL)";
     129static const char *digits_small = "0123456789abcdef";
     130static const char *digits_big = "0123456789ABCDEF";
     131static const char invalch = U_SPECIAL;
     132
     133/** Print one or more characters without adding newline.
     134 *
     135 * @param buf  Buffer holding characters with size of
     136 *             at least size bytes. NULL is not allowed!
     137 * @param size Size of the buffer in bytes.
     138 * @param ps   Output method and its data.
     139 *
     140 * @return Number of characters printed.
     141 *
     142 */
     143static int printf_putnchars(const char *buf, size_t size,
     144    printf_spec_t *ps)
     145{
     146        return ps->str_write((void *) buf, size, ps->data);
     147}
     148
     149/** Print one or more wide characters without adding newline.
     150 *
     151 * @param buf  Buffer holding wide characters with size of
     152 *             at least size bytes. NULL is not allowed!
     153 * @param size Size of the buffer in bytes.
     154 * @param ps   Output method and its data.
     155 *
     156 * @return Number of wide characters printed.
     157 *
     158 */
     159static int printf_wputnchars(const char32_t *buf, size_t size,
     160    printf_spec_t *ps)
     161{
     162        return ps->wstr_write((void *) buf, size, ps->data);
     163}
     164
     165/** Print string without adding a newline.
     166 *
     167 * @param str String to print.
     168 * @param ps  Write function specification and support data.
     169 *
     170 * @return Number of characters printed.
     171 *
     172 */
     173static int printf_putstr(const char *str, printf_spec_t *ps)
     174{
     175        if (str == NULL)
     176                return printf_putnchars(nullstr, str_size(nullstr), ps);
     177
     178        return ps->str_write((void *) str, str_size(str), ps->data);
     179}
     180
     181/** Print one ASCII character.
     182 *
     183 * @param c  ASCII character to be printed.
     184 * @param ps Output method.
     185 *
     186 * @return Number of characters printed.
     187 *
     188 */
     189static int printf_putchar(const char ch, printf_spec_t *ps)
     190{
     191        if (!ascii_check(ch))
     192                return ps->str_write((void *) &invalch, 1, ps->data);
     193
     194        return ps->str_write(&ch, 1, ps->data);
     195}
     196
     197/** Print one wide character.
     198 *
     199 * @param c  Wide character to be printed.
     200 * @param ps Output method.
     201 *
     202 * @return Number of characters printed.
     203 *
     204 */
     205static int printf_putuchar(const char32_t ch, printf_spec_t *ps)
     206{
     207        if (!chr_check(ch))
     208                return ps->str_write((void *) &invalch, 1, ps->data);
     209
     210        return ps->wstr_write(&ch, sizeof(char32_t), ps->data);
    262211}
    263212
     
    267216 * @param width Width modifier.
    268217 * @param flags Flags that change the way the character is printed.
    269  */
    270 static errno_t _format_char(const char c, size_t width, uint32_t flags,
    271     printf_spec_t *ps, size_t *written_bytes)
    272 {
    273         size_t bytes = 1;
    274 
    275         if (width <= bytes)
    276                 return _write_char(c, ps, written_bytes);
    277 
    278         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    279                 TRY(_write_char(c, ps, written_bytes));
    280                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    281         } else {
    282                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    283                 TRY(_write_char(c, ps, written_bytes));
    284         }
    285 
    286         return EOK;
     218 *
     219 * @return Number of characters printed, negative value on failure.
     220 *
     221 */
     222static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
     223{
     224        size_t counter = 0;
     225        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     226                while (--width > 0) {
     227                        /*
     228                         * One space is consumed by the character itself, hence
     229                         * the predecrement.
     230                         */
     231                        if (printf_putchar(' ', ps) > 0)
     232                                counter++;
     233                }
     234        }
     235
     236        if (printf_putchar(ch, ps) > 0)
     237                counter++;
     238
     239        while (--width > 0) {
     240                /*
     241                 * One space is consumed by the character itself, hence
     242                 * the predecrement.
     243                 */
     244                if (printf_putchar(' ', ps) > 0)
     245                        counter++;
     246        }
     247
     248        return (int) (counter);
    287249}
    288250
     
    292254 * @param width Width modifier.
    293255 * @param flags Flags that change the way the character is printed.
    294  */
    295 static errno_t _format_uchar(const char32_t ch, size_t width, uint32_t flags,
    296     printf_spec_t *ps, size_t *written_bytes)
    297 {
    298         /*
    299          * All widths in printf() are specified in bytes. It might seem nonsensical
    300          * with unicode text, but that's the way the function is defined. The width
    301      * is barely useful if you want column alignment in terminal, but keep in
    302      * mind that counting code points is only marginally better for that.
    303      * Characters can span more than one unicode code point, even in languages
    304      * based on latin alphabet, and a single unicode code point can occupy two
    305      * spaces in east asian scripts.
    306      *
    307      * What the width can actually be useful for is padding, when you need the
    308      * output to fill an exact number of bytes in a file. That use would break
    309      * if we did our own thing here.
    310      */
    311 
    312     size_t bytes = _utf8_bytes(ch);
    313 
    314         if (width <= bytes)
    315                 return _write_uchar(ch, ps, written_bytes);
    316 
    317         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    318                 TRY(_write_uchar(ch, ps, written_bytes));
    319                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    320         } else {
    321                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    322                 TRY(_write_uchar(ch, ps, written_bytes));
    323         }
    324 
    325         return EOK;
     256 *
     257 * @return Number of characters printed, negative value on failure.
     258 *
     259 */
     260static int print_wchar(const char32_t ch, int width, uint32_t flags, printf_spec_t *ps)
     261{
     262        size_t counter = 0;
     263        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     264                while (--width > 0) {
     265                        /*
     266                         * One space is consumed by the character itself, hence
     267                         * the predecrement.
     268                         */
     269                        if (printf_putchar(' ', ps) > 0)
     270                                counter++;
     271                }
     272        }
     273
     274        if (printf_putuchar(ch, ps) > 0)
     275                counter++;
     276
     277        while (--width > 0) {
     278                /*
     279                 * One space is consumed by the character itself, hence
     280                 * the predecrement.
     281                 */
     282                if (printf_putchar(' ', ps) > 0)
     283                        counter++;
     284        }
     285
     286        return (int) (counter);
    326287}
    327288
     
    332293 * @param precision Precision modifier.
    333294 * @param flags     Flags that modify the way the string is printed.
    334  */
    335 static errno_t _format_cstr(const char *str, size_t width, int precision,
    336     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
     295 *
     296 * @return Number of characters printed, negative value on failure.
     297 */
     298static int print_str(char *str, int width, unsigned int precision,
     299    uint32_t flags, printf_spec_t *ps)
    337300{
    338301        if (str == NULL)
    339                 str = _nullstr;
    340 
    341         /* Negative precision == unspecified. */
    342         size_t max_bytes = (precision < 0) ? SIZE_MAX : (size_t) precision;
    343         size_t bytes = str_nsize(str, max_bytes);
    344 
    345         if (width <= bytes)
    346                 return _write_bytes(str, bytes, ps, written_bytes);
    347 
    348         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    349                 TRY(_write_bytes(str, bytes, ps, written_bytes));
    350                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    351         } else {
    352                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    353                 TRY(_write_bytes(str, bytes, ps, written_bytes));
    354         }
    355 
    356         return EOK;
     302                return printf_putstr(nullstr, ps);
     303
     304        size_t strw = str_length(str);
     305
     306        /* Precision unspecified - print everything. */
     307        if ((precision == 0) || (precision > strw))
     308                precision = strw;
     309
     310        /* Left padding */
     311        size_t counter = 0;
     312        width -= precision;
     313        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     314                while (width-- > 0) {
     315                        if (printf_putchar(' ', ps) == 1)
     316                                counter++;
     317                }
     318        }
     319
     320        /* Part of @a str fitting into the alloted space. */
     321        int retval;
     322        size_t size = str_lsize(str, precision);
     323        if ((retval = printf_putnchars(str, size, ps)) < 0)
     324                return -counter;
     325
     326        counter += retval;
     327
     328        /* Right padding */
     329        while (width-- > 0) {
     330                if (printf_putchar(' ', ps) == 1)
     331                        counter++;
     332        }
     333
     334        return ((int) counter);
     335
    357336}
    358337
     
    363342 * @param precision Precision modifier.
    364343 * @param flags     Flags that modify the way the string is printed.
    365  */
    366 static errno_t _format_wstr(char32_t *str, size_t width, int precision,
    367     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
    368 {
    369         if (!str)
    370                 return _format_cstr(_nullstr, width, precision, flags, ps, written_bytes);
    371 
    372         /* Width and precision are always byte-based. See _format_uchar() */
    373         /* Negative precision == unspecified. */
    374         size_t max_bytes = (precision < 0) ? SIZE_MAX : (size_t) precision;
    375 
    376         size_t len;
    377         size_t bytes = _utf8_wstr_bytes_len(str, max_bytes, &len);
    378 
    379         if (width <= bytes)
    380                 return _write_chars(str, len, ps, written_bytes);
    381 
    382         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    383                 TRY(_write_chars(str, len, ps, written_bytes));
    384                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    385         } else {
    386                 TRY(_write_spaces(width - bytes, ps, written_bytes));
    387                 TRY(_write_chars(str, len, ps, written_bytes));
    388         }
    389 
    390         return EOK;
    391 }
    392 
    393 static char _sign(uint32_t flags)
    394 {
    395         if (!(flags & __PRINTF_FLAG_SIGNED))
    396                 return 0;
    397 
    398         if (flags & __PRINTF_FLAG_NEGATIVE)
    399                 return '-';
    400 
    401         if (flags & __PRINTF_FLAG_SHOWPLUS)
    402                 return '+';
    403 
    404         if (flags & __PRINTF_FLAG_SPACESIGN)
    405                 return ' ';
    406 
    407         return 0;
     344 *
     345 * @return Number of wide characters printed, negative value on failure.
     346 */
     347static int print_wstr(char32_t *str, int width, unsigned int precision,
     348    uint32_t flags, printf_spec_t *ps)
     349{
     350        if (str == NULL)
     351                return printf_putstr(nullstr, ps);
     352
     353        size_t strw = wstr_length(str);
     354
     355        /* Precision not specified - print everything. */
     356        if ((precision == 0) || (precision > strw))
     357                precision = strw;
     358
     359        /* Left padding */
     360        size_t counter = 0;
     361        width -= precision;
     362        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     363                while (width-- > 0) {
     364                        if (printf_putchar(' ', ps) == 1)
     365                                counter++;
     366                }
     367        }
     368
     369        /* Part of @a wstr fitting into the alloted space. */
     370        int retval;
     371        size_t size = wstr_lsize(str, precision);
     372        if ((retval = printf_wputnchars(str, size, ps)) < 0)
     373                return -counter;
     374
     375        counter += retval;
     376
     377        /* Right padding */
     378        while (width-- > 0) {
     379                if (printf_putchar(' ', ps) == 1)
     380                        counter++;
     381        }
     382
     383        return ((int) counter);
    408384}
    409385
     
    417393 * @param base      Base to print the number in (must be between 2 and 16).
    418394 * @param flags     Flags that modify the way the number is printed.
    419  */
    420 static errno_t _format_number(uint64_t num, size_t width, int precision, int base,
    421     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
    422 {
    423         assert(base >= 2 && base <= 16);
    424 
    425         /* Default precision for numeric output is 1. */
    426         size_t min_digits = (precision < 0) ? 1 : precision;
    427 
    428         bool bigchars = flags & __PRINTF_FLAG_BIGCHARS;
    429         bool prefix = flags & __PRINTF_FLAG_PREFIX;
    430         bool left_aligned = flags & __PRINTF_FLAG_LEFTALIGNED;
    431         bool zero_padded = flags & __PRINTF_FLAG_ZEROPADDED;
    432 
    433         const char *digits = bigchars ? _digits_big : _digits_small;
    434 
    435         char buffer[PRINT_NUMBER_BUFFER_SIZE];
    436         char *end = &buffer[PRINT_NUMBER_BUFFER_SIZE];
    437 
    438         /* Write number to the buffer. */
    439         int offset = 0;
    440         while (num > 0) {
    441                 end[--offset] = digits[num % base];
    442                 num /= base;
    443         }
    444 
    445         char *number = &end[offset];
    446         size_t number_len = end - number;
    447         char sign = _sign(flags);
    448 
    449         if (left_aligned) {
    450                 /* Space padded right-aligned. */
    451                 size_t real_size = max(number_len, min_digits);
    452 
    453                 if (sign) {
    454                         TRY(_write_char(sign, ps, written_bytes));
    455                         real_size++;
    456                 }
    457 
    458                 if (prefix && base == 2 && number_len > 0) {
    459                         TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes));
    460                         real_size += 2;
    461                 }
    462 
    463                 if (prefix && base == 16 && number_len > 0) {
    464                         TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes));
    465                         real_size += 2;
    466                 }
    467 
    468                 if (min_digits > number_len) {
    469                         TRY(_write_zeros(min_digits - number_len, ps, written_bytes));
    470                 } else if (prefix && base == 8) {
    471                         TRY(_write_zeros(1, ps, written_bytes));
    472                         real_size++;
    473                 }
    474 
    475                 TRY(_write_bytes(number, number_len, ps, written_bytes));
    476 
    477                 if (width > real_size)
    478                         TRY(_write_spaces(width - real_size, ps, written_bytes));
    479 
    480                 return EOK;
    481         }
    482 
    483         /* Zero padded number (ignored when left aligned or if precision is specified). */
    484         if (precision < 0 && zero_padded) {
    485                 size_t real_size = number_len;
    486 
    487                 if (sign) {
    488                         TRY(_write_char(sign, ps, written_bytes));
    489                         real_size++;
    490                 }
    491 
    492                 if (prefix && base == 2 && number_len > 0) {
    493                         TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes));
    494                         real_size += 2;
    495                 }
    496 
    497                 if (prefix && base == 16 && number_len > 0) {
    498                         TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes));
    499                         real_size += 2;
    500                 }
    501 
    502                 if (width > real_size)
    503                         TRY(_write_zeros(width - real_size, ps, written_bytes));
    504                 else if (number_len == 0 || (prefix && base == 8))
    505                         TRY(_write_char('0', ps, written_bytes));
    506 
    507                 return _write_bytes(number, number_len, ps, written_bytes);
    508         }
    509 
    510         /* Space padded right-aligned. */
    511         size_t real_size = max(number_len, min_digits);
    512         if (sign)
    513                 real_size++;
    514 
    515         if (prefix && (base == 2 || base == 16) && number_len > 0)
    516                 real_size += 2;
    517 
    518         if (prefix && base == 8 && number_len >= min_digits)
    519                 real_size += 1;
    520 
    521         if (width > real_size)
    522                 TRY(_write_spaces(width - real_size, ps, written_bytes));
    523 
    524         if (sign)
    525                 TRY(_write_char(sign, ps, written_bytes));
    526 
    527         if (prefix && base == 2 && number_len > 0)
    528                 TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes));
    529 
    530         if (prefix && base == 16 && number_len > 0)
    531                 TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes));
    532 
    533         if (min_digits > number_len)
    534                 TRY(_write_zeros(min_digits - number_len, ps, written_bytes));
    535         else if (prefix && base == 8)
    536                 TRY(_write_char('0', ps, written_bytes));
    537 
    538         return _write_bytes(number, number_len, ps, written_bytes);
     395 *
     396 * @return Number of characters printed.
     397 *
     398 */
     399static int print_number(uint64_t num, int width, int precision, int base,
     400    uint32_t flags, printf_spec_t *ps)
     401{
     402        /* Precision not specified. */
     403        if (precision < 0) {
     404                precision = 0;
     405        }
     406
     407        const char *digits;
     408        if (flags & __PRINTF_FLAG_BIGCHARS)
     409                digits = digits_big;
     410        else
     411                digits = digits_small;
     412
     413        char data[PRINT_NUMBER_BUFFER_SIZE];
     414        char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
     415
     416        /* Size of number with all prefixes and signs */
     417        int size = 0;
     418
     419        /* Put zero at end of string */
     420        *ptr-- = 0;
     421
     422        if (num == 0) {
     423                *ptr-- = '0';
     424                size++;
     425        } else {
     426                do {
     427                        *ptr-- = digits[num % base];
     428                        size++;
     429                } while (num /= base);
     430        }
     431
     432        /* Size of plain number */
     433        int number_size = size;
     434
     435        /*
     436         * Collect the sum of all prefixes/signs/etc. to calculate padding and
     437         * leading zeroes.
     438         */
     439        if (flags & __PRINTF_FLAG_PREFIX) {
     440                switch (base) {
     441                case 2:
     442                        /* Binary formating is not standard, but usefull */
     443                        size += 2;
     444                        break;
     445                case 8:
     446                        size++;
     447                        break;
     448                case 16:
     449                        size += 2;
     450                        break;
     451                }
     452        }
     453
     454        char sgn = 0;
     455        if (flags & __PRINTF_FLAG_SIGNED) {
     456                if (flags & __PRINTF_FLAG_NEGATIVE) {
     457                        sgn = '-';
     458                        size++;
     459                } else if (flags & __PRINTF_FLAG_SHOWPLUS) {
     460                        sgn = '+';
     461                        size++;
     462                } else if (flags & __PRINTF_FLAG_SPACESIGN) {
     463                        sgn = ' ';
     464                        size++;
     465                }
     466        }
     467
     468        if (flags & __PRINTF_FLAG_LEFTALIGNED)
     469                flags &= ~__PRINTF_FLAG_ZEROPADDED;
     470
     471        /*
     472         * If the number is left-aligned or precision is specified then
     473         * padding with zeros is ignored.
     474         */
     475        if (flags & __PRINTF_FLAG_ZEROPADDED) {
     476                if ((precision == 0) && (width > size))
     477                        precision = width - size + number_size;
     478        }
     479
     480        /* Print leading spaces */
     481        if (number_size > precision) {
     482                /* Print the whole number, not only a part */
     483                precision = number_size;
     484        }
     485
     486        width -= precision + size - number_size;
     487        size_t counter = 0;
     488
     489        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     490                while (width-- > 0) {
     491                        if (printf_putchar(' ', ps) == 1)
     492                                counter++;
     493                }
     494        }
     495
     496        /* Print sign */
     497        if (sgn) {
     498                if (printf_putchar(sgn, ps) == 1)
     499                        counter++;
     500        }
     501
     502        /* Print prefix */
     503        if (flags & __PRINTF_FLAG_PREFIX) {
     504                switch (base) {
     505                case 2:
     506                        /* Binary formating is not standard, but useful */
     507                        if (printf_putchar('0', ps) == 1)
     508                                counter++;
     509                        if (flags & __PRINTF_FLAG_BIGCHARS) {
     510                                if (printf_putchar('B', ps) == 1)
     511                                        counter++;
     512                        } else {
     513                                if (printf_putchar('b', ps) == 1)
     514                                        counter++;
     515                        }
     516                        break;
     517                case 8:
     518                        if (printf_putchar('o', ps) == 1)
     519                                counter++;
     520                        break;
     521                case 16:
     522                        if (printf_putchar('0', ps) == 1)
     523                                counter++;
     524                        if (flags & __PRINTF_FLAG_BIGCHARS) {
     525                                if (printf_putchar('X', ps) == 1)
     526                                        counter++;
     527                        } else {
     528                                if (printf_putchar('x', ps) == 1)
     529                                        counter++;
     530                        }
     531                        break;
     532                }
     533        }
     534
     535        /* Print leading zeroes */
     536        precision -= number_size;
     537        while (precision-- > 0) {
     538                if (printf_putchar('0', ps) == 1)
     539                        counter++;
     540        }
     541
     542        /* Print the number itself */
     543        int retval;
     544        if ((retval = printf_putstr(++ptr, ps)) > 0)
     545                counter += retval;
     546
     547        /* Print trailing spaces */
     548
     549        while (width-- > 0) {
     550                if (printf_putchar(' ', ps) == 1)
     551                        counter++;
     552        }
     553
     554        return ((int) counter);
    539555}
    540556
     
    554570
    555571/** Returns the sign character or 0 if no sign should be printed. */
    556 static char _get_sign_char(bool negative, uint32_t flags)
     572static int get_sign_char(bool negative, uint32_t flags)
    557573{
    558574        if (negative) {
     
    567583}
    568584
     585/** Prints count times character ch. */
     586static int print_padding(char ch, int count, printf_spec_t *ps)
     587{
     588        for (int i = 0; i < count; ++i) {
     589                if (ps->str_write(&ch, 1, ps->data) < 0) {
     590                        return -1;
     591                }
     592        }
     593
     594        return count;
     595}
     596
    569597/** Prints a special double (ie NaN, infinity) padded to width characters. */
    570 static errno_t _format_special(ieee_double_t val, int width, uint32_t flags,
    571     printf_spec_t *ps, size_t *written_bytes)
     598static int print_special(ieee_double_t val, int width, uint32_t flags,
     599    printf_spec_t *ps)
    572600{
    573601        assert(val.is_special);
    574602
    575         char sign = _get_sign_char(val.is_negative, flags);
     603        char sign = get_sign_char(val.is_negative, flags);
    576604
    577605        const int str_len = 3;
     
    586614        int padding_len = max(0, width - ((sign ? 1 : 0) + str_len));
    587615
     616        int counter = 0;
     617        int ret;
     618
    588619        /* Leading padding. */
    589         if (!(flags & __PRINTF_FLAG_LEFTALIGNED))
    590                 TRY(_write_spaces(padding_len, ps, written_bytes));
    591 
    592         if (sign)
    593                 TRY(_write_char(sign, ps, written_bytes));
    594 
    595         TRY(_write_bytes(str, str_len, ps, written_bytes));
     620        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     621                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     622                        return -1;
     623
     624                counter += ret;
     625        }
     626
     627        if (sign) {
     628                if ((ret = ps->str_write(&sign, 1, ps->data)) < 0)
     629                        return -1;
     630
     631                counter += ret;
     632        }
     633
     634        if ((ret = ps->str_write(str, str_len, ps->data)) < 0)
     635                return -1;
     636
     637        counter += ret;
    596638
    597639        /* Trailing padding. */
    598         if (flags & __PRINTF_FLAG_LEFTALIGNED)
    599                 TRY(_write_spaces(padding_len, ps, written_bytes));
    600 
    601         return EOK;
     640        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     641                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     642                        return -1;
     643
     644                counter += ret;
     645        }
     646
     647        return counter;
    602648}
    603649
    604650/** Trims trailing zeros but leaves a single "0" intact. */
    605 static void _fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)
     651static void fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)
    606652{
    607653        /* Cut the zero off by adjusting the exponent. */
     
    613659
    614660/** Textually round up the last digit thereby eliminating it. */
    615 static void _fp_round_up(char *buf, int *len, int *dec_exp)
     661static void fp_round_up(char *buf, int *len, int *dec_exp)
    616662{
    617663        assert(1 <= *len);
     
    657703 *  to the %f specifier.
    658704 */
    659 static errno_t _format_double_str_fixed(double_str_t *val_str, int precision, int width,
    660     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
     705static int print_double_str_fixed(double_str_t *val_str, int precision, int width,
     706    uint32_t flags, printf_spec_t *ps)
    661707{
    662708        int len = val_str->len;
     
    671717        int int_len = max(1, len + dec_exp);
    672718
    673         char sign = _get_sign_char(val_str->neg, flags);
     719        char sign = get_sign_char(val_str->neg, flags);
    674720
    675721        /* Fractional portion lengths. */
     
    680726        char *buf_frac = buf + len - signif_frac_figs;
    681727
    682         if (flags & __PRINTF_FLAG_NOFRACZEROS)
     728        if (flags & __PRINTF_FLAG_NOFRACZEROS) {
    683729                trailing_frac_zeros = 0;
     730        }
    684731
    685732        int frac_len = leading_frac_zeros + signif_frac_figs + trailing_frac_zeros;
     
    691738
    692739        int padding_len = max(0, width - num_len);
     740        int ret = 0;
     741        int counter = 0;
    693742
    694743        /* Leading padding and sign. */
    695744
    696         if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED)))
    697                 TRY(_write_spaces(padding_len, ps, written_bytes));
    698 
    699         if (sign)
    700                 TRY(_write_char(sign, ps, written_bytes));
    701 
    702         if (flags & __PRINTF_FLAG_ZEROPADDED)
    703                 TRY(_write_zeros(padding_len, ps, written_bytes));
     745        if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
     746                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     747                        return -1;
     748
     749                counter += ret;
     750        }
     751
     752        if (sign) {
     753                if ((ret = ps->str_write(&sign, 1, ps->data)) < 0)
     754                        return -1;
     755
     756                counter += ret;
     757        }
     758
     759        if (flags & __PRINTF_FLAG_ZEROPADDED) {
     760                if ((ret = print_padding('0', padding_len, ps)) < 0)
     761                        return -1;
     762
     763                counter += ret;
     764        }
    704765
    705766        /* Print the intergral part of the buffer. */
     
    708769
    709770        if (0 < buf_int_len) {
    710                 TRY(_write_bytes(buf, buf_int_len, ps, written_bytes));
     771                if ((ret = ps->str_write(buf, buf_int_len, ps->data)) < 0)
     772                        return -1;
     773
     774                counter += ret;
    711775
    712776                /* Print trailing zeros of the integral part of the number. */
    713                 TRY(_write_zeros(int_len - buf_int_len, ps, written_bytes));
     777                if ((ret = print_padding('0', int_len - buf_int_len, ps)) < 0)
     778                        return -1;
    714779        } else {
    715780                /* Single leading integer 0. */
    716                 TRY(_write_char('0', ps, written_bytes));
    717         }
     781                char ch = '0';
     782                if ((ret = ps->str_write(&ch, 1, ps->data)) < 0)
     783                        return -1;
     784        }
     785
     786        counter += ret;
    718787
    719788        /* Print the decimal point and the fractional part. */
    720789        if (has_decimal_pt) {
    721                 TRY(_write_char('.', ps, written_bytes));
     790                char ch = '.';
     791
     792                if ((ret = ps->str_write(&ch, 1, ps->data)) < 0)
     793                        return -1;
     794
     795                counter += ret;
    722796
    723797                /* Print leading zeros of the fractional part of the number. */
    724                 TRY(_write_zeros(leading_frac_zeros, ps, written_bytes));
     798                if ((ret = print_padding('0', leading_frac_zeros, ps)) < 0)
     799                        return -1;
     800
     801                counter += ret;
    725802
    726803                /* Print significant digits of the fractional part of the number. */
    727                 if (0 < signif_frac_figs)
    728                         TRY(_write_bytes(buf_frac, signif_frac_figs, ps, written_bytes));
     804                if (0 < signif_frac_figs) {
     805                        if ((ret = ps->str_write(buf_frac, signif_frac_figs, ps->data)) < 0)
     806                                return -1;
     807
     808                        counter += ret;
     809                }
    729810
    730811                /* Print trailing zeros of the fractional part of the number. */
    731                 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes));
     812                if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0)
     813                        return -1;
     814
     815                counter += ret;
    732816        }
    733817
    734818        /* Trailing padding. */
    735         if (flags & __PRINTF_FLAG_LEFTALIGNED)
    736                 TRY(_write_spaces(padding_len, ps, written_bytes));
    737 
    738         return EOK;
     819        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     820                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     821                        return -1;
     822
     823                counter += ret;
     824        }
     825
     826        return counter;
    739827}
    740828
     
    749837 * @param flags Printf flags.
    750838 * @param ps    Printing functions.
    751  */
    752 static errno_t _format_double_fixed(double g, int precision, int width,
    753         uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
     839 *
     840 * @return The number of characters printed; negative on failure.
     841 */
     842static int print_double_fixed(double g, int precision, int width, uint32_t flags,
     843    printf_spec_t *ps)
    754844{
    755845        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     
    764854
    765855        if (val.is_special) {
    766                 return _format_special(val, width, flags, ps, written_bytes);
     856                return print_special(val, width, flags, ps);
    767857        }
    768858
     
    787877                 * digit is definitely inaccurate so also round to get rid of it.
    788878                 */
    789                 _fp_round_up(buf, &val_str.len, &val_str.dec_exp);
     879                fp_round_up(buf, &val_str.len, &val_str.dec_exp);
    790880
    791881                /* Rounding could have introduced trailing zeros. */
    792882                if (flags & __PRINTF_FLAG_NOFRACZEROS) {
    793                         _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
     883                        fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
    794884                }
    795885        } else {
     
    801891        }
    802892
    803         return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes);
     893        return print_double_str_fixed(&val_str, precision, width, flags, ps);
    804894}
    805895
    806896/** Prints the decimal exponent part of a %e specifier formatted number. */
    807 static errno_t _format_exponent(int exp_val, uint32_t flags, printf_spec_t *ps,
    808     size_t *written_bytes)
    809 {
     897static int print_exponent(int exp_val, uint32_t flags, printf_spec_t *ps)
     898{
     899        int counter = 0;
     900        int ret;
     901
    810902        char exp_ch = (flags & __PRINTF_FLAG_BIGCHARS) ? 'E' : 'e';
    811         TRY(_write_char(exp_ch, ps, written_bytes));
     903
     904        if ((ret = ps->str_write(&exp_ch, 1, ps->data)) < 0)
     905                return -1;
     906
     907        counter += ret;
    812908
    813909        char exp_sign = (exp_val < 0) ? '-' : '+';
    814         TRY(_write_char(exp_sign, ps, written_bytes));
     910
     911        if ((ret = ps->str_write(&exp_sign, 1, ps->data)) < 0)
     912                return -1;
     913
     914        counter += ret;
    815915
    816916        /* Print the exponent. */
     
    826926        const char *exp_str_start = &exp_str[3] - exp_len;
    827927
    828         return _write_bytes(exp_str_start, exp_len, ps, written_bytes);
     928        if ((ret = ps->str_write(exp_str_start, exp_len, ps->data)) < 0)
     929                return -1;
     930
     931        counter += ret;
     932
     933        return counter;
    829934}
    830935
     
    832937 *  to the %e specifier.
    833938 */
    834 static errno_t _format_double_str_scient(double_str_t *val_str, int precision,
    835     int width, uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
     939static int print_double_str_scient(double_str_t *val_str, int precision,
     940    int width, uint32_t flags, printf_spec_t *ps)
    836941{
    837942        int len = val_str->len;
     
    841946        assert(0 < len);
    842947
    843         char sign = _get_sign_char(val_str->neg, flags);
     948        char sign = get_sign_char(val_str->neg, flags);
    844949        bool has_decimal_pt = (0 < precision) || (flags & __PRINTF_FLAG_DECIMALPT);
    845950        int dec_pt_len = has_decimal_pt ? 1 : 0;
     
    863968
    864969        int padding_len = max(0, width - num_len);
    865 
    866         if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED)))
    867                 TRY(_write_spaces(padding_len, ps, written_bytes));
    868 
    869         if (sign)
    870                 TRY(_write_char(sign, ps, written_bytes));
    871 
    872         if (flags & __PRINTF_FLAG_ZEROPADDED)
    873                 TRY(_write_zeros(padding_len, ps, written_bytes));
     970        int ret = 0;
     971        int counter = 0;
     972
     973        if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
     974                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     975                        return -1;
     976
     977                counter += ret;
     978        }
     979
     980        if (sign) {
     981                if ((ret = ps->str_write(&sign, 1, ps->data)) < 0)
     982                        return -1;
     983
     984                counter += ret;
     985        }
     986
     987        if (flags & __PRINTF_FLAG_ZEROPADDED) {
     988                if ((ret = print_padding('0', padding_len, ps)) < 0)
     989                        return -1;
     990
     991                counter += ret;
     992        }
    874993
    875994        /* Single leading integer. */
    876         TRY(_write_char(buf[0], ps, written_bytes));
     995        if ((ret = ps->str_write(buf, 1, ps->data)) < 0)
     996                return -1;
     997
     998        counter += ret;
    877999
    8781000        /* Print the decimal point and the fractional part. */
    8791001        if (has_decimal_pt) {
    880                 TRY(_write_char('.', ps, written_bytes));
     1002                char ch = '.';
     1003
     1004                if ((ret = ps->str_write(&ch, 1, ps->data)) < 0)
     1005                        return -1;
     1006
     1007                counter += ret;
    8811008
    8821009                /* Print significant digits of the fractional part of the number. */
    883                 if (0 < signif_frac_figs)
    884                         TRY(_write_bytes(buf + 1, signif_frac_figs, ps, written_bytes));
     1010                if (0 < signif_frac_figs) {
     1011                        if ((ret = ps->str_write(buf + 1, signif_frac_figs, ps->data)) < 0)
     1012                                return -1;
     1013
     1014                        counter += ret;
     1015                }
    8851016
    8861017                /* Print trailing zeros of the fractional part of the number. */
    887                 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes));
     1018                if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0)
     1019                        return -1;
     1020
     1021                counter += ret;
    8881022        }
    8891023
    8901024        /* Print the exponent. */
    891         TRY(_format_exponent(exp_val, flags, ps, written_bytes));
    892 
    893         if (flags & __PRINTF_FLAG_LEFTALIGNED)
    894                 TRY(_write_spaces(padding_len, ps, written_bytes));
    895 
    896         return EOK;
     1025        if ((ret = print_exponent(exp_val, flags, ps)) < 0)
     1026                return -1;
     1027
     1028        counter += ret;
     1029
     1030        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     1031                if ((ret = print_padding(' ', padding_len, ps)) < 0)
     1032                        return -1;
     1033
     1034                counter += ret;
     1035        }
     1036
     1037        return counter;
    8971038}
    8981039
     
    9161057 * @param flags Printf flags.
    9171058 * @param ps    Printing functions.
    918  */
    919 static errno_t _format_double_scientific(double g, int precision, int width,
    920     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
    921 {
    922         if (flags & __PRINTF_FLAG_LEFTALIGNED)
     1059 *
     1060 * @return The number of characters printed; negative on failure.
     1061 */
     1062static int print_double_scientific(double g, int precision, int width,
     1063    uint32_t flags, printf_spec_t *ps)
     1064{
     1065        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    9231066                flags &= ~__PRINTF_FLAG_ZEROPADDED;
     1067        }
    9241068
    9251069        ieee_double_t val = extract_ieee_double(g);
    9261070
    927         if (val.is_special)
    928                 return _format_special(val, width, flags, ps, written_bytes);
     1071        if (val.is_special) {
     1072                return print_special(val, width, flags, ps);
     1073        }
    9291074
    9301075        char buf[MAX_DOUBLE_STR_BUF_SIZE];
     
    9491094                 * digit is definitely inaccurate so also round to get rid of it.
    9501095                 */
    951                 _fp_round_up(buf, &val_str.len, &val_str.dec_exp);
     1096                fp_round_up(buf, &val_str.len, &val_str.dec_exp);
    9521097
    9531098                /* Rounding could have introduced trailing zeros. */
    9541099                if (flags & __PRINTF_FLAG_NOFRACZEROS) {
    955                         _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
     1100                        fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
    9561101                }
    9571102        } else {
     
    9631108        }
    9641109
    965         return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes);
     1110        return print_double_str_scient(&val_str, precision, width, flags, ps);
    9661111}
    9671112
     
    9811126 * @return The number of characters printed; negative on failure.
    9821127 */
    983 static errno_t _format_double_generic(double g, int precision, int width,
    984     uint32_t flags, printf_spec_t *ps, size_t *written_bytes)
     1128static int print_double_generic(double g, int precision, int width,
     1129    uint32_t flags, printf_spec_t *ps)
    9851130{
    9861131        ieee_double_t val = extract_ieee_double(g);
    9871132
    988         if (val.is_special)
    989                 return _format_special(val, width, flags, ps, written_bytes);
     1133        if (val.is_special) {
     1134                return print_special(val, width, flags, ps);
     1135        }
    9901136
    9911137        char buf[MAX_DOUBLE_STR_BUF_SIZE];
     
    10071153                if (-4 <= dec_exp && dec_exp < precision) {
    10081154                        precision = precision - (dec_exp + 1);
    1009                         return _format_double_fixed(g, precision, width,
    1010                             flags | __PRINTF_FLAG_NOFRACZEROS, ps, written_bytes);
     1155                        return print_double_fixed(g, precision, width,
     1156                            flags | __PRINTF_FLAG_NOFRACZEROS, ps);
    10111157                } else {
    10121158                        --precision;
    1013                         return _format_double_scientific(g, precision, width,
    1014                             flags | __PRINTF_FLAG_NOFRACZEROS, ps, written_bytes);
     1159                        return print_double_scientific(g, precision, width,
     1160                            flags | __PRINTF_FLAG_NOFRACZEROS, ps);
    10151161                }
    10161162        } else {
     
    10361182                        /* Precision needed for the last significant digit. */
    10371183                        precision = max(0, -val_str.dec_exp);
    1038                         return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes);
     1184                        return print_double_str_fixed(&val_str, precision, width, flags, ps);
    10391185                } else {
    10401186                        /* Use all produced digits. */
    10411187                        precision = val_str.len - 1;
    1042                         return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes);
     1188                        return print_double_str_scient(&val_str, precision, width, flags, ps);
    10431189                }
    10441190        }
     
    10611207 * @param flags Printf flags.
    10621208 * @param ps    Printing functions.
    1063  */
    1064 static errno_t _format_double(double g, char spec, int precision, int width,
    1065     uint32_t flags, printf_spec_t *ps, size_t *written_chars)
     1209 *
     1210 * @return The number of characters printed; negative on failure.
     1211 */
     1212static int print_double(double g, char spec, int precision, int width,
     1213    uint32_t flags, printf_spec_t *ps)
    10661214{
    10671215        switch (spec) {
     
    10711219        case 'f':
    10721220                precision = (precision < 0) ? 6 : precision;
    1073                 return _format_double_fixed(g, precision, width, flags, ps, written_chars);
     1221                return print_double_fixed(g, precision, width, flags, ps);
    10741222
    10751223        case 'E':
     
    10781226        case 'e':
    10791227                precision = (precision < 0) ? 6 : precision;
    1080                 return _format_double_scientific(g, precision, width, flags, ps, written_chars);
     1228                return print_double_scientific(g, precision, width, flags, ps);
    10811229
    10821230        case 'G':
     
    10841232                /* Fallthrough */
    10851233        case 'g':
    1086                 return _format_double_generic(g, precision, width, flags, ps, written_chars);
     1234                return print_double_generic(g, precision, width, flags, ps);
    10871235
    10881236        default:
     
    10931241
    10941242#endif
    1095 
    1096 static const char *_strchrnul(const char *s, int c)
    1097 {
    1098         while (*s != c && *s != 0)
    1099                 s++;
    1100         return s;
    1101 }
    1102 
    1103 /** Read a sequence of digits from the format string as a number.
    1104  * If the number has too many digits to fit in int, returns INT_MAX.
    1105  */
    1106 static int _read_num(const char *fmt, size_t *i)
    1107 {
    1108         const char *s;
    1109         unsigned n = 0;
    1110 
    1111         for (s = &fmt[*i]; isdigit(*s); s++) {
    1112                 unsigned digit = (*s - '0');
    1113 
    1114                 /* Check for overflow */
    1115                 if (n > INT_MAX / 10 || n * 10 > INT_MAX - digit) {
    1116                         n = INT_MAX;
    1117                         while (isdigit(*s))
    1118                                 s++;
    1119                         break;
    1120                 }
    1121 
    1122                 n = n * 10 + digit;
    1123         }
    1124 
    1125         *i = s - fmt;
    1126         return n;
    1127 }
    1128 
    1129 static uint32_t _parse_flags(const char *fmt, size_t *i)
    1130 {
    1131         uint32_t flags = 0;
    1132 
    1133         while (true) {
    1134                 switch (fmt[(*i)++]) {
    1135                 case '#':
    1136                         flags |= __PRINTF_FLAG_PREFIX;
    1137                         flags |= __PRINTF_FLAG_DECIMALPT;
    1138                         continue;
    1139                 case '-':
    1140                         flags |= __PRINTF_FLAG_LEFTALIGNED;
    1141                         continue;
    1142                 case '+':
    1143                         flags |= __PRINTF_FLAG_SHOWPLUS;
    1144                         continue;
    1145                 case ' ':
    1146                         flags |= __PRINTF_FLAG_SPACESIGN;
    1147                         continue;
    1148                 case '0':
    1149                         flags |= __PRINTF_FLAG_ZEROPADDED;
    1150                         continue;
    1151                 }
    1152 
    1153                 --*i;
    1154                 break;
    1155         }
    1156 
    1157         return flags;
    1158 }
    1159 
    1160 static bool _eat_char(const char *s, size_t *idx, int c)
    1161 {
    1162         if (s[*idx] != c)
    1163                 return false;
    1164 
    1165         (*idx)++;
    1166         return true;
    1167 }
    1168 
    1169 static qualifier_t _read_qualifier(const char *s, size_t *idx)
    1170 {
    1171         switch (s[(*idx)++]) {
    1172         case 't': /* ptrdiff_t */
    1173         case 'z': /* size_t */
    1174                 if (sizeof(ptrdiff_t) == sizeof(int))
    1175                         return PrintfQualifierInt;
    1176                 else
    1177                         return PrintfQualifierLong;
    1178 
    1179         case 'h':
    1180                 if (_eat_char(s, idx, 'h'))
    1181                         return PrintfQualifierByte;
    1182                 else
    1183                         return PrintfQualifierShort;
    1184 
    1185         case 'l':
    1186                 if (_eat_char(s, idx, 'l'))
    1187                         return PrintfQualifierLongLong;
    1188                 else
    1189                         return PrintfQualifierLong;
    1190 
    1191         case 'j':
    1192                 return PrintfQualifierLongLong;
    1193 
    1194         default:
    1195                 --*idx;
    1196 
    1197                 /* Unspecified */
    1198                 return PrintfQualifierInt;
    1199         }
    1200 }
    12011243
    12021244/** Print formatted string.
     
    12911333int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
    12921334{
    1293         errno_t rc = EOK;
     1335        size_t i;        /* Index of the currently processed character from fmt */
    12941336        size_t nxt = 0;  /* Index of the next character from fmt */
     1337        size_t j = 0;    /* Index to the first not printed nonformating character */
    12951338
    12961339        size_t counter = 0;   /* Number of characters printed */
    1297 
    1298         while (rc == EOK) {
    1299                 /* Find the next specifier and write all the bytes before it. */
    1300                 const char *s = _strchrnul(&fmt[nxt], '%');
    1301                 size_t bytes = s - &fmt[nxt];
    1302                 rc = _write_bytes(&fmt[nxt], bytes, ps, &counter);
    1303                 if (rc != EOK)
     1340        int retval;           /* Return values from nested functions */
     1341
     1342        while (true) {
     1343                i = nxt;
     1344                char32_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1345
     1346                if (uc == 0)
    13041347                        break;
    13051348
    1306                 nxt += bytes;
    1307 
    1308                 /* Check for end of string. */
    1309                 if (_eat_char(fmt, &nxt, 0))
    1310                         break;
    1311 
    1312                 /* We must be at the start of a specifier. */
    1313                 bool spec = _eat_char(fmt, &nxt, '%');
    1314                 assert(spec);
    1315 
    1316                 /* Parse modifiers */
    1317                 uint32_t flags = _parse_flags(fmt, &nxt);
    1318 
    1319                 /* Width & '*' operator */
    1320                 int width = -1;
    1321                 if (_eat_char(fmt, &nxt, '*')) {
    1322                         /* Get width value from argument list */
    1323                         width = va_arg(ap, int);
    1324 
    1325                         if (width < 0) {
    1326                                 /* Negative width sets '-' flag */
    1327                                 width = (width == INT_MIN) ? INT_MAX : -width;
    1328                                 flags |= __PRINTF_FLAG_LEFTALIGNED;
     1349                /* Control character */
     1350                if (uc == '%') {
     1351                        /* Print common characters if any processed */
     1352                        if (i > j) {
     1353                                if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
     1354                                        /* Error */
     1355                                        counter = -counter;
     1356                                        goto out;
     1357                                }
     1358                                counter += retval;
    13291359                        }
    1330                 } else {
    1331                         width = _read_num(fmt, &nxt);
    1332                 }
    1333 
    1334                 /* Precision and '*' operator */
    1335                 int precision = -1;
    1336                 if (_eat_char(fmt, &nxt, '.')) {
    1337                         if (_eat_char(fmt, &nxt, '*')) {
    1338                                 /* Get precision value from the argument list */
    1339                                 precision = va_arg(ap, int);
    1340 
    1341                                 /* Negative is treated as omitted. */
    1342                                 if (precision < 0)
    1343                                         precision = -1;
    1344                         } else {
    1345                                 precision = _read_num(fmt, &nxt);
     1360
     1361                        j = i;
     1362
     1363                        /* Parse modifiers */
     1364                        uint32_t flags = 0;
     1365                        bool end = false;
     1366
     1367                        do {
     1368                                i = nxt;
     1369                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1370                                switch (uc) {
     1371                                case '#':
     1372                                        flags |= __PRINTF_FLAG_PREFIX;
     1373                                        flags |= __PRINTF_FLAG_DECIMALPT;
     1374                                        break;
     1375                                case '-':
     1376                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     1377                                        break;
     1378                                case '+':
     1379                                        flags |= __PRINTF_FLAG_SHOWPLUS;
     1380                                        break;
     1381                                case ' ':
     1382                                        flags |= __PRINTF_FLAG_SPACESIGN;
     1383                                        break;
     1384                                case '0':
     1385                                        flags |= __PRINTF_FLAG_ZEROPADDED;
     1386                                        break;
     1387                                default:
     1388                                        end = true;
     1389                                }
     1390                        } while (!end);
     1391
     1392                        /* Width & '*' operator */
     1393                        int width = 0;
     1394                        if (isdigit(uc)) {
     1395                                while (true) {
     1396                                        width *= 10;
     1397                                        width += uc - '0';
     1398
     1399                                        i = nxt;
     1400                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1401                                        if (uc == 0)
     1402                                                break;
     1403                                        if (!isdigit(uc))
     1404                                                break;
     1405                                }
     1406                        } else if (uc == '*') {
     1407                                /* Get width value from argument list */
     1408                                i = nxt;
     1409                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1410                                width = (int) va_arg(ap, int);
     1411                                if (width < 0) {
     1412                                        /* Negative width sets '-' flag */
     1413                                        width *= -1;
     1414                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     1415                                }
    13461416                        }
    1347                 }
    1348 
    1349                 qualifier_t qualifier = _read_qualifier(fmt, &nxt);
    1350                 unsigned int base = 10;
    1351                 char specifier = fmt[nxt++];
    1352 
    1353                 switch (specifier) {
    1354                 /*
    1355                  * String and character conversions.
    1356                  */
    1357                 case 's':
    1358                         if (qualifier == PrintfQualifierLong)
    1359                                 rc = _format_wstr(va_arg(ap, char32_t *), width, precision, flags, ps, &counter);
    1360                         else
    1361                                 rc = _format_cstr(va_arg(ap, char *), width, precision, flags, ps, &counter);
    1362                         continue;
    1363 
    1364                 case 'c':
    1365                         if (qualifier == PrintfQualifierLong)
    1366                                 rc = _format_uchar(va_arg(ap, wint_t), width, flags, ps, &counter);
    1367                         else
    1368                                 rc = _format_char(va_arg(ap, int), width, flags, ps, &counter);
    1369                         continue;
    1370 
    1371                 /*
    1372                  * Floating point values
    1373                  */
    1374                 case 'G':
    1375                 case 'g':
    1376                 case 'F':
    1377                 case 'f':
    1378                 case 'E':
    1379                 case 'e':;
     1417
     1418                        /* Precision and '*' operator */
     1419                        int precision = -1;
     1420                        if (uc == '.') {
     1421                                i = nxt;
     1422                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1423                                if (isdigit(uc)) {
     1424                                        precision = 0;
     1425                                        while (true) {
     1426                                                precision *= 10;
     1427                                                precision += uc - '0';
     1428
     1429                                                i = nxt;
     1430                                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1431                                                if (uc == 0)
     1432                                                        break;
     1433                                                if (!isdigit(uc))
     1434                                                        break;
     1435                                        }
     1436                                } else if (uc == '*') {
     1437                                        /* Get precision value from the argument list */
     1438                                        i = nxt;
     1439                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1440                                        precision = (int) va_arg(ap, int);
     1441                                        if (precision < 0) {
     1442                                                /* Ignore negative precision - use default instead */
     1443                                                precision = -1;
     1444                                        }
     1445                                }
     1446                        }
     1447
     1448                        qualifier_t qualifier;
     1449
     1450                        switch (uc) {
     1451                        case 't':
     1452                                /* ptrdiff_t */
     1453                                if (sizeof(ptrdiff_t) == sizeof(int32_t))
     1454                                        qualifier = PrintfQualifierInt;
     1455                                else
     1456                                        qualifier = PrintfQualifierLongLong;
     1457                                i = nxt;
     1458                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1459                                break;
     1460                        case 'h':
     1461                                /* Char or short */
     1462                                qualifier = PrintfQualifierShort;
     1463                                i = nxt;
     1464                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1465                                if (uc == 'h') {
     1466                                        i = nxt;
     1467                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1468                                        qualifier = PrintfQualifierByte;
     1469                                }
     1470                                break;
     1471                        case 'l':
     1472                                /* Long or long long */
     1473                                qualifier = PrintfQualifierLong;
     1474                                i = nxt;
     1475                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1476                                if (uc == 'l') {
     1477                                        i = nxt;
     1478                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1479                                        qualifier = PrintfQualifierLongLong;
     1480                                }
     1481                                break;
     1482                        case 'z':
     1483                                qualifier = PrintfQualifierSize;
     1484                                i = nxt;
     1485                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1486                                break;
     1487                        case 'j':
     1488                                qualifier = PrintfQualifierMax;
     1489                                i = nxt;
     1490                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     1491                                break;
     1492                        default:
     1493                                /* Default type */
     1494                                qualifier = PrintfQualifierInt;
     1495                        }
     1496
     1497                        unsigned int base = 10;
     1498
     1499                        switch (uc) {
     1500                                /*
     1501                                 * String and character conversions.
     1502                                 */
     1503                        case 's':
     1504                                precision = max(0,  precision);
     1505
     1506                                if (qualifier == PrintfQualifierLong)
     1507                                        retval = print_wstr(va_arg(ap, char32_t *), width, precision, flags, ps);
     1508                                else
     1509                                        retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
     1510
     1511                                if (retval < 0) {
     1512                                        counter = -counter;
     1513                                        goto out;
     1514                                }
     1515
     1516                                counter += retval;
     1517                                j = nxt;
     1518                                continue;
     1519                        case 'c':
     1520                                if (qualifier == PrintfQualifierLong)
     1521                                        retval = print_wchar(va_arg(ap, wint_t), width, flags, ps);
     1522                                else
     1523                                        retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
     1524
     1525                                if (retval < 0) {
     1526                                        counter = -counter;
     1527                                        goto out;
     1528                                }
     1529
     1530                                counter += retval;
     1531                                j = nxt;
     1532                                continue;
     1533
    13801534#ifdef HAS_FLOAT
    1381                         rc = _format_double(va_arg(ap, double), specifier, precision,
    1382                             width, flags, ps, &counter);
    1383 #else
    1384                         rc = _format_cstr("<float unsupported>", width, -1, 0, ps, &counter);
     1535                                /*
     1536                                 * Floating point values
     1537                                 */
     1538                        case 'G':
     1539                        case 'g':
     1540                        case 'F':
     1541                        case 'f':
     1542                        case 'E':
     1543                        case 'e':
     1544                                retval = print_double(va_arg(ap, double), uc, precision,
     1545                                    width, flags, ps);
     1546
     1547                                if (retval < 0) {
     1548                                        counter = -counter;
     1549                                        goto out;
     1550                                }
     1551
     1552                                counter += retval;
     1553                                j = nxt;
     1554                                continue;
    13851555#endif
    1386                         continue;
    1387 
    1388                 /*
    1389                  * Integer values
    1390                  */
    1391                 case 'P':
    1392                         /* Pointer */
    1393                         flags |= __PRINTF_FLAG_BIGCHARS;
    1394                         /* Fallthrough */
    1395                 case 'p':
    1396                         flags |= __PRINTF_FLAG_PREFIX;
    1397                         flags |= __PRINTF_FLAG_ZEROPADDED;
    1398                         base = 16;
    1399                         qualifier = PrintfQualifierPointer;
    1400                         break;
    1401                 case 'b':
    1402                         base = 2;
    1403                         break;
    1404                 case 'o':
    1405                         base = 8;
    1406                         break;
    1407                 case 'd':
    1408                 case 'i':
    1409                         flags |= __PRINTF_FLAG_SIGNED;
    1410                         break;
    1411                 case 'u':
    1412                         break;
    1413                 case 'X':
    1414                         flags |= __PRINTF_FLAG_BIGCHARS;
    1415                         /* Fallthrough */
    1416                 case 'x':
    1417                         base = 16;
    1418                         break;
    1419 
    1420                 case '%':
    1421                         /* Percentile itself */
    1422                         rc = _write_char('%', ps, &counter);
    1423                         continue;
    1424 
    1425                 /*
    1426                  * Bad formatting.
    1427                  */
    1428                 default:
    1429                         rc = EINVAL;
    1430                         continue;
    1431                 }
    1432 
    1433                 /* Print integers */
    1434                 uint64_t number;
    1435 
    1436                 switch (qualifier) {
    1437                 case PrintfQualifierByte:
    1438                         number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    1439                         break;
    1440                 case PrintfQualifierShort:
    1441                         number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    1442                         break;
    1443                 case PrintfQualifierInt:
    1444                         number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    1445                         break;
    1446                 case PrintfQualifierLong:
    1447                         number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
    1448                         break;
    1449                 case PrintfQualifierLongLong:
    1450                         number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
    1451                         break;
    1452                 case PrintfQualifierPointer:
    1453                         precision = sizeof(void *) << 1;
    1454                         number = (uint64_t) (uintptr_t) va_arg(ap, void *);
    1455                         break;
    1456                 default:
    1457                         /* Unknown qualifier */
    1458                         rc = EINVAL;
    1459                         continue;
    1460                 }
    1461 
    1462                 rc = _format_number(number, width, precision, base, flags, ps, &counter);
    1463         }
    1464 
    1465         if (rc != EOK) {
    1466                 _set_errno(rc);
    1467                 return -1;
    1468         }
    1469 
    1470         if (counter > INT_MAX) {
    1471                 _set_errno(EOVERFLOW);
    1472                 return -1;
    1473         }
    1474 
    1475         return (int) counter;
     1556
     1557                                /*
     1558                                 * Integer values
     1559                                 */
     1560                        case 'P':
     1561                                /* Pointer */
     1562                                flags |= __PRINTF_FLAG_BIGCHARS;
     1563                                /* Fallthrough */
     1564                        case 'p':
     1565                                flags |= __PRINTF_FLAG_PREFIX;
     1566                                flags |= __PRINTF_FLAG_ZEROPADDED;
     1567                                base = 16;
     1568                                qualifier = PrintfQualifierPointer;
     1569                                break;
     1570                        case 'b':
     1571                                base = 2;
     1572                                break;
     1573                        case 'o':
     1574                                base = 8;
     1575                                break;
     1576                        case 'd':
     1577                        case 'i':
     1578                                flags |= __PRINTF_FLAG_SIGNED;
     1579                                /* Fallthrough */
     1580                        case 'u':
     1581                                break;
     1582                        case 'X':
     1583                                flags |= __PRINTF_FLAG_BIGCHARS;
     1584                                /* Fallthrough */
     1585                        case 'x':
     1586                                base = 16;
     1587                                break;
     1588
     1589                        case '%':
     1590                                /* Percentile itself */
     1591                                j = i;
     1592                                continue;
     1593
     1594                                /*
     1595                                 * Bad formatting.
     1596                                 */
     1597                        default:
     1598                                /*
     1599                                 * Unknown format. Now, j is the index of '%'
     1600                                 * so we will print whole bad format sequence.
     1601                                 */
     1602                                continue;
     1603                        }
     1604
     1605                        /* Print integers */
     1606                        size_t size;
     1607                        uint64_t number;
     1608
     1609                        switch (qualifier) {
     1610                        case PrintfQualifierByte:
     1611                                size = sizeof(unsigned char);
     1612                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
     1613                                break;
     1614                        case PrintfQualifierShort:
     1615                                size = sizeof(unsigned short);
     1616                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
     1617                                break;
     1618                        case PrintfQualifierInt:
     1619                                size = sizeof(unsigned int);
     1620                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
     1621                                break;
     1622                        case PrintfQualifierLong:
     1623                                size = sizeof(unsigned long);
     1624                                number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
     1625                                break;
     1626                        case PrintfQualifierLongLong:
     1627                                size = sizeof(unsigned long long);
     1628                                number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
     1629                                break;
     1630                        case PrintfQualifierPointer:
     1631                                size = sizeof(void *);
     1632                                precision = size << 1;
     1633                                number = (uint64_t) (uintptr_t) va_arg(ap, void *);
     1634                                break;
     1635                        case PrintfQualifierSize:
     1636                                size = sizeof(size_t);
     1637                                number = (uint64_t) va_arg(ap, size_t);
     1638                                break;
     1639                        case PrintfQualifierMax:
     1640                                size = sizeof(uintmax_t);
     1641                                number = (uint64_t) va_arg(ap, uintmax_t);
     1642                                break;
     1643                        default:
     1644                                /* Unknown qualifier */
     1645                                counter = -counter;
     1646                                goto out;
     1647                        }
     1648
     1649                        if ((retval = print_number(number, width, precision,
     1650                            base, flags, ps)) < 0) {
     1651                                counter = -counter;
     1652                                goto out;
     1653                        }
     1654
     1655                        counter += retval;
     1656                        j = nxt;
     1657                }
     1658        }
     1659
     1660        if (i > j) {
     1661                if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
     1662                        /* Error */
     1663                        counter = -counter;
     1664                        goto out;
     1665                }
     1666                counter += retval;
     1667        }
     1668
     1669out:
     1670        return ((int) counter);
    14761671}
    14771672
  • kernel/generic/meson.build

    rc7c6afd r240b2e4  
    4040        'common/adt/list.c',
    4141        'common/adt/odict.c',
    42         'common/gsort.c',
    4342        'common/printf/printf_core.c',
    4443        'common/stdc/calloc.c',
    4544        'common/stdc/ctype.c',
    4645        'common/stdc/mem.c',
    47         'common/stdc/snprintf.c',
    48         'common/stdc/vsnprintf.c',
     46        'common/gsort.c',
    4947        'common/str.c',
    5048        'common/str_error.c',
     
    9896        'src/mm/reserve.c',
    9997        'src/printf/printf.c',
     98        'src/printf/snprintf.c',
    10099        'src/printf/vprintf.c',
     100        'src/printf/vsnprintf.c',
    101101        'src/proc/program.c',
    102102        'src/proc/scheduler.c',
  • kernel/generic/src/log/log.c

    rc7c6afd r240b2e4  
    3333 */
    3434
    35 #include <abi/log.h>
    36 #include <arch.h>
    37 #include <atomic.h>
    38 #include <console/console.h>
     35#include <sysinfo/sysinfo.h>
     36#include <synch/spinlock.h>
     37#include <typedefs.h>
     38#include <ddi/irq.h>
    3939#include <ddi/ddi.h>
    40 #include <ddi/irq.h>
    41 #include <errno.h>
    4240#include <ipc/event.h>
    4341#include <ipc/irq.h>
     42#include <arch.h>
     43#include <panic.h>
     44#include <putchar.h>
     45#include <atomic.h>
     46#include <syscall/copy.h>
     47#include <errno.h>
     48#include <str.h>
     49#include <print.h>
     50#include <printf/printf_core.h>
     51#include <stdarg.h>
    4452#include <log.h>
    45 #include <panic.h>
    46 #include <print.h>
    47 #include <printf_core.h>
    48 #include <putchar.h>
    49 #include <stdarg.h>
     53#include <console/console.h>
     54#include <abi/log.h>
    5055#include <stdlib.h>
    51 #include <str.h>
    52 #include <synch/spinlock.h>
    53 #include <syscall/copy.h>
    54 #include <sysinfo/sysinfo.h>
    55 #include <typedefs.h>
    5656
    5757#define LOG_PAGES    8
     
    204204{
    205205        size_t offset = 0;
    206 
    207         while (offset < size)
     206        size_t chars = 0;
     207
     208        while (offset < size) {
    208209                kio_push_char(str_decode(str, &offset, size));
     210                chars++;
     211        }
    209212
    210213        log_append((const uint8_t *)str, size);
    211214
    212         return EOK;
     215        return chars;
     216}
     217
     218static int log_printf_wstr_write(const char32_t *wstr, size_t size, void *data)
     219{
     220        char buffer[16];
     221        size_t offset = 0;
     222        size_t chars = 0;
     223
     224        for (offset = 0; offset < size; offset += sizeof(char32_t), chars++) {
     225                kio_push_char(wstr[chars]);
     226
     227                size_t buffer_offset = 0;
     228                errno_t rc = chr_encode(wstr[chars], buffer, &buffer_offset, 16);
     229                if (rc != EOK) {
     230                        return EOF;
     231                }
     232
     233                log_append((const uint8_t *)buffer, buffer_offset);
     234        }
     235
     236        return chars;
    213237}
    214238
     
    219243int log_vprintf(const char *fmt, va_list args)
    220244{
     245        int ret;
     246
    221247        printf_spec_t ps = {
    222248                log_printf_str_write,
     249                log_printf_wstr_write,
    223250                NULL
    224251        };
    225252
    226         return printf_core(fmt, &ps, args);
     253        ret = printf_core(fmt, &ps, args);
     254
     255        return ret;
    227256}
    228257
  • kernel/generic/src/printf/vprintf.c

    rc7c6afd r240b2e4  
    3636#include <console/console.h>
    3737#include <print.h>
    38 #include <printf_core.h>
     38#include <printf/printf_core.h>
    3939#include <putchar.h>
    4040#include <str.h>
     
    4242#include <typedefs.h>
    4343
    44 static errno_t vprintf_str_write(const char *str, size_t size, void *data)
     44static int vprintf_str_write(const char *str, size_t size, void *data)
    4545{
    4646        size_t offset = 0;
     47        size_t chars = 0;
    4748
    48         while (offset < size)
     49        while (offset < size) {
    4950                putuchar(str_decode(str, &offset, size));
     51                chars++;
     52        }
    5053
    51         return EOK;
     54        return chars;
     55}
     56
     57static int vprintf_wstr_write(const char32_t *str, size_t size, void *data)
     58{
     59        size_t offset = 0;
     60        size_t chars = 0;
     61
     62        while (offset < size) {
     63                putuchar(str[chars]);
     64                chars++;
     65                offset += sizeof(char32_t);
     66        }
     67
     68        return chars;
    5269}
    5370
     
    7592        printf_spec_t ps = {
    7693                vprintf_str_write,
     94                vprintf_wstr_write,
    7795                NULL
    7896        };
  • uspace/lib/c/generic/io/asprintf.c

    rc7c6afd r240b2e4  
    4040#include <str.h>
    4141#include <printf_core.h>
     42
     43static int asprintf_str_write(const char *str, size_t count, void *unused)
     44{
     45        return str_nlength(str, count);
     46}
     47
     48static int asprintf_wstr_write(const char32_t *str, size_t count, void *unused)
     49{
     50        return wstr_nlength(str, count);
     51}
     52
     53int vprintf_length(const char *fmt, va_list args)
     54{
     55        printf_spec_t ps = {
     56                asprintf_str_write,
     57                asprintf_wstr_write,
     58                NULL
     59        };
     60
     61        return printf_core(fmt, &ps, args);
     62}
     63
     64int printf_length(const char *fmt, ...)
     65{
     66        va_list args;
     67        va_start(args, fmt);
     68        int ret = vprintf_length(fmt, args);
     69        va_end(args);
     70
     71        return ret;
     72}
    4273
    4374/** Allocate and print to string.
     
    84115        int ret = vasprintf(strp, fmt, args);
    85116        va_end(args);
     117
    86118        return ret;
    87119}
  • uspace/lib/c/generic/io/kio.c

    rc7c6afd r240b2e4  
    131131}
    132132
    133 static errno_t kio_vprintf_str_write(const char *str, size_t size, void *data)
     133static int kio_vprintf_str_write(const char *str, size_t size, void *data)
    134134{
    135         size_t wr = 0;
    136         return kio_write(str, size, &wr);
     135        size_t wr;
     136
     137        wr = 0;
     138        (void) kio_write(str, size, &wr);
     139        return str_nlength(str, wr);
     140}
     141
     142static int kio_vprintf_wstr_write(const char32_t *str, size_t size, void *data)
     143{
     144        size_t offset = 0;
     145        size_t chars = 0;
     146        size_t wr;
     147
     148        while (offset < size) {
     149                char buf[STR_BOUNDS(1)];
     150                size_t sz = 0;
     151
     152                if (chr_encode(str[chars], buf, &sz, STR_BOUNDS(1)) == EOK)
     153                        kio_write(buf, sz, &wr);
     154
     155                chars++;
     156                offset += sizeof(char32_t);
     157        }
     158
     159        return chars;
    137160}
    138161
     
    149172        printf_spec_t ps = {
    150173                kio_vprintf_str_write,
     174                kio_vprintf_wstr_write,
    151175                NULL
    152176        };
  • uspace/lib/c/generic/io/vprintf.c

    rc7c6afd r240b2e4  
    4242static FIBRIL_MUTEX_INITIALIZE(printf_mutex);
    4343
    44 static errno_t vprintf_str_write(const char *str, size_t size, void *stream)
     44static int vprintf_str_write(const char *str, size_t size, void *stream)
    4545{
    46         errno_t old_errno = errno;
     46        size_t wr = fwrite(str, 1, size, (FILE *) stream);
     47        return str_nlength(str, wr);
     48}
    4749
    48         errno = EOK;
    49         size_t written = fwrite(str, 1, size, (FILE *) stream);
     50static int vprintf_wstr_write(const char32_t *str, size_t size, void *stream)
     51{
     52        size_t offset = 0;
     53        size_t chars = 0;
    5054
    51         if (errno == EOK && written != size)
    52                 errno = EIO;
     55        while (offset < size) {
     56                if (fputuc(str[chars], (FILE *) stream) <= 0)
     57                        break;
    5358
    54         if (errno != EOK)
    55                 return errno;
     59                chars++;
     60                offset += sizeof(char32_t);
     61        }
    5662
    57         errno = old_errno;
    58         return EOK;
     63        return chars;
    5964}
    6065
     
    7277        printf_spec_t ps = {
    7378                vprintf_str_write,
     79                vprintf_wstr_write,
    7480                stream
    7581        };
  • uspace/lib/c/include/stdio.h

    rc7c6afd r240b2e4  
    209209};
    210210
     211extern int vprintf_length(const char *, va_list);
     212extern int printf_length(const char *, ...)
     213    _HELENOS_PRINTF_ATTRIBUTE(1, 2);
    211214extern FILE *fdopen(int, const char *);
    212215extern int fileno(FILE *);
  • uspace/lib/c/meson.build

    rc7c6afd r240b2e4  
    7272        'common/stdc/mem.c',
    7373        'common/stdc/qsort.c',
    74         'common/stdc/snprintf.c',
    7574        'common/stdc/uchar.c',
    76         'common/stdc/vsnprintf.c',
    7775        'common/stdc/wchar.c',
    7876        'common/str.c',
     
    115113        'generic/io/logctl.c',
    116114        'generic/io/printf.c',
     115        'generic/io/snprintf.c',
    117116        'generic/io/table.c',
    118117        'generic/io/vprintf.c',
     118        'generic/io/vsnprintf.c',
    119119        'generic/ipc.c',
    120120        'generic/irq.c',
  • uspace/lib/posix/src/stdio.c

    rc7c6afd r240b2e4  
    232232 * @return The number of written characters.
    233233 */
    234 static errno_t _dprintf_str_write(const char *str, size_t size, void *fd)
     234static int _dprintf_str_write(const char *str, size_t size, void *fd)
    235235{
    236236        const int fildes = *(int *) fd;
    237237        size_t wr;
    238         return vfs_write(fildes, &posix_pos[fildes], str, size, &wr);
     238        if (failed(vfs_write(fildes, &posix_pos[fildes], str, size, &wr)))
     239                return -1;
     240        return str_nlength(str, wr);
     241}
     242
     243/**
     244 * Write wide string to the opened file.
     245 *
     246 * @param str String to be written.
     247 * @param size Size of the string (in bytes).
     248 * @param fd File descriptor of the opened file.
     249 * @return The number of written characters.
     250 */
     251static int _dprintf_wstr_write(const char32_t *str, size_t size, void *fd)
     252{
     253        size_t offset = 0;
     254        size_t chars = 0;
     255        size_t sz;
     256        char buf[4];
     257
     258        while (offset < size) {
     259                sz = 0;
     260                if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
     261                        break;
     262                }
     263
     264                const int fildes = *(int *) fd;
     265                size_t nwr;
     266                if (vfs_write(fildes, &posix_pos[fildes], buf, sz, &nwr) != EOK)
     267                        break;
     268
     269                chars++;
     270                offset += sizeof(char32_t);
     271        }
     272
     273        return chars;
    239274}
    240275
     
    250285{
    251286        printf_spec_t spec = {
    252                 .write = _dprintf_str_write,
     287                .str_write = _dprintf_str_write,
     288                .wstr_write = _dprintf_wstr_write,
    253289                .data = &fildes
    254290        };
Note: See TracChangeset for help on using the changeset viewer.