Subversion Repositories HelenOS-historic

Rev

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

Rev 1010 Rev 1073
Line 30... Line 30...
30
#include <stdio.h>
30
#include <stdio.h>
31
#include <unistd.h>
31
#include <unistd.h>
32
#include <io/io.h>
32
#include <io/io.h>
33
#include <stdarg.h>
33
#include <stdarg.h>
34
 
34
 
35
#define __PRINTF_FLAG_PREFIX 0x00000001
35
#define __PRINTF_FLAG_PREFIX        0x00000001  /* show prefixes 0x or 0*/
36
#define __PRINTF_FLAG_SIGNED 0x00000002
36
#define __PRINTF_FLAG_SIGNED        0x00000002  /* signed / unsigned number */
37
 
-
 
38
static char digits[] = "0123456789abcdef";  /**< Hexadecimal characters */
37
#define __PRINTF_FLAG_ZEROPADDED    0x00000004  /* print leading zeroes */
39
 
-
 
40
/** Print hexadecimal digits
38
#define __PRINTF_FLAG_LEFTALIGNED   0x00000010  /* align to left */
41
 *
-
 
42
 * Print fixed count of hexadecimal digits from
39
#define __PRINTF_FLAG_SHOWPLUS      0x00000020  /* always show + sign */
43
 * the number num. The digits are printed in
40
#define __PRINTF_FLAG_SPACESIGN     0x00000040  /* print space instead of plus */
44
 * natural left-to-right order starting with
41
#define __PRINTF_FLAG_BIGCHARS      0x00000080  /* show big characters */
45
 * the width-th digit.
42
#define __PRINTF_FLAG_NEGATIVE      0x00000100  /* number has - sign */
46
 *
43
 
47
 * @param num   Number containing digits.
44
#define PRINT_NUMBER_BUFFER_SIZE    (64+5)      /* Buffer big enought for 64 bit number
48
 * @param width Count of digits to print.
45
                             * printed in base 2, sign, prefix and
49
 *
-
 
50
 */
-
 
51
static int print_fixed_hex(const uint64_t num, const int width, uint64_t flags)
46
                             * 0 to terminate string.. (last one is only for better testing
52
{
-
 
53
    int i;
-
 
54
    char buf[18]; /* 16 bytes for number + 2 for optionaly prefix */
47
                             * end of buffer by zero-filling subroutine)
55
    char *bptr;
48
                             */
56
   
-
 
57
    bptr = buf;
49
typedef enum {
58
   
-
 
59
    if (flags & __PRINTF_FLAG_PREFIX) {
50
    PrintfQualifierByte = 0,
60
        buf[0] = '0';
51
    PrintfQualifierShort,
61
        buf[1] = 'x';
52
    PrintfQualifierInt,
62
        bptr += 2;
53
    PrintfQualifierLong,
63
    }
-
 
64
 
-
 
65
    for (i = width*8 - 4; i >= 0; i -= 4)
54
    PrintfQualifierLongLong,
66
        *bptr++ = digits[(num>>i) & 0xf];
55
    PrintfQualifierSizeT,
67
    *bptr = '\0';
56
    PrintfQualifierPointer
68
   
-
 
69
    return putstr(buf);
57
} qualifier_t;
70
}
-
 
71
 
58
 
-
 
59
static char digits_small[] = "0123456789abcdef";    /* Small hexadecimal characters */
-
 
60
static char digits_big[] = "0123456789ABCDEF";  /* Big hexadecimal characters */
72
 
61
 
73
/** Print number in given base
62
/** Print number in given base
74
 *
63
 *
75
 * Print significant digits of a number in given
64
 * Print significant digits of a number in given
76
 * base.
65
 * base.
77
 *
66
 *
78
 * @param num  Number to print.
67
 * @param num  Number to print.
-
 
68
 * @param size not used, in future releases will be replaced with precision and width params
79
 * @param base Base to print the number in (should
69
 * @param base Base to print the number in (should
80
 *             be in range 2 .. 16).
70
 *             be in range 2 .. 16).
-
 
71
 * @param flags output modifiers
-
 
72
 * @return number of written characters or EOF
81
 *
73
 *
82
 */
74
 */
83
static int print_number(const unsigned long num, const unsigned int base, uint64_t flags)
75
static int print_number(uint64_t num, size_t size, int base , uint64_t flags)
84
{
76
{
-
 
77
    /* FIXME: This is only first version.
-
 
78
     * Printf does not have support for specification of size
-
 
79
     * and precision, so this function writes with parameters defined by
85
    int val = num;
80
     * their type size.
-
 
81
     */
-
 
82
    char *digits = digits_small;
86
    char d[sizeof(unsigned long)*8+1];  /* this is good enough even for base == 2 */
83
    char d[PRINT_NUMBER_BUFFER_SIZE];   /* this is good enough even for base == 2, prefix and sign */
87
    int i = sizeof(unsigned long)*8-1;
84
    char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
88
   
85
   
-
 
86
    if (flags & __PRINTF_FLAG_BIGCHARS)
89
    /* FIXME: if signed, print sign */
87
        digits = digits_big;   
90
   
88
   
-
 
89
    *ptr-- = 0; /* Put zero at end of string */
-
 
90
 
-
 
91
    if (num == 0) {
-
 
92
        *ptr-- = '0';
-
 
93
    } else {
91
    do {
94
        do {
92
        d[i--] = digits[val % base];
95
            *ptr-- = digits[num % base];
93
    } while (val /= base);
96
        } while (num /= base);
-
 
97
    }
-
 
98
    if (flags & __PRINTF_FLAG_PREFIX) { /*FIXME*/
-
 
99
        switch(base) {
-
 
100
            case 2: /* Binary formating is not standard, but usefull */
-
 
101
                *ptr = 'b';
-
 
102
                if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'B';
-
 
103
                ptr--;
-
 
104
                *ptr-- = '0';
-
 
105
                break;
-
 
106
            case 8:
-
 
107
                *ptr-- = 'o';
-
 
108
                break;
-
 
109
            case 16:
-
 
110
                *ptr = 'x';
-
 
111
                if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'X';
-
 
112
                ptr--;
-
 
113
                *ptr-- = '0';
-
 
114
                break;
-
 
115
        }
-
 
116
    }
94
   
117
   
95
    d[sizeof(unsigned long)*8] = 0;
118
    if (flags & __PRINTF_FLAG_SIGNED) {
-
 
119
        if (flags & __PRINTF_FLAG_NEGATIVE) {
-
 
120
            *ptr-- = '-';
-
 
121
        } else if (flags & __PRINTF_FLAG_SHOWPLUS) {
-
 
122
                *ptr-- = '+';
-
 
123
            } else if (flags & __PRINTF_FLAG_SPACESIGN) {
-
 
124
                    *ptr-- = ' ';
-
 
125
                }
-
 
126
    }
96
 
127
 
-
 
128
    /* Print leading zeroes */
-
 
129
 
-
 
130
    if (flags & __PRINTF_FLAG_LEFTALIGNED) {
-
 
131
        flags &= ~__PRINTF_FLAG_ZEROPADDED;
-
 
132
    }
-
 
133
    if (flags & __PRINTF_FLAG_ZEROPADDED) {
-
 
134
            while (ptr != d ) {
-
 
135
            *ptr-- = '0';
-
 
136
        }
-
 
137
    }
-
 
138
   
97
    return putstr(&d[i + 1]);
139
    return putstr(++ptr);
98
}
140
}
99
 
141
 
100
 
142
 
101
 
143
 
102
/** General formatted text print
144
/** General formatted text print
Line 154... Line 196...
154
 *
196
 *
155
 * @param fmt Formatting NULL terminated string.
197
 * @param fmt Formatting NULL terminated string.
156
 */
198
 */
157
int printf(const char *fmt, ...)
199
int printf(const char *fmt, ...)
158
{
200
{
-
 
201
    int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */
159
    int i = 0, j = 0;
202
    int end;
160
    int counter, retval;
203
    int counter; /* counter of printed characters */
-
 
204
    int retval; /* used to store return values from called functions */
161
    va_list ap;
205
    va_list ap;
162
    char c;
206
    char c;
163
 
-
 
-
 
207
    qualifier_t qualifier;  /* type of argument */
-
 
208
    int base;   /* base in which will be parameter (numbers only) printed */
-
 
209
    uint64_t number; /* argument value */
-
 
210
    size_t  size; /* byte size of integer parameter */
164
    uint64_t flags;
211
    uint64_t flags;
165
   
212
   
166
    counter = 0;
213
    counter = 0;
167
    va_start(ap, fmt);
214
    va_start(ap, fmt);
168
 
215
 
Line 174... Line 221...
174
                if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */
221
                if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */
175
                    return -counter;
222
                    return -counter;
176
                }
223
                }
177
                counter += retval;
224
                counter += retval;
178
            }
225
            }
179
           
226
       
180
            j = ++i;
227
            j = i;
181
           
-
 
182
            /* parse modifiers */
228
            /* parse modifiers */
183
            flags = 0;
229
            flags = 0;
-
 
230
            end = 0;
-
 
231
           
-
 
232
            do {
-
 
233
                ++i;
184
            /*switch (c = fmt[i]) {
234
                switch (c = fmt[i]) {
-
 
235
                    case '#': flags |= __PRINTF_FLAG_PREFIX; break;
-
 
236
                    case '-': flags |= __PRINTF_FLAG_LEFTALIGNED; break;
-
 
237
                    case '+': flags |= __PRINTF_FLAG_SHOWPLUS; break;
-
 
238
                    case ' ': flags |= __PRINTF_FLAG_SPACESIGN; break;
-
 
239
                    case '0': flags |= __PRINTF_FLAG_ZEROPADDED; break;
-
 
240
                    default: end = 1;
-
 
241
                }; 
-
 
242
               
-
 
243
            } while (end == 0);
-
 
244
            /* TODO: width & '*' operator */
-
 
245
            /* TODO: precision and '*' operator */ 
-
 
246
 
-
 
247
            switch (fmt[i++]) {
-
 
248
                case 'h':   /* char or short */
-
 
249
                    qualifier = PrintfQualifierShort;
-
 
250
                    if (fmt[i] == 'h') {
-
 
251
                        i++;
-
 
252
                        qualifier = PrintfQualifierByte;
-
 
253
                    }
-
 
254
                    break;
-
 
255
                case 'l':   /* long or long long*/
-
 
256
                    qualifier = PrintfQualifierLong;
-
 
257
                    if (fmt[i] == 'l') {
-
 
258
                        i++;
-
 
259
                        qualifier = PrintfQualifierLongLong;
-
 
260
                    }
-
 
261
                    break;
185
                case '-':  
262
                case 'z':   /* size_t */
-
 
263
                    qualifier = PrintfQualifierSizeT;
-
 
264
                    break;
-
 
265
                default:
-
 
266
                    qualifier = PrintfQualifierInt; /* default type */
-
 
267
                    --i;
186
            }  
268
            }  
187
            */
269
           
188
            switch (c = fmt[i]) {
270
            base = 10;
189
 
271
 
190
                /* percentile itself */
272
            switch (c = fmt[i]) {
191
                case '%':
-
 
192
                    --j;    /* soon will be incremented back */
-
 
193
                    break;
-
 
194
 
273
 
195
                /*
274
                /*
196
                * String and character conversions.
275
                * String and character conversions.
197
                */
276
                */
198
                case 's':
277
                case 's':
199
                    if ((retval = putstr(va_arg(ap, char*))) == EOF) {
278
                    if ((retval = putstr(va_arg(ap, char*))) == EOF) {
200
                        return -counter;
279
                        return -counter;
201
                    };
280
                    };
202
                   
281
                   
203
                    counter += retval;
282
                    counter += retval;
204
                    break;
283
                    j = i + 1;
-
 
284
                    goto next_char;
205
                case 'c':
285
                case 'c':
206
                    c = va_arg(ap, unsigned long);
286
                    c = va_arg(ap, unsigned long);
207
                    if ((retval = putnchars(&c, sizeof(char))) == EOF) {
287
                    if ((retval = putnchars(&c, sizeof(char))) == EOF) {
208
                        return -counter;
288
                        return -counter;
209
                    };
289
                    };
210
                   
290
                   
211
                    counter += retval;
291
                    counter += retval;
212
                    break;
292
                    j = i + 1;
-
 
293
                    goto next_char;
213
 
294
 
214
                /*
295
                /*
215
                * Hexadecimal conversions with fixed width.
296
                 * Integer values
216
                */
297
                */
217
                case 'P':
298
                case 'P': /* pointer */
218
                        flags |= __PRINTF_FLAG_PREFIX;
299
                        flags |= __PRINTF_FLAG_BIGCHARS;
219
                case 'p':
300
                case 'p':
220
                        if ((retval = print_fixed_hex(va_arg(ap, unsigned long), sizeof(unsigned long), flags)) == EOF ) {
-
 
221
                        return -counter;
301
                    flags |= __PRINTF_FLAG_PREFIX;
222
                    };
302
                    base = 16;
223
 
-
 
224
                    counter += retval;
303
                    qualifier = PrintfQualifierPointer;
225
                    break;
304
                    break; 
226
                case 'Q':
305
                case 'b':
227
                        flags |= __PRINTF_FLAG_PREFIX;
-
 
228
                case 'q':
306
                    base = 2;
229
                        if ((retval = print_fixed_hex(va_arg(ap, uint64_t), sizeof(uint64_t), flags)) == EOF ) {
-
 
230
                        return -counter;
-
 
231
                    };
-
 
232
 
-
 
233
                    counter += retval;
-
 
234
                    break;
307
                    break;
235
                case 'L':
-
 
236
                        flags |= __PRINTF_FLAG_PREFIX;
-
 
237
                case 'l':
308
                case 'o':
238
                        if ((retval = print_fixed_hex(va_arg(ap, unsigned long), sizeof(uint32_t), flags)) == EOF ) {
-
 
239
                        return -counter;
-
 
240
                    };
-
 
241
 
-
 
242
                    counter += retval;
-
 
243
                    break;
-
 
244
                case 'W':
-
 
245
                        flags |= __PRINTF_FLAG_PREFIX;
-
 
246
                case 'w':
309
                    base = 8;
247
                        if ((retval = print_fixed_hex(va_arg(ap, unsigned long), sizeof(uint16_t), flags)) == EOF ) {
-
 
248
                        return -counter;
-
 
249
                    };
-
 
250
 
-
 
251
                    counter += retval;
-
 
252
                    break;
310
                    break;
253
                case 'B':
-
 
254
                        flags |= __PRINTF_FLAG_PREFIX;
-
 
255
                case 'b':
-
 
256
                        if ((retval = print_fixed_hex(va_arg(ap, unsigned long), sizeof(uint8_t), flags)) == EOF ) {
-
 
257
                        return -counter;
-
 
258
                    };
-
 
259
 
-
 
260
                    counter += retval;
-
 
261
                    break;
-
 
262
                /*
-
 
263
                * Decimal and hexadecimal conversions.
-
 
264
                */
-
 
265
                case 'd':
311
                case 'd':
266
                case 'i':
312
                case 'i':
267
                        flags |= __PRINTF_FLAG_SIGNED;
313
                    flags |= __PRINTF_FLAG_SIGNED;  
268
                        if ((retval = print_number(va_arg(ap,unsigned long), 10, flags)) == EOF ) {
-
 
269
                        return -counter;
-
 
270
                    };
314
                case 'u':
271
 
-
 
272
                    counter += retval;
-
 
273
                    break;
315
                    break;
274
                case 'X':
316
                case 'X':
275
                        flags |= __PRINTF_FLAG_PREFIX;
317
                    flags |= __PRINTF_FLAG_BIGCHARS;
276
                case 'x':
318
                case 'x':
277
                        if ((retval = print_number(va_arg(ap, unsigned long), 16, flags)) == EOF ) {
-
 
278
                        return -counter;
319
                    base = 16;
279
                    };
320
                    break;
280
 
-
 
281
                    counter += retval;
321
                /* percentile itself */
-
 
322
                case '%':
282
                    break;
323
                    j = i;
-
 
324
                    goto next_char;
283
                /*
325
                /*
284
                * Bad formatting.
326
                * Bad formatting.
285
                */
327
                */
286
                default:
328
                default:
-
 
329
                    /* Unknown format
-
 
330
                     *  now, the j is index of '%' so we will
-
 
331
                     * print whole bad format sequence
-
 
332
                     */
-
 
333
                    goto next_char;    
-
 
334
            }
-
 
335
       
-
 
336
       
-
 
337
        /* Print integers */
-
 
338
            /* print number */
-
 
339
            switch (qualifier) {
-
 
340
                case PrintfQualifierByte:
-
 
341
                    size = sizeof(unsigned char);
-
 
342
                    number = (uint64_t)va_arg(ap, unsigned int);
-
 
343
                    break;
-
 
344
                case PrintfQualifierShort:
-
 
345
                    size = sizeof(unsigned short);
-
 
346
                    number = (uint64_t)va_arg(ap, unsigned int);
-
 
347
                    break;
-
 
348
                case PrintfQualifierInt:
-
 
349
                    size = sizeof(unsigned int);
-
 
350
                    number = (uint64_t)va_arg(ap, unsigned int);
-
 
351
                    break;
-
 
352
                case PrintfQualifierLong:
-
 
353
                    size = sizeof(unsigned long);
-
 
354
                    number = (uint64_t)va_arg(ap, unsigned long);
-
 
355
                    break;
-
 
356
                case PrintfQualifierLongLong:
-
 
357
                    size = sizeof(unsigned long long);
-
 
358
                    number = (uint64_t)va_arg(ap, unsigned long long);
-
 
359
                    break;
-
 
360
                case PrintfQualifierPointer:
-
 
361
                    size = sizeof(void *);
-
 
362
                    number = (uint64_t)(unsigned long)va_arg(ap, void *);
-
 
363
                    break;
-
 
364
                case PrintfQualifierSizeT:
-
 
365
                    size = sizeof(size_t);
-
 
366
                    number = (uint64_t)va_arg(ap, size_t);
-
 
367
                    break;
-
 
368
                default: /* Unknown qualifier */
287
                    return -counter;
369
                    return -counter;
-
 
370
                   
288
            }
371
            }
-
 
372
           
-
 
373
            if (flags & __PRINTF_FLAG_SIGNED) {
-
 
374
                if (number & (0x1 << (size*8 - 1))) {
-
 
375
                    flags |= __PRINTF_FLAG_NEGATIVE;
-
 
376
               
-
 
377
                    if (size == sizeof(uint64_t)) {
-
 
378
                        number = -((int64_t)number);
-
 
379
                    } else {
-
 
380
                        number = ~number;
-
 
381
                        number &= (~((0xFFFFFFFFFFFFFFFFll) <<  (size * 8)));
-
 
382
                        number++;
-
 
383
                    }
-
 
384
                }
-
 
385
            }
-
 
386
 
-
 
387
            if ((retval = print_number(number, size, base, flags)) == EOF ) {
-
 
388
                return -counter;
289
            ++j;
389
            };
-
 
390
 
-
 
391
            counter += retval;
-
 
392
            j = i + 1;
290
        }  
393
        }  
-
 
394
next_char:
-
 
395
           
291
        ++i;
396
        ++i;
292
    }
397
    }
293
   
398
   
294
    if (i > j) {
399
    if (i > j) {
295
        if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */
400
        if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */