308 lines
4.0 KiB
C
308 lines
4.0 KiB
C
|
/*
|
||
|
Copyright (C) 2015-2019 The University of Notre Dame
|
||
|
This software is distributed under the GNU General Public License.
|
||
|
See the file LICENSE for details.
|
||
|
*/
|
||
|
|
||
|
#include "kernel/types.h"
|
||
|
#include "kernel/ascii.h"
|
||
|
#include "library/malloc.h"
|
||
|
#include "library/string.h"
|
||
|
#include "library/malloc.h"
|
||
|
#include "stdarg.h"
|
||
|
|
||
|
void strcpy(char *d, const char *s)
|
||
|
{
|
||
|
while(*s) {
|
||
|
*d++ = *s++;
|
||
|
}
|
||
|
*d = 0;
|
||
|
}
|
||
|
|
||
|
void strncpy(char *d, const char *s, unsigned length)
|
||
|
{
|
||
|
while(*s && length--) {
|
||
|
*d++ = *s++;
|
||
|
}
|
||
|
*d = 0;
|
||
|
}
|
||
|
|
||
|
char * strdup(const char *s)
|
||
|
{
|
||
|
char * d = (char *)malloc((strlen(s)+1) * sizeof(char));
|
||
|
char * tmp = d;
|
||
|
while(*s) {
|
||
|
*tmp++ = *s++;
|
||
|
}
|
||
|
*tmp = 0;
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
int strcmp(const char *a, const char *b)
|
||
|
{
|
||
|
while(1) {
|
||
|
if(*a < *b) {
|
||
|
return -1;
|
||
|
} else if(*a > *b) {
|
||
|
return 1;
|
||
|
} else if(*a == 0) {
|
||
|
return 0;
|
||
|
} else {
|
||
|
a++;
|
||
|
b++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int strncmp(const char *a, const char *b, unsigned length)
|
||
|
{
|
||
|
while(length > 0) {
|
||
|
if(*a < *b) {
|
||
|
return -1;
|
||
|
} else if(*a > *b) {
|
||
|
return 1;
|
||
|
} else if(*a == 0) {
|
||
|
return 0;
|
||
|
} else {
|
||
|
a++;
|
||
|
b++;
|
||
|
length--;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
unsigned strlen(const char *s)
|
||
|
{
|
||
|
unsigned len = 0;
|
||
|
while(*s) {
|
||
|
len++;
|
||
|
s++;
|
||
|
}
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
char *strrev(char *s)
|
||
|
{
|
||
|
unsigned start = 0;
|
||
|
unsigned end = strlen(s) - 1;
|
||
|
char swap;
|
||
|
|
||
|
while(start < end) {
|
||
|
swap = s[start];
|
||
|
s[start] = s[end];
|
||
|
s[end] = swap;
|
||
|
|
||
|
start++;
|
||
|
end--;
|
||
|
}
|
||
|
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
char *strcat(char *d, const char *s)
|
||
|
{
|
||
|
strcpy(d + strlen(d), s);
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
const char *strchr(const char *s, char ch)
|
||
|
{
|
||
|
while(*s) {
|
||
|
if(*s == ch)
|
||
|
return s;
|
||
|
s++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char *strtok(char *s, const char *delim)
|
||
|
{
|
||
|
static char *oldword = 0;
|
||
|
char *word;
|
||
|
|
||
|
if(!s)
|
||
|
s = oldword;
|
||
|
|
||
|
while(*s && strchr(delim, *s))
|
||
|
s++;
|
||
|
|
||
|
if(!*s) {
|
||
|
oldword = s;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
word = s;
|
||
|
while(*s && !strchr(delim, *s))
|
||
|
s++;
|
||
|
|
||
|
if(*s) {
|
||
|
*s = 0;
|
||
|
oldword = s + 1;
|
||
|
} else {
|
||
|
oldword = s;
|
||
|
}
|
||
|
|
||
|
return word;
|
||
|
}
|
||
|
|
||
|
int str2int(const char *s, int *d)
|
||
|
{
|
||
|
int val = 0;
|
||
|
for(; *s; ++s) {
|
||
|
val *= 10;
|
||
|
if(*s > ASCII_9 || *s < ASCII_0) {
|
||
|
return 0;
|
||
|
}
|
||
|
val += (*s - '0');
|
||
|
}
|
||
|
*d = val;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void memset(void *vd, char value, unsigned length)
|
||
|
{
|
||
|
char *d = vd;
|
||
|
while(length) {
|
||
|
*d = value;
|
||
|
length--;
|
||
|
d++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void memcpy(void *vd, const void *vs, unsigned length)
|
||
|
{
|
||
|
char *d = vd;
|
||
|
const char *s = vs;
|
||
|
while(length) {
|
||
|
*d = *s;
|
||
|
d++;
|
||
|
s++;
|
||
|
length--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern void printf_putstring(const char *str);
|
||
|
extern void printf_putchar(char c);
|
||
|
|
||
|
static void printf_puthexdigit(uint8_t i)
|
||
|
{
|
||
|
if(i < 10) {
|
||
|
printf_putchar('0' + i);
|
||
|
} else {
|
||
|
printf_putchar('a' + i - 10);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void printf_puthex(uint32_t i)
|
||
|
{
|
||
|
int j;
|
||
|
for(j = 28; j >= 0; j = j - 4) {
|
||
|
printf_puthexdigit((i >> j) & 0x0f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void printf_putint(int32_t i)
|
||
|
{
|
||
|
int f, d;
|
||
|
if(i < 0 && i != 0) {
|
||
|
printf_putchar('-');
|
||
|
i = -i;
|
||
|
}
|
||
|
|
||
|
f = 1;
|
||
|
while((i / f) >= 10) {
|
||
|
f *= 10;
|
||
|
}
|
||
|
while(f > 0) {
|
||
|
d = i / f;
|
||
|
printf_putchar('0' + d);
|
||
|
i = i - d * f;
|
||
|
f = f / 10;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void printf_putuint(uint32_t u)
|
||
|
{
|
||
|
int f, d;
|
||
|
f = 1;
|
||
|
while((u / f) >= 10) {
|
||
|
f *= 10;
|
||
|
}
|
||
|
while(f > 0) {
|
||
|
d = u / f;
|
||
|
printf_putchar('0' + d);
|
||
|
u = u - d * f;
|
||
|
f = f / 10;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void printf(const char *s, ...)
|
||
|
{
|
||
|
va_list args;
|
||
|
|
||
|
uint32_t u;
|
||
|
int32_t i;
|
||
|
char *str;
|
||
|
|
||
|
va_start(args, s);
|
||
|
|
||
|
while(*s) {
|
||
|
if(*s != '%') {
|
||
|
printf_putchar(*s);
|
||
|
} else {
|
||
|
s++;
|
||
|
switch (*s) {
|
||
|
case 'd':
|
||
|
i = va_arg(args, int32_t);
|
||
|
printf_putint(i);
|
||
|
break;
|
||
|
case 'u':
|
||
|
u = va_arg(args, uint32_t);
|
||
|
printf_putuint(u);
|
||
|
break;
|
||
|
case 'x':
|
||
|
u = va_arg(args, uint32_t);
|
||
|
printf_puthex(u);
|
||
|
break;
|
||
|
case 's':
|
||
|
str = va_arg(args, char *);
|
||
|
printf_putstring(str);
|
||
|
break;
|
||
|
case 'c':
|
||
|
u = va_arg(args, int32_t);
|
||
|
printf_putchar(u);
|
||
|
break;
|
||
|
case 0:
|
||
|
return;
|
||
|
break;
|
||
|
default:
|
||
|
printf_putchar(*s);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
s++;
|
||
|
}
|
||
|
va_end(args);
|
||
|
}
|
||
|
|
||
|
char *uint_to_string(uint32_t u, char *s)
|
||
|
{
|
||
|
uint32_t f, d, i;
|
||
|
|
||
|
f = 1;
|
||
|
i = 0;
|
||
|
while((u / (f * 10)) > 0) {
|
||
|
f *= 10;
|
||
|
}
|
||
|
while(f > 0) {
|
||
|
d = u / f;
|
||
|
s[i] = '0' + d;
|
||
|
u = u % f;
|
||
|
f = f / 10;
|
||
|
i++;
|
||
|
}
|
||
|
s[i] = 0;
|
||
|
return s;
|
||
|
}
|