OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [lib/] [printk.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*********************************************************************
2
 *
3
 * Copyright (C) 2002-2004  Karlsruhe University
4
 *
5
 * File path:     generic/printk.cc
6
 * Description:   Implementation of printf
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 ********************************************************************/
30
#include <stdarg.h>     /* for va_list, ... comes with gcc */
31
#include <l4/lib/printk.h>
32
#include <l4/lib/mutex.h>
33
 
34
/* FIXME: LICENSE LICENCE */
35
typedef unsigned int word_t;
36
 
37
extern void putc(const char c);
38
extern int print_tid (word_t val, word_t width, word_t precision, int adjleft);
39
 
40
 
41
/* convert nibble to lowercase hex char */
42
#define hexchars(x) (((x) < 10) ? ('0' + (x)) : ('a' + ((x) - 10)))
43
 
44
/**
45
 *      Print hexadecimal value
46
 *
47
 *      @param val              value to print
48
 *      @param width            width in caracters
49
 *      @param precision        minimum number of digits to apprear
50
 *      @param adjleft          left adjust the value
51
 *      @param nullpad          pad with leading zeros (when right padding)
52
 *
53
 *      Prints a hexadecimal value with leading zeroes of given width
54
 *      using putc(), or if adjleft argument is given, print
55
 *      hexadecimal value with space padding to the right.
56
 *
57
 *      @returns the number of charaters printed (should be same as width).
58
 */
59
int print_hex64(u64 val, int width, int precision, int adjleft, int nullpad)
60
{
61
    int i, n = 0;
62
    int nwidth = 0;
63
    u32 high, low;
64
 
65
    high = val >> 32;
66
    low = (u32)val;
67
 
68
    // Find width of hexnumber
69
    if (high) {
70
        while ((high >> (4 * nwidth)) && ((unsigned) nwidth <  2 * sizeof (u32)))
71
            nwidth++;
72
        nwidth += 32;
73
    } else {
74
        while ((low >> (4 * nwidth)) && ((unsigned) nwidth <  2 * sizeof (u32)))
75
            nwidth++;
76
    }
77
 
78
    if (nwidth == 0)
79
        nwidth = 1;
80
 
81
    // May need to increase number of printed digits
82
    if (precision > nwidth)
83
        nwidth = precision;
84
 
85
    // May need to increase number of printed characters
86
    if (width == 0 && width < nwidth)
87
        width = nwidth;
88
 
89
    // Print number with padding
90
    if (high)
91
    {
92
        if (!adjleft)
93
            for (i = width - nwidth; i > 0; i--, n++)
94
                putc (nullpad ? '0' : ' ');
95
        for (i = 4 * (nwidth - 33); i >= 0; i -= 4, n++)
96
            putc (hexchars ((high >> i) & 0xF));
97
        if (adjleft)
98
            for (i = width - nwidth; i > 0; i--, n++)
99
                putc (' ');
100
        width -= 32;
101
        nwidth -= 32;
102
        nullpad = 1;
103
    }
104
    if (! adjleft)
105
        for (i = width - nwidth; i > 0; i--, n++)
106
            putc (nullpad ? '0' : ' ');
107
    for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
108
        putc (hexchars ((low >> i) & 0xF));
109
    if (adjleft)
110
        for (i = width - nwidth; i > 0; i--, n++)
111
            putc (' ');
112
 
113
    return n;
114
}
115
 
116
int print_hex_3arg(const word_t val, int width, int precision)
117
{
118
    long i, n = 0;
119
    long nwidth = 0;
120
    int adjleft = 0;
121
    int nullpad = 0;
122
 
123
    // Find width of hexnumber
124
    while ((val >> (4 * nwidth)) && (word_t) nwidth <  2 * sizeof (word_t))
125
        nwidth++;
126
 
127
    if (nwidth == 0)
128
        nwidth = 1;
129
 
130
    // May need to increase number of printed digits
131
    if (precision > nwidth)
132
        nwidth = precision;
133
 
134
    // May need to increase number of printed characters
135
    if (width == 0 && width < nwidth)
136
        width = nwidth;
137
 
138
    // Print number with padding
139
    if (! adjleft)
140
        for (i = width - nwidth; i > 0; i--, n++)
141
            putc (nullpad ? '0' : ' ');
142
    for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
143
        putc (hexchars ((val >> i) & 0xF));
144
    if (adjleft)
145
        for (i = width - nwidth; i > 0; i--, n++)
146
            putc (' ');
147
 
148
    return n;
149
}
150
 
151
int print_hex_5arg(const word_t val, int width,
152
                   int precision, int adjleft, int nullpad)
153
{
154
    long i, n = 0;
155
    long nwidth = 0;
156
 
157
    // Find width of hexnumber
158
    while ((val >> (4 * nwidth)) && (word_t) nwidth <  2 * sizeof (word_t))
159
        nwidth++;
160
 
161
    if (nwidth == 0)
162
        nwidth = 1;
163
 
164
    // May need to increase number of printed digits
165
    if (precision > nwidth)
166
        nwidth = precision;
167
 
168
    // May need to increase number of printed characters
169
    if (width == 0 && width < nwidth)
170
        width = nwidth;
171
 
172
    // Print number with padding
173
    if (! adjleft)
174
        for (i = width - nwidth; i > 0; i--, n++)
175
            putc (nullpad ? '0' : ' ');
176
    for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
177
        putc (hexchars ((val >> i) & 0xF));
178
    if (adjleft)
179
        for (i = width - nwidth; i > 0; i--, n++)
180
            putc (' ');
181
 
182
    return n;
183
}
184
/**
185
 *      Print a string
186
 *
187
 *      @param s        zero-terminated string to print
188
 *      @param width    minimum width of printed string
189
 *
190
 *      Prints the zero-terminated string using putc().  The printed
191
 *      string will be right padded with space to so that it will be
192
 *      at least WIDTH characters wide.
193
 *
194
 *      @returns the number of charaters printed.
195
 */
196
int print_string_3arg(const char * s, const int width, const int precision)
197
{
198
    int n = 0;
199
 
200
    for (;;)
201
    {
202
        if (*s == 0)
203
            break;
204
 
205
        putc(*s++);
206
        n++;
207
        if (precision && n >= precision)
208
            break;
209
    }
210
 
211
    while (n < width) { putc(' '); n++; }
212
 
213
    return n;
214
}
215
 
216
int print_string_1arg(const char * s)
217
{
218
        int n = 0;
219
        int width = 0;
220
        int precision = 0;
221
 
222
        for (;;) {
223
                if (*s == 0)
224
                        break;
225
 
226
                putc(*s++);
227
                n++;
228
                if (precision && n >= precision)
229
                        break;
230
        }
231
 
232
        while (n < width) {
233
                putc(' ');
234
                n++;
235
        }
236
 
237
        return n;
238
}
239
 
240
 
241
/**
242
 *      Print hexadecimal value with a separator
243
 *
244
 *      @param val      value to print
245
 *      @param bits     number of lower-most bits before which to
246
 *                      place the separator
247
 *      @param sep      the separator to print
248
 *
249
 *      @returns the number of charaters printed.
250
 */
251
int print_hex_sep(const word_t val, const int bits, const char *sep)
252
{
253
    int n = 0;
254
 
255
    n = print_hex_3arg(val >> bits, 0, 0);
256
    n += print_string_1arg(sep);
257
    n += print_hex_3arg(val & ((1 << bits) - 1), 0, 0);
258
 
259
    return n;
260
}
261
 
262
 
263
/**
264
 *      Print decimal value
265
 *
266
 *      @param val      value to print
267
 *      @param width    width of field
268
 *      @param pad      character used for padding value up to width
269
 *
270
 *      Prints a value as a decimal in the given WIDTH with leading
271
 *      whitespaces.
272
 *
273
 *      @returns the number of characters printed (may be more than WIDTH)
274
 */
275
int print_dec(const word_t val, int width)
276
{
277
    word_t divisor;
278
    int digits;
279
    /* estimate number of spaces and digits */
280
    for (divisor = 1, digits = 1; val/divisor >= 10; divisor *= 10, digits++);
281
 
282
    /* print spaces */
283
    for ( ; digits < width; digits++ )
284
        putc(' ');
285
 
286
    /* print digits */
287
    do {
288
        putc(((val/divisor) % 10) + '0');
289
    } while (divisor /= 10);
290
 
291
    /* report number of digits printed */
292
    return digits;
293
}
294
 
295
/**
296
 *      Does the real printk work
297
 *
298
 *      @param format_p         pointer to format string
299
 *      @param args             list of arguments, variable length
300
 *
301
 *      Prints the given arguments as specified by the format string.
302
 *      Implements a subset of the well-known printf plus some L4-specifics.
303
 *
304
 *      @returns the number of characters printed
305
 */
306
int do_printk(char* format_p, va_list args)
307
{
308
    const char* format = format_p;
309
    int n = 0;
310
    int i = 0;
311
    int width = 8;
312
    int precision = 0;
313
    int adjleft = 0, nullpad = 0;
314
 
315
#define arg(x) va_arg(args, x)
316
 
317
    /* sanity check */
318
    if (format == '\0')
319
    {
320
        return 0;
321
    }
322
 
323
    while (*format)
324
    {
325
        switch (*(format))
326
        {
327
        case '%':
328
            width = precision = 0;
329
            adjleft = nullpad = 0;
330
        reentry:
331
            switch (*(++format))
332
            {
333
                /* modifiers */
334
            case '.':
335
                for (format++; *format >= '0' && *format <= '9'; format++)
336
                    precision = precision * 10 + (*format) - '0';
337
                if (*format == 'w')
338
                {
339
                    // Set precision to printsize of a hex word
340
                    precision = sizeof (word_t) * 2;
341
                    format++;
342
                }
343
                format--;
344
                goto reentry;
345
            case '0':
346
                nullpad = (width == 0);
347
            case '1'...'9':
348
                width = width*10 + (*format)-'0';
349
                goto reentry;
350
            case 'w':
351
                // Set width to printsize of a hex word
352
                width = sizeof (word_t) * 2;
353
                goto reentry;
354
            case '-':
355
                adjleft = 0;
356
                goto reentry;
357
            case 'l':
358
                goto reentry;
359
                break;
360
            case 'c':
361
                putc(arg(int));
362
                n++;
363
                break;
364
            case 'm':   /* microseconds */
365
            {
366
                n += print_hex64(arg(u64), width, precision,
367
                               adjleft, nullpad);
368
                break;
369
            }
370
            case 'd':
371
            {
372
                long val = arg(long);
373
                if (val < 0)
374
                {
375
                    putc('-');
376
                    val = -val;
377
                }
378
                n += print_dec(val, width);
379
                break;
380
            }
381
            case 'u':
382
                n += print_dec(arg(long), width);
383
                break;
384
            case 'p':
385
                precision = sizeof (word_t) * 2;
386
            case 'x':
387
                n += print_hex_5arg(arg(long), width, precision, adjleft, nullpad);
388
                break;
389
            case 's':
390
            {
391
                char* s = arg(char*);
392
                if (s)
393
                    n += print_string_3arg(s, width, precision);
394
                else
395
                    n += print_string_3arg("(null)", width, precision);
396
            }
397
            break;
398
 
399
            case 't':
400
            case 'T':
401
                // Do nothing for now.
402
                //n += print_tid (arg (word_t), width, precision, adjleft);
403
                break;
404
 
405
            case '%':
406
                putc('%');
407
                n++;
408
                format++;
409
                continue;
410
            default:
411
                n += print_string_1arg("?");
412
                break;
413
            };
414
            i++;
415
            break;
416
        default:
417
            putc(*format);
418
            n++;
419
            break;
420
        }
421
        format++;
422
    }
423
 
424
    return n;
425
}
426
 
427
DECLARE_SPINLOCK(printk_lock);
428
 
429
/**
430
 *      Flexible print function
431
 *
432
 *      @param format   string containing formatting and parameter type
433
 *                      information
434
 *      @param ...      variable list of parameters
435
 *
436
 *      @returns the number of characters printed
437
 */
438
int printk(char *format, ...)
439
{
440
    va_list args;
441
    int i;
442
    unsigned long irqstate;
443
 
444
    va_start(args, format);
445
 
446
    spin_lock_irq(&printk_lock, &irqstate);
447
    i = do_printk(format, args);
448
    spin_unlock_irq(&printk_lock, irqstate);
449
 
450
    va_end(args);
451
    return i;
452
}
453
 
454
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.