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