X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=functions%2F_PDCLIB%2Fprint.c;h=aa397078086236a5e2c31efa12a6cfac338bbdcd;hb=8a6bd772ce0886b05136b195a87ba4a1e21a58d8;hp=78716d1412b0422c9887ef6e929a4bf24ee450d7;hpb=5e9cc43af20debd0df0d080a7f164398aae5eabe;p=pdclib.old diff --git a/functions/_PDCLIB/print.c b/functions/_PDCLIB/print.c index 78716d1..aa39707 100644 --- a/functions/_PDCLIB/print.c +++ b/functions/_PDCLIB/print.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -22,23 +23,23 @@ /* FIXME: one too many flags to work on a 16-bit machine, join some (e.g. the width flags) into a combined field. */ -#define E_minus 1<<0 -#define E_plus 1<<1 -#define E_alt 1<<2 -#define E_space 1<<3 -#define E_zero 1<<4 -#define E_done 1<<5 -#define E_char 1<<6 -#define E_short 1<<7 -#define E_long 1<<8 -#define E_llong 1<<9 -#define E_intmax 1<<10 -#define E_size 1<<11 -#define E_ptrdiff 1<<12 -#define E_intptr 1<<13 -#define E_ldouble 1<<14 -#define E_lower 1<<15 -#define E_unsigned 1<<16 +#define E_minus (1<<0) +#define E_plus (1<<1) +#define E_alt (1<<2) +#define E_space (1<<3) +#define E_zero (1<<4) +#define E_done (1<<5) +#define E_char (1<<6) +#define E_short (1<<7) +#define E_long (1<<8) +#define E_llong (1<<9) +#define E_intmax (1<<10) +#define E_size (1<<11) +#define E_ptrdiff (1<<12) +#define E_intptr (1<<13) +#define E_ldouble (1<<14) +#define E_lower (1<<15) +#define E_unsigned (1<<16) /* This macro delivers a given character to either a memory buffer or a stream, depending on the contents of 'status' (struct _PDCLIB_status_t). @@ -103,7 +104,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status ) const char * digits = (status->flags & E_lower) ? _PDCLIB_digits : _PDCLIB_Xdigits; uintmax_t remaining = value; - do { + if(status->prec != 0 || remaining != 0) do { uintmax_t digit = remaining % status->base; remaining /= status->base; @@ -112,7 +113,7 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status ) } // Pad field out to the precision specification - while( written < status->prec ) outend[-++written] = '0'; + while( (long) written < status->prec ) outend[-++written] = '0'; // If a field width specified, and zero padding was requested, then pad to // the field width @@ -140,6 +141,9 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status ) if ( outend[-written] != '0' ) outend[-++written] = '0'; break; case 16: + // No prefix if zero + if ( value == 0 ) break; + written += padding < 2 ? 2 - padding : 0; outend[-written ] = '0'; outend[-written + 1] = (status->flags & E_lower) ? 'x' : 'X'; @@ -161,6 +165,64 @@ static void int2base( uintmax_t value, struct _PDCLIB_status_t * status ) PUT( outend[-written--] ); } +static void printstr( const char * str, struct _PDCLIB_status_t * status ) +{ + if ( status->width == 0 || status->flags & E_minus ) + { + // Simple case or left justification + while ( str[status->current] && + ( status->prec < 0 || (long)status->current < status->prec ) ) + { + PUT( str[status->current++] ); + } + + while( status->current < status->width ) + { + PUT( ' ' ); + status->current++; + } + } else { + // Right justification + size_t len = status->prec >= 0 ? strnlen( str, status->prec ) + : strlen( str ); + int padding = status->width - len; + while((long)status->current < padding) + { + PUT( ' ' ); + status->current++; + } + + for( size_t i = 0; i != len; i++ ) + { + PUT( str[i] ); + status->current++; + } + } +} + +static void printchar( char chr, struct _PDCLIB_status_t * status ) +{ + if( ! ( status->flags & E_minus ) ) + { + // Right justification + for( ; status->current + 1 < status->width; status->current++) + { + PUT( ' ' ); + } + PUT( chr ); + status->current++; + } else { + // Left justification + PUT( chr ); + status->current++; + + for( ; status->current < status->width; status->current++) + { + PUT( ' ' ); + } + } +} + const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status ) { const char * orig_spec = spec; @@ -175,7 +237,7 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status status->base = 0; status->current = 0; status->width = 0; - status->prec = 0; + status->prec = EOF; /* First come 0..n flags */ do @@ -250,20 +312,14 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status EOF (negative), there is no need for testing for negative here. */ status->prec = va_arg( status->arg, int ); + ++spec; } else { - char * endptr; - status->prec = (int)strtol( spec, &endptr, 10 ); - if ( spec == endptr ) - { - /* Decimal point but no number - bad conversion specifier. */ - return orig_spec; - } - spec = endptr; + status->prec = (int)strtol( spec, (char**) &spec, 10 ); } /* Having a precision cancels out any zero flag. */ - status->flags ^= E_zero; + status->flags &= ~E_zero; } /* Optional length modifier @@ -355,17 +411,14 @@ const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status case 'A': break; case 'c': - /* TODO: Flags, wide chars. */ - PUT( va_arg( status->arg, int ) ); + /* TODO: wide chars. */ + printchar( va_arg( status->arg, int ), status ); return ++spec; case 's': - /* TODO: Flags, wide chars. */ + /* TODO: wide chars. */ { char * s = va_arg( status->arg, char * ); - while ( *s != '\0' ) - { - PUT( *(s++) ); - } + printstr( s, status ); return ++spec; } case 'p':