|  | @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 22 | 22 |  #include <stdarg.h>
 | 
		
	
		
			
			| 23 | 23 |  #include <stdio.h>
 | 
		
	
		
			
			| 24 | 24 |  #include <errno.h>
 | 
		
	
		
			
			|  | 25 | +#include <wchar.h>
 | 
		
	
		
			
			| 25 | 26 |  #include <ipxe/vsprintf.h>
 | 
		
	
		
			
			| 26 | 27 |  
 | 
		
	
		
			
			| 27 | 28 |  /** @file */
 | 
		
	
	
		
			
			|  | @@ -185,6 +186,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
 | 
		
	
		
			
			| 185 | 186 |  	char *ptr;
 | 
		
	
		
			
			| 186 | 187 |  	char tmp_buf[32]; /* 32 is enough for all numerical formats.
 | 
		
	
		
			
			| 187 | 188 |  			   * Insane width fields could overflow this buffer. */
 | 
		
	
		
			
			|  | 189 | +	wchar_t *wptr;
 | 
		
	
		
			
			| 188 | 190 |  
 | 
		
	
		
			
			| 189 | 191 |  	/* Initialise context */
 | 
		
	
		
			
			| 190 | 192 |  	ctx->len = 0;
 | 
		
	
	
		
			
			|  | @@ -234,11 +236,26 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
 | 
		
	
		
			
			| 234 | 236 |  		/* Process conversion specifier */
 | 
		
	
		
			
			| 235 | 237 |  		ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
 | 
		
	
		
			
			| 236 | 238 |  		*ptr = '\0';
 | 
		
	
		
			
			|  | 239 | +		wptr = NULL;
 | 
		
	
		
			
			| 237 | 240 |  		if ( *fmt == 'c' ) {
 | 
		
	
		
			
			| 238 |  | -			cputchar ( ctx, va_arg ( args, unsigned int ) );
 | 
		
	
		
			
			|  | 241 | +			if ( length < &type_sizes[LONG_LEN] ) {
 | 
		
	
		
			
			|  | 242 | +				cputchar ( ctx, va_arg ( args, unsigned int ) );
 | 
		
	
		
			
			|  | 243 | +			} else {
 | 
		
	
		
			
			|  | 244 | +				wchar_t wc;
 | 
		
	
		
			
			|  | 245 | +				size_t len;
 | 
		
	
		
			
			|  | 246 | +
 | 
		
	
		
			
			|  | 247 | +				wc = va_arg ( args, wint_t );
 | 
		
	
		
			
			|  | 248 | +				len = wcrtomb ( tmp_buf, wc, NULL );
 | 
		
	
		
			
			|  | 249 | +				tmp_buf[len] = '\0';
 | 
		
	
		
			
			|  | 250 | +				ptr = tmp_buf;
 | 
		
	
		
			
			|  | 251 | +			}
 | 
		
	
		
			
			| 239 | 252 |  		} else if ( *fmt == 's' ) {
 | 
		
	
		
			
			| 240 |  | -			ptr = va_arg ( args, char * );
 | 
		
	
		
			
			| 241 |  | -			if ( ! ptr )
 | 
		
	
		
			
			|  | 253 | +			if ( length < &type_sizes[LONG_LEN] ) {
 | 
		
	
		
			
			|  | 254 | +				ptr = va_arg ( args, char * );
 | 
		
	
		
			
			|  | 255 | +			} else {
 | 
		
	
		
			
			|  | 256 | +				wptr = va_arg ( args, wchar_t * );
 | 
		
	
		
			
			|  | 257 | +			}
 | 
		
	
		
			
			|  | 258 | +			if ( ( ptr == NULL ) && ( wptr == NULL ) )
 | 
		
	
		
			
			| 242 | 259 |  				ptr = "<NULL>";
 | 
		
	
		
			
			| 243 | 260 |  		} else if ( *fmt == 'p' ) {
 | 
		
	
		
			
			| 244 | 261 |  			intptr_t ptrval;
 | 
		
	
	
		
			
			|  | @@ -271,8 +288,17 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
 | 
		
	
		
			
			| 271 | 288 |  			*(--ptr) = *fmt;
 | 
		
	
		
			
			| 272 | 289 |  		}
 | 
		
	
		
			
			| 273 | 290 |  		/* Write out conversion result */
 | 
		
	
		
			
			| 274 |  | -		for ( ; *ptr ; ptr++ ) {
 | 
		
	
		
			
			| 275 |  | -			cputchar ( ctx, *ptr );
 | 
		
	
		
			
			|  | 291 | +		if ( wptr == NULL ) {
 | 
		
	
		
			
			|  | 292 | +			for ( ; *ptr ; ptr++ ) {
 | 
		
	
		
			
			|  | 293 | +				cputchar ( ctx, *ptr );
 | 
		
	
		
			
			|  | 294 | +			}
 | 
		
	
		
			
			|  | 295 | +		} else {
 | 
		
	
		
			
			|  | 296 | +			for ( ; *wptr ; wptr++ ) {
 | 
		
	
		
			
			|  | 297 | +				size_t len = wcrtomb ( tmp_buf, *wptr, NULL );
 | 
		
	
		
			
			|  | 298 | +				for ( ptr = tmp_buf ; len-- ; ptr++ ) {
 | 
		
	
		
			
			|  | 299 | +					cputchar ( ctx, *ptr );
 | 
		
	
		
			
			|  | 300 | +				}
 | 
		
	
		
			
			|  | 301 | +			}
 | 
		
	
		
			
			| 276 | 302 |  		}
 | 
		
	
		
			
			| 277 | 303 |  	}
 | 
		
	
		
			
			| 278 | 304 |  
 |