Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / printf.c
1 /*
2  * Acess2 C Library
3  * - By John Hodge (thePowersGang)
4  *
5  * scanf.c
6  * - *scanf family of functions
7  */
8 #include "lib.h"
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <ctype.h>      // toupper
13 #include <assert.h>     // assert() 
14
15 // Quick booleans
16 typedef char    BOOL;
17 #define TRUE    1
18 #define FALSE   0
19
20 // === TYPES ===
21 typedef void    (*printf_puts_t)(void *h, const char *s, size_t len);
22 enum eFPN {
23         FPN_STD,
24         FPN_SCI,
25         FPN_SHORTEST,
26 };
27
28 // === PROTOTYPES ===
29 void    itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned);
30 size_t  _printf_itoa(printf_puts_t puts_cb, void *puts_h, uint64_t num,
31         size_t base, int bUpper,
32         int bSigned, char SignChar, int Precision,
33         int PadLength, char PadChar, int bPadRight);
34 size_t  _printf_ftoa_hex(printf_puts_t puts_cb, void *puts_h, long double num, int Precision, int bForcePoint, int bForceSign, int bCapitals);
35 size_t  _printf_ftoa(printf_puts_t puts_cb, void *puts_h, long double num, size_t Base, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals);
36
37 // === CODE ===
38 /**
39  * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)
40  * \brief Prints a formatted string to a buffer
41  * \param buf   Pointer - Destination Buffer
42  * \param format        String - Format String
43  * \param args  VarArgs List - Arguments
44  */
45 EXPORT int _vcprintf_int(printf_puts_t puts_cb, void *puts_h, const char *format, va_list args)
46 {
47          int    c, minSize, precision, len;
48         size_t  pos = 0;
49         char    *p;
50         uint64_t        arg;
51         long double     arg_f;
52 //      char    cPositiveChar;
53         BOOL    bLongLong, bLong, bJustifyLeft, bAltForm;
54         char    cNumPad, cPlus;
55
56         #define _addchar(ch) do { \
57                 char _ch = ch; \
58                 puts_cb(puts_h, &_ch, 1); \
59                 pos ++; \
60         } while(0)
61
62         while((c = *format++) != 0)
63         {
64                 // Non-control character
65                 if (c != '%') {
66                         const char      *start = format-1;
67                         while( (c = *format) != 0 && c != '%' )
68                                 format ++;
69                         puts_cb(puts_h, start, format - start);
70                         pos += format - start;
71                         continue;
72                 }
73                 
74                 // Control Character
75                 c = *format++;
76                 if(c == '%') {  // Literal %
77                         _addchar('%');
78                         continue;
79                 }
80                 
81                 bAltForm = 0;
82                 cNumPad = ' ';
83                 bJustifyLeft = 0;
84                 cPlus = '\0';
85                 bLong = 0;
86                 bLongLong = 0;
87                 minSize = 0;
88                 precision = -1;
89                 
90                 // - Flags
91                 do
92                 {
93                         // Alternate form (0<oct>, 0x<hex>, 123.)
94                         if(c == '#') {
95                                 bAltForm = 1;
96                         }
97                         // Padding with '0'
98                         else if(c == '0') {
99                                 cNumPad = '0';
100                         }
101                         // Pad on left
102                         else if(c == '-') {
103                                 bJustifyLeft = 1;
104                         }
105                         // Include space for positive sign
106                         else if(c == ' ') {
107                                 cPlus = ' ';
108                         }
109                         // Always include sign
110                         else if(c == '+') {
111                                 cPlus = '+';
112                         }
113                         else
114                                 break;
115                 }
116                 while( (c = *format++) );
117                 
118                 // Padding length
119                 if( c == '*' ) {
120                         // Variable length
121                         minSize = va_arg(args, size_t);
122                         c = *format++;
123                 }
124                 else if('1' <= c && c <= '9')
125                 {
126                         minSize = 0;
127                         while('0' <= c && c <= '9')
128                         {
129                                 minSize *= 10;
130                                 minSize += c - '0';
131                                 c = *format++;
132                         }
133                 }
134
135                 // Precision
136                 if(c == '.') {
137                         c = *format++;
138                         if(c == '*') {
139                                 precision = va_arg(args, size_t);
140                                 c = *format++;
141                         }
142                         else if('1' <= c && c <= '9')
143                         {
144                                 precision = 0;
145                                 while('0' <= c && c <= '9')
146                                 {
147                                         precision *= 10;
148                                         precision += c - '0';
149                                         c = *format++;
150                                 }
151                         }
152                 }
153         
154                 // Check for long long
155                 if(c == 'l')
156                 {
157                         bLong = 1;
158                         c = *format++;
159                         if(c == 'l') {
160                                 bLongLong = 1;
161                                 c = *format++;
162                         }
163                 }
164                 
165                 // Get Type
166                 switch( c )
167                 {
168                 // Signed Integer
169                 case 'd':
170                 case 'i':
171                         // Get Argument
172                         arg = bLongLong ? va_arg(args, int64_t) : va_arg(args, int32_t);
173                         if( arg == 0 && precision == 0 )
174                                 break;
175                         pos += _printf_itoa(puts_cb, puts_h, arg, 10, FALSE,
176                                 TRUE, cPlus, precision, minSize, cNumPad, bJustifyLeft);
177                         break;
178                 
179                 // Unsigned Integer
180                 case 'u':
181                         arg = bLongLong ? va_arg(args, int64_t) : va_arg(args, int32_t);
182                         pos += _printf_itoa(puts_cb, puts_h, arg, 10, FALSE,
183                                 FALSE, '\0', precision, minSize, cNumPad, bJustifyLeft);
184                         break;
185                 
186                 // Pointer
187                 case 'p':
188                         _addchar('*');
189                         _addchar('0');
190                         _addchar('x');
191                         arg = va_arg(args, intptr_t);
192                         pos += _printf_itoa(puts_cb, puts_h, arg, 16, FALSE,
193                                 FALSE, '\0', sizeof(intptr_t)*2, 0,'\0',FALSE);
194                         break;
195                 // Unsigned Hexadecimal
196                 case 'X':
197                 case 'x':
198                         if(bAltForm) {
199                                 _addchar('0');
200                                 _addchar(c);
201                         }
202                         arg = bLongLong ? va_arg(args, uint64_t) : va_arg(args, uint32_t);
203                         pos += _printf_itoa(puts_cb, puts_h, arg, 16, c=='X',
204                                 FALSE, '\0', precision, minSize,cNumPad,bJustifyLeft);
205                         break;
206                 
207                 // Unsigned Octal
208                 case 'o':
209                         if(bAltForm) {
210                                 _addchar('0');
211                         }
212                         arg = bLongLong ? va_arg(args, int64_t) : va_arg(args, int32_t);
213                         pos += _printf_itoa(puts_cb, puts_h, arg, 8, FALSE,
214                                 FALSE, '\0', precision, minSize,cNumPad,bJustifyLeft);
215                         break;
216                 
217                 // Unsigned binary
218                 case 'b':
219                         if(bAltForm) {
220                                 _addchar('0');
221                                 _addchar('b');
222                         }
223                         arg = bLongLong ? va_arg(args, int64_t) : va_arg(args, int32_t);
224                         pos += _printf_itoa(puts_cb, puts_h, arg, 2, FALSE,
225                                 FALSE, '\0', precision, minSize,cNumPad,bJustifyLeft);
226                         break;
227
228                 // Standard float
229                 case 'f':
230                 case 'F':
231                         arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
232                         pos += _printf_ftoa(puts_cb, puts_h, arg_f, 10, FPN_STD,
233                                 precision, 0, bJustifyLeft, c == 'F');
234                         break;
235                 // Scientific Float
236                 case 'e':
237                 case 'E':
238                         arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
239                         pos += _printf_ftoa(puts_cb, puts_h, arg_f, 10, FPN_SCI,
240                                 precision, 0, bJustifyLeft, c == 'E');
241                         break;
242                 // Scientific Float
243                 case 'g':
244                 case 'G':
245                         arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
246                         pos += _printf_ftoa(puts_cb, puts_h, arg_f, 10, FPN_SHORTEST,
247                                 precision, 0, bJustifyLeft, c == 'G');
248                         break;
249                 // Hexadecimal Scientific
250                 case 'a':
251                 case 'A':
252                         arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
253                         pos += _printf_ftoa_hex(puts_cb, puts_h, arg_f, precision, 0, bJustifyLeft, c == 'A');
254                         break;
255
256                 // String
257                 case 's':
258                         p = va_arg(args, char*);
259                         if(!p)  p = "(null)";
260                         //_SysDebug("vsnprintf: p = '%s'", p);
261                         if(precision >= 0)
262                                 len = strnlen(p, precision);
263                         else
264                                 len = strlen(p);
265                         if(!bJustifyLeft)
266                                 while(minSize-- > len)  _addchar(' ');
267                         puts_cb(puts_h, p, len); pos += len;
268                         if(bJustifyLeft)
269                                 while(minSize-- > len)  _addchar(' ');
270                         break;
271
272                 // Unknown, just treat it as a character
273                 default:
274                         arg = va_arg(args, uint32_t);
275                         _addchar(arg);
276                         break;
277                 }
278         }
279         #undef _addchar
280         
281         return pos;
282 }
283
284 struct s_sprintf_info {
285         char    *dest;
286         size_t  ofs;
287         size_t  maxlen;
288 };
289
290 void _vsnprintf_puts(void *h, const char *str, size_t len)
291 {
292         struct s_sprintf_info   *info = h;
293         while( info->ofs < info->maxlen && len -- )
294                 info->dest[info->ofs++] = *str++;
295 }
296
297 EXPORT int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list __args)
298 {
299         struct s_sprintf_info   info = {__s, 0, __maxlen};
300         int ret;
301         ret = _vcprintf_int(_vsnprintf_puts, &info, __format, __args);
302         _vsnprintf_puts(&info, "", 1);
303         return ret;
304 }
305
306 EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)
307 {
308          int    ret;
309         va_list args;
310         va_start(args, format);
311         ret = vsnprintf((char*)buf, maxlen, (char*)format, args);
312         va_end(args);
313         return ret;
314 }
315
316
317 EXPORT int vsprintf(char * __s, const char *__format, va_list __args)
318 {
319         return vsnprintf(__s, 0x7FFFFFFF, __format, __args);
320 }
321 EXPORT int sprintf(char *buf, const char *format, ...)
322 {
323          int    ret;
324         va_list args;
325         va_start(args, format);
326         ret = vsprintf((char*)buf, (char*)format, args);
327         va_end(args);
328         return ret;
329 }
330
331 void _vfprintf_puts(void *h, const char *str, size_t len)
332 {
333         fwrite(str, len, 1, h);
334 }
335
336 EXPORT int vfprintf(FILE *__fp, const char *__format, va_list __args)
337 {
338         return _vcprintf_int(_vfprintf_puts, __fp, __format, __args);
339 }
340
341 EXPORT int fprintf(FILE *fp, const char *format, ...)
342 {
343         va_list args;
344          int    ret;
345         
346         // Get Size
347         va_start(args, format);
348         ret = vfprintf(fp, (char*)format, args);
349         va_end(args);
350         
351         return ret;
352 }
353
354 EXPORT int vprintf(const char *__format, va_list __args)
355 {
356         return vfprintf(stdout, __format, __args);
357 }
358
359 EXPORT int printf(const char *format, ...)
360 {
361         va_list args;
362          int    ret;
363         
364         // Get final size
365         va_start(args, format);
366         ret = vprintf(format, args);
367         va_end(args);
368         
369         // Return
370         return ret;
371 }
372
373 void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)
374 {
375         struct s_sprintf_info   info = {buf, 0, 1024};
376         if(!buf)        return;
377         _printf_itoa(_vsnprintf_puts, &info, num, base, FALSE, bSigned, '\0', 0, minLength, pad, FALSE);
378         buf[info.ofs] = '\0';
379 }
380
381 const char cDIGITS[] = "0123456789abcdef";
382 const char cUDIGITS[] = "0123456789ABCDEF";
383 /**
384  * \brief Convert an integer into a character string
385  * \param buf   Destination Buffer
386  * \param num   Number to convert
387  * \param base  Base-n number output
388  * \param minLength     Minimum length of output
389  * \param pad   Padding used to ensure minLength
390  * \param bSigned       Signed number output?
391  */
392 size_t _printf_itoa(printf_puts_t puts_cb, void *puts_h, uint64_t num,
393         size_t base, int bUpper,
394         int bSigned, char SignChar, int Precision,
395         int PadLength, char PadChar, int bPadRight)
396 {
397         char    tmpBuf[64+1];
398          int    pos = sizeof(tmpBuf);
399         size_t  ret = 0;
400          int    sign_is_neg = 0;
401         const char *map = bUpper ? cUDIGITS : cDIGITS;
402
403         if(base > 16 || base < 2) {
404                 return 0;
405         }
406         
407         if(bSigned && (int64_t)num < 0)
408         {
409                 num = -(int64_t)num;
410                 sign_is_neg = 1;
411         }
412         
413         // Encode into string
414         while(num > base-1) {
415                 tmpBuf[--pos] = map[ num % base ];
416                 num = (uint64_t) num / (uint64_t)base;          // Shift {number} right 1 digit
417         }
418         tmpBuf[--pos] = map[ num % base ];              // Most significant digit of {number}
419
420         // TODO: This assertion may not be valid
421         assert(Precision <= (int)sizeof(tmpBuf));
422         Precision -= sizeof(tmpBuf)-pos + (sign_is_neg || SignChar != '\0');
423         while( Precision-- > 0 )
424                 tmpBuf[--pos] = '0';
425
426         // Sign 
427         if(sign_is_neg)
428                 tmpBuf[--pos] = '-';    // Negative sign character
429         else if(SignChar)
430                 tmpBuf[--pos] = SignChar;       // positive sign character
431         else {
432         }
433         
434         // length of number, minus the sign character
435         size_t len = sizeof(tmpBuf)-pos;
436         PadLength -= len;
437         if( !bPadRight )
438         {
439                 while(PadLength-- > 0)
440                         puts_cb(puts_h, &PadChar, 1), ret ++;
441         }
442         
443         puts_cb(puts_h, tmpBuf+pos, len);
444         ret += len;
445
446         if( bPadRight )
447         {
448                 while(PadLength-- > 0)
449                         puts_cb(puts_h, &PadChar, 1), ret ++;
450         }
451         
452         return ret;
453 }
454
455 int expand_double(double num, uint64_t *Significand, int16_t *Exponent, int *SignIsNeg)
456 {
457         // IEEE 754 binary64
458         #if 0
459         {
460                 uint64_t test_exp = 0xC000000000000000;
461                 double test_value = -2.0f;
462                 assert( *((uint64_t*)&test_value) == test_exp );
463         }
464         #endif
465         
466         const uint64_t  *bit_rep = (void*)&num;
467         
468         *SignIsNeg = *bit_rep >> 63;
469         *Exponent = ((*bit_rep >> 52) & 0x7FF) - 1023;
470         *Significand = (*bit_rep & ((1ULL << 52)-1)) << (64-52);
471
472 //      printf("%llx %i %i %llx\n", *bit_rep, (int)*SignIsNeg, (int)*Exponent, *Significand);
473
474         // Subnormals
475         if( *Exponent == -0x3FF && *Significand != 0 )
476                 return 1;
477         // Infinity
478         if( *Exponent == 0x400 && *Significand == 0)
479                 return 2;
480         // NaNs
481         if( *Exponent == 0x400 && *Significand != 0)
482                 return 3;
483
484         return 0;
485 }
486
487 /**
488  * Internal function
489  * \return Remainder
490  */
491 double _longdiv(double num, double den, int *quot)
492 {
493         assert(num >= 0);
494         assert(den > 0);
495 //      printf("%llu / %llu\n", (long long int)num, (long long int)den);
496         
497         *quot = 0;
498         assert(num < den*10);
499         while(num >= den)
500         {
501                 num -= den;
502                 (*quot) ++;
503                 assert( *quot < 10 );
504         }
505 //      printf(" %i\n", *quot);
506         return num;
507 }
508
509 size_t _printf_ftoa_hex(printf_puts_t puts_cb, void *puts_h, long double num, int Precision, int bForcePoint, int bForceSign, int bCapitals)
510 {
511         uint64_t        significand;
512         int16_t exponent;
513          int    signisneg;
514          int    rv;
515         size_t  ret = 0;
516
517         #define _putch(_ch) do{\
518                 char __ch = (bCapitals ? toupper(_ch) : _ch);\
519                 puts_cb(puts_h, &__ch, 1); \
520                 ret ++;\
521         }while(0)
522
523         if( Precision == -1 )
524                 Precision = (64-4)/4;
525
526         rv = expand_double(num, &significand, &exponent, &signisneg);
527         switch(rv)
528         {
529         // 0: No errors, nothing special
530         case 0:
531                 break;
532         // 1: Subnormals
533         case 1:
534                 // TODO: Subnormal = 0?
535                 break;
536         // 2: Infinity
537         case 2:
538                 puts_cb(puts_h, "inf", 3);
539                 return 3;
540         case 3:
541                 puts_cb(puts_h, "NaN", 3);
542                 return 3;
543         }
544         
545         // int  exp_ofs = exponent % 4;
546         // int  exp_16 = exponent - exp_ofs;
547         //uint8_t       whole = (1 << exp_ofs) | ((significand >> (64-3)) >> exp_ofs);
548         //significand <<= 3 - exp_ofs;
549         uint8_t whole = (rv != 1) ? 1 : 0;
550         
551         if( signisneg )
552                 _putch('-');
553         else if( bForceSign )
554                 _putch('+');
555         else {
556         }
557         _putch('0');
558         _putch('x');
559         _putch(cDIGITS[whole]);
560         if( significand || bForcePoint )
561                 _putch('.');
562         // Fractional
563         while( significand && Precision -- )
564         {
565                 uint8_t val = significand >> (64-4);
566                 _putch(cDIGITS[val]);
567                 significand <<= 4;
568         }
569         _putch('p');
570         //ret += _printf_itoa(puts_cb, puts_h, exp_16, 16, bCapitals, TRUE, '+', 0, 0, '\0', 0);
571         ret += _printf_itoa(puts_cb, puts_h, exponent, 10, bCapitals, TRUE, '+', 0, 0, '\0', 0);
572         
573         #undef _putch
574         return ret;
575 }
576
577 #if 0
578 size_t _printf_itoa_fixed(printf_putch_t putch_cb, void *putch_h, uint64_t num, size_t Base)
579 {
580         uint64_t        den;
581         size_t  ret = 0;
582
583         den = 1ULL << (64-1);
584         
585         while( den )
586         {
587                 putch_cb(putch_h, cDIGITS[num / den]);
588                 ret ++;
589                 num %= den;
590                 den /= Base;
591         }
592
593         return ret;
594 }
595
596 size_t _printf_ftoa_dec(printf_putch_t putch_cb, void *putch_h, long double num, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
597 {
598         size_t  ret = 0;
599          int    i;
600
601         #define _putch(_ch) do{\
602                 putch_cb(putch_h, bCapitals ? toupper(_ch) : _ch), ret++;\
603         }while(0)
604         
605         uint64_t        significand;
606          int16_t        exponent;
607          int    signisneg;
608          int    rv = expand_double(num, &significand, &exponent, &signisneg);
609         switch(rv)
610         {
611         // 0: No errors, nothing special
612         case 0:
613                 break;
614         // 1: Subnormals
615         case 1:
616                 // TODO: Subnormal = 0?
617                 break;
618         // 2: Infinity
619         case 2:
620                 _putch('i');
621                 _putch('n');
622                 _putch('f');
623                 return 3;
624         case 3:
625                 _putch('N');
626                 _putch('a');
627                 _putch('N');
628                 return 3;
629         }
630
631         uint64_t        whole, part;
632          int    pre_zeros, post_zeros;
633
634         #define XXX     0
635         if( Notation == FPN_SCI )
636         {
637         }
638         else if( exponent < 0 )
639         {
640                 whole = 0;
641                 part = XXX;
642                 pre_zeros = 0;
643                 post_zeros = XXX;
644         }
645         else if( exponent >= 64 )
646         {
647                 part = 0;
648                 whole = XXX;
649                 pre_zeros = XXX;
650                 post_zeros = 0;
651         }
652         else
653         {
654                 // Split into fixed point
655                 whole = (1 << exponent) | (significand >> (64-exponent));
656                 part = significand << exponent;
657                 pre_zeros = 0;
658                 post_zeros = 0;
659         }
660
661         
662         // Whole portion
663         ret += _printf_itoa(putch_cb, putch_h, whole, 10, FALSE, FALSE, '\0', 0, 0, '\0', FALSE);
664         for(i = pre_zeros; i --; )      _putch('0');
665         // TODO: Conditional point
666         _putch('-');
667         for(i = post_zeros; i--; )      _putch('0');
668         ret += _printf_itoa_fixed(putch_cb, putch_h, part, 10);
669         
670         #undef _putch
671
672         return 0;
673 }
674 #endif
675
676 size_t _printf_ftoa(printf_puts_t puts_cb, void *puts_h, long double num, size_t Base, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
677 {
678         uint64_t        significand;
679         int16_t exponent;
680          int    signisneg;
681          int    rv, i;
682         size_t  ret = 0;
683
684         #define _putch(_ch) do{\
685                 char __ch = (bCapitals ? toupper(_ch) : _ch);\
686                 puts_cb(puts_h, &__ch, 1); \
687                 ret ++;\
688         }while(0)
689
690         if( Base <= 1 || Base > 16 )
691                 return 0;
692
693         rv = expand_double(num, &significand, &exponent, &signisneg);
694         switch(rv)
695         {
696         // 0: No errors, nothing special
697         case 0:
698                 break;
699         // 1: Subnormals
700         case 1:
701                 // TODO: Subnormal = 0?
702                 break;
703         // 2: Infinity
704         case 2:
705                 _putch('i');
706                 _putch('n');
707                 _putch('f');
708                 return 3;
709         case 3:
710                 _putch('N');
711                 _putch('a');
712                 _putch('N');
713                 return 3;
714         }
715
716         // - Used as 0/1 bools in arithmatic later on
717         bForcePoint = !!bForcePoint;
718         bForceSign = !!bForceSign;
719
720         // Apply default to precision
721         if( Precision == -1 )
722                 Precision = 6;
723
724         if( num < 0 )
725                 num = -num;
726
727         // Select optimum type
728         if( Notation == FPN_SHORTEST )
729         {
730                 //TODO:
731                 //int   first_set_sig = BSL(significand);
732                 // bSign+log10(num)+1+precision vs. bSign+1+1+precision+1+1+log10(exponent)
733                  int    log10_num = exponent * 301 / 1000;      // log_10(2) = 0.30102999566...
734                  int    log10_exp10 = 2;
735                  int    sci_len = (signisneg || bForceSign) + 2 + (Precision-1) + 2 + log10_exp10;
736                  int    std_whole_len = (log10_num > 0 ? log10_num : 1);
737                  int    std_len = (signisneg || bForceSign) + std_whole_len + 1 + (Precision-std_whole_len);
738                 if( sci_len > std_len ) {
739                         Precision -= std_whole_len;
740                         Notation = FPN_STD;
741                 }
742                 else {
743                         Precision -= 1;
744                         Notation = FPN_SCI;
745                 }
746         }
747
748         double precision_max = 1;
749         for(i = Precision; i--; )
750                 precision_max /= Base;
751
752         // Determine scientific's exponent and starting denominator
753         double den = 1;
754          int    sci_exponent = 0;
755         if( Notation == FPN_SCI )
756         {
757                 if( num < 1 )
758                 {
759                         while(num < 1)
760                         {
761                                 num *= Base;
762                                 sci_exponent ++;
763                         }
764                 }
765                 else if( num >= Base )
766                 {
767                         while(num >= Base)
768                         {
769                                 num /= Base;
770                                 sci_exponent ++;
771                         }
772                 }
773                 else
774                 {
775                         // no exponent
776                 }
777                 den = 1;
778         }
779         else if( num != 0.0 )
780         {
781                 while( den <= num )
782                         den *= Base;
783                 den /= Base;
784         }
785
786         // Leading sign
787         if( signisneg )
788                 _putch('-');
789         else if( bForceSign )
790                 _putch('+');
791         else {
792         }
793         
794         num += precision_max/10 * 4.999;
795
796          int    value;
797         // Whole section
798         do
799         {
800                 num = _longdiv(num, den, &value);
801                 _putch(cDIGITS[value]);
802                 den /= Base;
803         } while( den >= 1 );
804
805         // Decimal point (if needed/forced)     
806         if( Precision > 0 || bForcePoint )
807                 _putch('.');
808         // Decimal section
809         for(i = Precision; i--; )
810         {
811                 num = _longdiv(num, den, &value);
812                 _putch(cDIGITS[value]);
813                 den /= Base;
814         }
815
816         if( Notation == FPN_SCI )
817         {
818                 if( Base == 16 )
819                         _putch('p');
820                 else
821                         _putch('e');
822                 ret += _printf_itoa(puts_cb, puts_h, sci_exponent, Base, FALSE, TRUE, '+', 3, 0, '\0', FALSE);
823         }       
824
825         #undef _putch
826
827         return ret;
828 }

UCC git Repository :: git.ucc.asn.au