gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/libc/sprintf.c
1 #include <types.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6
7 #if defined(__PORT_mos6502)
8 typedef void (*emitter_t)(char, char **) REENTRANT;
9 #else
10 typedef void (*emitter_t)(char, char **) OLDCALL;
11 #endif
12
13 static const char _hex[] = "0123456789ABCDEF";
14
15 inline void _printhex(uint16_t u, emitter_t emitter, char ** pData)
16 {
17 (*emitter)(_hex[(uint8_t)(u >> 8) >> 4], pData);
18 (*emitter)(_hex[(uint8_t)(u >> 8) & 0x0fu], pData);
19 (*emitter)(_hex[((uint8_t)u >> 4) & 0x0fu], pData);
20 (*emitter)(_hex[(uint8_t)u & 0x0fu], pData);
21 }
22
23 inline void _printhexbyte(uint8_t u, emitter_t emitter, char ** pData)
24 {
25 (*emitter)(_hex[u >> 4], pData);
26 (*emitter)(_hex[u & 0x0fu], pData);
27 }
28
29 static void _printbuf(char * buf, emitter_t emitter, char ** pData) {
30 for (char *s = buf; *s; s++) (*emitter)(*s, pData);
31 }
32
33 void __printf(const char *format, emitter_t emitter, char **pData, va_list va)
34 {
35 char buf[16];
36 while ((uint8_t)(*format)) {
37 if ((uint8_t)(*format) == '%') {
38 format++;
39
40 // 0 Padding is not supported, ignore
41 if ((uint8_t)(*format) == '0') format++;
42
43 // Width Specifier is not supported, ignore 1 digit worth
44 if ((uint8_t)((uint8_t)(*format) - '1') < 9u) format++;
45
46 switch ((uint8_t)(*format)) {
47 case 'h':
48 switch ((uint8_t)(*++format)) {
49 case 'X' :
50 case 'x' :
51 _printhexbyte(va_arg(va, char), emitter, pData);
52 break;
53 case 'u':
54 uitoa((unsigned char)va_arg(va, char), buf, 10);
55 _printbuf(buf, emitter, pData);
56 break;
57 case 'd':
58 itoa((signed char)va_arg(va, char), buf, 10);
59 _printbuf(buf, emitter, pData);
60 break;
61 }
62 break;
63 case 'u':
64 uitoa(va_arg(va, int), buf, 10);
65 _printbuf(buf, emitter, pData);
66 break;
67 case 'd':
68 itoa(va_arg(va, int), buf, 10);
69 _printbuf(buf, emitter, pData);
70 break;
71 case 's':
72 _printbuf(va_arg(va, char *), emitter, pData);
73 break;
74 case 'c':
75 char c = va_arg(va, char);
76 (*emitter)(c, pData);
77 break;
78 case 'X':
79 case 'x':
80 _printhex(va_arg(va, int), emitter, pData);
81 break;
82 default:
83 (*emitter)(*format, pData);
84 break;
85 }
86 } else {
87 (*emitter)(*format, pData);
88 }
89 format++;
90 }
91 }
92
93 #if defined(__PORT_mos6502)
94 static void _sprintf_emitter(char c, char ** pData) REENTRANT
95 #else
96 static void _sprintf_emitter(char c, char ** pData) OLDCALL
97 #endif
98 {
99 **pData = c;
100 (*pData)++;
101 }
102
103 void sprintf(char *into, const char *format, ...) {
104 va_list va;
105 va_start(va, format);
106
107 __printf(format, _sprintf_emitter, &into, va);
108 _sprintf_emitter('\0', &into);
109 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.