OSDN Git Service

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