force C function definitions
parent
1f93bb5a9a
commit
e9e931fe4a
|
@ -19,6 +19,7 @@
|
||||||
+ bring back generics
|
+ bring back generics
|
||||||
- bring back forum/blog and vpm
|
- bring back forum/blog and vpm
|
||||||
- wrap up orm
|
- wrap up orm
|
||||||
|
+ bring back vweb
|
||||||
- fix vorum, migrate to orm
|
- fix vorum, migrate to orm
|
||||||
- wrap up memory management
|
- wrap up memory management
|
||||||
- remove all compiler memory leaks
|
- remove all compiler memory leaks
|
||||||
|
@ -42,6 +43,6 @@
|
||||||
+ bare metal support
|
+ bare metal support
|
||||||
+ inline assembly
|
+ inline assembly
|
||||||
+ x64 machine code generation (ELF)
|
+ x64 machine code generation (ELF)
|
||||||
- require implicit C.fn definitions, add all missing definitions
|
- require explicit C.fn definitions, add all missing definitions
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ TODO
|
||||||
print_backtrace()
|
print_backtrace()
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
free(C.malloc(n))
|
||||||
ptr := C.malloc(n)
|
ptr := C.malloc(n)
|
||||||
if isnil(ptr) {
|
if isnil(ptr) {
|
||||||
panic('malloc($n) failed')
|
panic('malloc($n) failed')
|
||||||
|
|
|
@ -29,6 +29,66 @@ fn C.realpath(byteptr, byteptr) &char
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn C.chmod(byteptr, int)
|
||||||
|
fn C.printf(byteptr, ...byteptr)
|
||||||
|
fn C.fputs(byteptr)
|
||||||
|
fn C.fflush(byteptr) int
|
||||||
|
// TODO define args in these functions
|
||||||
|
fn C.fseek() int
|
||||||
|
fn C.fopen() int
|
||||||
|
fn C.fwrite() int
|
||||||
|
fn C.fclose() int
|
||||||
|
fn C.pclose() int
|
||||||
|
fn C.system() int
|
||||||
|
fn C.setenv() int
|
||||||
|
fn C.unsetenv() int
|
||||||
|
fn C.access() int
|
||||||
|
fn C.remove() int
|
||||||
|
fn C.rmdir() int
|
||||||
|
fn C.chdir() int
|
||||||
|
fn C.fread() int
|
||||||
|
fn C.rewind() int
|
||||||
|
fn C.stat() int
|
||||||
|
fn C.rename() int
|
||||||
|
fn C.fgets() int
|
||||||
|
fn C.memset() int
|
||||||
|
fn C.sigemptyset() int
|
||||||
|
fn C.getcwd() int
|
||||||
|
fn C.signal() int
|
||||||
|
fn C.mktime() int
|
||||||
|
fn C.gettimeofday() int
|
||||||
|
fn C.sleep() int
|
||||||
|
fn C.usleep() int
|
||||||
|
fn C.opendir() voidptr
|
||||||
|
fn C.closedir() int
|
||||||
|
fn C.mkdir() int
|
||||||
|
fn C.srand() int
|
||||||
|
fn C.atof() int
|
||||||
|
fn C.tolower() int
|
||||||
|
fn C.toupper() int
|
||||||
|
fn C.getchar() int
|
||||||
|
fn C.strerror() *C.char
|
||||||
|
fn C.snprintf() int
|
||||||
|
fn C.fprintf(byteptr, ...byteptr)
|
||||||
|
|
||||||
|
fn C.WIFEXITED() bool
|
||||||
|
fn C.WEXITSTATUS() int
|
||||||
|
fn C.WIFSIGNALED() bool
|
||||||
|
fn C.WTERMSIG() int
|
||||||
|
fn C.DEFAULT_LE() bool
|
||||||
|
fn C.DEFAULT_EQ() bool
|
||||||
|
fn C.DEFAULT_GT() bool
|
||||||
|
fn C.DEFAULT_EQUAL() bool
|
||||||
|
fn C.DEFAULT_NOT_EQUAL() bool
|
||||||
|
fn C.DEFAULT_LT() bool
|
||||||
|
fn C.DEFAULT_GE() bool
|
||||||
|
fn C.isatty() int
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
fn C._setmode(int, int)
|
fn C._setmode(int, int)
|
||||||
fn C._fileno(int) int
|
fn C._fileno(int) int
|
||||||
|
@ -42,3 +102,4 @@ fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumbe
|
||||||
fn C.GetFileAttributesW(lpFileName byteptr) u32
|
fn C.GetFileAttributesW(lpFileName byteptr) u32
|
||||||
fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int
|
fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int
|
||||||
fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int
|
fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int
|
||||||
|
fn C.RemoveDirectory() int
|
||||||
|
|
|
@ -95,6 +95,7 @@ pub fn tos2(s byteptr) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as `tos2`, but for char*, to avoid warnings
|
||||||
pub fn tos3(s *C.char) string {
|
pub fn tos3(s *C.char) string {
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
panic('tos3: nil string')
|
panic('tos3: nil string')
|
||||||
|
|
|
@ -37,6 +37,8 @@ fn (cb &Clipboard) has_ownership() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.OSAtomicCompareAndSwapLong()
|
||||||
|
|
||||||
fn (cb &Clipboard) set_text(text string) bool {
|
fn (cb &Clipboard) set_text(text string) bool {
|
||||||
#NSString *ns_clip;
|
#NSString *ns_clip;
|
||||||
mut ret := false
|
mut ret := false
|
||||||
|
|
|
@ -1266,7 +1266,7 @@ fn replace_generic_type(gen_type string, ti &TypeInst) string {
|
||||||
args_r << replace_generic_type(arg, ti)
|
args_r << replace_generic_type(arg, ti)
|
||||||
}
|
}
|
||||||
mut t := 'fn (' + args_r.join(',') + ')'
|
mut t := 'fn (' + args_r.join(',') + ')'
|
||||||
if ret_t.len > 0 {
|
if ret_t.len > 0 {
|
||||||
t += ' ' + replace_generic_type(ret_t, ti)
|
t += ' ' + replace_generic_type(ret_t, ti)
|
||||||
}
|
}
|
||||||
typ = t
|
typ = t
|
||||||
|
@ -1379,7 +1379,7 @@ fn (p mut Parser) register_multi_return_stuct(types []string) string {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the tokens for the generic funciton body (between `{}`)
|
// save the tokens for the generic funciton body (between `{}`)
|
||||||
// the function signature isn't saved, it is reconstructed from Fn
|
// the function signature isn't saved, it is reconstructed from Fn
|
||||||
fn (p mut Parser) save_generic_tmpl(f mut Fn, pos int) {
|
fn (p mut Parser) save_generic_tmpl(f mut Fn, pos int) {
|
||||||
mut cbr_depth := 1
|
mut cbr_depth := 1
|
||||||
|
|
|
@ -1555,8 +1555,6 @@ fn (p mut Parser) get_const_type(name string, is_ptr bool) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) get_c_func_type(name string) string {
|
fn (p mut Parser) get_c_func_type(name string) string {
|
||||||
//p.warn(name + ' ' + p.expected_type)
|
|
||||||
//}
|
|
||||||
f := Fn {
|
f := Fn {
|
||||||
name: name
|
name: name
|
||||||
is_c: true
|
is_c: true
|
||||||
|
@ -1564,15 +1562,15 @@ fn (p mut Parser) get_c_func_type(name string) string {
|
||||||
p.is_c_fn_call = true
|
p.is_c_fn_call = true
|
||||||
p.fn_call(mut f, 0, '', '')
|
p.fn_call(mut f, 0, '', '')
|
||||||
p.is_c_fn_call = false
|
p.is_c_fn_call = false
|
||||||
// Try looking it up. Maybe its defined with "C.fn_name() fn_type",
|
// C functions must be defined with `C.fn_name() fn_type`
|
||||||
// then we know what type it returns
|
|
||||||
cfn := p.table.find_fn(name) or {
|
cfn := p.table.find_fn(name) or {
|
||||||
// Not Found? Return 'void*'
|
// Is the user trying to do `var := C.foo()` or `bar(C.foo())`
|
||||||
//return 'cvoid' //'void*'
|
// without declaring `foo`?
|
||||||
//if p.expected_type != '' && p.expected_type != 'void' {
|
// Do not allow it.
|
||||||
//p.warn('\n e=$p.expected_type define imported C function with ' +
|
if !name.starts_with('gl') && !name.starts_with('glad') {
|
||||||
//'`fn C.$name([args]) [return_type]`\n')
|
p.error('undefined C function `$f.name`\n' +
|
||||||
//}
|
'define it with `fn C.$name([args]) [return_type]`')
|
||||||
|
}
|
||||||
return 'void*'
|
return 'void*'
|
||||||
}
|
}
|
||||||
// println("C fn $name has type $cfn.typ")
|
// println("C fn $name has type $cfn.typ")
|
||||||
|
|
|
@ -89,7 +89,7 @@ pub fn (g mut Gen) generate_elf_footer() {
|
||||||
g.write64_at(file_size, g.file_size_pos+8)
|
g.write64_at(file_size, g.file_size_pos+8)
|
||||||
// Create the binary
|
// Create the binary
|
||||||
f := os.create(g.out_name) or { panic(err) }
|
f := os.create(g.out_name) or { panic(err) }
|
||||||
C.chmod(g.out_name.str, 0775)
|
os.chmod(g.out_name, 0775)
|
||||||
f.write_bytes(g.buf.data, g.buf.len)
|
f.write_bytes(g.buf.data, g.buf.len)
|
||||||
f.close()
|
f.close()
|
||||||
println('x64 elf binary has been successfully generated')
|
println('x64 elf binary has been successfully generated')
|
||||||
|
|
|
@ -8,6 +8,8 @@ module rand
|
||||||
|
|
||||||
#flag darwin -framework Security
|
#flag darwin -framework Security
|
||||||
|
|
||||||
|
fn C.SecRandomCopyBytes() int
|
||||||
|
|
||||||
pub fn read(bytes_needed int) ?[]byte {
|
pub fn read(bytes_needed int) ?[]byte {
|
||||||
mut buffer := malloc(bytes_needed)
|
mut buffer := malloc(bytes_needed)
|
||||||
status := C.SecRandomCopyBytes(0, bytes_needed, buffer)
|
status := C.SecRandomCopyBytes(0, bytes_needed, buffer)
|
||||||
|
|
|
@ -43,6 +43,8 @@ pub fn get_array<T>(p Params, name string, def T) []T {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.map_set() // TODO remove hack
|
||||||
|
|
||||||
// TODO: make this a method after generics are fixed.
|
// TODO: make this a method after generics are fixed.
|
||||||
pub fn get_map<T>(p Params, name string, valueTyp T) map[string]T {
|
pub fn get_map<T>(p Params, name string, valueTyp T) map[string]T {
|
||||||
param, _ := p.get_param(name, "")
|
param, _ := p.get_param(name, "")
|
||||||
|
@ -55,6 +57,7 @@ pub fn get_map<T>(p Params, name string, valueTyp T) map[string]T {
|
||||||
keys = C.new_array_from_c_array_no_alloc(len, len, sizeof(T), param.keys)
|
keys = C.new_array_from_c_array_no_alloc(len, len, sizeof(T), param.keys)
|
||||||
for i, key in keys {
|
for i, key in keys {
|
||||||
//the most simple way to set map value without knowing the typ
|
//the most simple way to set map value without knowing the typ
|
||||||
|
// TODO remove
|
||||||
C.map_set(&ret, key, param.value + i * sizeof(T))
|
C.map_set(&ret, key, param.value + i * sizeof(T))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,10 @@ import (
|
||||||
#include "ft2build.h"
|
#include "ft2build.h"
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
fn C.FT_Init_FreeType() voidptr
|
||||||
|
fn C.FT_New_Face() voidptr
|
||||||
|
fn C.FT_Set_Pixel_Sizes()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -153,6 +153,11 @@ pub fn (s Shader) use() {
|
||||||
gl.use_program(s.program_id)
|
gl.use_program(s.program_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.glGetUniformLocation() int
|
||||||
|
fn C.glUniformMatrix4fv()
|
||||||
|
fn C.glUniform1i()
|
||||||
|
fn C.glUniform3f()
|
||||||
|
|
||||||
pub fn (s Shader) uni_location(key string) int {
|
pub fn (s Shader) uni_location(key string) int {
|
||||||
return C.glGetUniformLocation(s.program_id, key.str)
|
return C.glGetUniformLocation(s.program_id, key.str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
module http
|
module http
|
||||||
|
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
// On linux, prefer a localy build openssl, because it is
|
// On linux, prefer a localy build openssl, because it is
|
||||||
// much more likely for it to be newer, than the system
|
// much more likely for it to be newer, than the system
|
||||||
|
@ -24,67 +24,87 @@ import strings
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
struct C.SSL {
|
struct C.SSL {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.SSL_library_init()
|
||||||
|
fn C.TLSv1_2_method() voidptr
|
||||||
|
fn C.SSL_CTX_set_options()
|
||||||
|
fn C.SSL_CTX_new() voidptr
|
||||||
|
fn C.SSL_CTX_set_verify_depth()
|
||||||
|
fn C.SSL_CTX_load_verify_locations() int
|
||||||
|
fn C.BIO_new_ssl_connect() voidptr
|
||||||
|
fn C.BIO_set_conn_hostname() int
|
||||||
|
fn C.BIO_get_ssl()
|
||||||
|
fn C.SSL_set_cipher_list() int
|
||||||
|
fn C.BIO_do_connect() int
|
||||||
|
fn C.BIO_do_handshake() int
|
||||||
|
fn C.SSL_get_peer_certificate() int
|
||||||
|
fn C.SSL_get_verify_result() int
|
||||||
|
fn C.SSL_set_tlsext_host_name() int
|
||||||
|
fn C.BIO_puts()
|
||||||
|
fn C.BIO_read()
|
||||||
|
fn C.BIO_free_all()
|
||||||
|
fn C.SSL_CTX_free()
|
||||||
|
|
||||||
fn init() int {
|
fn init() int {
|
||||||
C.SSL_library_init()
|
C.SSL_library_init()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
|
fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
|
||||||
//ssl_method := C.SSLv23_method()
|
//ssl_method := C.SSLv23_method()
|
||||||
ssl_method := C.TLSv1_2_method()
|
ssl_method := C.TLSv1_2_method()
|
||||||
if isnil(method) {
|
if isnil(method) {
|
||||||
}
|
}
|
||||||
ctx := C.SSL_CTX_new(ssl_method)
|
ctx := C.SSL_CTX_new(ssl_method)
|
||||||
if isnil(ctx) {
|
if isnil(ctx) {
|
||||||
}
|
}
|
||||||
C.SSL_CTX_set_verify_depth(ctx, 4)
|
C.SSL_CTX_set_verify_depth(ctx, 4)
|
||||||
flags := C.SSL_OP_NO_SSLv2 | C.SSL_OP_NO_SSLv3 | C.SSL_OP_NO_COMPRESSION
|
flags := C.SSL_OP_NO_SSLv2 | C.SSL_OP_NO_SSLv3 | C.SSL_OP_NO_COMPRESSION
|
||||||
C.SSL_CTX_set_options(ctx, flags)
|
C.SSL_CTX_set_options(ctx, flags)
|
||||||
mut res := C.SSL_CTX_load_verify_locations(ctx, 'random-org-chain.pem', 0)
|
mut res := C.SSL_CTX_load_verify_locations(ctx, 'random-org-chain.pem', 0)
|
||||||
if res != 1 {
|
if res != 1 {
|
||||||
}
|
}
|
||||||
web := C.BIO_new_ssl_connect(ctx)
|
web := C.BIO_new_ssl_connect(ctx)
|
||||||
if isnil(ctx) {
|
if isnil(ctx) {
|
||||||
}
|
}
|
||||||
addr := host_name + ':' + port.str()
|
addr := host_name + ':' + port.str()
|
||||||
res = C.BIO_set_conn_hostname(web, addr.str)
|
res = C.BIO_set_conn_hostname(web, addr.str)
|
||||||
if res != 1 {
|
if res != 1 {
|
||||||
}
|
}
|
||||||
ssl := &C.SSL{!}
|
ssl := &C.SSL{!}
|
||||||
C.BIO_get_ssl(web, &ssl)
|
C.BIO_get_ssl(web, &ssl)
|
||||||
if isnil(ssl) {
|
if isnil(ssl) {
|
||||||
}
|
}
|
||||||
preferred_ciphers := 'HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4'
|
preferred_ciphers := 'HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4'
|
||||||
res = C.SSL_set_cipher_list(ssl, preferred_ciphers.str)
|
res = C.SSL_set_cipher_list(ssl, preferred_ciphers.str)
|
||||||
if res != 1 {
|
if res != 1 {
|
||||||
}
|
}
|
||||||
res = C.SSL_set_tlsext_host_name(ssl, host_name.str)
|
res = C.SSL_set_tlsext_host_name(ssl, host_name.str)
|
||||||
res = C.BIO_do_connect(web)
|
res = C.BIO_do_connect(web)
|
||||||
res = C.BIO_do_handshake(web)
|
res = C.BIO_do_handshake(web)
|
||||||
cert := C.SSL_get_peer_certificate(ssl)
|
cert := C.SSL_get_peer_certificate(ssl)
|
||||||
res = C.SSL_get_verify_result(ssl)
|
res = C.SSL_get_verify_result(ssl)
|
||||||
///////
|
///////
|
||||||
s := req.build_request_headers(method, host_name, path)
|
s := req.build_request_headers(method, host_name, path)
|
||||||
C.BIO_puts(web, s.str)
|
C.BIO_puts(web, s.str)
|
||||||
mut sb := strings.new_builder(100)
|
mut sb := strings.new_builder(100)
|
||||||
for {
|
for {
|
||||||
buff := [1536]byte
|
buff := [1536]byte
|
||||||
len := int(C.BIO_read(web, buff, 1536) )
|
len := int(C.BIO_read(web, buff, 1536) )
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
sb.write(tos(buff, len))
|
sb.write(tos(buff, len))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isnil(web) {
|
if !isnil(web) {
|
||||||
C.BIO_free_all(web)
|
C.BIO_free_all(web)
|
||||||
}
|
}
|
||||||
if !isnil(ctx) {
|
if !isnil(ctx) {
|
||||||
C.SSL_CTX_free(ctx)
|
C.SSL_CTX_free(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return parse_response(sb.str())
|
return parse_response(sb.str())
|
||||||
|
|
|
@ -97,6 +97,13 @@ fn jsdecode_string(root &C.cJSON) string {
|
||||||
return tos_clone(root.valuestring)// , _strlen(root.valuestring))
|
return tos_clone(root.valuestring)// , _strlen(root.valuestring))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.cJSON_IsTrue() bool
|
||||||
|
fn C.cJSON_CreateNumber() &C.cJSON
|
||||||
|
fn C.cJSON_CreateBool() &C.cJSON
|
||||||
|
fn C.cJSON_CreateString() &C.cJSON
|
||||||
|
fn C.cJSON_Parse() &C.cJSON
|
||||||
|
fn C.cJSON_PrintUnformatted() byteptr
|
||||||
|
|
||||||
fn jsdecode_bool(root &C.cJSON) bool {
|
fn jsdecode_bool(root &C.cJSON) bool {
|
||||||
if isnil(root) {
|
if isnil(root) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -28,6 +28,7 @@ fn C.lgamma(x f64) f64
|
||||||
fn C.pow(x f64, y f64) f64
|
fn C.pow(x f64, y f64) f64
|
||||||
fn C.round(x f64) f64
|
fn C.round(x f64) f64
|
||||||
fn C.sin(x f64) f64
|
fn C.sin(x f64) f64
|
||||||
|
fn C.sinh(x f64) f64
|
||||||
fn C.sqrt(x f64) f64
|
fn C.sqrt(x f64) f64
|
||||||
fn C.tgamma(x f64) f64
|
fn C.tgamma(x f64) f64
|
||||||
fn C.tan(x f64) f64
|
fn C.tan(x f64) f64
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
module net
|
module net
|
||||||
|
|
||||||
// hostname returns the host name reported by the kernel.
|
fn C.gethostname() int
|
||||||
|
|
||||||
|
// hostname returns the host name reported by the kernel.
|
||||||
pub fn hostname() ?string {
|
pub fn hostname() ?string {
|
||||||
mut name := [256]byte
|
mut name := [256]byte
|
||||||
// https://www.ietf.org/rfc/rfc1035.txt
|
// https://www.ietf.org/rfc/rfc1035.txt
|
||||||
|
|
|
@ -36,15 +36,31 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct C.sockaddr_storage {}
|
struct C.sockaddr_storage {}
|
||||||
|
fn C.socket() int
|
||||||
|
fn C.setsockopt() int
|
||||||
|
fn C.htonl() int
|
||||||
|
fn C.htons() int
|
||||||
|
fn C.bind() int
|
||||||
|
fn C.listen() int
|
||||||
|
fn C.accept() int
|
||||||
|
fn C.getaddrinfo() int
|
||||||
|
fn C.connect() int
|
||||||
|
fn C.send() int
|
||||||
|
fn C.recv() int
|
||||||
|
fn C.read() int
|
||||||
|
fn C.shutdown() int
|
||||||
|
fn C.close() int
|
||||||
|
fn C.ntohs() int
|
||||||
|
fn C.getsockname() int
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
pub fn socket(family int, _type int, proto int) ?Socket {
|
pub fn new_socket(family int, _type int, proto int) ?Socket {
|
||||||
|
|
||||||
sockfd := C.socket(family, _type, proto)
|
sockfd := C.socket(family, _type, proto)
|
||||||
one:=1
|
one:=1
|
||||||
// This is needed so that there are no problems with reusing the
|
// This is needed so that there are no problems with reusing the
|
||||||
// same port after the application exits.
|
// same port after the application exits.
|
||||||
C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, sizeof(int))
|
C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, 4)//sizeof(int))
|
||||||
if sockfd == 0 {
|
if sockfd == 0 {
|
||||||
return error('net.socket: failed')
|
return error('net.socket: failed')
|
||||||
}
|
}
|
||||||
|
@ -58,16 +74,16 @@ pub fn socket(family int, _type int, proto int) ?Socket {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn socket_udp() ?Socket {
|
pub fn socket_udp() ?Socket {
|
||||||
return socket(C.AF_INET, C.SOCK_DGRAM, C.IPPROTO_UDP)
|
return new_socket(C.AF_INET, C.SOCK_DGRAM, C.IPPROTO_UDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set socket options
|
// set socket options
|
||||||
pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int {
|
pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int {
|
||||||
res := C.setsockopt(s.sockfd, level, optname, optvalue, C.sizeof(optvalue))
|
res := C.setsockopt(s.sockfd, level, optname, optvalue, sizeof(int))
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return error('net.setsocketopt: failed with $res')
|
return error('net.setsocketopt: failed with $res')
|
||||||
}
|
}
|
||||||
return int(res)
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind socket to port
|
// bind socket to port
|
||||||
|
@ -77,7 +93,7 @@ pub fn (s Socket) bind(port int) ?int {
|
||||||
addr.sin_port = C.htons(port)
|
addr.sin_port = C.htons(port)
|
||||||
addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY)
|
addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY)
|
||||||
size := 16 // sizeof(C.sockaddr_in)
|
size := 16 // sizeof(C.sockaddr_in)
|
||||||
res := int(C.bind(s.sockfd, &addr, size))
|
res := C.bind(s.sockfd, &addr, size)
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return error('net.bind: failed with $res')
|
return error('net.bind: failed with $res')
|
||||||
}
|
}
|
||||||
|
@ -87,7 +103,7 @@ pub fn (s Socket) bind(port int) ?int {
|
||||||
// put socket into passive mode and wait to receive
|
// put socket into passive mode and wait to receive
|
||||||
pub fn (s Socket) listen() ?int {
|
pub fn (s Socket) listen() ?int {
|
||||||
backlog := 128
|
backlog := 128
|
||||||
res := int(C.listen(s.sockfd, backlog))
|
res := C.listen(s.sockfd, backlog)
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return error('net.listen: failed with $res')
|
return error('net.listen: failed with $res')
|
||||||
}
|
}
|
||||||
|
@ -107,7 +123,7 @@ pub fn (s Socket) listen_backlog(backlog int) ?int {
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return error('net.listen_backlog: failed with $res')
|
return error('net.listen_backlog: failed with $res')
|
||||||
}
|
}
|
||||||
return int(res)
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper method to create, bind, and listen given port number
|
// helper method to create, bind, and listen given port number
|
||||||
|
@ -115,7 +131,7 @@ pub fn listen(port int) ?Socket {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('net.listen($port)')
|
println('net.listen($port)')
|
||||||
}
|
}
|
||||||
s := socket(C.AF_INET, C.SOCK_STREAM, 0) or {
|
s := new_socket(C.AF_INET, C.SOCK_STREAM, 0) or {
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
bind_res := s.bind(port) or {
|
bind_res := s.bind(port) or {
|
||||||
|
@ -167,17 +183,17 @@ pub fn (s Socket) connect(address string, port int) ?int {
|
||||||
error_message := os.get_error_msg(net.error_code())
|
error_message := os.get_error_msg(net.error_code())
|
||||||
return error('net.connect: getaddrinfo failed "$error_message"')
|
return error('net.connect: getaddrinfo failed "$error_message"')
|
||||||
}
|
}
|
||||||
res := int(C.connect(s.sockfd, info.ai_addr, info.ai_addrlen))
|
res := C.connect(s.sockfd, info.ai_addr, info.ai_addrlen)
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
error_message := os.get_error_msg(net.error_code())
|
error_message := os.get_error_msg(net.error_code())
|
||||||
return error('net.connect: connect failed "$error_message"')
|
return error('net.connect: connect failed "$error_message"')
|
||||||
}
|
}
|
||||||
return int(res)
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper method to create socket and connect
|
// helper method to create socket and connect
|
||||||
pub fn dial(address string, port int) ?Socket {
|
pub fn dial(address string, port int) ?Socket {
|
||||||
s := socket(C.AF_INET, C.SOCK_STREAM, 0) or {
|
s := new_socket(C.AF_INET, C.SOCK_STREAM, 0) or {
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
res := s.connect(address, port) or {
|
res := s.connect(address, port) or {
|
||||||
|
@ -188,7 +204,7 @@ pub fn dial(address string, port int) ?Socket {
|
||||||
|
|
||||||
// send string data to socket
|
// send string data to socket
|
||||||
pub fn (s Socket) send(buf byteptr, len int) ?int {
|
pub fn (s Socket) send(buf byteptr, len int) ?int {
|
||||||
res := int( C.send(s.sockfd, buf, len, MSG_NOSIGNAL) )
|
res := C.send(s.sockfd, buf, len, MSG_NOSIGNAL)
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return error('net.send: failed with $res')
|
return error('net.send: failed with $res')
|
||||||
}
|
}
|
||||||
|
@ -198,18 +214,18 @@ pub fn (s Socket) send(buf byteptr, len int) ?int {
|
||||||
// receive string data from socket
|
// receive string data from socket
|
||||||
pub fn (s Socket) recv(bufsize int) (byteptr, int) {
|
pub fn (s Socket) recv(bufsize int) (byteptr, int) {
|
||||||
buf := malloc(bufsize)
|
buf := malloc(bufsize)
|
||||||
res := int( C.recv(s.sockfd, buf, bufsize, 0) )
|
res := C.recv(s.sockfd, buf, bufsize, 0)
|
||||||
return buf, res
|
return buf, res
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove cread/2 and crecv/2 when the Go net interface is done
|
// TODO: remove cread/2 and crecv/2 when the Go net interface is done
|
||||||
pub fn (s Socket) cread( buffer byteptr, buffersize int ) int {
|
pub fn (s Socket) cread( buffer byteptr, buffersize int ) int {
|
||||||
return int( C.read(s.sockfd, buffer, buffersize) )
|
return C.read(s.sockfd, buffer, buffersize)
|
||||||
}
|
}
|
||||||
// Receive a message from the socket, and place it in a preallocated buffer buf,
|
// Receive a message from the socket, and place it in a preallocated buffer buf,
|
||||||
// with maximum message size bufsize. Returns the length of the received message.
|
// with maximum message size bufsize. Returns the length of the received message.
|
||||||
pub fn (s Socket) crecv( buffer byteptr, buffersize int ) int {
|
pub fn (s Socket) crecv( buffer byteptr, buffersize int ) int {
|
||||||
return int( C.recv(s.sockfd, buffer, buffersize, 0) )
|
return C.recv(s.sockfd, buffer, buffersize, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// shutdown and close socket
|
// shutdown and close socket
|
||||||
|
@ -250,7 +266,7 @@ pub const (
|
||||||
// write - write a string with CRLF after it over the socket s
|
// write - write a string with CRLF after it over the socket s
|
||||||
pub fn (s Socket) write(str string) ?int {
|
pub fn (s Socket) write(str string) ?int {
|
||||||
line := '$str$CRLF'
|
line := '$str$CRLF'
|
||||||
res := int( C.send(s.sockfd, line.str, line.len, MSG_NOSIGNAL) )
|
res := C.send(s.sockfd, line.str, line.len, MSG_NOSIGNAL)
|
||||||
if res < 0 { return error('net.write: failed with $res') }
|
if res < 0 { return error('net.write: failed with $res') }
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -299,6 +315,6 @@ pub fn (s Socket) read_line() string {
|
||||||
pub fn (s Socket) get_port() int {
|
pub fn (s Socket) get_port() int {
|
||||||
mut addr := C.sockaddr_in {}
|
mut addr := C.sockaddr_in {}
|
||||||
size := 16 // sizeof(sockaddr_in)
|
size := 16 // sizeof(sockaddr_in)
|
||||||
sockname_res := C.getsockname(s.sockfd, &addr, &size)
|
C.getsockname(s.sockfd, &addr, &size)
|
||||||
return int(C.ntohs(addr.sin_port))
|
return C.ntohs(addr.sin_port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1026,3 +1026,8 @@ pub fn tmpdir() string {
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn chmod(path string, mode int) {
|
||||||
|
C.chmod(path.str, mode)
|
||||||
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ pub fn init_os_args(argc int, argv &byteptr) []string {
|
||||||
|
|
||||||
// get_error_msg return error code representation in string.
|
// get_error_msg return error code representation in string.
|
||||||
pub fn get_error_msg(code int) string {
|
pub fn get_error_msg(code int) string {
|
||||||
_ptr_text := C.strerror(code) // voidptr?
|
ptr_text := C.strerror(code) // voidptr?
|
||||||
if _ptr_text == 0 {
|
if ptr_text == 0 {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return tos(_ptr_text, vstrlen(_ptr_text))
|
return tos3(ptr_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ls(path string) ?[]string {
|
pub fn ls(path string) ?[]string {
|
||||||
|
|
|
@ -34,6 +34,11 @@ pub fn (db DB) q_int(query string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C.sqlite3_column_text(voidptr, int) byteptr
|
fn C.sqlite3_column_text(voidptr, int) byteptr
|
||||||
|
fn C.sqlite3_column_int(voidptr, int) int
|
||||||
|
fn C.sqlite3_open()
|
||||||
|
fn C.sqlite3_step() int
|
||||||
|
fn C.sqlite3_prepare_v2()
|
||||||
|
fn C.sqlite3_finalize()
|
||||||
|
|
||||||
pub fn (db DB) q_string(query string) string {
|
pub fn (db DB) q_string(query string) string {
|
||||||
stmt := &C.sqlite3_stmt{!}
|
stmt := &C.sqlite3_stmt{!}
|
||||||
|
|
|
@ -21,6 +21,10 @@ mut:
|
||||||
ext string
|
ext string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C.stbi_load() voidptr
|
||||||
|
fn C.stbi_image_free()
|
||||||
|
fn C.stbi_set_flip_vertically_on_load()
|
||||||
|
|
||||||
pub fn load(path string) Image {
|
pub fn load(path string) Image {
|
||||||
ext := path.all_after('.')
|
ext := path.all_after('.')
|
||||||
mut res := Image {
|
mut res := Image {
|
||||||
|
|
|
@ -6,6 +6,11 @@ module sync
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
fn C.pthread_mutex_init()
|
||||||
|
fn C.pthread_mutex_lock()
|
||||||
|
fn C.pthread_mutex_unlock()
|
||||||
|
|
||||||
|
|
||||||
//[init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function.
|
//[init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function.
|
||||||
pub struct Mutex {
|
pub struct Mutex {
|
||||||
mutex C.pthread_mutex_t
|
mutex C.pthread_mutex_t
|
||||||
|
|
Loading…
Reference in New Issue