Browse Source

Update core library with `cstring`

gingerBill 7 years ago
parent
commit
9da05dd4cb
12 changed files with 154 additions and 144 deletions
  1. 6 1
      core/_preload.odin
  2. 8 10
      core/opengl.odin
  3. 2 2
      core/os_essence.odin
  4. 16 17
      core/os_linux.odin
  5. 3 3
      core/os_windows.odin
  6. 16 16
      core/os_x.odin
  7. 4 0
      core/raw.odin
  8. 4 6
      core/strings.odin
  9. 2 2
      core/sys/wgl.odin
  10. 88 86
      core/sys/windows.odin
  11. 3 1
      src/check_expr.cpp
  12. 2 0
      src/types.cpp

+ 6 - 1
core/_preload.odin

@@ -473,6 +473,9 @@ new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T {
 free_string :: proc(str: string, loc := #caller_location) {
 	free_ptr(raw.data(str), loc);
 }
+free_cstring :: proc(str: cstring, loc := #caller_location) {
+	free_ptr((^byte)(str), loc);
+}
 free_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
 	free_ptr(raw.data(array), loc);
 }
@@ -486,7 +489,9 @@ free_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
 }
 
 free :: proc[
-	free_ptr, free_string, free_dynamic_array, free_slice, free_map,
+	free_ptr,
+	free_string, free_cstring,
+	free_dynamic_array, free_slice, free_map,
 ];
 
 

+ 8 - 10
core/opengl.odin

@@ -31,7 +31,7 @@ foreign lib {
 	Color3f        :: proc(r, g, b: f32) ---;
 	Vertex3f       :: proc(x, y, z: f32) ---;
 	GetError       :: proc() -> i32 ---;
-	GetString      :: proc(name: i32) -> ^u8 ---;
+	GetString      :: proc(name: i32) -> cstring ---;
 	GetIntegerv    :: proc(name: i32, v: ^i32) ---;
 	TexCoord2f     :: proc(x, y: f32) ---;
 	TexImage2D     :: proc(target, level, internal_format: i32,
@@ -40,9 +40,7 @@ foreign lib {
 }
 
 
-_string_data :: inline proc(s: string) -> ^u8 do return &s[0];
-
-_libgl := win32.load_library_a(_string_data("opengl32.dll\x00"));
+_libgl := win32.load_library_a("opengl32.dll");
 
 get_gl_proc_address :: proc(name: string) -> rawptr {
 	if name[len(name)-1] == 0 {
@@ -50,9 +48,9 @@ get_gl_proc_address :: proc(name: string) -> rawptr {
 	}
 	// NOTE(bill): null terminated
 	assert((&name[0] + len(name))^ == 0);
-	res := wgl.get_gl_proc_address(&name[0]);
+	res := wgl.get_gl_proc_address(cstring(&name[0]));
 	if res == nil {
-		res = win32.get_proc_address(_libgl, &name[0]);
+		res = win32.get_proc_address(_libgl, cstring(&name[0]));
 	}
 	return rawptr(res);
 }
@@ -79,7 +77,7 @@ get_gl_proc_address :: proc(name: string) -> rawptr {
 	EnableVertexAttribArray:  proc "c" (index: u32);
 
 	CreateShader:             proc "c" (shader_type: i32) -> u32;
-	ShaderSource:             proc "c" (shader: u32, count: u32, str: ^^u8, length: ^i32);
+	ShaderSource:             proc "c" (shader: u32, count: u32, str: ^cstring, length: ^i32);
 	CompileShader:            proc "c" (shader: u32);
 	CreateProgram:            proc "c" () -> u32;
 	AttachShader:             proc "c" (program, shader: u32);
@@ -92,8 +90,8 @@ get_gl_proc_address :: proc(name: string) -> rawptr {
 
 	GetShaderiv:              proc "c" (shader:  u32, pname: i32, params: ^i32);
 	GetProgramiv:             proc "c" (program: u32, pname: i32, params: ^i32);
-	GetShaderInfoLog:         proc "c" (shader:  u32, max_length: u32, length: ^u32, info_long: ^u8);
-	GetProgramInfoLog:        proc "c" (program: u32, max_length: u32, length: ^u32, info_long: ^u8);
+	GetShaderInfoLog:         proc "c" (shader:  u32, max_length: u32, length: ^u32, info_long: cstring);
+	GetProgramInfoLog:        proc "c" (program: u32, max_length: u32, length: ^u32, info_long: cstring);
 
 	ActiveTexture:            proc "c" (texture: i32);
 	GenerateMipmap:           proc "c" (target:  i32);
@@ -116,7 +114,7 @@ get_gl_proc_address :: proc(name: string) -> rawptr {
 	Uniform4f:                proc "c" (loc: i32, v0, v1, v2, v3: f32);
 	UniformMatrix4fv:         proc "c" (loc: i32, count: u32, transpose: i32, value: ^f32);
 
-	GetUniformLocation:       proc "c" (program: u32, name: ^u8) -> i32;
+	GetUniformLocation:       proc "c" (program: u32, name: cstring) -> i32;
 
 
 init :: proc() {

+ 2 - 2
core/os_essence.odin

@@ -23,10 +23,10 @@ OS_Node_Information :: struct {
 
 foreign api {
 	@(link_name="OSHelloWorld")       os_hello_world       :: proc() ---;
-	@(link_name="OSPrintDirect")      os_print_direct      :: proc(string: ^byte, length: int) ---;
+	@(link_name="OSPrintDirect")      os_print_direct      :: proc(str: cstring, length: int) ---;
 	@(link_name="OSHeapAllocate")     os_heap_allocate     :: proc(bytes: int, zero: bool) -> rawptr ---;
 	@(link_name="OSHeapFree")         os_heap_free         :: proc(address: rawptr) ---;
-	@(link_name="OSOpenNode")         os_open_node         :: proc(path: ^byte, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
+	@(link_name="OSOpenNode")         os_open_node         :: proc(path: cstring, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
 	@(link_name="OSResizeFile")       os_resize_file       :: proc(handle: Handle, new_size: u64) -> Errno ---;
 	@(link_name="OSCloseHandle")      os_close_handle      :: proc(handle: Handle) ---;
 	@(link_name="OSWriteFileSync")    os_write_file_sync   :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;

+ 16 - 17
core/os_linux.odin

@@ -122,34 +122,33 @@ W_OK :: 2; // Test for write permission
 R_OK :: 4; // Test for read permission
 
 foreign libc {
-	@(link_name="open")    _unix_open    :: proc(path: ^byte, mode: int) -> Handle ---;
+	@(link_name="open")    _unix_open    :: proc(path: cstring, mode: int) -> Handle ---;
 	@(link_name="close")   _unix_close   :: proc(fd: Handle) -> i32 ---;
 	@(link_name="read")    _unix_read    :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
 	@(link_name="write")   _unix_write   :: proc(fd: Handle, buf: rawptr, size: int) -> int ---;
 	@(link_name="lseek64") _unix_seek    :: proc(fd: Handle, offset: i64, whence: i32) -> i64 ---;
 	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
-	@(link_name="stat")    _unix_stat    :: proc(path: ^byte, stat: ^Stat) -> i32 ---;
-	@(link_name="access")  _unix_access  :: proc(path: ^byte, mask: int) -> i32 ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: cstring, stat: ^Stat) -> i32 ---;
+	@(link_name="access")  _unix_access  :: proc(path: cstring, mask: int) -> i32 ---;
 
 	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
 	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
 	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
 	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
-	@(link_name="getenv")  _unix_getenv  :: proc(^byte) -> ^byte ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(cstring) -> cstring ---;
 
 	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 foreign dl {
-	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^byte, flags: int) -> rawptr ---;
-	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^byte) -> rawptr ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: cstring, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: cstring) -> rawptr ---;
 	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
-	@(link_name="dlerror") _unix_dlerror :: proc() -> ^byte ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
 open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
-
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	handle := _unix_open(cstr, mode);
 	free(cstr);
 	if(handle == -1) {
@@ -201,7 +200,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time {}
 */
 
 stat :: inline proc(path: string) -> (Stat, int) {
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	defer free(cstr);
 
 	s: Stat;
@@ -210,7 +209,7 @@ stat :: inline proc(path: string) -> (Stat, int) {
 }
 
 access :: inline proc(path: string, mask: int) -> bool {
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	defer free(cstr);
 	return _unix_access(cstr, mask) == 0;
 }
@@ -229,13 +228,13 @@ heap_free :: proc(ptr: rawptr) {
 }
 
 getenv :: proc(name: string) -> (string, bool) {
-	path_str := strings.new_c_string(name);
+	path_str := strings.new_cstring(name);
 	defer free(path_str);
 	cstr := _unix_getenv(path_str);
 	if cstr == nil {
 		return "", false;
 	}
-	return strings.to_odin_string(cstr), true;
+	return string(cstr), true;
 }
 
 exit :: proc(code: int) {
@@ -248,14 +247,14 @@ current_thread_id :: proc() -> int {
 }
 
 dlopen :: inline proc(filename: string, flags: int) -> rawptr {
-	cstr := strings.new_c_string(filename);
+	cstr := strings.new_cstring(filename);
 	defer free(cstr);
 	handle := _unix_dlopen(cstr, flags);
 	return handle;
 }
 dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr {
 	assert(handle != nil);
-	cstr := strings.new_c_string(symbol);
+	cstr := strings.new_cstring(symbol);
 	defer free(cstr);
 	proc_handle := _unix_dlsym(handle, cstr);
 	return proc_handle;
@@ -265,14 +264,14 @@ dlclose :: inline proc(handle: rawptr) -> bool {
 	return _unix_dlclose(handle) == 0;
 }
 dlerror :: proc() -> string {
-	return strings.to_odin_string(_unix_dlerror());
+	return string(_unix_dlerror());
 }
 
 
 _alloc_command_line_arguments :: proc() -> []string {
 	args := make([]string, __argc__);
 	for i in 0..__argc__ {
-		args[i] = strings.to_odin_string((__argv__+i)^);
+		args[i] = string((__argv__+i)^);
 	}
 	return args;
 }

+ 3 - 3
core/os_windows.odin

@@ -98,7 +98,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
 	buf: [300]byte;
 	copy(buf[..], cast([]byte)path);
 
-	handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
+	handle := Handle(win32.create_file_a(cstring(&buf[0]), access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
 	if handle != INVALID_HANDLE do return handle, ERROR_NONE;
 
 	err := Errno(win32.get_last_error());
@@ -219,7 +219,7 @@ last_write_time_by_name :: proc(name: string) -> File_Time {
 
 	copy(buf[..], cast([]byte)name);
 
-	if win32.get_file_attributes_ex_a(&buf[0], win32.GetFileExInfoStandard, &data) {
+	if win32.get_file_attributes_ex_a(cstring(&buf[0]), win32.GetFileExInfoStandard, &data) {
 		last_write_time = data.last_write_time;
 	}
 
@@ -272,7 +272,7 @@ _alloc_command_line_arguments :: proc() -> []string {
 
         buf := make([]byte, olen);
        	n := win32.wide_char_to_multi_byte(win32.CP_UTF8, 0, wc_str, -1,
-       	                                   &buf[0], olen, nil, nil);
+       	                                   cstring(&buf[0]), olen, nil, nil);
        	if n > 0 {
        		n -= 1;
        	}

+ 16 - 16
core/os_x.odin

@@ -122,34 +122,34 @@ X_OK :: 1; // Test for execute permission
 F_OK :: 0; // Test for file existance
 
 foreign libc {
-	@(link_name="open")    _unix_open    :: proc(path: ^byte, mode: int) -> Handle ---;
+	@(link_name="open")    _unix_open    :: proc(path: cstring, mode: int) -> Handle ---;
 	@(link_name="close")   _unix_close   :: proc(handle: Handle) ---;
 	@(link_name="read")    _unix_read    :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
 	@(link_name="write")   _unix_write   :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---;
 	@(link_name="lseek")   _unix_lseek   :: proc(fs: Handle, offset: int, whence: int) -> int ---;
 	@(link_name="gettid")  _unix_gettid  :: proc() -> u64 ---;
-	@(link_name="stat")    _unix_stat    :: proc(path: ^byte, stat: ^Stat) -> int ---;
-	@(link_name="access")  _unix_access  :: proc(path: ^byte, mask: int) -> int ---;
+	@(link_name="stat")    _unix_stat    :: proc(path: cstring, stat: ^Stat) -> int ---;
+	@(link_name="access")  _unix_access  :: proc(path: cstring, mask: int) -> int ---;
 
 	@(link_name="malloc")  _unix_malloc  :: proc(size: int) -> rawptr ---;
 	@(link_name="calloc")  _unix_calloc  :: proc(num, size: int) -> rawptr ---;
 	@(link_name="free")    _unix_free    :: proc(ptr: rawptr) ---;
 	@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---;
-	@(link_name="getenv")  _unix_getenv  :: proc(^byte) -> ^byte ---;
+	@(link_name="getenv")  _unix_getenv  :: proc(cstring) -> cstring ---;
 
 	@(link_name="exit")    _unix_exit    :: proc(status: int) ---;
 }
 
 foreign dl {
-	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: ^byte, flags: int) -> rawptr ---;
-	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: ^byte) -> rawptr ---;
+	@(link_name="dlopen")  _unix_dlopen  :: proc(filename: cstring, flags: int) -> rawptr ---;
+	@(link_name="dlsym")   _unix_dlsym   :: proc(handle: rawptr, symbol: cstring) -> rawptr ---;
 	@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---;
-	@(link_name="dlerror") _unix_dlerror :: proc() -> ^byte ---;
+	@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---;
 }
 
 // TODO(zangent): Change this to just `open` when Bill fixes overloading.
 open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	defer free(cstr);
 	handle := _unix_open(cstr, mode);
 	if handle == -1 {
@@ -218,14 +218,14 @@ last_write_time_by_name :: proc(name: string) -> File_Time {}
 
 stat :: inline proc(path: string) -> (Stat, bool) {
 	s: Stat;
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	defer free(cstr);
 	ret_int := _unix_stat(cstr, &s);
 	return s, ret_int==0;
 }
 
 access :: inline proc(path: string, mask: int) -> bool {
-	cstr := strings.new_c_string(path);
+	cstr := strings.new_cstring(path);
 	defer free(cstr);
 	return _unix_access(cstr, mask) == 0;
 }
@@ -242,13 +242,13 @@ heap_free :: inline proc(ptr: rawptr) {
 }
 
 getenv :: proc(name: string) -> (string, bool) {
-	path_str := strings.new_c_string(name);
+	path_str := strings.new_cstring(name);
 	defer free(path_str);
 	cstr := _unix_getenv(path_str);
 	if cstr == nil {
 		return "", false;
 	}
-	return strings.to_odin_string(cstr), true;
+	return string(cstr), true;
 }
 
 exit :: inline proc(code: int) {
@@ -262,14 +262,14 @@ current_thread_id :: proc() -> int {
 }
 
 dlopen :: inline proc(filename: string, flags: int) -> rawptr {
-	cstr := strings.new_c_string(filename);
+	cstr := strings.new_cstring(filename);
 	defer free(cstr);
 	handle := _unix_dlopen(cstr, flags);
 	return handle;
 }
 dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr {
 	assert(handle != nil);
-	cstr := strings.new_c_string(symbol);
+	cstr := strings.new_cstring(symbol);
 	defer free(cstr);
 	proc_handle := _unix_dlsym(handle, cstr);
 	return proc_handle;
@@ -279,14 +279,14 @@ dlclose :: inline proc(handle: rawptr) -> bool {
 	return _unix_dlclose(handle) == 0;
 }
 dlerror :: proc() -> string {
-	return strings.to_odin_string(_unix_dlerror());
+	return string(_unix_dlerror());
 }
 
 
 _alloc_command_line_arguments :: proc() -> []string {
 	args := make([]string, __argc__);
 	for i in 0..__argc__ {
-		args[i] = strings.to_odin_string((__argv__+i)^);
+		args[i] = string((__argv__+i)^);
 	}
 	return args;
 }

+ 4 - 0
core/raw.odin

@@ -8,6 +8,10 @@ String :: struct {
 	len:  int,
 }
 
+Cstring :: struct {
+	data: ^byte,
+}
+
 Slice :: struct {
 	data: rawptr,
 	len:  int,

+ 4 - 6
core/strings.odin

@@ -7,18 +7,16 @@ new_string :: proc(s: string) -> string {
 	return string(c[..len(s)]);
 }
 
-new_c_string :: proc(s: string) -> ^byte {
+new_cstring :: proc(s: string) -> cstring {
 	c := make([]byte, len(s)+1);
 	copy(c, cast([]byte)s);
 	c[len(s)] = 0;
-	return &c[0];
+	return cstring(&c[0]);
 }
 
-to_odin_string :: proc(str: ^byte) -> string {
+to_odin_string :: proc(str: cstring) -> string {
 	if str == nil do return "";
-	end := str;
-	for end^ != 0 do end+=1;
-	return string(mem.slice_ptr(str, end-str));
+	return string(str);
 }
 
 contains_rune :: proc(s: string, r: rune) -> int {

+ 2 - 2
core/sys/wgl.odin

@@ -55,7 +55,7 @@ Glyph_Metrics_Float :: struct {
 Create_Context_Attribs_ARB_Type :: #type proc "c" (hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
 Choose_Pixel_Format_ARB_Type    :: #type proc "c" (hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool;
 Swap_Interval_EXT_Type          :: #type proc "c" (interval: i32) -> bool;
-Get_Extensions_String_ARB_Type  :: #type proc "c" (Hdc) -> ^byte;
+Get_Extensions_String_ARB_Type  :: #type proc "c" (Hdc) -> cstring;
 
 // Procedures
 	create_context_attribs_arb: Create_Context_Attribs_ARB_Type;
@@ -72,7 +72,7 @@ foreign opengl32 {
 	make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---;
 
 	@(link_name="wglGetProcAddress")
-	get_gl_proc_address :: proc(c_str: ^byte) -> rawptr ---;
+	get_gl_proc_address :: proc(c_str: cstring) -> rawptr ---;
 
 	@(link_name="wglDeleteContext")
 	delete_context :: proc(hglrc: Hglrc) -> Bool ---;

+ 88 - 86
core/sys/windows.odin

@@ -28,6 +28,8 @@ Long_Ptr :: distinct int;
 
 Bool :: distinct b32;
 
+Wstring :: ^u16;
+
 Point :: struct {
 	x, y: i32,
 }
@@ -40,7 +42,7 @@ Wnd_Class_Ex_A :: struct {
 	icon:                  Hicon,
 	cursor:                Hcursor,
 	background:            Hbrush,
-	menu_name, class_name: ^byte,
+	menu_name, class_name: cstring,
 	sm:                    Hicon,
 }
 
@@ -52,7 +54,7 @@ Wnd_Class_Ex_W :: struct {
 	icon:                  Hicon,
 	cursor:                Hcursor,
 	background:            Hbrush,
-	menu_name, class_name: ^u16,
+	menu_name, class_name: Wstring,
 	sm:                    Hicon,
 }
 
@@ -145,24 +147,24 @@ Process_Information :: struct {
 }
 
 Startup_Info :: struct {
-    cb             : u32,
-    reserved       : ^u16,
-    desktop        : ^u16,
-    title          : ^u16,
-    x              : u32,
-    y              : u32,
-    x_size         : u32,
-    y_size         : u32,
-    x_count_chars  : u32,
-    y_count_chars  : u32,
-    fill_attribute : u32,
-    flags          : u32,
-    show_window    : u16,
-    _              : u16,
-    _              : ^byte,
-    stdin          : Handle,
-    stdout         : Handle,
-    stderr         : Handle,
+    cb:             u32,
+    reserved:       Wstring,
+    desktop:        Wstring,
+    title:          Wstring,
+    x:              u32,
+    y:              u32,
+    x_size:         u32,
+    y_size:         u32,
+    x_count_chars:  u32,
+    y_count_chars:  u32,
+    fill_attribute: u32,
+    flags:          u32,
+    show_window:    u16,
+    _:              u16,
+    _:              cstring,
+    stdin:          Handle,
+    stdout:         Handle,
+    stderr:         Handle,
 }
 
 Pixel_Format_Descriptor :: struct {
@@ -276,16 +278,16 @@ Raw_Input :: struct {
 
 
 Overlapped :: struct {
-    internal      : ^u64,
-    internal_high : ^u64,
-    using _ : struct #raw_union {
-        using _ : struct {
-            offset      : u32,
-            offset_high : u32,
+    internal:      ^u64,
+    internal_high: ^u64,
+    using _: struct #raw_union {
+        using _: struct {
+            offset:      u32,
+            offset_high: u32,
         },
-        pointer : rawptr,
+        pointer: rawptr,
     },
-    event : Handle,
+    event: Handle,
 }
 
 File_Notify_Information :: struct {
@@ -389,7 +391,7 @@ Hwnd_TOP                 :: Hwnd(uintptr(0));
 
 BI_RGB         :: 0;
 DIB_RGB_COLORS :: 0x00;
-SRCCOPY: u32    : 0x00cc0020;
+SRCCOPY: u32 : 0x00cc0020;
 
 
 MONITOR_DEFAULTTONULL    :: 0x00000000;
@@ -550,22 +552,22 @@ CP_UTF8       :: 65001; // UTF-8 translation
 @(default_calling_convention = "std")
 foreign kernel32 {
 	@(link_name="GetLastError")              get_last_error              :: proc() -> i32 ---;
-	@(link_name="CreateProcessA")		     create_process_a		     :: proc(application_name, command_line: ^byte,
+	@(link_name="CreateProcessA")		     create_process_a		     :: proc(application_name, command_line: cstring,
 	                                                              				 process_attributes, thread_attributes: ^Security_Attributes,
 	                                                              				 inherit_handle: Bool, creation_flags: u32, environment: rawptr,
-	                                                              				 current_direcotry: ^byte, startup_info : ^Startup_Info,
-	                                                              				 process_information : ^Process_Information) -> Bool ---;
+	                                                              				 current_direcotry: cstring, startup_info: ^Startup_Info,
+	                                                              				 process_information: ^Process_Information) -> Bool ---;
 	@(link_name="GetExitCodeProcess")		 get_exit_code_process       :: proc(process: Handle, exit: ^u32) -> Bool ---;
 	@(link_name="ExitProcess")               exit_process                :: proc(exit_code: u32) ---;
-	@(link_name="GetModuleHandleA")          get_module_handle_a         :: proc(module_name: ^byte) -> Hinstance ---;
-	@(link_name="GetModuleHandleW")          get_module_handle_w         :: proc(module_name: ^u16) -> Hinstance ---;
+	@(link_name="GetModuleHandleA")          get_module_handle_a         :: proc(module_name: cstring) -> Hinstance ---;
+	@(link_name="GetModuleHandleW")          get_module_handle_w         :: proc(module_name: Wstring) -> Hinstance ---;
 	@(link_name="Sleep")                     sleep                       :: proc(ms: i32) -> i32 ---;
 	@(link_name="QueryPerformanceFrequency") query_performance_frequency :: proc(result: ^i64) -> i32 ---;
 	@(link_name="QueryPerformanceCounter")   query_performance_counter   :: proc(result: ^i64) -> i32 ---;
-	@(link_name="OutputDebugStringA")        output_debug_string_a       :: proc(c_str: ^byte) ---;
+	@(link_name="OutputDebugStringA")        output_debug_string_a       :: proc(c_str: cstring) ---;
 
-	@(link_name="GetCommandLineA")    get_command_line_a    :: proc() -> ^byte ---;
-	@(link_name="GetCommandLineW")    get_command_line_w    :: proc() -> ^u16 ---;
+	@(link_name="GetCommandLineA")    get_command_line_a    :: proc() -> cstring ---;
+	@(link_name="GetCommandLineW")    get_command_line_w    :: proc() -> Wstring ---;
 	@(link_name="GetSystemMetrics")   get_system_metrics    :: proc(index: i32) -> i32 ---;
 	@(link_name="GetCurrentThreadId") get_current_thread_id :: proc() -> u32 ---;
 
@@ -578,12 +580,12 @@ foreign kernel32 {
 	@(link_name="GetStdHandle") get_std_handle :: proc(h: i32) -> Handle ---;
 
 	@(link_name="CreateFileA")
-	create_file_a :: proc(filename: ^byte, desired_access, share_module: u32,
+	create_file_a :: proc(filename: cstring, desired_access, share_module: u32,
 	                      security: rawptr,
 	                      creation, flags_and_attribs: u32, template_file: Handle) -> Handle ---;
 
 	@(link_name="CreateFileW")
-	create_file_w :: proc(filename: ^u16, desired_access, share_module: u32,
+	create_file_w :: proc(filename: Wstring, desired_access, share_module: u32,
 	                      security: rawptr,
 	                      creation, flags_and_attribs: u32, template_file: Handle) -> Handle ---;
 
@@ -592,34 +594,34 @@ foreign kernel32 {
 	@(link_name="WriteFile") write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool ---;
 
 	@(link_name="GetFileSizeEx")              get_file_size_ex               :: proc(file_handle: Handle, file_size: ^i64) -> Bool ---;
-	@(link_name="GetFileAttributesA")         get_file_attributes_a          :: proc(filename: ^byte) -> u32 ---;
-	@(link_name="GetFileAttributesW")         get_file_attributes_w          :: proc(filename: ^u16) -> u32 ---;
-	@(link_name="GetFileAttributesExA")       get_file_attributes_ex_a       :: proc(filename: ^byte, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---;
+	@(link_name="GetFileAttributesA")         get_file_attributes_a          :: proc(filename: cstring) -> u32 ---;
+	@(link_name="GetFileAttributesW")         get_file_attributes_w          :: proc(filename: Wstring) -> u32 ---;
+	@(link_name="GetFileAttributesExA")       get_file_attributes_ex_a       :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---;
 	@(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool ---;
 
-	@(link_name="CreateDirectoryA") 		  create_directory_a			 :: proc(path: ^byte, security_attributes: ^Security_Attributes) -> Bool ---;
-	@(link_name="CreateDirectoryW") 		  create_directory_w			 :: proc(path: ^u16, security_attributes: ^Security_Attributes) -> Bool ---;
+	@(link_name="CreateDirectoryA") 		  create_directory_a			 :: proc(path: cstring, security_attributes: ^Security_Attributes) -> Bool ---;
+	@(link_name="CreateDirectoryW") 		  create_directory_w			 :: proc(path: Wstring, security_attributes: ^Security_Attributes) -> Bool ---;
 
 	@(link_name="GetFileType")    get_file_type    :: proc(file_handle: Handle) -> u32 ---;
 	@(link_name="SetFilePointer") set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 ---;
 
 	@(link_name="SetHandleInformation") set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool ---;
 
-	@(link_name="FindFirstFileA") find_first_file_a :: proc(file_name : ^byte, data : ^Find_Data_A) -> Handle ---;
-	@(link_name="FindNextFileA")  find_next_file_a  :: proc(file : Handle, data : ^Find_Data_A) -> Bool ---;
-	
-	@(link_name="FindFirstFileW") find_first_file_w :: proc(file_name : ^u16, data : ^Find_Data_W) -> Handle ---;
-	@(link_name="FindNextFileW")  find_next_file_w  :: proc(file : Handle, data : ^Find_Data_W) -> Bool ---;
-	
-	@(link_name="FindClose")      find_close        :: proc(file : Handle) -> Bool ---;
+	@(link_name="FindFirstFileA") find_first_file_a :: proc(file_name: cstring, data: ^Find_Data_A) -> Handle ---;
+	@(link_name="FindNextFileA")  find_next_file_a  :: proc(file: Handle, data: ^Find_Data_A) -> Bool ---;
+
+	@(link_name="FindFirstFileW") find_first_file_w :: proc(file_name: Wstring, data: ^Find_Data_W) -> Handle ---;
+	@(link_name="FindNextFileW")  find_next_file_w  :: proc(file: Handle, data: ^Find_Data_W) -> Bool ---;
+
+	@(link_name="FindClose")      find_close        :: proc(file: Handle) -> Bool ---;
 
-	@(link_name="MoveFileExA")    move_file_ex_a    :: proc(existing, new: ^byte, flags: u32) -> Bool ---;
-	@(link_name="DeleteFileA")    delete_file_a     :: proc(file_name : ^byte) -> Bool ---;
-	@(link_name="CopyFileA")      copy_file_a       :: proc(existing, new: ^byte, fail_if_exists: Bool) -> Bool ---;
+	@(link_name="MoveFileExA")    move_file_ex_a    :: proc(existing, new: cstring, flags: u32) -> Bool ---;
+	@(link_name="DeleteFileA")    delete_file_a     :: proc(file_name: cstring) -> Bool ---;
+	@(link_name="CopyFileA")      copy_file_a       :: proc(existing, new: cstring, fail_if_exists: Bool) -> Bool ---;
 
-	@(link_name="MoveFileExW")    move_file_ex_w    :: proc(existing, new: ^u16, flags: u32) -> Bool ---;
-	@(link_name="DeleteFileW")    delete_file_w     :: proc(file_name : ^u16) -> Bool ---;
-	@(link_name="CopyFileW")      copy_file_w       :: proc(existing, new: ^u16, fail_if_exists: Bool) -> Bool ---;
+	@(link_name="MoveFileExW")    move_file_ex_w    :: proc(existing, new: Wstring, flags: u32) -> Bool ---;
+	@(link_name="DeleteFileW")    delete_file_w     :: proc(file_name: Wstring) -> Bool ---;
+	@(link_name="CopyFileW")      copy_file_w       :: proc(existing, new: Wstring, fail_if_exists: Bool) -> Bool ---;
 
 	@(link_name="HeapAlloc")      heap_alloc       :: proc(h: Handle, flags: u32, bytes: int) -> rawptr ---;
 	@(link_name="HeapReAlloc")    heap_realloc     :: proc(h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr ---;
@@ -630,7 +632,7 @@ foreign kernel32 {
 	@(link_name="LocalReAlloc")   local_realloc    :: proc(mem: rawptr, bytes: int, flags: uint) -> rawptr ---;
 	@(link_name="LocalFree")      local_free       :: proc(mem: rawptr) -> rawptr ---;
 
-	@(link_name="FindFirstChangeNotificationA") find_first_change_notification_a :: proc(path: ^byte, watch_subtree: Bool, filter: u32) -> Handle ---;
+	@(link_name="FindFirstChangeNotificationA") find_first_change_notification_a :: proc(path: cstring, watch_subtree: Bool, filter: u32) -> Handle ---;
 	@(link_name="FindNextChangeNotification")   find_next_change_notification    :: proc(h: Handle) -> Bool ---;
 	@(link_name="FindCloseChangeNotification")  find_close_change_notification   :: proc(h: Handle) -> Bool ---;
 
@@ -639,16 +641,16 @@ foreign kernel32 {
 	                                                                      bytes_returned: ^u32, overlapped: ^Overlapped,
 	                                                                      completion: rawptr) -> Bool ---;
 
-	@(link_name="WideCharToMultiByte") wide_char_to_multi_byte :: proc(code_page: u32, flags : u32,
-	                                                                   wchar_str: ^u16, wchar: i32,
-	                                                                   multi_str: ^byte, multi: i32,
-	                                                                   default_char: ^byte, used_default_char: ^Bool) -> i32 ---;
-	
-	@(link_name="MultiByteToWideChar") multi_byte_to_wide_char :: proc(code_page: u32, flags : u32,
-	                                                                   mb_str: ^byte, mb: i32,
-	                                                                   wc_str : ^u16, wc: i32) -> i32 ---;
-	
-	@(link_name="CreateSemaphoreA")    create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^byte) -> Handle ---;
+	@(link_name="WideCharToMultiByte") wide_char_to_multi_byte :: proc(code_page: u32, flags: u32,
+	                                                                   wchar_str: Wstring, wchar: i32,
+	                                                                   multi_str: cstring, multi: i32,
+	                                                                   default_char: cstring, used_default_char: ^Bool) -> i32 ---;
+
+	@(link_name="MultiByteToWideChar") multi_byte_to_wide_char :: proc(code_page: u32, flags: u32,
+	                                                                   mb_str: cstring, mb: i32,
+	                                                                   wc_str: Wstring, wc: i32) -> i32 ---;
+
+	@(link_name="CreateSemaphoreA")    create_semaphore_a     :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle ---;
 	@(link_name="ReleaseSemaphore")    release_semaphore      :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool ---;
 	@(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 ---;
 }
@@ -692,31 +694,31 @@ foreign kernel32 {
 	@(link_name="EnterCriticalSection")                  enter_critical_section                     :: proc(critical_section: ^Critical_Section) ---;
 	@(link_name="LeaveCriticalSection")                  leave_critical_section                     :: proc(critical_section: ^Critical_Section) ---;
 
-	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^byte) -> Handle ---;
+	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: cstring) -> Handle ---;
 
-	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: ^byte)  -> Hmodule ---;
-	@(link_name="LoadLibraryW")   load_library_w   :: proc(c_str: ^u16) -> Hmodule ---;
+	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: cstring)  -> Hmodule ---;
+	@(link_name="LoadLibraryW")   load_library_w   :: proc(c_str: Wstring) -> Hmodule ---;
 	@(link_name="FreeLibrary")    free_library     :: proc(h: Hmodule) ---;
-	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^byte) -> rawptr ---;
+	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: cstring) -> rawptr ---;
 
 }
 
 @(default_calling_convention = "std")
 foreign user32 {
 	@(link_name="GetDesktopWindow") get_desktop_window  :: proc() -> Hwnd ---;
-	@(link_name="ShowCursor")       show_cursor         :: proc(show : Bool) ---;
+	@(link_name="ShowCursor")       show_cursor         :: proc(show: Bool) ---;
 	@(link_name="GetCursorPos")     get_cursor_pos      :: proc(p: ^Point) -> Bool ---;
 	@(link_name="SetCursorPos")     set_cursor_pos      :: proc(x, y: i32) -> Bool ---;
 	@(link_name="ScreenToClient")   screen_to_client    :: proc(h: Hwnd, p: ^Point) -> Bool ---;
 	@(link_name="ClientToScreen")   client_to_screen    :: proc(h: Hwnd, p: ^Point) -> Bool ---;
 	@(link_name="PostQuitMessage")  post_quit_message   :: proc(exit_code: i32) ---;
-	@(link_name="SetWindowTextA")   set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^byte) -> Bool ---;
+	@(link_name="SetWindowTextA")   set_window_text_a   :: proc(hwnd: Hwnd, c_string: cstring) -> Bool ---;
 	@(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 ---;
 	@(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 ---;
 
 	@(link_name="CreateWindowExA")
 	create_window_ex_a :: proc(ex_style: u32,
-	                           class_name, title: ^byte,
+	                           class_name, title: cstring,
 	                           style: u32,
 	                           x, y, w, h: i32,
 	                           parent: Hwnd, menu: Hmenu, instance: Hinstance,
@@ -724,7 +726,7 @@ foreign user32 {
 
 	@(link_name="CreateWindowExW")
 	create_window_ex_w :: proc(ex_style: u32,
-	                           class_name, title: ^u16,
+	                           class_name, title: Wstring,
 	                           style: u32,
 	                           x, y, w, h: i32,
 	                           parent: Hwnd, menu: Hmenu, instance: Hinstance,
@@ -735,14 +737,14 @@ foreign user32 {
 	@(link_name="DispatchMessageA") dispatch_message_a :: proc(msg: ^Msg) -> Lresult ---;
 	@(link_name="DispatchMessageW") dispatch_message_w :: proc(msg: ^Msg) -> Lresult ---;
 	@(link_name="UpdateWindow")     update_window      :: proc(hwnd: Hwnd) -> Bool ---;
-	@(link_name="GetMessageA")      get_message_a      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool ---;
-	@(link_name="GetMessageW")      get_message_w      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool ---;
+	@(link_name="GetMessageA")      get_message_a      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool ---;
+	@(link_name="GetMessageW")      get_message_w      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max: u32) -> Bool ---;
 
 	@(link_name="PeekMessageA") peek_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool ---;
 	@(link_name="PeekMessageW") peek_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool ---;
 
 
-	@(link_name="PostMessageA") post_message :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool ---;
+	@(link_name="PostMessageA") post_message :: proc(hwnd: Hwnd, msg, wparam, lparam: u32) -> Bool ---;
 
 	@(link_name="DefWindowProcA") def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---;
 
@@ -753,7 +755,7 @@ foreign user32 {
 	@(link_name="DescribePixelFormat") describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes: u32, pfd: ^Pixel_Format_Descriptor) -> i32 ---;
 
 	@(link_name="GetMonitor_InfoA")  get_monitor_info_a  :: proc(monitor: Hmonitor, mi: ^Monitor_Info) -> Bool ---;
-	@(link_name="MonitorFromWindow") monitor_from_window :: proc(wnd: Hwnd, flags : u32) -> Hmonitor ---;
+	@(link_name="MonitorFromWindow") monitor_from_window :: proc(wnd: Hwnd, flags: u32) -> Hmonitor ---;
 
 	@(link_name="SetWindowPos") set_window_pos :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) ---;
 
@@ -766,15 +768,15 @@ foreign user32 {
 	@(link_name="GetWindowLongPtrW") get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr ---;
 	@(link_name="SetWindowLongPtrW") set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr ---;
 
-	@(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: ^byte, maxCount: i32) -> i32 ---;
+	@(link_name="GetWindowText") get_window_text :: proc(wnd: Hwnd, str: cstring, maxCount: i32) -> i32 ---;
 
 	@(link_name="GetClientRect") get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool ---;
 
 	@(link_name="GetDC")     get_dc     :: proc(h: Hwnd) -> Hdc ---;
 	@(link_name="ReleaseDC") release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 ---;
 
-	@(link_name="MapVirtualKeyA") map_virtual_key_a :: proc(scancode : u32, map_type : u32) -> u32 ---;
-	@(link_name="MapVirtualKeyW") map_virtual_key_w :: proc(scancode : u32, map_type : u32) -> u32 ---;
+	@(link_name="MapVirtualKeyA") map_virtual_key_a :: proc(scancode: u32, map_type: u32) -> u32 ---;
+	@(link_name="MapVirtualKeyW") map_virtual_key_w :: proc(scancode: u32, map_type: u32) -> u32 ---;
 
 	@(link_name="GetKeyState")      get_key_state       :: proc(v_key: i32) -> i16 ---;
 	@(link_name="GetAsyncKeyState") get_async_key_state :: proc(v_key: i32) -> i16 ---;
@@ -782,9 +784,9 @@ foreign user32 {
 	@(link_name="SetForegroundWindow") set_foreground_window :: proc(h: Hwnd) -> Bool ---;
 	@(link_name="SetFocus")            set_focus             :: proc(h: Hwnd) -> Hwnd ---;
 
-	@(link_name="LoadCursorA")      load_cursor_a       :: proc(instance : Hinstance, cursor_name : ^u8) -> Hcursor ---;
+	@(link_name="LoadCursorA")      load_cursor_a       :: proc(instance: Hinstance, cursor_name: cstring) -> Hcursor ---;
 	@(link_name="GetCursor")        get_cursor          :: proc() -> Hcursor ---;
-	@(link_name="SetCursor")        set_cursor          :: proc(cursor : Hcursor) -> Hcursor ---;
+	@(link_name="SetCursor")        set_cursor          :: proc(cursor: Hcursor) -> Hcursor ---;
 
 	@(link_name="RegisterRawInputDevices") register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool ---;
 
@@ -814,7 +816,7 @@ foreign gdi32 {
 
 @(default_calling_convention = "std")
 foreign shell32 {
-	@(link_name="CommandLineToArgvW") command_line_to_argv_w :: proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 ---;
+	@(link_name="CommandLineToArgvW") command_line_to_argv_w :: proc(cmd_list: Wstring, num_args: ^i32) -> ^Wstring ---;
 }
 
 @(default_calling_convention = "std")

+ 3 - 1
src/check_expr.cpp

@@ -1497,9 +1497,9 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
 				err_type = y->type;
 			}
 			gbString type_string = type_to_string(err_type);
+			defer (gb_string_free(type_string));
 			err_str = gb_string_make(c->tmp_allocator,
 			                         gb_bprintf("operator '%.*s' not defined for type '%s'", LIT(token_strings[op]), type_string));
-			gb_string_free(type_string);
 		}
 	} else {
 		gbString xt, yt;
@@ -2279,6 +2279,8 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
 			case Basic_UntypedNil:
 				if (is_type_any(target_type)) {
 					target_type = t_untyped_nil;
+				} else if (is_type_cstring(target_type)) {
+					target_type = t_untyped_nil;
 				} else if (!type_has_nil(target_type)) {
 					operand->mode = Addressing_Invalid;
 					convert_untyped_error(c, operand, target_type);

+ 2 - 0
src/types.cpp

@@ -1083,6 +1083,8 @@ bool type_has_nil(Type *t) {
 		case Basic_rawptr:
 		case Basic_any:
 			return true;
+		case Basic_cstring:
+			return true;
 		}
 		return false;
 	} break;