force C function definitions
parent
1f93bb5a9a
commit
e9e931fe4a
|
@ -19,6 +19,7 @@
|
|||
+ bring back generics
|
||||
- bring back forum/blog and vpm
|
||||
- wrap up orm
|
||||
+ bring back vweb
|
||||
- fix vorum, migrate to orm
|
||||
- wrap up memory management
|
||||
- remove all compiler memory leaks
|
||||
|
@ -42,6 +43,6 @@
|
|||
+ bare metal support
|
||||
+ inline assembly
|
||||
+ 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()
|
||||
#endif
|
||||
*/
|
||||
free(C.malloc(n))
|
||||
ptr := C.malloc(n)
|
||||
if isnil(ptr) {
|
||||
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
|
||||
fn C._setmode(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.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.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 {
|
||||
if s == 0 {
|
||||
panic('tos3: nil string')
|
||||
|
|
|
@ -37,6 +37,8 @@ fn (cb &Clipboard) has_ownership() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn C.OSAtomicCompareAndSwapLong()
|
||||
|
||||
fn (cb &Clipboard) set_text(text string) bool {
|
||||
#NSString *ns_clip;
|
||||
mut ret := false
|
||||
|
|
|
@ -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 {
|
||||
//p.warn(name + ' ' + p.expected_type)
|
||||
//}
|
||||
f := Fn {
|
||||
name: name
|
||||
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.fn_call(mut f, 0, '', '')
|
||||
p.is_c_fn_call = false
|
||||
// Try looking it up. Maybe its defined with "C.fn_name() fn_type",
|
||||
// then we know what type it returns
|
||||
// C functions must be defined with `C.fn_name() fn_type`
|
||||
cfn := p.table.find_fn(name) or {
|
||||
// Not Found? Return 'void*'
|
||||
//return 'cvoid' //'void*'
|
||||
//if p.expected_type != '' && p.expected_type != 'void' {
|
||||
//p.warn('\n e=$p.expected_type define imported C function with ' +
|
||||
//'`fn C.$name([args]) [return_type]`\n')
|
||||
//}
|
||||
// Is the user trying to do `var := C.foo()` or `bar(C.foo())`
|
||||
// without declaring `foo`?
|
||||
// Do not allow it.
|
||||
if !name.starts_with('gl') && !name.starts_with('glad') {
|
||||
p.error('undefined C function `$f.name`\n' +
|
||||
'define it with `fn C.$name([args]) [return_type]`')
|
||||
}
|
||||
return 'void*'
|
||||
}
|
||||
// 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)
|
||||
// Create the binary
|
||||
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.close()
|
||||
println('x64 elf binary has been successfully generated')
|
||||
|
|
|
@ -8,6 +8,8 @@ module rand
|
|||
|
||||
#flag darwin -framework Security
|
||||
|
||||
fn C.SecRandomCopyBytes() int
|
||||
|
||||
pub fn read(bytes_needed int) ?[]byte {
|
||||
mut buffer := malloc(bytes_needed)
|
||||
status := C.SecRandomCopyBytes(0, bytes_needed, buffer)
|
||||
|
|
|
@ -43,6 +43,8 @@ pub fn get_array<T>(p Params, name string, def T) []T {
|
|||
return []
|
||||
}
|
||||
|
||||
fn C.map_set() // TODO remove hack
|
||||
|
||||
// TODO: make this a method after generics are fixed.
|
||||
pub fn get_map<T>(p Params, name string, valueTyp T) map[string]T {
|
||||
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)
|
||||
for i, key in keys {
|
||||
//the most simple way to set map value without knowing the typ
|
||||
// TODO remove
|
||||
C.map_set(&ret, key, param.value + i * sizeof(T))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ import (
|
|||
#include "ft2build.h"
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
fn C.FT_Init_FreeType() voidptr
|
||||
fn C.FT_New_Face() voidptr
|
||||
fn C.FT_Set_Pixel_Sizes()
|
||||
|
||||
|
||||
|
||||
const (
|
||||
|
|
|
@ -153,6 +153,11 @@ pub fn (s Shader) use() {
|
|||
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 {
|
||||
return C.glGetUniformLocation(s.program_id, key.str)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,26 @@ 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 {
|
||||
C.SSL_library_init()
|
||||
return 1
|
||||
|
|
|
@ -97,6 +97,13 @@ fn jsdecode_string(root &C.cJSON) string {
|
|||
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 {
|
||||
if isnil(root) {
|
||||
return false
|
||||
|
|
|
@ -28,6 +28,7 @@ fn C.lgamma(x f64) f64
|
|||
fn C.pow(x f64, y f64) f64
|
||||
fn C.round(x f64) f64
|
||||
fn C.sin(x f64) f64
|
||||
fn C.sinh(x f64) f64
|
||||
fn C.sqrt(x f64) f64
|
||||
fn C.tgamma(x f64) f64
|
||||
fn C.tan(x f64) f64
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
module net
|
||||
|
||||
fn C.gethostname() int
|
||||
|
||||
// hostname returns the host name reported by the kernel.
|
||||
pub fn hostname() ?string {
|
||||
mut name := [256]byte
|
||||
|
|
|
@ -36,15 +36,31 @@ mut:
|
|||
}
|
||||
|
||||
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
|
||||
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)
|
||||
one:=1
|
||||
// This is needed so that there are no problems with reusing the
|
||||
// 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 {
|
||||
return error('net.socket: failed')
|
||||
}
|
||||
|
@ -58,16 +74,16 @@ pub fn socket(family int, _type int, proto int) ?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
|
||||
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 {
|
||||
return error('net.setsocketopt: failed with $res')
|
||||
}
|
||||
return int(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// bind socket to port
|
||||
|
@ -77,7 +93,7 @@ pub fn (s Socket) bind(port int) ?int {
|
|||
addr.sin_port = C.htons(port)
|
||||
addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY)
|
||||
size := 16 // sizeof(C.sockaddr_in)
|
||||
res := int(C.bind(s.sockfd, &addr, size))
|
||||
res := C.bind(s.sockfd, &addr, size)
|
||||
if res < 0 {
|
||||
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
|
||||
pub fn (s Socket) listen() ?int {
|
||||
backlog := 128
|
||||
res := int(C.listen(s.sockfd, backlog))
|
||||
res := C.listen(s.sockfd, backlog)
|
||||
if res < 0 {
|
||||
return error('net.listen: failed with $res')
|
||||
}
|
||||
|
@ -107,7 +123,7 @@ pub fn (s Socket) listen_backlog(backlog int) ?int {
|
|||
if res < 0 {
|
||||
return error('net.listen_backlog: failed with $res')
|
||||
}
|
||||
return int(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// helper method to create, bind, and listen given port number
|
||||
|
@ -115,7 +131,7 @@ pub fn listen(port int) ?Socket {
|
|||
$if debug {
|
||||
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)
|
||||
}
|
||||
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())
|
||||
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 {
|
||||
error_message := os.get_error_msg(net.error_code())
|
||||
return error('net.connect: connect failed "$error_message"')
|
||||
}
|
||||
return int(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// helper method to create socket and connect
|
||||
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)
|
||||
}
|
||||
res := s.connect(address, port) or {
|
||||
|
@ -188,7 +204,7 @@ pub fn dial(address string, port int) ?Socket {
|
|||
|
||||
// send string data to socket
|
||||
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 {
|
||||
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
|
||||
pub fn (s Socket) recv(bufsize int) (byteptr, int) {
|
||||
buf := malloc(bufsize)
|
||||
res := int( C.recv(s.sockfd, buf, bufsize, 0) )
|
||||
res := C.recv(s.sockfd, buf, bufsize, 0)
|
||||
return buf, res
|
||||
}
|
||||
|
||||
// TODO: remove cread/2 and crecv/2 when the Go net interface is done
|
||||
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,
|
||||
// with maximum message size bufsize. Returns the length of the received message.
|
||||
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
|
||||
|
@ -250,7 +266,7 @@ pub const (
|
|||
// write - write a string with CRLF after it over the socket s
|
||||
pub fn (s Socket) write(str string) ?int {
|
||||
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') }
|
||||
return res
|
||||
}
|
||||
|
@ -299,6 +315,6 @@ pub fn (s Socket) read_line() string {
|
|||
pub fn (s Socket) get_port() int {
|
||||
mut addr := C.sockaddr_in {}
|
||||
size := 16 // sizeof(sockaddr_in)
|
||||
sockname_res := C.getsockname(s.sockfd, &addr, &size)
|
||||
return int(C.ntohs(addr.sin_port))
|
||||
C.getsockname(s.sockfd, &addr, &size)
|
||||
return C.ntohs(addr.sin_port)
|
||||
}
|
||||
|
|
|
@ -1026,3 +1026,8 @@ pub fn tmpdir() string {
|
|||
}
|
||||
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.
|
||||
pub fn get_error_msg(code int) string {
|
||||
_ptr_text := C.strerror(code) // voidptr?
|
||||
if _ptr_text == 0 {
|
||||
ptr_text := C.strerror(code) // voidptr?
|
||||
if ptr_text == 0 {
|
||||
return ''
|
||||
}
|
||||
return tos(_ptr_text, vstrlen(_ptr_text))
|
||||
return tos3(ptr_text)
|
||||
}
|
||||
|
||||
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_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 {
|
||||
stmt := &C.sqlite3_stmt{!}
|
||||
|
|
|
@ -21,6 +21,10 @@ mut:
|
|||
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 {
|
||||
ext := path.all_after('.')
|
||||
mut res := Image {
|
||||
|
|
|
@ -6,6 +6,11 @@ module sync
|
|||
|
||||
#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.
|
||||
pub struct Mutex {
|
||||
mutex C.pthread_mutex_t
|
||||
|
|
Loading…
Reference in New Issue