codegen: improve the generated code on architectures with flags
[ajla.git] / os.h
blob62b4cba70e1e2d95a5a6f7ba8e61fdbd0cdc4ffe
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifndef AJLA_OS_H
20 #define AJLA_OS_H
22 #include "list.h"
23 #include "tree.h"
24 #include "thread.h"
26 #if defined(OS_OS2)
28 #include "thread.h"
30 #ifdef HAVE_SYS_TIME_H
31 #include <sys/time.h>
32 #endif
33 #include <sys/stat.h>
34 #include <fcntl.h>
36 #define NO_DIR_HANDLES
38 typedef long long os_off_t;
39 typedef int64_t os_time_t;
40 typedef struct {
41 uint32_t st_mode;
42 uint32_t st_dev;
43 uint8_t st_ino;
44 uint8_t st_nlink;
45 os_off_t st_size;
46 os_off_t st_blocks;
47 uint32_t st_blksize;
48 os_time_t st_atime;
49 os_time_t st_ctime;
50 os_time_t st_mtime;
51 uint8_t st_uid;
52 uint8_t st_gid;
53 uint8_t st_rdev;
54 } os_stat_t;
56 typedef struct {
57 unsigned f_bsize;
58 unsigned f_frsize;
59 uint64_t f_blocks;
60 uint64_t f_bfree;
61 uint64_t f_bavail;
62 uint64_t f_files;
63 uint64_t f_ffree;
64 uint64_t f_favail;
65 unsigned long f_fsid;
66 unsigned f_flag;
67 unsigned f_namemax;
68 } os_statvfs_t;
70 typedef struct {
71 int tc_flags;
72 } os_termios_t;
74 typedef struct {
75 char sysname[65];
76 char release[65];
77 char version[65];
78 char machine[65];
79 } os_utsname_t;
81 typedef struct os2_handle *handle_t;
82 #define handle_is_valid(h) ((h) != NULL)
83 #define handle_none NULL
84 uintptr_t os_handle_to_number(handle_t h);
85 handle_t os_number_to_handle(uintptr_t n, bool sckt, ajla_error_t *err);
87 typedef char *dir_handle_t;
88 #define dir_handle_is_valid(h) ((h) != NULL)
89 #define dir_none NULL
91 typedef unsigned char sig_state_t;
92 typedef unsigned signal_seq_t;
94 #define OS_HAS_DLOPEN
95 struct dl_handle_t;
96 struct dl_handle_t *os_dlopen(const char *filename, ajla_error_t *err, char **err_msg);
97 void os_dlclose(struct dl_handle_t *dlh);
98 bool os_dlsym(struct dl_handle_t *dlh, const char *symbol, void **result);
100 #define os_getaddrinfo_is_thread_safe() false
102 ULONG APIENTRY os2_exception_handler(PEXCEPTIONREPORTRECORD, struct _EXCEPTIONREGISTRATIONRECORD *, PCONTEXTRECORD, PVOID);
104 #elif defined(OS_WIN32)
106 #include <sys/stat.h>
107 #include <fcntl.h>
109 #define NO_DIR_HANDLES
111 typedef int64_t os_off_t;
112 typedef int64_t os_time_t;
114 typedef struct {
115 uint32_t st_mode;
116 uint32_t st_dev;
117 uint64_t st_ino;
118 uint32_t st_nlink;
119 os_off_t st_size;
120 os_off_t st_blocks;
121 uint32_t st_blksize;
122 os_time_t st_atime;
123 os_time_t st_ctime;
124 os_time_t st_mtime;
125 uint8_t st_uid;
126 uint8_t st_gid;
127 uint8_t st_rdev;
128 } os_stat_t;
130 typedef struct {
131 unsigned f_bsize;
132 unsigned f_frsize;
133 uint64_t f_blocks;
134 uint64_t f_bfree;
135 uint64_t f_bavail;
136 uint64_t f_files;
137 uint64_t f_ffree;
138 uint64_t f_favail;
139 unsigned long f_fsid;
140 unsigned f_flag;
141 unsigned f_namemax;
142 } os_statvfs_t;
144 typedef struct {
145 int tc_flags;
146 } os_termios_t;
148 typedef struct {
149 char sysname[65];
150 char release[65];
151 char version[129];
152 char machine[65];
153 } os_utsname_t;
155 typedef struct win32_handle *handle_t;
156 #define handle_is_valid(h) ((h) != NULL)
157 #define handle_none NULL
158 uintptr_t os_handle_to_number(handle_t h);
159 handle_t os_number_to_handle(uintptr_t n, bool sckt, ajla_error_t *err);
161 typedef char *dir_handle_t;
162 #define dir_handle_is_valid(h) ((h) != NULL)
163 #define dir_none NULL
165 typedef unsigned char sig_state_t;
166 typedef uint64_t signal_seq_t;
168 #ifndef O_NONBLOCK
169 #define O_NONBLOCK 0x40000000
170 #endif
172 #ifdef _MSC_VER
173 #undef S_IFIFO
174 #undef S_IFCHR
175 #undef S_IFDIR
176 #undef S_IFBLK
177 #undef S_IFREG
178 #undef S_IFLNK
179 #undef S_IFSOCK
180 #undef S_IFMT
181 #define S_IFIFO 0010000
182 #define S_IFCHR 0020000
183 #define S_IFDIR 0040000
184 #define S_IFBLK 0060000
185 #define S_IFREG 0100000
186 #define S_IFLNK 0120000
187 #define S_IFSOCK 0140000
188 #define S_IFMT 0170000
189 #define S_ISFIFO(x) (((x) & S_IFMT) == S_IFIFO)
190 #define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
191 #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
192 #define S_ISBLK(x) (((x) & S_IFMT) == S_IFBLK)
193 #define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
194 #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
195 #define S_ISSOCK(x) (((x) & S_IFMT) == S_IFSOCK)
196 #endif
198 #define OS_HAS_MMAP
199 int os_getpagesize(void);
200 void *os_mmap(void *ptr, size_t size, int prot, int flags, handle_t h, os_off_t off, ajla_error_t *err);
201 void os_munmap(void *ptr, size_t size, bool file);
202 bool os_mprotect(void *ptr, size_t size, int prot, ajla_error_t *err);
203 #define MAP_FAILED ((void *)-1)
204 #define PROT_NONE 0
205 #define PROT_READ 1
206 #define PROT_WRITE 2
207 #define PROT_EXEC 4
208 #define MAP_ANONYMOUS 1
209 #define MAP_PRIVATE 2
210 #define MAP_FIXED 4
211 #define MAP_EXCL 8
212 #define MAP_NORESERVE 16
213 #define MAP_ALIGNED(x) (32 * (x))
214 #define MAP_ALIGNED_BITS(m) ((m) >> 5)
216 #define OS_HAS_DLOPEN
217 struct dl_handle_t;
218 struct dl_handle_t *os_dlopen(const char *filename, ajla_error_t *err, char **err_msg);
219 void os_dlclose(struct dl_handle_t *dlh);
220 bool os_dlsym(struct dl_handle_t *dlh, const char *symbol, void **result);
222 bool os_getaddrinfo_is_thread_safe(void);
224 void os_get_environment(char **str, size_t *l);
226 #else
228 #ifdef HAVE_SYS_TIME_H
229 #include <sys/time.h>
230 #endif
231 #ifdef HAVE_SIGNAL_H
232 #include <signal.h>
233 #endif
234 #ifdef HAVE_UCONTEXT_H
235 #include <ucontext.h>
236 #endif
237 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
238 #include <sys/utsname.h>
239 #endif
240 #include <sys/stat.h>
241 #ifdef HAVE_SYS_STATVFS_H
242 #include <sys/statvfs.h>
243 #elif defined(HAVE_SYS_VFS_H)
244 #include <sys/vfs.h>
245 #endif
246 #include <termios.h>
247 #include <fcntl.h>
249 #if !defined(HAVE_FCHDIR) || defined(OS_DOS) || defined(OS_CYGWIN) || defined(UNUSUAL_NO_DIR_HANDLES)
250 #define NO_DIR_HANDLES
251 #endif
253 #if defined(__hpux) && !defined(__LP64__)
254 #if defined(HAVE_FSTAT64) && defined(HAVE_FSTATVFS64) && defined(HAVE_FTRUNCATE64) && defined(HAVE_LSEEK64) && defined(HAVE_LSTAT64) && defined(HAVE_MMAP64) && defined(HAVE_OPEN64) && defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) && defined(HAVE_STAT64) && defined(HAVE_STATVFS64) && defined(HAVE_TRUNCATE64)
255 #define OS_USE_LARGEFILE64_SOURCE
256 #endif
257 #endif
259 #ifdef OS_USE_LARGEFILE64_SOURCE
260 typedef off64_t os_off_t;
261 typedef struct stat64 os_stat_t;
262 typedef struct statvfs64 os_statvfs_t;
263 #else
264 typedef off_t os_off_t;
265 typedef struct stat os_stat_t;
266 #if defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)
267 typedef struct statvfs os_statvfs_t;
268 #endif
269 #endif
271 #if !defined(OS_USE_LARGEFILE64_SOURCE) && !defined(HAVE_STATVFS) && !defined(HAVE_FSTATVFS)
272 typedef struct {
273 unsigned f_bsize;
274 unsigned f_frsize;
275 uint64_t f_blocks;
276 uint64_t f_bfree;
277 uint64_t f_bavail;
278 uint64_t f_files;
279 uint64_t f_ffree;
280 uint64_t f_favail;
281 unsigned long f_fsid;
282 unsigned f_flag;
283 unsigned f_namemax;
284 } os_statvfs_t;
285 #endif
287 typedef time_t os_time_t;
288 typedef struct termios os_termios_t;
290 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
291 typedef struct utsname os_utsname_t;
292 #else
293 typedef struct {
294 char sysname[65];
295 char release[65];
296 char version[65];
297 char machine[65];
298 } os_utsname_t;
299 #endif
301 typedef int handle_t;
302 #define handle_is_valid(h) ((h) >= 0)
303 #define handle_none -1
304 #define os_handle_to_number(h) ((uintptr_t)(h))
305 handle_t os_number_to_handle(uintptr_t n, bool sckt, ajla_error_t *err);
307 #ifndef NO_DIR_HANDLES
308 typedef int dir_handle_t;
309 #define dir_handle_is_valid(h) ((h) >= 0)
310 #define dir_none (-1)
311 #else
312 typedef char *dir_handle_t;
313 #define dir_handle_is_valid(h) ((h) != NULL)
314 #define dir_none NULL
315 #endif
317 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
318 #include <sys/mman.h>
319 #define OS_HAS_MMAP
320 int os_getpagesize(void);
321 void *os_mmap(void *ptr, size_t size, int prot, int flags, handle_t h, os_off_t off, ajla_error_t *err);
322 void os_munmap(void *ptr, size_t size, bool file);
323 bool os_mprotect(void *ptr, size_t size, int prot, ajla_error_t *err);
324 #ifndef MAP_FAILED
325 #define MAP_FAILED ((void *)-1)
326 #endif
327 #ifndef MAP_ANONYMOUS
328 #define MAP_ANONYMOUS MAP_ANON
329 #endif
330 #ifndef MAP_NORESERVE
331 #define MAP_NORESERVE 0
332 #endif
333 #if defined(__linux__) && defined(HAVE_MREMAP)
334 #define OS_HAS_MREMAP
335 void *os_mremap(void *old_ptr, size_t old_size, size_t new_size, int flags, void *new_ptr, ajla_error_t *err);
336 #endif
337 #endif
339 #if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) && defined(HAVE_SIGFILLSET)
340 typedef sigset_t sig_state_t;
341 #define USE_SIGPROCMASK
342 #else
343 typedef int sig_state_t;
344 #endif
345 typedef sig_atomic_t signal_seq_t;
346 #ifdef HAVE_SIGACTION
347 #define OS_HAS_SIGNALS
348 #endif
350 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO) && defined(HAVE_UCONTEXT_H)
351 #define OS_SUPPORTS_TRAPS (!dll)
352 #else
353 #define OS_SUPPORTS_TRAPS 0
354 #endif
356 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
357 #define OS_HAS_DLOPEN
358 struct dl_handle_t;
359 struct dl_handle_t *os_dlopen(const char *filename, ajla_error_t *err, char **err_msg);
360 void os_dlclose(struct dl_handle_t *dlh);
361 bool os_dlsym(struct dl_handle_t *dlh, const char *symbol, void **result);
362 #endif
364 #if defined(HAVE_GETADDRINFO) && (defined(HAVE_HAVE_GETNAMEINFO) || !defined(HAVE_GETHOSTBYADDR))
365 #define os_getaddrinfo_is_thread_safe() true
366 #else
367 #define os_getaddrinfo_is_thread_safe() false
368 #endif
370 #endif
373 uint32_t os_get_last_error(void);
374 uint32_t os_get_last_socket_error(void);
377 void os_code_invalidate_cache(uint8_t *code, size_t code_size, bool set_exec);
378 void *os_code_map(uint8_t *code, size_t code_size, ajla_error_t *err);
379 void os_code_unmap(void *mapped_code, size_t code_size);
382 static inline char os_path_separator(void)
384 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
385 return '\\';
386 #else
387 return '/';
388 #endif
391 static inline bool os_is_path_separator(char c)
393 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32) || defined(OS_CYGWIN)
394 if (c == '\\' || c == ':')
395 return true;
396 #endif
397 return c == '/';
400 static inline bool os_is_env_separator(char c)
402 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
403 return c == ';';
404 #endif
405 return c == ':';
408 bool os_path_is_absolute(const char *path);
411 extern dir_handle_t os_cwd;
412 bool os_set_cwd(dir_handle_t h, ajla_error_t *err);
413 void os_set_original_cwd(void);
416 void os_block_signals(sig_state_t *set);
417 void os_unblock_signals(const sig_state_t *set);
418 void os_stop(void);
419 void os_background(void);
420 bool os_foreground(void);
422 void os_set_cloexec(handle_t h);
423 handle_t os_open(dir_handle_t dir, const char *path, int flags, int mode, ajla_error_t *err);
424 bool os_pipe(handle_t result[2], int nonblock_flags, ajla_error_t *err);
425 void os_close_handle(handle_t h);
426 void os_close(handle_t h);
427 unsigned os_n_std_handles(void);
428 handle_t os_get_std_handle(unsigned p);
429 #define OS_RW_ERROR -1
430 #define OS_RW_WOULDBLOCK -2
431 ssize_t os_read(handle_t h, char *buffer, int size, ajla_error_t *err);
432 ssize_t os_write(handle_t h, const char *buffer, int size, ajla_error_t *err);
433 ssize_t os_pread(handle_t h, char *buffer, int size, os_off_t off, ajla_error_t *err);
434 ssize_t os_pwrite(handle_t h, const char *buffer, int size, os_off_t off, ajla_error_t *err);
435 bool os_lseek(handle_t, unsigned mode, os_off_t off, os_off_t *result, ajla_error_t *err);
436 bool os_ftruncate(handle_t h, os_off_t size, ajla_error_t *err);
437 bool os_fallocate(handle_t h, os_off_t position, os_off_t size, ajla_error_t *err);
438 bool os_clone_range(handle_t src_h, os_off_t src_pos, handle_t dst_h, os_off_t dst_pos, os_off_t len, ajla_error_t *err);
439 bool os_fsync(handle_t h, unsigned mode, ajla_error_t *err);
440 int os_charset(void);
441 int os_charset_console(void);
442 struct console_read_packet {
443 int32_t type;
444 union {
445 struct {
446 int32_t vkey;
447 int32_t key;
448 int32_t ctrl;
449 int32_t cp;
450 } k;
451 struct {
452 int32_t x, y;
453 int32_t prev_buttons, buttons;
454 int32_t wx, wy;
455 int32_t soft_cursor;
456 } m;
457 } u;
459 #define CONSOLE_PACKET_ENTRIES (sizeof(struct console_read_packet) / sizeof(int32_t))
460 ssize_t os_read_console_packet(handle_t h, struct console_read_packet *result, ajla_error_t *err);
461 struct console_write_packet {
462 int32_t type;
463 union {
464 struct {
465 int32_t x, y;
466 int32_t n_chars;
467 int32_t data[FLEXIBLE_ARRAY_GCC];
468 } c;
469 struct {
470 int32_t x, y;
471 int32_t end;
472 } p;
473 struct {
474 int32_t v;
475 int32_t end;
476 } v;
477 } u;
479 bool os_write_console_packet(handle_t h, struct console_write_packet *packet, ajla_error_t *err);
481 dir_handle_t os_dir_root(ajla_error_t *err);
482 dir_handle_t os_dir_cwd(ajla_error_t *err);
483 dir_handle_t os_dir_open(dir_handle_t dir, const char *path, int flags, ajla_error_t *err);
484 void os_dir_close(dir_handle_t h);
485 char *os_dir_path(dir_handle_t h, ajla_error_t *err);
487 bool os_dir_read(dir_handle_t h, char ***files, size_t *n_files, ajla_error_t *err);
488 void os_dir_free(char **files, size_t n_files);
490 unsigned os_dev_t_major(dev_t dev);
491 unsigned os_dev_t_minor(dev_t dev);
492 bool os_fstat(handle_t h, os_stat_t *st, ajla_error_t *err);
493 bool os_stat(dir_handle_t dir, const char *path, bool lnk, os_stat_t *st, ajla_error_t *err);
494 char *os_readlink(dir_handle_t dir, const char *path, ajla_error_t *err);
495 bool os_fstatvfs(handle_t h, os_statvfs_t *st, ajla_error_t *err);
496 bool os_dstatvfs(dir_handle_t dir, os_statvfs_t *st, ajla_error_t *err);
497 bool os_dir_action(dir_handle_t dir, const char *path, int action, int mode, ajla_time_t major, ajla_time_t minor, const char *syml, ajla_error_t *err);
498 bool os_dir2_action(dir_handle_t dir, const char *path, int action, dir_handle_t src_dir, const char *src_path, ajla_error_t *err);
499 bool os_drives(char **drives, size_t *drives_l, ajla_error_t *err);
501 bool os_tcgetattr(handle_t h, os_termios_t *t, ajla_error_t *err);
502 bool os_tcsetattr(handle_t h, const os_termios_t *t, ajla_error_t *err);
503 void os_tcflags(os_termios_t *t, int flags);
504 bool os_tty_size(handle_t h, int *nx, int *ny, int *ox, int *oy, ajla_error_t *err);
505 const char *os_get_path_to_exe(void);
507 ajla_time_t os_time_t_to_ajla_time(os_time_t sec);
508 #ifdef HAVE_STRUCT_TIMESPEC
509 ajla_time_t os_timespec_to_ajla_time(const struct timespec *ts);
510 #endif
511 ajla_time_t os_time_real(void);
512 ajla_time_t os_time_monotonic(void);
513 bool os_time_to_calendar(ajla_time_t t, bool local, int *year, int *month, int *day, int *hour, int *min, int *sec, int *usec, int *yday, int *wday, int *is_dst, ajla_error_t *err);
514 bool os_calendar_to_time(bool local, int year, int month, int day, int hour, int min, int sec, int usec, int is_dst, ajla_time_t *t, ajla_error_t *err);
516 const char *os_get_flavor(void);
517 void os_get_uname(os_utsname_t *un);
518 bool os_kernel_version(const char *sys, const char *vers);
519 char *os_get_host_name(ajla_error_t *err);
521 struct proc_handle;
523 struct proc_handle *os_proc_spawn(dir_handle_t wd, const char *path, size_t n_handles, handle_t *src, int *target, char * const args[], char *envc, ajla_error_t *err);
524 void os_proc_free_handle(struct proc_handle *ph);
525 bool os_proc_register_wait(struct proc_handle *ph, mutex_t **mutex_to_lock, struct list *list_entry, int *status);
526 void os_proc_check_all(void);
528 int os_signal_handle(const char *str, signal_seq_t *seq, ajla_error_t *err);
529 void os_signal_unhandle(int sig);
530 signal_seq_t os_signal_seq(int sig);
531 bool os_signal_wait(int sig, signal_seq_t seq, mutex_t **mutex_to_lock, struct list *list_entry);
532 void os_signal_check_all(void);
533 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO)
534 void os_signal_trap(int sig, void (*handler)(int, siginfo_t *, void *));
535 void os_signal_untrap(int sig);
536 #endif
538 handle_t os_socket(int domain, int type, int protocol, ajla_error_t *err);
539 bool os_bind_connect(bool bnd, handle_t h, unsigned char *addr, size_t addr_len, ajla_error_t *err);
540 bool os_connect_completed(handle_t h, ajla_error_t *err);
541 bool os_listen(handle_t h, ajla_error_t *err);
542 int os_accept(handle_t h, handle_t *result, ajla_error_t *err);
543 bool os_getsockpeername(bool peer, handle_t h, unsigned char **addr, size_t *addr_len, ajla_error_t *err);
544 struct address {
545 unsigned char *address;
546 size_t address_length;
547 struct tree_entry entry;
549 ssize_t os_recvfrom(handle_t h, char *buffer, size_t len, int flags, unsigned char **addr, size_t *addr_len, ajla_error_t *err);
550 ssize_t os_sendto(handle_t h, const char *buffer, size_t len, int flags, unsigned char *addr, size_t addr_len, ajla_error_t *err);
551 bool os_getsockopt(handle_t h, int level, int option, char **buffer, size_t *buffer_len, ajla_error_t *err);
552 bool os_setsockopt(handle_t h, int level, int option, const char *buffer, size_t buffer_len, ajla_error_t *err);
553 bool os_getaddrinfo(const char *host, int port, struct address **result, size_t *result_l, ajla_error_t *err);
554 char *os_getnameinfo(unsigned char *addr, size_t addr_len, ajla_error_t *err);
556 const char *os_decode_error(ajla_error_t error, char *(*tls_buffer)(void));
558 #if !defined(OS_DOS)
559 #define OS_HAVE_NOTIFY_PIPE
560 extern handle_t os_notify_pipe[2];
561 void os_notify(void);
562 bool os_drain_notify_pipe(void);
563 void os_shutdown_notify_pipe(void);
564 #else
565 static inline void os_notify(void) { }
566 static inline void os_shutdown_notify_pipe(void) { }
567 #endif
569 #if defined(OS_DOS)
570 bool dos_poll_devices(void);
571 void dos_yield(void);
572 void dos_wait_on_packet(mutex_t **mutex_to_lock, struct list *list_entry);
573 void dos_init(void);
574 void dos_done(void);
575 #endif
577 void os_init(void);
578 void os_init_multithreaded(void);
579 void os_done_multithreaded(void);
580 void os_done(void);
582 #endif