Subversion Repositories HelenOS-historic

Rev

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

Rev 1199 Rev 1234
Line 25... Line 25...
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
28
 */
29
 
29
 
30
#include <stdio.h>
-
 
31
#include <unistd.h>
30
#include <unistd.h>
32
#include <io/io.h>
31
#include <stdio.h>
33
#include <stdarg.h>
32
#include <io/printf_core.h>
34
#include <ctype.h>
33
#include <ctype.h>
35
#include <string.h>
34
#include <string.h>
36
 
35
 
37
#define __PRINTF_FLAG_PREFIX        0x00000001  /* show prefixes 0x or 0*/
36
#define __PRINTF_FLAG_PREFIX        0x00000001  /* show prefixes 0x or 0*/
38
#define __PRINTF_FLAG_SIGNED        0x00000002  /* signed / unsigned number */
37
#define __PRINTF_FLAG_SIGNED        0x00000002  /* signed / unsigned number */
Line 59... Line 58...
59
} qualifier_t;
58
} qualifier_t;
60
 
59
 
61
static char digits_small[] = "0123456789abcdef";    /* Small hexadecimal characters */
60
static char digits_small[] = "0123456789abcdef";    /* Small hexadecimal characters */
62
static char digits_big[] = "0123456789ABCDEF";  /* Big hexadecimal characters */
61
static char digits_big[] = "0123456789ABCDEF";  /* Big hexadecimal characters */
63
 
62
 
-
 
63
/** Print count chars from buffer without adding newline
-
 
64
 * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
-
 
65
 * @param count
-
 
66
 * @param ps output method and its data
-
 
67
 * @return 0 on success, EOF on fail
-
 
68
 */
-
 
69
static int printf_putnchars(const char * buf, size_t count, struct printf_spec *ps)
-
 
70
{
-
 
71
    if (ps->write((void *)buf, count, ps->data) == count) {
-
 
72
        return 0;
-
 
73
    }
-
 
74
   
-
 
75
    return EOF;
-
 
76
}
-
 
77
 
-
 
78
/** Print string without added newline
-
 
79
 * @param str string to print
-
 
80
 * @param ps write function specification and support data
-
 
81
 * @return 0 on success or EOF on fail
-
 
82
 */
-
 
83
static int printf_putstr(const char * str, struct printf_spec *ps)
-
 
84
{
-
 
85
    size_t count;
-
 
86
   
-
 
87
    if (str == NULL) {
-
 
88
        return printf_putnchars("(NULL)", 6, ps);
-
 
89
    }
-
 
90
 
-
 
91
    for (count = 0; str[count] != 0; count++);
-
 
92
 
-
 
93
    if (ps->write((void *) str, count, ps->data) == count) {
-
 
94
        return 0;
-
 
95
    }
-
 
96
   
-
 
97
    return EOF;
-
 
98
}
-
 
99
 
-
 
100
/** Print one character to output
-
 
101
 * @param c one character
-
 
102
 * @param ps output method
-
 
103
 * @return printed character or EOF
-
 
104
 */
-
 
105
static int printf_putchar(int c, struct printf_spec *ps)
-
 
106
{
-
 
107
    unsigned char ch = c;
-
 
108
   
-
 
109
    if (ps->write((void *) &ch, 1, ps->data) == 1) {
-
 
110
        return c;
-
 
111
    }
-
 
112
   
-
 
113
    return EOF;
-
 
114
}
64
 
115
 
65
/** Print one formatted character
116
/** Print one formatted character
66
 * @param c character to print
117
 * @param c character to print
67
 * @param width
118
 * @param width
68
 * @param flags
119
 * @param flags
69
 * @return number of printed characters or EOF
120
 * @return number of printed characters or EOF
70
 */
121
 */
71
static int print_char(char c, int width, uint64_t flags)
122
static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
72
{
123
{
73
    int counter = 0;
124
    int counter = 0;
74
   
125
   
75
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
126
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
76
        while (--width > 0) {   /* one space is consumed by character itself hence predecrement */
127
        while (--width > 0) {   /* one space is consumed by character itself hence predecrement */
77
            /* FIXME: painful slow */
128
            /* FIXME: painful slow */
78
            putchar(' ');  
129
            printf_putchar(' ', ps);   
79
            ++counter;
130
            ++counter;
80
        }
131
        }
81
    }
132
    }
82
   
133
   
83
    if (putchar(c) == EOF) {
134
    if (printf_putchar(c, ps) == EOF) {
84
        return EOF;
135
        return EOF;
85
    }
136
    }
86
 
137
 
87
    while (--width > 0) { /* one space is consumed by character itself hence predecrement */
138
    while (--width > 0) { /* one space is consumed by character itself hence predecrement */
88
        putchar(' ');
139
        printf_putchar(' ', ps);
89
        ++counter;
140
        ++counter;
90
    }
141
    }
91
   
142
   
92
    return ++counter;
143
    return ++counter;
93
}
144
}
Line 98... Line 149...
98
 * @param precision
149
 * @param precision
99
 * @param flags
150
 * @param flags
100
 * @return number of printed characters or EOF
151
 * @return number of printed characters or EOF
101
 */
152
 */
102
                       
153
                       
103
static int print_string(char *s, int width, int precision, uint64_t flags)
154
static int print_string(char *s, int width, int precision, uint64_t flags, struct printf_spec *ps)
104
{
155
{
105
    int counter = 0;
156
    int counter = 0;
106
    size_t size;
157
    size_t size;
107
 
158
 
108
    if (s == NULL) {
159
    if (s == NULL) {
109
        return putstr("(NULL)");
160
        return printf_putstr("(NULL)", ps);
110
    }
161
    }
111
   
162
   
112
    size = strlen(s);
163
    size = strlen(s);
113
 
164
 
114
    /* print leading spaces */
165
    /* print leading spaces */
Line 118... Line 169...
118
 
169
 
119
    width -= precision;
170
    width -= precision;
120
   
171
   
121
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
172
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
122
        while (width-- > 0) {  
173
        while (width-- > 0) {  
123
            putchar(' ');  
174
            printf_putchar(' ', ps);   
124
            counter++;
175
            counter++;
125
        }
176
        }
126
    }
177
    }
127
 
178
 
128
    while (precision > size) {
179
    while (precision > size) {
129
        precision--;
180
        precision--;
130
        putchar(' ');  
181
        printf_putchar(' ', ps);   
131
        ++counter;
182
        ++counter;
132
    }
183
    }
133
   
184
   
134
    if (putnchars(s, precision) == EOF) {
185
    if (printf_putnchars(s, precision, ps) == EOF) {
135
        return EOF;
186
        return EOF;
136
    }
187
    }
137
 
188
 
138
    counter += precision;
189
    counter += precision;
139
 
190
 
140
    while (width-- > 0) {
191
    while (width-- > 0) {
141
        putchar(' ');  
192
        printf_putchar(' ', ps);   
142
        ++counter;
193
        ++counter;
143
    }
194
    }
144
   
195
   
145
    return ++counter;
196
    return ++counter;
146
}
197
}
Line 158... Line 209...
158
 *             be in range 2 .. 16).
209
 *             be in range 2 .. 16).
159
 * @param flags output modifiers
210
 * @param flags output modifiers
160
 * @return number of written characters or EOF
211
 * @return number of written characters or EOF
161
 *
212
 *
162
 */
213
 */
163
static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags)
214
static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags, struct printf_spec *ps)
164
{
215
{
165
    char *digits = digits_small;
216
    char *digits = digits_small;
166
    char d[PRINT_NUMBER_BUFFER_SIZE];   /* this is good enough even for base == 2, prefix and sign */
217
    char d[PRINT_NUMBER_BUFFER_SIZE];   /* this is good enough even for base == 2, prefix and sign */
167
    char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
218
    char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
-
 
219
    int size = 0; /* size of number with all prefixes and signs */
168
    int size = 0;
220
    int number_size; /* size of plain number */
169
    int written = 0;
221
    int written = 0;
170
    char sgn;
222
    char sgn;
171
   
223
   
172
    if (flags & __PRINTF_FLAG_BIGCHARS)
224
    if (flags & __PRINTF_FLAG_BIGCHARS)
173
        digits = digits_big;   
225
        digits = digits_big;   
Line 181... Line 233...
181
        do {
233
        do {
182
            *ptr-- = digits[num % base];
234
            *ptr-- = digits[num % base];
183
            size++;
235
            size++;
184
        } while (num /= base);
236
        } while (num /= base);
185
    }
237
    }
-
 
238
   
-
 
239
    number_size = size;
186
 
240
 
187
    /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
241
    /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
188
    if (flags & __PRINTF_FLAG_PREFIX) {
242
    if (flags & __PRINTF_FLAG_PREFIX) {
189
        switch(base) {
243
        switch(base) {
190
            case 2: /* Binary formating is not standard, but usefull */
244
            case 2: /* Binary formating is not standard, but usefull */
Line 218... Line 272...
218
    }
272
    }
219
 
273
 
220
    /* if number is leftaligned or precision is specified then zeropadding is ignored */
274
    /* if number is leftaligned or precision is specified then zeropadding is ignored */
221
    if (flags & __PRINTF_FLAG_ZEROPADDED) {
275
    if (flags & __PRINTF_FLAG_ZEROPADDED) {
222
        if ((precision == 0) && (width > size)) {
276
        if ((precision == 0) && (width > size)) {
223
            precision = width - size;
277
            precision = width - size + number_size;
224
        }
278
        }
225
    }
279
    }
226
 
280
 
227
    /* print leading spaces */
281
    /* print leading spaces */
228
    if (size > precision) /* We must print whole number not only a part */
282
    if (number_size > precision) /* We must print whole number not only a part */
229
        precision = size;
283
        precision = number_size;
230
 
284
 
231
    width -= precision;
285
    width -= precision + size - number_size;
232
   
286
   
233
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
287
    if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
234
        while (width-- > 0) {  
288
        while (width-- > 0) {  
235
            putchar(' ');  
289
            printf_putchar(' ', ps);   
236
            written++;
290
            written++;
237
        }
291
        }
238
    }
292
    }
239
   
293
   
240
    /* print sign */
294
    /* print sign */
241
    if (sgn) {
295
    if (sgn) {
242
        putchar(sgn);
296
        printf_putchar(sgn, ps);
243
        written++;
297
        written++;
244
    }
298
    }
245
   
299
   
246
    /* print prefix */
300
    /* print prefix */
247
   
301
   
248
    if (flags & __PRINTF_FLAG_PREFIX) {
302
    if (flags & __PRINTF_FLAG_PREFIX) {
249
        switch(base) {
303
        switch(base) {
250
            case 2: /* Binary formating is not standard, but usefull */
304
            case 2: /* Binary formating is not standard, but usefull */
251
                putchar('0');
305
                printf_putchar('0', ps);
252
                if (flags & __PRINTF_FLAG_BIGCHARS) {
306
                if (flags & __PRINTF_FLAG_BIGCHARS) {
253
                    putchar('B');
307
                    printf_putchar('B', ps);
254
                } else {
308
                } else {
255
                    putchar('b');
309
                    printf_putchar('b', ps);
256
                }
310
                }
257
                written += 2;
311
                written += 2;
258
                break;
312
                break;
259
            case 8:
313
            case 8:
260
                putchar('o');
314
                printf_putchar('o', ps);
261
                written++;
315
                written++;
262
                break;
316
                break;
263
            case 16:
317
            case 16:
264
                putchar('0');
318
                printf_putchar('0', ps);
265
                if (flags & __PRINTF_FLAG_BIGCHARS) {
319
                if (flags & __PRINTF_FLAG_BIGCHARS) {
266
                    putchar('X');
320
                    printf_putchar('X', ps);
267
                } else {
321
                } else {
268
                    putchar('x');
322
                    printf_putchar('x', ps);
269
                }
323
                }
270
                written += 2;
324
                written += 2;
271
                break;
325
                break;
272
        }
326
        }
273
    }
327
    }
274
 
328
 
275
    /* print leading zeroes */
329
    /* print leading zeroes */
276
    precision -= size;
330
    precision -= number_size;
277
    while (precision-- > 0) {  
331
    while (precision-- > 0) {  
278
        putchar('0');  
332
        printf_putchar('0', ps);   
279
        written++;
333
        written++;
280
    }
334
    }
281
 
335
 
282
   
336
   
283
    /* print number itself */
337
    /* print number itself */
284
 
338
 
285
    written += putstr(++ptr);
339
    written += printf_putstr(++ptr, ps);
286
   
340
   
287
    /* print ending spaces */
341
    /* print ending spaces */
288
   
342
   
289
    while (width-- > 0) {  
343
    while (width-- > 0) {  
290
        putchar(' ');  
344
        printf_putchar(' ', ps);   
291
        written++;
345
        written++;
292
    }
346
    }
293
 
347
 
294
    return written;
348
    return written;
295
}
349
}
Line 357... Line 411...
357
 * are printed in verbatim.
411
 * are printed in verbatim.
358
 *
412
 *
359
 * @param fmt Formatting NULL terminated string.
413
 * @param fmt Formatting NULL terminated string.
360
 * @return count of printed characters or negative value on fail.
414
 * @return count of printed characters or negative value on fail.
361
 */
415
 */
362
int printf(const char *fmt, ...)
416
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
363
{
417
{
364
    int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */
418
    int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */
365
    int end;
419
    int end;
366
    int counter; /* counter of printed characters */
420
    int counter; /* counter of printed characters */
367
    int retval; /* used to store return values from called functions */
421
    int retval; /* used to store return values from called functions */
368
    va_list ap;
-
 
369
    char c;
422
    char c;
370
    qualifier_t qualifier;  /* type of argument */
423
    qualifier_t qualifier;  /* type of argument */
371
    int base;   /* base in which will be parameter (numbers only) printed */
424
    int base;   /* base in which will be parameter (numbers only) printed */
372
    uint64_t number; /* argument value */
425
    uint64_t number; /* argument value */
373
    size_t  size; /* byte size of integer parameter */
426
    size_t  size; /* byte size of integer parameter */
374
    int width, precision;
427
    int width, precision;
375
    uint64_t flags;
428
    uint64_t flags;
376
   
429
   
377
    counter = 0;
430
    counter = 0;
378
    va_start(ap, fmt);
-
 
379
   
431
   
380
    while ((c = fmt[i])) {
432
    while ((c = fmt[i])) {
381
        /* control character */
433
        /* control character */
382
        if (c == '%' ) {
434
        if (c == '%' ) {
383
            /* print common characters if any processed */ 
435
            /* print common characters if any processed */ 
384
            if (i > j) {
436
            if (i > j) {
385
                if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */
437
                if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) == EOF) { /* error */
386
                    return -counter;
438
                    return -counter;
387
                }
439
                }
388
                counter += retval;
440
                counter += retval;
389
            }
441
            }
390
       
442
       
Line 476... Line 528...
476
 
528
 
477
                /*
529
                /*
478
                * String and character conversions.
530
                * String and character conversions.
479
                */
531
                */
480
                case 's':
532
                case 's':
481
                    if ((retval = print_string(va_arg(ap, char*), width, precision, flags)) == EOF) {
533
                    if ((retval = print_string(va_arg(ap, char*), width, precision, flags, ps)) == EOF) {
482
                        return -counter;
534
                        return -counter;
483
                    };
535
                    };
484
                   
536
                   
485
                    counter += retval;
537
                    counter += retval;
486
                    j = i + 1;
538
                    j = i + 1;
487
                    goto next_char;
539
                    goto next_char;
488
                case 'c':
540
                case 'c':
489
                    c = va_arg(ap, unsigned int);
541
                    c = va_arg(ap, unsigned int);
490
                    if ((retval = print_char(c, width, flags )) == EOF) {
542
                    if ((retval = print_char(c, width, flags, ps)) == EOF) {
491
                        return -counter;
543
                        return -counter;
492
                    };
544
                    };
493
                   
545
                   
494
                    counter += retval;
546
                    counter += retval;
495
                    j = i + 1;
547
                    j = i + 1;
Line 585... Line 637...
585
                        number++;
637
                        number++;
586
                    }
638
                    }
587
                }
639
                }
588
            }
640
            }
589
 
641
 
590
            if ((retval = print_number(number, width, precision, base, flags)) == EOF ) {
642
            if ((retval = print_number(number, width, precision, base, flags, ps)) == EOF ) {
591
                return -counter;
643
                return -counter;
592
            };
644
            };
593
 
645
 
594
            counter += retval;
646
            counter += retval;
595
            j = i + 1;
647
            j = i + 1;
Line 598... Line 650...
598
           
650
           
599
        ++i;
651
        ++i;
600
    }
652
    }
601
   
653
   
602
    if (i > j) {
654
    if (i > j) {
603
        if ((retval = putnchars(&fmt[j], (size_t)(i - j))) == EOF) { /* error */
655
        if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) == EOF) { /* error */
604
            return -counter;
656
            return -counter;
605
        }
657
        }
606
        counter += retval;
658
        counter += retval;
607
    }
659
    }
608
   
660
   
609
    va_end(ap);
-
 
610
    return counter;
661
    return counter;
611
}
662
}
612
 
663