* Added a simple version of printf()
[fw/sdcc] / device / lib / z80 / printf.c
1 /** Simple printf implementation
2     Again a stub - will use the std one later...
3 */
4
5 #define NULL 0
6
7 /* A hack because I dont understand how va_arg works...
8    sdcc pushes right to left with the real sizes, not cast up
9    to an int.
10    so printf(int, char, long)
11    results in push long, push char, push int
12    On the z80 the stack grows down, so the things seem to be in
13    the correct order.
14  */
15
16 typedef char * va_list;
17 #define va_start(list, last)    list = (char *)&last + sizeof(last)
18 #define va_arg(list, type)      *(type *)list; list += sizeof(type);
19
20 typedef void EMIT(char c, void *pData);
21
22
23 static void _printhex(unsigned u, EMIT *emitter, void *pData)
24 {
25     const char *_hex = "0123456789ABCDEF";
26     if (u >= 0x10)
27         _printhex(u/0x10, emitter, pData);
28     (*emitter)(_hex[u&0x0f], pData);
29 }
30
31 static void _printf(const char *format, EMIT *emitter, void *pData, va_list va)
32 {
33     while (*format) {
34         if (*format == '%') {
35             switch (*++format) {
36             case 'c': {
37                 char c = va_arg(va, char);
38                 (*emitter)(c, pData);
39                 break;
40             }
41             case 'u':
42             case 'd':
43                 {
44                     unsigned u = va_arg(va, unsigned);
45                     _printhex(u, emitter, pData);
46                     break;
47                 }
48             case 's': 
49                 {
50                     char *s = va_arg(va, char *);
51                     while (*s) {
52                         (*emitter)(*s, pData);
53                         s++;
54                     }
55                 }
56             }
57         }
58         else {
59             (*emitter)(*format, pData);
60         }
61         format++;
62     }
63 }
64
65 void putchar(char c);
66
67 static void _char_emitter(char c, void *pData)
68 {
69     putchar(c);
70 }
71
72 void printf(const char *format, ...)
73 {
74     va_list va;
75     va_start(va, format);
76
77     _printf(format, _char_emitter, NULL, va);
78 }