Subversion Repositories Kolibri OS

Rev

Rev 6424 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
647 andrew_pro 1
/*
2
        function for format output to the string
6424 siemargl 3
 
4
Siemargl update formats as http://www.cplusplus.com/reference/cstdio/printf/, no wchar though
5
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html  is used too
6
%g explain https://support.microsoft.com/en-us/kb/43392
7
 
8
todo:
9
-fix precision in %g
6425 siemargl 10
-%u printed as signed, %x, %o also is promoted to long long
11
// FAIL 0x0FFFF7A7E as %x - signed long promotes sign, need %llx or %Lx and type conversion
6424 siemargl 12
-%a
13
-%n nothing printed
14
-%17.18f digits maximum format
6425 siemargl 15
-use %C as w_char L'x' (non standard extension)
16
-radix point always '.', no LOCALEs
647 andrew_pro 17
*/
18
 
6424 siemargl 19
 
647 andrew_pro 20
#include 
21
#include 
6424 siemargl 22
#include 
647 andrew_pro 23
#include 
6424 siemargl 24
#include 
647 andrew_pro 25
 
6424 siemargl 26
enum flags_t
647 andrew_pro 27
{
6424 siemargl 28
        flag_unsigned   = 0x02,
29
        flag_register   = 0x04,
30
        flag_plus       = 0x08,
31
        flag_left_just  = 0x10,
32
        flag_lead_zeros = 0x20,
33
        flag_space_plus = 0x40,
34
        flag_hash_sign  = 0x80,
35
        flag_point      = 0x100
36
};
6425 siemargl 37
int formatted_double_to_string(long double number, int format1, int format2, char *s, int flags);
38
int formatted_double_to_string_scientific(long double number, int format1, int format2, char *s, int flags);
39
int formatted_long_to_string(long long number, int format1, int prec, char *s, int flags);
40
int formatted_hex_to_string(unsigned long long number, int fmt1, int prec, char *s, int flags);
41
int formatted_octa_to_string(unsigned long long number, int fmt1, int prec, char *s, int flags);
647 andrew_pro 42
 
6425 siemargl 43
 
44
int formatted_double_special(long double number, char *s)
45
// return 0 if no special values: NAN, INF. -0.0 ignored
46
// http://steve.hollasch.net/cgindex/coding/ieeefloat.html
47
{
48
    struct IEEExp {
49
        unsigned manl:32;
50
        unsigned manh:32;
51
        unsigned exp:15;
52
        unsigned sign:1;
53
    } *ip = (struct IEEExp *)&number;
54
 
55
    if (ip->exp != 0x7fff) return 0;
56
 
57
    if (ip->manh == 0x80000000 && ip->manl == 0) // Inf
58
    {
59
        if(ip->sign)
60
            strcpy(s, "-INF");
61
        else
62
            strcpy(s, "+INF");
63
    } else
64
    if (ip->manh & ~0x7fffffff)
65
        strcpy(s, "QNaN");
66
    else
67
        strcpy(s, "SNaN");
68
 
69
    return 4;
70
}
71
 
72
int copy_and_align(char *dest, int width, char *src, int src_len, char sign, int flags)
73
// alingn number in buffer, put sign and fills additional places
74
// flags used only flag_left_just and flag_lead_zeros
75
// sign can be zero, 0, x, X, space, +, -
76
{
77
    int     rc = 0, sign_len;
78
    char    fill;
79
 
80
    fill = (flags & flag_lead_zeros) ? '0' : ' ';
81
    if(sign == 'x' || sign == 'X')
82
    {
83
        sign_len = 2;
84
    } else
85
    if (sign)
86
        sign_len = 1;
87
    else
88
        sign_len = 0;
89
 
90
    if ((flags & flag_left_just) || (src_len + sign_len >= width))   // left justify or no room
91
    {
92
        if (sign)
93
        {
94
            if(sign == 'x' || sign == 'X')
95
            {
96
                dest[0] = '0';
97
                dest[1] = sign;
98
                memcpy(dest + 2, src, src_len);
99
                rc = src_len + 2;
100
            } else
101
            { // single sign
102
                dest[0] = sign;
103
                memcpy(dest + 1, src, src_len);
104
                rc = src_len + 1;
105
            }
106
        } else
107
        {
108
            memcpy(dest, src, src_len);
109
            rc = src_len;
110
        }
111
        if (rc < width)
112
        {
113
            memset(dest + rc, fill, width - rc);
114
            rc = width;
115
        }
116
    } else // right justify and fill
117
    {
118
        rc = width;
119
        memcpy(dest + width - src_len, src, src_len);
120
        memset(dest, fill, width - src_len);
121
        if (flags & flag_lead_zeros)
122
        {
123
            if(sign == 'x' || sign == 'X')
124
            {
125
                dest[0] = '0';
126
                dest[1] = sign;
127
            } else
128
            if (sign) dest[0] = sign;
129
        } else
130
        {
131
            if(sign == 'x' || sign == 'X')
132
            {
133
                dest[width - src_len - 2] = '0';
134
                dest[width - src_len - 1] = sign;
135
            } else
136
            if (sign) dest[width - src_len - 1] = sign;
137
        }
138
    }
139
    return rc;
140
}
141
 
6424 siemargl 142
int formatted_double_to_string_scientific(long double number, int format1, int format2, char *s, int flags)
143
{
6425 siemargl 144
    long double     norm_digit;
145
    long            mul = 0;
146
    char            sign = 0;
147
    char            buf[50];
148
    int     len;
149
 
150
    if((flags & flag_point) == 0) format2 = 6;  // default prec if no point spec
151
 
152
    len = formatted_double_special(number, buf);
153
    if (len == 0)
154
    {
155
        if (number < 0) { sign = '-'; norm_digit = -number; }
156
        else
157
        {
158
            norm_digit = number;
159
            if (flags & flag_plus) sign = '+';  else
160
            if (flags & flag_space_plus) sign = ' ';
161
        }
162
        // normalize
163
        while (norm_digit < 1.0) { norm_digit *= 10; mul--; }
164
        while (norm_digit >= 10.0) { norm_digit /= 10; mul++; }
165
 
166
        len = formatted_double_to_string(norm_digit, 0, format2, buf, flags & ~(flag_plus | flag_space_plus));
167
 
168
        if (flags & flag_register)
169
            buf[len++] = 'E';
170
        else
171
            buf[len++] = 'e';
172
 
173
        len += formatted_long_to_string(mul, 0, 3, buf + len, flag_plus | flag_lead_zeros);
174
    }
175
    else
176
        flags &= ~flag_lead_zeros; // no need for INF, NAN
177
 
178
    len = copy_and_align(s, format1, buf, len, sign, flags);
179
 
180
    return len;
6424 siemargl 181
}
647 andrew_pro 182
 
6424 siemargl 183
int formatted_double_to_string(long double number, int format1, int format2, char *s, int flags)
184
{
6425 siemargl 185
    long double	nafter, beforpointdigit;
186
    long long	intdigit, mul;
187
    int	    div;
188
    int     i;
189
    char    sign = 0;
190
    int     fmt1;
191
    int     fmt2;
192
    char    buf[100], *pbuf = buf;
193
    char    buf_low[50], *pbuf_lo = buf_low;
647 andrew_pro 194
 
6425 siemargl 195
    if((flags & flag_point) == 0) format2 = 6;  // default prec if no point spec
647 andrew_pro 196
 
6425 siemargl 197
    i = formatted_double_special(number, buf);
198
    if (i == 0)
199
    {
200
        if (number < 0) {sign = '-'; number = -number; }
6424 siemargl 201
        else
202
        {
6425 siemargl 203
            if (flags & flag_plus) sign = '+';  else
204
            if (flags & flag_space_plus) sign = ' ';
6424 siemargl 205
        }
647 andrew_pro 206
 
6424 siemargl 207
        fmt1 = 1;
208
        fmt2 = format2;
209
        if (fmt2 > 18) fmt2 = 18; //maximum size of long long type
647 andrew_pro 210
 
6424 siemargl 211
        beforpointdigit = floor(number + 0.00000000000001);
212
        nafter = number - beforpointdigit;
213
 
214
        //print part of number before point
215
        mul = 1;
216
        for(i = 0; i < sizeof buf - 1; i++)
217
        {
218
            mul *= 10;
219
            if ((beforpointdigit/mul) < 1.0) { fmt1 = i + 1; break; }
647 andrew_pro 220
        }
6424 siemargl 221
        if (i == sizeof buf - 1 || fmt1 > 17)
222
        {
223
            strcpy(s, "[too big number for %f, %a]");
224
            return strlen(s);
225
        }
647 andrew_pro 226
 
6424 siemargl 227
        mul /= 10;
228
        while(mul > 1)
229
        {
230
            div = beforpointdigit / mul;
231
            *pbuf++ = (char)div + '0';
232
            beforpointdigit = beforpointdigit - div * mul;
233
            mul /= 10;
234
        }
235
        *pbuf++=(char)beforpointdigit + '0';
647 andrew_pro 236
 
6424 siemargl 237
        //print part of number after point
238
        mul = 1;
239
        for(i = 0; i < fmt2; i++)
240
        {
241
            nafter = nafter*10;
242
            mul *= 10;
243
        }
647 andrew_pro 244
 
6424 siemargl 245
        intdigit = roundl(nafter);
647 andrew_pro 246
 
6424 siemargl 247
        mul /= 10;
248
        for(i = 0; i < fmt2 - 1; i++)
249
        {
250
                div = intdigit / mul;
251
                *pbuf_lo++=(char)div + '0';
252
                intdigit = intdigit - div * mul;
253
                mul /= 10;
254
                if (mul == 1) break;
255
        }
256
        *pbuf_lo++ = (char)intdigit + '0';
647 andrew_pro 257
 
6425 siemargl 258
        // form full number
6424 siemargl 259
        if (roundl(nafter) != 0 || fmt2 != 0)
260
        {
6425 siemargl 261
            *pbuf++ = '.';
262
            memcpy(pbuf, buf_low, pbuf_lo - buf_low);  pbuf += pbuf_lo - buf_low;
6424 siemargl 263
        } else if (flags & flag_hash_sign)
6425 siemargl 264
            *pbuf++ = '.';
265
    }
266
    else
267
    {
268
        flags &= ~flag_lead_zeros; // no need for INF, NAN
269
        pbuf += i;
270
    }
647 andrew_pro 271
 
6425 siemargl 272
    return copy_and_align(s, format1, buf, pbuf - buf, sign, flags);
647 andrew_pro 273
}
274
 
6424 siemargl 275
int formatted_long_to_string(long long number, int format1, int prec, char *s, int flags)
647 andrew_pro 276
{
6424 siemargl 277
        int         i;
278
        int         fmt;
6425 siemargl 279
        char        sign = 0;
6424 siemargl 280
        long long   digit;
281
        long long   mul;
282
        int         div;
283
        char        buf[100], *pbuf = buf;
647 andrew_pro 284
 
6424 siemargl 285
        if (number == -9223372036854775807LL - 1)  // overflow all our math, cant minus this
286
        {
6425 siemargl 287
            strcpy(s, "-9223372036854775808");
288
            return strlen(s);
6424 siemargl 289
        }
647 andrew_pro 290
 
6424 siemargl 291
        if (flags & flag_point) flags &= ~flag_lead_zeros;  // conflicting flags
647 andrew_pro 292
 
6425 siemargl 293
        if (number < 0) {sign = '-'; number = -number; }
6424 siemargl 294
        else
295
        {
6425 siemargl 296
            if (flags & flag_plus) sign = '+';  else
297
            if (flags & flag_space_plus) sign = ' ';
6424 siemargl 298
        }
647 andrew_pro 299
 
6424 siemargl 300
        digit = number;
647 andrew_pro 301
 
6424 siemargl 302
        mul = (digit < 0) ? -1 : 1;
647 andrew_pro 303
 
6424 siemargl 304
        for(i = 0; i < sizeof buf - 2; i++)
305
        {
306
            if (digit / mul < 10) { fmt = i + 1; break; }
307
            mul *= 10;
308
        }
309
 
6425 siemargl 310
        // add leading zeros by prec
6424 siemargl 311
        for(i = 0; i < prec - fmt; i++) *pbuf++ = '0';
312
 
313
        for(i = 0; i < fmt - 1; i++)
314
        {
315
            div = digit / mul;
316
            *pbuf++ = (char)div + '0';
317
            digit = digit - div * mul;
318
            mul /= 10;
319
            if (mul == 1 || mul == -1) break;
320
        }
321
        *pbuf++ = (char)digit + '0';
322
 
6425 siemargl 323
        return copy_and_align(s, format1, buf, pbuf - buf, sign, flags);
647 andrew_pro 324
}
325
 
6425 siemargl 326
int formatted_hex_to_string(unsigned long long number, int fmt1, int prec, char *s, int flags)
647 andrew_pro 327
{
6425 siemargl 328
    unsigned long long digit, mul;
329
    int             i, div, fmt;
330
    char            xdigs_lower[16]="0123456789abcdef";
331
    char            xdigs_upper[16]="0123456789ABCDEF";
332
    char            buf[50], *pbuf = buf, sign;
647 andrew_pro 333
 
6425 siemargl 334
    if (number == -9223372036854775807LL - 1)  // overflow all our math, cant minus this
335
    {
336
        strcpy(buf, "FFFFFFFFFFFFFFFF");
337
        pbuf += strlen(buf);
338
    }
339
    else
340
    {
341
        if (flags & flag_point) flags &= ~flag_lead_zeros;  // conflicting flags
647 andrew_pro 342
 
6425 siemargl 343
        digit = number;
647 andrew_pro 344
 
6425 siemargl 345
        mul = (digit < 0) ? -1 : 1;
346
 
347
        for(i = 0; i < sizeof buf - 2; i++)
647 andrew_pro 348
        {
6425 siemargl 349
            if (digit / mul < 16) { fmt = i + 1; break; }
350
            mul <<= 4;
647 andrew_pro 351
        }
352
 
6425 siemargl 353
        // add leading zeros by prec
354
        for(i = 0; i < prec - fmt; i++) *pbuf++ = '0';
647 andrew_pro 355
 
6425 siemargl 356
        for(i = 0; i < fmt - 1; i++)
647 andrew_pro 357
        {
6425 siemargl 358
            div = digit / mul;
359
            *pbuf++ = (flags & flag_register) ? xdigs_upper[div] : xdigs_lower[div];
360
            digit = digit - div * mul;
361
            mul >>= 4;
362
            if (mul == 1 || mul == -1) break;
647 andrew_pro 363
        }
6425 siemargl 364
        *pbuf++ = (flags & flag_register) ? xdigs_upper[digit] : xdigs_lower[digit];
365
    }
647 andrew_pro 366
 
6425 siemargl 367
    sign = 0;
368
    if(flags & flag_hash_sign)
369
        sign = (flags & flag_register) ? 'X' : 'x';
370
 
371
    return copy_and_align(s, fmt1, buf, pbuf - buf, sign, flags);
647 andrew_pro 372
}
373
 
6425 siemargl 374
int formatted_octa_to_string(unsigned long long number, int fmt1, int prec, char *s, int flags)
647 andrew_pro 375
{
6425 siemargl 376
    unsigned long long digit, mul;
377
    int             i, div, fmt;
378
    char            xdigs_lower[16]="01234567";
379
    char            buf[50], *pbuf = buf;
647 andrew_pro 380
 
6425 siemargl 381
    if (number == -9223372036854775807LL - 1)  // overflow all our math, cant minus this
382
    {
383
        strcpy(buf, "1777777777777777777777");
384
        pbuf += strlen(buf);
385
    }
386
    else
387
    {
388
        if (flags & flag_point) flags &= ~flag_lead_zeros;  // conflicting flags
647 andrew_pro 389
 
6425 siemargl 390
        digit = number;
647 andrew_pro 391
 
6425 siemargl 392
        mul = (digit < 0) ? -1 : 1;
393
 
394
        for(i = 0; i < sizeof buf - 2; i++)
647 andrew_pro 395
        {
6425 siemargl 396
            if (digit / mul < 8) { fmt = i + 1; break; }
397
            mul <<= 3;
647 andrew_pro 398
        }
399
 
6425 siemargl 400
        // add leading zeros by prec
401
        for(i = 0; i < prec - fmt; i++) *pbuf++ = '0';
647 andrew_pro 402
 
6425 siemargl 403
        for(i = 0; i < fmt - 1; i++)
647 andrew_pro 404
        {
6425 siemargl 405
            div = digit / mul;
406
            *pbuf++ = xdigs_lower[div & 0x7];
407
            digit = digit - div * mul;
408
            mul >>= 3;
409
            if (mul == 1 || mul == -1) break;
647 andrew_pro 410
        }
6425 siemargl 411
        *pbuf++ = xdigs_lower[digit];
412
    }
647 andrew_pro 413
 
6425 siemargl 414
    return copy_and_align(s, fmt1, buf, pbuf - buf, (flags & flag_hash_sign) ? '0' : 0, flags);
647 andrew_pro 415
}
416
 
6424 siemargl 417
//int vsnprintf (char * s, size_t n, const char * format, va_list arg );
418
int format_print(char *dest, size_t maxlen, const char *fmt0, va_list argp)
647 andrew_pro 419
{
6424 siemargl 420
    int                     i;
421
    int                     length;
422
    int                     fmt1, fmt2;  // width, precision
423
    size_t                  pos, posc;
424
    long	long	        intdigit;
425
    long	double          doubledigit;
426
    const   char            *fmt, *fmtc;  // first point to %, fmtc points to specifier
427
    char                    *s; // pointer to current dest char
428
    char                    *str;
429
    char                    buf[200];  // buffer for current argument value print representation
430
    int                     format_flag;
431
    int                     flag_long;        // 2 = long double or long long int or wchar
432
    int                    *point_to_n = NULL;
433
    int                     flags;  // parsed flags
647 andrew_pro 434
 
6424 siemargl 435
    fmt = fmt0;
436
    s = dest;
437
    pos = 0;
438
    while(pos < maxlen)
439
    {
440
        if (*fmt != '%')  // usual char
647 andrew_pro 441
        {
6424 siemargl 442
            if ('\0' == (*s++ = *fmt++)) break;
443
            pos++;
444
            continue;
445
        }
647 andrew_pro 446
 
6424 siemargl 447
        if (*(fmt + 1) == '%') // %%
448
        {
449
                *s++ = '%'; pos++;
450
                fmt += 2;
451
                continue;
452
        }
453
        //checking to containg format in the string
454
        fmtc = fmt;
455
        posc = pos;
647 andrew_pro 456
 
6424 siemargl 457
        flags = 0;
458
        format_flag = 0;
459
        flag_long = 0;  // 2 = long double or long long int or wchar
647 andrew_pro 460
 
6424 siemargl 461
        while(*fmtc != '\0' && !format_flag)    // searching end of format
462
        {
463
                fmtc++; posc++;
464
                switch( *fmtc )
465
                {
466
                case 'a':
467
                    format_flag = 1;
468
                    flags |= flag_unsigned;
469
                    break;
470
                case 'A':
471
                    format_flag = 1;
472
                    flags |= flag_unsigned | flag_register;
473
                    break;
474
                case 'c':   case 'd':   case 'i':   case 'e':   case 'f':   case 'g':   case 's':   case 'n':
475
                    format_flag = 1;
476
                    break;
477
                case 'E':   case 'F':   case 'G':
478
                    format_flag = 1;
479
                    flags |= flag_register;
480
                    break;
481
                case 'l':
482
                    flag_long  = flag_long ? 2 : 1;  // ll.eq.L
483
                    break;
484
                case 'L':
485
                    flag_long = 2;
486
                    break;
487
                case 'o':   case 'u':   case 'x':   case 'p':
488
                    format_flag = 1;
489
                    flags |= flag_unsigned;
490
                    break;
491
                case 'X':   case 'P':
492
                    format_flag = 1;
493
                    flags |= flag_unsigned | flag_register;
494
                    break;
495
                case '+':
496
                    flags |= flag_plus;
497
                    break;
498
                case '-':
499
                    flags |= flag_left_just;
500
                    break;
501
                case ' ': // space
502
                    flags |= flag_space_plus;
503
                    break;
504
                case '#':
505
                    flags |= flag_hash_sign;
506
                    break;
507
                case '*':   case '.':  // just skip
508
                    break;
509
                default:
510
                    if(isdigit(*fmtc))  break;
511
                    strncpy(dest, "print format error - in % invalid char found", maxlen);
512
                    return -1;  // non format char found - user error
513
                }
514
        }
647 andrew_pro 515
 
6424 siemargl 516
        if (format_flag == 0)
517
        {
518
            strncpy(dest, "print format error - % without format specifier", maxlen);
519
            return -1;  // format char not found - user error
520
        }
647 andrew_pro 521
 
6424 siemargl 522
        fmt1 = 0;
523
        fmt2 = 0;
524
        if (posc - pos > 1)  // try to read width, precision
525
        {
526
            fmt++;
527
            for(i = pos + 1; i < posc; i++)
528
            {
529
                switch(*fmt)
530
                {
531
                case '0':
532
                    if(fmt1 == 0 && (flags & flag_point) == 0)    flags |= flag_lead_zeros;
533
                case '1':   case '2':   case '3':   case '4':
534
                case '5':   case '6':   case '7':   case '8':   case '9':
535
                    if ((flags & flag_point) == 0)
536
                        fmt1 = fmt1 * 10 + (*fmt -'0');
537
                    else
538
                        fmt2 = fmt2 * 10 + (*fmt -'0');
539
                    break;
540
                case '*':
541
                    if (flag_point == 0)
542
                        fmt1 = va_arg(argp, int);
543
                    else
544
                        fmt2 = va_arg(argp, int);
545
                    break;
546
                case '.':
547
                    flags |= flag_point;
548
                    break;
549
                case 'l':   case 'L':   case '+':   // valid chars - skip
550
                case '-':   case ' ':   case '#':
551
                    break;
552
                default: // must be error
553
                    strncpy(dest, "print format error - %width.precision", maxlen);
554
                    return -1;  // format char not found - user error
555
                }
556
                fmt++;
557
            }
558
        }
647 andrew_pro 559
 
6424 siemargl 560
        // do real work - format arguments values
561
        length = 0;
562
        switch(*fmtc)
563
        {
564
        case 'n':
565
            point_to_n = va_arg(argp, int*);
566
            break;
567
        case 'c':
568
            if (pos + 1 <= maxlen)
569
            {
570
                buf[0] = (char)va_arg(argp, int);
571
                length = 1;
572
            }
573
            break;
574
        case 's':   // special case - without buf
575
            str = va_arg(argp, char*);
576
            length = strlen(str);
577
            if ((flags & flag_point) && (length > fmt2)) length = fmt2;  // cut by precision
578
            if (pos + length > maxlen) length = maxlen - pos;
579
            memcpy(s, str ,length);
580
            s += length;
581
            pos += length;
582
            break;
583
        case 'd':   case 'i':   case 'u':   case 'U':
584
            if (flag_long == 0) intdigit = va_arg(argp, int); else
585
            if (flag_long == 1) intdigit = va_arg(argp, long); else
586
            if (flag_long == 2) intdigit = va_arg(argp, long long);
587
            length = formatted_long_to_string(intdigit, fmt1, fmt2, buf, flags);
588
            break;
589
        case 'o':
590
            if (flag_long == 0) intdigit = va_arg(argp, int); else
591
            if (flag_long == 1) intdigit = va_arg(argp, long); else
592
            if (flag_long == 2) intdigit = va_arg(argp, long long);
6425 siemargl 593
            length = formatted_octa_to_string(intdigit, fmt1, fmt2, buf, flags);
6424 siemargl 594
            break;
595
        case 'p':   case 'P':   case 'x':   case 'X':
596
            if (flag_long == 0) intdigit = va_arg(argp, int); else
597
            if (flag_long == 1) intdigit = va_arg(argp, long); else
598
            if (flag_long == 2) intdigit = va_arg(argp, long long);
6425 siemargl 599
            length=formatted_hex_to_string(intdigit, fmt1, fmt2, buf, flags);
6424 siemargl 600
            break;
601
        case 'a':   case 'A':   case 'f':   case 'F':
602
            if (flag_long <= 1) doubledigit = va_arg(argp, double); else
603
            if (flag_long == 2) doubledigit = va_arg(argp, long double);
604
            length = formatted_double_to_string(doubledigit, fmt1, fmt2, buf, flags);
605
            break;
606
        case 'e':   case 'E':
607
            if (flag_long <= 1) doubledigit = va_arg(argp, double); else
608
            if (flag_long == 2) doubledigit = va_arg(argp, long double);
609
            length = formatted_double_to_string_scientific(doubledigit, fmt1, fmt2, buf, flags);
610
            break;
611
        case 'g':   case 'G':
612
 //prec special case, this is just workaround
613
            if (flag_long <= 1) doubledigit = va_arg(argp, double); else
614
            if (flag_long == 2) doubledigit = va_arg(argp, long double);
615
            length = formatted_double_to_string(doubledigit, fmt1, fmt2, buf, flags);
616
            i = formatted_double_to_string_scientific(doubledigit, fmt1, fmt2, buf + sizeof buf / 2, flags);
617
            if(length > i)
618
            {
619
                memcpy(buf, buf + sizeof buf / 2, i);
620
                length = i;
621
            }
622
            break;
623
        }
624
        if (*fmtc != 's' && length > 0) // skip multiple string copying
625
        {
626
            if (pos + length > maxlen)  length = maxlen - pos;
627
            memcpy(s, buf, length);
628
            s += length;
629
            pos += length;
630
        }
631
        fmt = fmtc + 1;
632
    }
647 andrew_pro 633
 
6424 siemargl 634
    if (point_to_n) *point_to_n = pos;
635
    return(pos);
647 andrew_pro 636
}