| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "printxf.h"
- struct printxf printxf_default;
- /* allow domains an easy way to defer standard specifiers to the
- * system's implementation. */
- int printxf_vfprintf(struct printxf *pxf,
- FILE *fp, const char *spec, va_list ap)
- {
- return vfprintf(fp, spec, ap);
- }
- int __printxf_wsegment(FILE *fp, const char **fmt, size_t ssize, size_t *tsize)
- {
- size_t wsize;
- wsize = fwrite(*fmt, 1, ssize, fp);
- *tsize += wsize;
- *fmt += wsize;
- return (wsize < ssize) ? EOF : 0;
- }
- int vfprintxf(struct printxf *pxf, FILE *fp, const char *fmt, va_list ap)
- {
- size_t tsize = 0, wsize, ssize;
- vfprintxf_fn handler;
- char spec[16];
- pxf = pxf ? : &printxf_default;
- if (!fmt)
- return 0;
- while (*fmt) {
- ssize = strcspn(fmt, "%");
- /* leading segment containing no format specifiers. */
- if (ssize && __printxf_wsegment(fp, &fmt, ssize, &tsize))
- break;
- if (fmt[0] == '\0') {
- /* this was the last segment */
- break;
- } else if ((fmt[0] == '%')
- && ((fmt[1] == '\0') || (fmt[1] == '%'))) {
- /* "%" or "%%", write "%" */
- if (!fwrite("%", 1, 1, fp))
- break;
- tsize++;
- fmt += fmt[1] ? 2 : 1;
- continue;
- }
-
- ssize = strspn(fmt + 1, " #$'*+,-.0123456789:;L_hjlqtvz") + 1;
- if (!fmt[ssize]) {
- /* corner case. fmt ends with an unterminated
- * format. e.g. "evilness: 100%" */
- __printxf_wsegment(fp, &fmt, ssize, &tsize);
- break;
- }
- handler = pxf->vfprintxf[fmt[ssize] & 0x7f];
- if (!handler) {
- /* unsupported specifier, write the entire
- * specifier unformatted to the output */
- if (__printxf_wsegment(fp, &fmt, ssize + 1, &tsize))
- break;
- continue;
- }
- ssize++;
- memset(spec, '\0', sizeof(spec));
- strncpy(spec, fmt, (ssize >= sizeof(spec)) ? sizeof(spec) - 1 : ssize);
- fmt += ssize;
- tsize += handler(pxf, fp, spec, ap);
- }
- return tsize;
- }
- int fprintxf(struct printxf *pxf, FILE *fp, const char *fmt, ...)
- {
- va_list ap;
- int ret;
- va_start(ap, fmt);
- ret = vfprintxf(pxf, fp, fmt, ap);
- va_end(ap);
- return ret;
- }
- int vprintxf(struct printxf *pxf, const char *fmt, va_list ap)
- {
- return vfprintxf(pxf, stdout, fmt, ap);
- }
- int printxf(struct printxf *pxf, const char *fmt, ...)
- {
- va_list ap;
- int ret;
- va_start(ap, fmt);
- ret = vprintxf(pxf, fmt, ap);
- va_end(ap);
- return ret;
- }
- __attribute__((constructor))
- static void printxf_init(void)
- {
- const char *std = "aAcdeEfFgGiosuxX";
- for (; *std; std++)
- printxf_default.vfprintxf[(int)*std] = &printxf_vfprintf;
- }
|