~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/libiberty/_doprnt.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

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