CS350 COS
COS
Loading...
Searching...
No Matches
printf.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006-2018 Ali Mashtizadeh
3 * All rights reserved.
4 */
5
6#include <stdbool.h>
7#include <stdint.h>
8#include <stdarg.h>
9#include <string.h>
10#include <stdio.h>
11
12// static unsigned long getuint(va_list *ap, int lflag)
13#define getuint(ap, lflag) \
14 (lflag == 8) ? va_arg(ap, uint64_t) : \
15 (lflag == 4) ? va_arg(ap, uint32_t) : \
16 (lflag == 2) ? va_arg(ap, uint32_t) : \
17 (lflag == 1) ? va_arg(ap, uint32_t) : 0
18
19// static long getint(va_list *ap, int lflag)
20#define getint(ap, lflag) \
21 (lflag == 8) ? va_arg(ap, int64_t) : \
22 (lflag == 4) ? va_arg(ap, int32_t) : \
23 (lflag == 2) ? va_arg(ap, int32_t) : \
24 (lflag == 1) ? va_arg(ap, int32_t) : 0
25
26static const char *numberstring_lower = "0123456789abcdef";
27static const char *numberstring_upper = "0123456789ABCDEF";
28
29static void printnum(void (*func)(int, void*),void *handle,
30 uint64_t num,int base,int width,int padc)
31{
32 char buf[64];
33 char *p = buf;
34 int spaces;
35 if (base < 0)
36 {
37 base = -base;
38 do {
39 *p = numberstring_upper[num % base];
40 p++;
41 } while (num /= base);
42 } else {
43 do {
44 *p = numberstring_lower[num % base];
45 p++;
46 } while (num /= base);
47 }
48
49 // Print spacers (pre-number)
50 spaces = width - (p - buf);
51 if (padc == ' ' || padc == '0') {
52 while (spaces > 0)
53 {
54 func(padc, handle);
55 spaces--;
56 }
57 }
58
59 // Print Number
60 while (p != buf) {
61 p--;
62 func((int)*p, handle);
63 }
64
65 // Print spacers (post-number)
66 if (padc == '-') {
67 while (spaces > 0)
68 {
69 func(' ', handle);
70 spaces--;
71 }
72 }
73}
74
75static int kvprintf(char const *fmt, void (*func)(int,void *), void *handle, va_list ap)
76{
77 const char *p;
78 int ch;
79 uint64_t unum;
80 int64_t num;
81 int lflag, width, padc;
82
83 while (1) {
84 while ((ch = *(unsigned char *)fmt++) != '%') {
85 if (ch == '\0') return -1;
86 func(ch, handle);
87 }
88
89 width = -1;
90 lflag = 4;
91 padc = ' ';
92again:
93 switch (ch = *(unsigned char *)fmt++) {
94 case '-':
95 padc = '-';
96 goto again;
97 case '0':
98 padc = '0';
99 goto again;
100 case '1':
101 case '2':
102 case '3':
103 case '4':
104 case '5':
105 case '6':
106 case '7':
107 case '8':
108 case '9':
109 width = 0;
110 while (1) {
111 width = 10 * width + ch - '0';
112 ch = *fmt;
113 if (ch < '0' || ch > '9')
114 {
115 break;
116 }
117 fmt++;
118 if (ch == '\0')
119 {
120 fmt--;
121 goto again;
122 }
123 }
124 goto again;
125 case 'c':
126 func(va_arg(ap, int) & 0xff, handle);
127 break;
128 case 's': {
129 int spaces;
130
131 p = va_arg(ap, char *);
132 if (p == NULL) {
133 func('*', handle);
134 func('N', handle);
135 func('U', handle);
136 func('L', handle);
137 func('L', handle);
138 func('*', handle);
139 break;
140 }
141 spaces = width - strlen(p);
142
143 if (padc == ' ') {
144 while (spaces > 0)
145 {
146 func(' ', handle);
147 spaces--;
148 }
149 }
150
151 while (*p != '\0')
152 {
153 func(*p++, handle);
154 }
155
156 if (padc == '-') {
157 while (spaces > 0)
158 {
159 func(' ', handle);
160 spaces--;
161 }
162 }
163 break;
164 }
165 case 'd':
166 num = getint(ap, lflag);
167 if (num < 0) {
168 func('-', handle);
169 unum = -num;
170 } else {
171 unum = num;
172 }
173 printnum(func, handle, unum, 10, width, padc);
174 break;
175 case 'u':
176 unum = getuint(ap, lflag);
177 printnum(func, handle, unum, 10, width, padc);
178 break;
179 case 'o':
180 unum = getuint(ap, lflag);
181 printnum(func, handle, unum, 8, width, padc);
182 break;
183 case 'p':
184 unum = (unsigned long)va_arg(ap, void *);
185 printnum(func, handle, unum, 8, width, padc);
186 break;
187 case 'x':
188 unum = getuint(ap, lflag);
189 printnum(func, handle, unum, 16, width, padc);
190 break;
191 case 'X':
192 unum = getuint(ap, lflag);
193 printnum(func, handle, unum, -16, width, padc);
194 break;
195 case 'l':
196 lflag = 8;
197 goto again;
198 case '%':
199 default: // Print Literally
200 func(ch, handle);
201 break;
202 }
203 }
204 return 0;
205}
206
207static void fileputc(int c, void* handle)
208{
209 fputc(c, (FILE *)handle);
210}
211
212int printf(const char *fmt, ...)
213{
214 int ret;
215 va_list ap;
216
217 va_start(ap, fmt);
218 ret = kvprintf(fmt, fileputc, (void *)stdout, ap);
219 va_end(ap);
220
221 return ret;
222}
223
224int fprintf(FILE *stream, const char *fmt, ...)
225{
226 int ret;
227 va_list ap;
228
229 va_start(ap, fmt);
230 ret = kvprintf(fmt, fileputc, stream, ap);
231 va_end(ap);
232
233 return ret;
234}
235
236typedef struct StrState {
237 char *buf;
238 char *cur;
239 size_t maxlen;
241
242static void strputc(int c, void *handle)
243{
244 StrState *state = (StrState *)handle;
245
246 if ((state->maxlen != -1) &&
247 (state->cur - state->buf >= state->maxlen)) {
248 state->cur[0] = '\0';
249 return;
250 }
251
252 state->cur[0] = c;
253 state->cur++;
254}
255
256int sprintf(char *str, const char *fmt, ...)
257{
258 int ret;
259 va_list ap;
260 StrState state;
261
262 state.buf = str;
263 state.cur = str;
264 state.maxlen = -1;
265
266 va_start(ap, fmt);
267 ret = kvprintf(fmt, strputc, &state, ap);
268 va_end(ap);
269
270 state.cur[0] = '\0';
271
272 return ret;
273}
274
275int snprintf(char *str, size_t n, const char *fmt, ...)
276{
277 int ret;
278 va_list ap;
279 StrState state;
280
281 state.buf = str;
282 state.cur = str;
283 state.maxlen = n;
284
285 va_start(ap, fmt);
286 ret = kvprintf(fmt, strputc, &state, ap);
287 va_end(ap);
288
289 state.cur[0] = '\0';
290
291 return ret;
292}
293
static char buf[4096]
Definition: ethdump.c:10
#define getuint(ap, lflag)
Definition: printf.c:13
static void printnum(void(*func)(int, void *), void *handle, uint64_t num, int base, int width, int padc)
Definition: printf.c:29
int printf(const char *fmt,...)
Definition: printf.c:212
int snprintf(char *str, size_t n, const char *fmt,...)
Definition: printf.c:275
size_t maxlen
Definition: printf.c:239
char * buf
Definition: printf.c:237
static int kvprintf(char const *fmt, void(*func)(int, void *), void *handle, va_list ap)
Definition: printf.c:75
int sprintf(char *str, const char *fmt,...)
Definition: printf.c:256
char * cur
Definition: printf.c:238
#define getint(ap, lflag)
Definition: printf.c:20
static const char * numberstring_upper
Definition: printf.c:27
static void fileputc(int c, void *handle)
Definition: printf.c:207
static const char * numberstring_lower
Definition: printf.c:26
int fprintf(FILE *stream, const char *fmt,...)
Definition: printf.c:224
static void strputc(int c, void *handle)
Definition: printf.c:242
static uint16_t base
Definition: sercons.c:37
#define va_arg(ap, type)
Definition: stdarg.h:12
#define va_end(ap)
Definition: stdarg.h:21
#define va_start(ap, last)
Definition: stdarg.h:9
__builtin_va_list va_list
Definition: stdarg.h:6
#define NULL
Definition: stddef.h:6
FILE * stdout
Definition: file.c:16
int fputc(int ch, FILE *fh)
Definition: file.c:124
Definition: stdio.h:8
size_t strlen(const char *str)
Definition: string.c:112
unsigned long uint64_t
Definition: types.h:13
signed long int64_t
Definition: types.h:8