Subversion Repositories HelenOS

Rev

Rev 623 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 623 Rev 674
Line 29... Line 29...
29
#include <putchar.h>
29
#include <putchar.h>
30
#include <print.h>
30
#include <print.h>
31
#include <synch/spinlock.h>
31
#include <synch/spinlock.h>
32
#include <arch/arg.h>
32
#include <arch/arg.h>
33
#include <arch/asm.h>
33
#include <arch/asm.h>
34
#include <arch/fmath.h>
-
 
35
 
34
 
36
#include <arch.h>
35
#include <arch.h>
37
 
36
 
38
static char digits[] = "0123456789abcdef";  /**< Hexadecimal characters */
37
static char digits[] = "0123456789abcdef";  /**< Hexadecimal characters */
39
SPINLOCK_INITIALIZE(printflock);        /**< printf spinlock */
38
SPINLOCK_INITIALIZE(printflock);        /**< printf spinlock */
40
 
39
 
41
#define DEFAULT_DOUBLE_PRECISION 16
-
 
42
#define DEFAULT_DOUBLE_BUFFER_SIZE 128
-
 
43
 
-
 
44
 
40
 
45
/** Print NULL terminated string
41
/** Print NULL terminated string
46
 *
42
 *
47
 * Print characters from str using putchar() until
43
 * Print characters from str using putchar() until
48
 * \\0 character is reached.
44
 * \\0 character is reached.
Line 103... Line 99...
103
    d[sizeof(__native)*8] = 0; 
99
    d[sizeof(__native)*8] = 0; 
104
    print_str(&d[i + 1]);
100
    print_str(&d[i + 1]);
105
}
101
}
106
 
102
 
107
 
103
 
108
static void print_double(double num, __u8 modifier, __u16 precision)
-
 
109
{
-
 
110
    double intval,intval2;
-
 
111
    int counter;
-
 
112
    int exponent,exponenttmp;
-
 
113
    unsigned char buf[DEFAULT_DOUBLE_BUFFER_SIZE];
-
 
114
    unsigned long in1,in2; 
-
 
115
   
-
 
116
 
-
 
117
    if (fmath_is_nan(num)) {
-
 
118
        print_str("NaN");
-
 
119
        return;
-
 
120
    }
-
 
121
   
-
 
122
    if (num<0.0) {
-
 
123
        putchar('-');
-
 
124
        num=num*-1.0;
-
 
125
    }
-
 
126
 
-
 
127
 
-
 
128
    if (fmath_is_infinity(num)) {
-
 
129
        print_str("Inf");
-
 
130
        return;
-
 
131
    }
-
 
132
 
-
 
133
    if ((modifier=='E')||(modifier=='e')) {
-
 
134
        intval2=fmath_fint(fmath_get_decimal_exponent(num),&intval);
-
 
135
        exponent=intval;
-
 
136
        if ((intval2<0.0)) exponent--;
-
 
137
        num = num / ((fmath_dpow(10.0,exponent)));
-
 
138
       
-
 
139
        print_double(num,modifier+1,precision); /* modifier+1 = E => F or e => f */
-
 
140
        putchar(modifier);
-
 
141
        if (exponent<0) {
-
 
142
            putchar('-');
-
 
143
            exponent*=-1;
-
 
144
        }
-
 
145
        print_number(exponent,10);
-
 
146
        return;
-
 
147
    }
-
 
148
       
-
 
149
    /* TODO: rounding constant - when we got fraction >= 0.5, we must increment last printed number */
-
 
150
 
-
 
151
    /*
-
 
152
     * Here is a problem with cumulative error while printing big double values -> we will divide
-
 
153
     * the number with a power of 10, print new number with better method for small numbers and
-
 
154
     * then print decimal point at correct position.
-
 
155
     */
-
 
156
   
-
 
157
    fmath_fint(fmath_get_decimal_exponent(num),&intval);
-
 
158
   
-
 
159
    exponent=(intval>0.0?intval:0);
-
 
160
   
-
 
161
    precision+=exponent;
-
 
162
   
-
 
163
    if (exponent>0) num = num / ((fmath_dpow(10.0,exponent)));
-
 
164
       
-
 
165
    num=fmath_fint(num,&intval);
-
 
166
   
-
 
167
    if (precision>0) {
-
 
168
        counter=precision-1;
-
 
169
        if (exponent>0) counter++;
-
 
170
       
-
 
171
        if (counter>=DEFAULT_DOUBLE_BUFFER_SIZE) {
-
 
172
            counter=DEFAULT_DOUBLE_BUFFER_SIZE;
-
 
173
        }
-
 
174
        exponenttmp=exponent;
-
 
175
        while(counter>=0) {
-
 
176
            num *= 10.0;
-
 
177
            num = fmath_fint(num,&intval2);
-
 
178
            buf[counter--]=((int)intval2)+'0';
-
 
179
            exponenttmp--;
-
 
180
            if ((exponenttmp==0)&&(counter>=0)) buf[counter--]='.';
-
 
181
        }
-
 
182
        counter=precision;
-
 
183
        if ((exponent==0)&&(counter<DEFAULT_DOUBLE_BUFFER_SIZE)) buf[counter]='.';
-
 
184
        counter++; 
-
 
185
    } else {
-
 
186
        counter=0; 
-
 
187
    }
-
 
188
   
-
 
189
    in1=intval;
-
 
190
    if (in1==0.0) {
-
 
191
        if (counter<DEFAULT_DOUBLE_BUFFER_SIZE) buf[counter++]='0';
-
 
192
    } else {
-
 
193
        while(( in1>0 )&&(counter<DEFAULT_DOUBLE_BUFFER_SIZE)) {
-
 
194
           
-
 
195
            in2=in1;
-
 
196
            in1/=10;
-
 
197
            buf[counter]=in2-in1*10 + '0';
-
 
198
            counter++;
-
 
199
        }
-
 
200
    }
-
 
201
   
-
 
202
    counter = (counter>=DEFAULT_DOUBLE_BUFFER_SIZE?DEFAULT_DOUBLE_BUFFER_SIZE:counter);
-
 
203
    while (counter>0) {
-
 
204
        putchar(buf[--counter]);
-
 
205
    }
-
 
206
    return;
-
 
207
}
-
 
208
 
-
 
209
 
104
 
210
/** General formatted text print
105
/** General formatted text print
211
 *
106
 *
212
 * Print text formatted according the fmt parameter
107
 * Print text formatted according the fmt parameter
213
 * and variant arguments. Each formatting directive
108
 * and variant arguments. Each formatting directive
Line 259... Line 154...
259
 *
154
 *
260
 * .    The decimal number following period will be treated as precision
155
 * .    The decimal number following period will be treated as precision
261
 *      for printing floating point numbers. One of 'e', 'E', 'f' or 'F'
156
 *      for printing floating point numbers. One of 'e', 'E', 'f' or 'F'
262
 *      must follow.
157
 *      must follow.
263
 *
158
 *
264
 * e    The next variant argument is treated as double precision float
-
 
265
 *      and printed in exponent notation with only one digit before decimal point
-
 
266
 *      in specified precision. The exponent sign is printed as 'e'.
-
 
267
 *
-
 
268
 * E    As with 'e', but the exponent sign is printed as 'E'.
-
 
269
 *
-
 
270
 * f    The next variant argument is treated as double precision float
-
 
271
 *      and printed in decimal notation in specified precision.
-
 
272
 *
-
 
273
 * F    As with 'f'.
-
 
274
 *
-
 
275
 * All other characters from fmt except the formatting directives
159
 * All other characters from fmt except the formatting directives
276
 * are printed in verbatim.
160
 * are printed in verbatim.
277
 *
161
 *
278
 * @param fmt Formatting NULL terminated string.
162
 * @param fmt Formatting NULL terminated string.
279
 */
163
 */
Line 281... Line 165...
281
{
165
{
282
    int irqpri, i = 0;
166
    int irqpri, i = 0;
283
    va_list ap;
167
    va_list ap;
284
    char c;
168
    char c;
285
   
169
   
286
    __u16 precision;
-
 
287
   
-
 
288
    va_start(ap, fmt);
170
    va_start(ap, fmt);
289
 
171
 
290
    irqpri = interrupts_disable();
172
    irqpri = interrupts_disable();
291
    spinlock_lock(&printflock);
173
    spinlock_lock(&printflock);
292
 
174
 
293
    while ((c = fmt[i++])) {
175
    while ((c = fmt[i++])) {
294
        switch (c) {
176
        switch (c) {
295
 
177
 
296
            /* control character */
178
            /* control character */
297
            case '%':
179
            case '%':
298
            precision = DEFAULT_DOUBLE_PRECISION;
-
 
299
            if (fmt[i]=='.') {
-
 
300
                precision=0;
-
 
301
                c=fmt[++i];
-
 
302
                while((c>='0')&&(c<='9')) {
-
 
303
                    precision = precision*10 + c - '0';
-
 
304
                    c=fmt[++i];
-
 
305
                }
-
 
306
            }
-
 
307
           
180
           
308
            switch (c = fmt[i++]) {
181
            switch (c = fmt[i++]) {
309
 
182
 
310
                /* percentile itself */
183
                /* percentile itself */
311
                case '%':
184
                case '%':
Line 352... Line 225...
352
                case 'B':
225
                case 'B':
353
                print_str("0x");
226
                print_str("0x");
354
                case 'b':
227
                case 'b':
355
                    print_fixed_hex(va_arg(ap, __native), INT8);
228
                    print_fixed_hex(va_arg(ap, __native), INT8);
356
                goto loop;
229
                goto loop;
357
 
230
   
358
                /*
-
 
359
                     * Floating point conversions.
-
 
360
                     */
-
 
361
                case 'F':
-
 
362
                    print_double(va_arg(ap, double),'F',precision);
-
 
363
                goto loop;
-
 
364
                   
-
 
365
                case 'f':
-
 
366
                    print_double(va_arg(ap, double),'f',precision);
-
 
367
                goto loop;
-
 
368
               
-
 
369
                case 'E':
-
 
370
                    print_double(va_arg(ap, double),'E',precision);
-
 
371
                goto loop;
-
 
372
                case 'e':
-
 
373
                    print_double(va_arg(ap, double),'e',precision);
-
 
374
                goto loop;
-
 
375
               
-
 
376
                /*
231
                /*
377
                     * Decimal and hexadecimal conversions.
232
                     * Decimal and hexadecimal conversions.
378
                     */
233
                     */
379
                case 'd':
234
                case 'd':
380
                    print_number(va_arg(ap, __native), 10);
235
                    print_number(va_arg(ap, __native), 10);