1a7c91847Schristos /* Formatted output to strings.
2a7c91847Schristos Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
3a7c91847Schristos
4a7c91847Schristos This program is free software; you can redistribute it and/or modify
5a7c91847Schristos it under the terms of the GNU General Public License as published by
6a7c91847Schristos the Free Software Foundation; either version 2, or (at your option)
7a7c91847Schristos any later version.
8a7c91847Schristos
9a7c91847Schristos This program is distributed in the hope that it will be useful,
10a7c91847Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
11a7c91847Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12a7c91847Schristos GNU General Public License for more details.
13a7c91847Schristos
14a7c91847Schristos You should have received a copy of the GNU General Public License along
15a7c91847Schristos with this program; if not, write to the Free Software Foundation,
16a7c91847Schristos Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17*5a6c14c8Schristos #include <sys/cdefs.h>
18*5a6c14c8Schristos __RCSID("$NetBSD: printf-parse.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
19*5a6c14c8Schristos
20a7c91847Schristos
21a7c91847Schristos #ifdef HAVE_CONFIG_H
22a7c91847Schristos # include <config.h>
23a7c91847Schristos #endif
24a7c91847Schristos
25a7c91847Schristos /* Specification. */
26a7c91847Schristos #if WIDE_CHAR_VERSION
27a7c91847Schristos # include "wprintf-parse.h"
28a7c91847Schristos #else
29a7c91847Schristos # include "printf-parse.h"
30a7c91847Schristos #endif
31a7c91847Schristos
32a7c91847Schristos /* Get size_t, NULL. */
33a7c91847Schristos #include <stddef.h>
34a7c91847Schristos
35a7c91847Schristos /* Get intmax_t. */
36a7c91847Schristos #if HAVE_STDINT_H_WITH_UINTMAX
37a7c91847Schristos # include <stdint.h>
38a7c91847Schristos #endif
39a7c91847Schristos #if HAVE_INTTYPES_H_WITH_UINTMAX
40a7c91847Schristos # include <inttypes.h>
41a7c91847Schristos #endif
42a7c91847Schristos
43a7c91847Schristos /* malloc(), realloc(), free(). */
44a7c91847Schristos #include <stdlib.h>
45a7c91847Schristos
46a7c91847Schristos /* Checked size_t computations. */
47a7c91847Schristos #include "xsize.h"
48a7c91847Schristos
49a7c91847Schristos #if WIDE_CHAR_VERSION
50a7c91847Schristos # define PRINTF_PARSE wprintf_parse
51a7c91847Schristos # define CHAR_T wchar_t
52a7c91847Schristos # define DIRECTIVE wchar_t_directive
53a7c91847Schristos # define DIRECTIVES wchar_t_directives
54a7c91847Schristos #else
55a7c91847Schristos # define PRINTF_PARSE printf_parse
56a7c91847Schristos # define CHAR_T char
57a7c91847Schristos # define DIRECTIVE char_directive
58a7c91847Schristos # define DIRECTIVES char_directives
59a7c91847Schristos #endif
60a7c91847Schristos
61a7c91847Schristos #ifdef STATIC
62a7c91847Schristos STATIC
63a7c91847Schristos #endif
64a7c91847Schristos int
PRINTF_PARSE(const CHAR_T * format,DIRECTIVES * d,arguments * a)65a7c91847Schristos PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
66a7c91847Schristos {
67a7c91847Schristos const CHAR_T *cp = format; /* pointer into format */
68a7c91847Schristos size_t arg_posn = 0; /* number of regular arguments consumed */
69a7c91847Schristos size_t d_allocated; /* allocated elements of d->dir */
70a7c91847Schristos size_t a_allocated; /* allocated elements of a->arg */
71a7c91847Schristos size_t max_width_length = 0;
72a7c91847Schristos size_t max_precision_length = 0;
73a7c91847Schristos
74a7c91847Schristos d->count = 0;
75a7c91847Schristos d_allocated = 1;
76a7c91847Schristos d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
77a7c91847Schristos if (d->dir == NULL)
78a7c91847Schristos /* Out of memory. */
79a7c91847Schristos return -1;
80a7c91847Schristos
81a7c91847Schristos a->count = 0;
82a7c91847Schristos a_allocated = 0;
83a7c91847Schristos a->arg = NULL;
84a7c91847Schristos
85a7c91847Schristos #define REGISTER_ARG(_index_,_type_) \
86a7c91847Schristos { \
87a7c91847Schristos size_t n = (_index_); \
88a7c91847Schristos if (n >= a_allocated) \
89a7c91847Schristos { \
90a7c91847Schristos size_t memory_size; \
91a7c91847Schristos argument *memory; \
92a7c91847Schristos \
93a7c91847Schristos a_allocated = xtimes (a_allocated, 2); \
94a7c91847Schristos if (a_allocated <= n) \
95a7c91847Schristos a_allocated = xsum (n, 1); \
96a7c91847Schristos memory_size = xtimes (a_allocated, sizeof (argument)); \
97a7c91847Schristos if (size_overflow_p (memory_size)) \
98a7c91847Schristos /* Overflow, would lead to out of memory. */ \
99a7c91847Schristos goto error; \
100a7c91847Schristos memory = (a->arg \
101a7c91847Schristos ? realloc (a->arg, memory_size) \
102a7c91847Schristos : malloc (memory_size)); \
103a7c91847Schristos if (memory == NULL) \
104a7c91847Schristos /* Out of memory. */ \
105a7c91847Schristos goto error; \
106a7c91847Schristos a->arg = memory; \
107a7c91847Schristos } \
108a7c91847Schristos while (a->count <= n) \
109a7c91847Schristos a->arg[a->count++].type = TYPE_NONE; \
110a7c91847Schristos if (a->arg[n].type == TYPE_NONE) \
111a7c91847Schristos a->arg[n].type = (_type_); \
112a7c91847Schristos else if (a->arg[n].type != (_type_)) \
113a7c91847Schristos /* Ambiguous type for positional argument. */ \
114a7c91847Schristos goto error; \
115a7c91847Schristos }
116a7c91847Schristos
117a7c91847Schristos while (*cp != '\0')
118a7c91847Schristos {
119a7c91847Schristos CHAR_T c = *cp++;
120a7c91847Schristos if (c == '%')
121a7c91847Schristos {
122a7c91847Schristos size_t arg_index = ARG_NONE;
123a7c91847Schristos DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
124a7c91847Schristos
125a7c91847Schristos /* Initialize the next directive. */
126a7c91847Schristos dp->dir_start = cp - 1;
127a7c91847Schristos dp->flags = 0;
128a7c91847Schristos dp->width_start = NULL;
129a7c91847Schristos dp->width_end = NULL;
130a7c91847Schristos dp->width_arg_index = ARG_NONE;
131a7c91847Schristos dp->precision_start = NULL;
132a7c91847Schristos dp->precision_end = NULL;
133a7c91847Schristos dp->precision_arg_index = ARG_NONE;
134a7c91847Schristos dp->arg_index = ARG_NONE;
135a7c91847Schristos
136a7c91847Schristos /* Test for positional argument. */
137a7c91847Schristos if (*cp >= '0' && *cp <= '9')
138a7c91847Schristos {
139a7c91847Schristos const CHAR_T *np;
140a7c91847Schristos
141a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
142a7c91847Schristos ;
143a7c91847Schristos if (*np == '$')
144a7c91847Schristos {
145a7c91847Schristos size_t n = 0;
146a7c91847Schristos
147a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
148a7c91847Schristos n = xsum (xtimes (n, 10), *np - '0');
149a7c91847Schristos if (n == 0)
150a7c91847Schristos /* Positional argument 0. */
151a7c91847Schristos goto error;
152a7c91847Schristos if (size_overflow_p (n))
153a7c91847Schristos /* n too large, would lead to out of memory later. */
154a7c91847Schristos goto error;
155a7c91847Schristos arg_index = n - 1;
156a7c91847Schristos cp = np + 1;
157a7c91847Schristos }
158a7c91847Schristos }
159a7c91847Schristos
160a7c91847Schristos /* Read the flags. */
161a7c91847Schristos for (;;)
162a7c91847Schristos {
163a7c91847Schristos if (*cp == '\'')
164a7c91847Schristos {
165a7c91847Schristos dp->flags |= FLAG_GROUP;
166a7c91847Schristos cp++;
167a7c91847Schristos }
168a7c91847Schristos else if (*cp == '-')
169a7c91847Schristos {
170a7c91847Schristos dp->flags |= FLAG_LEFT;
171a7c91847Schristos cp++;
172a7c91847Schristos }
173a7c91847Schristos else if (*cp == '+')
174a7c91847Schristos {
175a7c91847Schristos dp->flags |= FLAG_SHOWSIGN;
176a7c91847Schristos cp++;
177a7c91847Schristos }
178a7c91847Schristos else if (*cp == ' ')
179a7c91847Schristos {
180a7c91847Schristos dp->flags |= FLAG_SPACE;
181a7c91847Schristos cp++;
182a7c91847Schristos }
183a7c91847Schristos else if (*cp == '#')
184a7c91847Schristos {
185a7c91847Schristos dp->flags |= FLAG_ALT;
186a7c91847Schristos cp++;
187a7c91847Schristos }
188a7c91847Schristos else if (*cp == '0')
189a7c91847Schristos {
190a7c91847Schristos dp->flags |= FLAG_ZERO;
191a7c91847Schristos cp++;
192a7c91847Schristos }
193a7c91847Schristos else
194a7c91847Schristos break;
195a7c91847Schristos }
196a7c91847Schristos
197a7c91847Schristos /* Parse the field width. */
198a7c91847Schristos if (*cp == '*')
199a7c91847Schristos {
200a7c91847Schristos dp->width_start = cp;
201a7c91847Schristos cp++;
202a7c91847Schristos dp->width_end = cp;
203a7c91847Schristos if (max_width_length < 1)
204a7c91847Schristos max_width_length = 1;
205a7c91847Schristos
206a7c91847Schristos /* Test for positional argument. */
207a7c91847Schristos if (*cp >= '0' && *cp <= '9')
208a7c91847Schristos {
209a7c91847Schristos const CHAR_T *np;
210a7c91847Schristos
211a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
212a7c91847Schristos ;
213a7c91847Schristos if (*np == '$')
214a7c91847Schristos {
215a7c91847Schristos size_t n = 0;
216a7c91847Schristos
217a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
218a7c91847Schristos n = xsum (xtimes (n, 10), *np - '0');
219a7c91847Schristos if (n == 0)
220a7c91847Schristos /* Positional argument 0. */
221a7c91847Schristos goto error;
222a7c91847Schristos if (size_overflow_p (n))
223a7c91847Schristos /* n too large, would lead to out of memory later. */
224a7c91847Schristos goto error;
225a7c91847Schristos dp->width_arg_index = n - 1;
226a7c91847Schristos cp = np + 1;
227a7c91847Schristos }
228a7c91847Schristos }
229a7c91847Schristos if (dp->width_arg_index == ARG_NONE)
230a7c91847Schristos {
231a7c91847Schristos dp->width_arg_index = arg_posn++;
232a7c91847Schristos if (dp->width_arg_index == ARG_NONE)
233a7c91847Schristos /* arg_posn wrapped around. */
234a7c91847Schristos goto error;
235a7c91847Schristos }
236a7c91847Schristos REGISTER_ARG (dp->width_arg_index, TYPE_INT);
237a7c91847Schristos }
238a7c91847Schristos else if (*cp >= '0' && *cp <= '9')
239a7c91847Schristos {
240a7c91847Schristos size_t width_length;
241a7c91847Schristos
242a7c91847Schristos dp->width_start = cp;
243a7c91847Schristos for (; *cp >= '0' && *cp <= '9'; cp++)
244a7c91847Schristos ;
245a7c91847Schristos dp->width_end = cp;
246a7c91847Schristos width_length = dp->width_end - dp->width_start;
247a7c91847Schristos if (max_width_length < width_length)
248a7c91847Schristos max_width_length = width_length;
249a7c91847Schristos }
250a7c91847Schristos
251a7c91847Schristos /* Parse the precision. */
252a7c91847Schristos if (*cp == '.')
253a7c91847Schristos {
254a7c91847Schristos cp++;
255a7c91847Schristos if (*cp == '*')
256a7c91847Schristos {
257a7c91847Schristos dp->precision_start = cp - 1;
258a7c91847Schristos cp++;
259a7c91847Schristos dp->precision_end = cp;
260a7c91847Schristos if (max_precision_length < 2)
261a7c91847Schristos max_precision_length = 2;
262a7c91847Schristos
263a7c91847Schristos /* Test for positional argument. */
264a7c91847Schristos if (*cp >= '0' && *cp <= '9')
265a7c91847Schristos {
266a7c91847Schristos const CHAR_T *np;
267a7c91847Schristos
268a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
269a7c91847Schristos ;
270a7c91847Schristos if (*np == '$')
271a7c91847Schristos {
272a7c91847Schristos size_t n = 0;
273a7c91847Schristos
274a7c91847Schristos for (np = cp; *np >= '0' && *np <= '9'; np++)
275a7c91847Schristos n = xsum (xtimes (n, 10), *np - '0');
276a7c91847Schristos if (n == 0)
277a7c91847Schristos /* Positional argument 0. */
278a7c91847Schristos goto error;
279a7c91847Schristos if (size_overflow_p (n))
280a7c91847Schristos /* n too large, would lead to out of memory
281a7c91847Schristos later. */
282a7c91847Schristos goto error;
283a7c91847Schristos dp->precision_arg_index = n - 1;
284a7c91847Schristos cp = np + 1;
285a7c91847Schristos }
286a7c91847Schristos }
287a7c91847Schristos if (dp->precision_arg_index == ARG_NONE)
288a7c91847Schristos {
289a7c91847Schristos dp->precision_arg_index = arg_posn++;
290a7c91847Schristos if (dp->precision_arg_index == ARG_NONE)
291a7c91847Schristos /* arg_posn wrapped around. */
292a7c91847Schristos goto error;
293a7c91847Schristos }
294a7c91847Schristos REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
295a7c91847Schristos }
296a7c91847Schristos else
297a7c91847Schristos {
298a7c91847Schristos size_t precision_length;
299a7c91847Schristos
300a7c91847Schristos dp->precision_start = cp - 1;
301a7c91847Schristos for (; *cp >= '0' && *cp <= '9'; cp++)
302a7c91847Schristos ;
303a7c91847Schristos dp->precision_end = cp;
304a7c91847Schristos precision_length = dp->precision_end - dp->precision_start;
305a7c91847Schristos if (max_precision_length < precision_length)
306a7c91847Schristos max_precision_length = precision_length;
307a7c91847Schristos }
308a7c91847Schristos }
309a7c91847Schristos
310a7c91847Schristos {
311a7c91847Schristos arg_type type;
312a7c91847Schristos
313a7c91847Schristos /* Parse argument type/size specifiers. */
314a7c91847Schristos {
315a7c91847Schristos int flags = 0;
316a7c91847Schristos
317a7c91847Schristos for (;;)
318a7c91847Schristos {
319a7c91847Schristos if (*cp == 'h')
320a7c91847Schristos {
321a7c91847Schristos flags |= (1 << (flags & 1));
322a7c91847Schristos cp++;
323a7c91847Schristos }
324a7c91847Schristos else if (*cp == 'L')
325a7c91847Schristos {
326a7c91847Schristos flags |= 4;
327a7c91847Schristos cp++;
328a7c91847Schristos }
329a7c91847Schristos else if (*cp == 'l')
330a7c91847Schristos {
331a7c91847Schristos flags += 8;
332a7c91847Schristos cp++;
333a7c91847Schristos }
334a7c91847Schristos #ifdef HAVE_INTMAX_T
335a7c91847Schristos else if (*cp == 'j')
336a7c91847Schristos {
337a7c91847Schristos if (sizeof (intmax_t) > sizeof (long))
338a7c91847Schristos {
339a7c91847Schristos /* intmax_t = long long */
340a7c91847Schristos flags += 16;
341a7c91847Schristos }
342a7c91847Schristos else if (sizeof (intmax_t) > sizeof (int))
343a7c91847Schristos {
344a7c91847Schristos /* intmax_t = long */
345a7c91847Schristos flags += 8;
346a7c91847Schristos }
347a7c91847Schristos cp++;
348a7c91847Schristos }
349a7c91847Schristos #endif
350a7c91847Schristos else if (*cp == 'z' || *cp == 'Z')
351a7c91847Schristos {
352a7c91847Schristos /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
353a7c91847Schristos because the warning facility in gcc-2.95.2 understands
354a7c91847Schristos only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
355a7c91847Schristos if (sizeof (size_t) > sizeof (long))
356a7c91847Schristos {
357a7c91847Schristos /* size_t = long long */
358a7c91847Schristos flags += 16;
359a7c91847Schristos }
360a7c91847Schristos else if (sizeof (size_t) > sizeof (int))
361a7c91847Schristos {
362a7c91847Schristos /* size_t = long */
363a7c91847Schristos flags += 8;
364a7c91847Schristos }
365a7c91847Schristos cp++;
366a7c91847Schristos }
367a7c91847Schristos else if (*cp == 't')
368a7c91847Schristos {
369a7c91847Schristos if (sizeof (ptrdiff_t) > sizeof (long))
370a7c91847Schristos {
371a7c91847Schristos /* ptrdiff_t = long long */
372a7c91847Schristos flags += 16;
373a7c91847Schristos }
374a7c91847Schristos else if (sizeof (ptrdiff_t) > sizeof (int))
375a7c91847Schristos {
376a7c91847Schristos /* ptrdiff_t = long */
377a7c91847Schristos flags += 8;
378a7c91847Schristos }
379a7c91847Schristos cp++;
380a7c91847Schristos }
381a7c91847Schristos else
382a7c91847Schristos break;
383a7c91847Schristos }
384a7c91847Schristos
385a7c91847Schristos /* Read the conversion character. */
386a7c91847Schristos c = *cp++;
387a7c91847Schristos switch (c)
388a7c91847Schristos {
389a7c91847Schristos case 'd': case 'i':
390a7c91847Schristos #ifdef HAVE_LONG_LONG
391a7c91847Schristos if (flags >= 16 || (flags & 4))
392a7c91847Schristos type = TYPE_LONGLONGINT;
393a7c91847Schristos else
394a7c91847Schristos #endif
395a7c91847Schristos if (flags >= 8)
396a7c91847Schristos type = TYPE_LONGINT;
397a7c91847Schristos else if (flags & 2)
398a7c91847Schristos type = TYPE_SCHAR;
399a7c91847Schristos else if (flags & 1)
400a7c91847Schristos type = TYPE_SHORT;
401a7c91847Schristos else
402a7c91847Schristos type = TYPE_INT;
403a7c91847Schristos break;
404a7c91847Schristos case 'o': case 'u': case 'x': case 'X':
405a7c91847Schristos #ifdef HAVE_LONG_LONG
406a7c91847Schristos if (flags >= 16 || (flags & 4))
407a7c91847Schristos type = TYPE_ULONGLONGINT;
408a7c91847Schristos else
409a7c91847Schristos #endif
410a7c91847Schristos if (flags >= 8)
411a7c91847Schristos type = TYPE_ULONGINT;
412a7c91847Schristos else if (flags & 2)
413a7c91847Schristos type = TYPE_UCHAR;
414a7c91847Schristos else if (flags & 1)
415a7c91847Schristos type = TYPE_USHORT;
416a7c91847Schristos else
417a7c91847Schristos type = TYPE_UINT;
418a7c91847Schristos break;
419a7c91847Schristos case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
420a7c91847Schristos case 'a': case 'A':
421a7c91847Schristos #ifdef HAVE_LONG_DOUBLE
422a7c91847Schristos if (flags >= 16 || (flags & 4))
423a7c91847Schristos type = TYPE_LONGDOUBLE;
424a7c91847Schristos else
425a7c91847Schristos #endif
426a7c91847Schristos type = TYPE_DOUBLE;
427a7c91847Schristos break;
428a7c91847Schristos case 'c':
429a7c91847Schristos if (flags >= 8)
430a7c91847Schristos #ifdef HAVE_WINT_T
431a7c91847Schristos type = TYPE_WIDE_CHAR;
432a7c91847Schristos #else
433a7c91847Schristos goto error;
434a7c91847Schristos #endif
435a7c91847Schristos else
436a7c91847Schristos type = TYPE_CHAR;
437a7c91847Schristos break;
438a7c91847Schristos #ifdef HAVE_WINT_T
439a7c91847Schristos case 'C':
440a7c91847Schristos type = TYPE_WIDE_CHAR;
441a7c91847Schristos c = 'c';
442a7c91847Schristos break;
443a7c91847Schristos #endif
444a7c91847Schristos case 's':
445a7c91847Schristos if (flags >= 8)
446a7c91847Schristos #ifdef HAVE_WCHAR_T
447a7c91847Schristos type = TYPE_WIDE_STRING;
448a7c91847Schristos #else
449a7c91847Schristos goto error;
450a7c91847Schristos #endif
451a7c91847Schristos else
452a7c91847Schristos type = TYPE_STRING;
453a7c91847Schristos break;
454a7c91847Schristos #ifdef HAVE_WCHAR_T
455a7c91847Schristos case 'S':
456a7c91847Schristos type = TYPE_WIDE_STRING;
457a7c91847Schristos c = 's';
458a7c91847Schristos break;
459a7c91847Schristos #endif
460a7c91847Schristos case 'p':
461a7c91847Schristos type = TYPE_POINTER;
462a7c91847Schristos break;
463a7c91847Schristos case 'n':
464a7c91847Schristos #ifdef HAVE_LONG_LONG
465a7c91847Schristos if (flags >= 16 || (flags & 4))
466a7c91847Schristos type = TYPE_COUNT_LONGLONGINT_POINTER;
467a7c91847Schristos else
468a7c91847Schristos #endif
469a7c91847Schristos if (flags >= 8)
470a7c91847Schristos type = TYPE_COUNT_LONGINT_POINTER;
471a7c91847Schristos else if (flags & 2)
472a7c91847Schristos type = TYPE_COUNT_SCHAR_POINTER;
473a7c91847Schristos else if (flags & 1)
474a7c91847Schristos type = TYPE_COUNT_SHORT_POINTER;
475a7c91847Schristos else
476a7c91847Schristos type = TYPE_COUNT_INT_POINTER;
477a7c91847Schristos break;
478a7c91847Schristos case '%':
479a7c91847Schristos type = TYPE_NONE;
480a7c91847Schristos break;
481a7c91847Schristos default:
482a7c91847Schristos /* Unknown conversion character. */
483a7c91847Schristos goto error;
484a7c91847Schristos }
485a7c91847Schristos }
486a7c91847Schristos
487a7c91847Schristos if (type != TYPE_NONE)
488a7c91847Schristos {
489a7c91847Schristos dp->arg_index = arg_index;
490a7c91847Schristos if (dp->arg_index == ARG_NONE)
491a7c91847Schristos {
492a7c91847Schristos dp->arg_index = arg_posn++;
493a7c91847Schristos if (dp->arg_index == ARG_NONE)
494a7c91847Schristos /* arg_posn wrapped around. */
495a7c91847Schristos goto error;
496a7c91847Schristos }
497a7c91847Schristos REGISTER_ARG (dp->arg_index, type);
498a7c91847Schristos }
499a7c91847Schristos dp->conversion = c;
500a7c91847Schristos dp->dir_end = cp;
501a7c91847Schristos }
502a7c91847Schristos
503a7c91847Schristos d->count++;
504a7c91847Schristos if (d->count >= d_allocated)
505a7c91847Schristos {
506a7c91847Schristos size_t memory_size;
507a7c91847Schristos DIRECTIVE *memory;
508a7c91847Schristos
509a7c91847Schristos d_allocated = xtimes (d_allocated, 2);
510a7c91847Schristos memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
511a7c91847Schristos if (size_overflow_p (memory_size))
512a7c91847Schristos /* Overflow, would lead to out of memory. */
513a7c91847Schristos goto error;
514a7c91847Schristos memory = realloc (d->dir, memory_size);
515a7c91847Schristos if (memory == NULL)
516a7c91847Schristos /* Out of memory. */
517a7c91847Schristos goto error;
518a7c91847Schristos d->dir = memory;
519a7c91847Schristos }
520a7c91847Schristos }
521a7c91847Schristos }
522a7c91847Schristos d->dir[d->count].dir_start = cp;
523a7c91847Schristos
524a7c91847Schristos d->max_width_length = max_width_length;
525a7c91847Schristos d->max_precision_length = max_precision_length;
526a7c91847Schristos return 0;
527a7c91847Schristos
528a7c91847Schristos error:
529a7c91847Schristos if (a->arg)
530a7c91847Schristos free (a->arg);
531a7c91847Schristos if (d->dir)
532a7c91847Schristos free (d->dir);
533a7c91847Schristos return -1;
534a7c91847Schristos }
535a7c91847Schristos
536a7c91847Schristos #undef DIRECTIVES
537a7c91847Schristos #undef DIRECTIVE
538a7c91847Schristos #undef CHAR_T
539a7c91847Schristos #undef PRINTF_PARSE
540