diff --git a/src/printf.c b/src/printf.c new file mode 100644 index 0000000..385df9b --- /dev/null +++ b/src/printf.c @@ -0,0 +1,151 @@ +#include "config.h" +#include "printf.h" + +// output stream +static index_t _stdout=1; + +/* + Important: Output channel can be busy/full! + AVAILBYTE(od)==0 +*/ +INLINE void print_char(char c) { + OUTBYTE(_stdout,c); +} + + +void print_int(int i) { + if (i < 0) { + OUTBYTE(_stdout,'-'); + i = -i; + } + if (i / 10) print_int(i / 10); + OUTBYTE(_stdout,i % 10 + '0'); +} + +char* sprint_int(char *buf, int i) { + if (i < 0) { + *buf='-'; + i = -i; + buf++; + } + if (i / 10) buf=sprint_int(buf,i / 10); + *buf=i % 10 + '0'; + buf++; + return buf; +} + + +void print_uint_hex(int i) { + if (i / 16) print_uint_hex(i / 16); + OUTBYTE(_stdout,i % 16 > 9? 'A'+(i%16)-10: (i%16) + '0'); +} + +void print_uint(unsigned int i) { + if (i / 10) print_uint(i / 10); + OUTBYTE(_stdout,i % 10 + '0'); +} + +#if HAS_FLOAT==0 +void print_number(number_t x) { + print_int((int)x); +} +#else + // TODO +#endif + +/* + returns number of written array elements + returns zero or negative number if out channel is blocked +*/ +int print_array(number_t *x,index_t len) { + int n=0; + while (len) { + print_number(*x); + x++;len--; + n++; + } + return n; +} + +/* + returns number of written array elements + returns zero or negative number if out channel is blocked +*/ +int print_string(char *s) { + int n=0; + while (*s) { + OUTBYTE(_stdout,*s++); + n++; + } + return n; +} + +void print_format(char *format, ...) { + void **arg = (void **) &format + 1; + for (char *p = format; *p; p++) { + if (*p != '%') { + OUTBYTE(_stdout,*p); + continue; + } + switch (*++p) { + case 'd': + print_int(*(int *) arg++); + break; + case 'x': + print_uint_hex(*(int *) arg++); + break; + case 'u': + print_uint(*(unsigned int *) arg++); + break; + case 'c': + OUTBYTE(_stdout,*(char *) arg++); + break; + case 's': + print_string(*(char **) arg++); + break; + case '%': + OUTBYTE(_stdout,'%'); + break; + default: + OUTBYTE(_stdout,*p); + break; + } + } +} + + +/* + buffer versions supporting up and down growing cyclic buffers + dir=1: [0,1,..,size-1] + dir=-1 : [size-1,size-2,..,0] + dir=-2 : [size-1,size-2,..,size/2] +*/ +int bprint_char(char *buf, int off, int size, int dir, char c) { + buf[off]=c; + if (dir==1) off=(off+1)%size; + else if (dir==-1) off=off==0?size-1:off-1; + else /*-2*/ off=off==size/2?size-1:off-1; + return off; +} +int bprint_int(char *buf, int off, int size, int dir, int i) { + if (i < 0) { + buf[off]='-'; + i = -i; + if (dir==1) off=(off+1)%size; + else if (dir==-1) off=off==0?size-1:off-1; + else /*-2*/ off=off==size/2?size-1:off-1; + } + if (i / 10) off=bprint_int(buf,off,size,dir, i / 10); + buf[off]=i % 10 + '0'; + if (dir==1) off=(off+1)%size; + else if (dir==-1) off=off==0?size-1:off-1; + else /*-2*/ off=off==size/2?size-1:off-1; + return off; +} + + +/* + Set standard output channel (default 1) +*/ +index_t print_stdout(index_t handle) { index_t old=_stdout; _stdout=handle; return old; } +