aboutsummaryrefslogtreecommitdiff
path: root/core/os/errors.odin
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2026-02-09 15:50:21 +0100
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2026-02-09 15:50:21 +0100
commite7dbabf6681e4e6bcae33398e939c2c9c3cdc879 (patch)
tree91f25462cc2e9f3adf9884720b7f104d4d6d59f5 /core/os/errors.odin
parent8ed264680b1f3f94b6aa5176824d4ccadfc30322 (diff)
core:os -> core:os/old && core:os/os2 -> core:os
Diffstat (limited to 'core/os/errors.odin')
-rw-r--r--core/os/errors.odin257
1 files changed, 43 insertions, 214 deletions
diff --git a/core/os/errors.odin b/core/os/errors.odin
index fcf70ec74..508d824b3 100644
--- a/core/os/errors.odin
+++ b/core/os/errors.odin
@@ -1,13 +1,12 @@
-package os
+package os2
-import "base:intrinsics"
-import "base:runtime"
import "core:io"
+import "base:runtime"
-Platform_Error :: _Platform_Error
-#assert(size_of(Platform_Error) <= 4)
-#assert(intrinsics.type_has_nil(Platform_Error))
-
+/*
+ General errors that are common within this package which cannot
+ be categorized by `io.Error` nor `runtime.Allocator_Error`.
+*/
General_Error :: enum u32 {
None,
@@ -22,39 +21,43 @@ General_Error :: enum u32 {
Invalid_Dir,
Invalid_Path,
Invalid_Callback,
+ Invalid_Command,
Pattern_Has_Separator,
+ Pattern_Syntax_Error, // Indicates an error in `glob` or `match` pattern.
- File_Is_Pipe,
- Not_Dir,
-
- // Environment variable not found.
+ No_HOME_Variable,
Env_Var_Not_Found,
}
+// A platform specific error
+Platform_Error :: _Platform_Error
-Errno :: Error // alias for legacy use
-
+/*
+ `Error` is a union of different classes of errors that could be returned from procedures in this package.
+*/
Error :: union #shared_nil {
General_Error,
io.Error,
runtime.Allocator_Error,
Platform_Error,
}
-#assert(size_of(Error) == 8)
+#assert(size_of(Error) == size_of(u64))
ERROR_NONE :: Error{}
-ERROR_EOF :: io.Error.EOF
+// Attempts to convert an `Error` into a platform specific error as an integer. `ok` is false if not possible
@(require_results)
-is_platform_error :: proc "contextless" (ferr: Error) -> (err: i32, ok: bool) {
+is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
v := ferr.(Platform_Error) or_else {}
return i32(v), i32(v) != 0
}
+
+// Attempts to return the error `ferr` as a string without any allocation
@(require_results)
-error_string :: proc "contextless" (ferr: Error) -> string {
+error_string :: proc(ferr: Error) -> string {
if ferr == nil {
return ""
}
@@ -62,18 +65,19 @@ error_string :: proc "contextless" (ferr: Error) -> string {
case General_Error:
switch e {
case .None: return ""
- case .Exist: return "file already exists"
- case .Not_Exist: return "file does not exist"
- case .Timeout: return "i/o timeout"
- case .Broken_Pipe: return "Broken pipe"
- case .Invalid_File: return "invalid file"
- case .Invalid_Dir: return "invalid directory"
- case .Invalid_Path: return "invalid path"
- case .Invalid_Callback: return "invalid callback"
- case .Pattern_Has_Separator: return "pattern has separator"
- case .File_Is_Pipe: return "file is pipe"
- case .Not_Dir: return "file is not directory"
- case .Env_Var_Not_Found: return "environment variable not found"
+ case .Exist: return "file already exists"
+ case .Not_Exist: return "file does not exist"
+ case .Timeout: return "i/o timeout"
+ case .Broken_Pipe: return "Broken pipe"
+ case .Invalid_File: return "invalid file"
+ case .Invalid_Dir: return "invalid directory"
+ case .Invalid_Path: return "invalid path"
+ case .Invalid_Callback: return "invalid callback"
+ case .Invalid_Command: return "invalid command"
+ case .Pattern_Has_Separator: return "pattern has separator"
+ case .Pattern_Syntax_Error: return "glob pattern syntax error"
+ case .No_HOME_Variable: return "no $HOME variable"
+ case .Env_Var_Not_Found: return "environment variable not found"
}
case io.Error:
switch e {
@@ -106,210 +110,35 @@ error_string :: proc "contextless" (ferr: Error) -> string {
case .Mode_Not_Implemented: return "allocator mode not implemented"
}
case Platform_Error:
- return _error_string(e)
+ return _error_string(i32(e))
}
return "unknown error"
}
-print_error :: proc(f: Handle, ferr: Error, msg: string) -> (n: int, err: Error) {
+/*
+ `print_error` is a utility procedure which will print an error `ferr` to a specified file `f`.
+*/
+print_error :: proc(f: ^File, ferr: Error, msg: string) {
+ temp_allocator := TEMP_ALLOCATOR_GUARD({})
err_str := error_string(ferr)
// msg + ": " + err_str + '\n'
length := len(msg) + 2 + len(err_str) + 1
- buf_ := intrinsics.alloca(length, 1)
- buf := buf_[:length]
+ buf := make([]u8, length, temp_allocator)
copy(buf, msg)
buf[len(msg)] = ':'
buf[len(msg) + 1] = ' '
copy(buf[len(msg) + 2:], err_str)
buf[length - 1] = '\n'
- return write(f, buf)
+ write(f, buf)
}
-@(require_results, private)
-_error_string :: proc "contextless" (e: Platform_Error) -> string where intrinsics.type_is_enum(Platform_Error) {
- if e == nil {
- return ""
- }
-
- when ODIN_OS == .Darwin {
- if s := string(_darwin_string_error(i32(e))); s != "" {
- return s
- }
- }
-
- when ODIN_OS != .Linux {
- @(require_results)
- binary_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) #no_bounds_check {
- n := len(array)
- left, right := 0, n
- for left < right {
- mid := int(uint(left+right) >> 1)
- if array[mid] < key {
- left = mid+1
- } else {
- // equal or greater
- right = mid
- }
- }
- return left, left < n && array[left] == key
- }
-
- err := runtime.Type_Info_Enum_Value(e)
-
- ti := &runtime.type_info_base(type_info_of(Platform_Error)).variant.(runtime.Type_Info_Enum)
- if idx, ok := binary_search(ti.values, err); ok {
- return ti.names[idx]
- }
- } else {
- @(rodata, static)
- pe_strings := [Platform_Error]string{
- .NONE = "",
- .EPERM = "Operation not permitted",
- .ENOENT = "No such file or directory",
- .ESRCH = "No such process",
- .EINTR = "Interrupted system call",
- .EIO = "Input/output error",
- .ENXIO = "No such device or address",
- .E2BIG = "Argument list too long",
- .ENOEXEC = "Exec format error",
- .EBADF = "Bad file descriptor",
- .ECHILD = "No child processes",
- .EAGAIN = "Resource temporarily unavailable",
- .ENOMEM = "Cannot allocate memory",
- .EACCES = "Permission denied",
- .EFAULT = "Bad address",
- .ENOTBLK = "Block device required",
- .EBUSY = "Device or resource busy",
- .EEXIST = "File exists",
- .EXDEV = "Invalid cross-device link",
- .ENODEV = "No such device",
- .ENOTDIR = "Not a directory",
- .EISDIR = "Is a directory",
- .EINVAL = "Invalid argument",
- .ENFILE = "Too many open files in system",
- .EMFILE = "Too many open files",
- .ENOTTY = "Inappropriate ioctl for device",
- .ETXTBSY = "Text file busy",
- .EFBIG = "File too large",
- .ENOSPC = "No space left on device",
- .ESPIPE = "Illegal seek",
- .EROFS = "Read-only file system",
- .EMLINK = "Too many links",
- .EPIPE = "Broken pipe",
- .EDOM = "Numerical argument out of domain",
- .ERANGE = "Numerical result out of range",
- .EDEADLK = "Resource deadlock avoided",
- .ENAMETOOLONG = "File name too long",
- .ENOLCK = "No locks available",
- .ENOSYS = "Function not implemented",
- .ENOTEMPTY = "Directory not empty",
- .ELOOP = "Too many levels of symbolic links",
- .EUNKNOWN_41 = "Unknown Error (41)",
- .ENOMSG = "No message of desired type",
- .EIDRM = "Identifier removed",
- .ECHRNG = "Channel number out of range",
- .EL2NSYNC = "Level 2 not synchronized",
- .EL3HLT = "Level 3 halted",
- .EL3RST = "Level 3 reset",
- .ELNRNG = "Link number out of range",
- .EUNATCH = "Protocol driver not attached",
- .ENOCSI = "No CSI structure available",
- .EL2HLT = "Level 2 halted",
- .EBADE = "Invalid exchange",
- .EBADR = "Invalid request descriptor",
- .EXFULL = "Exchange full",
- .ENOANO = "No anode",
- .EBADRQC = "Invalid request code",
- .EBADSLT = "Invalid slot",
- .EUNKNOWN_58 = "Unknown Error (58)",
- .EBFONT = "Bad font file format",
- .ENOSTR = "Device not a stream",
- .ENODATA = "No data available",
- .ETIME = "Timer expired",
- .ENOSR = "Out of streams resources",
- .ENONET = "Machine is not on the network",
- .ENOPKG = "Package not installed",
- .EREMOTE = "Object is remote",
- .ENOLINK = "Link has been severed",
- .EADV = "Advertise error",
- .ESRMNT = "Srmount error",
- .ECOMM = "Communication error on send",
- .EPROTO = "Protocol error",
- .EMULTIHOP = "Multihop attempted",
- .EDOTDOT = "RFS specific error",
- .EBADMSG = "Bad message",
- .EOVERFLOW = "Value too large for defined data type",
- .ENOTUNIQ = "Name not unique on network",
- .EBADFD = "File descriptor in bad state",
- .EREMCHG = "Remote address changed",
- .ELIBACC = "Can not access a needed shared library",
- .ELIBBAD = "Accessing a corrupted shared library",
- .ELIBSCN = ".lib section in a.out corrupted",
- .ELIBMAX = "Attempting to link in too many shared libraries",
- .ELIBEXEC = "Cannot exec a shared library directly",
- .EILSEQ = "Invalid or incomplete multibyte or wide character",
- .ERESTART = "Interrupted system call should be restarted",
- .ESTRPIPE = "Streams pipe error",
- .EUSERS = "Too many users",
- .ENOTSOCK = "Socket operation on non-socket",
- .EDESTADDRREQ = "Destination address required",
- .EMSGSIZE = "Message too long",
- .EPROTOTYPE = "Protocol wrong type for socket",
- .ENOPROTOOPT = "Protocol not available",
- .EPROTONOSUPPORT = "Protocol not supported",
- .ESOCKTNOSUPPORT = "Socket type not supported",
- .EOPNOTSUPP = "Operation not supported",
- .EPFNOSUPPORT = "Protocol family not supported",
- .EAFNOSUPPORT = "Address family not supported by protocol",
- .EADDRINUSE = "Address already in use",
- .EADDRNOTAVAIL = "Cannot assign requested address",
- .ENETDOWN = "Network is down",
- .ENETUNREACH = "Network is unreachable",
- .ENETRESET = "Network dropped connection on reset",
- .ECONNABORTED = "Software caused connection abort",
- .ECONNRESET = "Connection reset by peer",
- .ENOBUFS = "No buffer space available",
- .EISCONN = "Transport endpoint is already connected",
- .ENOTCONN = "Transport endpoint is not connected",
- .ESHUTDOWN = "Cannot send after transport endpoint shutdown",
- .ETOOMANYREFS = "Too many references: cannot splice",
- .ETIMEDOUT = "Connection timed out",
- .ECONNREFUSED = "Connection refused",
- .EHOSTDOWN = "Host is down",
- .EHOSTUNREACH = "No route to host",
- .EALREADY = "Operation already in progress",
- .EINPROGRESS = "Operation now in progress",
- .ESTALE = "Stale file handle",
- .EUCLEAN = "Structure needs cleaning",
- .ENOTNAM = "Not a XENIX named type file",
- .ENAVAIL = "No XENIX semaphores available",
- .EISNAM = "Is a named type file",
- .EREMOTEIO = "Remote I/O error",
- .EDQUOT = "Disk quota exceeded",
- .ENOMEDIUM = "No medium found",
- .EMEDIUMTYPE = "Wrong medium type",
- .ECANCELED = "Operation canceled",
- .ENOKEY = "Required key not available",
- .EKEYEXPIRED = "Key has expired",
- .EKEYREVOKED = "Key has been revoked",
- .EKEYREJECTED = "Key was rejected by service",
- .EOWNERDEAD = "Owner died",
- .ENOTRECOVERABLE = "State not recoverable",
- .ERFKILL = "Operation not possible due to RF-kill",
- .EHWPOISON = "Memory page has hardware error",
- }
- if Platform_Error.NONE <= e && e <= max(Platform_Error) {
- return pe_strings[e]
- }
- }
- return "<unknown platform error>"
-}
-@(private, require_results)
+// Attempts to convert an `Error` `ferr` into an `io.Error`
+@(private)
error_to_io_error :: proc(ferr: Error) -> io.Error {
if ferr == nil {
return .None