stdlib.odin 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package odin_libc
  2. import "base:intrinsics"
  3. import "base:runtime"
  4. import "core:c"
  5. import "core:os"
  6. import "core:slice"
  7. import "core:sort"
  8. import "core:strconv"
  9. import "core:strings"
  10. @(require, linkage="strong", link_name="malloc")
  11. malloc :: proc "c" (size: uint) -> rawptr {
  12. context = g_ctx
  13. ptr, err := runtime.mem_alloc_non_zeroed(int(size))
  14. assert(err == nil, "allocation failure")
  15. return raw_data(ptr)
  16. }
  17. @(require, linkage="strong", link_name="aligned_alloc")
  18. aligned_alloc :: proc "c" (alignment: uint, size: uint) -> rawptr {
  19. context = g_ctx
  20. ptr, err := runtime.mem_alloc_non_zeroed(int(size), int(alignment))
  21. assert(err == nil, "allocation failure")
  22. return raw_data(ptr)
  23. }
  24. @(require, linkage="strong", link_name="free")
  25. free :: proc "c" (ptr: rawptr) {
  26. context = g_ctx
  27. runtime.mem_free(ptr)
  28. }
  29. @(require, linkage="strong", link_name="realloc")
  30. realloc :: proc "c" (ptr: rawptr, new_size: uint) -> rawptr {
  31. context = g_ctx
  32. // -1 for the old_size, assumed to be wrapped with the mem.Compat_Allocator to get the right size.
  33. // Note that realloc does not actually care about alignment and is allowed to just align it to something
  34. // else than the original allocation.
  35. ptr, err := runtime.non_zero_mem_resize(ptr, -1, int(new_size))
  36. assert(err == nil, "realloc failure")
  37. return raw_data(ptr)
  38. }
  39. @(require, linkage="strong", link_name="qsort")
  40. qsort :: proc "c" (base: rawptr, num: uint, size: uint, cmp: proc "c" (a, b: rawptr) -> i32) {
  41. context = g_ctx
  42. Inputs :: struct {
  43. base: rawptr,
  44. num: uint,
  45. size: uint,
  46. cmp: proc "c" (a, b: rawptr) -> i32,
  47. }
  48. sort.sort({
  49. collection = &Inputs{base, num, size, cmp},
  50. len = proc(it: sort.Interface) -> int {
  51. inputs := (^Inputs)(it.collection)
  52. return int(inputs.num)
  53. },
  54. less = proc(it: sort.Interface, i, j: int) -> bool {
  55. inputs := (^Inputs)(it.collection)
  56. a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
  57. b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
  58. return inputs.cmp(a, b) < 0
  59. },
  60. swap = proc(it: sort.Interface, i, j: int) {
  61. inputs := (^Inputs)(it.collection)
  62. a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
  63. b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
  64. slice.ptr_swap_non_overlapping(a, b, int(inputs.size))
  65. },
  66. })
  67. }
  68. @(require, linkage="strong", link_name="atoi")
  69. atoi :: proc "c" (str: cstring) -> i32 {
  70. return i32(atoll(str))
  71. }
  72. @(require, linkage="strong", link_name="atol")
  73. atol :: proc "c" (str: cstring) -> c.long {
  74. return c.long(atoll(str))
  75. }
  76. @(require, linkage="strong", link_name="atoll")
  77. atoll :: proc "c" (str: cstring) -> c.longlong {
  78. context = g_ctx
  79. sstr := string(str)
  80. sstr = strings.trim_left_space(sstr)
  81. i, _ := strconv.parse_i64_of_base(sstr, 10)
  82. return c.longlong(i)
  83. }
  84. @(require, linkage="strong", link_name="atof")
  85. atof :: proc "c" (str: cstring) -> f64 {
  86. context = g_ctx
  87. sstr := string(str)
  88. sstr = strings.trim_left_space(sstr)
  89. f, _ := strconv.parse_f64(sstr)
  90. return f
  91. }
  92. @(require, linkage="strong", link_name="strtol")
  93. strtol :: proc "c" (str: cstring, str_end: ^cstring, base: i32) -> c.long {
  94. context = g_ctx
  95. sstr := string(str)
  96. sstr = strings.trim_left_space(sstr)
  97. n: int
  98. i, _ := strconv.parse_i64_of_base(sstr, int(base), &n)
  99. str_end ^= cstring(raw_data(sstr)[n:])
  100. if str_end != nil {
  101. str_end ^= cstring(raw_data(sstr)[n:])
  102. }
  103. return c.long(clamp(i, i64(min(c.long)), i64(max(c.long))))
  104. }
  105. @(require, linkage="strong", link_name="strtod")
  106. strtod :: proc "c" (str: cstring, str_end: ^cstring) -> c.double {
  107. context = g_ctx
  108. sstr := string(str)
  109. sstr = strings.trim_left_space(sstr)
  110. n: int
  111. val, _ := strconv.parse_f64(sstr, &n)
  112. if str_end != nil {
  113. str_end ^= cstring(raw_data(sstr)[n:])
  114. }
  115. return c.double(val)
  116. }
  117. @(require, linkage="strong", link_name="abort")
  118. abort :: proc "c" () -> ! {
  119. intrinsics.trap()
  120. }
  121. ATEXIT_MAX :: 32
  122. @(private)
  123. atexit_functions: [ATEXIT_MAX]proc "c" ()
  124. @(private)
  125. atexit_functions_count: int
  126. @(require, linkage="strong", link_name="atexit")
  127. atexit :: proc "c" (function: proc "c" ()) -> i32 {
  128. entry := intrinsics.atomic_add(&atexit_functions_count, 1)
  129. if entry >= ATEXIT_MAX {
  130. return -1
  131. }
  132. atexit_functions[entry] = function
  133. return 0
  134. }
  135. @(require, linkage="strong", link_name="exit")
  136. exit :: proc "c" (exit_code: c.int) -> ! {
  137. finish_atexit()
  138. os.exit(int(exit_code))
  139. }
  140. @(private, fini)
  141. finish_atexit :: proc "c" () {
  142. n := intrinsics.atomic_exchange(&atexit_functions_count, 0)
  143. for function in atexit_functions[:n] {
  144. function()
  145. }
  146. }
  147. ldiv_t :: struct {
  148. quot: c.long,
  149. rem: c.long,
  150. }
  151. @(require, linkage="strong", link_name="ldiv")
  152. ldiv :: proc "c" (number: c.long, denom: c.long) -> ldiv_t {
  153. return {
  154. quot = number / denom,
  155. rem = number %% denom,
  156. }
  157. }