Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1029 | serge | 1 | /* |
2 | * vsprintf - print formatted output without ellipsis on an array |
||
3 | */ |
||
4 | /* $Header$ */ |
||
5 | |||
6 | //#include "stdio.h" |
||
7 | //#include |
||
8 | |||
9 | typedef unsigned size_t; |
||
10 | |||
11 | typedef struct |
||
12 | { |
||
13 | char *_ptr; |
||
14 | unsigned _count; |
||
15 | }__str; |
||
16 | |||
17 | |||
18 | #define va_start(v,l) __builtin_va_start(v,l) |
||
19 | #define va_end(v) __builtin_va_end(v) |
||
20 | #define va_arg(v,l) __builtin_va_arg(v,l) |
||
21 | #if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L |
||
22 | #define va_copy(d,s) __builtin_va_copy(d,s) |
||
23 | #endif |
||
24 | #define __va_copy(d,s) __builtin_va_copy(d,s) |
||
25 | |||
26 | typedef __builtin_va_list __gnuc_va_list; |
||
27 | typedef __gnuc_va_list va_list; |
||
28 | |||
29 | #define arg(x) va_arg (ap, u32) |
||
30 | |||
31 | #define io_testflag(p,x) ((p)->_flags & (x)) |
||
32 | |||
33 | char *_i_compute(unsigned long val, int base, char *s, int nrdigits); |
||
34 | char *_f_print(va_list *ap, int flags, char *s, char c, int precision); |
||
35 | void __cleanup(void); |
||
36 | |||
37 | |||
38 | void *calloc( size_t num, size_t size ); |
||
39 | int memcmp(const void *s1, const void *s2, size_t n); |
||
40 | void * memcpy(void * _dest, const void *_src, size_t _n); |
||
41 | char * strcpy(char *to, const char *from); |
||
42 | char * strcat(char *s, const char *append); |
||
43 | int strcmp(const char *s1, const char *s2); |
||
44 | size_t strlen(const char *str); |
||
45 | char * strdup(const char *_s); |
||
46 | char * strchr(const char *s, int c); |
||
47 | |||
48 | |||
49 | #define FL_LJUST 0x0001 /* left-justify field */ |
||
50 | #define FL_SIGN 0x0002 /* sign in signed conversions */ |
||
51 | #define FL_SPACE 0x0004 /* space in signed conversions */ |
||
52 | #define FL_ALT 0x0008 /* alternate form */ |
||
53 | #define FL_ZEROFILL 0x0010 /* fill with zero's */ |
||
54 | #define FL_SHORT 0x0020 /* optional h */ |
||
55 | #define FL_LONG 0x0040 /* optional l */ |
||
56 | #define FL_LONGDOUBLE 0x0080 /* optional L */ |
||
57 | #define FL_WIDTHSPEC 0x0100 /* field width is specified */ |
||
58 | #define FL_PRECSPEC 0x0200 /* precision is specified */ |
||
59 | #define FL_SIGNEDCONV 0x0400 /* may contain a sign */ |
||
60 | #define FL_NOASSIGN 0x0800 /* do not assign (in scanf) */ |
||
61 | #define FL_NOMORE 0x1000 /* all flags collected */ |
||
62 | |||
63 | #define _IOFBF 0x000 |
||
64 | #define _IOREAD 0x001 |
||
65 | #define _IOWRITE 0x002 |
||
66 | #define _IONBF 0x004 |
||
67 | #define _IOMYBUF 0x008 |
||
68 | #define _IOEOF 0x010 |
||
69 | #define _IOERR 0x020 |
||
70 | #define _IOLBF 0x040 |
||
71 | #define _IOREADING 0x080 |
||
72 | #define _IOWRITING 0x100 |
||
73 | #define _IOAPPEND 0x200 |
||
74 | #define _IOFIFO 0x400 |
||
75 | |||
76 | #define SGL_MAX 254 /* standard definition */ |
||
77 | #define SGL_MIN 1 /* standard definition */ |
||
78 | #define DBL_MAX 2046 /* standard definition */ |
||
79 | #define DBL_MIN 1 /* standard definition */ |
||
80 | #define EXT_MAX 16383 /* standard minimum */ |
||
81 | #define EXT_MIN -16382 /* standard minimum */ |
||
82 | #include |
||
83 | |||
84 | static char *cvt(); |
||
85 | #define NDIGITS 128 |
||
86 | |||
87 | unsigned char __dj_ctype_toupper[] = { |
||
88 | 0x00, |
||
89 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
||
90 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
||
91 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
||
92 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
||
93 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
||
94 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, |
||
95 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
||
96 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, |
||
97 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
||
98 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |
||
99 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |
||
100 | 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, |
||
101 | 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
||
102 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |
||
103 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |
||
104 | 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, |
||
105 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
||
106 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, |
||
107 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, |
||
108 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, |
||
109 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, |
||
110 | 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, |
||
111 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, |
||
112 | 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, |
||
113 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, |
||
114 | 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, |
||
115 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, |
||
116 | 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, |
||
117 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, |
||
118 | 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, |
||
119 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, |
||
120 | 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff |
||
121 | }; |
||
122 | #define toupper(c) (__dj_ctype_toupper[(int)(c)+1]) |
||
123 | |||
124 | int (toupper)(int c) |
||
125 | { |
||
126 | return toupper(c); |
||
127 | } |
||
128 | |||
129 | char * |
||
130 | _ecvt(value, ndigit, decpt, sign) |
||
131 | double value; |
||
132 | int ndigit, *decpt, *sign; |
||
133 | { |
||
134 | return cvt(value, ndigit, decpt, sign, 1); |
||
135 | } |
||
136 | |||
137 | char * |
||
138 | _fcvt(value, ndigit, decpt, sign) |
||
139 | double value; |
||
140 | int ndigit, *decpt, *sign; |
||
141 | { |
||
142 | return cvt(value, ndigit, decpt, sign, 0); |
||
143 | } |
||
144 | |||
145 | static struct powers_of_10 { |
||
146 | double pval; |
||
147 | double rpval; |
||
148 | int exp; |
||
149 | } p10[] = { |
||
150 | 1.0e32, 1.0e-32, 32, |
||
151 | 1.0e16, 1.0e-16, 16, |
||
152 | 1.0e8, 1.0e-8, 8, |
||
153 | 1.0e4, 1.0e-4, 4, |
||
154 | 1.0e2, 1.0e-2, 2, |
||
155 | 1.0e1, 1.0e-1, 1, |
||
156 | 1.0e0, 1.0e0, 0 |
||
157 | }; |
||
158 | |||
159 | static char * |
||
160 | cvt(value, ndigit, decpt, sign, ecvtflag) |
||
161 | double value; |
||
162 | int ndigit, *decpt, *sign; |
||
163 | { |
||
164 | static char buf[NDIGITS+1]; |
||
165 | register char *p = buf; |
||
166 | register char *pe; |
||
167 | |||
168 | if (ndigit < 0) ndigit = 0; |
||
169 | if (ndigit > NDIGITS) ndigit = NDIGITS; |
||
170 | pe = &buf[ndigit]; |
||
171 | buf[0] = '\0'; |
||
172 | |||
173 | *sign = 0; |
||
174 | if (value < 0) { |
||
175 | *sign = 1; |
||
176 | value = -value; |
||
177 | } |
||
178 | |||
179 | *decpt = 0; |
||
180 | if (value >= DBL_MAX) { |
||
181 | value = DBL_MAX; |
||
182 | } |
||
183 | if (value != 0.0) { |
||
184 | register struct powers_of_10 *pp = &p10[0]; |
||
185 | |||
186 | if (value >= 10.0) do { |
||
187 | while (value >= pp->pval) { |
||
188 | value *= pp->rpval; |
||
189 | *decpt += pp->exp; |
||
190 | } |
||
191 | } while ((++pp)->exp > 0); |
||
192 | |||
193 | pp = &p10[0]; |
||
194 | if (value < 1.0) do { |
||
195 | while (value * pp->pval < 10.0) { |
||
196 | value *= pp->pval; |
||
197 | *decpt -= pp->exp; |
||
198 | } |
||
199 | } while ((++pp)->exp > 0); |
||
200 | |||
201 | (*decpt)++; /* because now value in [1.0, 10.0) */ |
||
202 | } |
||
203 | if (! ecvtflag) { |
||
204 | /* for fcvt() we need ndigit digits behind the dot */ |
||
205 | pe += *decpt; |
||
206 | if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS]; |
||
207 | } |
||
208 | while (p <= pe) { |
||
209 | *p++ = (int)value + '0'; |
||
210 | value = 10.0 * (value - (int)value); |
||
211 | } |
||
212 | if (pe >= buf) { |
||
213 | p = pe; |
||
214 | *p += 5; /* round of at the end */ |
||
215 | while (*p > '9') { |
||
216 | *p = '0'; |
||
217 | if (p > buf) ++*--p; |
||
218 | else { |
||
219 | *p = '1'; |
||
220 | ++*decpt; |
||
221 | if (! ecvtflag) { |
||
222 | /* maybe add another digit at the end, |
||
223 | because the point was shifted right |
||
224 | */ |
||
225 | if (pe > buf) *pe = '0'; |
||
226 | pe++; |
||
227 | } |
||
228 | } |
||
229 | } |
||
230 | *pe = '\0'; |
||
231 | } |
||
232 | return buf; |
||
233 | } |
||
234 | |||
235 | |||
236 | int _fp_hook = 1; |
||
237 | |||
238 | static char * |
||
239 | _pfloat(double r, register char *s, int n, int flags) |
||
240 | { |
||
241 | register char *s1; |
||
242 | int sign, dp; |
||
243 | register int i; |
||
244 | |||
245 | s1 = _fcvt(r, n, &dp, &sign); |
||
246 | if (sign) |
||
247 | *s++ = '-'; |
||
248 | else if (flags & FL_SIGN) |
||
249 | *s++ = '+'; |
||
250 | else if (flags & FL_SPACE) |
||
251 | *s++ = ' '; |
||
252 | |||
253 | if (dp<=0) |
||
254 | *s++ = '0'; |
||
255 | for (i=dp; i>0; i--) |
||
256 | if (*s1) *s++ = *s1++; |
||
257 | else *s++ = '0'; |
||
258 | if (((i=n) > 0) || (flags & FL_ALT)) |
||
259 | *s++ = '.'; |
||
260 | while (++dp <= 0) { |
||
261 | if (--i<0) |
||
262 | break; |
||
263 | *s++ = '0'; |
||
264 | } |
||
265 | while (--i >= 0) |
||
266 | if (*s1) *s++ = *s1++; |
||
267 | else *s++ = '0'; |
||
268 | return s; |
||
269 | } |
||
270 | |||
271 | static char * |
||
272 | _pscien(double r, register char *s, int n, int flags) |
||
273 | { |
||
274 | int sign, dp; |
||
275 | register char *s1; |
||
276 | |||
277 | s1 = _ecvt(r, n + 1, &dp, &sign); |
||
278 | if (sign) |
||
279 | *s++ = '-'; |
||
280 | else if (flags & FL_SIGN) |
||
281 | *s++ = '+'; |
||
282 | else if (flags & FL_SPACE) |
||
283 | *s++ = ' '; |
||
284 | |||
285 | *s++ = *s1++; |
||
286 | if ((n > 0) || (flags & FL_ALT)) |
||
287 | *s++ = '.'; |
||
288 | while (--n >= 0) |
||
289 | if (*s1) *s++ = *s1++; |
||
290 | else *s++ = '0'; |
||
291 | *s++ = 'e'; |
||
292 | if ( r != 0 ) --dp ; |
||
293 | if ( dp<0 ) { |
||
294 | *s++ = '-' ; dp= -dp ; |
||
295 | } else { |
||
296 | *s++ = '+' ; |
||
297 | } |
||
298 | if (dp >= 100) { |
||
299 | *s++ = '0' + (dp / 100); |
||
300 | dp %= 100; |
||
301 | } |
||
302 | *s++ = '0' + (dp/10); |
||
303 | *s++ = '0' + (dp%10); |
||
304 | return s; |
||
305 | } |
||
306 | |||
307 | #define NDIGINEXP(exp) (((exp) >= 100 || (exp) <= -100) ? 3 : 2) |
||
308 | #define LOW_EXP -4 |
||
309 | #define USE_EXP(exp, ndigits) (((exp) < LOW_EXP + 1) || (exp >= ndigits + 1)) |
||
310 | |||
311 | static char * |
||
312 | _gcvt(double value, int ndigit, char *s, int flags) |
||
313 | { |
||
314 | int sign, dp; |
||
315 | register char *s1, *s2; |
||
316 | register int i; |
||
317 | register int nndigit = ndigit; |
||
318 | |||
319 | s1 = _ecvt(value, ndigit, &dp, &sign); |
||
320 | s2 = s; |
||
321 | if (sign) *s2++ = '-'; |
||
322 | else if (flags & FL_SIGN) |
||
323 | *s2++ = '+'; |
||
324 | else if (flags & FL_SPACE) |
||
325 | *s2++ = ' '; |
||
326 | |||
327 | if (!(flags & FL_ALT)) |
||
328 | for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--) |
||
329 | nndigit--; |
||
330 | |||
331 | if (USE_EXP(dp,ndigit)) { |
||
332 | /* Use E format */ |
||
333 | dp--; |
||
334 | *s2++ = *s1++; |
||
335 | if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.'; |
||
336 | while (--nndigit > 0) *s2++ = *s1++; |
||
337 | *s2++ = 'e'; |
||
338 | if (dp < 0) { |
||
339 | *s2++ = '-'; |
||
340 | dp = -dp; |
||
341 | } |
||
342 | else *s2++ = '+'; |
||
343 | s2 += NDIGINEXP(dp); |
||
344 | *s2 = 0; |
||
345 | for (i = NDIGINEXP(dp); i > 0; i--) { |
||
346 | *--s2 = dp % 10 + '0'; |
||
347 | dp /= 10; |
||
348 | } |
||
349 | return s; |
||
350 | } |
||
351 | /* Use f format */ |
||
352 | if (dp <= 0) { |
||
353 | if (*s1 != '0') { |
||
354 | /* otherwise the whole number is 0 */ |
||
355 | *s2++ = '0'; |
||
356 | *s2++ = '.'; |
||
357 | } |
||
358 | while (dp < 0) { |
||
359 | dp++; |
||
360 | *s2++ = '0'; |
||
361 | } |
||
362 | } |
||
363 | for (i = 1; i <= nndigit; i++) { |
||
364 | *s2++ = *s1++; |
||
365 | if (i == dp) *s2++ = '.'; |
||
366 | } |
||
367 | if (i <= dp) { |
||
368 | while (i++ <= dp) *s2++ = '0'; |
||
369 | *s2++ = '.'; |
||
370 | } |
||
371 | if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--; |
||
372 | *s2 = '\0'; |
||
373 | return s; |
||
374 | } |
||
375 | |||
376 | char * |
||
377 | _f_print(va_list *ap, int flags, char *s, char c, int precision) |
||
378 | { |
||
379 | register char *old_s = s; |
||
380 | double ld_val; |
||
381 | |||
382 | // if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, double); |
||
383 | // else |
||
384 | ld_val = (double) va_arg(*ap, double); |
||
385 | |||
386 | switch(c) { |
||
387 | case 'f': |
||
388 | s = _pfloat(ld_val, s, precision, flags); |
||
389 | break; |
||
390 | case 'e': |
||
391 | case 'E': |
||
392 | s = _pscien(ld_val, s, precision , flags); |
||
393 | break; |
||
394 | case 'g': |
||
395 | case 'G': |
||
396 | s = _gcvt(ld_val, precision, s, flags); |
||
397 | s += strlen(s); |
||
398 | break; |
||
399 | } |
||
400 | if ( c == 'E' || c == 'G') { |
||
401 | while (*old_s && *old_s != 'e') old_s++; |
||
402 | if (*old_s == 'e') *old_s = 'E'; |
||
403 | } |
||
404 | return s; |
||
405 | } |
||
406 | |||
407 | //#endif /* NOFLOAT */ |
||
408 | /* $Header$ */ |
||
409 | |||
410 | //#include |
||
411 | //#include "../ansi/ext_fmt.h" |
||
412 | |||
413 | //void _str_ext_cvt(const char *s, char **ss, struct EXTEND *e); |
||
414 | //double _ext_dbl_cvt(struct EXTEND *e); |
||
415 | |||
416 | //double |
||
417 | //strtod(const char *p, char **pp) |
||
418 | //{ |
||
419 | // struct EXTEND e; |
||
420 | |||
421 | // _str_ext_cvt(p, pp, &e); |
||
422 | // return _ext_dbl_cvt(&e); |
||
423 | //} |
||
424 | |||
425 | #define BUFSIZ 4096 |
||
426 | #define NULL ((void *)0) |
||
427 | #define EOF (-1) |
||
428 | |||
429 | |||
430 | /* gnum() is used to get the width and precision fields of a format. */ |
||
431 | static const char * |
||
432 | gnum(register const char *f, int *ip, va_list *app) |
||
433 | { |
||
434 | register int i, c; |
||
435 | |||
436 | if (*f == '*') { |
||
437 | *ip = va_arg((*app), int); |
||
438 | f++; |
||
439 | } else { |
||
440 | i = 0; |
||
441 | while ((c = *f - '0') >= 0 && c <= 9) { |
||
442 | i = i*10 + c; |
||
443 | f++; |
||
444 | } |
||
445 | *ip = i; |
||
446 | } |
||
447 | return f; |
||
448 | } |
||
449 | |||
450 | #if _EM_WSIZE == _EM_PSIZE |
||
451 | #define set_pointer(flags) /* nothing */ |
||
452 | #elif _EM_LSIZE == _EM_PSIZE |
||
453 | #define set_pointer(flags) (flags |= FL_LONG) |
||
454 | #else |
||
455 | #error garbage pointer size |
||
456 | #define set_pointer(flags) /* compilation might continue */ |
||
457 | #endif |
||
458 | |||
459 | /* print an ordinal number */ |
||
460 | static char * |
||
461 | o_print(va_list *ap, int flags, char *s, char c, int precision, int is_signed) |
||
462 | { |
||
463 | long signed_val; |
||
464 | unsigned long unsigned_val; |
||
465 | char *old_s = s; |
||
466 | int base; |
||
467 | |||
468 | switch (flags & (FL_SHORT | FL_LONG)) { |
||
469 | case FL_SHORT: |
||
470 | if (is_signed) { |
||
471 | signed_val = (short) va_arg(*ap, int); |
||
472 | } else { |
||
473 | unsigned_val = (unsigned short) va_arg(*ap, unsigned); |
||
474 | } |
||
475 | break; |
||
476 | case FL_LONG: |
||
477 | if (is_signed) { |
||
478 | signed_val = va_arg(*ap, long); |
||
479 | } else { |
||
480 | unsigned_val = va_arg(*ap, unsigned long); |
||
481 | } |
||
482 | break; |
||
483 | default: |
||
484 | if (is_signed) { |
||
485 | signed_val = va_arg(*ap, int); |
||
486 | } else { |
||
487 | unsigned_val = va_arg(*ap, unsigned int); |
||
488 | } |
||
489 | break; |
||
490 | } |
||
491 | |||
492 | if (is_signed) { |
||
493 | if (signed_val < 0) { |
||
494 | *s++ = '-'; |
||
495 | signed_val = -signed_val; |
||
496 | } else if (flags & FL_SIGN) *s++ = '+'; |
||
497 | else if (flags & FL_SPACE) *s++ = ' '; |
||
498 | unsigned_val = signed_val; |
||
499 | } |
||
500 | if ((flags & FL_ALT) && (c == 'o')) *s++ = '0'; |
||
501 | if (!unsigned_val && c != 'p') { |
||
502 | if (!precision) |
||
503 | return s; |
||
504 | } else if (((flags & FL_ALT) && (c == 'x' || c == 'X')) |
||
505 | || c == 'p') { |
||
506 | *s++ = '0'; |
||
507 | *s++ = (c == 'X' ? 'X' : 'x'); |
||
508 | } |
||
509 | |||
510 | switch (c) { |
||
511 | case 'b': base = 2; break; |
||
512 | case 'o': base = 8; break; |
||
513 | case 'd': |
||
514 | case 'i': |
||
515 | case 'u': base = 10; break; |
||
516 | case 'x': |
||
517 | case 'X': |
||
518 | case 'p': base = 16; break; |
||
519 | } |
||
520 | |||
521 | s = _i_compute(unsigned_val, base, s, precision); |
||
522 | |||
523 | if (c == 'X') |
||
524 | while (old_s != s) { |
||
525 | *old_s = toupper(*old_s); |
||
526 | old_s++; |
||
527 | } |
||
528 | |||
529 | return s; |
||
530 | } |
||
531 | |||
532 | |||
533 | #define putc(c, p) (--(p)->_count >= 0 ? (int) (*(p)->_ptr++ = (c)) : EOF) |
||
534 | |||
535 | int |
||
536 | _doprnt(register const char *fmt, va_list ap, __str *stream) |
||
537 | { |
||
538 | register char *s; |
||
539 | register int j; |
||
540 | int i, c, width, precision, zfill, flags, between_fill; |
||
541 | int nrchars=0; |
||
542 | const char *oldfmt; |
||
543 | char *s1, buf[512]; |
||
544 | |||
545 | while (c = *fmt++) |
||
546 | { |
||
547 | if (c != '%') |
||
548 | { |
||
549 | if (c == '\n') |
||
550 | { |
||
551 | if (putc('\r', stream) == EOF) |
||
552 | return nrchars ? -nrchars : -1; |
||
553 | nrchars++; |
||
554 | } |
||
555 | if (putc(c, stream) == EOF) |
||
556 | return nrchars ? -nrchars : -1; |
||
557 | nrchars++; |
||
558 | continue; |
||
559 | } |
||
560 | flags = 0; |
||
561 | do { |
||
562 | switch(*fmt) { |
||
563 | case '-': flags |= FL_LJUST; break; |
||
564 | case '+': flags |= FL_SIGN; break; |
||
565 | case ' ': flags |= FL_SPACE; break; |
||
566 | case '#': flags |= FL_ALT; break; |
||
567 | case '0': flags |= FL_ZEROFILL; break; |
||
568 | default: flags |= FL_NOMORE; continue; |
||
569 | } |
||
570 | fmt++; |
||
571 | } while(!(flags & FL_NOMORE)); |
||
572 | |||
573 | oldfmt = fmt; |
||
574 | fmt = gnum(fmt, &width, &ap); |
||
575 | if (fmt != oldfmt) flags |= FL_WIDTHSPEC; |
||
576 | |||
577 | if (*fmt == '.') { |
||
578 | fmt++; oldfmt = fmt; |
||
579 | fmt = gnum(fmt, &precision, &ap); |
||
580 | if (precision >= 0) flags |= FL_PRECSPEC; |
||
581 | } |
||
582 | |||
583 | if ((flags & FL_WIDTHSPEC) && width < 0) { |
||
584 | width = -width; |
||
585 | flags |= FL_LJUST; |
||
586 | } |
||
587 | if (!(flags & FL_WIDTHSPEC)) width = 0; |
||
588 | |||
589 | if (flags & FL_SIGN) flags &= ~FL_SPACE; |
||
590 | |||
591 | if (flags & FL_LJUST) flags &= ~FL_ZEROFILL; |
||
592 | |||
593 | |||
594 | s = s1 = buf; |
||
595 | |||
596 | switch (*fmt) { |
||
597 | case 'h': flags |= FL_SHORT; fmt++; break; |
||
598 | case 'l': flags |= FL_LONG; fmt++; break; |
||
599 | case 'L': flags |= FL_LONGDOUBLE; fmt++; break; |
||
600 | } |
||
601 | |||
602 | switch (c = *fmt++) { |
||
603 | default: |
||
604 | if (c == '\n') { |
||
605 | if (putc('\r', stream) == EOF) |
||
606 | return nrchars ? -nrchars : -1; |
||
607 | nrchars++; |
||
608 | } |
||
609 | if (putc(c, stream) == EOF) |
||
610 | return nrchars ? -nrchars : -1; |
||
611 | nrchars++; |
||
612 | continue; |
||
613 | case 'n': |
||
614 | if (flags & FL_SHORT) |
||
615 | *va_arg(ap, short *) = (short) nrchars; |
||
616 | else if (flags & FL_LONG) |
||
617 | *va_arg(ap, long *) = (long) nrchars; |
||
618 | else |
||
619 | *va_arg(ap, int *) = (int) nrchars; |
||
620 | continue; |
||
621 | case 's': |
||
622 | s1 = va_arg(ap, char *); |
||
623 | if (s1 == NULL) |
||
624 | s1 = "(null)"; |
||
625 | s = s1; |
||
626 | while (precision || !(flags & FL_PRECSPEC)) { |
||
627 | if (*s == '\0') |
||
628 | break; |
||
629 | s++; |
||
630 | precision--; |
||
631 | } |
||
632 | break; |
||
633 | case 'p': |
||
634 | set_pointer(flags); |
||
635 | /* fallthrough */ |
||
636 | case 'b': |
||
637 | case 'o': |
||
638 | case 'u': |
||
639 | case 'x': |
||
640 | case 'X': |
||
641 | if (!(flags & FL_PRECSPEC)) precision = 1; |
||
642 | else if (c != 'p') flags &= ~FL_ZEROFILL; |
||
643 | s = o_print(&ap, flags, s, c, precision, 0); |
||
644 | break; |
||
645 | case 'd': |
||
646 | case 'i': |
||
647 | flags |= FL_SIGNEDCONV; |
||
648 | if (!(flags & FL_PRECSPEC)) precision = 1; |
||
649 | else flags &= ~FL_ZEROFILL; |
||
650 | s = o_print(&ap, flags, s, c, precision, 1); |
||
651 | break; |
||
652 | case 'c': |
||
653 | *s++ = va_arg(ap, int); |
||
654 | break; |
||
655 | |||
656 | case 'G': |
||
657 | case 'g': |
||
658 | if ((flags & FL_PRECSPEC) && (precision == 0)) |
||
659 | precision = 1; |
||
660 | case 'f': |
||
661 | case 'E': |
||
662 | case 'e': |
||
663 | if (!(flags & FL_PRECSPEC)) |
||
664 | precision = 6; |
||
665 | |||
666 | if (precision >= sizeof(buf)) |
||
667 | precision = sizeof(buf) - 1; |
||
668 | |||
669 | flags |= FL_SIGNEDCONV; |
||
670 | s = _f_print(&ap, flags, s, c, precision); |
||
671 | break; |
||
672 | case 'r': |
||
673 | ap = va_arg(ap, va_list); |
||
674 | fmt = va_arg(ap, char *); |
||
675 | continue; |
||
676 | } |
||
677 | zfill = ' '; |
||
678 | if (flags & FL_ZEROFILL) zfill = '0'; |
||
679 | j = s - s1; |
||
680 | |||
681 | /* between_fill is true under the following conditions: |
||
682 | * 1- the fill character is '0' |
||
683 | * and |
||
684 | * 2a- the number is of the form 0x... or 0X... |
||
685 | * or |
||
686 | * 2b- the number contains a sign or space |
||
687 | */ |
||
688 | between_fill = 0; |
||
689 | if ((flags & FL_ZEROFILL) |
||
690 | && (((c == 'x' || c == 'X') && (flags & FL_ALT) && j > 1) |
||
691 | || (c == 'p') |
||
692 | || ((flags & FL_SIGNEDCONV) |
||
693 | && ( *s1 == '+' || *s1 == '-' || *s1 == ' ')))) |
||
694 | between_fill++; |
||
695 | |||
696 | if ((i = width - j) > 0) |
||
697 | if (!(flags & FL_LJUST)) { /* right justify */ |
||
698 | nrchars += i; |
||
699 | if (between_fill) { |
||
700 | if (flags & FL_SIGNEDCONV) { |
||
701 | j--; nrchars++; |
||
702 | if (putc(*s1++, stream) == EOF) |
||
703 | return nrchars ? -nrchars : -1; |
||
704 | } else { |
||
705 | j -= 2; nrchars += 2; |
||
706 | if ((putc(*s1++, stream) == EOF) |
||
707 | || (putc(*s1++, stream) == EOF)) |
||
708 | return nrchars ? -nrchars : -1; |
||
709 | } |
||
710 | } |
||
711 | do { |
||
712 | if (putc(zfill, stream) == EOF) |
||
713 | return nrchars ? -nrchars : -1; |
||
714 | } while (--i); |
||
715 | } |
||
716 | |||
717 | nrchars += j; |
||
718 | while (--j >= 0) { |
||
719 | if (putc(*s1++, stream) == EOF) |
||
720 | return nrchars ? -nrchars : -1; |
||
721 | } |
||
722 | |||
723 | if (i > 0) nrchars += i; |
||
724 | while (--i >= 0) |
||
725 | if (putc(zfill, stream) == EOF) |
||
726 | return nrchars ? -nrchars : -1; |
||
727 | } |
||
728 | return nrchars; |
||
729 | } |
||
730 | |||
731 | int |
||
732 | vsnprintf(char *s, size_t n, const char *format, va_list arg) |
||
733 | { |
||
734 | int retval; |
||
735 | __str tmp_stream; |
||
736 | |||
737 | //tmp_stream._buf = (unsigned char *) s; |
||
738 | tmp_stream._ptr = (unsigned char *) s; |
||
739 | tmp_stream._count = n-1; |
||
740 | |||
741 | retval = _doprnt(format, arg, &tmp_stream); |
||
742 | tmp_stream._count = 1; |
||
743 | putc('\0',&tmp_stream); |
||
744 | |||
745 | return retval; |
||
746 | } |
||
747 | |||
748 | int |
||
749 | vsprintf(char *s, const char *format, va_list arg) |
||
750 | { |
||
751 | return vsnprintf(s, INT_MAX, format, arg); |
||
752 | }>>=>=>=>=>>=>>>=>0>0) |
||
753 | |||
754 | |||
755 |