source: trunk/src/console/vtxprintf.c

Last change on this file was 5507, checked in by stepan, 5 years ago

Since some people disapprove of white space cleanups mixed in regular commits
while others dislike them being extra commits, let's clean them up once and
for all for the existing code. If it's ugly, let it only be ugly once :-)

Signed-off-by: Stefan Reinauer <stepan@…>
Acked-by: Stefan Reinauer <stepan@…>

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.6 KB
Line 
1/*  vtxprintf.c, from
2 *    linux/lib/vsprintf.c
3 *
4 *  Copyright (C) 1991, 1992  Linus Torvalds
5 */
6
7#include <string.h>
8#include <div64.h>
9#include <console/vtxprintf.h>
10
11/* haha, don't need ctype.c */
12#define isdigit(c)      ((c) >= '0' && (c) <= '9')
13#define is_digit isdigit
14#define isxdigit(c)     (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
15
16static int skip_atoi(const char **s)
17{
18        int i=0;
19
20        while (is_digit(**s))
21                i = i*10 + *((*s)++) - '0';
22        return i;
23}
24
25#define ZEROPAD 1               /* pad with zero */
26#define SIGN    2               /* unsigned/signed long */
27#define PLUS    4               /* show plus */
28#define SPACE   8               /* space if plus */
29#define LEFT    16              /* left justified */
30#define SPECIAL 32              /* 0x */
31#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
32
33static int number(void (*tx_byte)(unsigned char byte),
34        unsigned long long num, int base, int size, int precision, int type)
35{
36        char c,sign,tmp[66];
37        const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
38        int i;
39        int count = 0;
40
41        if (type & LARGE)
42                digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
43        if (type & LEFT)
44                type &= ~ZEROPAD;
45        if (base < 2 || base > 36)
46                return 0;
47        c = (type & ZEROPAD) ? '0' : ' ';
48        sign = 0;
49        if (type & SIGN) {
50                if ((signed long long)num < 0) {
51                        sign = '-';
52                        num = -num;
53                        size--;
54                } else if (type & PLUS) {
55                        sign = '+';
56                        size--;
57                } else if (type & SPACE) {
58                        sign = ' ';
59                        size--;
60                }
61        }
62        if (type & SPECIAL) {
63                if (base == 16)
64                        size -= 2;
65                else if (base == 8)
66                        size--;
67        }
68        i = 0;
69        if (num == 0)
70                tmp[i++]='0';
71        else while (num != 0)
72                tmp[i++] = digits[do_div(num,base)];
73        if (i > precision)
74                precision = i;
75        size -= precision;
76        if (!(type&(ZEROPAD+LEFT)))
77                while(size-->0)
78                        tx_byte(' '), count++;
79        if (sign)
80                tx_byte(sign), count++;
81        if (type & SPECIAL) {
82                if (base==8)
83                        tx_byte('0'), count++;
84                else if (base==16) {
85                        tx_byte('0'), count++;
86                        tx_byte(digits[33]), count++;
87                }
88        }
89        if (!(type & LEFT))
90                while (size-- > 0)
91                        tx_byte(c), count++;
92        while (i < precision--)
93                tx_byte('0'), count++;
94        while (i-- > 0)
95                tx_byte(tmp[i]), count++;
96        while (size-- > 0)
97                tx_byte(' '), count++;
98        return count;
99}
100
101
102int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args)
103{
104        int len;
105        unsigned long long num;
106        int i, base;
107        const char *s;
108
109        int flags;              /* flags to number() */
110
111        int field_width;        /* width of output field */
112        int precision;          /* min. # of digits for integers; max
113                                   number of chars for from string */
114        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
115
116        int count;
117
118        for (count=0; *fmt ; ++fmt) {
119                if (*fmt != '%') {
120                        tx_byte(*fmt), count++;
121                        continue;
122                }
123
124                /* process flags */
125                flags = 0;
126                repeat:
127                        ++fmt;          /* this also skips first '%' */
128                        switch (*fmt) {
129                                case '-': flags |= LEFT; goto repeat;
130                                case '+': flags |= PLUS; goto repeat;
131                                case ' ': flags |= SPACE; goto repeat;
132                                case '#': flags |= SPECIAL; goto repeat;
133                                case '0': flags |= ZEROPAD; goto repeat;
134                                }
135
136                /* get field width */
137                field_width = -1;
138                if (is_digit(*fmt))
139                        field_width = skip_atoi(&fmt);
140                else if (*fmt == '*') {
141                        ++fmt;
142                        /* it's the next argument */
143                        field_width = va_arg(args, int);
144                        if (field_width < 0) {
145                                field_width = -field_width;
146                                flags |= LEFT;
147                        }
148                }
149
150                /* get the precision */
151                precision = -1;
152                if (*fmt == '.') {
153                        ++fmt;
154                        if (is_digit(*fmt))
155                                precision = skip_atoi(&fmt);
156                        else if (*fmt == '*') {
157                                ++fmt;
158                                /* it's the next argument */
159                                precision = va_arg(args, int);
160                        }
161                        if (precision < 0)
162                                precision = 0;
163                }
164
165                /* get the conversion qualifier */
166                qualifier = -1;
167                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
168                        qualifier = *fmt;
169                        ++fmt;
170                        if (*fmt == 'l') {
171                                qualifier = 'L';
172                                ++fmt;
173                        }
174                }
175
176                /* default base */
177                base = 10;
178
179                switch (*fmt) {
180                case 'c':
181                        if (!(flags & LEFT))
182                                while (--field_width > 0)
183                                        tx_byte(' '), count++;
184                        tx_byte((unsigned char) va_arg(args, int)), count++;
185                        while (--field_width > 0)
186                                tx_byte(' '), count++;
187                        continue;
188
189                case 's':
190                        s = va_arg(args, char *);
191                        if (!s)
192                                s = "<NULL>";
193
194                        len = strnlen(s, precision);
195
196                        if (!(flags & LEFT))
197                                while (len < field_width--)
198                                        tx_byte(' '), count++;
199                        for (i = 0; i < len; ++i)
200                                tx_byte(*s++), count++;
201                        while (len < field_width--)
202                                tx_byte(' '), count++;
203                        continue;
204
205                case 'p':
206                        if (field_width == -1) {
207                                field_width = 2*sizeof(void *);
208                                flags |= ZEROPAD;
209                        }
210                        count += number(tx_byte,
211                                (unsigned long) va_arg(args, void *), 16,
212                                field_width, precision, flags);
213                        continue;
214
215
216                case 'n':
217                        if (qualifier == 'L') {
218                                long long *ip = va_arg(args, long long *);
219                                *ip = count;
220                        } else if (qualifier == 'l') {
221                                long * ip = va_arg(args, long *);
222                                *ip = count;
223                        } else {
224                                int * ip = va_arg(args, int *);
225                                *ip = count;
226                        }
227                        continue;
228
229                case '%':
230                        tx_byte('%'), count++;
231                        continue;
232
233                /* integer number formats - set up the flags and "break" */
234                case 'o':
235                        base = 8;
236                        break;
237
238                case 'X':
239                        flags |= LARGE;
240                case 'x':
241                        base = 16;
242                        break;
243
244                case 'd':
245                case 'i':
246                        flags |= SIGN;
247                case 'u':
248                        break;
249
250                default:
251                        tx_byte('%'), count++;
252                        if (*fmt)
253                                tx_byte(*fmt), count++;
254                        else
255                                --fmt;
256                        continue;
257                }
258                if (qualifier == 'L') {
259                        num = va_arg(args, unsigned long long);
260                } else if (qualifier == 'l') {
261                        num = va_arg(args, unsigned long);
262                } else if (qualifier == 'h') {
263                        num = (unsigned short) va_arg(args, int);
264                        if (flags & SIGN)
265                                num = (short) num;
266                } else if (flags & SIGN) {
267                        num = va_arg(args, int);
268                } else {
269                        num = va_arg(args, unsigned int);
270                }
271                count += number(tx_byte, num, base, field_width, precision, flags);
272        }
273        return count;
274}
275
Note: See TracBrowser for help on using the repository browser.