OSDN Git Service

Upgrade to AutoGen 5 Template
[pf3gnuchains/gcc-fork.git] / gcc / doprint.c
1 /* Provide a version _doprnt in terms of fprintf.
2    Copyright (C) 1998, 1999, 2000 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   va_list args;
213   int result;
214
215 #ifndef ANSI_PROTOTYPES
216   char *format;
217 #endif
218
219   VA_START (args, format);
220
221 #ifndef ANSI_PROTOTYPES
222   format = va_arg (args, char *);
223 #endif
224
225   result = _doprnt (format, args, stdout);
226   va_end(args);
227
228   return result;
229 }
230
231 int
232 main ()
233 {
234   RESULT(checkit ("<%d>\n", 0x12345678));
235   RESULT(printf ("<%d>\n", 0x12345678));
236
237   RESULT(checkit ("<%200d>\n", 5));
238   RESULT(printf ("<%200d>\n", 5));
239
240   RESULT(checkit ("<%.300d>\n", 6));
241   RESULT(printf ("<%.300d>\n", 6));
242
243   RESULT(checkit ("<%100.150d>\n", 7));
244   RESULT(printf ("<%100.150d>\n", 7));
245
246   RESULT(checkit ("<%s>\n",
247                   "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
248 777777777777777777333333333333366666666666622222222222777777777777733333"));
249   RESULT(printf ("<%s>\n",
250                  "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
251 777777777777777777333333333333366666666666622222222222777777777777733333"));
252
253   RESULT(checkit ("<%f><%0+#f>%s%d%s>\n",
254                   1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
255   RESULT(printf ("<%f><%0+#f>%s%d%s>\n",
256                  1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
257
258   RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
259   RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
260
261   RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
262   RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
263
264   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
265                   75, 75, 75, 75, 75, 75, 75));
266   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
267                  75, 75, 75, 75, 75, 75, 75));
268
269   RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
270                   75, 75, 75, 75, 75, 75, 75));
271   RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
272                  75, 75, 75, 75, 75, 75, 75));
273
274   RESULT(checkit ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
275   RESULT(printf ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
276
277 #if defined(__GNUC__) || defined (HAVE_LONG_LONG)
278   RESULT(checkit ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
279   RESULT(printf ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
280   RESULT(checkit ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
281   RESULT(printf ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
282 #endif
283
284 #if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
285   RESULT(checkit ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
286                   1.23456, 1.234567890123456789L, 1.23456));
287   RESULT(printf ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
288                  1.23456, 1.234567890123456789L, 1.23456));
289 #endif
290
291   return 0;
292 }
293 #endif /* TEST */