15ba6b03cSchristos /* Estimate the length of the string generated by a vprintf-like
25ba6b03cSchristos    function.  Used by vasprintf and xvasprintf.
3*f22f0ef4Schristos    Copyright (C) 1994-2022 Free Software Foundation, Inc.
45ba6b03cSchristos 
55ba6b03cSchristos This file is part of the libiberty library.
65ba6b03cSchristos Libiberty is free software; you can redistribute it and/or
75ba6b03cSchristos modify it under the terms of the GNU Library General Public
85ba6b03cSchristos License as published by the Free Software Foundation; either
95ba6b03cSchristos version 2 of the License, or (at your option) any later version.
105ba6b03cSchristos 
115ba6b03cSchristos Libiberty is distributed in the hope that it will be useful,
125ba6b03cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
135ba6b03cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145ba6b03cSchristos Library General Public License for more details.
155ba6b03cSchristos 
165ba6b03cSchristos You should have received a copy of the GNU Library General Public
175ba6b03cSchristos License along with libiberty; see the file COPYING.LIB.  If not, write
185ba6b03cSchristos to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
195ba6b03cSchristos Floor, Boston, MA 02110-1301, USA.  */
205ba6b03cSchristos 
215ba6b03cSchristos #ifdef HAVE_CONFIG_H
225ba6b03cSchristos #include "config.h"
235ba6b03cSchristos #endif
245ba6b03cSchristos #include <ansidecl.h>
255ba6b03cSchristos #include <stdarg.h>
265ba6b03cSchristos #if !defined (va_copy) && defined (__va_copy)
275ba6b03cSchristos # define va_copy(d,s)  __va_copy((d),(s))
285ba6b03cSchristos #endif
295ba6b03cSchristos #include <stdio.h>
305ba6b03cSchristos #ifdef HAVE_STRING_H
315ba6b03cSchristos #include <string.h>
325ba6b03cSchristos #endif
335ba6b03cSchristos #ifdef HAVE_STDLIB_H
345ba6b03cSchristos #include <stdlib.h>
355ba6b03cSchristos #else
365ba6b03cSchristos extern unsigned long strtoul ();
375ba6b03cSchristos #endif
385ba6b03cSchristos #include "libiberty.h"
395ba6b03cSchristos 
405ba6b03cSchristos int
libiberty_vprintf_buffer_size(const char * format,va_list args)415ba6b03cSchristos libiberty_vprintf_buffer_size (const char *format, va_list args)
425ba6b03cSchristos {
435ba6b03cSchristos   const char *p = format;
445ba6b03cSchristos   /* Add one to make sure that it is never zero, which might cause malloc
455ba6b03cSchristos      to return NULL.  */
465ba6b03cSchristos   int total_width = strlen (format) + 1;
475ba6b03cSchristos   va_list ap;
485ba6b03cSchristos 
495ba6b03cSchristos #ifdef va_copy
505ba6b03cSchristos   va_copy (ap, args);
515ba6b03cSchristos #else
52*f22f0ef4Schristos   memcpy ((void *) &ap, (void *) &args, sizeof (va_list));
535ba6b03cSchristos #endif
545ba6b03cSchristos 
555ba6b03cSchristos   while (*p != '\0')
565ba6b03cSchristos     {
575ba6b03cSchristos       if (*p++ == '%')
585ba6b03cSchristos 	{
595ba6b03cSchristos 	  while (strchr ("-+ #0", *p))
605ba6b03cSchristos 	    ++p;
615ba6b03cSchristos 	  if (*p == '*')
625ba6b03cSchristos 	    {
635ba6b03cSchristos 	      ++p;
645ba6b03cSchristos 	      total_width += abs (va_arg (ap, int));
655ba6b03cSchristos 	    }
665ba6b03cSchristos 	  else
675ba6b03cSchristos 	    total_width += strtoul (p, (char **) &p, 10);
685ba6b03cSchristos 	  if (*p == '.')
695ba6b03cSchristos 	    {
705ba6b03cSchristos 	      ++p;
715ba6b03cSchristos 	      if (*p == '*')
725ba6b03cSchristos 		{
735ba6b03cSchristos 		  ++p;
745ba6b03cSchristos 		  total_width += abs (va_arg (ap, int));
755ba6b03cSchristos 		}
765ba6b03cSchristos 	      else
775ba6b03cSchristos 	      total_width += strtoul (p, (char **) &p, 10);
785ba6b03cSchristos 	    }
795ba6b03cSchristos 	  while (strchr ("hlL", *p))
805ba6b03cSchristos 	    ++p;
815ba6b03cSchristos 	  /* Should be big enough for any format specifier except %s and floats.  */
825ba6b03cSchristos 	  total_width += 30;
835ba6b03cSchristos 	  switch (*p)
845ba6b03cSchristos 	    {
855ba6b03cSchristos 	    case 'd':
865ba6b03cSchristos 	    case 'i':
875ba6b03cSchristos 	    case 'o':
885ba6b03cSchristos 	    case 'u':
895ba6b03cSchristos 	    case 'x':
905ba6b03cSchristos 	    case 'X':
915ba6b03cSchristos 	    case 'c':
925ba6b03cSchristos 	      (void) va_arg (ap, int);
935ba6b03cSchristos 	      break;
945ba6b03cSchristos 	    case 'f':
955ba6b03cSchristos 	    case 'e':
965ba6b03cSchristos 	    case 'E':
975ba6b03cSchristos 	    case 'g':
985ba6b03cSchristos 	    case 'G':
995ba6b03cSchristos 	      (void) va_arg (ap, double);
1005ba6b03cSchristos 	      /* Since an ieee double can have an exponent of 307, we'll
1015ba6b03cSchristos 		 make the buffer wide enough to cover the gross case. */
1025ba6b03cSchristos 	      total_width += 307;
1035ba6b03cSchristos 	      break;
1045ba6b03cSchristos 	    case 's':
1055ba6b03cSchristos 	      total_width += strlen (va_arg (ap, char *));
1065ba6b03cSchristos 	      break;
1075ba6b03cSchristos 	    case 'p':
1085ba6b03cSchristos 	    case 'n':
1095ba6b03cSchristos 	      (void) va_arg (ap, char *);
1105ba6b03cSchristos 	      break;
1115ba6b03cSchristos 	    }
1125ba6b03cSchristos 	  p++;
1135ba6b03cSchristos 	}
1145ba6b03cSchristos     }
1155ba6b03cSchristos #ifdef va_copy
1165ba6b03cSchristos   va_end (ap);
1175ba6b03cSchristos #endif
1185ba6b03cSchristos   return total_width;
1195ba6b03cSchristos }
120