From 5596d52a975696c29adc741ac1cdb49fb7315d73 Mon Sep 17 00:00:00 2001 From: Martin Baute Date: Thu, 17 Mar 2016 20:29:04 +0100 Subject: [PATCH] Fixed pointer handling of printf() / scanf(). --- functions/_PDCLIB/print.c | 15 ++++++++++++--- functions/_PDCLIB/scan.c | 16 ++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/functions/_PDCLIB/print.c b/functions/_PDCLIB/print.c index 40ec2a2..5214612 100644 --- a/functions/_PDCLIB/print.c +++ b/functions/_PDCLIB/print.c @@ -29,7 +29,7 @@ #define E_intmax 1<<10 #define E_size 1<<11 #define E_ptrdiff 1<<12 -#define E_intptr 1<<13 +#define E_pointer 1<<13 #define E_ldouble 1<<14 #define E_lower 1<<15 #define E_unsigned 1<<16 @@ -394,7 +394,7 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status case 'p': /* TODO: E_long -> E_intptr */ status->base = 16; - status->flags |= ( E_lower | E_unsigned | E_alt | E_long ); + status->flags |= ( E_lower | E_unsigned | E_alt | E_pointer ); break; case 'n': { @@ -415,7 +415,7 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status if ( status->flags & E_unsigned ) { uintmax_t value; - switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size ) ) + switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size | E_pointer ) ) { case E_char: value = (uintmax_t)(unsigned char)va_arg( status->arg, int ); @@ -435,6 +435,12 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status case E_size: value = (uintmax_t)va_arg( status->arg, size_t ); break; + case E_pointer: + value = (uintmax_t)(uintptr_t)va_arg( status->arg, void * ); + break; + default: + puts( "UNSUPPORTED PRINTF FLAG COMBINATION" ); + return NULL; } ++(status->current); /* FIXME: The if clause means one-digit values do not get formatted */ @@ -486,6 +492,9 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status case E_intmax: int2base( va_arg( status->arg, intmax_t ), status ); break; + default: + puts( "UNSUPPORTED PRINTF FLAG COMBINATION" ); + return NULL; } } if ( status->flags & E_minus ) diff --git a/functions/_PDCLIB/scan.c b/functions/_PDCLIB/scan.c index 8110393..8d4d7e0 100644 --- a/functions/_PDCLIB/scan.c +++ b/functions/_PDCLIB/scan.c @@ -25,7 +25,7 @@ #define E_intmax 1<<10 #define E_size 1<<11 #define E_ptrdiff 1<<12 -#define E_intptr 1<<13 +#define E_pointer 1<<13 #define E_ldouble 1<<14 #define E_unsigned 1<<16 @@ -283,7 +283,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) case 's': { char * c = va_arg( status->arg, char * ); - while ( ( status->current < status->width ) && + while ( ( status->current < status->width ) && ( ( rc = GET( status ) ) != EOF ) ) { if ( isspace( rc ) ) @@ -343,7 +343,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) } while ( *endspec != ']' ); // read according to scanlist, equiv. to %s above char * c = va_arg( status->arg, char * ); - while ( ( status->current < status->width ) && + while ( ( status->current < status->width ) && ( ( rc = GET( status ) ) != EOF ) ) { if ( negative_scanlist ) @@ -382,8 +382,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) } case 'p': status->base = 16; - /* TODO: Assuming 'long' for pointers, this should be handled differently. */ - status->flags |= E_unsigned | E_long; + status->flags |= E_pointer; break; case 'n': { @@ -521,7 +520,7 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) if ( ! ( status->flags & E_suppressed ) ) { switch ( status->flags & ( E_char | E_short | E_long | E_llong | - E_intmax | E_size | E_ptrdiff | + E_intmax | E_size | E_ptrdiff | E_pointer | E_unsigned ) ) { case E_char: @@ -576,6 +575,11 @@ const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status ) *( va_arg( status->arg, ptrdiff_t * ) ) = (ptrdiff_t)( value * sign ); break; + case E_pointer: + /* E_pointer always implies unsigned */ + *( uintptr_t* )( va_arg( status->arg, void * ) ) = (uintptr_t)( value * sign ); + break; + default: puts( "UNSUPPORTED SCANF FLAG COMBINATION" ); return NULL; /* behaviour unspecified */ -- 2.40.0