mirror of
https://github.com/rfivet/stm32bringup.git
synced 2024-12-18 14:56:22 -05:00
Implements %[flags][width]type
This commit is contained in:
parent
5d11a2cdfa
commit
77253914e1
177
printf.c
177
printf.c
@ -1,39 +1,94 @@
|
||||
/* printf.c -- format and print data */
|
||||
/* Copyright (c) 2020 Renaud Fivet */
|
||||
/* printf.c -- format and print data
|
||||
** Copyright (c) 2020-2021 Renaud Fivet
|
||||
** v3: %[flags][width]type
|
||||
** v2: zero padding and uppercase/lowercase for hexadecimal
|
||||
** v1: type=c,u,x,X,i,d,s,%
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "system.h" /* kputc(), kputs() */
|
||||
|
||||
static int kputu( unsigned u, unsigned d, int padlen, char fmt) {
|
||||
char s[ 12] ; /* room for 11 octal digit + EOS */
|
||||
char *p = &s[ sizeof s - 1] ; /* point to last byte */
|
||||
size_t strlen( const char *s) {
|
||||
const char *end = s - 1 ;
|
||||
while( *++end) ;
|
||||
|
||||
*p = 0 ; /* null terminated string */
|
||||
fmt = fmt & 0x20 ; /* set uppercase bit */
|
||||
do {
|
||||
unsigned r = u % d ;
|
||||
u /= d ;
|
||||
*--p = "0123456789ABCDEF"[ r] | fmt ;
|
||||
padlen -= 1 ;
|
||||
} while( u) ;
|
||||
|
||||
while( padlen-- > 0) {
|
||||
kputc( '0') ;
|
||||
u += 1 ; /* use u to calculate output length */
|
||||
}
|
||||
|
||||
return u + kputs( p) ;
|
||||
return end - s ;
|
||||
}
|
||||
|
||||
static int kputi( int i) {
|
||||
int flag = i < 0 ;
|
||||
if( flag) {
|
||||
i = -i ;
|
||||
kputc( '-') ;
|
||||
#define ZEROPAD (1 << 3)
|
||||
#define LEFTALIGN (3 << 2)
|
||||
#define LEFTMASK 4
|
||||
#define PLUSSIGN (1 << 1)
|
||||
#define BLANKSIGN (1 << 0)
|
||||
|
||||
static const unsigned char base[] = {
|
||||
16, /* Xx 0x58 0x78 */
|
||||
10, /* iu 0x69 0x75 */
|
||||
2, /* b 0x62 unused */
|
||||
8, /* o 0x6F */
|
||||
} ;
|
||||
|
||||
static const char signs[] = { 0, ' ', '+', '+'} ;
|
||||
|
||||
static int kputpad( char c, int len) {
|
||||
int cnt ;
|
||||
|
||||
if( len > 0) {
|
||||
cnt = len ;
|
||||
while( len--)
|
||||
kputc( c) ;
|
||||
} else
|
||||
cnt = 0 ;
|
||||
|
||||
return cnt ;
|
||||
}
|
||||
|
||||
static int kputu( unsigned u, int padlen, char fmt) {
|
||||
char s[ 12] ; /* room for 11 octal digit + EOS */
|
||||
char *p = &s[ sizeof s - 1] ; /* point to last byte */
|
||||
char signprefix ;
|
||||
|
||||
*p = 0 ; /* null terminated string */
|
||||
|
||||
int flags = padlen >> 28 ;
|
||||
padlen &= 0x0FFFFFFF ; /* clear flags */
|
||||
if( fmt == 'i' && (0 > (int) u)) {
|
||||
u = - (int) u ;
|
||||
signprefix = '-' ;
|
||||
} else
|
||||
signprefix = signs[ flags & 3] ;
|
||||
|
||||
if( signprefix)
|
||||
padlen -= 1 ;
|
||||
|
||||
unsigned d = base[ fmt & 3] ;
|
||||
fmt = fmt & 0x20 ; /* set uppercase bit */
|
||||
do {
|
||||
*--p = "0123456789ABCDEF"[ u % d] | fmt ;
|
||||
padlen -= 1 ;
|
||||
u /= d ;
|
||||
} while( u) ;
|
||||
|
||||
/* reuse u to calculate output length */
|
||||
flags >>= 2 ;
|
||||
if( !flags) /* Right align */
|
||||
u += kputpad( ' ', padlen) ;
|
||||
|
||||
if( signprefix) {
|
||||
kputc( signprefix) ;
|
||||
u += 1 ;
|
||||
}
|
||||
|
||||
return flag + kputu( i, 10, 0, 'u') ;
|
||||
if( flags == (ZEROPAD >> 2))
|
||||
u += kputpad( '0', padlen) ;
|
||||
|
||||
u += kputs( p) ;
|
||||
if( flags == (LEFTALIGN >> 2))
|
||||
u += kputpad( ' ', padlen) ;
|
||||
|
||||
return u ;
|
||||
}
|
||||
|
||||
int printf( const char *fmt, ...) {
|
||||
@ -46,37 +101,77 @@ int printf( const char *fmt, ...) {
|
||||
if( c != '%') {
|
||||
cnt += 1 ; kputc( c) ;
|
||||
} else {
|
||||
int len = 0 ;
|
||||
/* %[flags][width]type */
|
||||
int flags = 0 ;
|
||||
int width = 0 ;
|
||||
|
||||
c = *fmt++ ;
|
||||
while( c >= '0' && c <= '9') {
|
||||
len = len * 10 + ( c - '0') ;
|
||||
/* flags and width */
|
||||
for( ;;) {
|
||||
c = *fmt++ ;
|
||||
switch( c) {
|
||||
case ' ':
|
||||
flags |= BLANKSIGN ;
|
||||
continue ;
|
||||
case '+':
|
||||
flags |= PLUSSIGN ;
|
||||
continue ;
|
||||
case '-':
|
||||
flags |= LEFTALIGN ;
|
||||
continue ;
|
||||
case '0':
|
||||
flags |= ZEROPAD ;
|
||||
continue ;
|
||||
case '*':
|
||||
width = va_arg( ap, int) ;
|
||||
c = *fmt++ ;
|
||||
break ;
|
||||
default:
|
||||
while( c >= '0' && c <= '9') {
|
||||
width = width * 10 + ( c - '0') ;
|
||||
c = *fmt++ ;
|
||||
}
|
||||
}
|
||||
|
||||
break ;
|
||||
}
|
||||
|
||||
/* type */
|
||||
if( c == 0)
|
||||
break ;
|
||||
|
||||
switch( c) {
|
||||
case 'c':
|
||||
flags >>= 2 ;
|
||||
if( !flags) /* right aligned */
|
||||
cnt += kputpad( ' ', width - 1) ;
|
||||
|
||||
cnt += 1 ; kputc( va_arg( ap, int /* char */)) ;
|
||||
if( flags == (LEFTALIGN >> 2))
|
||||
cnt += kputpad( ' ', width - 1) ;
|
||||
|
||||
break ;
|
||||
case 'd':
|
||||
c = 'i' ;
|
||||
/* fallthrough */
|
||||
case 'i':
|
||||
case 'o':
|
||||
cnt += kputu( va_arg( ap, unsigned), 8, len, c) ;
|
||||
break ;
|
||||
case 'u':
|
||||
cnt += kputu( va_arg( ap, unsigned), 10, len, c) ;
|
||||
break ;
|
||||
case 'x':
|
||||
case 'X':
|
||||
cnt += kputu( va_arg( ap, unsigned), 16, len, c) ;
|
||||
cnt += kputu( va_arg( ap, unsigned), width | flags << 28, c) ;
|
||||
break ;
|
||||
case 'i':
|
||||
case 'd':
|
||||
cnt += kputi( va_arg( ap, int)) ;
|
||||
break ;
|
||||
case 's':
|
||||
cnt += kputs( va_arg( ap, char *)) ;
|
||||
case 's': {
|
||||
char *argp = va_arg( ap, char *) ;
|
||||
flags >>= 2 ;
|
||||
if( !flags) /* right aligned */
|
||||
cnt += kputpad( ' ', width - strlen( argp)) ;
|
||||
|
||||
int size = kputs( argp) ;
|
||||
cnt += size ;
|
||||
if( flags == (LEFTMASK >> 2))
|
||||
cnt += kputpad( ' ', width - size) ;
|
||||
}
|
||||
|
||||
break ;
|
||||
default:
|
||||
cnt += 1 ; kputc( '%') ;
|
||||
|
Loading…
Reference in New Issue
Block a user