# HG changeset patch # User Matti Hamalainen # Date 1578442657 -7200 # Node ID b75f42ca08ef618f147ace0586e1bb94e49169b1 # Parent 11f56a652cb09b2464439c7467aece5c89570ffc Massage th_vprintf_do() a bit, and factor out the format specifier handling into a separate function and use through a callback. This breaks the th_vprintf_do() API, unfortunately, but should make for further flexibility in future. diff -r 11f56a652cb0 -r b75f42ca08ef th_printf.c --- a/th_printf.c Tue Jan 07 20:09:23 2020 +0200 +++ b/th_printf.c Wed Jan 08 02:17:37 2020 +0200 @@ -324,7 +324,77 @@ #endif -int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, const char *fmt, va_list ap) +int th_vprintf_do_format( + th_vprintf_ctx *ctx, th_vprintf_putch vputch, + int f_width, int f_prec, int f_flags, + const char fmt, va_list ap) +{ + int ret; + + switch (fmt) + { + case 0: + // Unexpected end of format string + return -104; + + case 'c': + if ((ret = th_printf_pad_pre(ctx, vputch, f_width - 1, f_flags)) == EOF) + return ret; + + if ((ret = vputch(ctx, va_arg(ap, int))) == EOF) + return ret; + + return th_printf_pad_post(ctx, vputch, f_width - 1, f_flags); + + case 'o': + return th_vprintf_put_int(ctx, vputch, ap, 8, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_oct); + + case 'u': + case 'i': + case 'd': + return th_vprintf_put_int(ctx, vputch, ap, 10, f_flags, f_width, f_prec, fmt == 'u', NULL); + + case 'x': + case 'X': + if (fmt == 'X') + f_flags |= TH_PF_UPCASE; + + return th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex); + + case 'p': + // Check for invalid flags + if (f_flags & (TH_PF_LONG | TH_PF_LONGLONG)) + return -120; + +#if (TH_PTRSIZE == 32) + f_flags |= TH_PF_LONG; +#elif (TH_PTRSIZE == 64) + f_flags |= TH_PF_LONGLONG; +#endif + f_flags |= TH_PF_ALT | TH_PF_POINTER; + + return th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex); + +#ifdef TH_WIP_FLOAT_SUPPORT + case 'f': + case 'F': + return th_vprintf_put_float(ctx, vputch, ap, + f_flags, f_width, f_prec); +#endif + + case 's': + return th_vprintf_put_str(ctx, vputch, va_arg(ap, char *), + f_flags, f_width, f_prec); + + //case '%': + default: + return vputch(ctx, fmt); + } +} + + +int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, + th_vprintf_format vformat, const char *fmt, va_list ap) { int ret = 0; @@ -440,75 +510,12 @@ return -202; } - switch (*fmt) - { - case 0: - return -104; - - case 'c': - if ((ret = th_printf_pad_pre(ctx, vputch, f_width - 1, f_flags)) == EOF) - goto out; - if ((ret = vputch(ctx, va_arg(ap, int))) == EOF) - goto out; - if ((ret = th_printf_pad_post(ctx, vputch, f_width - 1, f_flags)) == EOF) - goto out; - break; - - case 'o': - if ((ret = th_vprintf_put_int(ctx, vputch, ap, 8, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_oct)) == EOF) - goto out; - break; - - case 'u': - case 'i': - case 'd': - if ((ret = th_vprintf_put_int(ctx, vputch, ap, 10, f_flags, f_width, f_prec, *fmt == 'u', NULL)) == EOF) - goto out; - break; - - case 'x': - case 'X': - if (*fmt == 'X') - f_flags |= TH_PF_UPCASE; - if ((ret = th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex)) == EOF) - goto out; - break; + ret = vformat(ctx, vputch, f_width, f_prec, f_flags, *fmt, ap); + if (ret == EOF) + goto out; + if (ret < 0) + return ret; - case 'p': - if (f_flags & (TH_PF_LONG | TH_PF_LONGLONG)) - return -120; - -#if (TH_PTRSIZE == 32) - f_flags |= TH_PF_LONG; -#elif (TH_PTRSIZE == 64) - f_flags |= TH_PF_LONGLONG; -#endif - f_flags |= TH_PF_ALT | TH_PF_POINTER; - if ((ret = th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex)) == EOF) - goto out; - break; - -#ifdef TH_WIP_FLOAT_SUPPORT - case 'f': - case 'F': - if ((ret = th_vprintf_put_float(ctx, vputch, ap, - f_flags, f_width, f_prec)) == EOF) - goto out; - break; -#endif - - case 's': - if ((ret = th_vprintf_put_str(ctx, vputch, va_arg(ap, char *), - f_flags, f_width, f_prec)) == EOF) - goto out; - break; - - //case '%': - default: - if ((ret = vputch(ctx, *fmt)) == EOF) - goto out; - break; - } } fmt++; } diff -r 11f56a652cb0 -r b75f42ca08ef th_string.c --- a/th_string.c Tue Jan 07 20:09:23 2020 +0200 +++ b/th_string.c Wed Jan 08 02:17:37 2020 +0200 @@ -157,7 +157,7 @@ ctx.pos = 0; ctx.ipos = 0; - ret = th_vprintf_do(&ctx, th_pbuf_vputch, fmt, ap); + ret = th_vprintf_do(&ctx, th_pbuf_vputch, th_vprintf_do_format, fmt, ap); if (ctx.pos < size) buf[ctx.pos] = 0; @@ -205,7 +205,7 @@ ctx.pos = 0; ctx.ipos = 0; - return th_vprintf_do(&ctx, th_stdio_vputch, fmt, ap); + return th_vprintf_do(&ctx, th_stdio_vputch, th_vprintf_do_format, fmt, ap); #else return vfprintf(fh, fmt, ap); #endif @@ -226,7 +226,7 @@ ctx.pos = 0; ctx.ipos = 0; - ret = th_vprintf_do(&ctx, th_stdio_vputch, fmt, ap); + ret = th_vprintf_do(&ctx, th_stdio_vputch, th_vprintf_do_format, fmt, ap); #else ret = fprintf(fh, fmt, ap); #endif @@ -263,7 +263,7 @@ // Get size va_copy(ap, args); ctx.pos = 0; - th_vprintf_do(&ctx, th_pbuf_alloc_vputch1, fmt, ap); + th_vprintf_do(&ctx, th_pbuf_alloc_vputch1, th_vprintf_do_format, fmt, ap); va_end(ap); // Allocate memory @@ -273,7 +273,7 @@ va_copy(ap, args); ctx.pos = 0; - th_vprintf_do(&ctx, th_pbuf_alloc_vputch2, fmt, ap); + th_vprintf_do(&ctx, th_pbuf_alloc_vputch2, th_vprintf_do_format, fmt, ap); va_end(ap); ctx.buf[ctx.pos] = 0; diff -r 11f56a652cb0 -r b75f42ca08ef th_string.h --- a/th_string.h Tue Jan 07 20:09:23 2020 +0200 +++ b/th_string.h Wed Jan 08 02:17:37 2020 +0200 @@ -88,6 +88,14 @@ typedef int (*th_vprintf_putch)(th_vprintf_ctx *ctx, const char ch); +/** @def formatting helper function typedef for internal printf() implementation + */ +typedef int (*th_vprintf_format)( + th_vprintf_ctx *ctx, th_vprintf_putch vputch, + int f_width, int f_prec, int f_flags, + const char fmt, va_list ap); + + /* Normal NUL-terminated string functions */ char *th_strdup(const char *src); @@ -128,7 +136,9 @@ const char *buf, const size_t len, const int vret, int *prec, int *flags); -int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, const char *fmt, va_list ap); +int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, + th_vprintf_format vformat, const char *fmt, va_list ap); + int th_vprintf_put_str(th_vprintf_ctx *ctx, th_vprintf_putch vputch, const char *str, int f_flags, const int f_width, const int f_prec);