-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprintf.c
188 lines (149 loc) · 3.33 KB
/
printf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
Simplified printf and sprintf for SDCC+Z80
(c) 2018 Konamiman - www.konamiman.com
This version is about 1.5K smaller than the one contained
in the z80 library supplied with SDCC
To compile:
sdcc -mz80 -c --disable-warning 85 --disable-warning 196 --max-allocs-per-node 100000 --allow-unsafe-read --opt-code-size printf.c
Supported format specifiers:
%d or %i: signed int
%u: unsigned int
%x: hexadecimal int
%c: character
%s: string
%%: a % character
Also if SUPPORT_LONG is defined:
%l: signed long
%ul: unsigned long
%lx: hexadecimal long
*/
//#define SUPPORT_LONG
#include <stdint.h>
#include <stdarg.h>
#ifdef SUPPORT_LONG
extern char* my_ultoa(long val, char* buffer, uint8_t base);
extern char* my_ltoa(long val, char* buffer, uint8_t base);
#endif
extern char* my_uitoa(uint16_t val, char* buffer, uint8_t base);
extern char* my_itoa(int16_t val, char* buffer, uint8_t base);
extern void putchar(char* c);
static int format_string(char* buf, const char* fmt, va_list ap);
int printf(const char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
return format_string(0, fmt, arg);
}
int sprintf(char* buf, const char* fmt, ...)
{
va_list arg;
va_start(arg, fmt);
return format_string(buf, fmt, arg);
}
static void do_char(const char* buf, char c) __sdcccall(0) __naked
{
buf; c;
__asm
ld hl,#4
add hl,sp
ld e,(hl)
dec hl
ld a,(hl)
dec hl
ld l,(hl)
ld h,a
or l
jp z,_putchar_rr_dbs
ld(hl),e
ret
__endasm;
}
#define do_char_inc(c) {do_char(bufPnt,c); if(bufPnt) { bufPnt++; } count++;}
static int format_string(char* buf, const char *fmt, va_list ap)
{
const char *fmtPnt;
char *bufPnt;
char base;
#ifdef SUPPORT_LONG
char isLong;
#endif
char isUnsigned;
char *strPnt;
long val;
static char buffer[16];
char theChar;
int count=0;
fmtPnt = fmt;
bufPnt = buf;
while((theChar = *fmtPnt)!=0)
{
#ifdef SUPPORT_LONG
isLong = 0;
#endif
isUnsigned = 0;
base = 10;
fmtPnt++;
if(theChar != '%') {
do_char_inc(theChar);
continue;
}
theChar = *fmtPnt;
fmtPnt++;
if(theChar == 's')
{
strPnt = va_arg(ap, char *);
while((theChar = *strPnt++) != 0)
do_char_inc(theChar);
continue;
}
if(theChar == 'c')
{
val = va_arg(ap, int);
do_char_inc((char) val);
continue;
}
#ifdef SUPPORT_LONG
if(theChar == 'l')
{
isLong = 1;
theChar = *fmtPnt;
fmtPnt++;
}
#endif
if(theChar == 'u') {
isUnsigned = 1;
}
else if(theChar == 'x') {
base = 16;
}
else if(theChar != 'd' && theChar != 'i') {
do_char_inc(theChar);
continue;
}
#ifdef SUPPORT_LONG
if(isLong)
val = va_arg(ap, long);
else
val = va_arg(ap, int);
if(isUnsigned && isLong)
strPnt = _ultoa(val, buffer, base);
else if(isUnsigned)
strPnt = _uitoa(val, buffer, base);
else if(isLong)
strPnt = _ltoa(val, buffer, base);
else
strPnt = _itoa(val, buffer, base);
#else
val = va_arg(ap, int);
if(isUnsigned)
strPnt = my_uitoa(val, buffer, base);
else
strPnt = my_itoa(val, buffer, base);
#endif
//strPnt = buffer;
while((theChar = *strPnt++) != 0)
do_char_inc(theChar);
}
if(bufPnt) *bufPnt = '\0';
return count;
}