Update the changelog
[opencv] / apps / cvenv / EiC / stdClib / printf.c
1 /* vprintf.c
2  *
3  *      (C) Copyright Apr 15 1995, Edmond J. Breen.
4  *                 ALL RIGHTS RESERVED.
5  * This code may be copied for personal, non-profit use only.
6  *
7  */
8
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <stdarg.h>
15
16 #include "stdliblocal.h"
17
18 static int charin_(char **buf)
19 {
20     int ch;
21     ch = **buf;
22     *buf += 1;
23     if(!ch)
24         ch = EOF;
25     return ch;
26 }
27
28 static int charback_(int ch, char **buf)
29 {
30     *buf -= 1;
31     return ch;
32 }
33
34 static int charout_(int c, char **buf)
35 {
36     char *s;
37     s = *buf;
38     *s++ = c;
39     *s = 0;
40     *buf = s;
41     return 1;
42 }
43
44
45 int _Uprintf(int (*output)(), void *arg, const char *fmt, va_list ap)
46 {
47     /*_UPRINTF 
48      * Orginally developed from James Hendrix's Small C tools.
49      *
50      * (c) Edmond J.Breen (March, 1995).
51      *           ALL RIGHTS RESERVED.
52      *
53      * Purpose: To perform formatted printing to a function.
54      *          It performs a superset of printf type
55      *          operations.
56      *
57      *            _UPRINTF   RECOGNISES:
58      * FLAGS:
59      *         -, +, 0 and #.
60      *    plus ! and |  (see below).
61      *
62      * CONVERSION CHARACTERS:
63      *         d, i, o, x, X, u, c, s,
64      *         f, e, E, g, G, p, n, %
65      *    plus b   (see below).
66      *
67      * LENGTH MODIFIES:
68      *          l, L, and h.
69      *
70      * The WIDTH and or the PRECISION can be set indirectly
71      *  via * as specified by K&R.
72      *
73      *        _UPRINTF EXTRA FEATURES.
74      * NEW FLAGS:
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.
88      */
89   
90     int v;
91
92     static char str[128];
93     char *sptr, lseen,Lseen;
94   
95     int  left, right, centre, maxchr,
96     pad, len, width, sign, dprec,
97     mod, prec,dot,gotfloat;
98   
99     v = 0;
100
101     while(*fmt) {
102         if(*fmt != '%') {
103             (*output)(*fmt,arg);
104             ++fmt;++v;
105             continue;
106         } else if(*++fmt =='%') {
107             (*output)(*fmt++,arg);
108             ++v;
109             continue;
110         }
111         pad = ' ';
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;
122             else
123                 break;
124             ++fmt;
125         }
126         if(isdigit(*fmt)) {
127             width = atoi(fmt);
128             while(isdigit(*fmt)) ++fmt;
129         } else  if(*fmt == '*') {
130             width = va_arg(ap,int);
131             fmt++;
132         } else
133             width = -1;
134         if(*fmt == '.')  {
135             if(*++fmt == '*')  {
136                 maxchr = va_arg(ap,int);
137                 fmt++;
138             } else {
139                 maxchr = atoi(fmt);
140                 while(isdigit(*fmt)) ++fmt;
141             }
142         } else
143             maxchr = -1;
144     
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;
149         }
150         sptr = str;
151         switch(*fmt++) {
152           case 'c': sptr[0] = (char)va_arg(ap,int);
153             sptr[1] = 0;
154             break;
155           case 'b':
156             if(lseen) ultoa(va_arg(ap,long),sptr,2);
157             else utoa(va_arg(ap,int),sptr,2);
158             break;
159           case 'i':
160           case 'd': if(lseen) ltoa(va_arg(ap,long),sptr,10);
161           else itoa(va_arg(ap,int),sptr,10);
162           dprec=1;
163             break;
164           case 'u': if(lseen) ultoa(va_arg(ap,unsigned long),sptr,10);
165           else utoa(va_arg(ap,unsigned),sptr,10);
166           dprec=1;
167             break;
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);
171             dprec = 1;
172             break;
173           case 's': sptr = va_arg(ap,char*); break;
174           case 'x': case 'X':
175             if(mod) {
176                 *sptr = '0', sptr[1] = *(fmt-1);
177                 mod++;
178             }
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') {
182                 while(*sptr) {
183                     *sptr = toupper(*sptr);
184                     sptr++;
185                 }
186                 sptr = str;
187             }
188             dprec = 1;
189             break;
190             
191           case 'e': case 'E': case 'g': case 'G':
192           case 'f': {
193               int trunc = 0;
194               char type = *(fmt-1),c;
195               double d;
196       
197               gotfloat = 1;
198               if(maxchr < 0) prec = 6;
199               else prec = maxchr,maxchr = -1;
200
201               if(Lseen)
202                   d = va_arg(ap,double);
203               else
204                  d = va_arg(ap,double);
205       
206               if(type == 'g' || type == 'G') {
207                   double ex;
208                   if(d !=0)
209                       ex = log10(d < 0? -d:d);
210                   else
211                       ex = 1;
212                   if(ex < -4 || ex >= prec)
213                       c = type - 2;
214                   else
215                       c = 'f';
216                   trunc = 1;
217               } else
218                   c = type;
219               if(mod) {
220                   if(!prec) prec = 1;
221                   trunc = 0;
222               }
223               sptr = fftoa(d,str, prec, c,trunc);
224           }
225             break;
226           case 'n': *va_arg(ap,int*) = v; continue;
227           case 'p':
228               ultoa((long)va_arg(ap,long*),sptr,16);
229             break;
230           default: (*output)(*(fmt-1),arg);
231             while(*fmt) {
232                 (*output)(*fmt++,arg);
233                 ++v;
234             }
235             return v;
236         }
237     
238         if(!len && sptr) len = strlen(sptr);
239         if(sign) len += (*sptr == '-' ? 0: 1);
240
241         if(dprec && maxchr >=0) {
242             dprec = maxchr;
243             pad = '0';
244             
245         }else
246             dprec = 0;
247             
248         
249         if(maxchr > -1 && maxchr<len)
250             len = maxchr;
251         if(width>len)
252             width = width -len;
253         else if(dprec > len)
254             width = dprec - len;
255         else
256             width = 0;
257     
258         if(centre) {
259             left = (right = width >> 1) + (width%2);
260             if(dot && gotfloat) {
261                 int d = 0,c;
262                 while(sptr[d] && sptr[d] != '.')
263                     d++;
264                 if(sptr[d] == '.') {
265                     c = (width + len)/2;
266                     if(sign && sptr[0] != '-')
267                         d++;
268                     if(c-d > 0) right = c-d;
269                     else right = 0;
270                     if(width - right > 0)
271                         left = width - right;
272                     else
273                         left = 0;
274                 }
275             }
276         } else 
277             if(!left)
278                 right = width;
279             else
280                 left = width;
281     
282         if(sign && !left && pad == '0') {
283             if(*sptr != '-') {
284                 (*output)('+',arg);
285                 ++v;len--;
286             }
287             sign = 0;
288         }
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;}
293     }
294     return v;
295 }
296
297 int printf_(const char *fmt,...)
298 {
299     int rtn;
300     va_list ap;
301     /*ap =*/ va_start(ap,fmt);
302     rtn = _Uprintf(fputc,stdout,fmt,ap);
303     va_end(ap);
304     return rtn;
305 }
306
307 int fprintf(FILE *fp, const char *fmt, ...)
308 {
309     int rtn;
310     va_list ap;
311     va_start(ap,fmt);
312     rtn = _Uprintf(fputc,fp,fmt,ap);
313     va_end(ap);
314     return rtn;
315 }
316
317 int sprintf(char *str, const char *fmt, ...)
318 {
319     int rtn;
320     va_list ap;
321     va_start(ap,fmt);
322     rtn = _Uprintf(charout_,&str,fmt,ap);
323     va_end(ap);
324     return rtn;
325 }
326
327 int vfprintf(FILE *fp, const char *fmt,va_list ap)
328 {
329     int rtn;
330     rtn = _Uprintf(fputc,fp,fmt,ap);
331     return rtn;
332 }
333
334
335 int vsprintf(char *str, const char *fmt,va_list ap)
336 {
337     int rtn;
338     rtn = _Uprintf(charout_,&str,fmt,ap);
339     return rtn;
340 }
341
342
343
344
345
346
347
348