3 * (C) Copyright Apr 15 1995, Edmond J. Breen.
5 * This code may be copied for personal, non-profit use only.
16 #include "stdliblocal.h"
18 static int charin_(char **buf)
28 static int charback_(int ch, char **buf)
34 static int charout_(int c, char **buf)
45 int _Uprintf(int (*output)(), void *arg, const char *fmt, va_list ap)
48 * Orginally developed from James Hendrix's Small C tools.
50 * (c) Edmond J.Breen (March, 1995).
51 * ALL RIGHTS RESERVED.
53 * Purpose: To perform formatted printing to a function.
54 * It performs a superset of printf type
57 * _UPRINTF RECOGNISES:
60 * plus ! and | (see below).
62 * CONVERSION CHARACTERS:
63 * d, i, o, x, X, u, c, s,
64 * f, e, E, g, G, p, n, %
70 * The WIDTH and or the PRECISION can be set indirectly
71 * via * as specified by K&R.
73 * _UPRINTF EXTRA FEATURES.
75 * FLAG WHAT IT SPECIFIES
76 * | Centre justification.
77 * ! Used with floating point numbers.
78 * It specifies, if possible, that the
79 * number will be centred with respect
80 * to the decimal point.
81 * If used with non floating point
82 * numbers or the floating point number
83 * does not contain a decimal point,
84 * the ! flag is equivalent to |.
85 * NEW CONVERSION CHARACTER:
86 * CHARACTER WHAT IT SPECIFIES
87 * b int, unsigned binary notation.
93 char *sptr, lseen,Lseen;
95 int left, right, centre, maxchr,
96 pad, len, width, sign, dprec,
97 mod, prec,dot,gotfloat;
106 } else if(*++fmt =='%') {
107 (*output)(*fmt++,arg);
112 centre = len = right = left = 0;
113 gotfloat = dot = sign = mod = 0;
114 Lseen = lseen = dprec = 0;
115 while(*fmt) { /* collect in any order */
116 if(*fmt == '-') left = 1;
117 else if(*fmt == '0') pad = '0';
118 else if(*fmt == '+') sign = 1;
119 else if(*fmt == '#') mod = 1;
120 else if(*fmt == '|') centre = 1;
121 else if(*fmt == '!') centre = 1, dot = 1;
128 while(isdigit(*fmt)) ++fmt;
129 } else if(*fmt == '*') {
130 width = va_arg(ap,int);
136 maxchr = va_arg(ap,int);
140 while(isdigit(*fmt)) ++fmt;
145 switch(*fmt) { /* check for length modifier*/
146 case 'h': fmt++;break;
147 case 'l': lseen = 1; fmt++;break;
148 case 'L': Lseen = 1; fmt++;break;
152 case 'c': sptr[0] = (char)va_arg(ap,int);
156 if(lseen) ultoa(va_arg(ap,long),sptr,2);
157 else utoa(va_arg(ap,int),sptr,2);
160 case 'd': if(lseen) ltoa(va_arg(ap,long),sptr,10);
161 else itoa(va_arg(ap,int),sptr,10);
164 case 'u': if(lseen) ultoa(va_arg(ap,unsigned long),sptr,10);
165 else utoa(va_arg(ap,unsigned),sptr,10);
168 case 'o': if(mod) *sptr = '0';
169 if(lseen)ltoa(va_arg(ap,long),&sptr[mod],8);
170 else itoa(va_arg(ap,int),&sptr[mod],8);
173 case 's': sptr = va_arg(ap,char*); break;
176 *sptr = '0', sptr[1] = *(fmt-1);
179 if(lseen)ultoa(va_arg(ap,long),&sptr[mod],16);
180 else utoa(va_arg(ap,int),&sptr[mod],16);
181 if(*(fmt-1) == 'X') {
183 *sptr = toupper(*sptr);
191 case 'e': case 'E': case 'g': case 'G':
194 char type = *(fmt-1),c;
198 if(maxchr < 0) prec = 6;
199 else prec = maxchr,maxchr = -1;
202 d = va_arg(ap,double);
204 d = va_arg(ap,double);
206 if(type == 'g' || type == 'G') {
209 ex = log10(d < 0? -d:d);
212 if(ex < -4 || ex >= prec)
223 sptr = fftoa(d,str, prec, c,trunc);
226 case 'n': *va_arg(ap,int*) = v; continue;
228 ultoa((long)va_arg(ap,long*),sptr,16);
230 default: (*output)(*(fmt-1),arg);
232 (*output)(*fmt++,arg);
238 if(!len && sptr) len = strlen(sptr);
239 if(sign) len += (*sptr == '-' ? 0: 1);
241 if(dprec && maxchr >=0) {
249 if(maxchr > -1 && maxchr<len)
259 left = (right = width >> 1) + (width%2);
260 if(dot && gotfloat) {
262 while(sptr[d] && sptr[d] != '.')
266 if(sign && sptr[0] != '-')
268 if(c-d > 0) right = c-d;
270 if(width - right > 0)
271 left = width - right;
282 if(sign && !left && pad == '0') {
289 while(right--) {(*output)(pad,arg); ++v;}
290 if(sign && *sptr != '-') {(*output)('+',arg);len--;++v;}
291 while(len--) {(*output)(*sptr++,arg);++v;}
292 while(left--) {(*output)(pad,arg);++v;}
297 int printf_(const char *fmt,...)
301 /*ap =*/ va_start(ap,fmt);
302 rtn = _Uprintf(fputc,stdout,fmt,ap);
307 int fprintf(FILE *fp, const char *fmt, ...)
312 rtn = _Uprintf(fputc,fp,fmt,ap);
317 int sprintf(char *str, const char *fmt, ...)
322 rtn = _Uprintf(charout_,&str,fmt,ap);
327 int vfprintf(FILE *fp, const char *fmt,va_list ap)
330 rtn = _Uprintf(fputc,fp,fmt,ap);
335 int vsprintf(char *str, const char *fmt,va_list ap)
338 rtn = _Uprintf(charout_,&str,fmt,ap);