stdlib.odin 12 KB

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