Home | History | Annotate | Line # | Download | only in libiberty
_doprnt.c revision 1.1.1.2.16.2
      1           1.1     mrg /* Provide a version of _doprnt in terms of fprintf.
      2  1.1.1.2.16.2  martin    Copyright (C) 1998-2018 Free Software Foundation, Inc.
      3           1.1     mrg    Contributed by Kaveh Ghazi  (ghazi (at) caip.rutgers.edu)  3/29/98
      4           1.1     mrg 
      5           1.1     mrg This program is free software; you can redistribute it and/or modify it
      6           1.1     mrg under the terms of the GNU General Public License as published by the
      7           1.1     mrg Free Software Foundation; either version 2, or (at your option) any
      8           1.1     mrg later version.
      9           1.1     mrg 
     10           1.1     mrg This program is distributed in the hope that it will be useful,
     11           1.1     mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     12           1.1     mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13           1.1     mrg GNU General Public License for more details.
     14           1.1     mrg 
     15           1.1     mrg You should have received a copy of the GNU General Public License
     16           1.1     mrg along with this program; if not, write to the Free Software
     17           1.1     mrg Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
     18           1.1     mrg 
     19           1.1     mrg #include "config.h"
     20           1.1     mrg #include "ansidecl.h"
     21           1.1     mrg #include "safe-ctype.h"
     22           1.1     mrg 
     23           1.1     mrg #include <stdio.h>
     24           1.1     mrg #include <stdarg.h>
     25           1.1     mrg #ifdef HAVE_STRING_H
     26           1.1     mrg #include <string.h>
     27           1.1     mrg #endif
     28           1.1     mrg #ifdef HAVE_STDLIB_H
     29           1.1     mrg #include <stdlib.h>
     30           1.1     mrg #endif
     31           1.1     mrg 
     32           1.1     mrg #undef _doprnt
     33           1.1     mrg 
     34           1.1     mrg #ifdef HAVE__DOPRNT
     35           1.1     mrg #define TEST
     36           1.1     mrg #endif
     37           1.1     mrg 
     38           1.1     mrg #ifdef TEST /* Make sure to use the internal one.  */
     39           1.1     mrg #define _doprnt my_doprnt
     40           1.1     mrg #endif
     41           1.1     mrg 
     42           1.1     mrg #define COPY_VA_INT \
     43           1.1     mrg   do { \
     44           1.1     mrg 	 const int value = abs (va_arg (ap, int)); \
     45           1.1     mrg 	 char buf[32]; \
     46           1.1     mrg 	 ptr++; /* Go past the asterisk.  */ \
     47           1.1     mrg 	 *sptr = '\0'; /* NULL terminate sptr.  */ \
     48           1.1     mrg 	 sprintf(buf, "%d", value); \
     49           1.1     mrg 	 strcat(sptr, buf); \
     50           1.1     mrg 	 while (*sptr) sptr++; \
     51           1.1     mrg      } while (0)
     52           1.1     mrg 
     53           1.1     mrg #define PRINT_CHAR(CHAR) \
     54           1.1     mrg   do { \
     55           1.1     mrg 	 putc(CHAR, stream); \
     56           1.1     mrg 	 ptr++; \
     57           1.1     mrg 	 total_printed++; \
     58           1.1     mrg 	 continue; \
     59           1.1     mrg      } while (0)
     60           1.1     mrg 
     61           1.1     mrg #define PRINT_TYPE(TYPE) \
     62           1.1     mrg   do { \
     63           1.1     mrg 	int result; \
     64           1.1     mrg 	TYPE value = va_arg (ap, TYPE); \
     65           1.1     mrg 	*sptr++ = *ptr++; /* Copy the type specifier.  */ \
     66           1.1     mrg 	*sptr = '\0'; /* NULL terminate sptr.  */ \
     67           1.1     mrg 	result = fprintf(stream, specifier, value); \
     68           1.1     mrg 	if (result == -1) \
     69           1.1     mrg 	  return -1; \
     70           1.1     mrg 	else \
     71           1.1     mrg 	  { \
     72           1.1     mrg 	    total_printed += result; \
     73           1.1     mrg 	    continue; \
     74           1.1     mrg 	  } \
     75           1.1     mrg       } while (0)
     76           1.1     mrg 
     77           1.1     mrg int
     78           1.1     mrg _doprnt (const char *format, va_list ap, FILE *stream)
     79           1.1     mrg {
     80           1.1     mrg   const char * ptr = format;
     81           1.1     mrg   char specifier[128];
     82           1.1     mrg   int total_printed = 0;
     83           1.1     mrg 
     84           1.1     mrg   while (*ptr != '\0')
     85           1.1     mrg     {
     86           1.1     mrg       if (*ptr != '%') /* While we have regular characters, print them.  */
     87           1.1     mrg 	PRINT_CHAR(*ptr);
     88           1.1     mrg       else /* We got a format specifier! */
     89           1.1     mrg 	{
     90           1.1     mrg 	  char * sptr = specifier;
     91           1.1     mrg 	  int wide_width = 0, short_width = 0;
     92           1.1     mrg 
     93           1.1     mrg 	  *sptr++ = *ptr++; /* Copy the % and move forward.  */
     94           1.1     mrg 
     95           1.1     mrg 	  while (strchr ("-+ #0", *ptr)) /* Move past flags.  */
     96           1.1     mrg 	    *sptr++ = *ptr++;
     97           1.1     mrg 
     98           1.1     mrg 	  if (*ptr == '*')
     99           1.1     mrg 	    COPY_VA_INT;
    100           1.1     mrg 	  else
    101           1.1     mrg 	    while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
    102           1.1     mrg 	      *sptr++ = *ptr++;
    103           1.1     mrg 
    104           1.1     mrg 	  if (*ptr == '.')
    105           1.1     mrg 	    {
    106           1.1     mrg 	      *sptr++ = *ptr++; /* Copy and go past the period.  */
    107           1.1     mrg 	      if (*ptr == '*')
    108           1.1     mrg 		COPY_VA_INT;
    109           1.1     mrg 	      else
    110           1.1     mrg 		while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
    111           1.1     mrg 		  *sptr++ = *ptr++;
    112           1.1     mrg 	    }
    113           1.1     mrg 	  while (strchr ("hlL", *ptr))
    114           1.1     mrg 	    {
    115           1.1     mrg 	      switch (*ptr)
    116           1.1     mrg 		{
    117           1.1     mrg 		case 'h':
    118           1.1     mrg 		  short_width = 1;
    119           1.1     mrg 		  break;
    120           1.1     mrg 		case 'l':
    121           1.1     mrg 		  wide_width++;
    122           1.1     mrg 		  break;
    123           1.1     mrg 		case 'L':
    124           1.1     mrg 		  wide_width = 2;
    125           1.1     mrg 		  break;
    126           1.1     mrg 		default:
    127           1.1     mrg 		  abort();
    128           1.1     mrg 		}
    129           1.1     mrg 	      *sptr++ = *ptr++;
    130           1.1     mrg 	    }
    131           1.1     mrg 
    132           1.1     mrg 	  switch (*ptr)
    133           1.1     mrg 	    {
    134           1.1     mrg 	    case 'd':
    135           1.1     mrg 	    case 'i':
    136           1.1     mrg 	    case 'o':
    137           1.1     mrg 	    case 'u':
    138           1.1     mrg 	    case 'x':
    139           1.1     mrg 	    case 'X':
    140           1.1     mrg 	    case 'c':
    141           1.1     mrg 	      {
    142           1.1     mrg 		/* Short values are promoted to int, so just copy it
    143           1.1     mrg                    as an int and trust the C library printf to cast it
    144           1.1     mrg                    to the right width.  */
    145           1.1     mrg 		if (short_width)
    146           1.1     mrg 		  PRINT_TYPE(int);
    147           1.1     mrg 		else
    148           1.1     mrg 		  {
    149           1.1     mrg 		    switch (wide_width)
    150           1.1     mrg 		      {
    151           1.1     mrg 		      case 0:
    152           1.1     mrg 			PRINT_TYPE(int);
    153           1.1     mrg 			break;
    154           1.1     mrg 		      case 1:
    155           1.1     mrg 			PRINT_TYPE(long);
    156           1.1     mrg 			break;
    157           1.1     mrg 		      case 2:
    158           1.1     mrg 		      default:
    159           1.1     mrg #if defined(__GNUC__) || defined(HAVE_LONG_LONG)
    160           1.1     mrg 			PRINT_TYPE(long long);
    161           1.1     mrg #else
    162           1.1     mrg 			PRINT_TYPE(long); /* Fake it and hope for the best.  */
    163           1.1     mrg #endif
    164           1.1     mrg 			break;
    165           1.1     mrg 		      } /* End of switch (wide_width) */
    166           1.1     mrg 		  } /* End of else statement */
    167           1.1     mrg 	      } /* End of integer case */
    168           1.1     mrg 	      break;
    169           1.1     mrg 	    case 'f':
    170           1.1     mrg 	    case 'e':
    171           1.1     mrg 	    case 'E':
    172           1.1     mrg 	    case 'g':
    173           1.1     mrg 	    case 'G':
    174           1.1     mrg 	      {
    175           1.1     mrg 		if (wide_width == 0)
    176           1.1     mrg 		  PRINT_TYPE(double);
    177           1.1     mrg 		else
    178           1.1     mrg 		  {
    179           1.1     mrg #if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
    180           1.1     mrg 		    PRINT_TYPE(long double);
    181           1.1     mrg #else
    182           1.1     mrg 		    PRINT_TYPE(double); /* Fake it and hope for the best.  */
    183           1.1     mrg #endif
    184           1.1     mrg 		  }
    185           1.1     mrg 	      }
    186           1.1     mrg 	      break;
    187           1.1     mrg 	    case 's':
    188           1.1     mrg 	      PRINT_TYPE(char *);
    189           1.1     mrg 	      break;
    190           1.1     mrg 	    case 'p':
    191           1.1     mrg 	      PRINT_TYPE(void *);
    192           1.1     mrg 	      break;
    193           1.1     mrg 	    case '%':
    194           1.1     mrg 	      PRINT_CHAR('%');
    195           1.1     mrg 	      break;
    196           1.1     mrg 	    default:
    197           1.1     mrg 	      abort();
    198           1.1     mrg 	    } /* End of switch (*ptr) */
    199           1.1     mrg 	} /* End of else statement */
    200           1.1     mrg     }
    201           1.1     mrg 
    202           1.1     mrg   return total_printed;
    203           1.1     mrg }
    204           1.1     mrg 
    205           1.1     mrg #ifdef TEST
    206           1.1     mrg 
    207           1.1     mrg #include <math.h>
    208           1.1     mrg #ifndef M_PI
    209           1.1     mrg #define M_PI (3.1415926535897932385)
    210           1.1     mrg #endif
    211           1.1     mrg 
    212           1.1     mrg #define RESULT(x) do \
    213           1.1     mrg { \
    214           1.1     mrg     int i = (x); \
    215           1.1     mrg     printf ("printed %d characters\n", i); \
    216           1.1     mrg     fflush(stdin); \
    217           1.1     mrg } while (0)
    218           1.1     mrg 
    219           1.1     mrg static int checkit (const char * format, ...) ATTRIBUTE_PRINTF_1;
    220           1.1     mrg 
    221           1.1     mrg static int
    222           1.1     mrg checkit (const char* format, ...)
    223           1.1     mrg {
    224           1.1     mrg   int result;
    225       1.1.1.2     mrg   va_list args;
    226       1.1.1.2     mrg   va_start (args, format);
    227           1.1     mrg 
    228           1.1     mrg   result = _doprnt (format, args, stdout);
    229       1.1.1.2     mrg   va_end (args);
    230           1.1     mrg 
    231           1.1     mrg   return result;
    232           1.1     mrg }
    233           1.1     mrg 
    234           1.1     mrg int
    235           1.1     mrg main (void)
    236           1.1     mrg {
    237           1.1     mrg   RESULT(checkit ("<%d>\n", 0x12345678));
    238           1.1     mrg   RESULT(printf ("<%d>\n", 0x12345678));
    239           1.1     mrg 
    240           1.1     mrg   RESULT(checkit ("<%200d>\n", 5));
    241           1.1     mrg   RESULT(printf ("<%200d>\n", 5));
    242           1.1     mrg 
    243           1.1     mrg   RESULT(checkit ("<%.300d>\n", 6));
    244           1.1     mrg   RESULT(printf ("<%.300d>\n", 6));
    245           1.1     mrg 
    246           1.1     mrg   RESULT(checkit ("<%100.150d>\n", 7));
    247           1.1     mrg   RESULT(printf ("<%100.150d>\n", 7));
    248           1.1     mrg 
    249           1.1     mrg   RESULT(checkit ("<%s>\n",
    250           1.1     mrg 		  "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
    251           1.1     mrg 777777777777777777333333333333366666666666622222222222777777777777733333"));
    252           1.1     mrg   RESULT(printf ("<%s>\n",
    253           1.1     mrg 		 "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
    254           1.1     mrg 777777777777777777333333333333366666666666622222222222777777777777733333"));
    255           1.1     mrg 
    256           1.1     mrg   RESULT(checkit ("<%f><%0+#f>%s%d%s>\n",
    257           1.1     mrg 		  1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
    258           1.1     mrg   RESULT(printf ("<%f><%0+#f>%s%d%s>\n",
    259           1.1     mrg 		 1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
    260           1.1     mrg 
    261           1.1     mrg   RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
    262           1.1     mrg   RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
    263           1.1     mrg 
    264           1.1     mrg   RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
    265           1.1     mrg   RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
    266           1.1     mrg 
    267           1.1     mrg   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
    268           1.1     mrg 		  75, 75, 75, 75, 75, 75, 75));
    269           1.1     mrg   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
    270           1.1     mrg 		 75, 75, 75, 75, 75, 75, 75));
    271           1.1     mrg 
    272           1.1     mrg   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
    273           1.1     mrg 		  75, 75, 75, 75, 75, 75, 75));
    274           1.1     mrg   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
    275           1.1     mrg 		 75, 75, 75, 75, 75, 75, 75));
    276           1.1     mrg 
    277           1.1     mrg   RESULT(checkit ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
    278           1.1     mrg   RESULT(printf ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
    279           1.1     mrg 
    280           1.1     mrg #if defined(__GNUC__) || defined (HAVE_LONG_LONG)
    281           1.1     mrg   RESULT(checkit ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
    282           1.1     mrg   RESULT(printf ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
    283           1.1     mrg   RESULT(checkit ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
    284           1.1     mrg   RESULT(printf ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
    285           1.1     mrg #endif
    286           1.1     mrg 
    287           1.1     mrg #if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
    288           1.1     mrg   RESULT(checkit ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
    289           1.1     mrg 		  1.23456, 1.234567890123456789L, 1.23456));
    290           1.1     mrg   RESULT(printf ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
    291           1.1     mrg 		 1.23456, 1.234567890123456789L, 1.23456));
    292           1.1     mrg #endif
    293           1.1     mrg 
    294           1.1     mrg   return 0;
    295           1.1     mrg }
    296           1.1     mrg #endif /* TEST */
    297