diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index bf882e7e54..7e8b35d7c9 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -11,7 +11,9 @@ import ( pub struct TestSession { pub mut: files []string + skip_files []string vexe string + vroot string vargs string failed bool benchmark benchmark.Benchmark @@ -19,9 +21,20 @@ pub mut: } pub fn new_test_session(_vargs string) TestSession { + mut skip_files := []string + skip_files << '_non_existing_' + $if solaris { + skip_files << "examples/gg2.v" + skip_files << "examples/pico/pico.v" + skip_files << "examples/sokol_examples/fonts.v" + skip_files << "examples/sokol_examples/drawing.v" + } vargs := _vargs.replace('-silent', '') + vexe := pref.vexe_path() return TestSession{ - vexe: pref.vexe_path() + vexe: vexe + vroot: os.dir(vexe) + skip_files: skip_files vargs: vargs show_ok_tests: !_vargs.contains('-silent') } @@ -91,7 +104,7 @@ fn worker_trunner(p mut sync.PoolProcessor, idx int, thread_id int) voidptr { } tls_bench.cstep = idx dot_relative_file := p.get_string_item(idx) - relative_file := dot_relative_file.replace('./', '') + relative_file := dot_relative_file.replace(ts.vroot + os.path_separator, '').replace('./', '') file := os.real_path(relative_file) // Ensure that the generated binaries will be stored in the temporary folder. // Remove them after a test passes/fails. @@ -109,6 +122,12 @@ fn worker_trunner(p mut sync.PoolProcessor, idx int, thread_id int) voidptr { // eprintln('>>> v cmd: $cmd') ts.benchmark.step() tls_bench.step() + if relative_file in ts.skip_files { + ts.benchmark.skip() + tls_bench.skip() + eprintln(tls_bench.step_message_skip(relative_file)) + return sync.no_result + } if show_stats { eprintln(term.h_divider('-')) status := os.system(cmd) diff --git a/vlib/benchmark/benchmark.v b/vlib/benchmark/benchmark.v index d2511e18ba..6629685955 100644 --- a/vlib/benchmark/benchmark.v +++ b/vlib/benchmark/benchmark.v @@ -46,8 +46,9 @@ SPENT 462 ms in code_2 const ( - BOK = term.ok_message('OK') + BOK = term.ok_message('OK ') BFAIL = term.fail_message('FAIL') + BSKIP = term.fail_message('SKIP') BSPENT = term.ok_message('SPENT') ) @@ -60,6 +61,7 @@ pub mut: ntotal int nok int nfail int + nskip int verbose bool nexpected_steps int cstep int @@ -106,6 +108,12 @@ pub fn (b mut Benchmark) ok() { b.nok++ } +pub fn (b mut Benchmark) skip() { + b.step_end_time = benchmark.now() + b.ntotal++ + b.nskip++ +} + pub fn (b mut Benchmark) fail_many(n int) { b.step_end_time = benchmark.now() b.ntotal += n @@ -169,8 +177,12 @@ pub fn (b &Benchmark) step_message_fail(msg string) string { return b.step_message_with_label(BFAIL, msg) } +pub fn (b &Benchmark) step_message_skip(msg string) string { + return b.step_message_with_label(BSKIP, msg) +} + pub fn (b &Benchmark) total_message(msg string) string { - mut tmsg := '${msg}\n ok, fail, total = ' + term.ok_message('${b.nok:5d}') + ', ' + if b.nfail > 0 { term.fail_message('${b.nfail:5d}') } else { '${b.nfail:5d}' } + ', ' + '${b.ntotal:5d}' + mut tmsg := '${msg}\n ok, fail, skip, total = ' + term.ok_message('${b.nok:5d}') + ', ' + if b.nfail > 0 { term.fail_message('${b.nfail:5d}') } else { '${b.nfail:5d}' } + ', ' + '${b.nskip:5d}'+ ', ' + '${b.ntotal:5d}' if b.verbose { tmsg = '<=== total time spent $tmsg' } diff --git a/vlib/builtin/option.v b/vlib/builtin/option.v index 9c1649826f..133c8d9e23 100644 --- a/vlib/builtin/option.v +++ b/vlib/builtin/option.v @@ -14,7 +14,7 @@ struct Option2 { struct Option { - data [300]byte + data [400]byte error string ecode int ok bool @@ -23,8 +23,8 @@ struct Option { // `fn foo() ?Foo { return foo }` => `fn foo() ?Foo { return opt_ok(foo); }` fn opt_ok(data voidptr, size int) Option { - if size >= 300 { - panic('option size too big: $size (max is 300), this is a temporary limit') + if size >= 400 { + panic('option size too big: $size (max is 400), this is a temporary limit') } res := Option{ ok: true diff --git a/vlib/clipboard/clipboard_solaris.v b/vlib/clipboard/clipboard_solaris.v new file mode 100644 index 0000000000..4a023207c6 --- /dev/null +++ b/vlib/clipboard/clipboard_solaris.v @@ -0,0 +1,47 @@ +module clipboard + +pub struct Clipboard { + mut: + text string // text data sent or received + got_text bool // used to confirm that we have got the text + is_owner bool // to save selection owner state +} + +fn new_clipboard() &Clipboard { + eprintln('TODO: support clipboard on solaris') + return &Clipboard{} +} + +pub fn new_primary() &Clipboard { + eprintln('TODO: support clipboard on solaris') + return &Clipboard{} +} + +fn (cb mut Clipboard) set_text(text string) bool { + cb.text = text + cb.is_owner = true + cb.got_text = true + return true +} + +fn (cb mut Clipboard) get_text() string { + return cb.text +} + +fn (cb mut Clipboard) clear(){ + cb.text = '' + cb.is_owner = false +} + +fn (cb mut Clipboard) free(){ +} + +fn (cb &Clipboard) has_ownership() bool { + return cb.is_owner +} + +fn (cb &Clipboard) check_availability() bool { + // This is a dummy clipboard implementation, + // which can be always used, although it does not do much... + return true +} diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 1a96fe1da6..13c1d201c5 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -574,6 +574,15 @@ pub fn (v &V) v_files_from_dir(dir string) []string { if file.ends_with('_nix.v') && v.pref.os == .windows { continue } + if file.ends_with('_android.v') && v.pref.os != .android { + continue + } + if file.ends_with('_freebsd.v') && v.pref.os != .freebsd { + continue + } + if file.ends_with('_solaris.v') && v.pref.os != .solaris { + continue + } if file.ends_with('_js.v') && v.pref.os != .js { continue } diff --git a/vlib/crypto/rand/rand_solaris.v b/vlib/crypto/rand/rand_solaris.v new file mode 100644 index 0000000000..3ac6d2a434 --- /dev/null +++ b/vlib/crypto/rand/rand_solaris.v @@ -0,0 +1,45 @@ +// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +import math + +#include + +fn C.getrandom(p byteptr, n size_t, flags u32) int + +const ( + read_batch_size = 256 +) + +pub fn read(bytes_needed int) ?[]byte { + mut buffer := &byte(0) + unsafe { + buffer = malloc(bytes_needed) + } + mut bytes_read := 0 + // getrandom syscall wont block if requesting <= 256 bytes + if bytes_needed > read_batch_size { + no_batches := int(math.floor(f64(bytes_needed/read_batch_size))) + for i:=0; i read_batch_size { + panic('getrandom() dont request more than $read_batch_size bytes at once.') + } + return C.getrandom(buffer, bytes_needed, 0) +} diff --git a/vlib/freetype/freetype.v b/vlib/freetype/freetype.v index 21a44b0247..a6ec8f9081 100644 --- a/vlib/freetype/freetype.v +++ b/vlib/freetype/freetype.v @@ -15,6 +15,9 @@ import ( #flag windows -I @VROOT/thirdparty/freetype/include #flag windows -L @VROOT/thirdparty/freetype/win64 +#flag solaris -I/opt/local/include/freetype2 +#flag solaris -L/opt/local/lib + #flag darwin -I/usr/local/include/freetype2 // MacPorts #flag darwin -I/opt/local/include/freetype2 diff --git a/vlib/glfw/glfw.v b/vlib/glfw/glfw.v index 34e1d36a90..7bea08ff99 100644 --- a/vlib/glfw/glfw.v +++ b/vlib/glfw/glfw.v @@ -20,6 +20,11 @@ import gl #flag darwin -lglfw #flag freebsd -I/usr/local/include #flag freebsd -Wl,-L/usr/local/lib,-lglfw + +#flag solaris -I/opt/local/include +#flag solaris -L/opt/local/lib +#flag solaris -lglfw + #flag linux -lglfw #flag windows -lgdi32 -lshell32 -lglfw3 #flag mingw -mwindows diff --git a/vlib/net/init_nix.v b/vlib/net/init_nix.v index adf58c43bf..40d231fda1 100644 --- a/vlib/net/init_nix.v +++ b/vlib/net/init_nix.v @@ -13,3 +13,5 @@ pub const ( MSG_NOSIGNAL = 0x4000 ) +#flag solaris -lsocket + diff --git a/vlib/net/socket_test.v b/vlib/net/socket_test.v index 4fd8fc551a..4f42f6afd2 100644 --- a/vlib/net/socket_test.v +++ b/vlib/net/socket_test.v @@ -47,6 +47,7 @@ fn test_socket_write_fail_without_panic() { // continues to work, even when the client side has been disconnected // this test is important for a stable long standing server client.close() or {} + $if solaris { return } // TODO: fix segfaulting on Solaris for i:=0; i<3; i++{ socket.write(message2) or { println('write to a socket without a recipient should produce an option fail: $err | $message2') diff --git a/vlib/os/const.v b/vlib/os/const.v index 5a8fff2744..e36703c9d9 100644 --- a/vlib/os/const.v +++ b/vlib/os/const.v @@ -6,6 +6,9 @@ const ( S_IFMT = 0xF000 // type of file S_IFDIR = 0x4000 // directory S_IFLNK = 0xa000 // link + S_IXUSR = 0o100 // is executable by the owner + S_IXGRP = 0o010 // is executable by group + S_IXOTH = 0o001 // is executable by others ) const ( diff --git a/vlib/os/os.v b/vlib/os/os.v index 39a1785cfa..d72f04daf3 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -532,9 +532,15 @@ pub fn is_executable(path string) bool { // 06 Read and write p := os.real_path( path ) return ( os.exists( p ) && p.ends_with('.exe') ) - } $else { - return C.access(path.str, X_OK) != -1 } + $if solaris { + statbuf := C.stat{} + if C.stat(path.str, &statbuf) != 0 { + return false + } + return (int(statbuf.st_mode) & ( S_IXUSR | S_IXGRP | S_IXOTH )) != 0 + } + return C.access(path.str, X_OK) != -1 } // `is_writable` returns `true` if `path` is writable. diff --git a/vlib/readline/readline_solaris.v b/vlib/readline/readline_solaris.v new file mode 100644 index 0000000000..9c0cfeb5b2 --- /dev/null +++ b/vlib/readline/readline_solaris.v @@ -0,0 +1,71 @@ +// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +// Mac version +// Need to be implemented +// Will serve as more advanced input method +// Based on the work of https://github.com/AmokHuginnsson/replxx + +module readline + +import os + +#include + +// Only use standard os.get_line +// Need implementation for readline capabilities +pub fn (r mut Readline) read_line_utf8(prompt string) ?ustring { + r.current = ''.ustring() + r.cursor = 0 + r.prompt = prompt + r.search_index = 0 + if r.previous_lines.len <= 1 { + r.previous_lines << ''.ustring() + r.previous_lines << ''.ustring() + } + else { + r.previous_lines[0] = ''.ustring() + } + + print(r.prompt) + line := os.get_raw_line() + + if line.len >= 0 { + r.current = line.ustring() + } + r.previous_lines[0] = ''.ustring() + r.search_index = 0 + if r.current.s == '' { + return error('empty line') + } + return r.current +} + +// Returns the string from the utf8 ustring +pub fn (r mut Readline) read_line(prompt string) ?string { + s := r.read_line_utf8(prompt) or { + return error(err) + } + return s.s +} + +// Standalone function without persistent functionnalities (eg: history) +// Returns utf8 based ustring +pub fn read_line_utf8(prompt string) ?ustring { + mut r := Readline{} + s := r.read_line_utf8(prompt) or { + return error(err) + } + return s +} + +// Standalone function without persistent functionnalities (eg: history) +// Return string from utf8 ustring +pub fn read_line(prompt string) ?string { + mut r := Readline{} + s := r.read_line(prompt) or { + return error(err) + } + return s +} diff --git a/vlib/runtime/runtime_nix.v b/vlib/runtime/runtime_nix.v index 40c07a7983..f285dfd4a4 100644 --- a/vlib/runtime/runtime_nix.v +++ b/vlib/runtime/runtime_nix.v @@ -7,6 +7,9 @@ fn nr_cpus_nix() int { $if macos { return int(C.sysconf(C._SC_NPROCESSORS_ONLN)) } + $if solaris { + return int(C.sysconf(C._SC_NPROCESSORS_ONLN)) + } return 1 } diff --git a/vlib/sdl/sdl.v b/vlib/sdl/sdl.v index e675e906a4..5282d5bc06 100644 --- a/vlib/sdl/sdl.v +++ b/vlib/sdl/sdl.v @@ -6,6 +6,7 @@ module sdl #flag linux `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image #flag darwin `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image +#flag solaris `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image //#flag windows `sdl2-config --cflags` //#flag windows `sdl2-config --libs` -lSDL2_ttf -lSDL2_mixer -lSDL2_image