Mercurial > lcfOS
annotate cos/kernel/snprintf.c @ 219:1fa3e0050b49
Expanded ad hoc code generator
author | Windel Bouwman |
---|---|
date | Sat, 06 Jul 2013 12:38:09 +0200 |
parents | 8012221dd740 |
children |
rev | line source |
---|---|
9 | 1 /* |
2 * snprintf.c | |
3 */ | |
4 #include "kernel.h" | |
5 | |
13 | 6 /* |
7 * NOTE! This ctype does not handle EOF like the standard C | |
8 * library is required to. | |
9 */ | |
10 | |
11 #define _U 0x01 /* upper */ | |
12 #define _L 0x02 /* lower */ | |
13 #define _D 0x04 /* digit */ | |
14 #define _C 0x08 /* cntrl */ | |
15 #define _P 0x10 /* punct */ | |
16 #define _S 0x20 /* white space (space/lf/tab) */ | |
17 #define _X 0x40 /* hex digit */ | |
18 #define _SP 0x80 /* hard space (0x20) */ | |
19 | |
17 | 20 uint8_t _ctype[] = { |
9 | 21 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ |
22 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ | |
23 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ | |
24 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ | |
25 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ | |
26 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ | |
27 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ | |
28 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ | |
29 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ | |
30 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ | |
31 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ | |
32 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ | |
33 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ | |
34 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ | |
35 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ | |
36 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ | |
37 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ | |
38 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ | |
39 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ | |
40 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ | |
41 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ | |
42 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ | |
43 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ | |
44 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ | |
45 | |
17 | 46 #define __ismask(x) (_ctype[(int)(uint8_t)(x)]) |
13 | 47 |
48 #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) | |
49 #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) | |
50 #define iscntrl(c) ((__ismask(c)&(_C)) != 0) | |
51 #define isdigit(c) ((__ismask(c)&(_D)) != 0) | |
52 #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) | |
53 #define islower(c) ((__ismask(c)&(_L)) != 0) | |
54 #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) | |
55 #define ispunct(c) ((__ismask(c)&(_P)) != 0) | |
56 #define isspace(c) ((__ismask(c)&(_S)) != 0) | |
57 #define isupper(c) ((__ismask(c)&(_U)) != 0) | |
58 #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) | |
59 | |
60 #define isascii(c) (((unsigned char)(c))<=0x7f) | |
61 #define toascii(c) (((unsigned char)(c))&0x7f) | |
62 | |
17 | 63 static inline uint8_t tolower(uint8_t c) |
13 | 64 { |
65 if (isupper(c)) | |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
66 c += 'a'-'A'; |
13 | 67 return c; |
68 } | |
69 | |
17 | 70 static inline uint8_t toupper(uint8_t c) |
13 | 71 { |
72 if (islower(c)) | |
73 c -= 'a'-'A'; | |
74 return c; | |
75 } | |
9 | 76 |
77 #define MORE_THAN_YOU_WANT 1<<30 | |
78 #define MAX_STDOUT_CHARS 255 | |
79 | |
80 static char hexmap[] = { | |
81 '0', '1', '2', '3', '4', '5', '6', '7', | |
82 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' | |
83 }; | |
84 | |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
85 /* string print function. Supports the formats: |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
86 %p, %x: 64 bits hex number |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
87 %d: signed integer |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
88 %u: unsigned integer |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
89 */ |
9 | 90 void va_snprintf(char *b, int l, const char *fmt, va_list pvar) |
91 { | |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
92 int i; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
93 int64_t s64; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
94 uint64_t u64; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
95 char *t; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
96 char d[20]; // For storing the decimal value in chars. |
9 | 97 |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
98 if ((fmt == 0) || (b == 0) || (l < 1)) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
99 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
100 return; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
101 } |
9 | 102 |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
103 while ((l > 0) && (*fmt != 0)) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
104 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
105 if (*fmt == '%') |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
106 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
107 if ((--l) == 0) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
108 { |
9 | 109 break; |
110 } | |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
111 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
112 fmt++; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
113 switch (*fmt) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
114 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
115 case 's': /* string */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
116 t = va_arg(pvar, char *); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
117 while ((l > 0) && (*t != 0)) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
118 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
119 *b++ = *t++; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
120 l--; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
121 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
122 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
123 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
124 case 'c': /* single character */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
125 *b++ = (char)va_arg(pvar, int); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
126 l--; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
127 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
128 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
129 case 'x': |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
130 case 'p': |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
131 /* Pointer and hex uint64_t */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
132 /* 16 digit, unsigned 64-bit hex integer */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
133 if (l < 18) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
134 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
135 l = 0; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
136 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
137 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
138 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
139 *b++ = '0'; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
140 *b++ = 'x'; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
141 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
142 u64 = va_arg(pvar, uint64_t); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
143 for (i = 15; i >= 0; i--) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
144 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
145 b[i] = hexmap[u64 & 0x0f]; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
146 u64 >>= 4; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
147 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
148 b += 16; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
149 l -= 16; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
150 break; |
9 | 151 |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
152 case 'd': /* signed integer */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
153 s64 = va_arg(pvar, int); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
154 if (s64 < 0) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
155 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
156 u64 = (uint64_t)(-s64); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
157 *b++ = '-'; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
158 if ((--l) == 0) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
159 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
160 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
161 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
162 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
163 else |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
164 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
165 u64 = s64; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
166 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
167 goto u2; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
168 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
169 case 'u': /* unsigned integer */ |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
170 u64 = va_arg(pvar, unsigned int); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
171 u2: |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
172 i = 19; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
173 do |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
174 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
175 d[i] = (u64 % 10) + '0'; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
176 u64 /= 10; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
177 i--; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
178 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
179 while ((u64 != 0) && (i >= 0)); |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
180 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
181 // Now print the characters: |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
182 while (++i < 20) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
183 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
184 *b++ = d[i]; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
185 if ((--l) == 0) |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
186 { |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
187 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
188 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
189 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
190 break; |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
191 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
192 default: |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
193 *b++ = *fmt; |
9 | 194 } |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
195 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
196 else |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
197 { |
9 | 198 *b++ = *fmt; |
199 l--; | |
200 } | |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
201 |
9 | 202 fmt++; |
34
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
203 } |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
204 |
8012221dd740
Fixes for uninitialized data. This causes problems on real machines
windel
parents:
18
diff
changeset
|
205 *b = 0; // Add a 0 terminate |
9 | 206 } |
207 | |
208 void snprintf(char *str, int len, char *fmt, ...) | |
209 { | |
210 va_list pvar; | |
211 va_start(pvar, fmt); | |
212 va_snprintf(str, len, fmt, pvar); | |
213 va_end(pvar); | |
214 } | |
215 | |
216 void | |
217 printf(const char* fmt, ...) | |
218 { | |
219 static char buf[MAX_STDOUT_CHARS]; | |
220 | |
221 va_list args; | |
222 va_start(args, fmt); | |
223 va_snprintf(buf, MAX_STDOUT_CHARS, fmt, args); | |
224 va_end(args); | |
225 | |
226 print_string(buf); | |
227 } |