(root)/
gcc-13.2.0/
libiberty/
vprintf-support.c
       1  /* Estimate the length of the string generated by a vprintf-like
       2     function.  Used by vasprintf and xvasprintf.
       3     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       4  
       5  This file is part of the libiberty library.
       6  Libiberty is free software; you can redistribute it and/or
       7  modify it under the terms of the GNU Library General Public
       8  License as published by the Free Software Foundation; either
       9  version 2 of the License, or (at your option) any later version.
      10  
      11  Libiberty is distributed in the hope that it will be useful,
      12  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14  Library General Public License for more details.
      15  
      16  You should have received a copy of the GNU Library General Public
      17  License along with libiberty; see the file COPYING.LIB.  If not, write
      18  to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
      19  Floor, Boston, MA 02110-1301, USA.  */
      20  
      21  #ifdef HAVE_CONFIG_H
      22  #include "config.h"
      23  #endif
      24  #include <ansidecl.h>
      25  #include <stdarg.h>
      26  #if !defined (va_copy) && defined (__va_copy)
      27  # define va_copy(d,s)  __va_copy((d),(s))
      28  #endif
      29  #include <stdio.h>
      30  #ifdef HAVE_STRING_H
      31  #include <string.h>
      32  #endif
      33  #ifdef HAVE_STDLIB_H
      34  #include <stdlib.h>
      35  #else
      36  extern unsigned long strtoul ();
      37  #endif
      38  #include "libiberty.h"
      39  
      40  int
      41  libiberty_vprintf_buffer_size (const char *format, va_list args)
      42  {
      43    const char *p = format;
      44    /* Add one to make sure that it is never zero, which might cause malloc
      45       to return NULL.  */
      46    int total_width = strlen (format) + 1;
      47    va_list ap;
      48  
      49  #ifdef va_copy
      50    va_copy (ap, args);
      51  #else
      52    memcpy ((void *) &ap, (void *) &args, sizeof (va_list));
      53  #endif
      54  
      55    while (*p != '\0')
      56      {
      57        if (*p++ == '%')
      58  	{
      59  	  while (strchr ("-+ #0", *p))
      60  	    ++p;
      61  	  if (*p == '*')
      62  	    {
      63  	      ++p;
      64  	      total_width += abs (va_arg (ap, int));
      65  	    }
      66  	  else
      67  	    total_width += strtoul (p, (char **) &p, 10);
      68  	  if (*p == '.')
      69  	    {
      70  	      ++p;
      71  	      if (*p == '*')
      72  		{
      73  		  ++p;
      74  		  total_width += abs (va_arg (ap, int));
      75  		}
      76  	      else
      77  	      total_width += strtoul (p, (char **) &p, 10);
      78  	    }
      79  	  while (strchr ("hlL", *p))
      80  	    ++p;
      81  	  /* Should be big enough for any format specifier except %s and floats.  */
      82  	  total_width += 30;
      83  	  switch (*p)
      84  	    {
      85  	    case 'd':
      86  	    case 'i':
      87  	    case 'o':
      88  	    case 'u':
      89  	    case 'x':
      90  	    case 'X':
      91  	    case 'c':
      92  	      (void) va_arg (ap, int);
      93  	      break;
      94  	    case 'f':
      95  	    case 'e':
      96  	    case 'E':
      97  	    case 'g':
      98  	    case 'G':
      99  	      (void) va_arg (ap, double);
     100  	      /* Since an ieee double can have an exponent of 307, we'll
     101  		 make the buffer wide enough to cover the gross case. */
     102  	      total_width += 307;
     103  	      break;
     104  	    case 's':
     105  	      total_width += strlen (va_arg (ap, char *));
     106  	      break;
     107  	    case 'p':
     108  	    case 'n':
     109  	      (void) va_arg (ap, char *);
     110  	      break;
     111  	    }
     112  	  p++;
     113  	}
     114      }
     115  #ifdef va_copy
     116    va_end (ap);
     117  #endif
     118    return total_width;
     119  }