]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[libc] Add support for "%lc" and "%ls" format specifiers
authorMichael Brown <mcb30@ipxe.org>
Thu, 19 Jul 2012 12:57:17 +0000 (13:57 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 19 Jul 2012 15:33:33 +0000 (16:33 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/vsprintf.c
src/include/stddef.h

index b721b024114d2f598eb8b17caae2e72a6f719339..dd1a101df3b5c5c4731928e36ea55641daf93840 100644 (file)
@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <stdarg.h>
 #include <stdio.h>
 #include <errno.h>
+#include <wchar.h>
 #include <ipxe/vsprintf.h>
 
 /** @file */
@@ -185,6 +186,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
        char *ptr;
        char tmp_buf[32]; /* 32 is enough for all numerical formats.
                           * Insane width fields could overflow this buffer. */
+       wchar_t *wptr;
 
        /* Initialise context */
        ctx->len = 0;
@@ -234,11 +236,26 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
                /* Process conversion specifier */
                ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
                *ptr = '\0';
+               wptr = NULL;
                if ( *fmt == 'c' ) {
-                       cputchar ( ctx, va_arg ( args, unsigned int ) );
+                       if ( length < &type_sizes[LONG_LEN] ) {
+                               cputchar ( ctx, va_arg ( args, unsigned int ) );
+                       } else {
+                               wchar_t wc;
+                               size_t len;
+
+                               wc = va_arg ( args, wint_t );
+                               len = wcrtomb ( tmp_buf, wc, NULL );
+                               tmp_buf[len] = '\0';
+                               ptr = tmp_buf;
+                       }
                } else if ( *fmt == 's' ) {
-                       ptr = va_arg ( args, char * );
-                       if ( ! ptr )
+                       if ( length < &type_sizes[LONG_LEN] ) {
+                               ptr = va_arg ( args, char * );
+                       } else {
+                               wptr = va_arg ( args, wchar_t * );
+                       }
+                       if ( ( ptr == NULL ) && ( wptr == NULL ) )
                                ptr = "<NULL>";
                } else if ( *fmt == 'p' ) {
                        intptr_t ptrval;
@@ -271,8 +288,17 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
                        *(--ptr) = *fmt;
                }
                /* Write out conversion result */
-               for ( ; *ptr ; ptr++ ) {
-                       cputchar ( ctx, *ptr );
+               if ( wptr == NULL ) {
+                       for ( ; *ptr ; ptr++ ) {
+                               cputchar ( ctx, *ptr );
+                       }
+               } else {
+                       for ( ; *wptr ; wptr++ ) {
+                               size_t len = wcrtomb ( tmp_buf, *wptr, NULL );
+                               for ( ptr = tmp_buf ; len-- ; ptr++ ) {
+                                       cputchar ( ctx, *ptr );
+                               }
+                       }
                }
        }
 
index c91a103f836f2aa85110a04f653477d8ddba4fe1..83a0f0ed661ce5d04083c4b4a0fe66eed415d87e 100644 (file)
@@ -26,5 +26,6 @@ FILE_LICENCE ( GPL2_ONLY );
 #define __WCHAR_TYPE__ long int
 #endif
 typedef __WCHAR_TYPE__ wchar_t;
+typedef __WINT_TYPE__ wint_t;
 
 #endif /* STDDEF_H */