11debfc3dSmrg /* Estimate the length of the string generated by a vprintf-like
21debfc3dSmrg function. Used by vasprintf and xvasprintf.
3*8feb0f0bSmrg Copyright (C) 1994-2020 Free Software Foundation, Inc.
41debfc3dSmrg
51debfc3dSmrg This file is part of the libiberty library.
61debfc3dSmrg Libiberty is free software; you can redistribute it and/or
71debfc3dSmrg modify it under the terms of the GNU Library General Public
81debfc3dSmrg License as published by the Free Software Foundation; either
91debfc3dSmrg version 2 of the License, or (at your option) any later version.
101debfc3dSmrg
111debfc3dSmrg Libiberty is distributed in the hope that it will be useful,
121debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
141debfc3dSmrg Library General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU Library General Public
171debfc3dSmrg License along with libiberty; see the file COPYING.LIB. If not, write
181debfc3dSmrg to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
191debfc3dSmrg Floor, Boston, MA 02110-1301, USA. */
201debfc3dSmrg
211debfc3dSmrg #ifdef HAVE_CONFIG_H
221debfc3dSmrg #include "config.h"
231debfc3dSmrg #endif
241debfc3dSmrg #include <ansidecl.h>
251debfc3dSmrg #include <stdarg.h>
261debfc3dSmrg #if !defined (va_copy) && defined (__va_copy)
271debfc3dSmrg # define va_copy(d,s) __va_copy((d),(s))
281debfc3dSmrg #endif
291debfc3dSmrg #include <stdio.h>
301debfc3dSmrg #ifdef HAVE_STRING_H
311debfc3dSmrg #include <string.h>
321debfc3dSmrg #endif
331debfc3dSmrg #ifdef HAVE_STDLIB_H
341debfc3dSmrg #include <stdlib.h>
351debfc3dSmrg #else
361debfc3dSmrg extern unsigned long strtoul ();
371debfc3dSmrg #endif
381debfc3dSmrg #include "libiberty.h"
391debfc3dSmrg #include "vprintf-support.h"
401debfc3dSmrg
411debfc3dSmrg int
libiberty_vprintf_buffer_size(const char * format,va_list args)421debfc3dSmrg libiberty_vprintf_buffer_size (const char *format, va_list args)
431debfc3dSmrg {
441debfc3dSmrg const char *p = format;
451debfc3dSmrg /* Add one to make sure that it is never zero, which might cause malloc
461debfc3dSmrg to return NULL. */
471debfc3dSmrg int total_width = strlen (format) + 1;
481debfc3dSmrg va_list ap;
491debfc3dSmrg
501debfc3dSmrg #ifdef va_copy
511debfc3dSmrg va_copy (ap, args);
521debfc3dSmrg #else
531debfc3dSmrg memcpy ((PTR) &ap, (PTR) &args, sizeof (va_list));
541debfc3dSmrg #endif
551debfc3dSmrg
561debfc3dSmrg while (*p != '\0')
571debfc3dSmrg {
581debfc3dSmrg if (*p++ == '%')
591debfc3dSmrg {
601debfc3dSmrg while (strchr ("-+ #0", *p))
611debfc3dSmrg ++p;
621debfc3dSmrg if (*p == '*')
631debfc3dSmrg {
641debfc3dSmrg ++p;
651debfc3dSmrg total_width += abs (va_arg (ap, int));
661debfc3dSmrg }
671debfc3dSmrg else
681debfc3dSmrg total_width += strtoul (p, (char **) &p, 10);
691debfc3dSmrg if (*p == '.')
701debfc3dSmrg {
711debfc3dSmrg ++p;
721debfc3dSmrg if (*p == '*')
731debfc3dSmrg {
741debfc3dSmrg ++p;
751debfc3dSmrg total_width += abs (va_arg (ap, int));
761debfc3dSmrg }
771debfc3dSmrg else
781debfc3dSmrg total_width += strtoul (p, (char **) &p, 10);
791debfc3dSmrg }
801debfc3dSmrg while (strchr ("hlL", *p))
811debfc3dSmrg ++p;
821debfc3dSmrg /* Should be big enough for any format specifier except %s and floats. */
831debfc3dSmrg total_width += 30;
841debfc3dSmrg switch (*p)
851debfc3dSmrg {
861debfc3dSmrg case 'd':
871debfc3dSmrg case 'i':
881debfc3dSmrg case 'o':
891debfc3dSmrg case 'u':
901debfc3dSmrg case 'x':
911debfc3dSmrg case 'X':
921debfc3dSmrg case 'c':
931debfc3dSmrg (void) va_arg (ap, int);
941debfc3dSmrg break;
951debfc3dSmrg case 'f':
961debfc3dSmrg case 'e':
971debfc3dSmrg case 'E':
981debfc3dSmrg case 'g':
991debfc3dSmrg case 'G':
1001debfc3dSmrg (void) va_arg (ap, double);
1011debfc3dSmrg /* Since an ieee double can have an exponent of 307, we'll
1021debfc3dSmrg make the buffer wide enough to cover the gross case. */
1031debfc3dSmrg total_width += 307;
1041debfc3dSmrg break;
1051debfc3dSmrg case 's':
1061debfc3dSmrg total_width += strlen (va_arg (ap, char *));
1071debfc3dSmrg break;
1081debfc3dSmrg case 'p':
1091debfc3dSmrg case 'n':
1101debfc3dSmrg (void) va_arg (ap, char *);
1111debfc3dSmrg break;
1121debfc3dSmrg }
1131debfc3dSmrg p++;
1141debfc3dSmrg }
1151debfc3dSmrg }
1161debfc3dSmrg #ifdef va_copy
1171debfc3dSmrg va_end (ap);
1181debfc3dSmrg #endif
1191debfc3dSmrg return total_width;
1201debfc3dSmrg }
121