orca-software
hf-printf.h
1 /*
2 printf from hellfireos
3 https://github.com/sjohann81/hellfireos/tree/master/lib/libc
4 */
5 #ifndef __HF_PRINTF__
6 #define __HF_PRINTF__
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 #include <stdarg.h>
13 #include <stdint.h>
14 
15 #define DEBUG_ADDR 0xf00000d0
16 
17 #define isdigit(c) ('0' <= (c) && (c) <= '9')
18 #define NULL ((void *)0)
19 
20 void putchar(int32_t value)
21 { volatile uint32_t* DEBUG = (volatile uint32_t*) DEBUG_ADDR;
22  *DEBUG = value;
23 }
24 
25 void *memcpy(void *dst, const void *src, uint32_t n){
26  int8_t *r1 = dst;
27  const int8_t *r2 = src;
28 
29  while (n--)
30  *r1++ = *r2++;
31 
32  return dst;
33 }
34 
35 static uint32_t divide(long *n, int base)
36 {
37  uint32_t res;
38 
39  res = ((uint32_t)*n) % base;
40  *n = (long)(((uint32_t)*n) / base);
41  return res;
42 }
43 
44 static int toint(const char **s)
45 {
46  int i = 0;
47  while (isdigit((int)**s))
48  i = i * 10 + *((*s)++) - '0';
49  return i;
50 }
51 
52 static void printchar(int8_t **str, int32_t c){
53  if (str){
54  **str = c;
55  ++(*str);
56  }else{
57  if (c) putchar(c);
58  }
59 }
60 
61 static int vsprintf(char **buf, const char *fmt, va_list args)
62 {
63  char **p, *str;
64  const char *digits = "0123456789abcdef";
65  char pad, tmp[16];
66  int width, base, sign, i;
67  long num;
68 
69  for (p = buf; *fmt; fmt++) {
70  if (*fmt != '%') {
71  printchar(p, *fmt);
72  continue;
73  }
74  // get flags
75  ++fmt;
76  pad = ' ';
77  if (*fmt == '0') {
78  pad = '0';
79  fmt++;
80  }
81  // get width
82  width = -1;
83  if (isdigit(*fmt)) {
84  width = toint(&fmt);
85  }
86  // ignore long
87  if (*fmt == 'l')
88  fmt++;
89  base = 10;
90  sign = 0;
91  switch (*fmt) {
92  case 'c':
93  printchar(p, (char)va_arg(args, int));
94  continue;
95  case 's':
96  str = va_arg(args, char *);
97  if (str == NULL)
98  str = "<NULL>";
99  for (; *str && width != 0; str++, width--) {
100  printchar(p, *str);
101  }
102  while (width-- > 0)
103  printchar(p, pad);
104  continue;
105  case 'X':
106  case 'x':
107  base = 16;
108  break;
109  case 'd':
110  sign = 1;
111  break;
112  case 'u':
113  break;
114  default:
115  continue;
116  }
117  num = va_arg(args, long);
118  if (sign && num < 0) {
119  num = -num;
120  printchar(p, '-');
121  width--;
122  }
123  i = 0;
124  if (num == 0)
125  tmp[i++] = '0';
126  else
127  while (num != 0)
128  tmp[i++] = digits[divide(&num, base)];
129  width -= i;
130  while (width-- > 0)
131  printchar(p, pad);
132  while (i-- > 0)
133  printchar(p, tmp[i]);
134  }
135  printchar(p, '\0');
136 
137  return 0;
138 }
139 
140 int32_t printf(const int8_t *fmt, ...){
141  va_list args;
142  int32_t v;
143 
144  va_start(args, fmt);
145  v = vsprintf(0, fmt, args);
146  va_end(args);
147  return v;
148 }
149 
150 int32_t sprintf(int8_t *out, const int8_t *fmt, ...){
151  va_list args;
152  int32_t v;
153 
154  va_start(args, fmt);
155  v = vsprintf(&out, fmt, args);
156  va_end(args);
157  return v;
158 }
159 
161  float f;
162  int32_t l;
163  uint32_t u;
164 };
165 
166 int8_t *itoa(int32_t i, int8_t *s, int32_t base){
167  int8_t *ptr = s, *ptr1 = s, tmp_char;
168  int32_t tmp_value;
169 
170  if (base < 2 || base > 36) {
171  *s = '\0';
172  return s;
173  }
174  do {
175  tmp_value = i;
176  i /= base;
177  *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - i * base)];
178  } while (i);
179  if (tmp_value < 0)
180  *ptr++ = '-';
181  *ptr-- = '\0';
182  while(ptr1 < ptr) {
183  tmp_char = *ptr;
184  *ptr--= *ptr1;
185  *ptr1++ = tmp_char;
186  }
187  return s;
188 }
189 
190 
191 int32_t ftoa(float f, int8_t *outbuf, int32_t precision){
192  int32_t mantissa, int_part, frac_part, exp2, i;
193  int8_t *p;
194  union float_long fl;
195 
196  p = outbuf;
197 
198  if (f < 0.0){
199  *p = '-';
200  f = -f;
201  p++;
202  }
203 
204  fl.f = f;
205 
206  exp2 = (fl.l >> 23) - 127;
207  mantissa = (fl.l & 0xffffff) | 0x800000;
208  frac_part = 0;
209  int_part = 0;
210 
211  if (exp2 >= 31){
212  return -1; /* too large */
213  }else{
214  if (exp2 < -23){
215 // return -1; /* too small */
216  }else{
217  if (exp2 >= 23){
218  int_part = mantissa << (exp2 - 23);
219  }else{
220  if (exp2 >= 0){
221  int_part = mantissa >> (23 - exp2);
222  frac_part = (mantissa << (exp2 + 1)) & 0xffffff;
223  }else{
224  frac_part = (mantissa & 0xffffff) >> (-(exp2 + 1));
225  }
226  }
227  }
228  }
229 
230  if (int_part == 0){
231  *p = '0';
232  p++;
233  }else{
234  itoa(int_part, p, 10);
235  while(*p) p++;
236  }
237  *p = '.';
238  p++;
239 
240  for (i = 0; i < precision; i++){
241  frac_part = (frac_part << 3) + (frac_part << 1);
242  *p = (frac_part >> 24) + '0';
243  p++;
244  frac_part = frac_part & 0xffffff;
245  }
246 
247  *p = 0;
248 
249  return 0;
250 }
251 
252 
253 #ifdef __cplusplus
254 }
255 #endif
256 
257 #endif //__HF_PRINTF__
Definition: hf-printf.h:160