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