freestanding: ptr_str, string concat, struct declaration

* compiler: extract c_common_macros from c_headers, and use it in bare_c_headers too. Support for ptr_str and string concatenation in -freestanding mode.

* Add tests for structs and string concatenation in -freestanding mode .

* Move check_string_add_works to string/string.v .
pull/3119/head
Delyan Angelov 2019-12-16 18:05:33 +02:00 committed by Alexander Medvednikov
parent dadf147382
commit b7c477cc18
6 changed files with 109 additions and 31 deletions

View File

@ -1 +1,5 @@
checks checks
linuxsys/linuxsys
string/string
consts/consts
structs/structs

View File

@ -26,6 +26,7 @@ fn main() {
vcheck("linuxsys") vcheck("linuxsys")
vcheck("string") vcheck("string")
vcheck("consts") vcheck("consts")
vcheck("structs")
exit(0) exit(0)
} }

View File

@ -39,12 +39,24 @@ fn check_str_clone() {
assert c == "-6789" assert c == "-6789"
} }
fn check_string_add_works(){
abc := 'abc'
combined := 'a' + 'b' + 'c'
assert abc.len == combined.len
assert abc[0] == combined[0]
assert abc[1] == combined[1]
assert abc[2] == combined[2]
assert abc[0] == `a`
assert abc == combined
}
fn main () { fn main () {
mut fails := 0 mut fails := 0
fails += forkedtest.normal_run(check_string_eq, "check_string_eq") fails += forkedtest.normal_run(check_string_eq, "check_string_eq")
fails += forkedtest.normal_run(check_i64_tos, "check_i64_tos") fails += forkedtest.normal_run(check_i64_tos, "check_i64_tos")
fails += forkedtest.normal_run(check_i64_str, "check_i64_str") fails += forkedtest.normal_run(check_i64_str, "check_i64_str")
fails += forkedtest.normal_run(check_str_clone, "check_str_clone") fails += forkedtest.normal_run(check_str_clone, "check_str_clone")
fails += forkedtest.normal_run(check_string_add_works, "check_string_add_works")
assert fails == 0 assert fails == 0
sys_exit(0) sys_exit(0)
} }

View File

@ -0,0 +1,42 @@
module main
import forkedtest
struct SimpleEmptyStruct{
}
struct NonEmptyStruct{
x int
y int
z int
}
fn check_simple_empty_struct(){
s := SimpleEmptyStruct{}
addr_s := &s
str_addr_s := ptr_str( addr_s )
assert !isnil(addr_s)
assert str_addr_s.len > 3
println(str_addr_s)
}
fn check_non_empty_struct(){
a := NonEmptyStruct{1,2,3}
b := NonEmptyStruct{4,5,6}
assert sizeof(NonEmptyStruct) > 0
assert sizeof(SimpleEmptyStruct) < sizeof(NonEmptyStruct)
assert a.x == 1
assert a.y == 2
assert a.z == 3
assert b.x + b.y + b.z == 15
assert ptr_str(&a) != ptr_str(&b)
println('sizeof SimpleEmptyStruct:' + i64_str( sizeof(SimpleEmptyStruct) , 10 ))
println('sizeof NonEmptyStruct:' + i64_str( sizeof(NonEmptyStruct) , 10 ))
}
fn main(){
mut fails := 0
fails += forkedtest.normal_run(check_simple_empty_struct, "check_simple_empty_struct")
fails += forkedtest.normal_run(check_non_empty_struct, "check_non_empty_struct")
assert fails == 0
sys_exit(0)
}

View File

@ -22,6 +22,22 @@ pub fn tos(s byteptr, len int) string {
} }
} }
fn (s string) add(a string) string {
new_len := a.len + s.len
mut res := string {
len: new_len
str: malloc(new_len + 1)
}
for j := 0; j < s.len; j++ {
res[j] = s[j]
}
for j := 0; j < a.len; j++ {
res[s.len + j] = a[j]
}
res[new_len] = `\0`// V strings are not null terminated, but just in case
return res
}
/* /*
pub fn tos_clone(s byteptr) string { pub fn tos_clone(s byteptr) string {
if s == 0 { if s == 0 {
@ -100,6 +116,13 @@ pub fn i64_str(n0 i64, base int) string {
return i64_tos(buf, 79, n0, base) return i64_tos(buf, 79, n0, base)
} }
pub fn ptr_str(ptr voidptr) string {
buf := [16]byte
hex := i64_tos(buf, 15, i64(ptr), 16)
res := '0x' + hex
return res
}
pub fn (a string) clone() string { pub fn (a string) clone() string {
mut b := string { mut b := string {
len: a.len len: a.len
@ -109,3 +132,4 @@ pub fn (a string) clone() string {
b[a.len] = `\0` b[a.len] = `\0`
return b return b
} }

View File

@ -2,6 +2,28 @@ module compiler
const ( const (
c_common_macros = '
#define EMPTY_STRUCT_DECLARATION
#define EMPTY_STRUCT_INITIALIZATION 0
// Due to a tcc bug, the length of an array needs to be specified, but GCC crashes if it is...
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[])
#define TCCSKIP(x) x
#ifdef __TINYC__
#undef EMPTY_STRUCT_DECLARATION
#undef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_DECLARATION char _dummy
#define EMPTY_STRUCT_INITIALIZATION 0
#undef EMPTY_ARRAY_OF_ELEMS
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n])
#undef TCCSKIP
#define TCCSKIP(x)
#endif
#define OPTION_CAST(x) (x)
'
c_headers = ' c_headers = '
//#include <inttypes.h> // int64_t etc //#include <inttypes.h> // int64_t etc
@ -69,24 +91,7 @@ c_headers = '
#include <sys/wait.h> // os__wait uses wait on nix #include <sys/wait.h> // os__wait uses wait on nix
#endif #endif
#define EMPTY_STRUCT_DECLARATION $c_common_macros
#define EMPTY_STRUCT_INITIALIZATION 0
// Due to a tcc bug, the length of an array needs to be specified, but GCC crashes if it is...
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[])
#define TCCSKIP(x) x
#ifdef __TINYC__
#undef EMPTY_STRUCT_DECLARATION
#undef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_DECLARATION char _dummy
#define EMPTY_STRUCT_INITIALIZATION 0
#undef EMPTY_ARRAY_OF_ELEMS
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n])
#undef TCCSKIP
#define TCCSKIP(x)
#endif
#define OPTION_CAST(x) (x)
#ifdef _WIN32 #ifdef _WIN32
#define WINVER 0x0600 #define WINVER 0x0600
@ -209,19 +214,7 @@ typedef map map_string;
bare_c_headers = ' bare_c_headers = '
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[]) $c_common_macros
#define TCCSKIP(x) x
#ifdef __TINYC__
#undef EMPTY_ARRAY_OF_ELEMS
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n])
#undef TCCSKIP
#define TCCSKIP(x)
#endif
#ifndef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_INITIALIZATION 0
#endif
#ifndef exit #ifndef exit
#define exit(rc) sys_exit(rc) #define exit(rc) sys_exit(rc)
@ -229,3 +222,5 @@ void sys_exit (int);
#endif #endif
' '
) )