1From 6f9454184a02310802b1ed3e40287958b524a495 Mon Sep 17 00:00:00 2001 2From: Tim Orling <timothy.t.orling@linux.intel.com> 3Date: Thu, 28 Dec 2017 21:39:51 -0800 4Subject: [PATCH 2/3] musl does not provide printf.h 5 6Reuse the approach from systemd: 7systemd/0001-add-fallback-parse_printf_format-implementation.patch 8 9Original patch author: Emil Renner Berthing <systemd@esmil.dk> 10Includes work by: Khem Raj <raj.khem@gmail.com> 11 12Signed-off-by: Tim Orling <timothy.t.orling@linux.intel.com> 13Upstream-Status: Denied [https://github.com/systemd/systemd-bootchart/pull/47] 14--- 15 16 Makefile.am | 4 + 17 configure.ac | 3 + 18 src/log.c | 1 + 19 src/parse-printf-format.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++ 20 src/parse-printf-format.h | 57 ++++++++++ 21 src/stdio-util.h | 1 - 22 6 files changed, 338 insertions(+), 1 deletion(-) 23 create mode 100644 src/parse-printf-format.c 24 create mode 100644 src/parse-printf-format.h 25 26diff --git a/Makefile.am b/Makefile.am 27index 9bbc8fa..b887d16 100644 28--- a/Makefile.am 29+++ b/Makefile.am 30@@ -169,6 +169,10 @@ libutils_la_SOURCES = \ 31 src/util.c \ 32 src/util.h 33 34+if !HAVE_PRINTF_H 35+libutils_la_SOURCES += src/parse-printf-format.c 36+endif 37+ 38 libutils_la_CFLAGS = \ 39 $(AM_CFLAGS) \ 40 $(LIBSYSTEMD_CFLAGS) 41diff --git a/configure.ac b/configure.ac 42index 7f74bac..062e310 100644 43--- a/configure.ac 44+++ b/configure.ac 45@@ -73,6 +73,9 @@ AS_IF([test "x$with_libsystemd" != xno], 46 )] 47 ) 48 49+AC_CHECK_HEADERS([printf.h], [], []) 50+AM_CONDITIONAL(HAVE_PRINTF_H, [test "x$ac_cv_header_print_h" = xyes]) 51+ 52 CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ 53 -pipe \ 54 -Wall \ 55diff --git a/src/log.c b/src/log.c 56index 15dec83..aecf231 100644 57--- a/src/log.c 58+++ b/src/log.c 59@@ -28,6 +28,7 @@ 60 #include <sys/uio.h> 61 #include <unistd.h> 62 63+#include "parse-printf-format.h" 64 #include "sd-messages.h" 65 66 #include "fd-util.h" 67diff --git a/src/parse-printf-format.c b/src/parse-printf-format.c 68new file mode 100644 69index 0000000..49437e5 70--- /dev/null 71+++ b/src/parse-printf-format.c 72@@ -0,0 +1,273 @@ 73+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ 74+ 75+/*** 76+ This file is part of systemd. 77+ 78+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk> 79+ 80+ With parts from the musl C library 81+ Copyright 2005-2014 Rich Felker, et al. 82+ 83+ systemd is free software; you can redistribute it and/or modify it 84+ under the terms of the GNU Lesser General Public License as published by 85+ the Free Software Foundation; either version 2.1 of the License, or 86+ (at your option) any later version. 87+ 88+ systemd is distributed in the hope that it will be useful, but 89+ WITHOUT ANY WARRANTY; without even the implied warranty of 90+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 91+ Lesser General Public License for more details. 92+ 93+ You should have received a copy of the GNU Lesser General Public License 94+ along with systemd; If not, see <http://www.gnu.org/licenses/>. 95+***/ 96+ 97+#include <stddef.h> 98+#include <string.h> 99+ 100+#include "parse-printf-format.h" 101+ 102+static const char *consume_nonarg(const char *fmt) 103+{ 104+ do { 105+ if (*fmt == '\0') 106+ return fmt; 107+ } while (*fmt++ != '%'); 108+ return fmt; 109+} 110+ 111+static const char *consume_num(const char *fmt) 112+{ 113+ for (;*fmt >= '0' && *fmt <= '9'; fmt++) 114+ /* do nothing */; 115+ return fmt; 116+} 117+ 118+static const char *consume_argn(const char *fmt, size_t *arg) 119+{ 120+ const char *p = fmt; 121+ size_t val = 0; 122+ 123+ if (*p < '1' || *p > '9') 124+ return fmt; 125+ do { 126+ val = 10*val + (*p++ - '0'); 127+ } while (*p >= '0' && *p <= '9'); 128+ 129+ if (*p != '$') 130+ return fmt; 131+ *arg = val; 132+ return p+1; 133+} 134+ 135+static const char *consume_flags(const char *fmt) 136+{ 137+ while (1) { 138+ switch (*fmt) { 139+ case '#': 140+ case '0': 141+ case '-': 142+ case ' ': 143+ case '+': 144+ case '\'': 145+ case 'I': 146+ fmt++; 147+ continue; 148+ } 149+ return fmt; 150+ } 151+} 152+ 153+enum state { 154+ BARE, 155+ LPRE, 156+ LLPRE, 157+ HPRE, 158+ HHPRE, 159+ BIGLPRE, 160+ ZTPRE, 161+ JPRE, 162+ STOP 163+}; 164+ 165+enum type { 166+ NONE, 167+ PTR, 168+ INT, 169+ UINT, 170+ ULLONG, 171+ LONG, 172+ ULONG, 173+ SHORT, 174+ USHORT, 175+ CHAR, 176+ UCHAR, 177+ LLONG, 178+ SIZET, 179+ IMAX, 180+ UMAX, 181+ PDIFF, 182+ UIPTR, 183+ DBL, 184+ LDBL, 185+ MAXTYPE 186+}; 187+ 188+static const short pa_types[MAXTYPE] = { 189+ [NONE] = PA_INT, 190+ [PTR] = PA_POINTER, 191+ [INT] = PA_INT, 192+ [UINT] = PA_INT, 193+ [ULLONG] = PA_INT | PA_FLAG_LONG_LONG, 194+ [LONG] = PA_INT | PA_FLAG_LONG, 195+ [ULONG] = PA_INT | PA_FLAG_LONG, 196+ [SHORT] = PA_INT | PA_FLAG_SHORT, 197+ [USHORT] = PA_INT | PA_FLAG_SHORT, 198+ [CHAR] = PA_CHAR, 199+ [UCHAR] = PA_CHAR, 200+ [LLONG] = PA_INT | PA_FLAG_LONG_LONG, 201+ [SIZET] = PA_INT | PA_FLAG_LONG, 202+ [IMAX] = PA_INT | PA_FLAG_LONG_LONG, 203+ [UMAX] = PA_INT | PA_FLAG_LONG_LONG, 204+ [PDIFF] = PA_INT | PA_FLAG_LONG_LONG, 205+ [UIPTR] = PA_INT | PA_FLAG_LONG, 206+ [DBL] = PA_DOUBLE, 207+ [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE 208+}; 209+ 210+#define S(x) [(x)-'A'] 211+#define E(x) (STOP + (x)) 212+ 213+static const unsigned char states[]['z'-'A'+1] = { 214+ { /* 0: bare types */ 215+ S('d') = E(INT), S('i') = E(INT), 216+ S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT), 217+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL), 218+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL), 219+ S('c') = E(CHAR),S('C') = E(INT), 220+ S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR), 221+ S('m') = E(NONE), 222+ S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, 223+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE 224+ }, { /* 1: l-prefixed */ 225+ S('d') = E(LONG), S('i') = E(LONG), 226+ S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG), 227+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL), 228+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL), 229+ S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR), 230+ S('l') = LLPRE 231+ }, { /* 2: ll-prefixed */ 232+ S('d') = E(LLONG), S('i') = E(LLONG), 233+ S('o') = E(ULLONG),S('u') = E(ULLONG), 234+ S('x') = E(ULLONG),S('X') = E(ULLONG), 235+ S('n') = E(PTR) 236+ }, { /* 3: h-prefixed */ 237+ S('d') = E(SHORT), S('i') = E(SHORT), 238+ S('o') = E(USHORT),S('u') = E(USHORT), 239+ S('x') = E(USHORT),S('X') = E(USHORT), 240+ S('n') = E(PTR), 241+ S('h') = HHPRE 242+ }, { /* 4: hh-prefixed */ 243+ S('d') = E(CHAR), S('i') = E(CHAR), 244+ S('o') = E(UCHAR),S('u') = E(UCHAR), 245+ S('x') = E(UCHAR),S('X') = E(UCHAR), 246+ S('n') = E(PTR) 247+ }, { /* 5: L-prefixed */ 248+ S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL), 249+ S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL), 250+ S('n') = E(PTR) 251+ }, { /* 6: z- or t-prefixed (assumed to be same size) */ 252+ S('d') = E(PDIFF),S('i') = E(PDIFF), 253+ S('o') = E(SIZET),S('u') = E(SIZET), 254+ S('x') = E(SIZET),S('X') = E(SIZET), 255+ S('n') = E(PTR) 256+ }, { /* 7: j-prefixed */ 257+ S('d') = E(IMAX), S('i') = E(IMAX), 258+ S('o') = E(UMAX), S('u') = E(UMAX), 259+ S('x') = E(UMAX), S('X') = E(UMAX), 260+ S('n') = E(PTR) 261+ } 262+}; 263+ 264+size_t parse_printf_format(const char *fmt, size_t n, int *types) 265+{ 266+ size_t i = 0; 267+ size_t last = 0; 268+ 269+ memset(types, 0, n); 270+ 271+ while (1) { 272+ size_t arg; 273+ unsigned int state; 274+ 275+ fmt = consume_nonarg(fmt); 276+ if (*fmt == '\0') 277+ break; 278+ if (*fmt == '%') { 279+ fmt++; 280+ continue; 281+ } 282+ arg = 0; 283+ fmt = consume_argn(fmt, &arg); 284+ /* flags */ 285+ fmt = consume_flags(fmt); 286+ /* width */ 287+ if (*fmt == '*') { 288+ size_t warg = 0; 289+ fmt = consume_argn(fmt+1, &warg); 290+ if (warg == 0) 291+ warg = ++i; 292+ if (warg > last) 293+ last = warg; 294+ if (warg <= n && types[warg-1] == NONE) 295+ types[warg-1] = INT; 296+ } else 297+ fmt = consume_num(fmt); 298+ /* precision */ 299+ if (*fmt == '.') { 300+ fmt++; 301+ if (*fmt == '*') { 302+ size_t parg = 0; 303+ fmt = consume_argn(fmt+1, &parg); 304+ if (parg == 0) 305+ parg = ++i; 306+ if (parg > last) 307+ last = parg; 308+ if (parg <= n && types[parg-1] == NONE) 309+ types[parg-1] = INT; 310+ } else { 311+ if (*fmt == '-') 312+ fmt++; 313+ fmt = consume_num(fmt); 314+ } 315+ } 316+ /* length modifier and conversion specifier */ 317+ state = BARE; 318+ do { 319+ unsigned char c = *fmt++; 320+ 321+ if (c < 'A' || c > 'z') 322+ continue; 323+ state = states[state]S(c); 324+ if (state == 0) 325+ continue; 326+ } while (state < STOP); 327+ 328+ if (state == E(NONE)) 329+ continue; 330+ 331+ if (arg == 0) 332+ arg = ++i; 333+ if (arg > last) 334+ last = arg; 335+ if (arg <= n) 336+ types[arg-1] = state - STOP; 337+ } 338+ 339+ if (last > n) 340+ last = n; 341+ for (i = 0; i < last; i++) 342+ types[i] = pa_types[types[i]]; 343+ 344+ return last; 345+} 346diff --git a/src/parse-printf-format.h b/src/parse-printf-format.h 347new file mode 100644 348index 0000000..4371177 349--- /dev/null 350+++ b/src/parse-printf-format.h 351@@ -0,0 +1,57 @@ 352+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ 353+ 354+/*** 355+ This file is part of systemd. 356+ 357+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk> 358+ 359+ With parts from the GNU C Library 360+ Copyright 1991-2014 Free Software Foundation, Inc. 361+ 362+ systemd is free software; you can redistribute it and/or modify it 363+ under the terms of the GNU Lesser General Public License as published by 364+ the Free Software Foundation; either version 2.1 of the License, or 365+ (at your option) any later version. 366+ 367+ systemd is distributed in the hope that it will be useful, but 368+ WITHOUT ANY WARRANTY; without even the implied warranty of 369+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 370+ Lesser General Public License for more details. 371+ 372+ You should have received a copy of the GNU Lesser General Public License 373+ along with systemd; If not, see <http://www.gnu.org/licenses/>. 374+***/ 375+ 376+#pragma once 377+ 378+#include "config.h" 379+ 380+#ifdef HAVE_PRINTF_H 381+#include <printf.h> 382+#else 383+ 384+#include <stddef.h> 385+ 386+enum { /* C type: */ 387+ PA_INT, /* int */ 388+ PA_CHAR, /* int, cast to char */ 389+ PA_WCHAR, /* wide char */ 390+ PA_STRING, /* const char *, a '\0'-terminated string */ 391+ PA_WSTRING, /* const wchar_t *, wide character string */ 392+ PA_POINTER, /* void * */ 393+ PA_FLOAT, /* float */ 394+ PA_DOUBLE, /* double */ 395+ PA_LAST 396+}; 397+ 398+/* Flag bits that can be set in a type returned by `parse_printf_format'. */ 399+#define PA_FLAG_MASK 0xff00 400+#define PA_FLAG_LONG_LONG (1 << 8) 401+#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG 402+#define PA_FLAG_LONG (1 << 9) 403+#define PA_FLAG_SHORT (1 << 10) 404+#define PA_FLAG_PTR (1 << 11) 405+ 406+size_t parse_printf_format(const char *fmt, size_t n, int *types); 407+ 408+#endif /* HAVE_PRINTF_H */ 409diff --git a/src/stdio-util.h b/src/stdio-util.h 410index 0a67557..21cc515 100644 411--- a/src/stdio-util.h 412+++ b/src/stdio-util.h 413@@ -19,7 +19,6 @@ 414 along with systemd; If not, see <http://www.gnu.org/licenses/>. 415 ***/ 416 417-#include <printf.h> 418 #include <stdarg.h> 419 #include <stdio.h> 420 #include <sys/types.h> 421-- 4222.13.6 423 424