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