2 * doprnt.c - print formatted output
4 /* $Id: doprnt.c,v 1.11 1994/06/24 11:48:24 ceriel Exp $ */
12 /* gnum() is used to get the width and precision fields of a format. */
14 gnum(register const char *f, int *ip, va_list *app)
19 *ip = va_arg((*app), int);
23 while ((c = *f - '0') >= 0 && c <= 9) {
32 #if _EM_WSIZE == _EM_PSIZE
33 #define set_pointer(flags) /* nothing */
34 #elif _EM_LSIZE == _EM_PSIZE
35 #define set_pointer(flags) (flags |= FL_LONG)
37 #error garbage pointer size
38 #define set_pointer(flags) /* compilation might continue */
41 /* print an ordinal number */
43 o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed)
46 unsigned long unsigned_val;
50 switch (flags & (FL_SHORT | FL_LONG)) {
53 signed_val = (short) va_arg(*ap, int);
55 unsigned_val = (unsigned short) va_arg(*ap, unsigned);
60 signed_val = va_arg(*ap, long);
62 unsigned_val = va_arg(*ap, unsigned long);
67 signed_val = va_arg(*ap, int);
69 unsigned_val = va_arg(*ap, unsigned int);
77 signed_val = -signed_val;
78 } else if (flags & FL_SIGN) *s++ = '+';
79 else if (flags & FL_SPACE) *s++ = ' ';
80 unsigned_val = signed_val;
82 if ((flags & FL_ALT) && (c == 'o')) *s++ = '0';
86 } else if (((flags & FL_ALT) && (c == 'x' || c == 'X'))
89 *s++ = (c == 'X' ? 'X' : 'x');
93 case 'b': base = 2; break;
94 case 'o': base = 8; break;
97 case 'u': base = 10; break;
100 case 'p': base = 16; break;
103 s = _i_compute(unsigned_val, base, s, precision);
107 *old_s = toupper(*old_s);
115 _doprnt(register const char *fmt, va_list ap, FILE *stream)
119 int i, c, width, precision, zfill, flags, between_fill;
128 if (putc('\r', stream) == EOF)
129 return nrchars ? -nrchars : -1;
133 if (putc(c, stream) == EOF)
134 return nrchars ? -nrchars : -1;
141 case '-': flags |= FL_LJUST; break;
142 case '+': flags |= FL_SIGN; break;
143 case ' ': flags |= FL_SPACE; break;
144 case '#': flags |= FL_ALT; break;
145 case '0': flags |= FL_ZEROFILL; break;
146 default: flags |= FL_NOMORE; continue;
149 } while(!(flags & FL_NOMORE));
152 fmt = gnum(fmt, &width, &ap);
153 if (fmt != oldfmt) flags |= FL_WIDTHSPEC;
157 fmt = gnum(fmt, &precision, &ap);
158 if (precision >= 0) flags |= FL_PRECSPEC;
161 if ((flags & FL_WIDTHSPEC) && width < 0) {
165 if (!(flags & FL_WIDTHSPEC)) width = 0;
167 if (flags & FL_SIGN) flags &= ~FL_SPACE;
169 if (flags & FL_LJUST) flags &= ~FL_ZEROFILL;
175 case 'h': flags |= FL_SHORT; fmt++; break;
176 case 'l': flags |= FL_LONG; fmt++; break;
177 case 'L': flags |= FL_LONGDOUBLE; fmt++; break;
180 switch (c = *fmt++) {
184 if (putc('\r', stream) == EOF)
185 return nrchars ? -nrchars : -1;
189 if (putc(c, stream) == EOF)
190 return nrchars ? -nrchars : -1;
194 if (flags & FL_SHORT)
195 *va_arg(ap, short *) = (short) nrchars;
196 else if (flags & FL_LONG)
197 *va_arg(ap, long *) = (long) nrchars;
199 *va_arg(ap, int *) = (int) nrchars;
202 s1 = va_arg(ap, char *);
206 while (precision || !(flags & FL_PRECSPEC)) {
221 if (!(flags & FL_PRECSPEC)) precision = 1;
222 else if (c != 'p') flags &= ~FL_ZEROFILL;
223 s = o_print(&ap, flags, s, c, precision, 0);
227 flags |= FL_SIGNEDCONV;
228 if (!(flags & FL_PRECSPEC)) precision = 1;
229 else flags &= ~FL_ZEROFILL;
230 s = o_print(&ap, flags, s, c, precision, 1);
233 *s++ = va_arg(ap, int);
238 if ((flags & FL_PRECSPEC) && (precision == 0))
243 if (!(flags & FL_PRECSPEC))
246 if (precision >= sizeof(buf))
247 precision = sizeof(buf) - 1;
249 flags |= FL_SIGNEDCONV;
250 s = _f_print(&ap, flags, s, c, precision);
254 ap = va_arg(ap, va_list);
255 fmt = va_arg(ap, char *);
259 if (flags & FL_ZEROFILL) zfill = '0';
262 /* between_fill is true under the following conditions:
263 * 1- the fill character is '0'
265 * 2a- the number is of the form 0x... or 0X...
267 * 2b- the number contains a sign or space
270 if ((flags & FL_ZEROFILL)
271 && (((c == 'x' || c == 'X') && (flags & FL_ALT))
273 || ((flags & FL_SIGNEDCONV)
274 && ( *s1 == '+' || *s1 == '-' || *s1 == ' '))))
277 if ((i = width - j) > 0)
278 if (!(flags & FL_LJUST)) { /* right justify */
281 if (flags & FL_SIGNEDCONV) {
283 if (putc(*s1++, stream) == EOF)
284 return nrchars ? -nrchars : -1;
286 j -= 2; nrchars += 2;
287 if ((putc(*s1++, stream) == EOF)
288 || (putc(*s1++, stream) == EOF))
289 return nrchars ? -nrchars : -1;
293 if (putc(zfill, stream) == EOF)
294 return nrchars ? -nrchars : -1;
300 if (putc(*s1++, stream) == EOF)
301 return nrchars ? -nrchars : -1;
304 if (i > 0) nrchars += i;
306 if (putc(zfill, stream) == EOF)
307 return nrchars ? -nrchars : -1;