00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020 #include "ansidecl.h"
00021 #include "safe-ctype.h"
00022
00023 #include <stdio.h>
00024 #ifdef ANSI_PROTOTYPES
00025 #include <stdarg.h>
00026 #else
00027 #include <varargs.h>
00028 #endif
00029 #ifdef HAVE_STRING_H
00030 #include <string.h>
00031 #endif
00032 #ifdef HAVE_STDLIB_H
00033 #include <stdlib.h>
00034 #endif
00035
00036 #undef _doprnt
00037
00038 #ifdef HAVE__DOPRNT
00039 #define TEST
00040 #endif
00041
00042 #ifdef TEST
00043 #define _doprnt my_doprnt
00044 #endif
00045
00046 #define COPY_VA_INT \
00047 do { \
00048 const int value = abs (va_arg (ap, int)); \
00049 char buf[32]; \
00050 ptr++; \
00051 *sptr = '\0'; \
00052 sprintf(buf, "%d", value); \
00053 strcat(sptr, buf); \
00054 while (*sptr) sptr++; \
00055 } while (0)
00056
00057 #define PRINT_CHAR(CHAR) \
00058 do { \
00059 putc(CHAR, stream); \
00060 ptr++; \
00061 total_printed++; \
00062 continue; \
00063 } while (0)
00064
00065 #define PRINT_TYPE(TYPE) \
00066 do { \
00067 int result; \
00068 TYPE value = va_arg (ap, TYPE); \
00069 *sptr++ = *ptr++; \
00070 *sptr = '\0'; \
00071 result = fprintf(stream, specifier, value); \
00072 if (result == -1) \
00073 return -1; \
00074 else \
00075 { \
00076 total_printed += result; \
00077 continue; \
00078 } \
00079 } while (0)
00080
00081 int
00082 _doprnt (format, ap, stream)
00083 const char * format;
00084 va_list ap;
00085 FILE * stream;
00086 {
00087 const char * ptr = format;
00088 char specifier[128];
00089 int total_printed = 0;
00090
00091 while (*ptr != '\0')
00092 {
00093 if (*ptr != '%')
00094 PRINT_CHAR(*ptr);
00095 else
00096 {
00097 char * sptr = specifier;
00098 int wide_width = 0, short_width = 0;
00099
00100 *sptr++ = *ptr++;
00101
00102 while (strchr ("-+ #0", *ptr))
00103 *sptr++ = *ptr++;
00104
00105 if (*ptr == '*')
00106 COPY_VA_INT;
00107 else
00108 while (ISDIGIT(*ptr))
00109 *sptr++ = *ptr++;
00110
00111 if (*ptr == '.')
00112 {
00113 *sptr++ = *ptr++;
00114 if (*ptr == '*')
00115 COPY_VA_INT;
00116 else
00117 while (ISDIGIT(*ptr))
00118 *sptr++ = *ptr++;
00119 }
00120 while (strchr ("hlL", *ptr))
00121 {
00122 switch (*ptr)
00123 {
00124 case 'h':
00125 short_width = 1;
00126 break;
00127 case 'l':
00128 wide_width++;
00129 break;
00130 case 'L':
00131 wide_width = 2;
00132 break;
00133 default:
00134 abort();
00135 }
00136 *sptr++ = *ptr++;
00137 }
00138
00139 switch (*ptr)
00140 {
00141 case 'd':
00142 case 'i':
00143 case 'o':
00144 case 'u':
00145 case 'x':
00146 case 'X':
00147 case 'c':
00148 {
00149
00150
00151
00152 if (short_width)
00153 PRINT_TYPE(int);
00154 else
00155 {
00156 switch (wide_width)
00157 {
00158 case 0:
00159 PRINT_TYPE(int);
00160 break;
00161 case 1:
00162 PRINT_TYPE(long);
00163 break;
00164 case 2:
00165 default:
00166 #if defined(__GNUC__) || defined(HAVE_LONG_LONG)
00167 PRINT_TYPE(long long);
00168 #else
00169 PRINT_TYPE(long);
00170 #endif
00171 break;
00172 }
00173 }
00174 }
00175 break;
00176 case 'f':
00177 case 'e':
00178 case 'E':
00179 case 'g':
00180 case 'G':
00181 {
00182 if (wide_width == 0)
00183 PRINT_TYPE(double);
00184 else
00185 {
00186 #if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
00187 PRINT_TYPE(long double);
00188 #else
00189 PRINT_TYPE(double);
00190 #endif
00191 }
00192 }
00193 break;
00194 case 's':
00195 PRINT_TYPE(char *);
00196 break;
00197 case 'p':
00198 PRINT_TYPE(void *);
00199 break;
00200 case '%':
00201 PRINT_CHAR('%');
00202 break;
00203 default:
00204 abort();
00205 }
00206 }
00207 }
00208
00209 return total_printed;
00210 }
00211
00212 #ifdef TEST
00213
00214 #include <math.h>
00215 #ifndef M_PI
00216 #define M_PI (3.1415926535897932385)
00217 #endif
00218
00219 #define RESULT(x) do \
00220 { \
00221 int i = (x); \
00222 printf ("printed %d characters\n", i); \
00223 fflush(stdin); \
00224 } while (0)
00225
00226 static int checkit PARAMS ((const char * format, ...)) ATTRIBUTE_PRINTF_1;
00227
00228 static int
00229 checkit VPARAMS ((const char* format, ...))
00230 {
00231 int result;
00232 VA_OPEN (args, format);
00233 VA_FIXEDARG (args, char *, format);
00234
00235 result = _doprnt (format, args, stdout);
00236 VA_CLOSE (args);
00237
00238 return result;
00239 }
00240
00241 int
00242 main ()
00243 {
00244 RESULT(checkit ("<%d>\n", 0x12345678));
00245 RESULT(printf ("<%d>\n", 0x12345678));
00246
00247 RESULT(checkit ("<%200d>\n", 5));
00248 RESULT(printf ("<%200d>\n", 5));
00249
00250 RESULT(checkit ("<%.300d>\n", 6));
00251 RESULT(printf ("<%.300d>\n", 6));
00252
00253 RESULT(checkit ("<%100.150d>\n", 7));
00254 RESULT(printf ("<%100.150d>\n", 7));
00255
00256 RESULT(checkit ("<%s>\n",
00257 "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
00258 777777777777777777333333333333366666666666622222222222777777777777733333"));
00259 RESULT(printf ("<%s>\n",
00260 "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
00261 777777777777777777333333333333366666666666622222222222777777777777733333"));
00262
00263 RESULT(checkit ("<%f><%0+#f>%s%d%s>\n",
00264 1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
00265 RESULT(printf ("<%f><%0+#f>%s%d%s>\n",
00266 1.0, 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"));
00267
00268 RESULT(checkit ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
00269 RESULT(printf ("<%4f><%.4f><%%><%4.4f>\n", M_PI, M_PI, M_PI));
00270
00271 RESULT(checkit ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
00272 RESULT(printf ("<%*f><%.*f><%%><%*.*f>\n", 3, M_PI, 3, M_PI, 3, 3, M_PI));
00273
00274 RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
00275 75, 75, 75, 75, 75, 75, 75));
00276 RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
00277 75, 75, 75, 75, 75, 75, 75));
00278
00279 RESULT(checkit ("<%d><%i><%o><%u><%x><%X><%c>\n",
00280 75, 75, 75, 75, 75, 75, 75));
00281 RESULT(printf ("<%d><%i><%o><%u><%x><%X><%c>\n",
00282 75, 75, 75, 75, 75, 75, 75));
00283
00284 RESULT(checkit ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
00285 RESULT(printf ("Testing (hd) short: <%d><%ld><%hd><%hd><%d>\n", 123, (long)234, 345, 123456789, 456));
00286
00287 #if defined(__GNUC__) || defined (HAVE_LONG_LONG)
00288 RESULT(checkit ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
00289 RESULT(printf ("Testing (lld) long long: <%d><%lld><%d>\n", 123, 234234234234234234LL, 345));
00290 RESULT(checkit ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
00291 RESULT(printf ("Testing (Ld) long long: <%d><%Ld><%d>\n", 123, 234234234234234234LL, 345));
00292 #endif
00293
00294 #if defined(__GNUC__) || defined (HAVE_LONG_DOUBLE)
00295 RESULT(checkit ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
00296 1.23456, 1.234567890123456789L, 1.23456));
00297 RESULT(printf ("Testing (Lf) long double: <%.20f><%.20Lf><%0+#.20f>\n",
00298 1.23456, 1.234567890123456789L, 1.23456));
00299 #endif
00300
00301 return 0;
00302 }
00303 #endif