123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- From 3d9910dcda697b1e361bba49c99050ee0d116742 Mon Sep 17 00:00:00 2001
- From: Alexander Kanavin <alex.kanavin@gmail.com>
- Date: Sat, 22 May 2021 20:26:24 +0200
- Subject: [PATCH] add fallback parse_printf_format implementation
- Upstream-Status: Inappropriate [musl specific]
- Signed-off-by: Emil Renner Berthing <systemd@esmil.dk>
- Signed-off-by: Khem Raj <raj.khem@gmail.com>
- Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
- [rebased for systemd 243]
- Signed-off-by: Scott Murray <scott.murray@konsulko.com>
- ---
- meson.build | 1 +
- src/basic/meson.build | 5 +
- src/basic/parse-printf-format.c | 273 +++++++++++++++++++++++
- src/basic/parse-printf-format.h | 57 +++++
- src/basic/stdio-util.h | 2 +-
- src/libsystemd/sd-journal/journal-send.c | 2 +-
- 6 files changed, 338 insertions(+), 2 deletions(-)
- create mode 100644 src/basic/parse-printf-format.c
- create mode 100644 src/basic/parse-printf-format.h
- --- a/meson.build
- +++ b/meson.build
- @@ -739,6 +739,7 @@ endif
- foreach header : ['crypt.h',
- 'linux/memfd.h',
- 'linux/vm_sockets.h',
- + 'printf.h',
- 'sys/auxv.h',
- 'valgrind/memcheck.h',
- 'valgrind/valgrind.h',
- --- a/src/basic/meson.build
- +++ b/src/basic/meson.build
- @@ -337,6 +337,11 @@ endforeach
-
- basic_sources += generated_gperf_headers
-
- +if conf.get('HAVE_PRINTF_H') != 1
- + basic_sources += [files('parse-printf-format.c')]
- +endif
- +
- +
- ############################################################
-
- arch_list = [
- --- /dev/null
- +++ b/src/basic/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 <systemd@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;
- +}
- --- /dev/null
- +++ b/src/basic/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 <systemd@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"
- +
- +#if 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 */
- --- a/src/basic/stdio-util.h
- +++ b/src/basic/stdio-util.h
- @@ -1,12 +1,12 @@
- /* SPDX-License-Identifier: LGPL-2.1-or-later */
- #pragma once
-
- -#include <printf.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <sys/types.h>
-
- #include "macro.h"
- +#include "parse-printf-format.h"
-
- #define snprintf_ok(buf, len, fmt, ...) \
- ({ \
- --- a/src/libsystemd/sd-journal/journal-send.c
- +++ b/src/libsystemd/sd-journal/journal-send.c
- @@ -2,7 +2,6 @@
-
- #include <errno.h>
- #include <fcntl.h>
- -#include <printf.h>
- #include <stddef.h>
- #include <sys/un.h>
- #include <unistd.h>
- @@ -25,6 +24,7 @@
- #include "stdio-util.h"
- #include "string-util.h"
- #include "tmpfile-util.h"
- +#include "parse-printf-format.h"
-
- #define SNDBUF_SIZE (8*1024*1024)
-
|