add internal functions to access private fenv values.
[AROS.git] / compiler / arossupport / kprintf.c
blob71068b4235a0162686b003a275dcc3d0f36c9f4e
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Formats a message and makes sure the user will see it.
6 Lang: english
7 */
9 #include <aros/config.h>
10 #include <aros/arossupportbase.h>
11 #include <stdarg.h>
13 #include <aros/system.h>
14 #include <dos/bptr.h>
15 #include <proto/exec.h>
16 #include <proto/arossupport.h>
17 #undef kprintf
18 #undef vkprintf
19 #include <exec/execbase.h>
21 #if defined(__AROSEXEC_SMP__)
22 #include <aros/atomic.h>
23 #include <asm/cpu.h>
24 extern volatile ULONG safedebug;
25 #endif
27 /* Can't use ctype.h *sigh* */
28 #define isdigit(x) ((x) >= '0' && (x) <= '9')
29 #define isprint(x) (((x) >= ' ' && (x) <= 128) || (x) >= 160)
31 /* Nor string.h */
32 static inline int my_strlen(const char *c)
34 int i = 0;
35 while (*(c++)) i++;
36 return i;
39 /* Nor atoi */
40 static inline int atoi(const char *c)
42 int i;
43 int isneg = 0;
45 if (*c == '+')
46 c++;
48 if (*c == '-') {
49 isneg = 1;
50 c++;
53 for (i = 0; *c && isdigit(*c); c++) {
54 i *= 10;
55 i += *c - '0';
58 return (isneg) ? -i : i;
61 /*****************************************************************************
63 NAME */
64 #include <proto/arossupport.h>
66 int kprintf (
68 /* SYNOPSIS */
69 const char * fmt,
70 ...)
72 /* FUNCTION
73 Formats fmt with the specified arguments like printf() (and *not*
74 like RawDoFmt()) and uses a secure way to deliver the message to
75 the user; ie. the user *will* see this message no matter what.
77 INPUTS
78 fmt - printf()-style format string
80 RESULT
81 The number of characters output.
83 NOTES
84 This function is not part of a library and may thus be called
85 any time.
87 EXAMPLE
89 BUGS
91 SEE ALSO
93 INTERNALS
95 HISTORY
96 24-12-95 digulla created
98 ******************************************************************************/
100 va_list ap;
101 int result;
103 va_start (ap, fmt);
104 result = vkprintf (fmt, ap);
105 va_end (ap);
107 return result;
108 } /* kprintf */
112 int vkprintf (const char * fmt, va_list args)
114 int ret;
115 static const char uhex[] = "0123456789ABCDEF";
116 static const char lhex[] = "0123456789abcdef";
117 char * fill;
118 unsigned long val;
119 long lval = 0;
121 if (!fmt)
123 #if defined(__AROSEXEC_SMP__)
124 if (safedebug & 1)
126 while (bit_test_and_set_long((ULONG*)&safedebug, 1)) { asm volatile("pause"); };
128 #endif
129 RawPutChars ((const UBYTE *)"(null)", 6);
130 #if defined(__AROSEXEC_SMP__)
131 if (safedebug & 1)
133 __AROS_ATOMIC_AND_L(safedebug, ~(1 << 1));
135 #endif
136 return 6;
139 ret = 0;
140 #if defined(__AROSEXEC_SMP__)
141 if (safedebug & 1)
143 while (bit_test_and_set_long((ULONG*)&safedebug, 1)) { asm volatile("pause"); };
145 #endif
147 while (*fmt)
149 if (*fmt == '%')
151 int width = 0;
152 int precision = 0;
154 fmt ++;
156 if (*fmt == '0')
158 fill = "00000000";
159 fmt ++;
161 else
163 fill = " ";
166 if (*fmt == '*')
168 width = va_arg (args, int);
169 fmt++;
171 else
172 if (isdigit (*fmt))
174 width = atoi (fmt);
175 while (isdigit(*fmt)) fmt++;
178 if (*fmt == '.') fmt++;
180 if (*fmt == '*')
182 precision = va_arg (args, int);
183 fmt++;
185 else
186 if (isdigit (*fmt))
187 precision = atoi (fmt);
189 while (isdigit(*fmt) || *fmt=='.' || *fmt=='-' || *fmt=='+')
190 fmt ++;
192 switch (*fmt)
194 case '%':
195 RawPutChar (*fmt);
196 ret ++;
197 break;
199 case 'b':
200 #ifndef AROS_FAST_BPTR
202 char * str = va_arg (args, char *);
203 int len;
205 if (str) {
206 str = (char *)((unsigned long)str << 2);
207 len = *str++;
208 } else {
209 str = "(null)";
210 len = 6;
213 if (precision)
214 len = precision;
216 RawPutChars (str, len);
217 ret += len;
219 break; }
220 #endif
221 case 's':
222 case 'S': {
223 char * str = va_arg (args, char *);
224 int len;
226 if (!str)
227 str = "(null)";
229 if (*fmt == 'S')
231 RawPutChar ('"');
232 ret ++;
235 if (precision)
236 len = precision;
237 else
238 len = my_strlen (str);
240 RawPutChars ((const UBYTE *)str, len);
241 ret += len;
243 if (*fmt == 'S')
245 RawPutChar ('"');
246 ret ++;
249 break; }
251 case 'p': {
252 int t;
253 char puffer[sizeof (void *)*2];
255 t = sizeof (void *)*2;
256 val = va_arg (args, IPTR);
258 while (t)
260 puffer[--t] = lhex[val & 0x0F];
261 val >>= 4;
264 RawPutChars ((const UBYTE *)puffer, sizeof (void *)*2);
266 break; }
268 case 'c': {
269 UBYTE c;
271 c = va_arg (args, int);
273 if (isprint (c))
274 RawPutChar (c);
275 else
277 RawPutChars ((const UBYTE *)"'\\0x", 4);
278 RawPutChar (lhex[c / 16]);
279 RawPutChar (lhex[c & 15]);
280 RawPutChar ('\'');
283 break; }
285 case 'l': {
286 int t;
287 char puffer[32];
289 if (fmt[1] == 'u' || fmt[1] == 'd' || fmt[1] == 'x' || fmt[1] == 'X')
290 fmt ++;
292 if (*fmt == 'd')
294 lval = va_arg (args, long);
296 val = (lval < 0) ? -lval : lval;
298 else
300 val = va_arg (args, unsigned long);
303 print_int:
304 if (val==0)
306 if (width == 0)
307 width = 1;
309 if (*fill == ' ')
310 width --;
312 while (width > 0)
314 RawPutChars ((const UBYTE *)fill, (width < 8) ? width : 8);
315 width -= 8;
318 if (*fill == ' ')
319 RawPutChar ('0');
321 ret ++;
322 break;
325 t = 32;
327 if (*fmt == 'd' || *fmt == 'u')
329 if (*fmt == 'd')
331 if (lval < 0)
333 RawPutChar ('-');
334 ret ++;
335 val = -lval;
337 else
338 val = lval;
341 while (val && t)
343 puffer[--t] = lhex[val % 10];
345 val /= 10;
348 else if (*fmt == 'x')
350 while (val && t)
352 puffer[--t] = lhex[val & 0x0F];
354 val >>= 4;
357 else
359 while (val && t)
361 puffer[--t] = uhex[val & 0x0F];
363 val >>= 4;
367 width -= 32-t;
369 while (width > 0)
371 RawPutChars ((const UBYTE *)fill, (width < 8) ? width : 8);
372 width -= 8;
375 RawPutChars ((const UBYTE *)&puffer[t], 32-t);
376 ret += 32-t;
378 break; }
380 default: {
381 if (*fmt == 'd')
383 lval = va_arg (args, int);
385 val = (lval < 0) ? -lval : lval;
387 else
389 val = va_arg (args, unsigned int);
392 goto print_int;
394 break; }
395 } /* switch */
397 else
399 RawPutChar (*fmt);
400 ret ++;
403 fmt ++; /* Next char */
404 } /* while (*fmt); */
405 #if defined(__AROSEXEC_SMP__)
406 if (safedebug & 1)
408 __AROS_ATOMIC_AND_L(safedebug, ~(1 << 1));
410 #endif
411 return ret;
412 } /* vkprintf */