Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset eec616b in mainline


Ignore:
Timestamp:
2009-03-24T14:43:25Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
8f29e336
Parents:
74c8da2c
Message:

Unicode aware printf and family functions
(this breaks some things, but will be fixed soon)

Location:
kernel/generic
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/console/chardev.h

    r74c8da2c reec616b  
    7272typedef struct {
    7373        /** Write character to output. */
    74         void (* write)(struct outdev *, char c, bool silent);
     74        void (* write)(struct outdev *, wchar_t c, bool silent);
    7575} outdev_operations_t;
    7676
  • kernel/generic/include/console/console.h

    r74c8da2c reec616b  
    5353extern uint8_t _getc(indev_t *indev);
    5454extern count_t gets(indev_t *indev, char *buf, size_t buflen);
    55 extern void putchar(char c);
    5655extern unative_t sys_klog(int fd, const void * buf, size_t count);
    5756
  • kernel/generic/include/print.h

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    4747extern int puts(const char *s);
    4848extern int printf(const char *fmt, ...);
    49 extern int sprintf(char *str, const char *fmt, ...);
    5049extern int snprintf(char *str, size_t size, const char *fmt, ...);
    5150
    5251extern int vprintf(const char *fmt, va_list ap);
    53 extern int vsprintf(char *str, const char *fmt, va_list ap);
    5452extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
    5553
  • kernel/generic/include/printf/printf_core.h

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3636#define KERN_PRINTF_CORE_H_
    3737
    38 #include <arch/types.h>
     38#include <typedefs.h>
    3939#include <arch/arg.h>
    4040
    4141/** Structure for specifying output methods for different printf clones. */
    42 struct printf_spec {
    43         /* Output function, returns count of printed characters or EOF */
    44         int (*write)(void *, size_t, void *);
    45         /* Support data - output stream specification, its state, locks,... */
     42typedef struct {
     43        /* UTF-8 output function, returns number of printed UTF-8 characters or EOF */
     44        int (*write_utf8)(const char *, size_t, void *);
     45       
     46        /* UTF-32 output function, returns number of printed UTF-32 characters or EOF */
     47        int (*write_utf32)(const wchar_t *, size_t, void *);
     48       
     49        /* User data - output stream specification, state, locks, etc. */
    4650        void *data;
     51} printf_spec_t;
    4752
    48 };
    49 
    50 int printf_core(const char *fmt, struct printf_spec *ps, va_list ap);
     53int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);
    5154
    5255#endif
  • kernel/generic/include/putchar.h

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3636#define KERN_PUTCHAR_H_
    3737
    38 extern void putchar(const char ch);
     38extern void putchar(const wchar_t ch);
    3939
    4040#endif
  • kernel/generic/src/console/chardev.c

    r74c8da2c reec616b  
    3434
    3535#include <console/chardev.h>
    36 #include <putchar.h>
    3736#include <synch/waitq.h>
    3837#include <synch/spinlock.h>
  • kernel/generic/src/console/console.c

    r74c8da2c reec616b  
    4747#include <func.h>
    4848#include <print.h>
     49#include <putchar.h>
    4950#include <atomic.h>
    5051#include <syscall/copy.h>
    5152#include <errno.h>
    5253
    53 #define KLOG_SIZE PAGE_SIZE
    54 #define KLOG_LATENCY 8
     54#define KLOG_SIZE     PAGE_SIZE
     55#define KLOG_LATENCY  8
    5556
    5657/** Kernel log cyclic buffer */
    57 static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
     58static wchar_t klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
    5859
    5960/** Kernel log initialized */
     
    9697       
    9798        klog_parea.pbase = (uintptr_t) faddr;
    98         klog_parea.frames = SIZE2FRAMES(KLOG_SIZE);
     99        klog_parea.frames = SIZE2FRAMES(sizeof(klog));
    99100        ddi_parea_register(&klog_parea);
    100101       
    101102        sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr);
    102         sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE));
     103        sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(sizeof(klog)));
    103104       
    104105        spinlock_lock(&klog_lock);
     
    246247}
    247248
    248 void putchar(char c)
     249void putchar(const wchar_t ch)
    249250{
    250251        spinlock_lock(&klog_lock);
     
    259260       
    260261        /* Store character in the cyclic kernel log */
    261         klog[(klog_start + klog_len) % KLOG_SIZE] = c;
     262        klog[(klog_start + klog_len) % KLOG_SIZE] = ch;
    262263        if (klog_len < KLOG_SIZE)
    263264                klog_len++;
     
    266267       
    267268        if ((stdout) && (stdout->op->write))
    268                 stdout->op->write(stdout, c, silent);
     269                stdout->op->write(stdout, ch, silent);
    269270        else {
    270271                /* The character is just in the kernel log */
     
    279280        /* Check notify uspace to update */
    280281        bool update;
    281         if ((klog_uspace > KLOG_LATENCY) || (c == '\n'))
     282        if ((klog_uspace > KLOG_LATENCY) || (ch == '\n'))
    282283                update = true;
    283284        else
     
    295296 *
    296297 */
    297 unative_t sys_klog(int fd, const void * buf, size_t count) 
     298unative_t sys_klog(int fd, const void * buf, size_t count)
    298299{
    299300        char *data;
    300301        int rc;
    301 
     302       
    302303        if (count > PAGE_SIZE)
    303304                return ELIMIT;
  • kernel/generic/src/console/kconsole.c

    r74c8da2c reec616b  
    5656#include <symtab.h>
    5757#include <errno.h>
     58#include <putchar.h>
    5859
    5960/** Simple kernel console.
     
    160161
    161162/** Print count times a character */
    162 static void rdln_print_c(char ch, int count)
    163 {
    164         int i;
     163static void rdln_print_c(wchar_t ch, count_t count)
     164{
     165        count_t i;
    165166        for (i = 0; i < count; i++)
    166167                putchar(ch);
  • kernel/generic/src/printf/printf.c

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3434
    3535#include <print.h>
    36 int printf(const char *fmt, ...);
    3736
    3837int printf(const char *fmt, ...)
     
    4039        int ret;
    4140        va_list args;
    42 
     41       
    4342        va_start(args, fmt);
    44 
     43       
    4544        ret = vprintf(fmt, args);
    4645       
    4746        va_end(args);
    48 
     47       
    4948        return ret;
    5049}
  • kernel/generic/src/printf/printf_core.c

    r74c8da2c reec616b  
    22 * Copyright (c) 2001-2004 Jakub Jermar
    33 * Copyright (c) 2006 Josef Cejka
     4 * Copyright (c) 2009 Martin Decky
    45 * All rights reserved.
    56 *
     
    2829 */
    2930
    30 /** @addtogroup generic 
     31/** @addtogroup generic
    3132 * @{
    3233 */
    3334/**
    3435 * @file
    35  * @brief       Printing functions.
     36 * @brief Printing functions.
    3637 */
    3738
    3839#include <printf/printf_core.h>
    39 #include <putchar.h>
    4040#include <print.h>
    4141#include <arch/arg.h>
     
    4545
    4646/** show prefixes 0x or 0 */
    47 #define __PRINTF_FLAG_PREFIX            0x00000001
     47#define __PRINTF_FLAG_PREFIX       0x00000001
    4848/** signed / unsigned number */
    49 #define __PRINTF_FLAG_SIGNED            0x00000002
     49#define __PRINTF_FLAG_SIGNED       0x00000002
    5050/** print leading zeroes */
    51 #define __PRINTF_FLAG_ZEROPADDED        0x00000004
     51#define __PRINTF_FLAG_ZEROPADDED   0x00000004
    5252/** align to left */
    53 #define __PRINTF_FLAG_LEFTALIGNED       0x00000010
     53#define __PRINTF_FLAG_LEFTALIGNED  0x00000010
    5454/** always show + sign */
    55 #define __PRINTF_FLAG_SHOWPLUS          0x00000020
     55#define __PRINTF_FLAG_SHOWPLUS     0x00000020
    5656/** print space instead of plus */
    57 #define __PRINTF_FLAG_SPACESIGN         0x00000040
     57#define __PRINTF_FLAG_SPACESIGN    0x00000040
    5858/** show big characters */
    59 #define __PRINTF_FLAG_BIGCHARS          0x00000080
     59#define __PRINTF_FLAG_BIGCHARS     0x00000080
    6060/** number has - sign */
    61 #define __PRINTF_FLAG_NEGATIVE          0x00000100
     61#define __PRINTF_FLAG_NEGATIVE     0x00000100
    6262
    6363/**
     
    6666 * zero-filling subroutine)
    6767 */
    68 #define PRINT_NUMBER_BUFFER_SIZE        (64 + 5)       
     68#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
    6969
    7070/** Enumeration of possible arguments types.
     
    7979} qualifier_t;
    8080
     81static char nullstr[] = "(NULL)";
    8182static char digits_small[] = "0123456789abcdef";
    8283static char digits_big[] = "0123456789ABCDEF";
    8384
    84 /** Print one or more characters without adding newline.
    85  *
    86  * @param buf           Buffer with size at least count bytes. NULL pointer is
    87  *                      not allowed!
    88  * @param count         Number of characters to print.
    89  * @param ps            Output method and its data.
    90  * @return              Number of characters printed.
    91  */
    92 static int printf_putnchars(const char * buf, size_t count,
    93     struct printf_spec *ps)
    94 {
    95         return ps->write((void *) buf, count, ps->data);
    96 }
    97 
    98 /** Print a string without adding a newline.
    99  *
    100  * @param str           String to print.
    101  * @param ps            Write function specification and support data.
    102  * @return              Number of characters printed.
    103  */
    104 static int printf_putstr(const char * str, struct printf_spec *ps)
    105 {
    106         size_t count;
    107        
    108         if (str == NULL) {
    109                 char *nullstr = "(NULL)";
    110                 return printf_putnchars(nullstr, strlen(nullstr), ps);
    111         }
    112 
    113         count = strlen(str);
    114 
    115         return ps->write((void *) str, count, ps->data);
    116 }
    117 
    118 /** Print one character.
    119  *
    120  * @param c             Character to be printed.
    121  * @param ps            Output method.
    122  *
    123  * @return              Number of characters printed.
    124  */
    125 static int printf_putchar(int c, struct printf_spec *ps)
    126 {
    127         unsigned char ch = c;
    128        
    129         return ps->write((void *) &ch, 1, ps->data);
    130 }
    131 
    132 /** Print one formatted character.
    133  *
    134  * @param c             Character to print.
    135  * @param width         Width modifier.
    136  * @param flags         Flags that change the way the character is printed.
    137  *
    138  * @return              Number of characters printed, negative value on failure.
    139  */
    140 static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
    141 {
    142         int counter = 0;
    143        
     85/** Print one or more UTF-8 characters without adding newline.
     86 *
     87 * @param buf  Buffer holding UTF-8 characters with size of
     88 *             at least size bytes. NULL is not allowed!
     89 * @param size Size of the buffer in bytes.
     90 * @param ps   Output method and its data.
     91 *
     92 * @return Number of UTF-8 characters printed.
     93 *
     94 */
     95static int printf_putnchars_utf8(const char *buf, size_t size,
     96    printf_spec_t *ps)
     97{
     98        return ps->write_utf8((void *) buf, size, ps->data);
     99}
     100
     101/** Print one or more UTF-32 characters without adding newline.
     102 *
     103 * @param buf  Buffer holding UTF-32 characters with size of
     104 *             at least size bytes. NULL is not allowed!
     105 * @param size Size of the buffer in bytes.
     106 * @param ps   Output method and its data.
     107 *
     108 * @return Number of UTF-32 characters printed.
     109 *
     110 */
     111static int printf_putnchars_utf32(const wchar_t *buf, size_t size,
     112    printf_spec_t *ps)
     113{
     114        return ps->write_utf32((void *) buf, size, ps->data);
     115}
     116
     117/** Print UTF-8 string without adding a newline.
     118 *
     119 * @param str UTF-8 string to print.
     120 * @param ps  Write function specification and support data.
     121 *
     122 * @return Number of UTF-8 characters printed.
     123 *
     124 */
     125static int printf_putstr(const char *str, printf_spec_t *ps)
     126{
     127        if (str == NULL)
     128                return printf_putnchars_utf8(nullstr, strlen(nullstr), ps);
     129       
     130        return ps->write_utf8((void *) str, strlen(str), ps->data);
     131}
     132
     133/** Print one ASCII character.
     134 *
     135 * @param c  ASCII character to be printed.
     136 * @param ps Output method.
     137 *
     138 * @return Number of characters printed.
     139 *
     140 */
     141static int printf_putchar(const char ch, printf_spec_t *ps)
     142{
     143        if (!ascii_check(ch))
     144                return ps->write_utf8((void *) &invalch, 1, ps->data);
     145       
     146        return ps->write_utf8(&ch, 1, ps->data);
     147}
     148
     149/** Print one UTF-32 character.
     150 *
     151 * @param c  UTF-32 character to be printed.
     152 * @param ps Output method.
     153 *
     154 * @return Number of characters printed.
     155 *
     156 */
     157static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
     158{
     159        if (!unicode_check(ch))
     160                return ps->write_utf8((void *) &invalch, 1, ps->data);
     161       
     162        return ps->write_utf32(&ch, 1, ps->data);
     163}
     164
     165/** Print one formatted ASCII character.
     166 *
     167 * @param ch    Character to print.
     168 * @param width Width modifier.
     169 * @param flags Flags that change the way the character is printed.
     170 *
     171 * @return Number of characters printed, negative value on failure.
     172 *
     173 */
     174static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
     175{
     176        count_t counter = 0;
    144177        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    145178                while (--width > 0) {
     
    148181                         * the predecrement.
    149182                         */
    150                         if (printf_putchar(' ', ps) > 0)       
    151                                 ++counter;
    152                 }
    153         }
    154        
    155         if (printf_putchar(c, ps) > 0)
     183                        if (printf_putchar(' ', ps) > 0)
     184                                counter++;
     185                }
     186        }
     187       
     188        if (printf_putchar(ch, ps) > 0)
    156189                counter++;
    157 
     190       
    158191        while (--width > 0) {
     192                /*
     193                 * One space is consumed by the character itself, hence
     194                 * the predecrement.
     195                 */
     196                if (printf_putchar(' ', ps) > 0)
     197                        counter++;
     198        }
     199       
     200        return (int) (counter + 1);
     201}
     202
     203/** Print one formatted UTF-32 character.
     204 *
     205 * @param ch    Character to print.
     206 * @param width Width modifier.
     207 * @param flags Flags that change the way the character is printed.
     208 *
     209 * @return Number of characters printed, negative value on failure.
     210 *
     211 */
     212static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
     213{
     214        count_t counter = 0;
     215        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     216                while (--width > 0) {
    159217                        /*
    160218                         * One space is consumed by the character itself, hence
    161219                         * the predecrement.
    162220                         */
     221                        if (printf_putchar(' ', ps) > 0)
     222                                counter++;
     223                }
     224        }
     225       
     226        if (printf_putwchar(ch, ps) > 0)
     227                counter++;
     228       
     229        while (--width > 0) {
     230                /*
     231                 * One space is consumed by the character itself, hence
     232                 * the predecrement.
     233                 */
    163234                if (printf_putchar(' ', ps) > 0)
    164                         ++counter;
    165         }
    166        
    167         return ++counter;
    168 }
    169 
    170 /** Print string.
    171  *
    172  * @param s             String to be printed.
    173  * @param width         Width modifier.
    174  * @param precision     Precision modifier.
    175  * @param flags         Flags that modify the way the string is printed.
    176  *
    177  * @return              Number of characters printed, negative value on failure.
    178  */
    179 static int print_string(char *s, int width, unsigned int precision,
    180         uint64_t flags, struct printf_spec *ps)
    181 {
    182         int counter = 0;
    183         size_t size;
     235                        counter++;
     236        }
     237       
     238        return (int) (counter + 1);
     239}
     240
     241/** Print UTF-8 string.
     242 *
     243 * @param str       UTF-8 string to be printed.
     244 * @param width     Width modifier.
     245 * @param precision Precision modifier.
     246 * @param flags     Flags that modify the way the string is printed.
     247 *
     248 * @return Number of UTF-8 characters printed, negative value on failure.
     249 */
     250static int print_utf8(char *str, int width, unsigned int precision,
     251        uint32_t flags, printf_spec_t *ps)
     252{
     253        if (str == NULL)
     254                return printf_putstr(nullstr, ps);
     255       
     256        /* Print leading spaces */
     257        size_t size = strlen_utf8(str);
     258        if (precision == 0)
     259                precision = size;
     260       
     261        count_t counter = 0;
     262        width -= precision;
     263        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     264                while (width-- > 0) {
     265                        if (printf_putchar(' ', ps) == 1)
     266                                counter++;
     267                }
     268        }
     269       
    184270        int retval;
    185 
    186         if (s == NULL) {
    187                 return printf_putstr("(NULL)", ps);
    188         }
    189        
    190         size = strlen(s);
    191 
    192         /* print leading spaces */
    193 
    194         if (precision == 0)
     271        size_t bytes = utf8_count_bytes(str, min(size, precision));
     272        if ((retval = printf_putnchars_utf8(str, bytes, ps)) < 0)
     273                return -counter;
     274       
     275        counter += retval;
     276       
     277        while (width-- > 0) {
     278                if (printf_putchar(' ', ps) == 1)
     279                        counter++;
     280        }
     281       
     282        return ((int) counter);
     283}
     284
     285/** Print UTF-32 string.
     286 *
     287 * @param str       UTF-32 string to be printed.
     288 * @param width     Width modifier.
     289 * @param precision Precision modifier.
     290 * @param flags     Flags that modify the way the string is printed.
     291 *
     292 * @return Number of UTF-32 characters printed, negative value on failure.
     293 */
     294static int print_utf32(wchar_t *str, int width, unsigned int precision,
     295        uint32_t flags, printf_spec_t *ps)
     296{
     297        if (str == NULL)
     298                return printf_putstr(nullstr, ps);
     299       
     300        /* Print leading spaces */
     301        size_t size = strlen_utf32(str);
     302        if (precision == 0)
    195303                precision = size;
    196 
     304       
     305        count_t counter = 0;
    197306        width -= precision;
    198        
    199307        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    200                 while (width-- > 0) {   
    201                         if (printf_putchar(' ', ps) == 1)       
     308                while (width-- > 0) {
     309                        if (printf_putchar(' ', ps) == 1)
    202310                                counter++;
    203311                }
    204312        }
    205 
    206         if ((retval = printf_putnchars(s, min(size, precision), ps)) < 0) {
     313       
     314        int retval;
     315        size_t bytes = min(size, precision) * sizeof(wchar_t);
     316        if ((retval = printf_putnchars_utf32(str, bytes, ps)) < 0)
    207317                return -counter;
    208         }
    209         counter += retval;     
    210 
     318       
     319        counter += retval;
     320       
    211321        while (width-- > 0) {
    212                 if (printf_putchar(' ', ps) == 1)       
    213                         ++counter;
    214         }
    215        
    216         return counter;
    217 }
    218 
     322                if (printf_putchar(' ', ps) == 1)
     323                        counter++;
     324        }
     325       
     326        return ((int) counter);
     327}
    219328
    220329/** Print a number in a given base.
     
    222331 * Print significant digits of a number in given base.
    223332 *
    224  * @param num           Number to print.
    225  * @param widt          Width modifier.h
    226  * @param precision     Precision modifier.
    227  * @param base          Base to print the number in (must be between 2 and 16).
    228  * @param flags         Flags that modify the way the number is printed.       
    229  *
    230  * @return              Number of characters printed.
     333 * @param num       Number to print.
     334 * @param width     Width modifier.
     335 * @param precision Precision modifier.
     336 * @param base      Base to print the number in (must be between 2 and 16).
     337 * @param flags     Flags that modify the way the number is printed.
     338 *
     339 * @return Number of characters printed.
    231340 *
    232341 */
    233342static int print_number(uint64_t num, int width, int precision, int base,
    234     uint64_t flags, struct printf_spec *ps)
    235 {
    236         char *digits = digits_small;
    237         char d[PRINT_NUMBER_BUFFER_SIZE];
    238         char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
    239         int size = 0;           /* size of number with all prefixes and signs */
    240         int number_size;        /* size of plain number */
    241         char sgn;
    242         int retval;
    243         int counter = 0;
    244        
    245         if (flags & __PRINTF_FLAG_BIGCHARS)
    246                 digits = digits_big;   
    247        
    248         *ptr-- = 0; /* Put zero at end of string */
    249 
     343    uint32_t flags, printf_spec_t *ps)
     344{
     345        char *digits;
     346        if (flags & __PRINTF_FLAG_BIGCHARS)
     347                digits = digits_big;
     348        else
     349                digits = digits_small;
     350       
     351        char data[PRINT_NUMBER_BUFFER_SIZE];
     352        char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
     353       
     354        /* Size of number with all prefixes and signs */
     355        int size = 0;
     356       
     357        /* Put zero at end of string */
     358        *ptr-- = 0;
     359       
    250360        if (num == 0) {
    251361                *ptr-- = '0';
     
    258368        }
    259369       
    260         number_size = size;
    261 
     370        /* Size of plain number */
     371        int number_size = size;
     372       
    262373        /*
    263          * Collect the sum of all prefixes/signs/... to calculate padding and
     374         * Collect the sum of all prefixes/signs/etc. to calculate padding and
    264375         * leading zeroes.
    265376         */
    266377        if (flags & __PRINTF_FLAG_PREFIX) {
    267378                switch(base) {
    268                 case 2: /* Binary formating is not standard, but usefull */
     379                case 2:
     380                        /* Binary formating is not standard, but usefull */
    269381                        size += 2;
    270382                        break;
     
    277389                }
    278390        }
    279 
    280         sgn = 0;
     391       
     392        char sgn = 0;
    281393        if (flags & __PRINTF_FLAG_SIGNED) {
    282394                if (flags & __PRINTF_FLAG_NEGATIVE) {
     
    291403                }
    292404        }
    293 
    294         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     405       
     406        if (flags & __PRINTF_FLAG_LEFTALIGNED)
    295407                flags &= ~__PRINTF_FLAG_ZEROPADDED;
    296         }
    297 
     408       
    298409        /*
    299          * If the number is leftaligned or precision is specified then
    300          * zeropadding is ignored.
     410         * If the number is left-aligned or precision is specified then
     411         * padding with zeros is ignored.
    301412         */
    302413        if (flags & __PRINTF_FLAG_ZEROPADDED) {
    303                 if ((precision == 0) && (width > size)) {
     414                if ((precision == 0) && (width > size))
    304415                        precision = width - size + number_size;
    305                 }
    306         }
    307 
    308         /* print leading spaces */
     416        }
     417       
     418        /* Print leading spaces */
    309419        if (number_size > precision) {
    310                 /* print the whole number not only a part */
     420                /* Print the whole number, not only a part */
    311421                precision = number_size;
    312422        }
    313 
     423       
    314424        width -= precision + size - number_size;
     425        count_t counter = 0;
    315426       
    316427        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    317                 while (width-- > 0) {   
    318                         if (printf_putchar(' ', ps) == 1)       
     428                while (width-- > 0) {
     429                        if (printf_putchar(' ', ps) == 1)
    319430                                counter++;
    320431                }
    321432        }
    322433       
    323        
    324         /* print sign */
     434        /* Print sign */
    325435        if (sgn) {
    326436                if (printf_putchar(sgn, ps) == 1)
     
    328438        }
    329439       
    330         /* print prefix */
    331        
     440        /* Print prefix */
    332441        if (flags & __PRINTF_FLAG_PREFIX) {
    333442                switch(base) {
    334                 case 2: /* Binary formating is not standard, but usefull */
     443                case 2:
     444                        /* Binary formating is not standard, but usefull */
    335445                        if (printf_putchar('0', ps) == 1)
    336446                                counter++;
     
    360470                }
    361471        }
    362 
    363         /* print leading zeroes */
     472       
     473        /* Print leading zeroes */
    364474        precision -= number_size;
    365         while (precision-- > 0) {       
     475        while (precision-- > 0) {
    366476                if (printf_putchar('0', ps) == 1)
    367477                        counter++;
    368478        }
    369 
    370        
    371         /* print number itself */
    372 
    373         if ((retval = printf_putstr(++ptr, ps)) > 0) {
     479       
     480        /* Print the number itself */
     481        int retval;
     482        if ((retval = printf_putstr(++ptr, ps)) > 0)
    374483                counter += retval;
    375         }
    376        
    377         /* print ending spaces */
    378        
    379         while (width-- > 0) {   
    380                 if (printf_putchar(' ', ps) == 1)       
     484       
     485        /* Print tailing spaces */
     486       
     487        while (width-- > 0) {
     488                if (printf_putchar(' ', ps) == 1)
    381489                        counter++;
    382490        }
    383 
    384         return counter;
    385 }
    386 
     491       
     492        return ((int) counter);
     493}
    387494
    388495/** Print formatted string.
     
    390497 * Print string formatted according to the fmt parameter and variadic arguments.
    391498 * Each formatting directive must have the following form:
    392  * 
    393  *      \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
     499 *
     500 *  \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
    394501 *
    395502 * FLAGS:@n
    396  *      - "#"   Force to print prefix.For \%o conversion, the prefix is 0, for
    397  *              \%x and \%X prefixes are 0x and 0X and for conversion \%b the
    398  *              prefix is 0b.
    399  *
    400  *      - "-"   Align to left.
    401  *
    402  *      - "+"   Print positive sign just as negative.
    403  *
    404  *      - " "   If the printed number is positive and "+" flag is not set,
    405  *              print space in place of sign.
    406  *
    407  *      - "0"   Print 0 as padding instead of spaces. Zeroes are placed between
    408  *              sign and the rest of the number. This flag is ignored if "-"
    409  *              flag is specified.
    410  * 
     503 *  - "#" Force to print prefix. For \%o conversion, the prefix is 0, for
     504 *        \%x and \%X prefixes are 0x and 0X and for conversion \%b the
     505 *        prefix is 0b.
     506 *
     507 *  - "-" Align to left.
     508 *
     509 *  - "+" Print positive sign just as negative.
     510 *
     511 *  - " " If the printed number is positive and "+" flag is not set,
     512 *        print space in place of sign.
     513 *
     514 *  - "0" Print 0 as padding instead of spaces. Zeroes are placed between
     515 *        sign and the rest of the number. This flag is ignored if "-"
     516 *        flag is specified.
     517 *
    411518 * WIDTH:@n
    412  *      - Specify the minimal width of a printed argument. If it is bigger,
    413  *      width is ignored. If width is specified with a "*" character instead of
    414  *      number, width is taken from parameter list. And integer parameter is
    415  *      expected before parameter for processed conversion specification. If
    416  *      this value is negative its absolute value is taken and the "-" flag is
    417  *      set.
     519 *  - Specify the minimal width of a printed argument. If it is bigger,
     520 *    width is ignored. If width is specified with a "*" character instead of
     521 *    number, width is taken from parameter list. And integer parameter is
     522 *    expected before parameter for processed conversion specification. If
     523 *    this value is negative its absolute value is taken and the "-" flag is
     524 *    set.
    418525 *
    419526 * PRECISION:@n
    420  *      - Value precision. For numbers it specifies minimum valid numbers.
    421  *      Smaller numbers are printed with leading zeroes. Bigger numbers are not
    422  *      affected. Strings with more than precision characters are cut off. Just
    423  *      as with width, an "*" can be used used instead of a number. An integer
    424  *      value is then expected in parameters. When both width and precision are
    425  *      specified using "*", the first parameter is used for width and the
    426  *      second one for precision.
    427  * 
     527 *  - Value precision. For numbers it specifies minimum valid numbers.
     528 *    Smaller numbers are printed with leading zeroes. Bigger numbers are not
     529 *    affected. Strings with more than precision characters are cut off. Just
     530 *    as with width, an "*" can be used used instead of a number. An integer
     531 *    value is then expected in parameters. When both width and precision are
     532 *    specified using "*", the first parameter is used for width and the
     533 *    second one for precision.
     534 *
    428535 * TYPE:@n
    429  *      - "hh"  Signed or unsigned char.@n
    430  *      - "h"   Signed or unsigned short.@n
    431  *      - ""    Signed or unsigned int (default value).@n
    432  *      - "l"   Signed or unsigned long int.@n
    433  *      - "ll"  Signed or unsigned long long int.@n
    434  *
    435  *
     536 *  - "hh" Signed or unsigned char.@n
     537 *  - "h"  Signed or unsigned short.@n
     538 *  - ""   Signed or unsigned int (default value).@n
     539 *  - "l"  Signed or unsigned long int.@n
     540 *         If conversion is "c", the character is wchar_t (UTF-32).@n
     541 *         If conversion is "s", the string is wchar_t * (UTF-32).@n
     542 *  - "ll" Signed or unsigned long long int.@n
     543 *
    436544 * CONVERSION:@n
    437  *      - %     Print percentile character itself.
    438  *
    439  *      - c     Print single character.
    440  *
    441  *      - s     Print zero terminated string. If a NULL value is passed as
    442  *              value, "(NULL)" is printed instead.
    443  *
    444  *      - P, p  Print value of a pointer. Void * value is expected and it is
    445  *              printed in hexadecimal notation with prefix (as with \%#X / \%#x
    446  *              for 32-bit or \%#X / \%#x for 64-bit long pointers).
    447  *
    448  *      - b     Print value as unsigned binary number. Prefix is not printed by
    449  *              default. (Nonstandard extension.)
    450  *
    451  *      - o     Print value as unsigned octal number. Prefix is not printed by
    452  *              default.
    453  *
    454  *      - d, i  Print signed decimal number. There is no difference between d
    455  *              and i conversion.
    456  *
    457  *      - u     Print unsigned decimal number.
    458  *
    459  *      - X, x  Print hexadecimal number with upper- or lower-case. Prefix is
    460  *              not printed by default.
    461  *
     545 *  - % Print percentile character itself.
     546 *
     547 *  - c Print single character. The character is expected to be plain
     548 *      ASCII (e.g. only values 0 .. 127 are valid).@n
     549 *      If type is "l", then the character is expected to be UTF-32
     550 *      (e.g. values 0 .. 0x10ffff are valid).
     551 *
     552 *  - s Print zero terminated string. If a NULL value is passed as
     553 *      value, "(NULL)" is printed instead.@n
     554 *      The string is expected to be correctly encoded UTF-8 (or plain
     555 *      ASCII, which is a subset of UTF-8).@n
     556 *      If type is "l", then the string is expected to be correctly
     557 *      encoded UTF-32.
     558 *
     559 *  - P, p Print value of a pointer. Void * value is expected and it is
     560 *         printed in hexadecimal notation with prefix (as with \%#X / \%#x
     561 *         for 32-bit or \%#X / \%#x for 64-bit long pointers).
     562 *
     563 *  - b Print value as unsigned binary number. Prefix is not printed by
     564 *      default. (Nonstandard extension.)
     565 *
     566 *  - o Print value as unsigned octal number. Prefix is not printed by
     567 *      default.
     568 *
     569 *  - d, i Print signed decimal number. There is no difference between d
     570 *         and i conversion.
     571 *
     572 *  - u Print unsigned decimal number.
     573 *
     574 *  - X, x Print hexadecimal number with upper- or lower-case. Prefix is
     575 *         not printed by default.
     576 *
    462577 * All other characters from fmt except the formatting directives are printed in
    463578 * verbatim.
    464579 *
    465  * @param fmt           Formatting NULL terminated string.
    466  * @return              Number of characters printed, negative value on failure.
    467  */
    468 int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
    469 {
    470         int i = 0; /* index of the currently processed char from fmt */
    471         int j = 0; /* index to the first not printed nonformating character */
    472         int end;
    473         int counter; /* counter of printed characters */
    474         int retval; /* used to store return values from called functions */
    475         char c;
    476         qualifier_t qualifier; /* type of argument */
    477         int base; /* base in which a numeric parameter will be printed */
    478         uint64_t number; /* argument value */
    479         size_t  size; /* byte size of integer parameter */
    480         int width, precision;
    481         uint64_t flags;
    482        
    483         counter = 0;
    484                
    485         while ((c = fmt[i])) {
    486                 /* control character */
    487                 if (c == '%') {
    488                         /* print common characters if any processed */ 
     580 * @param fmt Formatting NULL terminated string (UTF-8 or plain ASCII).
     581 *
     582 * @return Number of UTF-8 characters printed, negative value on failure.
     583 *
     584 */
     585int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
     586{
     587        index_t i = 0;  /* Index of the currently processed character from fmt */
     588        index_t j = 0;  /* Index to the first not printed nonformating character */
     589       
     590        wchar_t uc;           /* Current UTF-32 character decoded from fmt */
     591        count_t counter = 0;  /* Number of UTF-8 characters printed */
     592        int retval;           /* Return values from nested functions */
     593       
     594        while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
     595                /* Control character */
     596                if (uc == '%') {
     597                        /* Print common characters if any processed */
    489598                        if (i > j) {
    490                                 if ((retval = printf_putnchars(&fmt[j],
    491                                     (size_t)(i - j), ps)) < 0) { /* error */
     599                                if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
     600                                        /* Error */
    492601                                        counter = -counter;
    493602                                        goto out;
     
    495604                                counter += retval;
    496605                        }
    497                
     606                       
    498607                        j = i;
    499                         /* parse modifiers */
    500                         flags = 0;
    501                         end = 0;
     608                       
     609                        /* Parse modifiers */
     610                        uint32_t flags = 0;
     611                        bool end = false;
    502612                       
    503613                        do {
    504                                 ++i;
    505                                 switch (c = fmt[i]) {
     614                                i++;
     615                                switch ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
    506616                                case '#':
    507617                                        flags |= __PRINTF_FLAG_PREFIX;
     
    520630                                        break;
    521631                                default:
    522                                         end = 1;
    523                                 };     
    524                                
    525                         } while (end == 0);     
    526                        
    527                         /* width & '*' operator */
    528                         width = 0;
    529                         if (isdigit(fmt[i])) {
    530                                 while (isdigit(fmt[i])) {
     632                                        end = true;
     633                                };
     634                        } while (!end);
     635                       
     636                        /* Width & '*' operator */
     637                        int width = 0;
     638                        if (isdigit(uc)) {
     639                                while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
     640                                        if (!isdigit(uc))
     641                                                break;
     642                                       
    531643                                        width *= 10;
    532                                         width += fmt[i++] - '0';
     644                                        width += uc - '0';
     645                                        i++;
    533646                                }
    534                         } else if (fmt[i] == '*') {
    535                                 /* get width value from argument list */
     647                        } else if (uc == '*') {
     648                                /* Get width value from argument list */
    536649                                i++;
     650                                uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
    537651                                width = (int) va_arg(ap, int);
    538652                                if (width < 0) {
    539                                         /* negative width sets '-' flag */
     653                                        /* Negative width sets '-' flag */
    540654                                        width *= -1;
    541655                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     
    543657                        }
    544658                       
    545                         /* precision and '*' operator */       
    546                         precision = 0;
    547                         if (fmt[i] == '.') {
    548                                 ++i;
    549                                 if (isdigit(fmt[i])) {
    550                                         while (isdigit(fmt[i])) {
     659                        /* Precision and '*' operator */
     660                        int precision = 0;
     661                        if (uc == '.') {
     662                                i++;
     663                                uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
     664                                if (isdigit(uc)) {
     665                                        while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
     666                                                if (!isdigit(uc))
     667                                                        break;
     668                                               
    551669                                                precision *= 10;
    552                                                 precision += fmt[i++] - '0';
     670                                                precision += uc - '0';
     671                                                i++;
    553672                                        }
    554673                                } else if (fmt[i] == '*') {
    555                                         /*
    556                                          * Get precision value from the argument
    557                                          * list.
    558                                          */
     674                                        /* Get precision value from the argument list */
    559675                                        i++;
     676                                        uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
    560677                                        precision = (int) va_arg(ap, int);
    561678                                        if (precision < 0) {
    562                                                 /* ignore negative precision */
     679                                                /* Ignore negative precision */
    563680                                                precision = 0;
    564681                                        }
    565682                                }
    566683                        }
    567 
    568                         switch (fmt[i++]) {
    569                         /** @todo unimplemented qualifiers:
    570                          * t ptrdiff_t - ISO C 99
     684                       
     685                        qualifier_t qualifier;
     686                       
     687                        switch (uc) {
     688                        /** @todo Unimplemented qualifiers:
     689                         *        t ptrdiff_t - ISO C 99
    571690                         */
    572                         case 'h':       /* char or short */
     691                        case 'h':
     692                                /* Char or short */
    573693                                qualifier = PrintfQualifierShort;
    574                                 if (fmt[i] == 'h') {
     694                                i++;
     695                                uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
     696                                if (uc == 'h') {
    575697                                        i++;
     698                                        uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
    576699                                        qualifier = PrintfQualifierByte;
    577700                                }
    578701                                break;
    579                         case 'l':       /* long or long long*/
     702                        case 'l':
     703                                /* Long or long long */
    580704                                qualifier = PrintfQualifierLong;
    581                                 if (fmt[i] == 'l') {
     705                                i++;
     706                                uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
     707                                if (uc == 'l') {
    582708                                        i++;
     709                                        uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
    583710                                        qualifier = PrintfQualifierLongLong;
    584711                                }
    585712                                break;
    586713                        default:
    587                                 /* default type */
    588                                 qualifier = PrintfQualifierInt;
    589                                 --i;
    590                         }       
    591                        
    592                         base = 10;
    593 
    594                         switch (c = fmt[i]) {
    595 
     714                                /* Default type */
     715                                qualifier = PrintfQualifierInt;
     716                        }
     717                       
     718                        unsigned int base = 10;
     719                       
     720                        switch (uc) {
    596721                        /*
    597                         * String and character conversions.
    598                         */
     722                         * String and character conversions.
     723                         */
    599724                        case 's':
    600                                 if ((retval = print_string(va_arg(ap, char *),
    601                                     width, precision, flags, ps)) < 0) {
     725                                if (qualifier == PrintfQualifierLong)
     726                                        retval = print_utf32(va_arg(ap, wchar_t *), width, precision, flags, ps);
     727                                else
     728                                        retval = print_utf8(va_arg(ap, char *), width, precision, flags, ps);
     729                               
     730                                if (retval < 0) {
    602731                                        counter = -counter;
    603732                                        goto out;
    604                                 };
    605 
     733                                }
     734                               
    606735                                counter += retval;
    607                                 j = i + 1; 
     736                                j = i + 1;
    608737                                goto next_char;
    609738                        case 'c':
    610                                 c = va_arg(ap, unsigned int);
    611                                 retval = print_char(c, width, flags, ps);
     739                                if (qualifier == PrintfQualifierLong)
     740                                        retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps);
     741                                else
     742                                        retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
     743                               
    612744                                if (retval < 0) {
    613745                                        counter = -counter;
    614746                                        goto out;
    615747                                };
    616                                        
     748                               
    617749                                counter += retval;
    618750                                j = i + 1;
    619751                                goto next_char;
    620 
    621                         /* 
     752                       
     753                        /*
    622754                         * Integer values
    623755                         */
    624                         case 'P': /* pointer */
     756                        case 'P':
     757                                /* Pointer */
    625758                                flags |= __PRINTF_FLAG_BIGCHARS;
    626759                        case 'p':
     
    628761                                base = 16;
    629762                                qualifier = PrintfQualifierPointer;
    630                                 break; 
    631                         case 'b': 
     763                                break;
     764                        case 'b':
    632765                                base = 2;
    633766                                break;
     
    637770                        case 'd':
    638771                        case 'i':
    639                                 flags |= __PRINTF_FLAG_SIGNED; 
     772                                flags |= __PRINTF_FLAG_SIGNED;
    640773                        case 'u':
    641774                                break;
     
    645778                                base = 16;
    646779                                break;
    647                         /* percentile itself */
    648                         case '%':
     780                       
     781                        /* Percentile itself */
     782                        case '%':
    649783                                j = i;
    650784                                goto next_char;
     785                       
    651786                        /*
    652787                         * Bad formatting.
     
    657792                                 * so we will print whole bad format sequence.
    658793                                 */
    659                                 goto next_char;         
    660                         }
    661                
    662                
    663                 /* Print integers */
    664                         /* print number */
     794                                goto next_char;
     795                        }
     796                       
     797                        /* Print integers */
     798                        size_t size;
     799                        uint64_t number;
    665800                        switch (qualifier) {
    666801                        case PrintfQualifierByte:
     
    688823                                number = (uint64_t) (unsigned long) va_arg(ap, void *);
    689824                                break;
    690                         default: /* Unknown qualifier */
     825                        default:
     826                                /* Unknown qualifier */
    691827                                counter = -counter;
    692828                                goto out;
     
    696832                                if (number & (0x1 << (size * 8 - 1))) {
    697833                                        flags |= __PRINTF_FLAG_NEGATIVE;
    698                                
     834                                       
    699835                                        if (size == sizeof(uint64_t)) {
    700836                                                number = -((int64_t) number);
     
    708844                                }
    709845                        }
    710 
     846                       
    711847                        if ((retval = print_number(number, width, precision,
    712848                            base, flags, ps)) < 0) {
     
    714850                                goto out;
    715851                        }
    716 
     852                       
    717853                        counter += retval;
    718854                        j = i + 1;
    719                 }       
     855                }
    720856next_char:
    721                        
    722                 ++i;
     857               
     858                i++;
    723859        }
    724860       
    725861        if (i > j) {
    726                 if ((retval = printf_putnchars(&fmt[j], (unative_t) (i - j),
    727                     ps)) < 0) { /* error */
     862                if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
     863                        /* Error */
    728864                        counter = -counter;
    729865                        goto out;
    730                        
    731866                }
    732867                counter += retval;
    733868        }
    734 
     869       
    735870out:
    736         return counter;
     871        return ((int) counter);
    737872}
    738873
  • kernel/generic/src/printf/snprintf.c

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    4343        va_start(args, fmt);
    4444        ret = vsnprintf(str, size, fmt, args);
    45 
     45       
    4646        va_end(args);
    47 
     47       
    4848        return ret;
    4949}
  • kernel/generic/src/printf/vprintf.c

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    4040#include <arch/types.h>
    4141#include <typedefs.h>
     42#include <string.h>
    4243
    43 SPINLOCK_INITIALIZE(printf_lock);                       /**< vprintf spinlock */
     44SPINLOCK_INITIALIZE(printf_lock);  /**< vprintf spinlock */
    4445
    45 static int vprintf_write(const char *str, size_t count, void *unused)
     46static int vprintf_write_utf8(const char *str, size_t size, void *data)
    4647{
    47         size_t i;
    48         for (i = 0; i < count; i++)
    49                 putchar(str[i]);
    50         return i;
     48        index_t index = 0;
     49        index_t chars = 0;
     50       
     51        while (index < size) {
     52                putchar(utf8_decode(str, &index, size - 1));
     53                index++;
     54                chars++;
     55        }
     56       
     57        return chars;
    5158}
    5259
    53 int puts(const char *s)
     60static int vprintf_write_utf32(const wchar_t *str, size_t size, void *data)
    5461{
    55         size_t i;
    56         for (i = 0; s[i] != 0; i++)
    57                 putchar(s[i]);
    58         return i;
     62        index_t index = 0;
     63       
     64        while (index < (size / sizeof(wchar_t))) {
     65                putchar(str[index]);
     66                index++;
     67        }
     68       
     69        return index;
     70}
     71
     72int puts(const char *str)
     73{
     74        index_t index = 0;
     75        index_t chars = 0;
     76        wchar_t uc;
     77       
     78        while ((uc = utf8_decode(str, &index, UTF8_NO_LIMIT)) != 0) {
     79                putchar(uc);
     80                index++;
     81                chars++;
     82        }
     83       
     84        return chars;
    5985}
    6086
    6187int vprintf(const char *fmt, va_list ap)
    6288{
    63         struct printf_spec ps = {(int(*)(void *, size_t, void *)) vprintf_write, NULL};
     89        printf_spec_t ps = {
     90                vprintf_write_utf8,
     91                vprintf_write_utf32,
     92                NULL
     93        };
    6494       
    6595        ipl_t ipl = interrupts_disable();
  • kernel/generic/src/printf/vsnprintf.c

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3535#include <print.h>
    3636#include <printf/printf_core.h>
     37#include <string.h>
    3738#include <memstr.h>
    3839
    39 struct vsnprintf_data {
    40         size_t size; /* total space for string */
    41         size_t len; /* count of currently used characters */
    42         char *string; /* destination string */
    43 };
     40typedef struct {
     41        size_t size;    /* Total size of the buffer (in bytes) */
     42        size_t len;     /* Number of already used bytes */
     43        char *dst;      /* Destination */
     44} vsnprintf_data_t;
    4445
    45 /** Write string to given buffer.
    46  * Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number
    47  * of characters that would have been written if enough space had been available. Hence the return value is not
    48  * number of really printed characters but size of the input string. Number of really used characters
    49  * is stored in data->len.
    50  * @param str source string to print
    51  * @param count size of source string
    52  * @param data structure with destination string, counter of used space and total string size.
    53  * @return number of characters to print (not characters really printed!)
     46/** Write UTF-8 string to given buffer.
     47 *
     48 * Write at most data->size plain characters including trailing zero.
     49 * According to C99, snprintf() has to return number of characters that
     50 * would have been written if enough space had been available. Hence
     51 * the return value is not the number of actually printed characters
     52 * but size of the input string.
     53 *
     54 * @param str  Source UTF-8 string to print.
     55 * @param size Number of plain characters in str.
     56 * @param data Structure describing destination string, counter
     57 *             of used space and total string size.
     58 *
     59 * @return Number of UTF-8 characters to print (not characters actually
     60 *         printed).
     61 *
    5462 */
    55 static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
     63static int vsnprintf_write_utf8(const char *str, size_t size, vsnprintf_data_t *data)
    5664{
    57         size_t i;
    58         i = data->size - data->len;
    59 
    60         if (i == 0) {
    61                 return count;
     65        size_t left = data->size - data->len;
     66       
     67        if (left == 0)
     68                return ((int) size);
     69       
     70        if (left == 1) {
     71                /* We have only one free byte left in buffer
     72                 * -> store trailing zero
     73                 */
     74                data->dst[data->size - 1] = 0;
     75                data->len = data->size;
     76                return ((int) size);
    6277        }
    6378       
    64         if (i == 1) {
    65                 /* We have only one free byte left in buffer => write there trailing zero */
    66                 data->string[data->size - 1] = 0;
    67                 data->len = data->size;
    68                 return count;
     79        if (left <= size) {
     80                /* We have not enought space for whole string
     81                 * with the trailing zero => print only a part
     82                 * of string
     83                 */
     84                index_t index = 0;
     85               
     86                while (index < size) {
     87                        wchar_t uc = utf8_decode(str, &index, size - 1);
     88                       
     89                        if (!utf8_encode(uc, data->dst, &data->len, data->size - 1))
     90                                break;
     91                       
     92                        data->len++;
     93                        index++;
     94                }
     95               
     96                /* Put trailing zero at end, but not count it
     97                 * into data->len so it could be rewritten next time
     98                 */
     99                data->dst[data->len] = 0;
     100               
     101                return ((int) size);
    69102        }
    70103       
    71         if (i <= count) {
    72                 /* We have not enought space for whole string with the trailing zero => print only a part of string */
    73                         memcpy((void *)(data->string + data->len), (void *)str, i - 1);
    74                         data->string[data->size - 1] = 0;
     104        /* Buffer is big enought to print the whole string */
     105        memcpy((void *)(data->dst + data->len), (void *) str, size);
     106        data->len += size;
     107       
     108        /* Put trailing zero at end, but not count it
     109         * into data->len so it could be rewritten next time
     110         */
     111        data->dst[data->len] = 0;
     112       
     113        return ((int) size);
     114}
     115
     116/** Write UTF-32 string to given buffer.
     117 *
     118 * Write at most data->size plain characters including trailing zero.
     119 * According to C99, snprintf() has to return number of characters that
     120 * would have been written if enough space had been available. Hence
     121 * the return value is not the number of actually printed characters
     122 * but size of the input string.
     123 *
     124 * @param str  Source UTF-32 string to print.
     125 * @param size Number of bytes in str.
     126 * @param data Structure describing destination string, counter
     127 *             of used space and total string size.
     128 *
     129 * @return Number of UTF-8 characters to print (not characters actually
     130 *         printed).
     131 *
     132 */
     133static int vsnprintf_write_utf32(const wchar_t *str, size_t size, vsnprintf_data_t *data)
     134{
     135        index_t index = 0;
     136       
     137        while (index < (size / sizeof(wchar_t))) {
     138                size_t left = data->size - data->len;
     139               
     140                if (left == 0)
     141                        return ((int) size);
     142               
     143                if (left == 1) {
     144                        /* We have only one free byte left in buffer
     145                         * -> store trailing zero
     146                         */
     147                        data->dst[data->size - 1] = 0;
    75148                        data->len = data->size;
    76                         return count;
     149                        return ((int) size);
     150                }
     151               
     152                if (!utf8_encode(str[index], data->dst, &data->len, data->size - 1))
     153                        break;
     154               
     155                data->len++;
     156                index++;
    77157        }
    78158       
    79         /* Buffer is big enought to print whole string */
    80         memcpy((void *)(data->string + data->len), (void *)str, count);
    81         data->len += count;
    82         /* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */
    83         data->string[data->len] = 0;
    84 
    85         return count;   
     159        /* Put trailing zero at end, but not count it
     160         * into data->len so it could be rewritten next time
     161         */
     162        data->dst[data->len] = 0;
     163       
     164        return ((int) size);
    86165}
    87166
    88167int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
    89168{
    90         struct vsnprintf_data data = {size, 0, str};
    91         struct printf_spec ps = {(int(*)(void *, size_t, void *))vsnprintf_write, &data};
    92 
     169        vsnprintf_data_t data = {
     170                size,
     171                0,
     172                str
     173        };
     174        printf_spec_t ps = {
     175                (int(*) (const char *, size_t, void *)) vsnprintf_write_utf8,
     176                (int(*) (const wchar_t *, size_t, void *)) vsnprintf_write_utf32,
     177                &data
     178        };
     179       
    93180        /* Print 0 at end of string - fix the case that nothing will be printed */
    94181        if (size > 0)
  • kernel/generic/src/syscall/syscall.c

    r74c8da2c reec616b  
    4242#include <mm/as.h>
    4343#include <print.h>
    44 #include <putchar.h>
    4544#include <arch.h>
    4645#include <debug.h>
Note: See TracChangeset for help on using the changeset viewer.