xref: /netbsd-src/external/gpl3/binutils.old/dist/libiberty/vprintf-support.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
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