Skip to content

Commit

Permalink
libc: implement %f, %lf format specifiers for scanf, strtod, fix strc…
Browse files Browse the repository at this point in the history
…hr function
  • Loading branch information
ffwff committed Sep 12, 2019
1 parent 86fc33e commit a4d8275
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 60 deletions.
20 changes: 17 additions & 3 deletions userspace/libraries/libc/src/core.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,23 @@ end

# Ints
struct Int
# needed by SimpleAllocator
def ~
self ^ -1
def to_int
self.to_i32
end
def to_uint
self.to_u32
end
def to_long
self.to_i32
end
def to_ulong
self.to_u32
end
def to_longlong
self.to_i64
end
def to_ulonglong
self.to_u64
end
end

Expand Down
86 changes: 86 additions & 0 deletions userspace/libraries/libc/src/functions/arch/shim/scanf.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,62 @@ static void __scanf_ungetc(char ch, void *userptr) {
slice->overflow_ch = ch;
}

struct scanf_fp {
int sign;
int intg_part;
unsigned int dec_part;
unsigned int dec_base;
};

static struct scanf_fp __scanf_atofp(ngets_fn_t ngets_fn, nungetc_fn_t ungetc_fn, void *userptr, int *readden) {
struct scanf_fp fp = { 0 };
fp.sign = 1;
fp.dec_base = 1;
char ch = 0;
int retval;

// negative or digit
if (!(retval = ngets_fn(&ch, 1, userptr)))
return fp;
if (ch == '-') {
fp.sign = -1;
(*readden)++;
} else if (ch == '+') {
(*readden)++;
} else if (isdigit(ch)) {
fp.intg_part = (int)(ch - '0');
(*readden)++;
} else {
return fp;
}

// integer part
while ((retval = ngets_fn(&ch, 1, userptr))) {
if (isdigit(ch)) {
int digit = ch - '0';
fp.intg_part = fp.intg_part * 10 + digit;
} else {
break;
}
(*readden)++;
}
// decimal part
if(ch == '.') {
(*readden)++;
while ((retval = ngets_fn(&ch, 1, userptr))) {
if (isdigit(ch)) {
int digit = ch - '0';
fp.dec_part = fp.dec_part * 10 + digit;
} else {
break;
}
(*readden)++;
fp.dec_base *= 10;
}
}
return fp;
}

// expose
static int __sscanf(ngets_fn_t ngets_fn, nungetc_fn_t ungetc_fn, void *userptr,
const char *restrict format, va_list args) {
Expand Down Expand Up @@ -84,6 +140,8 @@ static int __sscanf(ngets_fn_t ngets_fn, nungetc_fn_t ungetc_fn, void *userptr,
return readden;
if (ch == '-') {
sign = -1;
} else if (ch == '+') {
// noop
} else if (isdigit(ch)) {
num = (int)(ch - '0');
} else {
Expand Down Expand Up @@ -111,6 +169,34 @@ static int __sscanf(ngets_fn_t ngets_fn, nungetc_fn_t ungetc_fn, void *userptr,
*intptr = num;
break;
}
case 'f': {
format++;
struct scanf_fp fp = __scanf_atofp(ngets_fn, ungetc_fn, userptr, &readden);
// store
float d = (float)fp.sign * ((float)fp.intg_part + ((float)fp.dec_part / (float)fp.dec_base));
float *dptr = va_arg(args, float *);
*dptr = d;
break;
}
case 'l': {
format++;
switch (*format) {
case 0:
default: {
return readden;
}
case 'f': {
format++;
struct scanf_fp fp = __scanf_atofp(ngets_fn, ungetc_fn, userptr, &readden);
// store
float d = (double)fp.sign * ((double)fp.intg_part + ((double)fp.dec_part / (double)fp.dec_base));
double *dptr = va_arg(args, double *);
*dptr = d;
break;
}
}
break;
}
default: {
format--;
break;
Expand Down
11 changes: 11 additions & 0 deletions userspace/libraries/libc/src/functions/arch/shim/stdlib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <stdio.h>
#include <stdlib.h>

double strtod(const char *nptr, char **endptr) {
double retval = 0.0;
int written = sscanf(nptr, "%lf", &retval);
if(endptr != NULL) {
*endptr = (char *)nptr + written;
}
return retval;
}
34 changes: 14 additions & 20 deletions userspace/libraries/libc/src/functions/ctype.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@ fun tolower(ch : LibC::Int) : LibC::Int
ch
end

fun isspace(ch : LibC::Int) : LibC::Int
fun isspace(ch : LibC::Int) : Bool
ch = ch.unsafe_chr
(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ? 1 : 0
ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'
end

fun isprint(ch : LibC::Int) : LibC::Int
(ch >= 0x20 && ch <= 0x7e) ? 1 : 0
fun isprint(ch : LibC::Int) : Bool
ch >= 0x20 && ch <= 0x7e
end

fun isdigit(ch : LibC::Int) : LibC::Int
(ch >= '0'.ord && ch <= '9'.ord) ? 1 : 0
fun isdigit(ch : LibC::Int) : Bool
ch >= '0'.ord && ch <= '9'.ord
end

fun islower(ch : LibC::Int) : LibC::Int
(ch >= 'a'.ord && ch <= 'z'.ord) ? 1 : 0
fun islower(ch : LibC::Int) : Bool
ch >= 'a'.ord && ch <= 'z'.ord
end

fun isupper(ch : LibC::Int) : LibC::Int
(ch >= 'A'.ord && ch <= 'Z'.ord) ? 1 : 0
fun isupper(ch : LibC::Int) : Bool
ch >= 'A'.ord && ch <= 'Z'.ord
end

fun isalpha(ch : LibC::Int) : LibC::Int
(islower(ch) == 1 || isupper(ch) == 1) ? 1 : 0
fun isalpha(ch : LibC::Int) : Bool
islower(ch) || isupper(ch)
end

fun isgraph(ch : LibC::Int) : LibC::Int
Expand All @@ -61,12 +61,6 @@ fun isxdigit(ch : LibC::Int) : LibC::Int
0
end

fun isalnum(ch : LibC::Int) : LibC::Int
if isalpha(ch)
1
elsif isdigit(ch)
1
else
0
end
fun isalnum(ch : LibC::Int) : Bool
isalpha(ch) || isdigit(ch)
end
22 changes: 11 additions & 11 deletions userspace/libraries/libc/src/functions/stdio.cr
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ class File
# reading
def fputs(str)
return -1 unless @status.includes?(Status::Write)
len = strlen(str).to_i32
len = strlen(str).to_int
if @buffering == Buffering::Unbuffered
write(@fd, str, len).to_i32
write(@fd, str, len).to_int
else
@wbuffer.fwrite(@fd, str.as(UInt8*), len, line_buffered?)
end
Expand All @@ -145,17 +145,17 @@ class File
def fnputs(str, len)
return -1 unless @status.includes?(Status::Write)
if @buffering == Buffering::Unbuffered
write(@fd, str, len.to_i32).to_i32
write(@fd, str, len.to_int).to_int
else
@wbuffer.fwrite(@fd, str.as(UInt8*), len.to_i32, line_buffered?)
@wbuffer.fwrite(@fd, str.as(UInt8*), len.to_int, line_buffered?)
end
end

def fputc(c)
return -1 unless @status.includes?(Status::Write)
buffer = uninitialized Int8[1]
buffer.to_unsafe[0] = c.to_i8
write(@fd, buffer.to_unsafe, 1).to_i32
write(@fd, buffer.to_unsafe, 1).to_int
end

# getting
Expand Down Expand Up @@ -224,7 +224,7 @@ class File
def fread(ptr, len)
return 0u32 unless @status.includes?(Status::Read)
if @buffering == Buffering::Unbuffered
read(@fd, ptr.as(LibC::String), len.to_i32).to_u32
read(@fd, ptr.as(LibC::String), len.to_int).to_u32
else
abort
0u32
Expand All @@ -234,9 +234,9 @@ class File
def fwrite(ptr, len)
return 0u32 unless @status.includes?(Status::Write)
if @buffering == Buffering::Unbuffered
write(@fd, ptr.as(LibC::String), len.to_i32).to_u32
write(@fd, ptr.as(LibC::String), len.to_int).to_u32
else
ret = @wbuffer.fwrite(@fd, ptr.as(UInt8*), len.to_i32, line_buffered?)
ret = @wbuffer.fwrite(@fd, ptr.as(UInt8*), len.to_int, line_buffered?)
ret == EOF ? 0u32 : ret.to_u32
end
end
Expand Down Expand Up @@ -401,13 +401,13 @@ end

# prints
fun puts(data : LibC::String) : LibC::Int
ret = write(STDOUT, data, strlen(data).to_i32)
ret += putchar '\n'.ord.to_i32
ret = write(STDOUT, data, strlen(data).to_int)
ret += putchar '\n'.ord.to_int
ret
end

fun nputs(data : LibC::String, len : LibC::SizeT) : LibC::Int
write(STDOUT, data, len.to_i32)
write(STDOUT, data, len.to_int)
end

fun putchar(c : LibC::Int) : LibC::Int
Expand Down
5 changes: 0 additions & 5 deletions userspace/libraries/libc/src/functions/stdlib.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ fun strtoul(nptr : LibC::String, endptr : LibC::String*, base : LibC::Int) : Lib
0u32
end

fun strtod(nptr : LibC::String, endptr : LibC::String*) : Float64
abort
0.0f64
end

fun atoi(nptr : LibC::String) : LibC::Int
abort
0
Expand Down
14 changes: 7 additions & 7 deletions userspace/libraries/libc/src/functions/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fun strcmp(s1 : LibC::UString, s2 : LibC::UString) : LibC::Int
s1 += 1
s2 += 1
end
(s1.value - s2.value).to_i32
(s1.value - s2.value).to_int
end

fun strncmp(s1 : LibC::UString, s2 : LibC::UString, n : LibC::SizeT) : LibC::Int
Expand All @@ -35,7 +35,7 @@ fun strncmp(s1 : LibC::UString, s2 : LibC::UString, n : LibC::SizeT) : LibC::Int
n -= 1
end
return 0 if n == 0
(s1.value - s2.value).to_i32
(s1.value - s2.value).to_int
end

# cpy
Expand Down Expand Up @@ -63,7 +63,7 @@ fun strncpy(dst : LibC::String, src : LibC::String, n : LibC::SizeT) : LibC::Str
end

# tok
module Strtok
private module Strtok
extend self

@@saveptr = LibC::String.null
Expand Down Expand Up @@ -139,16 +139,16 @@ end
# chr
fun strchr(str : LibC::String, c : LibC::Int) : LibC::String
until str.value == c
str += 1
return LibC::String.null if str.value == 0
str += 1
end
str
end

# pbrk
fun strpbrk(s1 : LibC::String, s2 : LibC::String) : LibC::String
until s1.value == 0
return s1 if strchr(s2, s1.value.to_i32)
return s1 if strchr(s2, s1.value.to_int)
s1 += 1
end
LibC::String.null
Expand All @@ -157,7 +157,7 @@ end
# spn
fun strspn(s1 : LibC::String, s2 : LibC::String) : LibC::SizeT
ret = 0u32
while s1.value != 0 && strchr(s2, s1.value.to_i32)
while s1.value != 0 && strchr(s2, s1.value.to_int)
s1 += 1
ret += 1
end
Expand Down Expand Up @@ -218,7 +218,7 @@ fun memcmp(s1 : LibC::UString, s2 : LibC::UString, n : LibC::SizeT) : LibC::Int
n -= 1
end
return 0 if n == 0
(s1.value - s2.value).to_i32
(s1.value - s2.value).to_int
end

fun memchr(str : LibC::String, c : LibC::Int, n : LibC::SizeT) : LibC::String
Expand Down
Loading

0 comments on commit a4d8275

Please sign in to comment.