00001
00002
00003
00004
00005
00006 #include <ctype.h>
00007 #include <stdio.h>
00008 #include <stdarg.h>
00009 #include <string.h>
00010 #include "loc_incl.h"
00011
00012
00013 static const char *
00014 gnum(register const char *f, int *ip, va_list *app)
00015 {
00016 register int i, c;
00017
00018 if (*f == '*') {
00019 *ip = va_arg((*app), int);
00020 f++;
00021 } else {
00022 i = 0;
00023 while ((c = *f - '0') >= 0 && c <= 9) {
00024 i = i*10 + c;
00025 f++;
00026 }
00027 *ip = i;
00028 }
00029 return f;
00030 }
00031
00032 #if _EM_WSIZE == _EM_PSIZE
00033 #define set_pointer(flags)
00034 #elif _EM_LSIZE == _EM_PSIZE
00035 #define set_pointer(flags) (flags |= FL_LONG)
00036 #else
00037 #error garbage pointer size
00038 #define set_pointer(flags)
00039 #endif
00040
00041
00042 static char *
00043 o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
00044 {
00045 long signed_val;
00046 unsigned long unsigned_val;
00047 char *old_s = s;
00048 int base;
00049
00050 switch (flags & (FL_SHORT | FL_LONG)) {
00051 case FL_SHORT:
00052 if (is_signed) {
00053 signed_val = (short) va_arg(*ap, int);
00054 } else {
00055 unsigned_val = (unsigned short) va_arg(*ap, unsigned);
00056 }
00057 break;
00058 case FL_LONG:
00059 if (is_signed) {
00060 signed_val = va_arg(*ap, long);
00061 } else {
00062 unsigned_val = va_arg(*ap, unsigned long);
00063 }
00064 break;
00065 default:
00066 if (is_signed) {
00067 signed_val = va_arg(*ap, int);
00068 } else {
00069 unsigned_val = va_arg(*ap, unsigned int);
00070 }
00071 break;
00072 }
00073
00074 if (is_signed) {
00075 if (signed_val < 0) {
00076 *s++ = '-';
00077 signed_val = -signed_val;
00078 } else if (flags & FL_SIGN) *s++ = '+';
00079 else if (flags & FL_SPACE) *s++ = ' ';
00080 unsigned_val = signed_val;
00081 }
00082 if ((flags & FL_ALT) && (c == 'o')) *s++ = '0';
00083 if (!unsigned_val) {
00084 if (!precision)
00085 return s;
00086 } else if (((flags & FL_ALT) && (c == 'x' || c == 'X'))
00087 || c == 'p') {
00088 *s++ = '0';
00089 *s++ = (c == 'X' ? 'X' : 'x');
00090 }
00091
00092 switch (c) {
00093 case 'b': base = 2; break;
00094 case 'o': base = 8; break;
00095 case 'd':
00096 case 'i':
00097 case 'u': base = 10; break;
00098 case 'x':
00099 case 'X':
00100 case 'p': base = 16; break;
00101 }
00102
00103 s = _i_compute(unsigned_val, base, s, precision);
00104
00105 if (c == 'X')
00106 while (old_s != s) {
00107 *old_s = toupper(*old_s);
00108 old_s++;
00109 }
00110
00111 return s;
00112 }
00113
00114 int
00115 _doprnt(register const char *fmt, va_list ap, FILE *stream)
00116 {
00117 register char *s;
00118 register int j;
00119 int i, c, width, precision, zfill, flags, between_fill;
00120 int nrchars=0;
00121 const char *oldfmt;
00122 char *s1, buf[1025];
00123
00124 while (c = *fmt++) {
00125 if (c != '%') {
00126 #ifdef CPM
00127 if (c == '\n') {
00128 if (putc('\r', stream) == EOF)
00129 return nrchars ? -nrchars : -1;
00130 nrchars++;
00131 }
00132 #endif
00133 if (putc(c, stream) == EOF)
00134 return nrchars ? -nrchars : -1;
00135 nrchars++;
00136 continue;
00137 }
00138 flags = 0;
00139 do {
00140 switch(*fmt) {
00141 case '-': flags |= FL_LJUST; break;
00142 case '+': flags |= FL_SIGN; break;
00143 case ' ': flags |= FL_SPACE; break;
00144 case '#': flags |= FL_ALT; break;
00145 case '0': flags |= FL_ZEROFILL; break;
00146 default: flags |= FL_NOMORE; continue;
00147 }
00148 fmt++;
00149 } while(!(flags & FL_NOMORE));
00150
00151 oldfmt = fmt;
00152 fmt = gnum(fmt, &width, &ap);
00153 if (fmt != oldfmt) flags |= FL_WIDTHSPEC;
00154
00155 if (*fmt == '.') {
00156 fmt++; oldfmt = fmt;
00157 fmt = gnum(fmt, &precision, &ap);
00158 if (precision >= 0) flags |= FL_PRECSPEC;
00159 }
00160
00161 if ((flags & FL_WIDTHSPEC) && width < 0) {
00162 width = -width;
00163 flags |= FL_LJUST;
00164 }
00165 if (!(flags & FL_WIDTHSPEC)) width = 0;
00166
00167 if (flags & FL_SIGN) flags &= ~FL_SPACE;
00168
00169 if (flags & FL_LJUST) flags &= ~FL_ZEROFILL;
00170
00171
00172 s = s1 = buf;
00173
00174 switch (*fmt) {
00175 case 'h': flags |= FL_SHORT; fmt++; break;
00176 case 'l': flags |= FL_LONG; fmt++; break;
00177 case 'L': flags |= FL_LONGDOUBLE; fmt++; break;
00178 }
00179
00180 switch (c = *fmt++) {
00181 default:
00182 #ifdef CPM
00183 if (c == '\n') {
00184 if (putc('\r', stream) == EOF)
00185 return nrchars ? -nrchars : -1;
00186 nrchars++;
00187 }
00188 #endif
00189 if (putc(c, stream) == EOF)
00190 return nrchars ? -nrchars : -1;
00191 nrchars++;
00192 continue;
00193 case 'n':
00194 if (flags & FL_SHORT)
00195 *va_arg(ap, short *) = (short) nrchars;
00196 else if (flags & FL_LONG)
00197 *va_arg(ap, long *) = (long) nrchars;
00198 else
00199 *va_arg(ap, int *) = (int) nrchars;
00200 continue;
00201 case 's':
00202 s1 = va_arg(ap, char *);
00203 if (s1 == NULL)
00204 s1 = "(null)";
00205 s = s1;
00206 while (precision || !(flags & FL_PRECSPEC)) {
00207 if (*s == '\0')
00208 break;
00209 s++;
00210 precision--;
00211 }
00212 break;
00213 case 'p':
00214 set_pointer(flags);
00215
00216 case 'b':
00217 case 'o':
00218 case 'u':
00219 case 'x':
00220 case 'X':
00221 if (!(flags & FL_PRECSPEC)) precision = 1;
00222 else if (c != 'p') flags &= ~FL_ZEROFILL;
00223 s = o_print(&ap, flags, s, c, precision, 0);
00224 break;
00225 case 'd':
00226 case 'i':
00227 flags |= FL_SIGNEDCONV;
00228 if (!(flags & FL_PRECSPEC)) precision = 1;
00229 else flags &= ~FL_ZEROFILL;
00230 s = o_print(&ap, flags, s, c, precision, 1);
00231 break;
00232 case 'c':
00233 *s++ = va_arg(ap, int);
00234 break;
00235 #ifndef NOFLOAT
00236 case 'G':
00237 case 'g':
00238 if ((flags & FL_PRECSPEC) && (precision == 0))
00239 precision = 1;
00240 case 'f':
00241 case 'E':
00242 case 'e':
00243 if (!(flags & FL_PRECSPEC))
00244 precision = 6;
00245
00246 if (precision >= sizeof(buf))
00247 precision = sizeof(buf) - 1;
00248
00249 flags |= FL_SIGNEDCONV;
00250 s = _f_print(&ap, flags, s, c, precision);
00251 break;
00252 #endif
00253 case 'r':
00254 ap = va_arg(ap, va_list);
00255 fmt = va_arg(ap, char *);
00256 continue;
00257 }
00258 zfill = ' ';
00259 if (flags & FL_ZEROFILL) zfill = '0';
00260 j = s - s1;
00261
00262
00263
00264
00265
00266
00267
00268
00269 between_fill = 0;
00270 if ((flags & FL_ZEROFILL)
00271 && (((c == 'x' || c == 'X') && (flags & FL_ALT))
00272 || (c == 'p')
00273 || ((flags & FL_SIGNEDCONV)
00274 && ( *s1 == '+' || *s1 == '-' || *s1 == ' '))))
00275 between_fill++;
00276
00277 if ((i = width - j) > 0)
00278 if (!(flags & FL_LJUST)) {
00279 nrchars += i;
00280 if (between_fill) {
00281 if (flags & FL_SIGNEDCONV) {
00282 j--; nrchars++;
00283 if (putc(*s1++, stream) == EOF)
00284 return nrchars ? -nrchars : -1;
00285 } else {
00286 j -= 2; nrchars += 2;
00287 if ((putc(*s1++, stream) == EOF)
00288 || (putc(*s1++, stream) == EOF))
00289 return nrchars ? -nrchars : -1;
00290 }
00291 }
00292 do {
00293 if (putc(zfill, stream) == EOF)
00294 return nrchars ? -nrchars : -1;
00295 } while (--i);
00296 }
00297
00298 nrchars += j;
00299 while (--j >= 0) {
00300 if (putc(*s1++, stream) == EOF)
00301 return nrchars ? -nrchars : -1;
00302 }
00303
00304 if (i > 0) nrchars += i;
00305 while (--i >= 0)
00306 if (putc(zfill, stream) == EOF)
00307 return nrchars ? -nrchars : -1;
00308 }
00309 return nrchars;
00310 }