OSDN Git Service

* g++.dg/other/debug1.C: Fix typos.
[pf3gnuchains/gcc-fork.git] / gcc / doprint.c
1 /* Provide a version _doprnt in terms of fprintf.
2    Copyright (C) 1998, 1999, 2000, 2001   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 "system.h"
21 #undef _doprnt
22
23 #ifdef TEST /* Make sure to use the internal one.  */
24 #define _doprnt my_doprnt
25 #endif
26
27 #define COPY_VA_INT \
28   do { \
29          const int value = abs (va_arg (ap, int)); \
30          char buf[32]; \
31          ptr++; /* Go past the asterisk.  */ \
32          *sptr = '\0'; /* NULL terminate sptr.  */ \
33          sprintf(buf, "%d", value); \
34          strcat(sptr, buf); \
35          while (*sptr) sptr++; \
36      } while (0)
37
38 #define PRINT_CHAR(CHAR) \
39   do { \
40          putc(CHAR, stream); \
41          ptr++; \
42          total_printed++; \
43          continue; \
44      } while (0)
45
46 #define PRINT_TYPE(TYPE) \
47   do { \
48         int result; \
49         TYPE value = va_arg (ap, TYPE); \
50         *sptr++ = *ptr++; /* Copy the type specifier.  */ \
51         *sptr = '\0'; /* NULL terminate sptr.  */ \
52         result = fprintf(stream, specifier, value); \
53         if (result == -1) \
54           return -1; \
55         else \
56           { \
57             total_printed += result; \
58             continue; \
59           } \
60       } while (0)
61
62 int
63 _doprnt (format, ap, stream)
64   const char * format;
65   va_list ap;
66   FILE * stream;
67 {
68   const char * ptr = format;
69   char specifier[128];
70   int total_printed = 0;
71   
72   while (*ptr != '\0')
73     {
74       if (*ptr != '%') /* While we have regular characters, print them.  */
75         PRINT_CHAR(*ptr);
76       else /* We got a format specifier! */
77         {
78           char * sptr = specifier;
79           int wide_width = 0, short_width = 0;
80           
81           *sptr++ = *ptr++; /* Copy the % and move forward.  */
82
83           while (strchr ("-+ #0", *ptr)) /* Move past flags.  */
84             *sptr++ = *ptr++;
85
86           if (*ptr == '*')
87             COPY_VA_INT;
88           else
89             while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
90               *sptr++ = *ptr++;
91           
92           if (*ptr == '.')
93             {
94               *sptr++ = *ptr++; /* Copy and go past the period.  */
95               if (*ptr == '*')
96                 COPY_VA_INT;
97               else
98                 while (ISDIGIT(*ptr)) /* Handle explicit numeric value.  */
99                   *sptr++ = *ptr++;
100             }
101           while (strchr ("hlL", *ptr))
102             {
103               switch (*ptr)
104                 {
105                 case 'h':
106                   short_width = 1;
107                   break;
108                 case 'l':
109                   wide_width++;
110                   break;
111                 case 'L':
112                   wide_width = 2;
113                   break;
114                 default:
115                   abort();
116                 }
117               *sptr++ = *ptr++;
118             }
119
120           switch (*ptr)
121             {
122             case 'd':
123             case 'i':
124             case 'o':
125             case 'u':
126             case 'x':
127             case 'X':
128             case 'c':
129               {
130                 /* Short values are promoted to int, so just copy it
131                    as an int and trust the C library printf to cast it
132                    to the right width.  */
133                 if (short_width)
134                   PRINT_TYPE(int);
135                 else
136                   {
137                     switch (wide_width)
138                       {
139                       case 0:
140                         PRINT_TYPE(int);
141                         break;
142                       case 1:
143                         PRINT_TYPE(long);
144                         break;
145                       case 2:
146                       default:
147 #if defined(__GNUC__) || defined(HAVE_LONG_LONG)
148                         PRINT_TYPE(long long);
149 #else
150                         PRINT_TYPE(long); /* Fake it and hope for the best.  */
151 #endif
152                         break;
153                       } /* End of switch (wide_width) */
154                   } /* End of else statement */
155               } /* End of integer case */
156               break;
157             case 'f':
158             case 'e':
159             case 'E':
160             case 'g':
161             case 'G':
162               {
163                 if (wide_width == 0)
164                   PRINT_TYPE(double);
165                 else
166                   {
167 #if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
168                     PRINT_TYPE(long double);
169 #else
170                     PRINT_TYPE(double); /* Fake it and hope for the best.  */
171 #endif
172                   }
173               }
174               break;
175             case 's':
176               PRINT_TYPE(char *);
177               break;
178             case 'p':
179               PRINT_TYPE(void *);
180               break;
181             case '%':
182               PRINT_CHAR('%');
183               break;
184             default:
185               abort();
186             } /* End of switch (*ptr) */
187         } /* End of else statement */
188     }
189
190   return total_printed;
191 }
192
193 #ifdef TEST
194
195 #include <math.h>
196 #ifndef M_PI
197 #define M_PI (3.1415926535897932385)
198 #endif
199
200 #define RESULT(x) do \
201 { \
202     int i = (x); \
203     printf ("printed %d characters\n", i); \
204     fflush(stdin); \
205 } while (0)
206
207 static int checkit PARAMS ((const char * format, ...)) ATTRIBUTE_PRINTF_1;
208
209 static int
210 checkit VPARAMS ((const char* format, ...))
211 {
212   int result;
213   VA_OPEN (args, format);
214   VA_FIXEDARG (args, char *, format);
215
216   result = _doprnt (format, args, stdout);
217   VA_CLOSE (args);
218
219   return result;
220 }
221
222 int
223 main ()
224 {
225   RESULT(checkit ("<%d>\n", 0x12345678));
226   RESULT(printf ("<%d>\n", 0x12345678));
227
228   RESULT(checkit ("<%200d>\n", 5));
229   RESULT(printf ("<%200d>\n", 5));
230
231   RESULT(checkit ("<%.300d>\n", 6));
232   RESULT(printf ("<%.300d>\n", 6));
233
234   RESULT(checkit ("<%100.150d>\n", 7));
235   RESULT(printf ("<%100.150d>\n", 7));
236
237   RESULT(checkit ("<%s>\n",
238                   "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
239 777777777777777777333333333333366666666666622222222222777777777777733333"));
240   RESULT(printf ("<%s>\n",
241                  "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
242 777777777777777777333333333333366666666666622222222222777777777777733333"));
243
244   RESULT(checkit ("<%f><%0+#f>%s%d%s>\n",
245                   1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
246   RESULT(printf ("<%f><%0+#f>%s%d%s>\n",
247                  1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
248
249   RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
250   RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
251
252   RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
253   RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
254
255   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
256                   75, 75, 75, 75, 75, 75, 75));
257   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
258                  75, 75, 75, 75, 75, 75, 75));
259
260   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
261                   75, 75, 75, 75, 75, 75, 75));
262   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
263                  75, 75, 75, 75, 75, 75, 75));
264
265   RESULT(checkit ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
266   RESULT(printf ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
267
268 #if defined(__GNUC__) || defined (HAVE_LONG_LONG)
269   RESULT(checkit ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
270   RESULT(printf ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
271   RESULT(checkit ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
272   RESULT(printf ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
273 #endif
274
275 #if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
276   RESULT(checkit ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
277                   1.23456, 1.234567890123456789L, 1.23456));
278   RESULT(printf ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
279                  1.23456, 1.234567890123456789L, 1.23456));
280 #endif
281
282   return 0;
283 }
284 #endif /* TEST */