116dce513Schristos /* Estimate the length of the string generated by a vprintf-like
216dce513Schristos function. Used by vasprintf and xvasprintf.
3*e992f068Schristos Copyright (C) 1994-2022 Free Software Foundation, Inc.
416dce513Schristos
516dce513Schristos This file is part of the libiberty library.
616dce513Schristos Libiberty is free software; you can redistribute it and/or
716dce513Schristos modify it under the terms of the GNU Library General Public
816dce513Schristos License as published by the Free Software Foundation; either
916dce513Schristos version 2 of the License, or (at your option) any later version.
1016dce513Schristos
1116dce513Schristos Libiberty is distributed in the hope that it will be useful,
1216dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1316dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1416dce513Schristos Library General Public License for more details.
1516dce513Schristos
1616dce513Schristos You should have received a copy of the GNU Library General Public
1716dce513Schristos License along with libiberty; see the file COPYING.LIB. If not, write
1816dce513Schristos to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
1916dce513Schristos Floor, Boston, MA 02110-1301, USA. */
2016dce513Schristos
2116dce513Schristos #ifdef HAVE_CONFIG_H
2216dce513Schristos #include "config.h"
2316dce513Schristos #endif
2416dce513Schristos #include <ansidecl.h>
2516dce513Schristos #include <stdarg.h>
2616dce513Schristos #if !defined (va_copy) && defined (__va_copy)
2716dce513Schristos # define va_copy(d,s) __va_copy((d),(s))
2816dce513Schristos #endif
2916dce513Schristos #include <stdio.h>
3016dce513Schristos #ifdef HAVE_STRING_H
3116dce513Schristos #include <string.h>
3216dce513Schristos #endif
3316dce513Schristos #ifdef HAVE_STDLIB_H
3416dce513Schristos #include <stdlib.h>
3516dce513Schristos #else
3616dce513Schristos extern unsigned long strtoul ();
3716dce513Schristos #endif
3816dce513Schristos #include "libiberty.h"
3916dce513Schristos
4016dce513Schristos int
libiberty_vprintf_buffer_size(const char * format,va_list args)4116dce513Schristos libiberty_vprintf_buffer_size (const char *format, va_list args)
4216dce513Schristos {
4316dce513Schristos const char *p = format;
4416dce513Schristos /* Add one to make sure that it is never zero, which might cause malloc
4516dce513Schristos to return NULL. */
4616dce513Schristos int total_width = strlen (format) + 1;
4716dce513Schristos va_list ap;
4816dce513Schristos
4916dce513Schristos #ifdef va_copy
5016dce513Schristos va_copy (ap, args);
5116dce513Schristos #else
52*e992f068Schristos memcpy ((void *) &ap, (void *) &args, sizeof (va_list));
5316dce513Schristos #endif
5416dce513Schristos
5516dce513Schristos while (*p != '\0')
5616dce513Schristos {
5716dce513Schristos if (*p++ == '%')
5816dce513Schristos {
5916dce513Schristos while (strchr ("-+ #0", *p))
6016dce513Schristos ++p;
6116dce513Schristos if (*p == '*')
6216dce513Schristos {
6316dce513Schristos ++p;
6416dce513Schristos total_width += abs (va_arg (ap, int));
6516dce513Schristos }
6616dce513Schristos else
6716dce513Schristos total_width += strtoul (p, (char **) &p, 10);
6816dce513Schristos if (*p == '.')
6916dce513Schristos {
7016dce513Schristos ++p;
7116dce513Schristos if (*p == '*')
7216dce513Schristos {
7316dce513Schristos ++p;
7416dce513Schristos total_width += abs (va_arg (ap, int));
7516dce513Schristos }
7616dce513Schristos else
7716dce513Schristos total_width += strtoul (p, (char **) &p, 10);
7816dce513Schristos }
7916dce513Schristos while (strchr ("hlL", *p))
8016dce513Schristos ++p;
8116dce513Schristos /* Should be big enough for any format specifier except %s and floats. */
8216dce513Schristos total_width += 30;
8316dce513Schristos switch (*p)
8416dce513Schristos {
8516dce513Schristos case 'd':
8616dce513Schristos case 'i':
8716dce513Schristos case 'o':
8816dce513Schristos case 'u':
8916dce513Schristos case 'x':
9016dce513Schristos case 'X':
9116dce513Schristos case 'c':
9216dce513Schristos (void) va_arg (ap, int);
9316dce513Schristos break;
9416dce513Schristos case 'f':
9516dce513Schristos case 'e':
9616dce513Schristos case 'E':
9716dce513Schristos case 'g':
9816dce513Schristos case 'G':
9916dce513Schristos (void) va_arg (ap, double);
10016dce513Schristos /* Since an ieee double can have an exponent of 307, we'll
10116dce513Schristos make the buffer wide enough to cover the gross case. */
10216dce513Schristos total_width += 307;
10316dce513Schristos break;
10416dce513Schristos case 's':
10516dce513Schristos total_width += strlen (va_arg (ap, char *));
10616dce513Schristos break;
10716dce513Schristos case 'p':
10816dce513Schristos case 'n':
10916dce513Schristos (void) va_arg (ap, char *);
11016dce513Schristos break;
11116dce513Schristos }
11216dce513Schristos p++;
11316dce513Schristos }
11416dce513Schristos }
11516dce513Schristos #ifdef va_copy
11616dce513Schristos va_end (ap);
11716dce513Schristos #endif
11816dce513Schristos return total_width;
11916dce513Schristos }
120