Blame libiberty/_doprnt.c

Packit Service 72eb06
/* Provide a version of _doprnt in terms of fprintf.
Packit Service 72eb06
   Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit Service 72eb06
   Contributed by Kaveh Ghazi  (ghazi@caip.rutgers.edu)  3/29/98
Packit Service 72eb06
Packit Service 72eb06
This program is free software; you can redistribute it and/or modify it
Packit Service 72eb06
under the terms of the GNU General Public License as published by the
Packit Service 72eb06
Free Software Foundation; either version 2, or (at your option) any
Packit Service 72eb06
later version.
Packit Service 72eb06
Packit Service 72eb06
This program is distributed in the hope that it will be useful,
Packit Service 72eb06
but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 72eb06
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 72eb06
GNU General Public License for more details.
Packit Service 72eb06
Packit Service 72eb06
You should have received a copy of the GNU General Public License
Packit Service 72eb06
along with this program; if not, write to the Free Software
Packit Service 72eb06
Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
Packit Service 72eb06
Packit Service 72eb06
#include "config.h"
Packit Service 72eb06
#include "ansidecl.h"
Packit Service 72eb06
#include "safe-ctype.h"
Packit Service 72eb06
Packit Service 72eb06
#include <stdio.h>
Packit Service 72eb06
#include <stdarg.h>
Packit Service 72eb06
#ifdef HAVE_STRING_H
Packit Service 72eb06
#include <string.h>
Packit Service 72eb06
#endif
Packit Service 72eb06
#ifdef HAVE_STDLIB_H
Packit Service 72eb06
#include <stdlib.h>
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
#undef _doprnt
Packit Service 72eb06
Packit Service 72eb06
#ifdef HAVE__DOPRNT
Packit Service 72eb06
#define TEST
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
#ifdef TEST /* Make sure to use the internal one.  */
Packit Service 72eb06
#define _doprnt my_doprnt
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
#define COPY_VA_INT \
Packit Service 72eb06
  do { \
Packit Service 72eb06
	 const int value = abs (va_arg (ap, int)); \
Packit Service 72eb06
	 char buf[32]; \
Packit Service 72eb06
	 ptr++; /* Go past the asterisk.  */ \
Packit Service 72eb06
	 *sptr = '\0'; /* NULL terminate sptr.  */ \
Packit Service 72eb06
	 sprintf(buf, "%d", value); \
Packit Service 72eb06
	 strcat(sptr, buf); \
Packit Service 72eb06
	 while (*sptr) sptr++; \
Packit Service 72eb06
     } while (0)
Packit Service 72eb06
Packit Service 72eb06
#define PRINT_CHAR(CHAR) \
Packit Service 72eb06
  do { \
Packit Service 72eb06
	 putc(CHAR, stream); \
Packit Service 72eb06
	 ptr++; \
Packit Service 72eb06
	 total_printed++; \
Packit Service 72eb06
	 continue; \
Packit Service 72eb06
     } while (0)
Packit Service 72eb06
Packit Service 72eb06
#define PRINT_TYPE(TYPE) \
Packit Service 72eb06
  do { \
Packit Service 72eb06
	int result; \
Packit Service 72eb06
	TYPE value = va_arg (ap, TYPE); \
Packit Service 72eb06
	*sptr++ = *ptr++; /* Copy the type specifier.  */ \
Packit Service 72eb06
	*sptr = '\0'; /* NULL terminate sptr.  */ \
Packit Service 72eb06
	result = fprintf(stream, specifier, value); \
Packit Service 72eb06
	if (result == -1) \
Packit Service 72eb06
	  return -1; \
Packit Service 72eb06
	else \
Packit Service 72eb06
	  { \
Packit Service 72eb06
	    total_printed += result; \
Packit Service 72eb06
	    continue; \
Packit Service 72eb06
	  } \
Packit Service 72eb06
      } while (0)
Packit Service 72eb06
Packit Service 72eb06
int
Packit Service 72eb06
_doprnt (const char *format, va_list ap, FILE *stream)
Packit Service 72eb06
{
Packit Service 72eb06
  const char * ptr = format;
Packit Service 72eb06
  char specifier[128];
Packit Service 72eb06
  int total_printed = 0;
Packit Service 72eb06
  
Packit Service 72eb06
  while (*ptr != '\0')
Packit Service 72eb06
    {
Packit Service 72eb06
      if (*ptr != '%') /* While we have regular characters, print them.  */
Packit Service 72eb06
	PRINT_CHAR(*ptr);
Packit Service 72eb06
      else /* We got a format specifier! */
Packit Service 72eb06
	{
Packit Service 72eb06
	  char * sptr = specifier;
Packit Service 72eb06
	  int wide_width = 0, short_width = 0;
Packit Service 72eb06
	  
Packit Service 72eb06
	  *sptr++ = *ptr++; /* Copy the % and move forward.  */
Packit Service 72eb06
Packit Service 72eb06
	  while (strchr ("-+ #0", *ptr)) /* Move past flags.  */
Packit Service 72eb06
	    *sptr++ = *ptr++;
Packit Service 72eb06
Packit Service 72eb06
	  if (*ptr == '*')
Packit Service 72eb06
	    COPY_VA_INT;
Packit Service 72eb06
	  else
Packit Service 72eb06
	    while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
Packit Service 72eb06
	      *sptr++ = *ptr++;
Packit Service 72eb06
	  
Packit Service 72eb06
	  if (*ptr == '.')
Packit Service 72eb06
	    {
Packit Service 72eb06
	      *sptr++ = *ptr++; /* Copy and go past the period.  */
Packit Service 72eb06
	      if (*ptr == '*')
Packit Service 72eb06
		COPY_VA_INT;
Packit Service 72eb06
	      else
Packit Service 72eb06
		while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
Packit Service 72eb06
		  *sptr++ = *ptr++;
Packit Service 72eb06
	    }
Packit Service 72eb06
	  while (strchr ("hlL", *ptr))
Packit Service 72eb06
	    {
Packit Service 72eb06
	      switch (*ptr)
Packit Service 72eb06
		{
Packit Service 72eb06
		case 'h':
Packit Service 72eb06
		  short_width = 1;
Packit Service 72eb06
		  break;
Packit Service 72eb06
		case 'l':
Packit Service 72eb06
		  wide_width++;
Packit Service 72eb06
		  break;
Packit Service 72eb06
		case 'L':
Packit Service 72eb06
		  wide_width = 2;
Packit Service 72eb06
		  break;
Packit Service 72eb06
		default:
Packit Service 72eb06
		  abort();
Packit Service 72eb06
		}
Packit Service 72eb06
	      *sptr++ = *ptr++;
Packit Service 72eb06
	    }
Packit Service 72eb06
Packit Service 72eb06
	  switch (*ptr)
Packit Service 72eb06
	    {
Packit Service 72eb06
	    case 'd':
Packit Service 72eb06
	    case 'i':
Packit Service 72eb06
	    case 'o':
Packit Service 72eb06
	    case 'u':
Packit Service 72eb06
	    case 'x':
Packit Service 72eb06
	    case 'X':
Packit Service 72eb06
	    case 'c':
Packit Service 72eb06
	      {
Packit Service 72eb06
		/* Short values are promoted to int, so just copy it
Packit Service 72eb06
                   as an int and trust the C library printf to cast it
Packit Service 72eb06
                   to the right width.  */
Packit Service 72eb06
		if (short_width)
Packit Service 72eb06
		  PRINT_TYPE(int);
Packit Service 72eb06
		else
Packit Service 72eb06
		  {
Packit Service 72eb06
		    switch (wide_width)
Packit Service 72eb06
		      {
Packit Service 72eb06
		      case 0:
Packit Service 72eb06
			PRINT_TYPE(int);
Packit Service 72eb06
			break;
Packit Service 72eb06
		      case 1:
Packit Service 72eb06
			PRINT_TYPE(long);
Packit Service 72eb06
			break;
Packit Service 72eb06
		      case 2:
Packit Service 72eb06
		      default:
Packit Service 72eb06
#if defined(__GNUC__) || defined(HAVE_LONG_LONG)
Packit Service 72eb06
			PRINT_TYPE(long long);
Packit Service 72eb06
#else
Packit Service 72eb06
			PRINT_TYPE(long); /* Fake it and hope for the best.  */
Packit Service 72eb06
#endif
Packit Service 72eb06
			break;
Packit Service 72eb06
		      } /* End of switch (wide_width) */
Packit Service 72eb06
		  } /* End of else statement */
Packit Service 72eb06
	      } /* End of integer case */
Packit Service 72eb06
	      break;
Packit Service 72eb06
	    case 'f':
Packit Service 72eb06
	    case 'e':
Packit Service 72eb06
	    case 'E':
Packit Service 72eb06
	    case 'g':
Packit Service 72eb06
	    case 'G':
Packit Service 72eb06
	      {
Packit Service 72eb06
		if (wide_width == 0)
Packit Service 72eb06
		  PRINT_TYPE(double);
Packit Service 72eb06
		else
Packit Service 72eb06
		  {
Packit Service 72eb06
#if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
Packit Service 72eb06
		    PRINT_TYPE(long double);
Packit Service 72eb06
#else
Packit Service 72eb06
		    PRINT_TYPE(double); /* Fake it and hope for the best.  */
Packit Service 72eb06
#endif
Packit Service 72eb06
		  }
Packit Service 72eb06
	      }
Packit Service 72eb06
	      break;
Packit Service 72eb06
	    case 's':
Packit Service 72eb06
	      PRINT_TYPE(char *);
Packit Service 72eb06
	      break;
Packit Service 72eb06
	    case 'p':
Packit Service 72eb06
	      PRINT_TYPE(void *);
Packit Service 72eb06
	      break;
Packit Service 72eb06
	    case '%':
Packit Service 72eb06
	      PRINT_CHAR('%');
Packit Service 72eb06
	      break;
Packit Service 72eb06
	    default:
Packit Service 72eb06
	      abort();
Packit Service 72eb06
	    } /* End of switch (*ptr) */
Packit Service 72eb06
	} /* End of else statement */
Packit Service 72eb06
    }
Packit Service 72eb06
Packit Service 72eb06
  return total_printed;
Packit Service 72eb06
}
Packit Service 72eb06
Packit Service 72eb06
#ifdef TEST
Packit Service 72eb06
Packit Service 72eb06
#include <math.h>
Packit Service 72eb06
#ifndef M_PI
Packit Service 72eb06
#define M_PI (3.1415926535897932385)
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
#define RESULT(x) do \
Packit Service 72eb06
{ \
Packit Service 72eb06
    int i = (x); \
Packit Service 72eb06
    printf ("printed %d characters\n", i); \
Packit Service 72eb06
    fflush(stdin); \
Packit Service 72eb06
} while (0)
Packit Service 72eb06
Packit Service 72eb06
static int checkit (const char * format, ...) ATTRIBUTE_PRINTF_1;
Packit Service 72eb06
Packit Service 72eb06
static int
Packit Service 72eb06
checkit (const char* format, ...)
Packit Service 72eb06
{
Packit Service 72eb06
  int result;
Packit Service 72eb06
  va_list args;
Packit Service 72eb06
  va_start (args, format);
Packit Service 72eb06
Packit Service 72eb06
  result = _doprnt (format, args, stdout);
Packit Service 72eb06
  va_end (args);
Packit Service 72eb06
Packit Service 72eb06
  return result;
Packit Service 72eb06
}
Packit Service 72eb06
Packit Service 72eb06
int
Packit Service 72eb06
main (void)
Packit Service 72eb06
{
Packit Service 72eb06
  RESULT(checkit ("<%d>\n", 0x12345678));
Packit Service 72eb06
  RESULT(printf ("<%d>\n", 0x12345678));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%200d>\n", 5));
Packit Service 72eb06
  RESULT(printf ("<%200d>\n", 5));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%.300d>\n", 6));
Packit Service 72eb06
  RESULT(printf ("<%.300d>\n", 6));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%100.150d>\n", 7));
Packit Service 72eb06
  RESULT(printf ("<%100.150d>\n", 7));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%s>\n",
Packit Service 72eb06
		  "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
Packit Service 72eb06
777777777777777777333333333333366666666666622222222222777777777777733333"));
Packit Service 72eb06
  RESULT(printf ("<%s>\n",
Packit Service 72eb06
		 "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
Packit Service 72eb06
777777777777777777333333333333366666666666622222222222777777777777733333"));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%f><%0+#f>%s%d%s>\n",
Packit Service 72eb06
		  1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
Packit Service 72eb06
  RESULT(printf ("<%f><%0+#f>%s%d%s>\n",
Packit Service 72eb06
		 1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
Packit Service 72eb06
  RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
Packit Service 72eb06
  RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
Packit Service 72eb06
		  75, 75, 75, 75, 75, 75, 75));
Packit Service 72eb06
  RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
Packit Service 72eb06
		 75, 75, 75, 75, 75, 75, 75));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
Packit Service 72eb06
		  75, 75, 75, 75, 75, 75, 75));
Packit Service 72eb06
  RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
Packit Service 72eb06
		 75, 75, 75, 75, 75, 75, 75));
Packit Service 72eb06
Packit Service 72eb06
  RESULT(checkit ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
Packit Service 72eb06
  RESULT(printf ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
Packit Service 72eb06
Packit Service 72eb06
#if defined(__GNUC__) || defined (HAVE_LONG_LONG)
Packit Service 72eb06
  RESULT(checkit ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
Packit Service 72eb06
  RESULT(printf ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
Packit Service 72eb06
  RESULT(checkit ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
Packit Service 72eb06
  RESULT(printf ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
#if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
Packit Service 72eb06
  RESULT(checkit ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
Packit Service 72eb06
		  1.23456, 1.234567890123456789L, 1.23456));
Packit Service 72eb06
  RESULT(printf ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
Packit Service 72eb06
		 1.23456, 1.234567890123456789L, 1.23456));
Packit Service 72eb06
#endif
Packit Service 72eb06
Packit Service 72eb06
  return 0;
Packit Service 72eb06
}
Packit Service 72eb06
#endif /* TEST */