This sholud definitely go in your libc instead. Cheers,
Tom On Thu, Sep 18, 2014 at 3:24 PM, Emil Renner Berthing <syst...@esmil.dk> wrote: > --- > Makefile.am | 4 + > configure.ac | 2 + > src/journal/journal-send.c | 2 +- > src/shared/log.c | 2 +- > src/shared/parse-printf-format.c | 273 > +++++++++++++++++++++++++++++++++++++++ > src/shared/parse-printf-format.h | 57 ++++++++ > 6 files changed, 338 insertions(+), 2 deletions(-) > create mode 100644 src/shared/parse-printf-format.c > create mode 100644 src/shared/parse-printf-format.h > > diff --git a/Makefile.am b/Makefile.am > index 5dc17f8..7fc682f 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -879,6 +879,10 @@ libsystemd_shared_la_SOURCES = \ > src/shared/switch-root.c \ > src/shared/nss-util.h > > +if !HAVE_PRINTF_H > +libsystemd_shared_la_SOURCES += src/shared/parse-printf-format.c > +endif > + > nodist_libsystemd_shared_la_SOURCES = \ > src/shared/errno-from-name.h \ > src/shared/errno-to-name.h \ > diff --git a/configure.ac b/configure.ac > index 3db0e24..397521e 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -283,6 +283,8 @@ AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test > "$have_python_devel" = "yes"]) > AC_SEARCH_LIBS([dlsym], [dl], [], [AC_MSG_ERROR([*** Dynamic linking loader > library not found])]) > AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps > headers not found])]) > AC_CHECK_HEADERS([linux/btrfs.h], [], []) > +AC_CHECK_HEADERS([printf.h], [], []) > +AM_CONDITIONAL(HAVE_PRINTF_H, [test "x$ac_cv_header_printf_h" = xyes]) > > # unconditionally pull-in librt with old glibc versions > AC_SEARCH_LIBS([clock_gettime], [rt], [], []) > diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c > index bb1ef66..9ca4a0b 100644 > --- a/src/journal/journal-send.c > +++ b/src/journal/journal-send.c > @@ -25,12 +25,12 @@ > #include <stddef.h> > #include <unistd.h> > #include <fcntl.h> > -#include <printf.h> > > #define SD_JOURNAL_SUPPRESS_LOCATION > > #include "sd-journal.h" > #include "util.h" > +#include "parse-printf-format.h" > #include "socket-util.h" > > #define SNDBUF_SIZE (8*1024*1024) > diff --git a/src/shared/log.c b/src/shared/log.c > index 26c604a..8e968f1 100644 > --- a/src/shared/log.c > +++ b/src/shared/log.c > @@ -27,11 +27,11 @@ > #include <sys/socket.h> > #include <sys/un.h> > #include <stddef.h> > -#include <printf.h> > > #include "log.h" > #include "util.h" > #include "missing.h" > +#include "parse-printf-format.h" > #include "macro.h" > #include "socket-util.h" > > diff --git a/src/shared/parse-printf-format.c > b/src/shared/parse-printf-format.c > new file mode 100644 > index 0000000..49437e5 > --- /dev/null > +++ b/src/shared/parse-printf-format.c > @@ -0,0 +1,273 @@ > +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ > + > +/*** > + This file is part of systemd. > + > + Copyright 2014 Emil Renner Berthing <syst...@esmil.dk> > + > + With parts from the musl C library > + Copyright 2005-2014 Rich Felker, et al. > + > + systemd is free software; you can redistribute it and/or modify it > + under the terms of the GNU Lesser General Public License as published by > + the Free Software Foundation; either version 2.1 of the License, or > + (at your option) any later version. > + > + systemd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public License > + along with systemd; If not, see <http://www.gnu.org/licenses/>. > +***/ > + > +#include <stddef.h> > +#include <string.h> > + > +#include "parse-printf-format.h" > + > +static const char *consume_nonarg(const char *fmt) > +{ > + do { > + if (*fmt == '\0') > + return fmt; > + } while (*fmt++ != '%'); > + return fmt; > +} > + > +static const char *consume_num(const char *fmt) > +{ > + for (;*fmt >= '0' && *fmt <= '9'; fmt++) > + /* do nothing */; > + return fmt; > +} > + > +static const char *consume_argn(const char *fmt, size_t *arg) > +{ > + const char *p = fmt; > + size_t val = 0; > + > + if (*p < '1' || *p > '9') > + return fmt; > + do { > + val = 10*val + (*p++ - '0'); > + } while (*p >= '0' && *p <= '9'); > + > + if (*p != '$') > + return fmt; > + *arg = val; > + return p+1; > +} > + > +static const char *consume_flags(const char *fmt) > +{ > + while (1) { > + switch (*fmt) { > + case '#': > + case '0': > + case '-': > + case ' ': > + case '+': > + case '\'': > + case 'I': > + fmt++; > + continue; > + } > + return fmt; > + } > +} > + > +enum state { > + BARE, > + LPRE, > + LLPRE, > + HPRE, > + HHPRE, > + BIGLPRE, > + ZTPRE, > + JPRE, > + STOP > +}; > + > +enum type { > + NONE, > + PTR, > + INT, > + UINT, > + ULLONG, > + LONG, > + ULONG, > + SHORT, > + USHORT, > + CHAR, > + UCHAR, > + LLONG, > + SIZET, > + IMAX, > + UMAX, > + PDIFF, > + UIPTR, > + DBL, > + LDBL, > + MAXTYPE > +}; > + > +static const short pa_types[MAXTYPE] = { > + [NONE] = PA_INT, > + [PTR] = PA_POINTER, > + [INT] = PA_INT, > + [UINT] = PA_INT, > + [ULLONG] = PA_INT | PA_FLAG_LONG_LONG, > + [LONG] = PA_INT | PA_FLAG_LONG, > + [ULONG] = PA_INT | PA_FLAG_LONG, > + [SHORT] = PA_INT | PA_FLAG_SHORT, > + [USHORT] = PA_INT | PA_FLAG_SHORT, > + [CHAR] = PA_CHAR, > + [UCHAR] = PA_CHAR, > + [LLONG] = PA_INT | PA_FLAG_LONG_LONG, > + [SIZET] = PA_INT | PA_FLAG_LONG, > + [IMAX] = PA_INT | PA_FLAG_LONG_LONG, > + [UMAX] = PA_INT | PA_FLAG_LONG_LONG, > + [PDIFF] = PA_INT | PA_FLAG_LONG_LONG, > + [UIPTR] = PA_INT | PA_FLAG_LONG, > + [DBL] = PA_DOUBLE, > + [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE > +}; > + > +#define S(x) [(x)-'A'] > +#define E(x) (STOP + (x)) > + > +static const unsigned char states[]['z'-'A'+1] = { > + { /* 0: bare types */ > + S('d') = E(INT), S('i') = E(INT), > + S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = > E(UINT), > + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = > E(DBL), > + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = > E(DBL), > + S('c') = E(CHAR),S('C') = E(INT), > + S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = > E(PTR), > + S('m') = E(NONE), > + S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, > + S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE > + }, { /* 1: l-prefixed */ > + S('d') = E(LONG), S('i') = E(LONG), > + S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') > = E(ULONG), > + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') > = E(DBL), > + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') > = E(DBL), > + S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR), > + S('l') = LLPRE > + }, { /* 2: ll-prefixed */ > + S('d') = E(LLONG), S('i') = E(LLONG), > + S('o') = E(ULLONG),S('u') = E(ULLONG), > + S('x') = E(ULLONG),S('X') = E(ULLONG), > + S('n') = E(PTR) > + }, { /* 3: h-prefixed */ > + S('d') = E(SHORT), S('i') = E(SHORT), > + S('o') = E(USHORT),S('u') = E(USHORT), > + S('x') = E(USHORT),S('X') = E(USHORT), > + S('n') = E(PTR), > + S('h') = HHPRE > + }, { /* 4: hh-prefixed */ > + S('d') = E(CHAR), S('i') = E(CHAR), > + S('o') = E(UCHAR),S('u') = E(UCHAR), > + S('x') = E(UCHAR),S('X') = E(UCHAR), > + S('n') = E(PTR) > + }, { /* 5: L-prefixed */ > + S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = > E(LDBL), > + S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = > E(LDBL), > + S('n') = E(PTR) > + }, { /* 6: z- or t-prefixed (assumed to be same size) */ > + S('d') = E(PDIFF),S('i') = E(PDIFF), > + S('o') = E(SIZET),S('u') = E(SIZET), > + S('x') = E(SIZET),S('X') = E(SIZET), > + S('n') = E(PTR) > + }, { /* 7: j-prefixed */ > + S('d') = E(IMAX), S('i') = E(IMAX), > + S('o') = E(UMAX), S('u') = E(UMAX), > + S('x') = E(UMAX), S('X') = E(UMAX), > + S('n') = E(PTR) > + } > +}; > + > +size_t parse_printf_format(const char *fmt, size_t n, int *types) > +{ > + size_t i = 0; > + size_t last = 0; > + > + memset(types, 0, n); > + > + while (1) { > + size_t arg; > + unsigned int state; > + > + fmt = consume_nonarg(fmt); > + if (*fmt == '\0') > + break; > + if (*fmt == '%') { > + fmt++; > + continue; > + } > + arg = 0; > + fmt = consume_argn(fmt, &arg); > + /* flags */ > + fmt = consume_flags(fmt); > + /* width */ > + if (*fmt == '*') { > + size_t warg = 0; > + fmt = consume_argn(fmt+1, &warg); > + if (warg == 0) > + warg = ++i; > + if (warg > last) > + last = warg; > + if (warg <= n && types[warg-1] == NONE) > + types[warg-1] = INT; > + } else > + fmt = consume_num(fmt); > + /* precision */ > + if (*fmt == '.') { > + fmt++; > + if (*fmt == '*') { > + size_t parg = 0; > + fmt = consume_argn(fmt+1, &parg); > + if (parg == 0) > + parg = ++i; > + if (parg > last) > + last = parg; > + if (parg <= n && types[parg-1] == NONE) > + types[parg-1] = INT; > + } else { > + if (*fmt == '-') > + fmt++; > + fmt = consume_num(fmt); > + } > + } > + /* length modifier and conversion specifier */ > + state = BARE; > + do { > + unsigned char c = *fmt++; > + > + if (c < 'A' || c > 'z') > + continue; > + state = states[state]S(c); > + if (state == 0) > + continue; > + } while (state < STOP); > + > + if (state == E(NONE)) > + continue; > + > + if (arg == 0) > + arg = ++i; > + if (arg > last) > + last = arg; > + if (arg <= n) > + types[arg-1] = state - STOP; > + } > + > + if (last > n) > + last = n; > + for (i = 0; i < last; i++) > + types[i] = pa_types[types[i]]; > + > + return last; > +} > diff --git a/src/shared/parse-printf-format.h > b/src/shared/parse-printf-format.h > new file mode 100644 > index 0000000..4371177 > --- /dev/null > +++ b/src/shared/parse-printf-format.h > @@ -0,0 +1,57 @@ > +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ > + > +/*** > + This file is part of systemd. > + > + Copyright 2014 Emil Renner Berthing <syst...@esmil.dk> > + > + With parts from the GNU C Library > + Copyright 1991-2014 Free Software Foundation, Inc. > + > + systemd is free software; you can redistribute it and/or modify it > + under the terms of the GNU Lesser General Public License as published by > + the Free Software Foundation; either version 2.1 of the License, or > + (at your option) any later version. > + > + systemd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public License > + along with systemd; If not, see <http://www.gnu.org/licenses/>. > +***/ > + > +#pragma once > + > +#include "config.h" > + > +#ifdef HAVE_PRINTF_H > +#include <printf.h> > +#else > + > +#include <stddef.h> > + > +enum { /* C type: */ > + PA_INT, /* int */ > + PA_CHAR, /* int, cast to char */ > + PA_WCHAR, /* wide char */ > + PA_STRING, /* const char *, a '\0'-terminated string */ > + PA_WSTRING, /* const wchar_t *, wide character string */ > + PA_POINTER, /* void * */ > + PA_FLOAT, /* float */ > + PA_DOUBLE, /* double */ > + PA_LAST > +}; > + > +/* Flag bits that can be set in a type returned by `parse_printf_format'. */ > +#define PA_FLAG_MASK 0xff00 > +#define PA_FLAG_LONG_LONG (1 << 8) > +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG > +#define PA_FLAG_LONG (1 << 9) > +#define PA_FLAG_SHORT (1 << 10) > +#define PA_FLAG_PTR (1 << 11) > + > +size_t parse_printf_format(const char *fmt, size_t n, int *types); > + > +#endif /* HAVE_PRINTF_H */ > -- > 2.1.0 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel