stdlib.odin 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. package posix
  2. import "base:intrinsics"
  3. import "core:c"
  4. import "core:c/libc"
  5. when ODIN_OS == .Darwin {
  6. foreign import lib "system:System.framework"
  7. } else {
  8. foreign import lib "system:c"
  9. }
  10. // stdlib.h - standard library definitions
  11. atof :: libc.atof
  12. atoi :: libc.atoi
  13. atol :: libc.atol
  14. atoll :: libc.atoll
  15. strtod :: libc.strtod
  16. strtof :: libc.strtof
  17. strtol :: libc.strtol
  18. strtoll :: libc.strtoll
  19. strtoul :: libc.strtoul
  20. strtoull :: libc.strtoull
  21. rand :: libc.rand
  22. srand :: libc.srand
  23. calloc :: libc.calloc
  24. malloc :: libc.malloc
  25. realloc :: libc.realloc
  26. abort :: libc.abort
  27. atexit :: libc.atexit
  28. at_quick_exit :: libc.at_quick_exit
  29. exit :: libc.exit
  30. _Exit :: libc._Exit
  31. getenv :: libc.getenv
  32. quick_exit :: libc.quick_exit
  33. system :: libc.system
  34. bsearch :: libc.bsearch
  35. qsort :: libc.qsort
  36. abs :: libc.abs
  37. labs :: libc.labs
  38. llabs :: libc.llabs
  39. div :: libc.div
  40. ldiv :: libc.ldiv
  41. lldiv :: libc.lldiv
  42. mblen :: libc.mblen
  43. mbtowc :: libc.mbtowc
  44. wctomb :: libc.wctomb
  45. mbstowcs :: libc.mbstowcs
  46. wcstombs :: libc.wcstombs
  47. free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring {
  48. libc.free(rawptr(ptr))
  49. }
  50. foreign lib {
  51. /*
  52. Takes a pointer to a radix-64 representation, in which the first digit is the least significant,
  53. and return the corresponding long value.
  54. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/a64l.html ]]
  55. */
  56. a64l :: proc(s: cstring) -> c.long ---
  57. /*
  58. The l64a() function shall take a long argument and return a pointer to the corresponding
  59. radix-64 representation.
  60. Returns: a string that may be invalidated by subsequent calls
  61. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/a64l.html ]]
  62. */
  63. l64a :: proc(value: c.long) -> cstring ---
  64. /*
  65. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  66. Returns: non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0,1.0)
  67. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  68. */
  69. drand48 :: proc() -> c.double ---
  70. /*
  71. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  72. Returns: non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0,1.0)
  73. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  74. */
  75. erand48 :: proc(xsubi: ^[3]c.ushort) -> c.double ---
  76. /*
  77. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  78. Returns: return signed long integers uniformly distributed over the interval [-231,231)
  79. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  80. */
  81. mrand48 :: proc() -> c.long ---
  82. /*
  83. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  84. Returns: return signed long integers uniformly distributed over the interval [-231,231)
  85. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  86. */
  87. jrand48 :: proc(xsubi: ^[3]c.ushort) -> c.long ---
  88. /*
  89. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  90. Returns: non-negative, long integers, uniformly distributed over the interval [0,231)
  91. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  92. */
  93. lrand48 :: proc() -> c.long ---
  94. /*
  95. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  96. Returns: non-negative, long integers, uniformly distributed over the interval [0,231)
  97. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  98. */
  99. nrand48 :: proc(xsubi: ^[3]c.ushort) -> c.long ---
  100. /*
  101. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  102. The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called.
  103. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  104. */
  105. srand48 :: proc(seedval: c.long) ---
  106. /*
  107. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  108. The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called.
  109. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  110. */
  111. lcong48 :: proc(param: ^[7]c.ushort) ---
  112. /*
  113. This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.
  114. The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called.
  115. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]]
  116. */
  117. seed48 :: proc(seed16v: ^[3]c.ushort) -> ^[3]c.ushort ---
  118. /*
  119. Parses suboption arguments in a flag argument.
  120. Returns: the index of the matched token string, or -1 if no token strings were matched
  121. Example:
  122. args := runtime.args__
  123. Opt :: enum {
  124. RO,
  125. RW,
  126. NAME,
  127. NIL,
  128. }
  129. token := [Opt]cstring{
  130. .RO = "ro",
  131. .RW = "rw",
  132. .NAME = "name",
  133. .NIL = nil,
  134. }
  135. Options :: struct {
  136. readonly, readwrite: bool,
  137. name: cstring,
  138. }
  139. opts: Options
  140. errfnd: bool
  141. for {
  142. opt := posix.getopt(i32(len(args)), raw_data(args), "o:")
  143. if opt == -1 {
  144. break
  145. }
  146. switch opt {
  147. case 'o':
  148. subopt := posix.optarg
  149. value: cstring
  150. for subopt != "" && !errfnd {
  151. o := posix.getsubopt(&subopt, &token[.RO], &value)
  152. switch Opt(o) {
  153. case .RO: opts.readonly = true
  154. case .RW: opts.readwrite = true
  155. case .NAME:
  156. if value == nil {
  157. fmt.eprintfln("missing value for suboption %s", token[.NAME])
  158. errfnd = true
  159. continue
  160. }
  161. opts.name = value
  162. case .NIL:
  163. fallthrough
  164. case:
  165. fmt.eprintfln("no match found for token: %s", value)
  166. errfnd = true
  167. }
  168. }
  169. if opts.readwrite && opts.readonly {
  170. fmt.eprintfln("Only one of %s and %s can be specified", token[.RO], token[.RW])
  171. errfnd = true
  172. }
  173. case:
  174. errfnd = true
  175. }
  176. }
  177. if errfnd || len(args) == 1 {
  178. fmt.eprintfln("\nUsage: %s -o <suboptstring>", args[0])
  179. fmt.eprintfln("suboptions are 'ro', 'rw', and 'name=<value>'")
  180. posix.exit(1)
  181. }
  182. fmt.println(opts)
  183. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html ]]
  184. */
  185. getsubopt :: proc(optionp: ^cstring, keylistp: [^]cstring, valuep: ^cstring) -> c.int ---
  186. /*
  187. Changes the mode and ownership of the slave pseudo-terminal device associated with its master pseudo-terminal counterpart.
  188. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html ]]
  189. */
  190. grantpt :: proc(fildes: FD) -> result ---
  191. /*
  192. Allows a state array, pointed to by the state argument, to be initialized for future use.
  193. Returns: the previous state array or nil on failure
  194. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]]
  195. */
  196. @(link_name=LINITSTATE)
  197. initstate :: proc(seed: c.uint, state: [^]byte, size: c.size_t) -> [^]byte ---
  198. /*
  199. Sets the state array of the random number generator.
  200. Returns: the previous state array or nil on failure
  201. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]]
  202. */
  203. setstate :: proc(state: [^]byte) -> [^]byte ---
  204. /*
  205. Use a non-linear additive feedback random-number generator employing a default state array
  206. size of 31 long integers to return successive pseudo-random numbers in the range from 0 to 231-1.
  207. The period of this random-number generator is approximately 16 x (231-1).
  208. The size of the state array determines the period of the random-number generator.
  209. Increasing the state array size shall increase the period.
  210. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]]
  211. */
  212. random :: proc() -> c.long ---
  213. /*
  214. Initializes the current state array using the value of seed.
  215. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]]
  216. */
  217. @(link_name=LSRANDOM)
  218. srandom :: proc(seed: c.uint) ---
  219. /*
  220. Creates a directory with a unique name derived from template.
  221. The application shall ensure that the string provided in template is a pathname ending
  222. with at least six trailing 'X' characters.
  223. Returns: nil (setting errno) on failure, template on success
  224. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html ]]
  225. */
  226. mkdtemp :: proc(template: [^]byte) -> cstring ---
  227. /*
  228. Creates a regular file with a unique name derived from template and return a file descriptor
  229. for the file open for reading and writing.
  230. The application shall ensure that the string provided in template is a pathname ending with
  231. at least six trailing 'X' characters.
  232. Returns: -1 (setting errno) on failure, an open file descriptor on success
  233. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html ]]
  234. */
  235. mkstemp :: proc(template: cstring) -> FD ---
  236. /*
  237. Allocates size bytes aligned on a boundary specified by alignment, and shall return a pointer
  238. to the allocated memory in memptr.
  239. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_memalign.html ]]
  240. */
  241. posix_memalign :: proc(memptr: ^[^]byte, alignment: c.size_t, size: c.size_t) -> Errno ---
  242. /*
  243. Establishes a connection between a master device for a pseudo-terminal and a file descriptor.
  244. Returns: -1 (setting errno) on failure, an open file descriptor otherwise
  245. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html ]]
  246. */
  247. posix_openpt :: proc(oflag: O_Flags) -> FD ---
  248. /*
  249. Returns the name of the slave pseudo-terminal device associated with a master pseudo-terminal device.
  250. Returns: nil (setting errno) on failure, the name on success, which may be invalidated on subsequent calls
  251. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/ptsname.html ]]
  252. */
  253. ptsname :: proc(fildes: FD) -> cstring ---
  254. /*
  255. Unlocks the slave pseudo-terminal device associated with the master to which fildes refers.
  256. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html ]]
  257. */
  258. unlockpt :: proc(fildes: FD) -> result ---
  259. /*
  260. Uses the string argument to set environment variable values.
  261. Returns: 0 on success, non-zero (setting errno) on failure
  262. Example:
  263. if posix.putenv("HOME=/usr/home") != 0 {
  264. fmt.panicf("putenv failure: %v", posix.strerror(posix.errno()))
  265. }
  266. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html ]]
  267. */
  268. @(link_name=LPUTENV)
  269. putenv :: proc(string: cstring) -> c.int ---
  270. /*
  271. Updates or add a variable in the environment of the calling process.
  272. Example:
  273. if posix.setenv("HOME", "/usr/home") != .OK {
  274. fmt.panicf("putenv failure: %v", posix.strerror(posix.errno()))
  275. }
  276. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setenv.html ]]
  277. */
  278. setenv :: proc(envname: cstring, envval: cstring, overwrite: b32) -> result ---
  279. /*
  280. Removes an environment variable from the environment of the calling process.
  281. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unsetenv.html ]]
  282. */
  283. @(link_name=LUNSETENV)
  284. unsetenv :: proc(name: cstring) -> result ---
  285. /*
  286. Computes a sequence of pseudo-random integers in the range [0, {RAND_MAX}].
  287. (The value of the {RAND_MAX} macro shall be at least 32767.)
  288. If rand_r() is called with the same initial value for the object pointed to by seed and that object is not modified between successive returns and calls to rand_r(), the same sequence shall be generated.
  289. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand_r.html ]]
  290. */
  291. rand_r :: proc(seed: ^c.uint) -> c.int ---
  292. /*
  293. Derive, from the pathname file_name, an absolute pathname that resolves to the same directory entry,
  294. whose resolution does not involve '.', '..', or symbolic links.
  295. If resolved_name is not `nil` it should be larger than `PATH_MAX` and the result will use it as a backing buffer.
  296. If resolved_name is `nil` the returned string is allocated by `malloc`.
  297. Returns: `nil` (setting errno) on failure, the "real path" otherwise
  298. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html ]]
  299. */
  300. realpath :: proc(file_name: cstring, resolved_name: [^]byte = nil) -> cstring ---
  301. /*
  302. Provides access to an implementation-defined encoding algorithm.
  303. The argument of setkey() is an array of length 64 bytes containing only the bytes with numerical
  304. value of 0 and 1.
  305. If this string is divided into groups of 8, the low-order bit in each group is ignored; this gives a 56-bit key which is used by the algorithm.
  306. This is the key that shall be used with the algorithm to encode a string block passed to encrypt().
  307. The setkey() function shall not change the setting of errno if successful.
  308. An application wishing to check for error situations should set errno to 0 before calling setkey().
  309. If errno is non-zero on return, an error has occurred.
  310. Example:
  311. key: [64]byte
  312. // set key bytes...
  313. posix.set_errno(.NONE)
  314. posix.setkey(raw_data(key))
  315. if errno := posix.errno(); errno != .NONE {
  316. fmt.panicf("setkey failure: %s", posix.strerror(errno))
  317. }
  318. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setkey.html ]]
  319. */
  320. setkey :: proc(key: [^]byte) ---
  321. }
  322. EXIT_FAILURE :: libc.EXIT_FAILURE
  323. EXIT_SUCCESS :: libc.EXIT_SUCCESS
  324. RAND_MAX :: libc.RAND_MAX
  325. MB_CUR_MAX :: libc.MB_CUR_MAX
  326. div_t :: libc.div_t
  327. ldiv_t :: libc.ldiv_t
  328. lldiv_t :: libc.lldiv_t
  329. when ODIN_OS == .NetBSD {
  330. @(private) LPUTENV :: "__putenv50"
  331. @(private) LINITSTATE :: "__initstate60"
  332. @(private) LSRANDOM :: "__srandom60"
  333. @(private) LUNSETENV :: "__unsetenv13"
  334. } else {
  335. @(private) LPUTENV :: "putenv"
  336. @(private) LINITSTATE :: "initstate"
  337. @(private) LSRANDOM :: "srandom"
  338. @(private) LUNSETENV :: "unsetenv"
  339. }