diff options
author | David Lamparter <equinox@diac24.net> | 2019-05-12 21:10:04 +0200 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2019-06-03 16:44:51 +0200 |
commit | 5c25bd87b5a0b722e7491e8467728ffff936a904 (patch) | |
tree | 8591fc660caa31814e2d994189ef7e1e141b1ee2 /lib/printf | |
parent | lib/printf: rename & private __find_arguments (diff) | |
download | frr-5c25bd87b5a0b722e7491e8467728ffff936a904.tar.xz frr-5c25bd87b5a0b722e7491e8467728ffff936a904.zip |
lib/printf: integrate
Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'lib/printf')
-rw-r--r-- | lib/printf/glue.c | 154 | ||||
-rw-r--r-- | lib/printf/printf-pos.c | 6 | ||||
-rw-r--r-- | lib/printf/printfcommon.h | 30 | ||||
-rw-r--r-- | lib/printf/printflocal.h | 1 | ||||
-rw-r--r-- | lib/printf/vfprintf.c | 27 |
5 files changed, 186 insertions, 32 deletions
diff --git a/lib/printf/glue.c b/lib/printf/glue.c new file mode 100644 index 000000000..6b6e17daf --- /dev/null +++ b/lib/printf/glue.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2019 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <string.h> + +#include "printfrr.h" + +ssize_t bprintfrr(struct fbuf *out, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vbprintfrr(out, fmt, ap); + va_end(ap); + return ret; +} + +ssize_t vsnprintfrr(char *out, size_t outsz, const char *fmt, va_list ap) +{ + struct fbuf fbb = { .buf = out, .pos = out, .len = outsz - 1, }; + struct fbuf *fb = (out && outsz) ? &fbb : NULL; + ssize_t ret; + + ret = vbprintfrr(fb, fmt, ap); + if (fb) + fb->pos[0] = '\0'; + return ret; +} + +ssize_t snprintfrr(char *out, size_t outsz, const char *fmt, ...) +{ + struct fbuf fbb = { .buf = out, .pos = out, .len = outsz - 1, }; + struct fbuf *fb = (out && outsz) ? &fbb : NULL; + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vbprintfrr(fb, fmt, ap); + va_end(ap); + if (fb) + fb->pos[0] = '\0'; + return ret; +} + +ssize_t vcsnprintfrr(char *out, size_t outsz, const char *fmt, va_list ap) +{ + if (!out || !outsz) + return vbprintfrr(NULL, fmt, ap); + + struct fbuf fbb = { .buf = out, .pos = out, .len = outsz - 1, }; + ssize_t ret; + size_t pos; + + pos = strnlen(out, outsz); + fbb.pos += pos; + + ret = vbprintfrr(&fbb, fmt, ap); + fbb.pos[0] = '\0'; + return ret >= 0 ? ret + (ssize_t)pos : ret; +} + +ssize_t csnprintfrr(char *out, size_t outsz, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vcsnprintfrr(out, outsz, fmt, ap); + va_end(ap); + return ret; +} + +char *vasnprintfrr(struct memtype *mt, char *out, size_t outsz, const char *fmt, + va_list ap) +{ + struct fbuf fb = { .buf = out, .pos = out, .len = outsz - 1, }; + ssize_t len; + va_list ap2; + char *ret = out; + + va_copy(ap2, ap); + len = vbprintfrr(&fb, fmt, ap); + if (len < 0) + /* error = malformed format string => try something useful */ + return qstrdup(mt, fmt); + + if ((size_t)len >= outsz - 1) { + ret = qmalloc(mt, len + 1); + fb.buf = fb.pos = ret; + fb.len = len; + + vbprintfrr(&fb, fmt, ap2); + } + ret[len] = '\0'; + return ret; +} + +char *asnprintfrr(struct memtype *mt, char *out, size_t outsz, const char *fmt, + ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = vasnprintfrr(mt, out, outsz, fmt, ap); + va_end(ap); + return ret; +} + +char *vasprintfrr(struct memtype *mt, const char *fmt, va_list ap) +{ + char buf[256]; + char *ret; + + ret = vasnprintfrr(mt, buf, sizeof(buf), fmt, ap); + + if (ret == buf) + ret = qstrdup(mt, ret); + return ret; +} + +char *asprintfrr(struct memtype *mt, const char *fmt, ...) +{ + char buf[256]; + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = vasnprintfrr(mt, buf, sizeof(buf), fmt, ap); + va_end(ap); + + if (ret == buf) + ret = qstrdup(mt, ret); + return ret; +} diff --git a/lib/printf/printf-pos.c b/lib/printf/printf-pos.c index a461a2be9..7e5231c27 100644 --- a/lib/printf/printf-pos.c +++ b/lib/printf/printf-pos.c @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif /* * This is the code responsible for handling positional arguments diff --git a/lib/printf/printfcommon.h b/lib/printf/printfcommon.h index 716177c57..5c45520b4 100644 --- a/lib/printf/printfcommon.h +++ b/lib/printf/printfcommon.h @@ -50,19 +50,15 @@ static CHAR *__ultoa(u_long, CHAR *, int, int, const char *); #define NIOV 8 struct io_state { - FILE *fp; - struct __suio uio; /* output information: summary */ - struct iovec iov[NIOV];/* ... and individual io vectors */ + struct fbuf *cb; + size_t avail; }; static inline void -io_init(struct io_state *iop, FILE *fp) +io_init(struct io_state *iop, struct fbuf *cb) { - - iop->uio.uio_iov = iop->iov; - iop->uio.uio_resid = 0; - iop->uio.uio_iovcnt = 0; - iop->fp = fp; + iop->cb = cb; + iop->avail = cb ? cb->len - (cb->pos - cb->buf) : 0; } /* @@ -70,13 +66,19 @@ io_init(struct io_state *iop, FILE *fp) * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, size_t len) { + size_t copylen = len; - iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; - iop->iov[iop->uio.uio_iovcnt].iov_len = len; - iop->uio.uio_resid += len; - return (0); + if (!iop->cb) + return 0; + if (iop->avail < copylen) + copylen = iop->avail; + + memcpy(iop->cb->pos, ptr, copylen); + iop->avail -= copylen; + iop->cb->pos += copylen; + return 0; } /* diff --git a/lib/printf/printflocal.h b/lib/printf/printflocal.h index a2de16113..653baf2a4 100644 --- a/lib/printf/printflocal.h +++ b/lib/printf/printflocal.h @@ -35,6 +35,7 @@ */ #include "compiler.h" +#include "printfrr.h" /* * Flags used during conversion. diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c index 66cedcb69..05e88afd7 100644 --- a/lib/printf/vfprintf.c +++ b/lib/printf/vfprintf.c @@ -37,7 +37,13 @@ * SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> +#endif /* * Actual printf innards. @@ -60,17 +66,6 @@ #include <stdarg.h> -#define NO_FLOATING_POINT - -int __vfprintf(FILE *fp, const char *fmt0, va_list ap); - -struct __suio { - size_t uio_resid; - - struct iovec *uio_iov; - size_t uio_iovcnt; -}; - #include "printflocal.h" #define CHAR char @@ -151,8 +146,8 @@ __wcsconv(wchar_t *wcsarg, int prec) /* * Non-MT-safe version */ -int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +ssize_t +vbprintfrr(struct fbuf *cb, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -181,7 +176,6 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) int nextarg; /* 1-based argument index */ va_list orgap; /* original argument pointer */ char *convbuf; /* wide to multibyte conversion result */ - int savserr; static const char xdigs_lower[16] = "0123456789abcdef"; static const char xdigs_upper[16] = "0123456789ABCDEF"; @@ -266,16 +260,13 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) val = GETARG (int); \ } - savserr = fp->_flags & __SERR; - fp->_flags &= ~__SERR; - saved_errno = errno; convbuf = NULL; fmt = (char *)fmt0; argtable = NULL; nextarg = 1; va_copy(orgap, ap); - io_init(&io, fp); + io_init(&io, cb); ret = 0; /* |