public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* egcs, REVIEW FOR SUBMISSION, vfprintf.c ...
@ 1998-04-02 11:32 Kaveh R. Ghazi
  1998-04-04 11:01 ` Eric Dana
  1998-04-05 21:29 ` Jeffrey A Law
  0 siblings, 2 replies; 3+ messages in thread
From: Kaveh R. Ghazi @ 1998-04-02 11:32 UTC (permalink / raw)
  To: egcs; +Cc: ghazi

	Here is my first cut at a vfprintf.c for platforms with
stdarg/varargs but no vfprintf() function.  It fakes things by parsing
the format specifier string, pulling args and printing using fprintf.
I hacked it up using parts of libiberty/vasprintf.c and some RTFM.

	Its currently meant to live in the gcc directory of egcs since
I'm not ready to tackle libiberty.  But it could easily live in the
libiberty directory with only a couple of changes in whcih include
files it gets.

	I'd like it if people more familiar with the exact conformant
behavior of vfprintf() would look at it to make sure I got it right.
I'm especially unsure of the 'h' flag's meaning.

	You can use -DTEST to do build a runnable self testing
program.  I compiled it like this out of the gcc dir:

 > stage2/xgcc -DTEST -Bstage2/ -DMAIN -DIN_GCC -DSVR4 -W -Wall -O2 -g
 > 	-DHAVE_CONFIG_H -I. -I. -I./config vfprintf.c

		--Kaveh

-----cut-here-----
/* Provide a version vfprintf in terms of fprintf.
   By Kaveh Ghazi  (ghazi@caip.rutgers.edu)  3/29/98
   Copyright (C) 1998 Free Software Foundation, Inc.
 */

#include "config.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "system.h"
#include "gansidecl.h"

#ifdef TEST /* Make sure to use the internal one. */
#define vfprintf my_vfprintf
#endif

#define COPY_VA_INT \
  do { \
	 const int value = abs (va_arg (ap, int)); \
	 char buf[32]; \
	 ptr++; /* Go past the asterisk. */ \
	 *sptr = '\0'; /* NULL terminate sptr. */ \
	 sprintf(buf, "%d", value); \
	 strcat(sptr, buf); \
	 while (*sptr) sptr++; \
     } while (0)

#define PRINT_CHAR(CHAR) \
  do { \
	 putc(CHAR, stream); \
	 ptr++; \
	 total_printed++; \
	 continue; \
     } while (0)

#define PRINT_TYPE(TYPE) \
  do { \
	int result; \
	TYPE value = va_arg (ap, TYPE); \
	*sptr++ = *ptr++; /* Copy the type specifier. */ \
	*sptr = '\0'; /* NULL terminate sptr. */ \
	result = fprintf(stream, specifier, value); \
	if (result == -1) \
	  return -1; \
	else \
	  { \
	    total_printed += result; \
	    continue; \
	  } \
      } while (0)

int
vfprintf (stream, format, ap)
  FILE * stream;
  const char * format;
  va_list ap;
{
#ifdef HAVE_DOPRNT
  return _doprnt (format, ap, stream);
#else /* ! HAVE_DOPRNT */
   
  const char * ptr = format;
  char specifier[128];
  int total_printed = 0;
  
  while (*ptr != '\0')
    {
      if (*ptr != '%') /* While we have regular characters, print them. */
	PRINT_CHAR(*ptr);
      else /* We got a format specifier! */
	{
	  char * sptr = specifier;
	  int long_width = 0, short_width = 0, double_width = 0;
	  
	  *sptr++ = *ptr++; /* Copy the % and move forward. */

	  while (strchr ("-+ #0", *ptr)) /* Move past flags. */
	    *sptr++ = *ptr++;

	  if (*ptr == '*')
	    COPY_VA_INT;
	  else
	    while (isdigit(*ptr)) /* Handle explicit numeric value. */
	      *sptr++ = *ptr++;
	  
	  if (*ptr == '.')
	    {
	      *sptr++ = *ptr++; /* Copy and go past the period. */
	      if (*ptr == '*')
		COPY_VA_INT;
	      else
		while (isdigit(*ptr)) /* Handle explicit numeric value. */
		  *sptr++ = *ptr++;
	    }
	  while (strchr ("hlL", *ptr))
	    {
	      switch (*ptr)
		{
		case 'h':
		  short_width = 1;
		  break;
		case 'l':
		  long_width++;
		  break;
		case 'L':
		  double_width = 1;
		  break;
		default:
		  abort();
		}
	      *sptr++ = *ptr++;
	    }

	  switch (*ptr)
	    {
	    case 'd':
	    case 'i':
	    case 'o':
	    case 'u':
	    case 'x':
	    case 'X':
	    case 'c':
	      {
		if (short_width)
		  PRINT_TYPE(short);
		else
		  {
		    switch (long_width)
		      {
		      case 0:
			PRINT_TYPE(int);
			break;
		      case 1:
			PRINT_TYPE(long);
			break;
		      case 2:
#if defined(__GNUC__) || defined(HAVE_LONG_LONG)
			PRINT_TYPE(long long);
#else
			PRINT_TYPE(long); /* Fake it and hope for the best. */
#endif
			break;
		      default:
			abort();
		      } /* End of switch (int_width) */
		  } /* End of else statement */
	      } /* End of integer case */
	      break;
	    case 'f':
	    case 'e':
	    case 'E':
	    case 'g':
	    case 'G':
	      {
		if (double_width == 0)
		  PRINT_TYPE(double);
		else
		  {
#if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
		    PRINT_TYPE(long double);
#else
		    PRINT_TYPE(double); /* Fake it and hope for the best. */
#endif
		  }
	      }
	      break;
	    case 's':
	      PRINT_TYPE(char *);
	      break;
	    case 'p':
	      PRINT_TYPE(void *);
	      break;
	    case '%':
	      PRINT_CHAR('%');
	      break;
	    default:
	      abort();
	    } /* End of switch (*ptr) */
	} /* End of else statement */
    }

    return total_printed;
#endif /* HAVE_DOPRNT */
}

#ifdef TEST

#include <math.h>
#ifndef M_PI
#define M_PI (3.1415926535897932385)
#endif

#define RESULT(x) printf ("printed %d characters\n", (x));

#ifndef PRINTF_ATTRIBUTE
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
#  define PRINTF_ATTRIBUTE(m, n)
# else
#  define PRINTF_ATTRIBUTE(m, n) __attribute__ ((format (__printf__, m, n)))
# endif
#endif

#define PRINTF_ATTRIBUTE_1 PRINTF_ATTRIBUTE(1, 2)
#define PRINTF_ATTRIBUTE_2 PRINTF_ATTRIBUTE(2, 3)
#define PRINTF_ATTRIBUTE_3 PRINTF_ATTRIBUTE(3, 4)

static int checkit PVPROTO ((const char * format, ...)) PRINTF_ATTRIBUTE_1;

static int
checkit VPROTO ((const char* format, ...))
{
  va_list args;
  int result;

#ifndef __STDC__
  char *format;
#endif

  VA_START (args, format);

#ifndef __STDC__
  format = va_arg (args, char *);
#endif

  result = vfprintf(stdout, format, args);
  va_end(args);

  return result;
}

int
main ()
{
  RESULT(checkit ("<%d>\n", 0x12345678));
  RESULT(printf ("<%d>\n", 0x12345678));

  RESULT(checkit ("<%200d>\n", 5));
  RESULT(printf ("<%200d>\n", 5));

  RESULT(checkit ("<%.300d>\n", 6));
  RESULT(printf ("<%.300d>\n", 6));

  RESULT(checkit ("<%100.150d>\n", 7));
  RESULT(printf ("<%100.150d>\n", 7));

  RESULT(checkit ("<%s>\n",
		  "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
777777777777777777333333333333366666666666622222222222777777777777733333"));
  RESULT(printf ("<%s>\n",
		 "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
777777777777777777333333333333366666666666622222222222777777777777733333"));

  RESULT(checkit ("<%f%s%d%s>\n",
		  1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
  RESULT(printf ("<%f%s%d%s>\n",
		 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));

  RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
  RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));

  RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
  RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));

  RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
		  75, 75, 75, 75, 75, 75, 75));
  RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
		 75, 75, 75, 75, 75, 75, 75));

  RESULT(checkit ("<%d><%ld><%hd><%d>\n", 123, (long)234, (short)345, 456));
  RESULT(printf ("<%d><%ld><%hd><%d>\n", 123, (long)234, (short)345, 456));

#if defined(__GNUC__) || defined (HAVE_LONG_LONG)
  RESULT(checkit ("<%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
  RESULT(printf ("<%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
#endif

#if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
  RESULT(checkit ("<%.20f><%.20Lf><%.20f>\n",
		  1.23456, 1.234567890123456789L, 1.23456));
  RESULT(printf ("<%.20f><%.20Lf><%.20f>\n",
		 1.23456, 1.234567890123456789L, 1.23456));
#endif

  return 0;
}
#endif /* TEST */

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: egcs, REVIEW FOR SUBMISSION, vfprintf.c ...
  1998-04-02 11:32 egcs, REVIEW FOR SUBMISSION, vfprintf.c Kaveh R. Ghazi
@ 1998-04-04 11:01 ` Eric Dana
  1998-04-05 21:29 ` Jeffrey A Law
  1 sibling, 0 replies; 3+ messages in thread
From: Eric Dana @ 1998-04-04 11:01 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: egcs, ghazi

Kaveh,

   Here is a small patch to allow 'll' prefixes stand for double
width (ex: %lld). I've also made a portable _doprint()/_doscan()
replacement for many UNIX's (original based on netbsd and freebsd
work). Your welcome to look at the code.

Eric Dana
Principal Software Engineer
BMC Inc.

-------------------------cut here-------------
*** vfprintf.c.orig	Fri Apr  3 09:52:05 1998
--- vfprintf.c	Fri Apr  3 09:55:26 1998
***************
*** 102,108 ****
  		  short_width = 1;
  		  break;
  		case 'l':
! 		  long_width++;
  		  break;
  		case 'L':
  		  double_width = 1;
--- 102,114 ----
  		  short_width = 1;
  		  break;
  		case 'l':
! 		  if (*(ptr+1) == 'l')     /* test for 'll' == double width */
! 		    {
! 		       double_width = 1;
! 		       ptr++;
! 		    }
! 		  else
! 		    long_width++;
  		  break;
  		case 'L':
  		  double_width = 1;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: egcs, REVIEW FOR SUBMISSION, vfprintf.c ...
  1998-04-02 11:32 egcs, REVIEW FOR SUBMISSION, vfprintf.c Kaveh R. Ghazi
  1998-04-04 11:01 ` Eric Dana
@ 1998-04-05 21:29 ` Jeffrey A Law
  1 sibling, 0 replies; 3+ messages in thread
From: Jeffrey A Law @ 1998-04-05 21:29 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: egcs, wilson

  In message < 199803312140.QAA28085@caip.rutgers.edu >you write:
  > 	Here is my first cut at a vfprintf.c for platforms with
  > stdarg/varargs but no vfprintf() function.  It fakes things by parsing
  > the format specifier string, pulling args and printing using fprintf.
  > I hacked it up using parts of libiberty/vasprintf.c and some RTFM.
  > 
  > 	Its currently meant to live in the gcc directory of egcs since
  > I'm not ready to tackle libiberty.  But it could easily live in the
  > libiberty directory with only a couple of changes in whcih include
  > files it gets.
  > 
  > 	I'd like it if people more familiar with the exact conformant
  > behavior of vfprintf() would look at it to make sure I got it right.
  > I'm especially unsure of the 'h' flag's meaning.
Wow.

Probably more complete than I would have done since systems without
vfprintf are diminishing regularly.

Even with the 'h' issue pending, I'd say go ahead and cobble up the
changes so that it can be installed -- it's a lot better than the
stuff we're currently using.

I suspect this will be linked into both the compiler (gcc, cpp,
cc1, etc) & the generator programs (gen*).  If so, you need
to handle it like rtl.o/HOST_RTL.





jeff

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1998-04-05 21:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-04-02 11:32 egcs, REVIEW FOR SUBMISSION, vfprintf.c Kaveh R. Ghazi
1998-04-04 11:01 ` Eric Dana
1998-04-05 21:29 ` Jeffrey A Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).