Skip to content

Commit 8a60de9

Browse files
committed
Add libc
0 parents  commit 8a60de9

2 files changed

Lines changed: 325 additions & 0 deletions

File tree

libc.c

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
#include "libc.h"
2+
3+
#include <stdarg.h>
4+
5+
void _putchar(char character);
6+
7+
/** \brief Division result
8+
* \sa uidiv
9+
*/
10+
typedef struct uidiv_result {
11+
u32_t quo; ///< Quotient
12+
u32_t rem; ///< Remainder
13+
} uidiv_result_t;
14+
15+
/********************************************//**
16+
* \brief Unsigned integer division
17+
*
18+
* ARM does not have native division support
19+
* \returns Result of operation or zero if
20+
* dividing by zero.
21+
***********************************************/
22+
uidiv_result_t
23+
uidiv (u32_t num, ///< Numerator
24+
u32_t dem) ///< Denominator
25+
{
26+
u32_t tmp = dem;
27+
uidiv_result_t ans = {0};
28+
29+
if (dem == 0)
30+
{
31+
// TODO: Somehow make error
32+
return ans;
33+
}
34+
35+
while (tmp <= num >> 1)
36+
{
37+
tmp <<= 1;
38+
}
39+
40+
do
41+
{
42+
if (num >= tmp)
43+
{
44+
num -= tmp;
45+
ans.quo++;
46+
}
47+
ans.quo <<= 1;
48+
tmp >>= 1;
49+
} while (tmp >= dem);
50+
ans.quo >>= 1;
51+
ans.rem = num;
52+
53+
return ans;
54+
}
55+
56+
void* memset(void* dst, int c, u32_t n)
57+
{
58+
char* q = dst;
59+
char* end = q + n;
60+
61+
for (;;) {
62+
if (q >= end) break; *q++ = (char) c;
63+
if (q >= end) break; *q++ = (char) c;
64+
if (q >= end) break; *q++ = (char) c;
65+
if (q >= end) break; *q++ = (char) c;
66+
}
67+
68+
return dst;
69+
}
70+
71+
u32_t
72+
strlen(const char *str)
73+
{
74+
const char *s;
75+
76+
for (s = str; *s; ++s)
77+
;
78+
return (s - str);
79+
}
80+
81+
// thanks naehrwert for the tiny printf
82+
static void _putn(char **p_str, u32_t x, u32_t base, char fill, int fcnt, int upper)
83+
{
84+
char buf[65];
85+
char *digits;
86+
char *p;
87+
int c = fcnt;
88+
uidiv_result_t div_res;
89+
90+
if (upper)
91+
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
92+
else
93+
digits = "0123456789abcdefghijklmnopqrstuvwxyz";
94+
95+
if(base > 36)
96+
return;
97+
98+
p = buf + 64;
99+
*p = 0;
100+
do
101+
{
102+
c--;
103+
div_res = uidiv (x, base);
104+
*--p = digits[div_res.rem];
105+
x = div_res.quo;
106+
}while(x);
107+
108+
if(fill != 0)
109+
{
110+
while(c > 0)
111+
{
112+
*--p = fill;
113+
c--;
114+
}
115+
}
116+
117+
for(; *p != '\0'; *((*p_str)++) = *(p++));
118+
}
119+
120+
/********************************************//**
121+
* \brief Simple @c vsprintf
122+
*
123+
* Only supports %c, %s, %u, %x, %X with
124+
* optional zero padding.
125+
* Always returns zero.
126+
***********************************************/
127+
int vsprintf (char *str, const char *fmt, va_list ap)
128+
{
129+
char *s;
130+
char c, fill;
131+
int fcnt;
132+
u32_t n;
133+
134+
while(*fmt)
135+
{
136+
if(*fmt == '%')
137+
{
138+
fmt++;
139+
fill = 0;
140+
fcnt = 0;
141+
if((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
142+
if(*(fmt+1) >= '0' && *(fmt+1) <= '9')
143+
{
144+
fill = *fmt;
145+
fcnt = *(fmt+1) - '0';
146+
fmt++;
147+
fmt++;
148+
}
149+
switch(*fmt)
150+
{
151+
case 'c':
152+
c = va_arg(ap, u32_t);
153+
*(str++) = c;
154+
break;
155+
case 's':
156+
s = va_arg(ap, char *);
157+
for(; *s != '\0'; *(str++) = *(s++));
158+
break;
159+
case 'u':
160+
n = va_arg(ap, u32_t);
161+
_putn(&str, n, 10, fill, fcnt, 0);
162+
break;
163+
case 'x':
164+
n = va_arg(ap, u32_t);
165+
_putn(&str, n, 16, fill, fcnt, 0);
166+
break;
167+
case 'X':
168+
n = va_arg(ap, u32_t);
169+
_putn(&str, n, 16, fill, fcnt, 1);
170+
break;
171+
case '%':
172+
*(str++) = '%';
173+
break;
174+
case '\0':
175+
goto out;
176+
default:
177+
*(str++) = '%';
178+
*(str++) = *fmt;
179+
break;
180+
}
181+
}
182+
else
183+
*(str++) = *fmt;
184+
fmt++;
185+
}
186+
187+
out:
188+
*str = '\0';
189+
return 0;
190+
}
191+
192+
/********************************************//**
193+
* \brief Simple @c sprintf
194+
*
195+
* Only supports %c, %s, %u, %x, %X with
196+
* optional zero padding.
197+
* Always returns zero.
198+
***********************************************/
199+
int sprintf (char *str, const char *format, ...)
200+
{
201+
va_list arg;
202+
203+
va_start (arg, format);
204+
vsprintf (str, format, arg);
205+
va_end (arg);
206+
return 0;
207+
}
208+
209+
int putchar(int c) {
210+
_putchar(c);
211+
return 0;
212+
}
213+
214+
int printf(const char *format, ...) {
215+
char line[512] = {0};
216+
va_list arg;
217+
218+
va_start (arg, format);
219+
vsprintf (line, format, arg);
220+
va_end (arg);
221+
222+
for (char *c = line; *c; ++c) {
223+
putchar(*c);
224+
}
225+
226+
return 0;
227+
}
228+
229+
int puts(const char *line) {
230+
for (const char *c = line; *c; ++c) {
231+
putchar(*c);
232+
}
233+
putchar('\n');
234+
return 0;
235+
}
236+
237+
char *
238+
strcpy(char *to, const char *from)
239+
{
240+
char *save = to;
241+
242+
for (; (*to = *from) != '\0'; ++from, ++to);
243+
return(save);
244+
}
245+
246+
char *
247+
strcat(char *dest, const char *src)
248+
{
249+
strcpy(dest + strlen(dest), src);
250+
return dest;
251+
}
252+
253+
/*
254+
* Compare strings.
255+
*/
256+
int
257+
strcmp(const char *s1, const char *s2)
258+
{
259+
while (*s1 == *s2++)
260+
if (*s1++ == 0)
261+
return (0);
262+
return (*(unsigned char *)s1 - *(unsigned char *)--s2);
263+
}
264+
265+
int
266+
strncmp(const char *s1, const char *s2, u32_t n)
267+
{
268+
if (n == 0)
269+
return (0);
270+
do {
271+
if (*s1 != *s2++)
272+
return (*(unsigned char *)s1 - *(unsigned char *)--s2);
273+
if (*s1++ == 0)
274+
break;
275+
} while (--n != 0);
276+
return (0);
277+
}
278+
279+
void *memcpy(void *dest, const void *src, size_t n)
280+
{
281+
char *dp = dest;
282+
const char *sp = src;
283+
while (n--)
284+
*dp++ = *sp++;
285+
return dest;
286+
}
287+
288+
int memcmp(const void* s1, const void* s2,size_t n)
289+
{
290+
const unsigned char *p1 = s1, *p2 = s2;
291+
while(n--)
292+
if( *p1 != *p2 )
293+
return *p1 - *p2;
294+
else
295+
p1++,p2++;
296+
return 0;
297+
}

libc.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#pragma once
2+
3+
/** \name Fixed width integers
4+
* @{
5+
*/
6+
typedef unsigned char u8_t; ///< Unsigned 8-bit type
7+
typedef unsigned short int u16_t; ///< Unsigned 16-bit type
8+
typedef unsigned int u32_t; ///< Unsigned 32-bit type
9+
typedef unsigned long long u64_t; ///< Unsigned 64-bit type
10+
11+
typedef u64_t u64;
12+
typedef u32_t u32;
13+
typedef u16_t u16;
14+
typedef u8_t u8;
15+
16+
typedef unsigned size_t;
17+
18+
size_t strlen(const char *str);
19+
int printf(const char *format, ...);
20+
int sprintf (char *str, const char *format, ...);
21+
char *strcpy(char *to, const char *from);
22+
int strncmp(const char *s1, const char *s2, u32_t n);
23+
void* memset(void* dst, int c, u32_t n);
24+
void *memcpy(void *dest, const void *src, size_t n);
25+
int strcmp(const char *s1, const char *s2);
26+
27+
int puts(const char *line);
28+
int memcmp(const void* s1, const void* s2,size_t n);

0 commit comments

Comments
 (0)