diff --git a/.gitattributes b/.gitattributes index 6e3cae0f5..0178b8a8f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ *.odin linguist-language=Odin +* text=auto \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aacaf427d..fda99edfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -163,7 +163,7 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat cd tests\documentation - call build.bat + rem call build.bat timeout-minutes: 10 - name: core:math/big tests shell: cmd diff --git a/.gitignore b/.gitignore index 59b5adb6d..83f64f145 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,31 @@ bld/ tests/documentation/verify/ tests/documentation/all.odin-doc tests/internal/test_map +tests/internal/test_pow tests/internal/test_rtti +tests/core/test_core_compress +tests/core/test_core_filepath +tests/core/test_core_fmt +tests/core/test_core_i18n +tests/core/test_core_image +tests/core/test_core_libc +tests/core/test_core_match +tests/core/test_core_math +tests/core/test_core_net +tests/core/test_core_os_exit +tests/core/test_core_reflect +tests/core/test_core_strings +tests/core/test_crypto_hash +tests/core/test_hash +tests/core/test_hxa +tests/core/test_json +tests/core/test_linalg_glsl_math +tests/core/test_noise +tests/core/test_varint +tests/core/test_xml +tests/core/test_core_slice +tests/core/test_core_thread +tests/vendor/vendor_botan # Visual Studio 2015 cache/options directory .vs/ # Visual Studio Code options directory @@ -290,3 +314,6 @@ shared/ examples/bug/ build.sh !core/debug/ + +# RAD debugger project file +*.raddbg \ No newline at end of file diff --git a/bin/lld-link.exe b/bin/lld-link.exe new file mode 100644 index 000000000..da6527264 Binary files /dev/null and b/bin/lld-link.exe differ diff --git a/bin/wasm-ld.exe b/bin/wasm-ld.exe new file mode 100644 index 000000000..da6527264 Binary files /dev/null and b/bin/wasm-ld.exe differ diff --git a/build.bat b/build.bat index b0ebfe634..050789bbc 100644 --- a/build.bat +++ b/build.bat @@ -110,7 +110,8 @@ if %errorlevel% neq 0 goto end_of_build call build_vendor.bat if %errorlevel% neq 0 goto end_of_build -if %release_mode% EQU 0 odin run examples/demo +rem If the demo doesn't run for you and your CPU is more than a decade old, try -microarch:native +if %release_mode% EQU 0 odin run examples/demo -- Hellope World del *.obj > NUL 2> NUL diff --git a/build_odin.sh b/build_odin.sh index 2a2505c97..589aeb550 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -27,11 +27,13 @@ error() { if [ -z "$LLVM_CONFIG" ]; then # darwin, linux, openbsd if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17" + elif [ -n "$(command -v llvm-config-14)" ]; then LLVM_CONFIG="llvm-config-14" elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13" elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12" elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11" # freebsd elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17" + elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config-14" elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config-13" elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config-12" elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config-11" @@ -117,7 +119,7 @@ build_odin() { } run_demo() { - ./odin run examples/demo/demo.odin -file + ./odin run examples/demo/demo.odin -file -- Hellope World } if [ $# -eq 0 ]; then diff --git a/core/builtin/builtin.odin b/core/builtin/builtin.odin index 211db9770..5cba3c8ea 100644 --- a/core/builtin/builtin.odin +++ b/core/builtin/builtin.odin @@ -110,7 +110,7 @@ typeid_of :: proc($T: typeid) -> typeid --- swizzle :: proc(x: [N]T, indices: ..int) -> [len(indices)]T --- complex :: proc(real, imag: Float) -> Complex_Type --- -quaternion :: proc(real, imag, jmag, kmag: Float) -> Quaternion_Type --- +quaternion :: proc(imag, jmag, kmag, real: Float) -> Quaternion_Type --- // fields must be named real :: proc(value: Complex_Or_Quaternion) -> Float --- imag :: proc(value: Complex_Or_Quaternion) -> Float --- jmag :: proc(value: Quaternion) -> Float --- diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin index d39f01b06..208949fd8 100644 --- a/core/bytes/bytes.odin +++ b/core/bytes/bytes.odin @@ -895,7 +895,7 @@ split_multi_iterator :: proc(s: ^[]byte, substrs: [][]byte, skip_empty := false) -// scrub scruvs invalid utf-8 characters and replaces them with the replacement string +// Scrubs invalid utf-8 characters and replaces them with the replacement string // Adjacent invalid bytes are only replaced once scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator) -> []byte { str := s diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index 94007595c..39969e4a8 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -1,5 +1,7 @@ package libc +import "core:io" + when ODIN_OS == .Windows { foreign import libc { "system:libucrt.lib", @@ -218,3 +220,102 @@ foreign libc { ferror :: proc(stream: ^FILE) -> int --- perror :: proc(s: cstring) --- } + +to_stream :: proc(file: ^FILE) -> io.Stream { + stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { + unknown_or_eof :: proc(f: ^FILE) -> io.Error { + switch { + case ferror(f) != 0: + return .Unknown + case feof(f) != 0: + return .EOF + case: + return nil + } + } + + file := (^FILE)(stream_data) + switch mode { + case .Close: + if fclose(file) != 0 { + return 0, unknown_or_eof(file) + } + + case .Flush: + if fflush(file) != 0 { + return 0, unknown_or_eof(file) + } + + case .Read: + n = i64(fread(raw_data(p), size_of(byte), len(p), file)) + if n == 0 { err = unknown_or_eof(file) } + + case .Read_At: + curr := ftell(file) + if curr == -1 { + return 0, unknown_or_eof(file) + } + + if fseek(file, long(offset), SEEK_SET) != 0 { + return 0, unknown_or_eof(file) + } + + defer fseek(file, long(curr), SEEK_SET) + + n = i64(fread(raw_data(p), size_of(byte), len(p), file)) + if n == 0 { err = unknown_or_eof(file) } + + case .Write: + n = i64(fwrite(raw_data(p), size_of(byte), len(p), file)) + if n == 0 { err = unknown_or_eof(file) } + + case .Write_At: + curr := ftell(file) + if curr == -1 { + return 0, unknown_or_eof(file) + } + + if fseek(file, long(offset), SEEK_SET) != 0 { + return 0, unknown_or_eof(file) + } + + defer fseek(file, long(curr), SEEK_SET) + + n = i64(fwrite(raw_data(p), size_of(byte), len(p), file)) + if n == 0 { err = unknown_or_eof(file) } + + case .Seek: + if fseek(file, long(offset), int(whence)) != 0 { + return 0, unknown_or_eof(file) + } + + case .Size: + curr := ftell(file) + if curr == -1 { + return 0, unknown_or_eof(file) + } + defer fseek(file, curr, SEEK_SET) + + if fseek(file, 0, SEEK_END) != 0 { + return 0, unknown_or_eof(file) + } + + n = i64(ftell(file)) + if n == -1 { + return 0, unknown_or_eof(file) + } + + case .Destroy: + return 0, .Empty + + case .Query: + return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size }) + } + return + } + + return { + data = file, + procedure = stream_proc, + } +} diff --git a/core/c/libc/types.odin b/core/c/libc/types.odin index a49e52fb6..cc844c1c5 100644 --- a/core/c/libc/types.odin +++ b/core/c/libc/types.odin @@ -2,6 +2,8 @@ package libc import "core:c" +#assert(!ODIN_NO_CRT, `"core:c/libc" cannot be imported when '-no-crt' is used`) + char :: c.char // assuming -funsigned-char schar :: c.schar diff --git a/core/compress/common.odin b/core/compress/common.odin index e1cfb4cb5..b343ce493 100644 --- a/core/compress/common.odin +++ b/core/compress/common.odin @@ -20,10 +20,9 @@ import "core:runtime" */ -/* - When a decompression routine doesn't stream its output, but writes to a buffer, - we pre-allocate an output buffer to speed up decompression. The default is 1 MiB. -*/ + +// When a decompression routine doesn't stream its output, but writes to a buffer, +// we pre-allocate an output buffer to speed up decompression. The default is 1 MiB. COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 20)) /* @@ -34,16 +33,14 @@ COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 2 */ when size_of(uintptr) == 8 { - /* - For 64-bit platforms, we set the default max buffer size to 4 GiB, - which is GZIP and PKZIP's max payload size. - */ + + // For 64-bit platforms, we set the default max buffer size to 4 GiB, + // which is GZIP and PKZIP's max payload size. COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32)) } else { - /* - For 32-bit platforms, we set the default max buffer size to 512 MiB. - */ - COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29)) + + // For 32-bit platforms, we set the default max buffer size to 512 MiB. + COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29)) } @@ -69,9 +66,8 @@ General_Error :: enum { Incompatible_Options, Unimplemented, - /* - Memory errors - */ + // Memory errors + Allocation_Failed, Resize_Failed, } @@ -86,17 +82,16 @@ GZIP_Error :: enum { Payload_Length_Invalid, Payload_CRC_Invalid, - /* - GZIP's payload can be a maximum of max(u32le), or 4 GiB. - If you tell it you expect it to contain more, that's obviously an error. - */ - Payload_Size_Exceeds_Max_Payload, - /* - For buffered instead of streamed output, the payload size can't exceed - the max set by the `COMPRESS_OUTPUT_ALLOCATE_MAX` switch in compress/common.odin. + // GZIP's payload can be a maximum of max(u32le), or 4 GiB. + // If you tell it you expect it to contain more, that's obviously an error. + + Payload_Size_Exceeds_Max_Payload, + + // For buffered instead of streamed output, the payload size can't exceed + // the max set by the `COMPRESS_OUTPUT_ALLOCATE_MAX` switch in compress/common.odin. + // + // You can tweak this setting using `-define:COMPRESS_OUTPUT_ALLOCATE_MAX=size_in_bytes` - You can tweak this setting using `-define:COMPRESS_OUTPUT_ALLOCATE_MAX=size_in_bytes` - */ Output_Exceeds_COMPRESS_OUTPUT_ALLOCATE_MAX, } @@ -137,9 +132,8 @@ Context_Memory_Input :: struct #packed { code_buffer: u64, num_bits: u64, - /* - If we know the data size, we can optimize the reads and writes. - */ + // If we know the data size, we can optimize the reads and writes. + size_packed: i64, size_unpacked: i64, } @@ -159,18 +153,16 @@ Context_Stream_Input :: struct #packed { code_buffer: u64, num_bits: u64, - /* - If we know the data size, we can optimize the reads and writes. - */ + // If we know the data size, we can optimize the reads and writes. + size_packed: i64, size_unpacked: i64, - /* - Flags: - `input_fully_in_memory` - true = This tells us we read input from `input_data` exclusively. [] = EOF. - false = Try to refill `input_data` from the `input` stream. - */ + // Flags: + // `input_fully_in_memory` + // true = This tells us we read input from `input_data` exclusively. [] = EOF. + // false = Try to refill `input_data` from the `input` stream. + input_fully_in_memory: b8, padding: [1]u8, @@ -214,7 +206,7 @@ read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int @(optimization_mode="speed") read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int) -> (res: []u8, err: io.Error) { // TODO: REMOVE ALL USE OF context.temp_allocator here - // the is literally no need for it + // there is literally no need for it b := make([]u8, size, context.temp_allocator) _ = io.read(z.input, b[:]) or_return return b, nil @@ -248,10 +240,8 @@ read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, read_u8 :: proc{read_u8_from_memory, read_u8_from_stream} -/* - You would typically only use this at the end of Inflate, to drain bits from the code buffer - preferentially. -*/ +// You would typically only use this at the end of Inflate, to drain bits from the code buffer +// preferentially. @(optimization_mode="speed") read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) { if z.num_bits >= 8 { diff --git a/core/container/priority_queue/priority_queue.odin b/core/container/priority_queue/priority_queue.odin index 0c5c4931d..0c43816e1 100644 --- a/core/container/priority_queue/priority_queue.odin +++ b/core/container/priority_queue/priority_queue.odin @@ -140,3 +140,18 @@ remove :: proc(pq: ^$Q/Priority_Queue($T), i: int) -> (value: T, ok: bool) { return } +peek_safe :: proc(pq: $Q/Priority_Queue($T), loc := #caller_location) -> (res: T, ok: bool) { + if builtin.len(pq.queue) > 0 { + return pq.queue[0], true + } + return +} + +peek :: proc(pq: $Q/Priority_Queue($T), loc := #caller_location) -> (res: T) { + assert(condition=builtin.len(pq.queue)>0, loc=loc) + + if builtin.len(pq.queue) > 0 { + return pq.queue[0] + } + return +} \ No newline at end of file diff --git a/core/container/queue/queue.odin b/core/container/queue/queue.odin index 5783cbc6c..bdc61c2a6 100644 --- a/core/container/queue/queue.odin +++ b/core/container/queue/queue.odin @@ -22,7 +22,9 @@ init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := contex return reserve(q, capacity) } -// Procedure to initialize a queue from a fixed backing slice +// Procedure to initialize a queue from a fixed backing slice. +// The contents of the `backing` will be overwritten as items are pushed onto the `Queue`. +// Any previous contents are not available. init_from_slice :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { clear(q) q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ @@ -34,6 +36,21 @@ init_from_slice :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { return true } +// Procedure to initialize a queue from a fixed backing slice. +// Existing contents are preserved and available on the queue. +init_with_contents :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { + clear(q) + q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ + data = raw_data(backing), + len = builtin.len(backing), + cap = builtin.len(backing), + allocator = {procedure=runtime.nil_allocator_proc, data=nil}, + } + q.len = len(backing) + q.offset = len(backing) + return true +} + // Procedure to destroy a queue destroy :: proc(q: ^$Q/Queue($T)) { delete(q.data) diff --git a/core/crypto/README.md b/core/crypto/README.md index dd594d5c2..adb815df4 100644 --- a/core/crypto/README.md +++ b/core/crypto/README.md @@ -1,95 +1,86 @@ # crypto -A crypto library for the Odin language + +A cryptography library for the Odin language ## Supported + This library offers various algorithms implemented in Odin. -Please see the chart below for the options. +Please see the chart below for some of the options. ## Hashing algorithms + | Algorithm | | |:-------------------------------------------------------------------------------------------------------------|:-----------------| -| [BLAKE](https://web.archive.org/web/20190915215948/https://131002.net/blake) | ✔️ | | [BLAKE2B](https://datatracker.ietf.org/doc/html/rfc7693) | ✔️ | | [BLAKE2S](https://datatracker.ietf.org/doc/html/rfc7693) | ✔️ | -| [GOST](https://datatracker.ietf.org/doc/html/rfc5831) | ✔️ | -| [Grøstl](http://www.groestl.info/Groestl.zip) | ✔️ | -| [HAVAL](https://web.archive.org/web/20150111210116/http://labs.calyptix.com/haval.php) | ✔️ | -| [JH](https://www3.ntu.edu.sg/home/wuhj/research/jh/index.html) | ✔️ | -| [Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ | -| [MD2](https://datatracker.ietf.org/doc/html/rfc1319) | ✔️ | -| [MD4](https://datatracker.ietf.org/doc/html/rfc1320) | ✔️ | -| [MD5](https://datatracker.ietf.org/doc/html/rfc1321) | ✔️ | -| [RIPEMD](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html) | ✔️ | -| [SHA-1](https://datatracker.ietf.org/doc/html/rfc3174) | ✔️ | | [SHA-2](https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf) | ✔️ | | [SHA-3](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ | | [SHAKE](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ | | [SM3](https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02) | ✔️ | -| [Streebog](https://datatracker.ietf.org/doc/html/rfc6986) | ✔️ | -| [Tiger](https://www.cs.technion.ac.il/~biham/Reports/Tiger/) | ✔️ | -| [Tiger2](https://www.cs.technion.ac.il/~biham/Reports/Tiger/) | ✔️ | -| [Whirlpool](https://web.archive.org/web/20171129084214/http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html) | ✔️ | +| legacy/[Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf) | ✔️ | +| legacy/[MD5](https://datatracker.ietf.org/doc/html/rfc1321) | ✔️ | +| legacy/[SHA-1](https://datatracker.ietf.org/doc/html/rfc3174) | ✔️ | #### High level API -Each hash algorithm contains a procedure group named `hash`, or if the algorithm provides more than one digest size `hash_`\*. -Included in these groups are six procedures. -* `hash_string` - Hash a given string and return the computed hash. Just calls `hash_bytes` internally -* `hash_bytes` - Hash a given byte slice and return the computed hash -* `hash_string_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. Just calls `hash_bytes_to_buffer` internally -* `hash_bytes_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. The destination buffer has to be at least as big as the digest size of the hash -* `hash_stream` - Takes a stream from io.Stream and returns the computed hash from it -* `hash_file` - Takes a file handle and returns the computed hash from it. A second optional boolean parameter controls if the file is streamed (this is the default) or read at once (set to true) -\* On some algorithms there is another part to the name, since they might offer control about additional parameters. -For instance, `HAVAL` offers different sizes as well as three different round amounts. -Computing a 256-bit hash with 3 rounds is therefore achieved by calling `haval.hash_256_3(...)`. +Each hash algorithm contains a procedure group named `hash`, or if the algorithm provides more than one digest size `hash_`\*. +Included in these groups are six procedures. +- `hash_string` - Hash a given string and return the computed hash. Just calls `hash_bytes` internally +- `hash_bytes` - Hash a given byte slice and return the computed hash +- `hash_string_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. Just calls `hash_bytes_to_buffer` internally +- `hash_bytes_to_buffer` - Hash a given string and put the computed hash in the second proc parameter. The destination buffer has to be at least as big as the digest size of the hash +- `hash_stream` - Takes a stream from io.Stream and returns the computed hash from it +- `hash_file` - Takes a file handle and returns the computed hash from it. A second optional boolean parameter controls if the file is streamed (this is the default) or read at once (set to true) + +\* On some algorithms there is another part to the name, since they might offer control about additional parameters. +For instance, `SHA-2` offers different sizes. +Computing a 512-bit hash is therefore achieved by calling `sha2.hash_512(...)`. #### Low level API + The above mentioned procedures internally call three procedures: `init`, `update` and `final`. You may also directly call them, if you wish. #### Example + ```odin package crypto_example // Import the desired package -import "core:crypto/md4" +import "core:crypto/blake2b" main :: proc() { input := "foo" // Compute the hash, using the high level API - computed_hash := md4.hash(input) + computed_hash := blake2b.hash(input) // Variant that takes a destination buffer, instead of returning the computed hash - hash := make([]byte, md4.DIGEST_SIZE) // @note: Destination buffer has to be at least as big as the digest size of the hash - md4.hash(input, hash[:]) + hash := make([]byte, sha2.DIGEST_SIZE) // @note: Destination buffer has to be at least as big as the digest size of the hash + blake2b.hash(input, hash[:]) // Compute the hash, using the low level API - ctx: md4.Md4_Context - computed_hash_low: [16]byte - md4.init(&ctx) - md4.update(&ctx, transmute([]byte)input) - md4.final(&ctx, computed_hash_low[:]) + ctx: blake2b.Context + computed_hash_low: [blake2b.DIGEST_SIZE]byte + blake2b.init(&ctx) + blake2b.update(&ctx, transmute([]byte)input) + blake2b.final(&ctx, computed_hash_low[:]) } ``` For example uses of all available algorithms, please see the tests within `tests/core/crypto`. -#### Thread safety -The crypto package is not thread-safe at the moment. This may change in the future. +## Implementation considerations -### Disclaimer -The algorithms were ported out of curiosity and due to interest in the field. -We have not had any of the code verified by a third party or tested/fuzzed by any automatic means. -Wherever we were able to find official test vectors, those were used to verify the implementation. -We do not recommend using them in a production environment, without any additional testing and/or verification. +- The crypto packages are not thread-safe. +- Best-effort is make to mitigate timing side-channels on reasonable + architectures. Architectures that are known to be unreasonable include + but are not limited to i386, i486, and WebAssembly. +- Some but not all of the packages attempt to santize sensitive data, + however this is not done consistently through the library at the moment. + As Thomas Pornin puts it "In general, such memory cleansing is a fool's + quest." +- All of these packages have not received independent third party review. -### ToDo -* Ciphers (Symmetric, Asymmetric) -* MACs (Message Authentication Code) -* CSPRNGs (Cryptographically Secure PseudoRandom Number Generator) -* KDFs (Key Derivation Function) -* KEAs (Key Exchange Algorithm) +## License -### License This library is made available under the BSD-3 license. \ No newline at end of file diff --git a/core/crypto/_blake2/blake2.odin b/core/crypto/_blake2/blake2.odin index 7b75541e9..13b58dba9 100644 --- a/core/crypto/_blake2/blake2.odin +++ b/core/crypto/_blake2/blake2.odin @@ -10,12 +10,12 @@ package _blake2 Implementation of the BLAKE2 hashing algorithm, as defined in and */ -import "../util" +import "core:encoding/endian" -BLAKE2S_BLOCK_SIZE :: 64 -BLAKE2S_SIZE :: 32 -BLAKE2B_BLOCK_SIZE :: 128 -BLAKE2B_SIZE :: 64 +BLAKE2S_BLOCK_SIZE :: 64 +BLAKE2S_SIZE :: 32 +BLAKE2B_BLOCK_SIZE :: 128 +BLAKE2B_SIZE :: 64 Blake2s_Context :: struct { h: [8]u32, @@ -28,7 +28,9 @@ Blake2s_Context :: struct { is_keyed: bool, size: byte, is_last_node: bool, - cfg: Blake2_Config, + cfg: Blake2_Config, + + is_initialized: bool, } Blake2b_Context :: struct { @@ -42,15 +44,19 @@ Blake2b_Context :: struct { is_keyed: bool, size: byte, is_last_node: bool, - cfg: Blake2_Config, + cfg: Blake2_Config, + + is_initialized: bool, } Blake2_Config :: struct { - size: byte, - key: []byte, - salt: []byte, + size: byte, + key: []byte, + salt: []byte, person: []byte, - tree: union{Blake2_Tree}, + tree: union { + Blake2_Tree, + }, } Blake2_Tree :: struct { @@ -63,11 +69,13 @@ Blake2_Tree :: struct { is_last_node: bool, } +@(private) BLAKE2S_IV := [8]u32 { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, } +@(private) BLAKE2B_IV := [8]u64 { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, @@ -78,8 +86,14 @@ BLAKE2B_IV := [8]u64 { init :: proc(ctx: ^$T) { when T == Blake2s_Context { block_size :: BLAKE2S_BLOCK_SIZE + max_size :: BLAKE2S_SIZE } else when T == Blake2b_Context { block_size :: BLAKE2B_BLOCK_SIZE + max_size :: BLAKE2B_SIZE + } + + if ctx.cfg.size > max_size { + panic("blake2: requested output size exceeeds algorithm max") } p := make([]byte, block_size) @@ -106,10 +120,10 @@ init :: proc(ctx: ^$T) { if ctx.cfg.tree != nil { p[2] = ctx.cfg.tree.(Blake2_Tree).fanout p[3] = ctx.cfg.tree.(Blake2_Tree).max_depth - util.PUT_U32_LE(p[4:], ctx.cfg.tree.(Blake2_Tree).leaf_size) + endian.unchecked_put_u32le(p[4:], ctx.cfg.tree.(Blake2_Tree).leaf_size) when T == Blake2s_Context { - p[8] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset) - p[9] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 8) + p[8] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset) + p[9] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 8) p[10] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 16) p[11] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 24) p[12] = byte(ctx.cfg.tree.(Blake2_Tree).node_offset >> 32) @@ -117,7 +131,7 @@ init :: proc(ctx: ^$T) { p[14] = ctx.cfg.tree.(Blake2_Tree).node_depth p[15] = ctx.cfg.tree.(Blake2_Tree).inner_hash_size } else when T == Blake2b_Context { - util.PUT_U64_LE(p[8:], ctx.cfg.tree.(Blake2_Tree).node_offset) + endian.unchecked_put_u64le(p[8:], ctx.cfg.tree.(Blake2_Tree).node_offset) p[16] = ctx.cfg.tree.(Blake2_Tree).node_depth p[17] = ctx.cfg.tree.(Blake2_Tree).inner_hash_size } @@ -127,10 +141,10 @@ init :: proc(ctx: ^$T) { ctx.size = ctx.cfg.size for i := 0; i < 8; i += 1 { when T == Blake2s_Context { - ctx.h[i] = BLAKE2S_IV[i] ~ util.U32_LE(p[i * 4:]) + ctx.h[i] = BLAKE2S_IV[i] ~ endian.unchecked_get_u32le(p[i * 4:]) } when T == Blake2b_Context { - ctx.h[i] = BLAKE2B_IV[i] ~ util.U64_LE(p[i * 8:]) + ctx.h[i] = BLAKE2B_IV[i] ~ endian.unchecked_get_u64le(p[i * 8:]) } } if ctx.cfg.tree != nil && ctx.cfg.tree.(Blake2_Tree).is_last_node { @@ -142,13 +156,19 @@ init :: proc(ctx: ^$T) { ctx.is_keyed = true } copy(ctx.ih[:], ctx.h[:]) - copy(ctx.h[:], ctx.ih[:]) + copy(ctx.h[:], ctx.ih[:]) if ctx.is_keyed { update(ctx, ctx.padded_key[:]) } + + ctx.nx = 0 + + ctx.is_initialized = true } -update :: proc "contextless" (ctx: ^$T, p: []byte) { +update :: proc(ctx: ^$T, p: []byte) { + assert(ctx.is_initialized) + p := p when T == Blake2s_Context { block_size :: BLAKE2S_BLOCK_SIZE @@ -174,15 +194,25 @@ update :: proc "contextless" (ctx: ^$T, p: []byte) { ctx.nx += copy(ctx.x[ctx.nx:], p) } -final :: proc "contextless" (ctx: ^$T, hash: []byte) { +final :: proc(ctx: ^$T, hash: []byte) { + assert(ctx.is_initialized) + when T == Blake2s_Context { + if len(hash) < int(ctx.cfg.size) { + panic("crypto/blake2s: invalid destination digest size") + } blake2s_final(ctx, hash) - } - when T == Blake2b_Context { + } else when T == Blake2b_Context { + if len(hash) < int(ctx.cfg.size) { + panic("crypto/blake2b: invalid destination digest size") + } blake2b_final(ctx, hash) } + + ctx.is_initialized = false } +@(private) blake2s_final :: proc "contextless" (ctx: ^Blake2s_Context, hash: []byte) { if ctx.is_keyed { for i := 0; i < len(ctx.padded_key); i += 1 { @@ -203,16 +233,14 @@ blake2s_final :: proc "contextless" (ctx: ^Blake2s_Context, hash: []byte) { blocks(ctx, ctx.x[:]) - j := 0 - for s, _ in ctx.h[:(ctx.size - 1) / 4 + 1] { - hash[j + 0] = byte(s >> 0) - hash[j + 1] = byte(s >> 8) - hash[j + 2] = byte(s >> 16) - hash[j + 3] = byte(s >> 24) - j += 4 + dst: [BLAKE2S_SIZE]byte + for i := 0; i < BLAKE2S_SIZE / 4; i += 1 { + endian.unchecked_put_u32le(dst[i * 4:], ctx.h[i]) } + copy(hash, dst[:]) } +@(private) blake2b_final :: proc "contextless" (ctx: ^Blake2b_Context, hash: []byte) { if ctx.is_keyed { for i := 0; i < len(ctx.padded_key); i += 1 { @@ -229,56 +257,52 @@ blake2b_final :: proc "contextless" (ctx: ^Blake2b_Context, hash: []byte) { ctx.f[0] = 0xffffffffffffffff if ctx.is_last_node { ctx.f[1] = 0xffffffffffffffff - } + } blocks(ctx, ctx.x[:]) - j := 0 - for s, _ in ctx.h[:(ctx.size - 1) / 8 + 1] { - hash[j + 0] = byte(s >> 0) - hash[j + 1] = byte(s >> 8) - hash[j + 2] = byte(s >> 16) - hash[j + 3] = byte(s >> 24) - hash[j + 4] = byte(s >> 32) - hash[j + 5] = byte(s >> 40) - hash[j + 6] = byte(s >> 48) - hash[j + 7] = byte(s >> 56) - j += 8 + dst: [BLAKE2B_SIZE]byte + for i := 0; i < BLAKE2B_SIZE / 8; i += 1 { + endian.unchecked_put_u64le(dst[i * 8:], ctx.h[i]) } + copy(hash, dst[:]) } +@(private) blocks :: proc "contextless" (ctx: ^$T, p: []byte) { when T == Blake2s_Context { blake2s_blocks(ctx, p) - } - when T == Blake2b_Context { + } else when T == Blake2b_Context { blake2b_blocks(ctx, p) } } +@(private) blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: []byte) { - h0, h1, h2, h3, h4, h5, h6, h7 := ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] + h0, h1, h2, h3, h4, h5, h6, h7 := + ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] p := p for len(p) >= BLAKE2S_BLOCK_SIZE { ctx.t[0] += BLAKE2S_BLOCK_SIZE if ctx.t[0] < BLAKE2S_BLOCK_SIZE { ctx.t[1] += 1 - } + } v0, v1, v2, v3, v4, v5, v6, v7 := h0, h1, h2, h3, h4, h5, h6, h7 - v8 := BLAKE2S_IV[0] - v9 := BLAKE2S_IV[1] + v8 := BLAKE2S_IV[0] + v9 := BLAKE2S_IV[1] v10 := BLAKE2S_IV[2] v11 := BLAKE2S_IV[3] v12 := BLAKE2S_IV[4] ~ ctx.t[0] v13 := BLAKE2S_IV[5] ~ ctx.t[1] v14 := BLAKE2S_IV[6] ~ ctx.f[0] v15 := BLAKE2S_IV[7] ~ ctx.f[1] - m: [16]u32 - j := 0 + + m: [16]u32 = --- for i := 0; i < 16; i += 1 { - m[i] = u32(p[j]) | u32(p[j + 1]) << 8 | u32(p[j + 2]) << 16 | u32(p[j + 3]) << 24 - j += 4 + m[i] = endian.unchecked_get_u32le(p[i * 4:]) } + + // Round 1 v0 += m[0] v0 += v4 v12 ~= v0 @@ -391,6 +415,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 2 v0 += m[14] v0 += v4 v12 ~= v0 @@ -503,6 +529,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 3 v0 += m[11] v0 += v4 v12 ~= v0 @@ -615,6 +643,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 4 v0 += m[7] v0 += v4 v12 ~= v0 @@ -727,6 +757,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 5 v0 += m[9] v0 += v4 v12 ~= v0 @@ -839,6 +871,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 6 v0 += m[2] v0 += v4 v12 ~= v0 @@ -951,6 +985,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 7 v0 += m[12] v0 += v4 v12 ~= v0 @@ -1063,6 +1099,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 8 v0 += m[13] v0 += v4 v12 ~= v0 @@ -1175,6 +1213,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 9 v0 += m[6] v0 += v4 v12 ~= v0 @@ -1287,6 +1327,8 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + + // Round 10 v0 += m[10] v0 += v4 v12 ~= v0 @@ -1399,6 +1441,7 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (32 - 7) | v5 >> 7 + h0 ~= v0 ~ v8 h1 ~= v1 ~ v9 h2 ~= v2 ~ v10 @@ -1407,19 +1450,23 @@ blake2s_blocks :: #force_inline proc "contextless" (ctx: ^Blake2s_Context, p: [] h5 ~= v5 ~ v13 h6 ~= v6 ~ v14 h7 ~= v7 ~ v15 + p = p[BLAKE2S_BLOCK_SIZE:] } - ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 + ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] = + h0, h1, h2, h3, h4, h5, h6, h7 } +@(private) blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: []byte) { - h0, h1, h2, h3, h4, h5, h6, h7 := ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] + h0, h1, h2, h3, h4, h5, h6, h7 := + ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] p := p for len(p) >= BLAKE2B_BLOCK_SIZE { ctx.t[0] += BLAKE2B_BLOCK_SIZE if ctx.t[0] < BLAKE2B_BLOCK_SIZE { - ctx.t[1]+=1 - } + ctx.t[1] += 1 + } v0, v1, v2, v3, v4, v5, v6, v7 := h0, h1, h2, h3, h4, h5, h6, h7 v8 := BLAKE2B_IV[0] v9 := BLAKE2B_IV[1] @@ -1429,13 +1476,13 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v13 := BLAKE2B_IV[5] ~ ctx.t[1] v14 := BLAKE2B_IV[6] ~ ctx.f[0] v15 := BLAKE2B_IV[7] ~ ctx.f[1] + m: [16]u64 = --- - j := 0 - for i := 0; i < 16; i+=1 { - m[i] = u64(p[j]) | u64(p[j + 1]) << 8 | u64(p[j + 2]) << 16 | u64(p[j + 3]) << 24 | - u64(p[j + 4]) << 32 | u64(p[j + 5]) << 40 | u64(p[j + 6]) << 48 | u64(p[j + 7]) << 56 - j += 8 + for i := 0; i < 16; i += 1 { + m[i] = endian.unchecked_get_u64le(p[i * 8:]) } + + // Round 1 v0 += m[0] v0 += v4 v12 ~= v0 @@ -1548,6 +1595,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 2 v0 += m[14] v0 += v4 v12 ~= v0 @@ -1660,6 +1709,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 3 v0 += m[11] v0 += v4 v12 ~= v0 @@ -1772,6 +1823,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 4 v0 += m[7] v0 += v4 v12 ~= v0 @@ -1884,6 +1937,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 5 v0 += m[9] v0 += v4 v12 ~= v0 @@ -1996,6 +2051,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 6 v0 += m[2] v0 += v4 v12 ~= v0 @@ -2108,6 +2165,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 7 v0 += m[12] v0 += v4 v12 ~= v0 @@ -2220,6 +2279,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 8 v0 += m[13] v0 += v4 v12 ~= v0 @@ -2332,6 +2393,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 9 v0 += m[6] v0 += v4 v12 ~= v0 @@ -2444,6 +2507,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 10 v0 += m[10] v0 += v4 v12 ~= v0 @@ -2556,6 +2621,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 11 v0 += m[0] v0 += v4 v12 ~= v0 @@ -2668,6 +2735,8 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + + // Round 12 v0 += m[14] v0 += v4 v12 ~= v0 @@ -2780,6 +2849,7 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] v10 += v15 v5 ~= v10 v5 = v5 << (64 - 63) | v5 >> 63 + h0 ~= v0 ~ v8 h1 ~= v1 ~ v9 h2 ~= v2 ~ v10 @@ -2788,7 +2858,9 @@ blake2b_blocks :: #force_inline proc "contextless" (ctx: ^Blake2b_Context, p: [] h5 ~= v5 ~ v13 h6 ~= v6 ~ v14 h7 ~= v7 ~ v15 + p = p[BLAKE2B_BLOCK_SIZE:] } - ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 -} \ No newline at end of file + ctx.h[0], ctx.h[1], ctx.h[2], ctx.h[3], ctx.h[4], ctx.h[5], ctx.h[6], ctx.h[7] = + h0, h1, h2, h3, h4, h5, h6, h7 +} diff --git a/core/crypto/_fiat/field_poly1305/field.odin b/core/crypto/_fiat/field_poly1305/field.odin index ca458e079..a103f6fc7 100644 --- a/core/crypto/_fiat/field_poly1305/field.odin +++ b/core/crypto/_fiat/field_poly1305/field.odin @@ -1,6 +1,6 @@ package field_poly1305 -import "core:crypto/util" +import "core:encoding/endian" import "core:mem" fe_relax_cast :: #force_inline proc "contextless" (arg1: ^Tight_Field_Element) -> ^Loose_Field_Element { @@ -11,7 +11,7 @@ fe_tighten_cast :: #force_inline proc "contextless" (arg1: ^Loose_Field_Element) return transmute(^Tight_Field_Element)(arg1) } -fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, arg2: byte, sanitize: bool = true) { +fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, arg2: byte) { // fiat-crypto's deserialization routine effectively processes a // single byte at a time, and wants 256-bits of input for a value // that will be 128-bits or 129-bits. @@ -22,42 +22,29 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a assert(len(arg1) == 16) - when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 { - // While it may be unwise to do deserialization here on our - // own when fiat-crypto provides equivalent functionality, - // doing it this way provides a little under 3x performance - // improvement when optimization is enabled. - src_p := transmute(^[2]u64)(&arg1[0]) - lo := src_p[0] - hi := src_p[1] + // While it may be unwise to do deserialization here on our + // own when fiat-crypto provides equivalent functionality, + // doing it this way provides a little under 3x performance + // improvement when optimization is enabled. + lo := endian.unchecked_get_u64le(arg1[0:]) + hi := endian.unchecked_get_u64le(arg1[8:]) - // This is inspired by poly1305-donna, though adjustments were - // made since a Tight_Field_Element's limbs are 44-bits, 43-bits, - // and 43-bits wide. - // - // Note: This could be transplated into fe_from_u64s, but that - // code is called once per MAC, and is non-criticial path. - hibit := u64(arg2) << 41 // arg2 << 128 - out1[0] = lo & 0xfffffffffff - out1[1] = ((lo >> 44) | (hi << 20)) & 0x7ffffffffff - out1[2] = ((hi >> 23) & 0x7ffffffffff) | hibit - } else { - tmp: [32]byte - copy_slice(tmp[0:16], arg1[:]) - tmp[16] = arg2 - - _fe_from_bytes(out1, &tmp) - if sanitize { - // This is used to deserialize `s` which is confidential. - mem.zero_explicit(&tmp, size_of(tmp)) - } - } + // This is inspired by poly1305-donna, though adjustments were + // made since a Tight_Field_Element's limbs are 44-bits, 43-bits, + // and 43-bits wide. + // + // Note: This could be transplated into fe_from_u64s, but that + // code is called once per MAC, and is non-criticial path. + hibit := u64(arg2) << 41 // arg2 << 128 + out1[0] = lo & 0xfffffffffff + out1[1] = ((lo >> 44) | (hi << 20)) & 0x7ffffffffff + out1[2] = ((hi >> 23) & 0x7ffffffffff) | hibit } fe_from_u64s :: proc "contextless" (out1: ^Tight_Field_Element, lo, hi: u64) { tmp: [32]byte - util.PUT_U64_LE(tmp[0:8], lo) - util.PUT_U64_LE(tmp[8:16], hi) + endian.unchecked_put_u64le(tmp[0:], lo) + endian.unchecked_put_u64le(tmp[8:], hi) _fe_from_bytes(out1, &tmp) diff --git a/core/crypto/_sha3/sha3.odin b/core/crypto/_sha3/sha3.odin index 9846aca42..43af0ad75 100644 --- a/core/crypto/_sha3/sha3.odin +++ b/core/crypto/_sha3/sha3.odin @@ -11,159 +11,173 @@ package _sha3 To use the original Keccak padding, set the is_keccak bool to true, otherwise it will use SHA3 padding. */ -import "../util" +import "core:math/bits" ROUNDS :: 24 Sha3_Context :: struct { - st: struct #raw_union { - b: [200]u8, - q: [25]u64, - }, - pt: int, - rsiz: int, - mdlen: int, - is_keccak: bool, + st: struct #raw_union { + b: [200]u8, + q: [25]u64, + }, + pt: int, + rsiz: int, + mdlen: int, + is_keccak: bool, + + is_initialized: bool, + is_finalized: bool, // For SHAKE (unlimited squeeze is allowed) } keccakf :: proc "contextless" (st: ^[25]u64) { - keccakf_rndc := [?]u64 { - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, - 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, - 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, - 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, - 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, - 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, - } + keccakf_rndc := [?]u64 { + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, + } - keccakf_rotc := [?]i32 { - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, - } + keccakf_rotc := [?]int { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, + } - keccakf_piln := [?]i32 { - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, - } + keccakf_piln := [?]i32 { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, + } - i, j, r: i32 = ---, ---, --- - t: u64 = --- - bc: [5]u64 = --- + i, j, r: i32 = ---, ---, --- + t: u64 = --- + bc: [5]u64 = --- - when ODIN_ENDIAN != .Little { - v: uintptr = --- - for i = 0; i < 25; i += 1 { - v := uintptr(&st[i]) - st[i] = u64((^u8)(v + 0)^ << 0) | u64((^u8)(v + 1)^ << 8) | - u64((^u8)(v + 2)^ << 16) | u64((^u8)(v + 3)^ << 24) | - u64((^u8)(v + 4)^ << 32) | u64((^u8)(v + 5)^ << 40) | - u64((^u8)(v + 6)^ << 48) | u64((^u8)(v + 7)^ << 56) - } - } + when ODIN_ENDIAN != .Little { + for i = 0; i < 25; i += 1 { + st[i] = bits.byte_swap(st[i]) + } + } - for r = 0; r < ROUNDS; r += 1 { - // theta - for i = 0; i < 5; i += 1 { - bc[i] = st[i] ~ st[i + 5] ~ st[i + 10] ~ st[i + 15] ~ st[i + 20] - } + for r = 0; r < ROUNDS; r += 1 { + // theta + for i = 0; i < 5; i += 1 { + bc[i] = st[i] ~ st[i + 5] ~ st[i + 10] ~ st[i + 15] ~ st[i + 20] + } - for i = 0; i < 5; i += 1 { - t = bc[(i + 4) % 5] ~ util.ROTL64(bc[(i + 1) % 5], 1) - for j = 0; j < 25; j += 5 { - st[j + i] ~= t - } - } + for i = 0; i < 5; i += 1 { + t = bc[(i + 4) % 5] ~ bits.rotate_left64(bc[(i + 1) % 5], 1) + for j = 0; j < 25; j += 5 { + st[j + i] ~= t + } + } - // rho pi - t = st[1] - for i = 0; i < 24; i += 1 { - j = keccakf_piln[i] - bc[0] = st[j] - st[j] = util.ROTL64(t, u64(keccakf_rotc[i])) - t = bc[0] - } + // rho pi + t = st[1] + for i = 0; i < 24; i += 1 { + j = keccakf_piln[i] + bc[0] = st[j] + st[j] = bits.rotate_left64(t, keccakf_rotc[i]) + t = bc[0] + } - // chi - for j = 0; j < 25; j += 5 { - for i = 0; i < 5; i += 1 { - bc[i] = st[j + i] - } - for i = 0; i < 5; i += 1 { - st[j + i] ~= ~bc[(i + 1) % 5] & bc[(i + 2) % 5] - } - } + // chi + for j = 0; j < 25; j += 5 { + for i = 0; i < 5; i += 1 { + bc[i] = st[j + i] + } + for i = 0; i < 5; i += 1 { + st[j + i] ~= ~bc[(i + 1) % 5] & bc[(i + 2) % 5] + } + } - st[0] ~= keccakf_rndc[r] - } + st[0] ~= keccakf_rndc[r] + } - when ODIN_ENDIAN != .Little { - for i = 0; i < 25; i += 1 { - v = uintptr(&st[i]) - t = st[i] - (^u8)(v + 0)^ = (t >> 0) & 0xff - (^u8)(v + 1)^ = (t >> 8) & 0xff - (^u8)(v + 2)^ = (t >> 16) & 0xff - (^u8)(v + 3)^ = (t >> 24) & 0xff - (^u8)(v + 4)^ = (t >> 32) & 0xff - (^u8)(v + 5)^ = (t >> 40) & 0xff - (^u8)(v + 6)^ = (t >> 48) & 0xff - (^u8)(v + 7)^ = (t >> 56) & 0xff - } - } + when ODIN_ENDIAN != .Little { + for i = 0; i < 25; i += 1 { + st[i] = bits.byte_swap(st[i]) + } + } } -init :: proc "contextless" (c: ^Sha3_Context) { - for i := 0; i < 25; i += 1 { - c.st.q[i] = 0 - } - c.rsiz = 200 - 2 * c.mdlen +init :: proc(c: ^Sha3_Context) { + for i := 0; i < 25; i += 1 { + c.st.q[i] = 0 + } + c.rsiz = 200 - 2 * c.mdlen + c.pt = 0 + + c.is_initialized = true + c.is_finalized = false } -update :: proc "contextless" (c: ^Sha3_Context, data: []byte) { - j := c.pt - for i := 0; i < len(data); i += 1 { - c.st.b[j] ~= data[i] - j += 1 - if j >= c.rsiz { - keccakf(&c.st.q) - j = 0 - } - } - c.pt = j +update :: proc(c: ^Sha3_Context, data: []byte) { + assert(c.is_initialized) + assert(!c.is_finalized) + + j := c.pt + for i := 0; i < len(data); i += 1 { + c.st.b[j] ~= data[i] + j += 1 + if j >= c.rsiz { + keccakf(&c.st.q) + j = 0 + } + } + c.pt = j } -final :: proc "contextless" (c: ^Sha3_Context, hash: []byte) { - if c.is_keccak { - c.st.b[c.pt] ~= 0x01 - } else { - c.st.b[c.pt] ~= 0x06 - } - - c.st.b[c.rsiz - 1] ~= 0x80 - keccakf(&c.st.q) - for i := 0; i < c.mdlen; i += 1 { - hash[i] = c.st.b[i] - } +final :: proc(c: ^Sha3_Context, hash: []byte) { + assert(c.is_initialized) + + if len(hash) < c.mdlen { + if c.is_keccak { + panic("crypto/keccac: invalid destination digest size") + } + panic("crypto/sha3: invalid destination digest size") + } + if c.is_keccak { + c.st.b[c.pt] ~= 0x01 + } else { + c.st.b[c.pt] ~= 0x06 + } + + c.st.b[c.rsiz - 1] ~= 0x80 + keccakf(&c.st.q) + for i := 0; i < c.mdlen; i += 1 { + hash[i] = c.st.b[i] + } + + c.is_initialized = false // No more absorb, no more squeeze. } -shake_xof :: proc "contextless" (c: ^Sha3_Context) { - c.st.b[c.pt] ~= 0x1F - c.st.b[c.rsiz - 1] ~= 0x80 - keccakf(&c.st.q) - c.pt = 0 +shake_xof :: proc(c: ^Sha3_Context) { + assert(c.is_initialized) + assert(!c.is_finalized) + + c.st.b[c.pt] ~= 0x1F + c.st.b[c.rsiz - 1] ~= 0x80 + keccakf(&c.st.q) + c.pt = 0 + + c.is_finalized = true // No more absorb, unlimited squeeze. } -shake_out :: proc "contextless" (c: ^Sha3_Context, hash: []byte) { - j := c.pt - for i := 0; i < len(hash); i += 1 { - if j >= c.rsiz { - keccakf(&c.st.q) - j = 0 - } - hash[i] = c.st.b[j] - j += 1 - } - c.pt = j +shake_out :: proc(c: ^Sha3_Context, hash: []byte) { + assert(c.is_initialized) + assert(c.is_finalized) + + j := c.pt + for i := 0; i < len(hash); i += 1 { + if j >= c.rsiz { + keccakf(&c.st.q) + j = 0 + } + hash[i] = c.st.b[j] + j += 1 + } + c.pt = j } diff --git a/core/crypto/_tiger/tiger.odin b/core/crypto/_tiger/tiger.odin deleted file mode 100644 index e1629c4ca..000000000 --- a/core/crypto/_tiger/tiger.odin +++ /dev/null @@ -1,410 +0,0 @@ -package _tiger - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the Tiger hashing algorithm, as defined in -*/ - -import "../util" - -T1 := [?]u64 { - 0x02aab17cf7e90c5e, 0xac424b03e243a8ec, 0x72cd5be30dd5fcd3, 0x6d019b93f6f97f3a, - 0xcd9978ffd21f9193, 0x7573a1c9708029e2, 0xb164326b922a83c3, 0x46883eee04915870, - 0xeaace3057103ece6, 0xc54169b808a3535c, 0x4ce754918ddec47c, 0x0aa2f4dfdc0df40c, - 0x10b76f18a74dbefa, 0xc6ccb6235ad1ab6a, 0x13726121572fe2ff, 0x1a488c6f199d921e, - 0x4bc9f9f4da0007ca, 0x26f5e6f6e85241c7, 0x859079dbea5947b6, 0x4f1885c5c99e8c92, - 0xd78e761ea96f864b, 0x8e36428c52b5c17d, 0x69cf6827373063c1, 0xb607c93d9bb4c56e, - 0x7d820e760e76b5ea, 0x645c9cc6f07fdc42, 0xbf38a078243342e0, 0x5f6b343c9d2e7d04, - 0xf2c28aeb600b0ec6, 0x6c0ed85f7254bcac, 0x71592281a4db4fe5, 0x1967fa69ce0fed9f, - 0xfd5293f8b96545db, 0xc879e9d7f2a7600b, 0x860248920193194e, 0xa4f9533b2d9cc0b3, - 0x9053836c15957613, 0xdb6dcf8afc357bf1, 0x18beea7a7a370f57, 0x037117ca50b99066, - 0x6ab30a9774424a35, 0xf4e92f02e325249b, 0x7739db07061ccae1, 0xd8f3b49ceca42a05, - 0xbd56be3f51382f73, 0x45faed5843b0bb28, 0x1c813d5c11bf1f83, 0x8af0e4b6d75fa169, - 0x33ee18a487ad9999, 0x3c26e8eab1c94410, 0xb510102bc0a822f9, 0x141eef310ce6123b, - 0xfc65b90059ddb154, 0xe0158640c5e0e607, 0x884e079826c3a3cf, 0x930d0d9523c535fd, - 0x35638d754e9a2b00, 0x4085fccf40469dd5, 0xc4b17ad28be23a4c, 0xcab2f0fc6a3e6a2e, - 0x2860971a6b943fcd, 0x3dde6ee212e30446, 0x6222f32ae01765ae, 0x5d550bb5478308fe, - 0xa9efa98da0eda22a, 0xc351a71686c40da7, 0x1105586d9c867c84, 0xdcffee85fda22853, - 0xccfbd0262c5eef76, 0xbaf294cb8990d201, 0xe69464f52afad975, 0x94b013afdf133e14, - 0x06a7d1a32823c958, 0x6f95fe5130f61119, 0xd92ab34e462c06c0, 0xed7bde33887c71d2, - 0x79746d6e6518393e, 0x5ba419385d713329, 0x7c1ba6b948a97564, 0x31987c197bfdac67, - 0xde6c23c44b053d02, 0x581c49fed002d64d, 0xdd474d6338261571, 0xaa4546c3e473d062, - 0x928fce349455f860, 0x48161bbacaab94d9, 0x63912430770e6f68, 0x6ec8a5e602c6641c, - 0x87282515337ddd2b, 0x2cda6b42034b701b, 0xb03d37c181cb096d, 0xe108438266c71c6f, - 0x2b3180c7eb51b255, 0xdf92b82f96c08bbc, 0x5c68c8c0a632f3ba, 0x5504cc861c3d0556, - 0xabbfa4e55fb26b8f, 0x41848b0ab3baceb4, 0xb334a273aa445d32, 0xbca696f0a85ad881, - 0x24f6ec65b528d56c, 0x0ce1512e90f4524a, 0x4e9dd79d5506d35a, 0x258905fac6ce9779, - 0x2019295b3e109b33, 0xf8a9478b73a054cc, 0x2924f2f934417eb0, 0x3993357d536d1bc4, - 0x38a81ac21db6ff8b, 0x47c4fbf17d6016bf, 0x1e0faadd7667e3f5, 0x7abcff62938beb96, - 0xa78dad948fc179c9, 0x8f1f98b72911e50d, 0x61e48eae27121a91, 0x4d62f7ad31859808, - 0xeceba345ef5ceaeb, 0xf5ceb25ebc9684ce, 0xf633e20cb7f76221, 0xa32cdf06ab8293e4, - 0x985a202ca5ee2ca4, 0xcf0b8447cc8a8fb1, 0x9f765244979859a3, 0xa8d516b1a1240017, - 0x0bd7ba3ebb5dc726, 0xe54bca55b86adb39, 0x1d7a3afd6c478063, 0x519ec608e7669edd, - 0x0e5715a2d149aa23, 0x177d4571848ff194, 0xeeb55f3241014c22, 0x0f5e5ca13a6e2ec2, - 0x8029927b75f5c361, 0xad139fabc3d6e436, 0x0d5df1a94ccf402f, 0x3e8bd948bea5dfc8, - 0xa5a0d357bd3ff77e, 0xa2d12e251f74f645, 0x66fd9e525e81a082, 0x2e0c90ce7f687a49, - 0xc2e8bcbeba973bc5, 0x000001bce509745f, 0x423777bbe6dab3d6, 0xd1661c7eaef06eb5, - 0xa1781f354daacfd8, 0x2d11284a2b16affc, 0xf1fc4f67fa891d1f, 0x73ecc25dcb920ada, - 0xae610c22c2a12651, 0x96e0a810d356b78a, 0x5a9a381f2fe7870f, 0xd5ad62ede94e5530, - 0xd225e5e8368d1427, 0x65977b70c7af4631, 0x99f889b2de39d74f, 0x233f30bf54e1d143, - 0x9a9675d3d9a63c97, 0x5470554ff334f9a8, 0x166acb744a4f5688, 0x70c74caab2e4aead, - 0xf0d091646f294d12, 0x57b82a89684031d1, 0xefd95a5a61be0b6b, 0x2fbd12e969f2f29a, - 0x9bd37013feff9fe8, 0x3f9b0404d6085a06, 0x4940c1f3166cfe15, 0x09542c4dcdf3defb, - 0xb4c5218385cd5ce3, 0xc935b7dc4462a641, 0x3417f8a68ed3b63f, 0xb80959295b215b40, - 0xf99cdaef3b8c8572, 0x018c0614f8fcb95d, 0x1b14accd1a3acdf3, 0x84d471f200bb732d, - 0xc1a3110e95e8da16, 0x430a7220bf1a82b8, 0xb77e090d39df210e, 0x5ef4bd9f3cd05e9d, - 0x9d4ff6da7e57a444, 0xda1d60e183d4a5f8, 0xb287c38417998e47, 0xfe3edc121bb31886, - 0xc7fe3ccc980ccbef, 0xe46fb590189bfd03, 0x3732fd469a4c57dc, 0x7ef700a07cf1ad65, - 0x59c64468a31d8859, 0x762fb0b4d45b61f6, 0x155baed099047718, 0x68755e4c3d50baa6, - 0xe9214e7f22d8b4df, 0x2addbf532eac95f4, 0x32ae3909b4bd0109, 0x834df537b08e3450, - 0xfa209da84220728d, 0x9e691d9b9efe23f7, 0x0446d288c4ae8d7f, 0x7b4cc524e169785b, - 0x21d87f0135ca1385, 0xcebb400f137b8aa5, 0x272e2b66580796be, 0x3612264125c2b0de, - 0x057702bdad1efbb2, 0xd4babb8eacf84be9, 0x91583139641bc67b, 0x8bdc2de08036e024, - 0x603c8156f49f68ed, 0xf7d236f7dbef5111, 0x9727c4598ad21e80, 0xa08a0896670a5fd7, - 0xcb4a8f4309eba9cb, 0x81af564b0f7036a1, 0xc0b99aa778199abd, 0x959f1ec83fc8e952, - 0x8c505077794a81b9, 0x3acaaf8f056338f0, 0x07b43f50627a6778, 0x4a44ab49f5eccc77, - 0x3bc3d6e4b679ee98, 0x9cc0d4d1cf14108c, 0x4406c00b206bc8a0, 0x82a18854c8d72d89, - 0x67e366b35c3c432c, 0xb923dd61102b37f2, 0x56ab2779d884271d, 0xbe83e1b0ff1525af, - 0xfb7c65d4217e49a9, 0x6bdbe0e76d48e7d4, 0x08df828745d9179e, 0x22ea6a9add53bd34, - 0xe36e141c5622200a, 0x7f805d1b8cb750ee, 0xafe5c7a59f58e837, 0xe27f996a4fb1c23c, - 0xd3867dfb0775f0d0, 0xd0e673de6e88891a, 0x123aeb9eafb86c25, 0x30f1d5d5c145b895, - 0xbb434a2dee7269e7, 0x78cb67ecf931fa38, 0xf33b0372323bbf9c, 0x52d66336fb279c74, - 0x505f33ac0afb4eaa, 0xe8a5cd99a2cce187, 0x534974801e2d30bb, 0x8d2d5711d5876d90, - 0x1f1a412891bc038e, 0xd6e2e71d82e56648, 0x74036c3a497732b7, 0x89b67ed96361f5ab, - 0xffed95d8f1ea02a2, 0xe72b3bd61464d43d, 0xa6300f170bdc4820, 0xebc18760ed78a77a, -} - -T2 := [?]u64 { - 0xe6a6be5a05a12138, 0xb5a122a5b4f87c98, 0x563c6089140b6990, 0x4c46cb2e391f5dd5, - 0xd932addbc9b79434, 0x08ea70e42015aff5, 0xd765a6673e478cf1, 0xc4fb757eab278d99, - 0xdf11c6862d6e0692, 0xddeb84f10d7f3b16, 0x6f2ef604a665ea04, 0x4a8e0f0ff0e0dfb3, - 0xa5edeef83dbcba51, 0xfc4f0a2a0ea4371e, 0xe83e1da85cb38429, 0xdc8ff882ba1b1ce2, - 0xcd45505e8353e80d, 0x18d19a00d4db0717, 0x34a0cfeda5f38101, 0x0be77e518887caf2, - 0x1e341438b3c45136, 0xe05797f49089ccf9, 0xffd23f9df2591d14, 0x543dda228595c5cd, - 0x661f81fd99052a33, 0x8736e641db0f7b76, 0x15227725418e5307, 0xe25f7f46162eb2fa, - 0x48a8b2126c13d9fe, 0xafdc541792e76eea, 0x03d912bfc6d1898f, 0x31b1aafa1b83f51b, - 0xf1ac2796e42ab7d9, 0x40a3a7d7fcd2ebac, 0x1056136d0afbbcc5, 0x7889e1dd9a6d0c85, - 0xd33525782a7974aa, 0xa7e25d09078ac09b, 0xbd4138b3eac6edd0, 0x920abfbe71eb9e70, - 0xa2a5d0f54fc2625c, 0xc054e36b0b1290a3, 0xf6dd59ff62fe932b, 0x3537354511a8ac7d, - 0xca845e9172fadcd4, 0x84f82b60329d20dc, 0x79c62ce1cd672f18, 0x8b09a2add124642c, - 0xd0c1e96a19d9e726, 0x5a786a9b4ba9500c, 0x0e020336634c43f3, 0xc17b474aeb66d822, - 0x6a731ae3ec9baac2, 0x8226667ae0840258, 0x67d4567691caeca5, 0x1d94155c4875adb5, - 0x6d00fd985b813fdf, 0x51286efcb774cd06, 0x5e8834471fa744af, 0xf72ca0aee761ae2e, - 0xbe40e4cdaee8e09a, 0xe9970bbb5118f665, 0x726e4beb33df1964, 0x703b000729199762, - 0x4631d816f5ef30a7, 0xb880b5b51504a6be, 0x641793c37ed84b6c, 0x7b21ed77f6e97d96, - 0x776306312ef96b73, 0xae528948e86ff3f4, 0x53dbd7f286a3f8f8, 0x16cadce74cfc1063, - 0x005c19bdfa52c6dd, 0x68868f5d64d46ad3, 0x3a9d512ccf1e186a, 0x367e62c2385660ae, - 0xe359e7ea77dcb1d7, 0x526c0773749abe6e, 0x735ae5f9d09f734b, 0x493fc7cc8a558ba8, - 0xb0b9c1533041ab45, 0x321958ba470a59bd, 0x852db00b5f46c393, 0x91209b2bd336b0e5, - 0x6e604f7d659ef19f, 0xb99a8ae2782ccb24, 0xccf52ab6c814c4c7, 0x4727d9afbe11727b, - 0x7e950d0c0121b34d, 0x756f435670ad471f, 0xf5add442615a6849, 0x4e87e09980b9957a, - 0x2acfa1df50aee355, 0xd898263afd2fd556, 0xc8f4924dd80c8fd6, 0xcf99ca3d754a173a, - 0xfe477bacaf91bf3c, 0xed5371f6d690c12d, 0x831a5c285e687094, 0xc5d3c90a3708a0a4, - 0x0f7f903717d06580, 0x19f9bb13b8fdf27f, 0xb1bd6f1b4d502843, 0x1c761ba38fff4012, - 0x0d1530c4e2e21f3b, 0x8943ce69a7372c8a, 0xe5184e11feb5ce66, 0x618bdb80bd736621, - 0x7d29bad68b574d0b, 0x81bb613e25e6fe5b, 0x071c9c10bc07913f, 0xc7beeb7909ac2d97, - 0xc3e58d353bc5d757, 0xeb017892f38f61e8, 0xd4effb9c9b1cc21a, 0x99727d26f494f7ab, - 0xa3e063a2956b3e03, 0x9d4a8b9a4aa09c30, 0x3f6ab7d500090fb4, 0x9cc0f2a057268ac0, - 0x3dee9d2dedbf42d1, 0x330f49c87960a972, 0xc6b2720287421b41, 0x0ac59ec07c00369c, - 0xef4eac49cb353425, 0xf450244eef0129d8, 0x8acc46e5caf4deb6, 0x2ffeab63989263f7, - 0x8f7cb9fe5d7a4578, 0x5bd8f7644e634635, 0x427a7315bf2dc900, 0x17d0c4aa2125261c, - 0x3992486c93518e50, 0xb4cbfee0a2d7d4c3, 0x7c75d6202c5ddd8d, 0xdbc295d8e35b6c61, - 0x60b369d302032b19, 0xce42685fdce44132, 0x06f3ddb9ddf65610, 0x8ea4d21db5e148f0, - 0x20b0fce62fcd496f, 0x2c1b912358b0ee31, 0xb28317b818f5a308, 0xa89c1e189ca6d2cf, - 0x0c6b18576aaadbc8, 0xb65deaa91299fae3, 0xfb2b794b7f1027e7, 0x04e4317f443b5beb, - 0x4b852d325939d0a6, 0xd5ae6beefb207ffc, 0x309682b281c7d374, 0xbae309a194c3b475, - 0x8cc3f97b13b49f05, 0x98a9422ff8293967, 0x244b16b01076ff7c, 0xf8bf571c663d67ee, - 0x1f0d6758eee30da1, 0xc9b611d97adeb9b7, 0xb7afd5887b6c57a2, 0x6290ae846b984fe1, - 0x94df4cdeacc1a5fd, 0x058a5bd1c5483aff, 0x63166cc142ba3c37, 0x8db8526eb2f76f40, - 0xe10880036f0d6d4e, 0x9e0523c9971d311d, 0x45ec2824cc7cd691, 0x575b8359e62382c9, - 0xfa9e400dc4889995, 0xd1823ecb45721568, 0xdafd983b8206082f, 0xaa7d29082386a8cb, - 0x269fcd4403b87588, 0x1b91f5f728bdd1e0, 0xe4669f39040201f6, 0x7a1d7c218cf04ade, - 0x65623c29d79ce5ce, 0x2368449096c00bb1, 0xab9bf1879da503ba, 0xbc23ecb1a458058e, - 0x9a58df01bb401ecc, 0xa070e868a85f143d, 0x4ff188307df2239e, 0x14d565b41a641183, - 0xee13337452701602, 0x950e3dcf3f285e09, 0x59930254b9c80953, 0x3bf299408930da6d, - 0xa955943f53691387, 0xa15edecaa9cb8784, 0x29142127352be9a0, 0x76f0371fff4e7afb, - 0x0239f450274f2228, 0xbb073af01d5e868b, 0xbfc80571c10e96c1, 0xd267088568222e23, - 0x9671a3d48e80b5b0, 0x55b5d38ae193bb81, 0x693ae2d0a18b04b8, 0x5c48b4ecadd5335f, - 0xfd743b194916a1ca, 0x2577018134be98c4, 0xe77987e83c54a4ad, 0x28e11014da33e1b9, - 0x270cc59e226aa213, 0x71495f756d1a5f60, 0x9be853fb60afef77, 0xadc786a7f7443dbf, - 0x0904456173b29a82, 0x58bc7a66c232bd5e, 0xf306558c673ac8b2, 0x41f639c6b6c9772a, - 0x216defe99fda35da, 0x11640cc71c7be615, 0x93c43694565c5527, 0xea038e6246777839, - 0xf9abf3ce5a3e2469, 0x741e768d0fd312d2, 0x0144b883ced652c6, 0xc20b5a5ba33f8552, - 0x1ae69633c3435a9d, 0x97a28ca4088cfdec, 0x8824a43c1e96f420, 0x37612fa66eeea746, - 0x6b4cb165f9cf0e5a, 0x43aa1c06a0abfb4a, 0x7f4dc26ff162796b, 0x6cbacc8e54ed9b0f, - 0xa6b7ffefd2bb253e, 0x2e25bc95b0a29d4f, 0x86d6a58bdef1388c, 0xded74ac576b6f054, - 0x8030bdbc2b45805d, 0x3c81af70e94d9289, 0x3eff6dda9e3100db, 0xb38dc39fdfcc8847, - 0x123885528d17b87e, 0xf2da0ed240b1b642, 0x44cefadcd54bf9a9, 0x1312200e433c7ee6, - 0x9ffcc84f3a78c748, 0xf0cd1f72248576bb, 0xec6974053638cfe4, 0x2ba7b67c0cec4e4c, - 0xac2f4df3e5ce32ed, 0xcb33d14326ea4c11, 0xa4e9044cc77e58bc, 0x5f513293d934fcef, - 0x5dc9645506e55444, 0x50de418f317de40a, 0x388cb31a69dde259, 0x2db4a83455820a86, - 0x9010a91e84711ae9, 0x4df7f0b7b1498371, 0xd62a2eabc0977179, 0x22fac097aa8d5c0e, -} - -T3 := [?]u64 { - 0xf49fcc2ff1daf39b, 0x487fd5c66ff29281, 0xe8a30667fcdca83f, 0x2c9b4be3d2fcce63, - 0xda3ff74b93fbbbc2, 0x2fa165d2fe70ba66, 0xa103e279970e93d4, 0xbecdec77b0e45e71, - 0xcfb41e723985e497, 0xb70aaa025ef75017, 0xd42309f03840b8e0, 0x8efc1ad035898579, - 0x96c6920be2b2abc5, 0x66af4163375a9172, 0x2174abdcca7127fb, 0xb33ccea64a72ff41, - 0xf04a4933083066a5, 0x8d970acdd7289af5, 0x8f96e8e031c8c25e, 0xf3fec02276875d47, - 0xec7bf310056190dd, 0xf5adb0aebb0f1491, 0x9b50f8850fd58892, 0x4975488358b74de8, - 0xa3354ff691531c61, 0x0702bbe481d2c6ee, 0x89fb24057deded98, 0xac3075138596e902, - 0x1d2d3580172772ed, 0xeb738fc28e6bc30d, 0x5854ef8f63044326, 0x9e5c52325add3bbe, - 0x90aa53cf325c4623, 0xc1d24d51349dd067, 0x2051cfeea69ea624, 0x13220f0a862e7e4f, - 0xce39399404e04864, 0xd9c42ca47086fcb7, 0x685ad2238a03e7cc, 0x066484b2ab2ff1db, - 0xfe9d5d70efbf79ec, 0x5b13b9dd9c481854, 0x15f0d475ed1509ad, 0x0bebcd060ec79851, - 0xd58c6791183ab7f8, 0xd1187c5052f3eee4, 0xc95d1192e54e82ff, 0x86eea14cb9ac6ca2, - 0x3485beb153677d5d, 0xdd191d781f8c492a, 0xf60866baa784ebf9, 0x518f643ba2d08c74, - 0x8852e956e1087c22, 0xa768cb8dc410ae8d, 0x38047726bfec8e1a, 0xa67738b4cd3b45aa, - 0xad16691cec0dde19, 0xc6d4319380462e07, 0xc5a5876d0ba61938, 0x16b9fa1fa58fd840, - 0x188ab1173ca74f18, 0xabda2f98c99c021f, 0x3e0580ab134ae816, 0x5f3b05b773645abb, - 0x2501a2be5575f2f6, 0x1b2f74004e7e8ba9, 0x1cd7580371e8d953, 0x7f6ed89562764e30, - 0xb15926ff596f003d, 0x9f65293da8c5d6b9, 0x6ecef04dd690f84c, 0x4782275fff33af88, - 0xe41433083f820801, 0xfd0dfe409a1af9b5, 0x4325a3342cdb396b, 0x8ae77e62b301b252, - 0xc36f9e9f6655615a, 0x85455a2d92d32c09, 0xf2c7dea949477485, 0x63cfb4c133a39eba, - 0x83b040cc6ebc5462, 0x3b9454c8fdb326b0, 0x56f56a9e87ffd78c, 0x2dc2940d99f42bc6, - 0x98f7df096b096e2d, 0x19a6e01e3ad852bf, 0x42a99ccbdbd4b40b, 0xa59998af45e9c559, - 0x366295e807d93186, 0x6b48181bfaa1f773, 0x1fec57e2157a0a1d, 0x4667446af6201ad5, - 0xe615ebcacfb0f075, 0xb8f31f4f68290778, 0x22713ed6ce22d11e, 0x3057c1a72ec3c93b, - 0xcb46acc37c3f1f2f, 0xdbb893fd02aaf50e, 0x331fd92e600b9fcf, 0xa498f96148ea3ad6, - 0xa8d8426e8b6a83ea, 0xa089b274b7735cdc, 0x87f6b3731e524a11, 0x118808e5cbc96749, - 0x9906e4c7b19bd394, 0xafed7f7e9b24a20c, 0x6509eadeeb3644a7, 0x6c1ef1d3e8ef0ede, - 0xb9c97d43e9798fb4, 0xa2f2d784740c28a3, 0x7b8496476197566f, 0x7a5be3e6b65f069d, - 0xf96330ed78be6f10, 0xeee60de77a076a15, 0x2b4bee4aa08b9bd0, 0x6a56a63ec7b8894e, - 0x02121359ba34fef4, 0x4cbf99f8283703fc, 0x398071350caf30c8, 0xd0a77a89f017687a, - 0xf1c1a9eb9e423569, 0x8c7976282dee8199, 0x5d1737a5dd1f7abd, 0x4f53433c09a9fa80, - 0xfa8b0c53df7ca1d9, 0x3fd9dcbc886ccb77, 0xc040917ca91b4720, 0x7dd00142f9d1dcdf, - 0x8476fc1d4f387b58, 0x23f8e7c5f3316503, 0x032a2244e7e37339, 0x5c87a5d750f5a74b, - 0x082b4cc43698992e, 0xdf917becb858f63c, 0x3270b8fc5bf86dda, 0x10ae72bb29b5dd76, - 0x576ac94e7700362b, 0x1ad112dac61efb8f, 0x691bc30ec5faa427, 0xff246311cc327143, - 0x3142368e30e53206, 0x71380e31e02ca396, 0x958d5c960aad76f1, 0xf8d6f430c16da536, - 0xc8ffd13f1be7e1d2, 0x7578ae66004ddbe1, 0x05833f01067be646, 0xbb34b5ad3bfe586d, - 0x095f34c9a12b97f0, 0x247ab64525d60ca8, 0xdcdbc6f3017477d1, 0x4a2e14d4decad24d, - 0xbdb5e6d9be0a1eeb, 0x2a7e70f7794301ab, 0xdef42d8a270540fd, 0x01078ec0a34c22c1, - 0xe5de511af4c16387, 0x7ebb3a52bd9a330a, 0x77697857aa7d6435, 0x004e831603ae4c32, - 0xe7a21020ad78e312, 0x9d41a70c6ab420f2, 0x28e06c18ea1141e6, 0xd2b28cbd984f6b28, - 0x26b75f6c446e9d83, 0xba47568c4d418d7f, 0xd80badbfe6183d8e, 0x0e206d7f5f166044, - 0xe258a43911cbca3e, 0x723a1746b21dc0bc, 0xc7caa854f5d7cdd3, 0x7cac32883d261d9c, - 0x7690c26423ba942c, 0x17e55524478042b8, 0xe0be477656a2389f, 0x4d289b5e67ab2da0, - 0x44862b9c8fbbfd31, 0xb47cc8049d141365, 0x822c1b362b91c793, 0x4eb14655fb13dfd8, - 0x1ecbba0714e2a97b, 0x6143459d5cde5f14, 0x53a8fbf1d5f0ac89, 0x97ea04d81c5e5b00, - 0x622181a8d4fdb3f3, 0xe9bcd341572a1208, 0x1411258643cce58a, 0x9144c5fea4c6e0a4, - 0x0d33d06565cf620f, 0x54a48d489f219ca1, 0xc43e5eac6d63c821, 0xa9728b3a72770daf, - 0xd7934e7b20df87ef, 0xe35503b61a3e86e5, 0xcae321fbc819d504, 0x129a50b3ac60bfa6, - 0xcd5e68ea7e9fb6c3, 0xb01c90199483b1c7, 0x3de93cd5c295376c, 0xaed52edf2ab9ad13, - 0x2e60f512c0a07884, 0xbc3d86a3e36210c9, 0x35269d9b163951ce, 0x0c7d6e2ad0cdb5fa, - 0x59e86297d87f5733, 0x298ef221898db0e7, 0x55000029d1a5aa7e, 0x8bc08ae1b5061b45, - 0xc2c31c2b6c92703a, 0x94cc596baf25ef42, 0x0a1d73db22540456, 0x04b6a0f9d9c4179a, - 0xeffdafa2ae3d3c60, 0xf7c8075bb49496c4, 0x9cc5c7141d1cd4e3, 0x78bd1638218e5534, - 0xb2f11568f850246a, 0xedfabcfa9502bc29, 0x796ce5f2da23051b, 0xaae128b0dc93537c, - 0x3a493da0ee4b29ae, 0xb5df6b2c416895d7, 0xfcabbd25122d7f37, 0x70810b58105dc4b1, - 0xe10fdd37f7882a90, 0x524dcab5518a3f5c, 0x3c9e85878451255b, 0x4029828119bd34e2, - 0x74a05b6f5d3ceccb, 0xb610021542e13eca, 0x0ff979d12f59e2ac, 0x6037da27e4f9cc50, - 0x5e92975a0df1847d, 0xd66de190d3e623fe, 0x5032d6b87b568048, 0x9a36b7ce8235216e, - 0x80272a7a24f64b4a, 0x93efed8b8c6916f7, 0x37ddbff44cce1555, 0x4b95db5d4b99bd25, - 0x92d3fda169812fc0, 0xfb1a4a9a90660bb6, 0x730c196946a4b9b2, 0x81e289aa7f49da68, - 0x64669a0f83b1a05f, 0x27b3ff7d9644f48b, 0xcc6b615c8db675b3, 0x674f20b9bcebbe95, - 0x6f31238275655982, 0x5ae488713e45cf05, 0xbf619f9954c21157, 0xeabac46040a8eae9, - 0x454c6fe9f2c0c1cd, 0x419cf6496412691c, 0xd3dc3bef265b0f70, 0x6d0e60f5c3578a9e, -} - -T4 := [?]u64 { - 0x5b0e608526323c55, 0x1a46c1a9fa1b59f5, 0xa9e245a17c4c8ffa, 0x65ca5159db2955d7, - 0x05db0a76ce35afc2, 0x81eac77ea9113d45, 0x528ef88ab6ac0a0d, 0xa09ea253597be3ff, - 0x430ddfb3ac48cd56, 0xc4b3a67af45ce46f, 0x4ececfd8fbe2d05e, 0x3ef56f10b39935f0, - 0x0b22d6829cd619c6, 0x17fd460a74df2069, 0x6cf8cc8e8510ed40, 0xd6c824bf3a6ecaa7, - 0x61243d581a817049, 0x048bacb6bbc163a2, 0xd9a38ac27d44cc32, 0x7fddff5baaf410ab, - 0xad6d495aa804824b, 0xe1a6a74f2d8c9f94, 0xd4f7851235dee8e3, 0xfd4b7f886540d893, - 0x247c20042aa4bfda, 0x096ea1c517d1327c, 0xd56966b4361a6685, 0x277da5c31221057d, - 0x94d59893a43acff7, 0x64f0c51ccdc02281, 0x3d33bcc4ff6189db, 0xe005cb184ce66af1, - 0xff5ccd1d1db99bea, 0xb0b854a7fe42980f, 0x7bd46a6a718d4b9f, 0xd10fa8cc22a5fd8c, - 0xd31484952be4bd31, 0xc7fa975fcb243847, 0x4886ed1e5846c407, 0x28cddb791eb70b04, - 0xc2b00be2f573417f, 0x5c9590452180f877, 0x7a6bddfff370eb00, 0xce509e38d6d9d6a4, - 0xebeb0f00647fa702, 0x1dcc06cf76606f06, 0xe4d9f28ba286ff0a, 0xd85a305dc918c262, - 0x475b1d8732225f54, 0x2d4fb51668ccb5fe, 0xa679b9d9d72bba20, 0x53841c0d912d43a5, - 0x3b7eaa48bf12a4e8, 0x781e0e47f22f1ddf, 0xeff20ce60ab50973, 0x20d261d19dffb742, - 0x16a12b03062a2e39, 0x1960eb2239650495, 0x251c16fed50eb8b8, 0x9ac0c330f826016e, - 0xed152665953e7671, 0x02d63194a6369570, 0x5074f08394b1c987, 0x70ba598c90b25ce1, - 0x794a15810b9742f6, 0x0d5925e9fcaf8c6c, 0x3067716cd868744e, 0x910ab077e8d7731b, - 0x6a61bbdb5ac42f61, 0x93513efbf0851567, 0xf494724b9e83e9d5, 0xe887e1985c09648d, - 0x34b1d3c675370cfd, 0xdc35e433bc0d255d, 0xd0aab84234131be0, 0x08042a50b48b7eaf, - 0x9997c4ee44a3ab35, 0x829a7b49201799d0, 0x263b8307b7c54441, 0x752f95f4fd6a6ca6, - 0x927217402c08c6e5, 0x2a8ab754a795d9ee, 0xa442f7552f72943d, 0x2c31334e19781208, - 0x4fa98d7ceaee6291, 0x55c3862f665db309, 0xbd0610175d53b1f3, 0x46fe6cb840413f27, - 0x3fe03792df0cfa59, 0xcfe700372eb85e8f, 0xa7be29e7adbce118, 0xe544ee5cde8431dd, - 0x8a781b1b41f1873e, 0xa5c94c78a0d2f0e7, 0x39412e2877b60728, 0xa1265ef3afc9a62c, - 0xbcc2770c6a2506c5, 0x3ab66dd5dce1ce12, 0xe65499d04a675b37, 0x7d8f523481bfd216, - 0x0f6f64fcec15f389, 0x74efbe618b5b13c8, 0xacdc82b714273e1d, 0xdd40bfe003199d17, - 0x37e99257e7e061f8, 0xfa52626904775aaa, 0x8bbbf63a463d56f9, 0xf0013f1543a26e64, - 0xa8307e9f879ec898, 0xcc4c27a4150177cc, 0x1b432f2cca1d3348, 0xde1d1f8f9f6fa013, - 0x606602a047a7ddd6, 0xd237ab64cc1cb2c7, 0x9b938e7225fcd1d3, 0xec4e03708e0ff476, - 0xfeb2fbda3d03c12d, 0xae0bced2ee43889a, 0x22cb8923ebfb4f43, 0x69360d013cf7396d, - 0x855e3602d2d4e022, 0x073805bad01f784c, 0x33e17a133852f546, 0xdf4874058ac7b638, - 0xba92b29c678aa14a, 0x0ce89fc76cfaadcd, 0x5f9d4e0908339e34, 0xf1afe9291f5923b9, - 0x6e3480f60f4a265f, 0xeebf3a2ab29b841c, 0xe21938a88f91b4ad, 0x57dfeff845c6d3c3, - 0x2f006b0bf62caaf2, 0x62f479ef6f75ee78, 0x11a55ad41c8916a9, 0xf229d29084fed453, - 0x42f1c27b16b000e6, 0x2b1f76749823c074, 0x4b76eca3c2745360, 0x8c98f463b91691bd, - 0x14bcc93cf1ade66a, 0x8885213e6d458397, 0x8e177df0274d4711, 0xb49b73b5503f2951, - 0x10168168c3f96b6b, 0x0e3d963b63cab0ae, 0x8dfc4b5655a1db14, 0xf789f1356e14de5c, - 0x683e68af4e51dac1, 0xc9a84f9d8d4b0fd9, 0x3691e03f52a0f9d1, 0x5ed86e46e1878e80, - 0x3c711a0e99d07150, 0x5a0865b20c4e9310, 0x56fbfc1fe4f0682e, 0xea8d5de3105edf9b, - 0x71abfdb12379187a, 0x2eb99de1bee77b9c, 0x21ecc0ea33cf4523, 0x59a4d7521805c7a1, - 0x3896f5eb56ae7c72, 0xaa638f3db18f75dc, 0x9f39358dabe9808e, 0xb7defa91c00b72ac, - 0x6b5541fd62492d92, 0x6dc6dee8f92e4d5b, 0x353f57abc4beea7e, 0x735769d6da5690ce, - 0x0a234aa642391484, 0xf6f9508028f80d9d, 0xb8e319a27ab3f215, 0x31ad9c1151341a4d, - 0x773c22a57bef5805, 0x45c7561a07968633, 0xf913da9e249dbe36, 0xda652d9b78a64c68, - 0x4c27a97f3bc334ef, 0x76621220e66b17f4, 0x967743899acd7d0b, 0xf3ee5bcae0ed6782, - 0x409f753600c879fc, 0x06d09a39b5926db6, 0x6f83aeb0317ac588, 0x01e6ca4a86381f21, - 0x66ff3462d19f3025, 0x72207c24ddfd3bfb, 0x4af6b6d3e2ece2eb, 0x9c994dbec7ea08de, - 0x49ace597b09a8bc4, 0xb38c4766cf0797ba, 0x131b9373c57c2a75, 0xb1822cce61931e58, - 0x9d7555b909ba1c0c, 0x127fafdd937d11d2, 0x29da3badc66d92e4, 0xa2c1d57154c2ecbc, - 0x58c5134d82f6fe24, 0x1c3ae3515b62274f, 0xe907c82e01cb8126, 0xf8ed091913e37fcb, - 0x3249d8f9c80046c9, 0x80cf9bede388fb63, 0x1881539a116cf19e, 0x5103f3f76bd52457, - 0x15b7e6f5ae47f7a8, 0xdbd7c6ded47e9ccf, 0x44e55c410228bb1a, 0xb647d4255edb4e99, - 0x5d11882bb8aafc30, 0xf5098bbb29d3212a, 0x8fb5ea14e90296b3, 0x677b942157dd025a, - 0xfb58e7c0a390acb5, 0x89d3674c83bd4a01, 0x9e2da4df4bf3b93b, 0xfcc41e328cab4829, - 0x03f38c96ba582c52, 0xcad1bdbd7fd85db2, 0xbbb442c16082ae83, 0xb95fe86ba5da9ab0, - 0xb22e04673771a93f, 0x845358c9493152d8, 0xbe2a488697b4541e, 0x95a2dc2dd38e6966, - 0xc02c11ac923c852b, 0x2388b1990df2a87b, 0x7c8008fa1b4f37be, 0x1f70d0c84d54e503, - 0x5490adec7ece57d4, 0x002b3c27d9063a3a, 0x7eaea3848030a2bf, 0xc602326ded2003c0, - 0x83a7287d69a94086, 0xc57a5fcb30f57a8a, 0xb56844e479ebe779, 0xa373b40f05dcbce9, - 0xd71a786e88570ee2, 0x879cbacdbde8f6a0, 0x976ad1bcc164a32f, 0xab21e25e9666d78b, - 0x901063aae5e5c33c, 0x9818b34448698d90, 0xe36487ae3e1e8abb, 0xafbdf931893bdcb4, - 0x6345a0dc5fbbd519, 0x8628fe269b9465ca, 0x1e5d01603f9c51ec, 0x4de44006a15049b7, - 0xbf6c70e5f776cbb1, 0x411218f2ef552bed, 0xcb0c0708705a36a3, 0xe74d14754f986044, - 0xcd56d9430ea8280e, 0xc12591d7535f5065, 0xc83223f1720aef96, 0xc3a0396f7363a51f, -} - -Tiger_Context :: struct { - a: u64, - b: u64, - c: u64, - x: [64]byte, - nx: int, - length: u64, - ver: int, -} - -round :: #force_inline proc "contextless" (a, b, c, x, mul: u64) -> (u64, u64, u64) { - a, b, c := a, b, c - c ~= x - a -= T1[c & 0xff] ~ T2[(c >> 16) & 0xff] ~ T3[(c >> 32) & 0xff] ~ T4[(c >> 48) & 0xff] - b += T4[(c >> 8) & 0xff] ~ T3[(c >> 24) & 0xff] ~ T2[(c >> 40) & 0xff] ~ T1[(c >> 56) & 0xff] - b *= mul - return a, b, c -} - -pass :: #force_inline proc "contextless" (a, b, c: u64, d: []u64, mul: u64) -> (x, y, z: u64) { - x, y, z = round(a, b, c, d[0], mul) - y, z, x = round(y, z, x, d[1], mul) - z, x, y = round(z, x, y, d[2], mul) - x, y, z = round(x, y, z, d[3], mul) - y, z, x = round(y, z, x, d[4], mul) - z, x, y = round(z, x, y, d[5], mul) - x, y, z = round(x, y, z, d[6], mul) - y, z, x = round(y, z, x, d[7], mul) - return -} - -key_schedule :: #force_inline proc "contextless" (x: []u64) { - x[0] -= x[7] ~ 0xa5a5a5a5a5a5a5a5 - x[1] ~= x[0] - x[2] += x[1] - x[3] -= x[2] ~ ((~x[1]) << 19) - x[4] ~= x[3] - x[5] += x[4] - x[6] -= x[5] ~ ((~x[4]) >> 23) - x[7] ~= x[6] - x[0] += x[7] - x[1] -= x[0] ~ ((~x[7]) << 19) - x[2] ~= x[1] - x[3] += x[2] - x[4] -= x[3] ~ ((~x[2]) >> 23) - x[5] ~= x[4] - x[6] += x[5] - x[7] -= x[6] ~ 0x0123456789abcdef -} - -compress :: #force_inline proc "contextless" (ctx: ^Tiger_Context, data: []byte) { - a := ctx.a - b := ctx.b - c := ctx.c - x := util.cast_slice([]u64, data) - ctx.a, ctx.b, ctx.c = pass(ctx.a, ctx.b, ctx.c, x, 5) - key_schedule(x) - ctx.c, ctx.a, ctx.b = pass(ctx.c, ctx.a, ctx.b, x, 7) - key_schedule(x) - ctx.b, ctx.c, ctx.a = pass(ctx.b, ctx.c, ctx.a, x, 9) - ctx.a ~= a - ctx.b -= b - ctx.c += c -} - -init :: proc "contextless" (ctx: ^Tiger_Context) { - ctx.a = 0x0123456789abcdef - ctx.b = 0xfedcba9876543210 - ctx.c = 0xf096a5b4c3b2e187 -} - -update :: proc(ctx: ^Tiger_Context, input: []byte) { - p := make([]byte, len(input)) - copy(p, input) - - length := len(p) - ctx.length += u64(length) - if ctx.nx > 0 { - n := len(p) - if n > 64 - ctx.nx { - n = 64 - ctx.nx - } - copy(ctx.x[ctx.nx:ctx.nx + n], p[:n]) - ctx.nx += n - if ctx.nx == 64 { - compress(ctx, ctx.x[:64 - 1]) - ctx.nx = 0 - } - p = p[n:] - } - for len(p) >= 64 { - compress(ctx, p[:64]) - p = p[64:] - } - if len(p) > 0 { - ctx.nx = copy(ctx.x[:], p) - } -} - -final :: proc(ctx: ^Tiger_Context, hash: []byte) { - length := ctx.length - tmp: [64]byte - if ctx.ver == 1 { - tmp[0] = 0x01 - } else { - tmp[0] = 0x80 - } - - size := length & 0x3f - if size < 56 { - update(ctx, tmp[:56 - size]) - } else { - update(ctx, tmp[:64 + 56 - size]) - } - - length <<= 3 - for i := uint(0); i < 8; i += 1 { - tmp[i] = byte(length >> (8 * i)) - } - update(ctx, tmp[:8]) - - for i := uint(0); i < 8; i += 1 { - tmp[i] = byte(ctx.a >> (8 * i)) - tmp[i + 8] = byte(ctx.b >> (8 * i)) - tmp[i + 16] = byte(ctx.c >> (8 * i)) - } - copy(hash[:], tmp[:len(hash)]) -} \ No newline at end of file diff --git a/core/crypto/blake/blake.odin b/core/crypto/blake/blake.odin deleted file mode 100644 index 3685109e4..000000000 --- a/core/crypto/blake/blake.odin +++ /dev/null @@ -1,726 +0,0 @@ -package blake - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the BLAKE hashing algorithm, as defined in -*/ - -import "core:os" -import "core:io" - -/* - High level API -*/ - -DIGEST_SIZE_224 :: 28 -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_384 :: 48 -DIGEST_SIZE_512 :: 64 - -// hash_string_224 will hash the given input and return the -// computed hash -hash_string_224 :: proc "contextless" (data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) -} - -// hash_bytes_224 will hash the given input and return the -// computed hash -hash_bytes_224 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Blake256_Context - ctx.is224 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Blake256_Context - ctx.is224 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Blake256_Context - ctx.is224 = true - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224 will read the file provided by the given handle -// and compute a hash -hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, -} - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc "contextless" (data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Blake256_Context - ctx.is224 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Blake256_Context - ctx.is224 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Blake256_Context - ctx.is224 = false - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_384 will hash the given input and return the -// computed hash -hash_string_384 :: proc "contextless" (data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) -} - -// hash_bytes_384 will hash the given input and return the -// computed hash -hash_bytes_384 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: Blake512_Context - ctx.is384 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_384 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_384 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: Blake512_Context - ctx.is384 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_384 will read the stream in chunks and compute a -// hash from its contents -hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { - hash: [DIGEST_SIZE_384]byte - ctx: Blake512_Context - ctx.is384 = true - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_384 will read the file provided by the given handle -// and compute a hash -hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false -} - -hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, -} - -// hash_string_512 will hash the given input and return the -// computed hash -hash_string_512 :: proc "contextless" (data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) -} - -// hash_bytes_512 will hash the given input and return the -// computed hash -hash_bytes_512 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: Blake512_Context - ctx.is384 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_512 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_512 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: Blake512_Context - ctx.is384 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_512 will read the stream in chunks and compute a -// hash from its contents -hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: Blake512_Context - ctx.is384 = false - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_512 will read the file provided by the given handle -// and compute a hash -hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false -} - -hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, -} - -/* - Low level API -*/ - -init :: proc "contextless" (ctx: ^$T) { - when T == Blake256_Context { - if ctx.is224 { - ctx.h[0] = 0xc1059ed8 - ctx.h[1] = 0x367cd507 - ctx.h[2] = 0x3070dd17 - ctx.h[3] = 0xf70e5939 - ctx.h[4] = 0xffc00b31 - ctx.h[5] = 0x68581511 - ctx.h[6] = 0x64f98fa7 - ctx.h[7] = 0xbefa4fa4 - } else { - ctx.h[0] = 0x6a09e667 - ctx.h[1] = 0xbb67ae85 - ctx.h[2] = 0x3c6ef372 - ctx.h[3] = 0xa54ff53a - ctx.h[4] = 0x510e527f - ctx.h[5] = 0x9b05688c - ctx.h[6] = 0x1f83d9ab - ctx.h[7] = 0x5be0cd19 - } - } else when T == Blake512_Context { - if ctx.is384 { - ctx.h[0] = 0xcbbb9d5dc1059ed8 - ctx.h[1] = 0x629a292a367cd507 - ctx.h[2] = 0x9159015a3070dd17 - ctx.h[3] = 0x152fecd8f70e5939 - ctx.h[4] = 0x67332667ffc00b31 - ctx.h[5] = 0x8eb44a8768581511 - ctx.h[6] = 0xdb0c2e0d64f98fa7 - ctx.h[7] = 0x47b5481dbefa4fa4 - } else { - ctx.h[0] = 0x6a09e667f3bcc908 - ctx.h[1] = 0xbb67ae8584caa73b - ctx.h[2] = 0x3c6ef372fe94f82b - ctx.h[3] = 0xa54ff53a5f1d36f1 - ctx.h[4] = 0x510e527fade682d1 - ctx.h[5] = 0x9b05688c2b3e6c1f - ctx.h[6] = 0x1f83d9abfb41bd6b - ctx.h[7] = 0x5be0cd19137e2179 - } - } -} - -update :: proc "contextless" (ctx: ^$T, data: []byte) { - data := data - when T == Blake256_Context { - if ctx.nx > 0 { - n := copy(ctx.x[ctx.nx:], data) - ctx.nx += n - if ctx.nx == BLOCKSIZE_256 { - block256(ctx, ctx.x[:]) - ctx.nx = 0 - } - data = data[n:] - } - if len(data) >= BLOCKSIZE_256 { - n := len(data) &~ (BLOCKSIZE_256 - 1) - block256(ctx, data[:n]) - data = data[n:] - } - if len(data) > 0 { - ctx.nx = copy(ctx.x[:], data) - } - } else when T == Blake512_Context { - if ctx.nx > 0 { - n := copy(ctx.x[ctx.nx:], data) - ctx.nx += n - if ctx.nx == BLOCKSIZE_512 { - block512(ctx, ctx.x[:]) - ctx.nx = 0 - } - data = data[n:] - } - if len(data) >= BLOCKSIZE_512 { - n := len(data) &~ (BLOCKSIZE_512 - 1) - block512(ctx, data[:n]) - data = data[n:] - } - if len(data) > 0 { - ctx.nx = copy(ctx.x[:], data) - } - } -} - -final :: proc "contextless" (ctx: ^$T, hash: []byte) { - when T == Blake256_Context { - tmp: [65]byte - } else when T == Blake512_Context { - tmp: [129]byte - } - nx := u64(ctx.nx) - tmp[0] = 0x80 - length := (ctx.t + nx) << 3 - - when T == Blake256_Context { - if nx == 55 { - if ctx.is224 { - write_additional(ctx, {0x80}) - } else { - write_additional(ctx, {0x81}) - } - } else { - if nx < 55 { - if nx == 0 { - ctx.nullt = true - } - write_additional(ctx, tmp[0 : 55 - nx]) - } else { - write_additional(ctx, tmp[0 : 64 - nx]) - write_additional(ctx, tmp[1:56]) - ctx.nullt = true - } - if ctx.is224 { - write_additional(ctx, {0x00}) - } else { - write_additional(ctx, {0x01}) - } - } - - for i : uint = 0; i < 8; i += 1 { - tmp[i] = byte(length >> (56 - 8 * i)) - } - write_additional(ctx, tmp[0:8]) - - h := ctx.h[:] - if ctx.is224 { - h = h[0:7] - } - for s, i in h { - hash[i * 4] = byte(s >> 24) - hash[i * 4 + 1] = byte(s >> 16) - hash[i * 4 + 2] = byte(s >> 8) - hash[i * 4 + 3] = byte(s) - } - } else when T == Blake512_Context { - if nx == 111 { - if ctx.is384 { - write_additional(ctx, {0x80}) - } else { - write_additional(ctx, {0x81}) - } - } else { - if nx < 111 { - if nx == 0 { - ctx.nullt = true - } - write_additional(ctx, tmp[0 : 111 - nx]) - } else { - write_additional(ctx, tmp[0 : 128 - nx]) - write_additional(ctx, tmp[1:112]) - ctx.nullt = true - } - if ctx.is384 { - write_additional(ctx, {0x00}) - } else { - write_additional(ctx, {0x01}) - } - } - - for i : uint = 0; i < 16; i += 1 { - tmp[i] = byte(length >> (120 - 8 * i)) - } - write_additional(ctx, tmp[0:16]) - - h := ctx.h[:] - if ctx.is384 { - h = h[0:6] - } - for s, i in h { - hash[i * 8] = byte(s >> 56) - hash[i * 8 + 1] = byte(s >> 48) - hash[i * 8 + 2] = byte(s >> 40) - hash[i * 8 + 3] = byte(s >> 32) - hash[i * 8 + 4] = byte(s >> 24) - hash[i * 8 + 5] = byte(s >> 16) - hash[i * 8 + 6] = byte(s >> 8) - hash[i * 8 + 7] = byte(s) - } - } -} - -SIZE_224 :: 28 -SIZE_256 :: 32 -SIZE_384 :: 48 -SIZE_512 :: 64 -BLOCKSIZE_256 :: 64 -BLOCKSIZE_512 :: 128 - -Blake256_Context :: struct { - h: [8]u32, - s: [4]u32, - t: u64, - x: [64]byte, - nx: int, - is224: bool, - nullt: bool, -} - -Blake512_Context :: struct { - h: [8]u64, - s: [4]u64, - t: u64, - x: [128]byte, - nx: int, - is384: bool, - nullt: bool, -} - -SIGMA := [?]int { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, - 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, - 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, - 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, -} - -U256 := [16]u32 { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, -} - -U512 := [16]u64 { - 0x243f6a8885a308d3, 0x13198a2e03707344, 0xa4093822299f31d0, 0x082efa98ec4e6c89, - 0x452821e638d01377, 0xbe5466cf34e90c6c, 0xc0ac29b7c97c50dd, 0x3f84d5b5b5470917, - 0x9216d5d98979fb1b, 0xd1310ba698dfb5ac, 0x2ffd72dbd01adfb7, 0xb8e1afed6a267e96, - 0xba7c9045f12c7f99, 0x24a19947b3916cf7, 0x0801f2e2858efc16, 0x636920d871574e69, -} - -G256 :: #force_inline proc "contextless" (a, b, c, d: u32, m: [16]u32, i, j: int) -> (u32, u32, u32, u32) { - a, b, c, d := a, b, c, d - a += m[SIGMA[(i % 10) * 16 + (2 * j)]] ~ U256[SIGMA[(i % 10) * 16 + (2 * j + 1)]] - a += b - d ~= a - d = d << (32 - 16) | d >> 16 - c += d - b ~= c - b = b << (32 - 12) | b >> 12 - a += m[SIGMA[(i % 10) * 16 + (2 * j + 1)]] ~ U256[SIGMA[(i % 10) * 16 + (2 * j)]] - a += b - d ~= a - d = d << (32 - 8) | d >> 8 - c += d - b ~= c - b = b << (32 - 7) | b >> 7 - return a, b, c, d -} - -G512 :: #force_inline proc "contextless" (a, b, c, d: u64, m: [16]u64, i, j: int) -> (u64, u64, u64, u64) { - a, b, c, d := a, b, c, d - a += m[SIGMA[(i % 10) * 16 + (2 * j)]] ~ U512[SIGMA[(i % 10) * 16 + (2 * j + 1)]] - a += b - d ~= a - d = d << (64 - 32) | d >> 32 - c += d - b ~= c - b = b << (64 - 25) | b >> 25 - a += m[SIGMA[(i % 10) * 16 + (2 * j + 1)]] ~ U512[SIGMA[(i % 10) * 16 + (2 * j)]] - a += b - d ~= a - d = d << (64 - 16) | d >> 16 - c += d - b ~= c - b = b << (64 - 11) | b >> 11 - return a, b, c, d -} - -block256 :: proc "contextless" (ctx: ^Blake256_Context, p: []byte) #no_bounds_check { - i, j: int = ---, --- - v, m: [16]u32 = ---, --- - p := p - for len(p) >= BLOCKSIZE_256 { - v[0] = ctx.h[0] - v[1] = ctx.h[1] - v[2] = ctx.h[2] - v[3] = ctx.h[3] - v[4] = ctx.h[4] - v[5] = ctx.h[5] - v[6] = ctx.h[6] - v[7] = ctx.h[7] - v[8] = ctx.s[0] ~ U256[0] - v[9] = ctx.s[1] ~ U256[1] - v[10] = ctx.s[2] ~ U256[2] - v[11] = ctx.s[3] ~ U256[3] - v[12] = U256[4] - v[13] = U256[5] - v[14] = U256[6] - v[15] = U256[7] - - ctx.t += 512 - if !ctx.nullt { - v[12] ~= u32(ctx.t) - v[13] ~= u32(ctx.t) - v[14] ~= u32(ctx.t >> 32) - v[15] ~= u32(ctx.t >> 32) - } - - for i, j = 0, 0; i < 16; i, j = i+1, j+4 { - m[i] = u32(p[j]) << 24 | u32(p[j + 1]) << 16 | u32(p[j + 2]) << 8 | u32(p[j + 3]) - } - - for i = 0; i < 14; i += 1 { - v[0], v[4], v[8], v[12] = G256(v[0], v[4], v[8], v[12], m, i, 0) - v[1], v[5], v[9], v[13] = G256(v[1], v[5], v[9], v[13], m, i, 1) - v[2], v[6], v[10], v[14] = G256(v[2], v[6], v[10], v[14], m, i, 2) - v[3], v[7], v[11], v[15] = G256(v[3], v[7], v[11], v[15], m, i, 3) - v[0], v[5], v[10], v[15] = G256(v[0], v[5], v[10], v[15], m, i, 4) - v[1], v[6], v[11], v[12] = G256(v[1], v[6], v[11], v[12], m, i, 5) - v[2], v[7], v[8], v[13] = G256(v[2], v[7], v[8], v[13], m, i, 6) - v[3], v[4], v[9], v[14] = G256(v[3], v[4], v[9], v[14], m, i, 7) - } - - for i = 0; i < 8; i += 1 { - ctx.h[i] ~= ctx.s[i % 4] ~ v[i] ~ v[i + 8] - } - p = p[BLOCKSIZE_256:] - } -} - -block512 :: proc "contextless" (ctx: ^Blake512_Context, p: []byte) #no_bounds_check { - i, j: int = ---, --- - v, m: [16]u64 = ---, --- - p := p - for len(p) >= BLOCKSIZE_512 { - v[0] = ctx.h[0] - v[1] = ctx.h[1] - v[2] = ctx.h[2] - v[3] = ctx.h[3] - v[4] = ctx.h[4] - v[5] = ctx.h[5] - v[6] = ctx.h[6] - v[7] = ctx.h[7] - v[8] = ctx.s[0] ~ U512[0] - v[9] = ctx.s[1] ~ U512[1] - v[10] = ctx.s[2] ~ U512[2] - v[11] = ctx.s[3] ~ U512[3] - v[12] = U512[4] - v[13] = U512[5] - v[14] = U512[6] - v[15] = U512[7] - - ctx.t += 1024 - if !ctx.nullt { - v[12] ~= ctx.t - v[13] ~= ctx.t - v[14] ~= 0 - v[15] ~= 0 - } - - for i, j = 0, 0; i < 16; i, j = i + 1, j + 8 { - m[i] = u64(p[j]) << 56 | u64(p[j + 1]) << 48 | u64(p[j + 2]) << 40 | u64(p[j + 3]) << 32 | - u64(p[j + 4]) << 24 | u64(p[j + 5]) << 16 | u64(p[j + 6]) << 8 | u64(p[j + 7]) - } - for i = 0; i < 16; i += 1 { - v[0], v[4], v[8], v[12] = G512(v[0], v[4], v[8], v[12], m, i, 0) - v[1], v[5], v[9], v[13] = G512(v[1], v[5], v[9], v[13], m, i, 1) - v[2], v[6], v[10], v[14] = G512(v[2], v[6], v[10], v[14], m, i, 2) - v[3], v[7], v[11], v[15] = G512(v[3], v[7], v[11], v[15], m, i, 3) - v[0], v[5], v[10], v[15] = G512(v[0], v[5], v[10], v[15], m, i, 4) - v[1], v[6], v[11], v[12] = G512(v[1], v[6], v[11], v[12], m, i, 5) - v[2], v[7], v[8], v[13] = G512(v[2], v[7], v[8], v[13], m, i, 6) - v[3], v[4], v[9], v[14] = G512(v[3], v[4], v[9], v[14], m, i, 7) - } - - for i = 0; i < 8; i += 1 { - ctx.h[i] ~= ctx.s[i % 4] ~ v[i] ~ v[i + 8] - } - p = p[BLOCKSIZE_512:] - } -} - -write_additional :: proc "contextless" (ctx: ^$T, data: []byte) { - ctx.t -= u64(len(data)) << 3 - update(ctx, data) -} diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin index 8f0770f82..17657311e 100644 --- a/core/crypto/blake2b/blake2b.odin +++ b/core/crypto/blake2b/blake2b.odin @@ -7,12 +7,12 @@ package blake2b List of contributors: zhibog, dotbmp: Initial implementation. - Interface for the BLAKE2B hashing algorithm. - BLAKE2B and BLAKE2B share the implementation in the _blake2 package. + Interface for the BLAKE2b hashing algorithm. + BLAKE2b and BLAKE2s share the implementation in the _blake2 package. */ -import "core:os" import "core:io" +import "core:os" import "../_blake2" @@ -25,103 +25,103 @@ DIGEST_SIZE :: 64 // hash_string will hash the given input and return the // computed hash hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) + return hash_bytes(transmute([]byte)(data)) } // hash_bytes will hash the given input and return the // computed hash hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: _blake2.Blake2b_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2B_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - _blake2.update(&ctx, data) - _blake2.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE]byte + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2B_SIZE + ctx.cfg = cfg + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: _blake2.Blake2b_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2B_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - _blake2.update(&ctx, data) - _blake2.final(&ctx, hash) + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2B_SIZE + ctx.cfg = cfg + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } - // hash_stream will read the stream in chunks and compute a // hash from its contents hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: _blake2.Blake2b_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2B_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _blake2.update(&ctx, buf[:read]) - } - } - _blake2.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE]byte + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2B_SIZE + ctx.cfg = cfg + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file will read the file provided by the given handle // and compute a hash hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false + if !load_at_once { + return hash_stream(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes(buf[:]), ok + } + } + return [DIGEST_SIZE]byte{}, false } hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, + hash_stream, + hash_file, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, } /* Low level API */ -Blake2b_Context :: _blake2.Blake2b_Context +Context :: _blake2.Blake2b_Context -init :: proc(ctx: ^_blake2.Blake2b_Context) { - _blake2.init(ctx) +init :: proc(ctx: ^Context) { + _blake2.init(ctx) } -update :: proc "contextless" (ctx: ^_blake2.Blake2b_Context, data: []byte) { - _blake2.update(ctx, data) +update :: proc(ctx: ^Context, data: []byte) { + _blake2.update(ctx, data) } -final :: proc "contextless" (ctx: ^_blake2.Blake2b_Context, hash: []byte) { - _blake2.final(ctx, hash) +final :: proc(ctx: ^Context, hash: []byte) { + _blake2.final(ctx, hash) } diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin index 6a2d4ab9b..2da619bb8 100644 --- a/core/crypto/blake2s/blake2s.odin +++ b/core/crypto/blake2s/blake2s.odin @@ -7,12 +7,12 @@ package blake2s List of contributors: zhibog, dotbmp: Initial implementation. - Interface for the BLAKE2S hashing algorithm. - BLAKE2B and BLAKE2B share the implementation in the _blake2 package. + Interface for the BLAKE2s hashing algorithm. + BLAKE2s and BLAKE2b share the implementation in the _blake2 package. */ -import "core:os" import "core:io" +import "core:os" import "../_blake2" @@ -25,103 +25,103 @@ DIGEST_SIZE :: 32 // hash_string will hash the given input and return the // computed hash hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) + return hash_bytes(transmute([]byte)(data)) } // hash_bytes will hash the given input and return the // computed hash hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: _blake2.Blake2s_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2S_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - _blake2.update(&ctx, data) - _blake2.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE]byte + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2S_SIZE + ctx.cfg = cfg + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } - // hash_string_to_buffer will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: _blake2.Blake2s_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2S_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - _blake2.update(&ctx, data) - _blake2.final(&ctx, hash) + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2S_SIZE + ctx.cfg = cfg + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream will read the stream in chunks and compute a // hash from its contents hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: _blake2.Blake2s_Context - cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2S_SIZE - ctx.cfg = cfg - _blake2.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _blake2.update(&ctx, buf[:read]) - } - } - _blake2.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE]byte + ctx: Context + cfg: _blake2.Blake2_Config + cfg.size = _blake2.BLAKE2S_SIZE + ctx.cfg = cfg + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file will read the file provided by the given handle // and compute a hash hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false + if !load_at_once { + return hash_stream(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes(buf[:]), ok + } + } + return [DIGEST_SIZE]byte{}, false } hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, + hash_stream, + hash_file, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, } /* Low level API */ -Blake2s_Context :: _blake2.Blake2b_Context +Context :: _blake2.Blake2s_Context -init :: proc(ctx: ^_blake2.Blake2s_Context) { - _blake2.init(ctx) +init :: proc(ctx: ^Context) { + _blake2.init(ctx) } -update :: proc "contextless" (ctx: ^_blake2.Blake2s_Context, data: []byte) { - _blake2.update(ctx, data) +update :: proc(ctx: ^Context, data: []byte) { + _blake2.update(ctx, data) } -final :: proc "contextless" (ctx: ^_blake2.Blake2s_Context, hash: []byte) { - _blake2.final(ctx, hash) +final :: proc(ctx: ^Context, hash: []byte) { + _blake2.final(ctx, hash) } diff --git a/core/crypto/chacha20/chacha20.odin b/core/crypto/chacha20/chacha20.odin index b29dc1228..43b3303c2 100644 --- a/core/crypto/chacha20/chacha20.odin +++ b/core/crypto/chacha20/chacha20.odin @@ -1,6 +1,6 @@ package chacha20 -import "core:crypto/util" +import "core:encoding/endian" import "core:math/bits" import "core:mem" @@ -60,23 +60,23 @@ init :: proc (ctx: ^Context, key, nonce: []byte) { ctx._s[1] = _SIGMA_1 ctx._s[2] = _SIGMA_2 ctx._s[3] = _SIGMA_3 - ctx._s[4] = util.U32_LE(k[0:4]) - ctx._s[5] = util.U32_LE(k[4:8]) - ctx._s[6] = util.U32_LE(k[8:12]) - ctx._s[7] = util.U32_LE(k[12:16]) - ctx._s[8] = util.U32_LE(k[16:20]) - ctx._s[9] = util.U32_LE(k[20:24]) - ctx._s[10] = util.U32_LE(k[24:28]) - ctx._s[11] = util.U32_LE(k[28:32]) + ctx._s[4] = endian.unchecked_get_u32le(k[0:4]) + ctx._s[5] = endian.unchecked_get_u32le(k[4:8]) + ctx._s[6] = endian.unchecked_get_u32le(k[8:12]) + ctx._s[7] = endian.unchecked_get_u32le(k[12:16]) + ctx._s[8] = endian.unchecked_get_u32le(k[16:20]) + ctx._s[9] = endian.unchecked_get_u32le(k[20:24]) + ctx._s[10] = endian.unchecked_get_u32le(k[24:28]) + ctx._s[11] = endian.unchecked_get_u32le(k[28:32]) ctx._s[12] = 0 if !is_xchacha { - ctx._s[13] = util.U32_LE(n[0:4]) - ctx._s[14] = util.U32_LE(n[4:8]) - ctx._s[15] = util.U32_LE(n[8:12]) + ctx._s[13] = endian.unchecked_get_u32le(n[0:4]) + ctx._s[14] = endian.unchecked_get_u32le(n[4:8]) + ctx._s[15] = endian.unchecked_get_u32le(n[8:12]) } else { ctx._s[13] = 0 - ctx._s[14] = util.U32_LE(n[0:4]) - ctx._s[15] = util.U32_LE(n[4:8]) + ctx._s[14] = endian.unchecked_get_u32le(n[0:4]) + ctx._s[15] = endian.unchecked_get_u32le(n[4:8]) // The sub-key is stored in the keystream buffer. While // this will be overwritten in most circumstances, explicitly @@ -221,114 +221,114 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) { // quarterround(x, 0, 4, 8, 12) x0 += x4 x12 ~= x0 - x12 = util.ROTL32(x12, 16) + x12 = bits.rotate_left32(x12, 16) x8 += x12 x4 ~= x8 - x4 = util.ROTL32(x4, 12) + x4 = bits.rotate_left32(x4, 12) x0 += x4 x12 ~= x0 - x12 = util.ROTL32(x12, 8) + x12 = bits.rotate_left32(x12, 8) x8 += x12 x4 ~= x8 - x4 = util.ROTL32(x4, 7) + x4 = bits.rotate_left32(x4, 7) // quarterround(x, 1, 5, 9, 13) x1 += x5 x13 ~= x1 - x13 = util.ROTL32(x13, 16) + x13 = bits.rotate_left32(x13, 16) x9 += x13 x5 ~= x9 - x5 = util.ROTL32(x5, 12) + x5 = bits.rotate_left32(x5, 12) x1 += x5 x13 ~= x1 - x13 = util.ROTL32(x13, 8) + x13 = bits.rotate_left32(x13, 8) x9 += x13 x5 ~= x9 - x5 = util.ROTL32(x5, 7) + x5 = bits.rotate_left32(x5, 7) // quarterround(x, 2, 6, 10, 14) x2 += x6 x14 ~= x2 - x14 = util.ROTL32(x14, 16) + x14 = bits.rotate_left32(x14, 16) x10 += x14 x6 ~= x10 - x6 = util.ROTL32(x6, 12) + x6 = bits.rotate_left32(x6, 12) x2 += x6 x14 ~= x2 - x14 = util.ROTL32(x14, 8) + x14 = bits.rotate_left32(x14, 8) x10 += x14 x6 ~= x10 - x6 = util.ROTL32(x6, 7) + x6 = bits.rotate_left32(x6, 7) // quarterround(x, 3, 7, 11, 15) x3 += x7 x15 ~= x3 - x15 = util.ROTL32(x15, 16) + x15 = bits.rotate_left32(x15, 16) x11 += x15 x7 ~= x11 - x7 = util.ROTL32(x7, 12) + x7 = bits.rotate_left32(x7, 12) x3 += x7 x15 ~= x3 - x15 = util.ROTL32(x15, 8) + x15 = bits.rotate_left32(x15, 8) x11 += x15 x7 ~= x11 - x7 = util.ROTL32(x7, 7) + x7 = bits.rotate_left32(x7, 7) // quarterround(x, 0, 5, 10, 15) x0 += x5 x15 ~= x0 - x15 = util.ROTL32(x15, 16) + x15 = bits.rotate_left32(x15, 16) x10 += x15 x5 ~= x10 - x5 = util.ROTL32(x5, 12) + x5 = bits.rotate_left32(x5, 12) x0 += x5 x15 ~= x0 - x15 = util.ROTL32(x15, 8) + x15 = bits.rotate_left32(x15, 8) x10 += x15 x5 ~= x10 - x5 = util.ROTL32(x5, 7) + x5 = bits.rotate_left32(x5, 7) // quarterround(x, 1, 6, 11, 12) x1 += x6 x12 ~= x1 - x12 = util.ROTL32(x12, 16) + x12 = bits.rotate_left32(x12, 16) x11 += x12 x6 ~= x11 - x6 = util.ROTL32(x6, 12) + x6 = bits.rotate_left32(x6, 12) x1 += x6 x12 ~= x1 - x12 = util.ROTL32(x12, 8) + x12 = bits.rotate_left32(x12, 8) x11 += x12 x6 ~= x11 - x6 = util.ROTL32(x6, 7) + x6 = bits.rotate_left32(x6, 7) // quarterround(x, 2, 7, 8, 13) x2 += x7 x13 ~= x2 - x13 = util.ROTL32(x13, 16) + x13 = bits.rotate_left32(x13, 16) x8 += x13 x7 ~= x8 - x7 = util.ROTL32(x7, 12) + x7 = bits.rotate_left32(x7, 12) x2 += x7 x13 ~= x2 - x13 = util.ROTL32(x13, 8) + x13 = bits.rotate_left32(x13, 8) x8 += x13 x7 ~= x8 - x7 = util.ROTL32(x7, 7) + x7 = bits.rotate_left32(x7, 7) // quarterround(x, 3, 4, 9, 14) x3 += x4 x14 ~= x3 - x14 = util.ROTL32(x14, 16) + x14 = bits.rotate_left32(x14, 16) x9 += x14 x4 ~= x9 - x4 = util.ROTL32(x4, 12) + x4 = bits.rotate_left32(x4, 12) x3 += x4 x14 ~= x3 - x14 = util.ROTL32(x14, 8) + x14 = bits.rotate_left32(x14, 8) x9 += x14 x4 ~= x9 - x4 = util.ROTL32(x4, 7) + x4 = bits.rotate_left32(x4, 7) } x0 += _SIGMA_0 @@ -352,93 +352,48 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) { // this is "use vector operations", support for that is currently // a work in progress/to be designed. // - // Until dedicated assembly can be written leverage the fact that - // the callers of this routine ensure that src/dst are valid. + // In the meantime: + // - The caller(s) ensure that src/dst are valid. + // - The compiler knows if the target is picky about alignment. - when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 { - // util.PUT_U32_LE/util.U32_LE are not required on little-endian - // systems that also happen to not be strict about aligned - // memory access. - - dst_p := transmute(^[16]u32)(&dst[0]) + #no_bounds_check { if src != nil { - src_p := transmute(^[16]u32)(&src[0]) - dst_p[0] = src_p[0] ~ x0 - dst_p[1] = src_p[1] ~ x1 - dst_p[2] = src_p[2] ~ x2 - dst_p[3] = src_p[3] ~ x3 - dst_p[4] = src_p[4] ~ x4 - dst_p[5] = src_p[5] ~ x5 - dst_p[6] = src_p[6] ~ x6 - dst_p[7] = src_p[7] ~ x7 - dst_p[8] = src_p[8] ~ x8 - dst_p[9] = src_p[9] ~ x9 - dst_p[10] = src_p[10] ~ x10 - dst_p[11] = src_p[11] ~ x11 - dst_p[12] = src_p[12] ~ x12 - dst_p[13] = src_p[13] ~ x13 - dst_p[14] = src_p[14] ~ x14 - dst_p[15] = src_p[15] ~ x15 + endian.unchecked_put_u32le(dst[0:4], endian.unchecked_get_u32le(src[0:4]) ~ x0) + endian.unchecked_put_u32le(dst[4:8], endian.unchecked_get_u32le(src[4:8]) ~ x1) + endian.unchecked_put_u32le(dst[8:12], endian.unchecked_get_u32le(src[8:12]) ~ x2) + endian.unchecked_put_u32le(dst[12:16], endian.unchecked_get_u32le(src[12:16]) ~ x3) + endian.unchecked_put_u32le(dst[16:20], endian.unchecked_get_u32le(src[16:20]) ~ x4) + endian.unchecked_put_u32le(dst[20:24], endian.unchecked_get_u32le(src[20:24]) ~ x5) + endian.unchecked_put_u32le(dst[24:28], endian.unchecked_get_u32le(src[24:28]) ~ x6) + endian.unchecked_put_u32le(dst[28:32], endian.unchecked_get_u32le(src[28:32]) ~ x7) + endian.unchecked_put_u32le(dst[32:36], endian.unchecked_get_u32le(src[32:36]) ~ x8) + endian.unchecked_put_u32le(dst[36:40], endian.unchecked_get_u32le(src[36:40]) ~ x9) + endian.unchecked_put_u32le(dst[40:44], endian.unchecked_get_u32le(src[40:44]) ~ x10) + endian.unchecked_put_u32le(dst[44:48], endian.unchecked_get_u32le(src[44:48]) ~ x11) + endian.unchecked_put_u32le(dst[48:52], endian.unchecked_get_u32le(src[48:52]) ~ x12) + endian.unchecked_put_u32le(dst[52:56], endian.unchecked_get_u32le(src[52:56]) ~ x13) + endian.unchecked_put_u32le(dst[56:60], endian.unchecked_get_u32le(src[56:60]) ~ x14) + endian.unchecked_put_u32le(dst[60:64], endian.unchecked_get_u32le(src[60:64]) ~ x15) src = src[_BLOCK_SIZE:] } else { - dst_p[0] = x0 - dst_p[1] = x1 - dst_p[2] = x2 - dst_p[3] = x3 - dst_p[4] = x4 - dst_p[5] = x5 - dst_p[6] = x6 - dst_p[7] = x7 - dst_p[8] = x8 - dst_p[9] = x9 - dst_p[10] = x10 - dst_p[11] = x11 - dst_p[12] = x12 - dst_p[13] = x13 - dst_p[14] = x14 - dst_p[15] = x15 + endian.unchecked_put_u32le(dst[0:4], x0) + endian.unchecked_put_u32le(dst[4:8], x1) + endian.unchecked_put_u32le(dst[8:12], x2) + endian.unchecked_put_u32le(dst[12:16], x3) + endian.unchecked_put_u32le(dst[16:20], x4) + endian.unchecked_put_u32le(dst[20:24], x5) + endian.unchecked_put_u32le(dst[24:28], x6) + endian.unchecked_put_u32le(dst[28:32], x7) + endian.unchecked_put_u32le(dst[32:36], x8) + endian.unchecked_put_u32le(dst[36:40], x9) + endian.unchecked_put_u32le(dst[40:44], x10) + endian.unchecked_put_u32le(dst[44:48], x11) + endian.unchecked_put_u32le(dst[48:52], x12) + endian.unchecked_put_u32le(dst[52:56], x13) + endian.unchecked_put_u32le(dst[56:60], x14) + endian.unchecked_put_u32le(dst[60:64], x15) } dst = dst[_BLOCK_SIZE:] - } else { - #no_bounds_check { - if src != nil { - util.PUT_U32_LE(dst[0:4], util.U32_LE(src[0:4]) ~ x0) - util.PUT_U32_LE(dst[4:8], util.U32_LE(src[4:8]) ~ x1) - util.PUT_U32_LE(dst[8:12], util.U32_LE(src[8:12]) ~ x2) - util.PUT_U32_LE(dst[12:16], util.U32_LE(src[12:16]) ~ x3) - util.PUT_U32_LE(dst[16:20], util.U32_LE(src[16:20]) ~ x4) - util.PUT_U32_LE(dst[20:24], util.U32_LE(src[20:24]) ~ x5) - util.PUT_U32_LE(dst[24:28], util.U32_LE(src[24:28]) ~ x6) - util.PUT_U32_LE(dst[28:32], util.U32_LE(src[28:32]) ~ x7) - util.PUT_U32_LE(dst[32:36], util.U32_LE(src[32:36]) ~ x8) - util.PUT_U32_LE(dst[36:40], util.U32_LE(src[36:40]) ~ x9) - util.PUT_U32_LE(dst[40:44], util.U32_LE(src[40:44]) ~ x10) - util.PUT_U32_LE(dst[44:48], util.U32_LE(src[44:48]) ~ x11) - util.PUT_U32_LE(dst[48:52], util.U32_LE(src[48:52]) ~ x12) - util.PUT_U32_LE(dst[52:56], util.U32_LE(src[52:56]) ~ x13) - util.PUT_U32_LE(dst[56:60], util.U32_LE(src[56:60]) ~ x14) - util.PUT_U32_LE(dst[60:64], util.U32_LE(src[60:64]) ~ x15) - src = src[_BLOCK_SIZE:] - } else { - util.PUT_U32_LE(dst[0:4], x0) - util.PUT_U32_LE(dst[4:8], x1) - util.PUT_U32_LE(dst[8:12], x2) - util.PUT_U32_LE(dst[12:16], x3) - util.PUT_U32_LE(dst[16:20], x4) - util.PUT_U32_LE(dst[20:24], x5) - util.PUT_U32_LE(dst[24:28], x6) - util.PUT_U32_LE(dst[28:32], x7) - util.PUT_U32_LE(dst[32:36], x8) - util.PUT_U32_LE(dst[36:40], x9) - util.PUT_U32_LE(dst[40:44], x10) - util.PUT_U32_LE(dst[44:48], x11) - util.PUT_U32_LE(dst[48:52], x12) - util.PUT_U32_LE(dst[52:56], x13) - util.PUT_U32_LE(dst[56:60], x14) - util.PUT_U32_LE(dst[60:64], x15) - } - dst = dst[_BLOCK_SIZE:] - } } // Increment the counter. Overflow checking is done upon @@ -451,141 +406,141 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) { } @(private) -_hchacha20 :: proc (dst, key, nonce: []byte) { +_hchacha20 :: proc "contextless" (dst, key, nonce: []byte) { x0, x1, x2, x3 := _SIGMA_0, _SIGMA_1, _SIGMA_2, _SIGMA_3 - x4 := util.U32_LE(key[0:4]) - x5 := util.U32_LE(key[4:8]) - x6 := util.U32_LE(key[8:12]) - x7 := util.U32_LE(key[12:16]) - x8 := util.U32_LE(key[16:20]) - x9 := util.U32_LE(key[20:24]) - x10 := util.U32_LE(key[24:28]) - x11 := util.U32_LE(key[28:32]) - x12 := util.U32_LE(nonce[0:4]) - x13 := util.U32_LE(nonce[4:8]) - x14 := util.U32_LE(nonce[8:12]) - x15 := util.U32_LE(nonce[12:16]) + x4 := endian.unchecked_get_u32le(key[0:4]) + x5 := endian.unchecked_get_u32le(key[4:8]) + x6 := endian.unchecked_get_u32le(key[8:12]) + x7 := endian.unchecked_get_u32le(key[12:16]) + x8 := endian.unchecked_get_u32le(key[16:20]) + x9 := endian.unchecked_get_u32le(key[20:24]) + x10 := endian.unchecked_get_u32le(key[24:28]) + x11 := endian.unchecked_get_u32le(key[28:32]) + x12 := endian.unchecked_get_u32le(nonce[0:4]) + x13 := endian.unchecked_get_u32le(nonce[4:8]) + x14 := endian.unchecked_get_u32le(nonce[8:12]) + x15 := endian.unchecked_get_u32le(nonce[12:16]) for i := _ROUNDS; i > 0; i = i - 2 { // quarterround(x, 0, 4, 8, 12) x0 += x4 x12 ~= x0 - x12 = util.ROTL32(x12, 16) + x12 = bits.rotate_left32(x12, 16) x8 += x12 x4 ~= x8 - x4 = util.ROTL32(x4, 12) + x4 = bits.rotate_left32(x4, 12) x0 += x4 x12 ~= x0 - x12 = util.ROTL32(x12, 8) + x12 = bits.rotate_left32(x12, 8) x8 += x12 x4 ~= x8 - x4 = util.ROTL32(x4, 7) + x4 = bits.rotate_left32(x4, 7) // quarterround(x, 1, 5, 9, 13) x1 += x5 x13 ~= x1 - x13 = util.ROTL32(x13, 16) + x13 = bits.rotate_left32(x13, 16) x9 += x13 x5 ~= x9 - x5 = util.ROTL32(x5, 12) + x5 = bits.rotate_left32(x5, 12) x1 += x5 x13 ~= x1 - x13 = util.ROTL32(x13, 8) + x13 = bits.rotate_left32(x13, 8) x9 += x13 x5 ~= x9 - x5 = util.ROTL32(x5, 7) + x5 = bits.rotate_left32(x5, 7) // quarterround(x, 2, 6, 10, 14) x2 += x6 x14 ~= x2 - x14 = util.ROTL32(x14, 16) + x14 = bits.rotate_left32(x14, 16) x10 += x14 x6 ~= x10 - x6 = util.ROTL32(x6, 12) + x6 = bits.rotate_left32(x6, 12) x2 += x6 x14 ~= x2 - x14 = util.ROTL32(x14, 8) + x14 = bits.rotate_left32(x14, 8) x10 += x14 x6 ~= x10 - x6 = util.ROTL32(x6, 7) + x6 = bits.rotate_left32(x6, 7) // quarterround(x, 3, 7, 11, 15) x3 += x7 x15 ~= x3 - x15 = util.ROTL32(x15, 16) + x15 = bits.rotate_left32(x15, 16) x11 += x15 x7 ~= x11 - x7 = util.ROTL32(x7, 12) + x7 = bits.rotate_left32(x7, 12) x3 += x7 x15 ~= x3 - x15 = util.ROTL32(x15, 8) + x15 = bits.rotate_left32(x15, 8) x11 += x15 x7 ~= x11 - x7 = util.ROTL32(x7, 7) + x7 = bits.rotate_left32(x7, 7) // quarterround(x, 0, 5, 10, 15) x0 += x5 x15 ~= x0 - x15 = util.ROTL32(x15, 16) + x15 = bits.rotate_left32(x15, 16) x10 += x15 x5 ~= x10 - x5 = util.ROTL32(x5, 12) + x5 = bits.rotate_left32(x5, 12) x0 += x5 x15 ~= x0 - x15 = util.ROTL32(x15, 8) + x15 = bits.rotate_left32(x15, 8) x10 += x15 x5 ~= x10 - x5 = util.ROTL32(x5, 7) + x5 = bits.rotate_left32(x5, 7) // quarterround(x, 1, 6, 11, 12) x1 += x6 x12 ~= x1 - x12 = util.ROTL32(x12, 16) + x12 = bits.rotate_left32(x12, 16) x11 += x12 x6 ~= x11 - x6 = util.ROTL32(x6, 12) + x6 = bits.rotate_left32(x6, 12) x1 += x6 x12 ~= x1 - x12 = util.ROTL32(x12, 8) + x12 = bits.rotate_left32(x12, 8) x11 += x12 x6 ~= x11 - x6 = util.ROTL32(x6, 7) + x6 = bits.rotate_left32(x6, 7) // quarterround(x, 2, 7, 8, 13) x2 += x7 x13 ~= x2 - x13 = util.ROTL32(x13, 16) + x13 = bits.rotate_left32(x13, 16) x8 += x13 x7 ~= x8 - x7 = util.ROTL32(x7, 12) + x7 = bits.rotate_left32(x7, 12) x2 += x7 x13 ~= x2 - x13 = util.ROTL32(x13, 8) + x13 = bits.rotate_left32(x13, 8) x8 += x13 x7 ~= x8 - x7 = util.ROTL32(x7, 7) + x7 = bits.rotate_left32(x7, 7) // quarterround(x, 3, 4, 9, 14) x3 += x4 x14 ~= x3 - x14 = util.ROTL32(x14, 16) + x14 = bits.rotate_left32(x14, 16) x9 += x14 x4 ~= x9 - x4 = util.ROTL32(x4, 12) + x4 = bits.rotate_left32(x4, 12) x3 += x4 x14 ~= x3 - x14 = util.ROTL32(x14, 8) + x14 = bits.rotate_left32(x14, 8) x9 += x14 x4 ~= x9 - x4 = util.ROTL32(x4, 7) + x4 = bits.rotate_left32(x4, 7) } - util.PUT_U32_LE(dst[0:4], x0) - util.PUT_U32_LE(dst[4:8], x1) - util.PUT_U32_LE(dst[8:12], x2) - util.PUT_U32_LE(dst[12:16], x3) - util.PUT_U32_LE(dst[16:20], x12) - util.PUT_U32_LE(dst[20:24], x13) - util.PUT_U32_LE(dst[24:28], x14) - util.PUT_U32_LE(dst[28:32], x15) + endian.unchecked_put_u32le(dst[0:4], x0) + endian.unchecked_put_u32le(dst[4:8], x1) + endian.unchecked_put_u32le(dst[8:12], x2) + endian.unchecked_put_u32le(dst[12:16], x3) + endian.unchecked_put_u32le(dst[16:20], x12) + endian.unchecked_put_u32le(dst[20:24], x13) + endian.unchecked_put_u32le(dst[24:28], x14) + endian.unchecked_put_u32le(dst[28:32], x15) } diff --git a/core/crypto/chacha20poly1305/chacha20poly1305.odin b/core/crypto/chacha20poly1305/chacha20poly1305.odin index ae395f9e0..86fe54e79 100644 --- a/core/crypto/chacha20poly1305/chacha20poly1305.odin +++ b/core/crypto/chacha20poly1305/chacha20poly1305.odin @@ -3,7 +3,7 @@ package chacha20poly1305 import "core:crypto" import "core:crypto/chacha20" import "core:crypto/poly1305" -import "core:crypto/util" +import "core:encoding/endian" import "core:mem" KEY_SIZE :: chacha20.KEY_SIZE @@ -87,8 +87,8 @@ encrypt :: proc (ciphertext, tag, key, nonce, aad, plaintext: []byte) { // mac_data |= num_to_8_le_bytes(aad.length) // mac_data |= num_to_8_le_bytes(ciphertext.length) l_buf := otk[0:16] // Reuse the scratch buffer. - util.PUT_U64_LE(l_buf[0:8], u64(aad_len)) - util.PUT_U64_LE(l_buf[8:16], u64(ciphertext_len)) + endian.unchecked_put_u64le(l_buf[0:8], u64(aad_len)) + endian.unchecked_put_u64le(l_buf[8:16], u64(ciphertext_len)) poly1305.update(&mac_ctx, l_buf) // tag = poly1305_mac(mac_data, otk) @@ -128,8 +128,8 @@ decrypt :: proc (plaintext, tag, key, nonce, aad, ciphertext: []byte) -> bool { poly1305.update(&mac_ctx, ciphertext) _update_mac_pad16(&mac_ctx, ciphertext_len) l_buf := otk[0:16] // Reuse the scratch buffer. - util.PUT_U64_LE(l_buf[0:8], u64(aad_len)) - util.PUT_U64_LE(l_buf[8:16], u64(ciphertext_len)) + endian.unchecked_put_u64le(l_buf[0:8], u64(aad_len)) + endian.unchecked_put_u64le(l_buf[8:16], u64(ciphertext_len)) poly1305.update(&mac_ctx, l_buf) // tag = poly1305_mac(mac_data, otk) diff --git a/core/crypto/gost/gost.odin b/core/crypto/gost/gost.odin deleted file mode 100644 index 5aca8ce95..000000000 --- a/core/crypto/gost/gost.odin +++ /dev/null @@ -1,382 +0,0 @@ -package gost - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the GOST hashing algorithm, as defined in RFC 5831 -*/ - -import "core:mem" -import "core:os" -import "core:io" - -/* - High level API -*/ - -DIGEST_SIZE :: 32 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Gost_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Gost_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Gost_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -init :: proc "contextless" (ctx: ^Gost_Context) { - sbox: [8][16]u32 = { - { 10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15 }, - { 5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8 }, - { 7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13 }, - { 4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3 }, - { 7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5 }, - { 7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3 }, - { 13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11 }, - { 1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12 }, - } - - i := 0 - for a := 0; a < 16; a += 1 { - ax := sbox[1][a] << 15 - bx := sbox[3][a] << 23 - cx := sbox[5][a] - cx = (cx >> 1) | (cx << 31) - dx := sbox[7][a] << 7 - for b := 0; b < 16; b, i = b + 1, i + 1 { - SBOX_1[i] = ax | (sbox[0][b] << 11) - SBOX_2[i] = bx | (sbox[2][b] << 19) - SBOX_3[i] = cx | (sbox[4][b] << 27) - SBOX_4[i] = dx | (sbox[6][b] << 3) - } - } -} - -update :: proc(ctx: ^Gost_Context, data: []byte) { - length := byte(len(data)) - j: byte - - i := ctx.partial_bytes - for i < 32 && j < length { - ctx.partial[i] = data[j] - i, j = i + 1, j + 1 - } - - if i < 32 { - ctx.partial_bytes = i - return - } - bytes(ctx, ctx.partial[:], 256) - - for (j + 32) < length { - bytes(ctx, data[j:], 256) - j += 32 - } - - i = 0 - for j < length { - ctx.partial[i] = data[j] - i, j = i + 1, j + 1 - } - ctx.partial_bytes = i -} - -final :: proc(ctx: ^Gost_Context, hash: []byte) { - if ctx.partial_bytes > 0 { - mem.set(&ctx.partial[ctx.partial_bytes], 0, 32 - int(ctx.partial_bytes)) - bytes(ctx, ctx.partial[:], u32(ctx.partial_bytes) << 3) - } - - compress(ctx.hash[:], ctx.len[:]) - compress(ctx.hash[:], ctx.sum[:]) - - for i, j := 0, 0; i < 8; i, j = i + 1, j + 4 { - hash[j] = byte(ctx.hash[i]) - hash[j + 1] = byte(ctx.hash[i] >> 8) - hash[j + 2] = byte(ctx.hash[i] >> 16) - hash[j + 3] = byte(ctx.hash[i] >> 24) - } -} - -/* - GOST implementation -*/ - -Gost_Context :: struct { - sum: [8]u32, - hash: [8]u32, - len: [8]u32, - partial: [32]byte, - partial_bytes: byte, -} - -SBOX_1: [256]u32 -SBOX_2: [256]u32 -SBOX_3: [256]u32 -SBOX_4: [256]u32 - -ENCRYPT_ROUND :: #force_inline proc "contextless" (l, r, t, k1, k2: u32) -> (u32, u32, u32) { - l, r, t := l, r, t - t = (k1) + r - l ~= SBOX_1[t & 0xff] ~ SBOX_2[(t >> 8) & 0xff] ~ SBOX_3[(t >> 16) & 0xff] ~ SBOX_4[t >> 24] - t = (k2) + l - r ~= SBOX_1[t & 0xff] ~ SBOX_2[(t >> 8) & 0xff] ~ SBOX_3[(t >> 16) & 0xff] ~ SBOX_4[t >> 24] - return l, r, t -} - -ENCRYPT :: #force_inline proc "contextless" (a, b, c: u32, key: []u32) -> (l, r, t: u32) { - l, r, t = ENCRYPT_ROUND(a, b, c, key[0], key[1]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[2], key[3]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[4], key[5]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[6], key[7]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[0], key[1]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[2], key[3]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[4], key[5]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[6], key[7]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[0], key[1]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[2], key[3]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[4], key[5]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[6], key[7]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[7], key[6]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[5], key[4]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[3], key[2]) - l, r, t = ENCRYPT_ROUND(l, r, t, key[1], key[0]) - t = r - r = l - l = t - return -} - -bytes :: proc(ctx: ^Gost_Context, buf: []byte, bits: u32) { - a, c: u32 - m: [8]u32 - - for i, j := 0, 0; i < 8; i += 1 { - a = u32(buf[j]) | u32(buf[j + 1]) << 8 | u32(buf[j + 2]) << 16 | u32(buf[j + 3]) << 24 - j += 4 - m[i] = a - c = a + c + ctx.sum[i] - ctx.sum[i] = c - c = c < a ? 1 : 0 - } - - compress(ctx.hash[:], m[:]) - ctx.len[0] += bits - if ctx.len[0] < bits { - ctx.len[1] += 1 - } -} - -compress :: proc(h, m: []u32) { - key, u, v, w, s: [8]u32 - - copy(u[:], h) - copy(v[:], m) - - for i := 0; i < 8; i += 2 { - w[0] = u[0] ~ v[0] - w[1] = u[1] ~ v[1] - w[2] = u[2] ~ v[2] - w[3] = u[3] ~ v[3] - w[4] = u[4] ~ v[4] - w[5] = u[5] ~ v[5] - w[6] = u[6] ~ v[6] - w[7] = u[7] ~ v[7] - - key[0] = (w[0] & 0x000000ff) | (w[2] & 0x000000ff) << 8 | (w[4] & 0x000000ff) << 16 | (w[6] & 0x000000ff) << 24 - key[1] = (w[0] & 0x0000ff00) >> 8 | (w[2] & 0x0000ff00) | (w[4] & 0x0000ff00) << 8 | (w[6] & 0x0000ff00) << 16 - key[2] = (w[0] & 0x00ff0000) >> 16 | (w[2] & 0x00ff0000) >> 8 | (w[4] & 0x00ff0000) | (w[6] & 0x00ff0000) << 8 - key[3] = (w[0] & 0xff000000) >> 24 | (w[2] & 0xff000000) >> 16 | (w[4] & 0xff000000) >> 8 | (w[6] & 0xff000000) - key[4] = (w[1] & 0x000000ff) | (w[3] & 0x000000ff) << 8 | (w[5] & 0x000000ff) << 16 | (w[7] & 0x000000ff) << 24 - key[5] = (w[1] & 0x0000ff00) >> 8 | (w[3] & 0x0000ff00) | (w[5] & 0x0000ff00) << 8 | (w[7] & 0x0000ff00) << 16 - key[6] = (w[1] & 0x00ff0000) >> 16 | (w[3] & 0x00ff0000) >> 8 | (w[5] & 0x00ff0000) | (w[7] & 0x00ff0000) << 8 - key[7] = (w[1] & 0xff000000) >> 24 | (w[3] & 0xff000000) >> 16 | (w[5] & 0xff000000) >> 8 | (w[7] & 0xff000000) - - r := h[i] - l := h[i + 1] - t: u32 - l, r, t = ENCRYPT(l, r, 0, key[:]) - - s[i] = r - s[i + 1] = l - - if i == 6 { - break - } - - l = u[0] ~ u[2] - r = u[1] ~ u[3] - u[0] = u[2] - u[1] = u[3] - u[2] = u[4] - u[3] = u[5] - u[4] = u[6] - u[5] = u[7] - u[6] = l - u[7] = r - - if i == 2 { - u[0] ~= 0xff00ff00 - u[1] ~= 0xff00ff00 - u[2] ~= 0x00ff00ff - u[3] ~= 0x00ff00ff - u[4] ~= 0x00ffff00 - u[5] ~= 0xff0000ff - u[6] ~= 0x000000ff - u[7] ~= 0xff00ffff - } - - l = v[0] - r = v[2] - v[0] = v[4] - v[2] = v[6] - v[4] = l ~ r - v[6] = v[0] ~ r - l = v[1] - r = v[3] - v[1] = v[5] - v[3] = v[7] - v[5] = l ~ r - v[7] = v[1] ~ r - } - - u[0] = m[0] ~ s[6] - u[1] = m[1] ~ s[7] - u[2] = m[2] ~ (s[0] << 16) ~ (s[0] >> 16) ~ (s[0] & 0xffff) ~ - (s[1] & 0xffff) ~ (s[1] >> 16) ~ (s[2] << 16) ~ s[6] ~ (s[6] << 16) ~ - (s[7] & 0xffff0000) ~ (s[7] >> 16) - u[3] = m[3] ~ (s[0] & 0xffff) ~ (s[0] << 16) ~ (s[1] & 0xffff) ~ - (s[1] << 16) ~ (s[1] >> 16) ~ (s[2] << 16) ~ (s[2] >> 16) ~ - (s[3] << 16) ~ s[6] ~ (s[6] << 16) ~ (s[6] >> 16) ~ (s[7] & 0xffff) ~ - (s[7] << 16) ~ (s[7] >> 16) - u[4] = m[4] ~ - (s[0] & 0xffff0000) ~ (s[0] << 16) ~ (s[0] >> 16) ~ - (s[1] & 0xffff0000) ~ (s[1] >> 16) ~ (s[2] << 16) ~ (s[2] >> 16) ~ - (s[3] << 16) ~ (s[3] >> 16) ~ (s[4] << 16) ~ (s[6] << 16) ~ - (s[6] >> 16) ~(s[7] & 0xffff) ~ (s[7] << 16) ~ (s[7] >> 16) - u[5] = m[5] ~ (s[0] << 16) ~ (s[0] >> 16) ~ (s[0] & 0xffff0000) ~ - (s[1] & 0xffff) ~ s[2] ~ (s[2] >> 16) ~ (s[3] << 16) ~ (s[3] >> 16) ~ - (s[4] << 16) ~ (s[4] >> 16) ~ (s[5] << 16) ~ (s[6] << 16) ~ - (s[6] >> 16) ~ (s[7] & 0xffff0000) ~ (s[7] << 16) ~ (s[7] >> 16) - u[6] = m[6] ~ s[0] ~ (s[1] >> 16) ~ (s[2] << 16) ~ s[3] ~ (s[3] >> 16) ~ - (s[4] << 16) ~ (s[4] >> 16) ~ (s[5] << 16) ~ (s[5] >> 16) ~ s[6] ~ - (s[6] << 16) ~ (s[6] >> 16) ~ (s[7] << 16) - u[7] = m[7] ~ (s[0] & 0xffff0000) ~ (s[0] << 16) ~ (s[1] & 0xffff) ~ - (s[1] << 16) ~ (s[2] >> 16) ~ (s[3] << 16) ~ s[4] ~ (s[4] >> 16) ~ - (s[5] << 16) ~ (s[5] >> 16) ~ (s[6] >> 16) ~ (s[7] & 0xffff) ~ - (s[7] << 16) ~ (s[7] >> 16) - - v[0] = h[0] ~ (u[1] << 16) ~ (u[0] >> 16) - v[1] = h[1] ~ (u[2] << 16) ~ (u[1] >> 16) - v[2] = h[2] ~ (u[3] << 16) ~ (u[2] >> 16) - v[3] = h[3] ~ (u[4] << 16) ~ (u[3] >> 16) - v[4] = h[4] ~ (u[5] << 16) ~ (u[4] >> 16) - v[5] = h[5] ~ (u[6] << 16) ~ (u[5] >> 16) - v[6] = h[6] ~ (u[7] << 16) ~ (u[6] >> 16) - v[7] = h[7] ~ (u[0] & 0xffff0000) ~ (u[0] << 16) ~ (u[7] >> 16) ~ (u[1] & 0xffff0000) ~ (u[1] << 16) ~ (u[6] << 16) ~ (u[7] & 0xffff0000) - - h[0] = (v[0] & 0xffff0000) ~ (v[0] << 16) ~ (v[0] >> 16) ~ (v[1] >> 16) ~ - (v[1] & 0xffff0000) ~ (v[2] << 16) ~ (v[3] >> 16) ~ (v[4] << 16) ~ - (v[5] >> 16) ~ v[5] ~ (v[6] >> 16) ~ (v[7] << 16) ~ (v[7] >> 16) ~ - (v[7] & 0xffff) - h[1] = (v[0] << 16) ~ (v[0] >> 16) ~ (v[0] & 0xffff0000) ~ (v[1] & 0xffff) ~ - v[2] ~ (v[2] >> 16) ~ (v[3] << 16) ~ (v[4] >> 16) ~ (v[5] << 16) ~ - (v[6] << 16) ~ v[6] ~ (v[7] & 0xffff0000) ~ (v[7] >> 16) - h[2] = (v[0] & 0xffff) ~ (v[0] << 16) ~ (v[1] << 16) ~ (v[1] >> 16) ~ - (v[1] & 0xffff0000) ~ (v[2] << 16) ~ (v[3] >> 16) ~ v[3] ~ (v[4] << 16) ~ - (v[5] >> 16) ~ v[6] ~ (v[6] >> 16) ~ (v[7] & 0xffff) ~ (v[7] << 16) ~ - (v[7] >> 16) - h[3] = (v[0] << 16) ~ (v[0] >> 16) ~ (v[0] & 0xffff0000) ~ - (v[1] & 0xffff0000) ~ (v[1] >> 16) ~ (v[2] << 16) ~ (v[2] >> 16) ~ v[2] ~ - (v[3] << 16) ~ (v[4] >> 16) ~ v[4] ~ (v[5] << 16) ~ (v[6] << 16) ~ - (v[7] & 0xffff) ~ (v[7] >> 16) - h[4] = (v[0] >> 16) ~ (v[1] << 16) ~ v[1] ~ (v[2] >> 16) ~ v[2] ~ - (v[3] << 16) ~ (v[3] >> 16) ~ v[3] ~ (v[4] << 16) ~ (v[5] >> 16) ~ - v[5] ~ (v[6] << 16) ~ (v[6] >> 16) ~ (v[7] << 16) - h[5] = (v[0] << 16) ~ (v[0] & 0xffff0000) ~ (v[1] << 16) ~ (v[1] >> 16) ~ - (v[1] & 0xffff0000) ~ (v[2] << 16) ~ v[2] ~ (v[3] >> 16) ~ v[3] ~ - (v[4] << 16) ~ (v[4] >> 16) ~ v[4] ~ (v[5] << 16) ~ (v[6] << 16) ~ - (v[6] >> 16) ~ v[6] ~ (v[7] << 16) ~ (v[7] >> 16) ~ (v[7] & 0xffff0000) - h[6] = v[0] ~ v[2] ~ (v[2] >> 16) ~ v[3] ~ (v[3] << 16) ~ v[4] ~ - (v[4] >> 16) ~ (v[5] << 16) ~ (v[5] >> 16) ~ v[5] ~ (v[6] << 16) ~ - (v[6] >> 16) ~ v[6] ~ (v[7] << 16) ~ v[7] - h[7] = v[0] ~ (v[0] >> 16) ~ (v[1] << 16) ~ (v[1] >> 16) ~ (v[2] << 16) ~ - (v[3] >> 16) ~ v[3] ~ (v[4] << 16) ~ v[4] ~ (v[5] >> 16) ~ v[5] ~ - (v[6] << 16) ~ (v[6] >> 16) ~ (v[7] << 16) ~ v[7] -} \ No newline at end of file diff --git a/core/crypto/groestl/groestl.odin b/core/crypto/groestl/groestl.odin deleted file mode 100644 index 61460808f..000000000 --- a/core/crypto/groestl/groestl.odin +++ /dev/null @@ -1,653 +0,0 @@ -package groestl - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the GROESTL hashing algorithm, as defined in -*/ - -import "core:os" -import "core:io" - -/* - High level API -*/ - -DIGEST_SIZE_224 :: 28 -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_384 :: 48 -DIGEST_SIZE_512 :: 64 - -// hash_string_224 will hash the given input and return the -// computed hash -hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) -} - -// hash_bytes_224 will hash the given input and return the -// computed hash -hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Groestl_Context - ctx.hashbitlen = 224 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Groestl_Context - ctx.hashbitlen = 224 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Groestl_Context - ctx.hashbitlen = 224 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224 will read the file provided by the given handle -// and compute a hash -hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, -} - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Groestl_Context - ctx.hashbitlen = 256 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Groestl_Context - ctx.hashbitlen = 256 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Groestl_Context - ctx.hashbitlen = 256 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_384 will hash the given input and return the -// computed hash -hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) -} - -// hash_bytes_384 will hash the given input and return the -// computed hash -hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: Groestl_Context - ctx.hashbitlen = 384 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_384 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_384 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: Groestl_Context - ctx.hashbitlen = 384 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_384 will read the stream in chunks and compute a -// hash from its contents -hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { - hash: [DIGEST_SIZE_384]byte - ctx: Groestl_Context - ctx.hashbitlen = 384 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_384 will read the file provided by the given handle -// and compute a hash -hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false -} - -hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, -} - -// hash_string_512 will hash the given input and return the -// computed hash -hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) -} - -// hash_bytes_512 will hash the given input and return the -// computed hash -hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: Groestl_Context - ctx.hashbitlen = 512 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_512 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_512 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: Groestl_Context - ctx.hashbitlen = 512 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_512 will read the stream in chunks and compute a -// hash from its contents -hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: Groestl_Context - ctx.hashbitlen = 512 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_512 will read the file provided by the given handle -// and compute a hash -hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false -} - -hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Groestl_Context) { - assert(ctx.hashbitlen == 224 || ctx.hashbitlen == 256 || ctx.hashbitlen == 384 || ctx.hashbitlen == 512, "hashbitlen must be set to 224, 256, 384 or 512") - if ctx.hashbitlen <= 256 { - ctx.rounds = 10 - ctx.columns = 8 - ctx.statesize = 64 - } else { - ctx.rounds = 14 - ctx.columns = 16 - ctx.statesize = 128 - } - for i := 8 - size_of(i32); i < 8; i += 1 { - ctx.chaining[i][ctx.columns - 1] = byte(ctx.hashbitlen >> (8 * (7 - uint(i)))) - } -} - -update :: proc(ctx: ^Groestl_Context, data: []byte) { - databitlen := len(data) * 8 - msglen := databitlen / 8 - rem := databitlen % 8 - - i: int - assert(ctx.bits_in_last_byte == 0) - - if ctx.buf_ptr != 0 { - for i = 0; ctx.buf_ptr < ctx.statesize && i < msglen; i, ctx.buf_ptr = i + 1, ctx.buf_ptr + 1 { - ctx.buffer[ctx.buf_ptr] = data[i] - } - - if ctx.buf_ptr < ctx.statesize { - if rem != 0 { - ctx.bits_in_last_byte = rem - ctx.buffer[ctx.buf_ptr] = data[i] - ctx.buf_ptr += 1 - } - return - } - - ctx.buf_ptr = 0 - transform(ctx, ctx.buffer[:], u32(ctx.statesize)) - } - - transform(ctx, data[i:], u32(msglen - i)) - i += ((msglen - i) / ctx.statesize) * ctx.statesize - for i < msglen { - ctx.buffer[ctx.buf_ptr] = data[i] - i, ctx.buf_ptr = i + 1, ctx.buf_ptr + 1 - } - - if rem != 0 { - ctx.bits_in_last_byte = rem - ctx.buffer[ctx.buf_ptr] = data[i] - ctx.buf_ptr += 1 - } -} - -final :: proc(ctx: ^Groestl_Context, hash: []byte) { - hashbytelen := ctx.hashbitlen / 8 - - if ctx.bits_in_last_byte != 0 { - ctx.buffer[ctx.buf_ptr - 1] &= ((1 << uint(ctx.bits_in_last_byte)) - 1) << (8 - uint(ctx.bits_in_last_byte)) - ctx.buffer[ctx.buf_ptr - 1] ~= 0x1 << (7 - uint(ctx.bits_in_last_byte)) - } else { - ctx.buffer[ctx.buf_ptr] = 0x80 - ctx.buf_ptr += 1 - } - - if ctx.buf_ptr > ctx.statesize - 8 { - for ctx.buf_ptr < ctx.statesize { - ctx.buffer[ctx.buf_ptr] = 0 - ctx.buf_ptr += 1 - } - transform(ctx, ctx.buffer[:], u32(ctx.statesize)) - ctx.buf_ptr = 0 - } - - for ctx.buf_ptr < ctx.statesize - 8 { - ctx.buffer[ctx.buf_ptr] = 0 - ctx.buf_ptr += 1 - } - - ctx.block_counter += 1 - ctx.buf_ptr = ctx.statesize - - for ctx.buf_ptr > ctx.statesize - 8 { - ctx.buf_ptr -= 1 - ctx.buffer[ctx.buf_ptr] = byte(ctx.block_counter) - ctx.block_counter >>= 8 - } - - transform(ctx, ctx.buffer[:], u32(ctx.statesize)) - output_transformation(ctx) - - for i, j := ctx.statesize - hashbytelen , 0; i < ctx.statesize; i, j = i + 1, j + 1 { - hash[j] = ctx.chaining[i % 8][i / 8] - } -} - -/* - GROESTL implementation -*/ - -SBOX := [256]byte { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -} - -SHIFT := [2][2][8]int { - {{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6}}, - {{0, 1, 2, 3, 4, 5, 6, 11}, {1, 3, 5, 11, 0, 2, 4, 6}}, -} - -Groestl_Context :: struct { - chaining: [8][16]byte, - block_counter: u64, - hashbitlen: int, - buffer: [128]byte, - buf_ptr: int, - bits_in_last_byte: int, - columns: int, - rounds: int, - statesize: int, -} - -Groestl_Variant :: enum { - P512 = 0, - Q512 = 1, - P1024 = 2, - Q1024 = 3, -} - -MUL2 :: #force_inline proc "contextless"(b: byte) -> byte { - return (b >> 7) != 0 ? (b << 1) ~ 0x1b : (b << 1) -} - -MUL3 :: #force_inline proc "contextless"(b: byte) -> byte { - return MUL2(b) ~ b -} - -MUL4 :: #force_inline proc "contextless"(b: byte) -> byte { - return MUL2(MUL2(b)) -} - -MUL5 :: #force_inline proc "contextless"(b: byte) -> byte { - return MUL4(b) ~ b -} - -MUL6 :: #force_inline proc "contextless"(b: byte) -> byte { - return MUL4(b) ~ MUL2(b) -} - -MUL7 :: #force_inline proc "contextless"(b: byte) -> byte { - return MUL4(b) ~ MUL2(b) ~ b -} - -sub_bytes :: #force_inline proc (x: [][16]byte, columns: int) { - for i := 0; i < 8; i += 1 { - for j := 0; j < columns; j += 1 { - x[i][j] = SBOX[x[i][j]] - } - } -} - -shift_bytes :: #force_inline proc (x: [][16]byte, columns: int, v: Groestl_Variant) { - temp: [16]byte - R := &SHIFT[int(v) / 2][int(v) & 1] - - for i := 0; i < 8; i += 1 { - for j := 0; j < columns; j += 1 { - temp[j] = x[i][(j + R[i]) % columns] - } - for j := 0; j < columns; j += 1 { - x[i][j] = temp[j] - } - } -} - -mix_bytes :: #force_inline proc (x: [][16]byte, columns: int) { - temp: [8]byte - - for i := 0; i < columns; i += 1 { - for j := 0; j < 8; j += 1 { - temp[j] = MUL2(x[(j + 0) % 8][i]) ~ - MUL2(x[(j + 1) % 8][i]) ~ - MUL3(x[(j + 2) % 8][i]) ~ - MUL4(x[(j + 3) % 8][i]) ~ - MUL5(x[(j + 4) % 8][i]) ~ - MUL3(x[(j + 5) % 8][i]) ~ - MUL5(x[(j + 6) % 8][i]) ~ - MUL7(x[(j + 7) % 8][i]) - } - for j := 0; j < 8; j += 1 { - x[j][i] = temp[j] - } - } -} - -p :: #force_inline proc (ctx: ^Groestl_Context, x: [][16]byte) { - v := ctx.columns == 8 ? Groestl_Variant.P512 : Groestl_Variant.P1024 - for i := 0; i < ctx.rounds; i += 1 { - add_roundconstant(x, ctx.columns, byte(i), v) - sub_bytes(x, ctx.columns) - shift_bytes(x, ctx.columns, v) - mix_bytes(x, ctx.columns) - } -} - -q :: #force_inline proc (ctx: ^Groestl_Context, x: [][16]byte) { - v := ctx.columns == 8 ? Groestl_Variant.Q512 : Groestl_Variant.Q1024 - for i := 0; i < ctx.rounds; i += 1 { - add_roundconstant(x, ctx.columns, byte(i), v) - sub_bytes(x, ctx.columns) - shift_bytes(x, ctx.columns, v) - mix_bytes(x, ctx.columns) - } -} - -transform :: proc(ctx: ^Groestl_Context, input: []byte, msglen: u32) { - tmp1, tmp2: [8][16]byte - input, msglen := input, msglen - - for msglen >= u32(ctx.statesize) { - for i := 0; i < 8; i += 1 { - for j := 0; j < ctx.columns; j += 1 { - tmp1[i][j] = ctx.chaining[i][j] ~ input[j * 8 + i] - tmp2[i][j] = input[j * 8 + i] - } - } - - p(ctx, tmp1[:]) - q(ctx, tmp2[:]) - - for i := 0; i < 8; i += 1 { - for j := 0; j < ctx.columns; j += 1 { - ctx.chaining[i][j] ~= tmp1[i][j] ~ tmp2[i][j] - } - } - - ctx.block_counter += 1 - msglen -= u32(ctx.statesize) - input = input[ctx.statesize:] - } -} - -output_transformation :: proc(ctx: ^Groestl_Context) { - temp: [8][16]byte - - for i := 0; i < 8; i += 1 { - for j := 0; j < ctx.columns; j += 1 { - temp[i][j] = ctx.chaining[i][j] - } - } - - p(ctx, temp[:]) - - for i := 0; i < 8; i += 1 { - for j := 0; j < ctx.columns; j += 1 { - ctx.chaining[i][j] ~= temp[i][j] - } - } -} - -add_roundconstant :: proc(x: [][16]byte, columns: int, round: byte, v: Groestl_Variant) { - switch (i32(v) & 1) { - case 0: - for i := 0; i < columns; i += 1 { - x[0][i] ~= byte(i << 4) ~ round - } - case 1: - for i := 0; i < columns; i += 1 { - for j := 0; j < 7; j += 1 { - x[j][i] ~= 0xff - } - } - for i := 0; i < columns; i += 1 { - x[7][i] ~= byte(i << 4) ~ 0xff ~ round - } - } -} diff --git a/core/crypto/haval/haval.odin b/core/crypto/haval/haval.odin deleted file mode 100644 index b98facb33..000000000 --- a/core/crypto/haval/haval.odin +++ /dev/null @@ -1,1814 +0,0 @@ -package haval - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation for the HAVAL hashing algorithm as defined in -*/ - -import "core:mem" -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE_128 :: 16 -DIGEST_SIZE_160 :: 20 -DIGEST_SIZE_192 :: 24 -DIGEST_SIZE_224 :: 28 -DIGEST_SIZE_256 :: 32 - -// hash_string_128_3 will hash the given input and return the -// computed hash -hash_string_128_3 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128_3(transmute([]byte)(data)) -} - -// hash_bytes_128_3 will hash the given input and return the -// computed hash -hash_bytes_128_3 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128_3 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128_3 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128_3 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128_3 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_128_3 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 3 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128_3 will read the file provided by the given handle -// and compute a hash -hash_file_128_3 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128_3(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128_3(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128_3 :: proc { - hash_stream_128_3, - hash_file_128_3, - hash_bytes_128_3, - hash_string_128_3, - hash_bytes_to_buffer_128_3, - hash_string_to_buffer_128_3, -} - -// hash_string_128_4 will hash the given input and return the -// computed hash -hash_string_128_4 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128_4(transmute([]byte)(data)) -} - -// hash_bytes_128_4 will hash the given input and return the -// computed hash -hash_bytes_128_4 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128_4 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128_4 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128_4 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128_4 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_128_4 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 4 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128_4 will read the file provided by the given handle -// and compute a hash -hash_file_128_4 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128_4(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128_4(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128_4 :: proc { - hash_stream_128_4, - hash_file_128_4, - hash_bytes_128_4, - hash_string_128_4, - hash_bytes_to_buffer_128_4, - hash_string_to_buffer_128_4, -} - -// hash_string_128_5 will hash the given input and return the -// computed hash -hash_string_128_5 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128_5(transmute([]byte)(data)) -} - -// hash_bytes_128_5 will hash the given input and return the -// computed hash -hash_bytes_128_5 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128_5 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128_5 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128_5 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128_5 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_128_5 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: Haval_Context - ctx.hashbitlen = 128 - ctx.rounds = 5 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128_5 will read the file provided by the given handle -// and compute a hash -hash_file_128_5 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128_5(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128_5(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128_5 :: proc { - hash_stream_128_5, - hash_file_128_5, - hash_bytes_128_5, - hash_string_128_5, - hash_bytes_to_buffer_128_5, - hash_string_to_buffer_128_5, -} - -// hash_string_160_3 will hash the given input and return the -// computed hash -hash_string_160_3 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160_3(transmute([]byte)(data)) -} - -// hash_bytes_160_3 will hash the given input and return the -// computed hash -hash_bytes_160_3 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160_3 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160_3 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160_3 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160_3 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_160_3 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 3 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160_3 will read the file provided by the given handle -// and compute a hash -hash_file_160_3 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160_3(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160_3(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160_3 :: proc { - hash_stream_160_3, - hash_file_160_3, - hash_bytes_160_3, - hash_string_160_3, - hash_bytes_to_buffer_160_3, - hash_string_to_buffer_160_3, -} - -// hash_string_160_4 will hash the given input and return the -// computed hash -hash_string_160_4 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160_4(transmute([]byte)(data)) -} - -// hash_bytes_160_4 will hash the given input and return the -// computed hash -hash_bytes_160_4 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160_4 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160_4 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160_4 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160_4 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_160_4 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 4 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160_4 will read the file provided by the given handle -// and compute a hash -hash_file_160_4 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160_4(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160_4(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160_4 :: proc { - hash_stream_160_4, - hash_file_160_4, - hash_bytes_160_4, - hash_string_160_4, - hash_bytes_to_buffer_160_4, - hash_string_to_buffer_160_4, -} - -// hash_string_160_5 will hash the given input and return the -// computed hash -hash_string_160_5 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160_5(transmute([]byte)(data)) -} - -// hash_bytes_160_5 will hash the given input and return the -// computed hash -hash_bytes_160_5 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160_5 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160_5 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160_5 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160_5 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_160_5 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: Haval_Context - ctx.hashbitlen = 160 - ctx.rounds = 5 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160_5 will read the file provided by the given handle -// and compute a hash -hash_file_160_5 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160_5(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160_5(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160_5 :: proc { - hash_stream_160_5, - hash_file_160_5, - hash_bytes_160_5, - hash_string_160_5, - hash_bytes_to_buffer_160_5, - hash_string_to_buffer_160_5, -} - -// hash_string_192_3 will hash the given input and return the -// computed hash -hash_string_192_3 :: proc(data: string) -> [DIGEST_SIZE_192]byte { - return hash_bytes_192_3(transmute([]byte)(data)) -} - -// hash_bytes_192_3 will hash the given input and return the -// computed hash -hash_bytes_192_3 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_192_3 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_192_3 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_192_3 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_192_3 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_192, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_192_3 will read the stream in chunks and compute a -// hash from its contents -hash_stream_192_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 3 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_192_3 will read the file provided by the given handle -// and compute a hash -hash_file_192_3 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_192]byte, bool) { - if !load_at_once { - return hash_stream_192_3(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_192_3(buf[:]), ok - } - } - return [DIGEST_SIZE_192]byte{}, false -} - -hash_192_3 :: proc { - hash_stream_192_3, - hash_file_192_3, - hash_bytes_192_3, - hash_string_192_3, - hash_bytes_to_buffer_192_3, - hash_string_to_buffer_192_3, -} - -// hash_string_192_4 will hash the given input and return the -// computed hash -hash_string_192_4 :: proc(data: string) -> [DIGEST_SIZE_192]byte { - return hash_bytes_192_4(transmute([]byte)(data)) -} - -// hash_bytes_192_4 will hash the given input and return the -// computed hash -hash_bytes_192_4 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_192_4 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_192_4 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_192_4 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_192_4 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_192, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_192_4 will read the stream in chunks and compute a -// hash from its contents -hash_stream_192_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 4 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_192_4 will read the file provided by the given handle -// and compute a hash -hash_file_192_4 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_192]byte, bool) { - if !load_at_once { - return hash_stream_192_4(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_192_4(buf[:]), ok - } - } - return [DIGEST_SIZE_192]byte{}, false -} - -hash_192_4 :: proc { - hash_stream_192_4, - hash_file_192_4, - hash_bytes_192_4, - hash_string_192_4, - hash_bytes_to_buffer_192_4, - hash_string_to_buffer_192_4, -} - -// hash_string_192_5 will hash the given input and return the -// computed hash -hash_string_192_5 :: proc(data: string) -> [DIGEST_SIZE_192]byte { - return hash_bytes_192_5(transmute([]byte)(data)) -} - -// hash_bytes_2DIGEST_SIZE_192_5 will hash the given input and return the -// computed hash -hash_bytes_192_5 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_192_5 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_192_5 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_192_5 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_192_5 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_192, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_192_5 will read the stream in chunks and compute a -// hash from its contents -hash_stream_192_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) { - hash: [DIGEST_SIZE_192]byte - ctx: Haval_Context - ctx.hashbitlen = 192 - ctx.rounds = 5 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_192_5 will read the file provided by the given handle -// and compute a hash -hash_file_192_5 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_192]byte, bool) { - if !load_at_once { - return hash_stream_192_5(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_192_5(buf[:]), ok - } - } - return [DIGEST_SIZE_192]byte{}, false -} - -hash_192_5 :: proc { - hash_stream_192_5, - hash_file_192_5, - hash_bytes_192_5, - hash_string_192_5, - hash_bytes_to_buffer_192_5, - hash_string_to_buffer_192_5, -} - -// hash_string_224_3 will hash the given input and return the -// computed hash -hash_string_224_3 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224_3(transmute([]byte)(data)) -} - -// hash_bytes_224_3 will hash the given input and return the -// computed hash -hash_bytes_224_3 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224_3 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224_3 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224_3 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224_3 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224_3 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 3 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224_3 will read the file provided by the given handle -// and compute a hash -hash_file_224_3 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224_3(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224_3(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224_3 :: proc { - hash_stream_224_3, - hash_file_224_3, - hash_bytes_224_3, - hash_string_224_3, - hash_bytes_to_buffer_224_3, - hash_string_to_buffer_224_3, -} - -// hash_string_224_4 will hash the given input and return the -// computed hash -hash_string_224_4 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224_4(transmute([]byte)(data)) -} - -// hash_bytes_224_4 will hash the given input and return the -// computed hash -hash_bytes_224_4 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224_4 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224_4 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224_4 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224_4 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224_4 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 4 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224_4 will read the file provided by the given handle -// and compute a hash -hash_file_224_4 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224_4(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224_4(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224_4 :: proc { - hash_stream_224_4, - hash_file_224_4, - hash_bytes_224_4, - hash_string_224_4, - hash_bytes_to_buffer_224_4, - hash_string_to_buffer_224_4, -} - -// hash_string_224_5 will hash the given input and return the -// computed hash -hash_string_224_5 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224_5(transmute([]byte)(data)) -} - -// hash_bytes_224_5 will hash the given input and return the -// computed hash -hash_bytes_224_5 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224_5 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224_5 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224_5 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224_5 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224_5 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Haval_Context - ctx.hashbitlen = 224 - ctx.rounds = 5 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224_5 will read the file provided by the given handle -// and compute a hash -hash_file_224_5 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224_5(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224_5(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224_5 :: proc { - hash_stream_224_5, - hash_file_224_5, - hash_bytes_224_5, - hash_string_224_5, - hash_bytes_to_buffer_224_5, - hash_string_to_buffer_224_5, -} - -// hash_string_256_3 will hash the given input and return the -// computed hash -hash_string_256_3 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256_3(transmute([]byte)(data)) -} - -// hash_bytes_256_3 will hash the given input and return the -// computed hash -hash_bytes_256_3 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256_3 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256_3 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256_3 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256_3 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 3 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256_3 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 3 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256_3 will read the file provided by the given handle -// and compute a hash -hash_file_256_3 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256_3(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256_3(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256_3 :: proc { - hash_stream_256_3, - hash_file_256_3, - hash_bytes_256_3, - hash_string_256_3, - hash_bytes_to_buffer_256_3, - hash_string_to_buffer_256_3, -} - -// hash_string_256_4 will hash the given input and return the -// computed hash -hash_string_256_4 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256_4(transmute([]byte)(data)) -} - -// hash_bytes_256_4 will hash the given input and return the -// computed hash -hash_bytes_256_4 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256_4 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256_4 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256_4 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256_4 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 4 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256_4 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 4 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256_4 will read the file provided by the given handle -// and compute a hash -hash_file_256_4 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256_4(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256_4(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256_4 :: proc { - hash_stream_256_4, - hash_file_256_4, - hash_bytes_256_4, - hash_string_256_4, - hash_bytes_to_buffer_256_4, - hash_string_to_buffer_256_4, -} - -// hash_string_256_5 will hash the given input and return the -// computed hash -hash_string_256_5 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256_5(transmute([]byte)(data)) -} - -// hash_bytes_256_5 will hash the given input and return the -// computed hash -hash_bytes_256_5 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256_5 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256_5 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256_5 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256_5 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 5 - init(&ctx) - ctx.str_len = u32(len(data)) - update(&ctx, data) - final(&ctx, hash) -} - - -// hash_stream_256_5 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Haval_Context - ctx.hashbitlen = 256 - ctx.rounds = 5 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - ctx.str_len = u32(len(buf[:read])) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256_5 will read the file provided by the given handle -// and compute a hash -hash_file_256_5 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256_5(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256_5(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256_5 :: proc { - hash_stream_256_5, - hash_file_256_5, - hash_bytes_256_5, - hash_string_256_5, - hash_bytes_to_buffer_256_5, - hash_string_to_buffer_256_5, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Haval_Context) { - assert(ctx.hashbitlen == 128 || ctx.hashbitlen == 160 || ctx.hashbitlen == 192 || ctx.hashbitlen == 224 || ctx.hashbitlen == 256, "hashbitlen must be set to 128, 160, 192, 224 or 256") - assert(ctx.rounds == 3 || ctx.rounds == 4 || ctx.rounds == 5, "rounds must be set to 3, 4 or 5") - ctx.fingerprint[0] = 0x243f6a88 - ctx.fingerprint[1] = 0x85a308d3 - ctx.fingerprint[2] = 0x13198a2e - ctx.fingerprint[3] = 0x03707344 - ctx.fingerprint[4] = 0xa4093822 - ctx.fingerprint[5] = 0x299f31d0 - ctx.fingerprint[6] = 0x082efa98 - ctx.fingerprint[7] = 0xec4e6c89 -} - -// @note(zh): Make sure to set ctx.str_len to the remaining buffer size before calling this proc - e.g. ctx.str_len = u32(len(data)) -update :: proc(ctx: ^Haval_Context, data: []byte) { - i: u32 - rmd_len := u32((ctx.count[0] >> 3) & 0x7f) - fill_len := 128 - rmd_len - str_len := ctx.str_len - - ctx.count[0] += str_len << 3 - if ctx.count[0] < (str_len << 3) { - ctx.count[1] += 1 - } - ctx.count[1] += str_len >> 29 - - when ODIN_ENDIAN == .Little { - if rmd_len + str_len >= 128 { - copy(util.slice_to_bytes(ctx.block[:])[rmd_len:], data[:fill_len]) - block(ctx, ctx.rounds) - for i = fill_len; i + 127 < str_len; i += 128 { - copy(util.slice_to_bytes(ctx.block[:]), data[i:128]) - block(ctx, ctx.rounds) - } - rmd_len = 0 - } else { - i = 0 - } - copy(util.slice_to_bytes(ctx.block[:])[rmd_len:], data[i:]) - } else { - if rmd_len + str_len >= 128 { - copy(ctx.remainder[rmd_len:], data[:fill_len]) - CH2UINT(ctx.remainder[:], ctx.block[:]) - block(ctx, ctx.rounds) - for i = fill_len; i + 127 < str_len; i += 128 { - copy(ctx.remainder[:], data[i:128]) - CH2UINT(ctx.remainder[:], ctx.block[:]) - block(ctx, ctx.rounds) - } - rmd_len = 0 - } else { - i = 0 - } - copy(ctx.remainder[rmd_len:], data[i:]) - } -} - -final :: proc(ctx: ^Haval_Context, hash: []byte) { - pad_len: u32 - tail: [10]byte - - tail[0] = byte(ctx.hashbitlen & 0x3) << 6 | byte(ctx.rounds & 0x7) << 3 | (VERSION & 0x7) - tail[1] = byte(ctx.hashbitlen >> 2) & 0xff - - UINT2CH(ctx.count[:], util.slice_to_bytes(tail[2:]), 2) - rmd_len := (ctx.count[0] >> 3) & 0x7f - if rmd_len < 118 { - pad_len = 118 - rmd_len - } else { - pad_len = 246 - rmd_len - } - - ctx.str_len = pad_len - update(ctx, PADDING[:]) - ctx.str_len = 10 - update(ctx, tail[:]) - tailor(ctx, ctx.hashbitlen) - UINT2CH(ctx.fingerprint[:], hash, ctx.hashbitlen >> 5) - - mem.set(ctx, 0, size_of(ctx)) -} - -/* - HAVAL implementation -*/ - -VERSION :: 1 - -Haval_Context :: struct { - count: [2]u32, - fingerprint: [8]u32, - block: [32]u32, - remainder: [128]byte, - rounds: u32, - hashbitlen: u32, - str_len: u32, -} - -PADDING := [128]byte { - 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -F_1 :: #force_inline proc "contextless" (x6, x5, x4, x3, x2, x1, x0: u32) -> u32 { - return ((x1) & ((x0) ~ (x4)) ~ (x2) & (x5) ~ (x3) & (x6) ~ (x0)) -} - -F_2 :: #force_inline proc "contextless" (x6, x5, x4, x3, x2, x1, x0: u32) -> u32 { - return ((x2) & ((x1) & ~(x3) ~ (x4) & (x5) ~ (x6) ~ (x0)) ~ (x4) & ((x1) ~ (x5)) ~ (x3) & (x5) ~ (x0)) -} - -F_3 :: #force_inline proc "contextless" (x6, x5, x4, x3, x2, x1, x0: u32) -> u32 { - return ((x3) & ((x1) & (x2) ~ (x6) ~ (x0)) ~ (x1) & (x4) ~ (x2) & (x5) ~ (x0)) -} - -F_4 :: #force_inline proc "contextless" (x6, x5, x4, x3, x2, x1, x0: u32) -> u32 { - return ((x4) & ((x5) & ~(x2) ~ (x3) & ~(x6) ~ (x1) ~ (x6) ~ (x0)) ~ (x3) & ((x1) & (x2) ~ (x5) ~ (x6)) ~ (x2) & (x6) ~ (x0)) -} - -F_5 :: #force_inline proc "contextless" (x6, x5, x4, x3, x2, x1, x0: u32) -> u32 { - return ((x0) & ((x1) & (x2) & (x3) ~ ~(x5)) ~ (x1) & (x4) ~ (x2) & (x5) ~ (x3) & (x6)) -} - -FPHI_1 :: #force_inline proc(x6, x5, x4, x3, x2, x1, x0, rounds: u32) -> u32 { - switch rounds { - case 3: return F_1(x1, x0, x3, x5, x6, x2, x4) - case 4: return F_1(x2, x6, x1, x4, x5, x3, x0) - case 5: return F_1(x3, x4, x1, x0, x5, x2, x6) - case: assert(rounds < 3 || rounds > 5, "Rounds count not supported!") - } - return 0 -} - -FPHI_2 :: #force_inline proc(x6, x5, x4, x3, x2, x1, x0, rounds: u32) -> u32 { - switch rounds { - case 3: return F_2(x4, x2, x1, x0, x5, x3, x6) - case 4: return F_2(x3, x5, x2, x0, x1, x6, x4) - case 5: return F_2(x6, x2, x1, x0, x3, x4, x5) - case: assert(rounds < 3 || rounds > 5, "Rounds count not supported!") - } - return 0 -} - -FPHI_3 :: #force_inline proc(x6, x5, x4, x3, x2, x1, x0, rounds: u32) -> u32 { - switch rounds { - case 3: return F_3(x6, x1, x2, x3, x4, x5, x0) - case 4: return F_3(x1, x4, x3, x6, x0, x2, x5) - case 5: return F_3(x2, x6, x0, x4, x3, x1, x5) - case: assert(rounds < 3 || rounds > 5, "Rounds count not supported!") - } - return 0 -} - -FPHI_4 :: #force_inline proc(x6, x5, x4, x3, x2, x1, x0, rounds: u32) -> u32 { - switch rounds { - case 4: return F_4(x6, x4, x0, x5, x2, x1, x3) - case 5: return F_4(x1, x5, x3, x2, x0, x4, x6) - case: assert(rounds < 4 || rounds > 5, "Rounds count not supported!") - } - return 0 -} - -FPHI_5 :: #force_inline proc(x6, x5, x4, x3, x2, x1, x0, rounds: u32) -> u32 { - switch rounds { - case 5: return F_5(x2, x5, x0, x6, x4, x3, x1) - case: assert(rounds != 5, "Rounds count not supported!") - } - return 0 -} - -FF_1 :: #force_inline proc(x7, x6, x5, x4, x3, x2, x1, x0, w, rounds: u32) -> u32 { - tmp := FPHI_1(x6, x5, x4, x3, x2, x1, x0, rounds) - x8 := util.ROTR32(tmp, 7) + util.ROTR32(x7, 11) + w - return x8 -} - -FF_2 :: #force_inline proc(x7, x6, x5, x4, x3, x2, x1, x0, w, c, rounds: u32) -> u32 { - tmp := FPHI_2(x6, x5, x4, x3, x2, x1, x0, rounds) - x8 := util.ROTR32(tmp, 7) + util.ROTR32(x7, 11) + w + c - return x8 -} - -FF_3 :: #force_inline proc(x7, x6, x5, x4, x3, x2, x1, x0, w, c, rounds: u32) -> u32 { - tmp := FPHI_3(x6, x5, x4, x3, x2, x1, x0, rounds) - x8 := util.ROTR32(tmp, 7) + util.ROTR32(x7, 11) + w + c - return x8 -} - -FF_4 :: #force_inline proc(x7, x6, x5, x4, x3, x2, x1, x0, w, c, rounds: u32) -> u32 { - tmp := FPHI_4(x6, x5, x4, x3, x2, x1, x0, rounds) - x8 := util.ROTR32(tmp, 7) + util.ROTR32(x7, 11) + w + c - return x8 -} - -FF_5 :: #force_inline proc(x7, x6, x5, x4, x3, x2, x1, x0, w, c, rounds: u32) -> u32 { - tmp := FPHI_5(x6, x5, x4, x3, x2, x1, x0, rounds) - x8 := util.ROTR32(tmp, 7) + util.ROTR32(x7, 11) + w + c - return x8 -} - -CH2UINT :: #force_inline proc "contextless" (str: []byte, word: []u32) { - for _, i in word[:32] { - word[i] = u32(str[i*4+0]) << 0 | u32(str[i*4+1]) << 8 | u32(str[i*4+2]) << 16 | u32(str[i*4+3]) << 24 - } -} - -UINT2CH :: #force_inline proc "contextless" (word: []u32, str: []byte, wlen: u32) { - for _, i in word[:wlen] { - str[i*4+0] = byte(word[i] >> 0) & 0xff - str[i*4+1] = byte(word[i] >> 8) & 0xff - str[i*4+2] = byte(word[i] >> 16) & 0xff - str[i*4+3] = byte(word[i] >> 24) & 0xff - } -} - -block :: proc(ctx: ^Haval_Context, rounds: u32) { - t0, t1, t2, t3 := ctx.fingerprint[0], ctx.fingerprint[1], ctx.fingerprint[2], ctx.fingerprint[3] - t4, t5, t6, t7 := ctx.fingerprint[4], ctx.fingerprint[5], ctx.fingerprint[6], ctx.fingerprint[7] - w := ctx.block - - t7 = FF_1(t7, t6, t5, t4, t3, t2, t1, t0, w[ 0], rounds) - t6 = FF_1(t6, t5, t4, t3, t2, t1, t0, t7, w[ 1], rounds) - t5 = FF_1(t5, t4, t3, t2, t1, t0, t7, t6, w[ 2], rounds) - t4 = FF_1(t4, t3, t2, t1, t0, t7, t6, t5, w[ 3], rounds) - t3 = FF_1(t3, t2, t1, t0, t7, t6, t5, t4, w[ 4], rounds) - t2 = FF_1(t2, t1, t0, t7, t6, t5, t4, t3, w[ 5], rounds) - t1 = FF_1(t1, t0, t7, t6, t5, t4, t3, t2, w[ 6], rounds) - t0 = FF_1(t0, t7, t6, t5, t4, t3, t2, t1, w[ 7], rounds) - - t7 = FF_1(t7, t6, t5, t4, t3, t2, t1, t0, w[ 8], rounds) - t6 = FF_1(t6, t5, t4, t3, t2, t1, t0, t7, w[ 9], rounds) - t5 = FF_1(t5, t4, t3, t2, t1, t0, t7, t6, w[10], rounds) - t4 = FF_1(t4, t3, t2, t1, t0, t7, t6, t5, w[11], rounds) - t3 = FF_1(t3, t2, t1, t0, t7, t6, t5, t4, w[12], rounds) - t2 = FF_1(t2, t1, t0, t7, t6, t5, t4, t3, w[13], rounds) - t1 = FF_1(t1, t0, t7, t6, t5, t4, t3, t2, w[14], rounds) - t0 = FF_1(t0, t7, t6, t5, t4, t3, t2, t1, w[15], rounds) - - t7 = FF_1(t7, t6, t5, t4, t3, t2, t1, t0, w[16], rounds) - t6 = FF_1(t6, t5, t4, t3, t2, t1, t0, t7, w[17], rounds) - t5 = FF_1(t5, t4, t3, t2, t1, t0, t7, t6, w[18], rounds) - t4 = FF_1(t4, t3, t2, t1, t0, t7, t6, t5, w[19], rounds) - t3 = FF_1(t3, t2, t1, t0, t7, t6, t5, t4, w[20], rounds) - t2 = FF_1(t2, t1, t0, t7, t6, t5, t4, t3, w[21], rounds) - t1 = FF_1(t1, t0, t7, t6, t5, t4, t3, t2, w[22], rounds) - t0 = FF_1(t0, t7, t6, t5, t4, t3, t2, t1, w[23], rounds) - - t7 = FF_1(t7, t6, t5, t4, t3, t2, t1, t0, w[24], rounds) - t6 = FF_1(t6, t5, t4, t3, t2, t1, t0, t7, w[25], rounds) - t5 = FF_1(t5, t4, t3, t2, t1, t0, t7, t6, w[26], rounds) - t4 = FF_1(t4, t3, t2, t1, t0, t7, t6, t5, w[27], rounds) - t3 = FF_1(t3, t2, t1, t0, t7, t6, t5, t4, w[28], rounds) - t2 = FF_1(t2, t1, t0, t7, t6, t5, t4, t3, w[29], rounds) - t1 = FF_1(t1, t0, t7, t6, t5, t4, t3, t2, w[30], rounds) - t0 = FF_1(t0, t7, t6, t5, t4, t3, t2, t1, w[31], rounds) - - t7 = FF_2(t7, t6, t5, t4, t3, t2, t1, t0, w[ 5], 0x452821e6, rounds) - t6 = FF_2(t6, t5, t4, t3, t2, t1, t0, t7, w[14], 0x38d01377, rounds) - t5 = FF_2(t5, t4, t3, t2, t1, t0, t7, t6, w[26], 0xbe5466cf, rounds) - t4 = FF_2(t4, t3, t2, t1, t0, t7, t6, t5, w[18], 0x34e90c6c, rounds) - t3 = FF_2(t3, t2, t1, t0, t7, t6, t5, t4, w[11], 0xc0ac29b7, rounds) - t2 = FF_2(t2, t1, t0, t7, t6, t5, t4, t3, w[28], 0xc97c50dd, rounds) - t1 = FF_2(t1, t0, t7, t6, t5, t4, t3, t2, w[ 7], 0x3f84d5b5, rounds) - t0 = FF_2(t0, t7, t6, t5, t4, t3, t2, t1, w[16], 0xb5470917, rounds) - - t7 = FF_2(t7, t6, t5, t4, t3, t2, t1, t0, w[ 0], 0x9216d5d9, rounds) - t6 = FF_2(t6, t5, t4, t3, t2, t1, t0, t7, w[23], 0x8979fb1b, rounds) - t5 = FF_2(t5, t4, t3, t2, t1, t0, t7, t6, w[20], 0xd1310ba6, rounds) - t4 = FF_2(t4, t3, t2, t1, t0, t7, t6, t5, w[22], 0x98dfb5ac, rounds) - t3 = FF_2(t3, t2, t1, t0, t7, t6, t5, t4, w[ 1], 0x2ffd72db, rounds) - t2 = FF_2(t2, t1, t0, t7, t6, t5, t4, t3, w[10], 0xd01adfb7, rounds) - t1 = FF_2(t1, t0, t7, t6, t5, t4, t3, t2, w[ 4], 0xb8e1afed, rounds) - t0 = FF_2(t0, t7, t6, t5, t4, t3, t2, t1, w[ 8], 0x6a267e96, rounds) - - t7 = FF_2(t7, t6, t5, t4, t3, t2, t1, t0, w[30], 0xba7c9045, rounds) - t6 = FF_2(t6, t5, t4, t3, t2, t1, t0, t7, w[ 3], 0xf12c7f99, rounds) - t5 = FF_2(t5, t4, t3, t2, t1, t0, t7, t6, w[21], 0x24a19947, rounds) - t4 = FF_2(t4, t3, t2, t1, t0, t7, t6, t5, w[ 9], 0xb3916cf7, rounds) - t3 = FF_2(t3, t2, t1, t0, t7, t6, t5, t4, w[17], 0x0801f2e2, rounds) - t2 = FF_2(t2, t1, t0, t7, t6, t5, t4, t3, w[24], 0x858efc16, rounds) - t1 = FF_2(t1, t0, t7, t6, t5, t4, t3, t2, w[29], 0x636920d8, rounds) - t0 = FF_2(t0, t7, t6, t5, t4, t3, t2, t1, w[ 6], 0x71574e69, rounds) - - t7 = FF_2(t7, t6, t5, t4, t3, t2, t1, t0, w[19], 0xa458fea3, rounds) - t6 = FF_2(t6, t5, t4, t3, t2, t1, t0, t7, w[12], 0xf4933d7e, rounds) - t5 = FF_2(t5, t4, t3, t2, t1, t0, t7, t6, w[15], 0x0d95748f, rounds) - t4 = FF_2(t4, t3, t2, t1, t0, t7, t6, t5, w[13], 0x728eb658, rounds) - t3 = FF_2(t3, t2, t1, t0, t7, t6, t5, t4, w[ 2], 0x718bcd58, rounds) - t2 = FF_2(t2, t1, t0, t7, t6, t5, t4, t3, w[25], 0x82154aee, rounds) - t1 = FF_2(t1, t0, t7, t6, t5, t4, t3, t2, w[31], 0x7b54a41d, rounds) - t0 = FF_2(t0, t7, t6, t5, t4, t3, t2, t1, w[27], 0xc25a59b5, rounds) - - t7 = FF_3(t7, t6, t5, t4, t3, t2, t1, t0, w[19], 0x9c30d539, rounds) - t6 = FF_3(t6, t5, t4, t3, t2, t1, t0, t7, w[ 9], 0x2af26013, rounds) - t5 = FF_3(t5, t4, t3, t2, t1, t0, t7, t6, w[ 4], 0xc5d1b023, rounds) - t4 = FF_3(t4, t3, t2, t1, t0, t7, t6, t5, w[20], 0x286085f0, rounds) - t3 = FF_3(t3, t2, t1, t0, t7, t6, t5, t4, w[28], 0xca417918, rounds) - t2 = FF_3(t2, t1, t0, t7, t6, t5, t4, t3, w[17], 0xb8db38ef, rounds) - t1 = FF_3(t1, t0, t7, t6, t5, t4, t3, t2, w[ 8], 0x8e79dcb0, rounds) - t0 = FF_3(t0, t7, t6, t5, t4, t3, t2, t1, w[22], 0x603a180e, rounds) - - t7 = FF_3(t7, t6, t5, t4, t3, t2, t1, t0, w[29], 0x6c9e0e8b, rounds) - t6 = FF_3(t6, t5, t4, t3, t2, t1, t0, t7, w[14], 0xb01e8a3e, rounds) - t5 = FF_3(t5, t4, t3, t2, t1, t0, t7, t6, w[25], 0xd71577c1, rounds) - t4 = FF_3(t4, t3, t2, t1, t0, t7, t6, t5, w[12], 0xbd314b27, rounds) - t3 = FF_3(t3, t2, t1, t0, t7, t6, t5, t4, w[24], 0x78af2fda, rounds) - t2 = FF_3(t2, t1, t0, t7, t6, t5, t4, t3, w[30], 0x55605c60, rounds) - t1 = FF_3(t1, t0, t7, t6, t5, t4, t3, t2, w[16], 0xe65525f3, rounds) - t0 = FF_3(t0, t7, t6, t5, t4, t3, t2, t1, w[26], 0xaa55ab94, rounds) - - t7 = FF_3(t7, t6, t5, t4, t3, t2, t1, t0, w[31], 0x57489862, rounds) - t6 = FF_3(t6, t5, t4, t3, t2, t1, t0, t7, w[15], 0x63e81440, rounds) - t5 = FF_3(t5, t4, t3, t2, t1, t0, t7, t6, w[ 7], 0x55ca396a, rounds) - t4 = FF_3(t4, t3, t2, t1, t0, t7, t6, t5, w[ 3], 0x2aab10b6, rounds) - t3 = FF_3(t3, t2, t1, t0, t7, t6, t5, t4, w[ 1], 0xb4cc5c34, rounds) - t2 = FF_3(t2, t1, t0, t7, t6, t5, t4, t3, w[ 0], 0x1141e8ce, rounds) - t1 = FF_3(t1, t0, t7, t6, t5, t4, t3, t2, w[18], 0xa15486af, rounds) - t0 = FF_3(t0, t7, t6, t5, t4, t3, t2, t1, w[27], 0x7c72e993, rounds) - - t7 = FF_3(t7, t6, t5, t4, t3, t2, t1, t0, w[13], 0xb3ee1411, rounds) - t6 = FF_3(t6, t5, t4, t3, t2, t1, t0, t7, w[ 6], 0x636fbc2a, rounds) - t5 = FF_3(t5, t4, t3, t2, t1, t0, t7, t6, w[21], 0x2ba9c55d, rounds) - t4 = FF_3(t4, t3, t2, t1, t0, t7, t6, t5, w[10], 0x741831f6, rounds) - t3 = FF_3(t3, t2, t1, t0, t7, t6, t5, t4, w[23], 0xce5c3e16, rounds) - t2 = FF_3(t2, t1, t0, t7, t6, t5, t4, t3, w[11], 0x9b87931e, rounds) - t1 = FF_3(t1, t0, t7, t6, t5, t4, t3, t2, w[ 5], 0xafd6ba33, rounds) - t0 = FF_3(t0, t7, t6, t5, t4, t3, t2, t1, w[ 2], 0x6c24cf5c, rounds) - - if rounds >= 4 { - t7 = FF_4(t7, t6, t5, t4, t3, t2, t1, t0, w[24], 0x7a325381, rounds) - t6 = FF_4(t6, t5, t4, t3, t2, t1, t0, t7, w[ 4], 0x28958677, rounds) - t5 = FF_4(t5, t4, t3, t2, t1, t0, t7, t6, w[ 0], 0x3b8f4898, rounds) - t4 = FF_4(t4, t3, t2, t1, t0, t7, t6, t5, w[14], 0x6b4bb9af, rounds) - t3 = FF_4(t3, t2, t1, t0, t7, t6, t5, t4, w[ 2], 0xc4bfe81b, rounds) - t2 = FF_4(t2, t1, t0, t7, t6, t5, t4, t3, w[ 7], 0x66282193, rounds) - t1 = FF_4(t1, t0, t7, t6, t5, t4, t3, t2, w[28], 0x61d809cc, rounds) - t0 = FF_4(t0, t7, t6, t5, t4, t3, t2, t1, w[23], 0xfb21a991, rounds) - - t7 = FF_4(t7, t6, t5, t4, t3, t2, t1, t0, w[26], 0x487cac60, rounds) - t6 = FF_4(t6, t5, t4, t3, t2, t1, t0, t7, w[ 6], 0x5dec8032, rounds) - t5 = FF_4(t5, t4, t3, t2, t1, t0, t7, t6, w[30], 0xef845d5d, rounds) - t4 = FF_4(t4, t3, t2, t1, t0, t7, t6, t5, w[20], 0xe98575b1, rounds) - t3 = FF_4(t3, t2, t1, t0, t7, t6, t5, t4, w[18], 0xdc262302, rounds) - t2 = FF_4(t2, t1, t0, t7, t6, t5, t4, t3, w[25], 0xeb651b88, rounds) - t1 = FF_4(t1, t0, t7, t6, t5, t4, t3, t2, w[19], 0x23893e81, rounds) - t0 = FF_4(t0, t7, t6, t5, t4, t3, t2, t1, w[ 3], 0xd396acc5, rounds) - - t7 = FF_4(t7, t6, t5, t4, t3, t2, t1, t0, w[22], 0x0f6d6ff3, rounds) - t6 = FF_4(t6, t5, t4, t3, t2, t1, t0, t7, w[11], 0x83f44239, rounds) - t5 = FF_4(t5, t4, t3, t2, t1, t0, t7, t6, w[31], 0x2e0b4482, rounds) - t4 = FF_4(t4, t3, t2, t1, t0, t7, t6, t5, w[21], 0xa4842004, rounds) - t3 = FF_4(t3, t2, t1, t0, t7, t6, t5, t4, w[ 8], 0x69c8f04a, rounds) - t2 = FF_4(t2, t1, t0, t7, t6, t5, t4, t3, w[27], 0x9e1f9b5e, rounds) - t1 = FF_4(t1, t0, t7, t6, t5, t4, t3, t2, w[12], 0x21c66842, rounds) - t0 = FF_4(t0, t7, t6, t5, t4, t3, t2, t1, w[ 9], 0xf6e96c9a, rounds) - - t7 = FF_4(t7, t6, t5, t4, t3, t2, t1, t0, w[ 1], 0x670c9c61, rounds) - t6 = FF_4(t6, t5, t4, t3, t2, t1, t0, t7, w[29], 0xabd388f0, rounds) - t5 = FF_4(t5, t4, t3, t2, t1, t0, t7, t6, w[ 5], 0x6a51a0d2, rounds) - t4 = FF_4(t4, t3, t2, t1, t0, t7, t6, t5, w[15], 0xd8542f68, rounds) - t3 = FF_4(t3, t2, t1, t0, t7, t6, t5, t4, w[17], 0x960fa728, rounds) - t2 = FF_4(t2, t1, t0, t7, t6, t5, t4, t3, w[10], 0xab5133a3, rounds) - t1 = FF_4(t1, t0, t7, t6, t5, t4, t3, t2, w[16], 0x6eef0b6c, rounds) - t0 = FF_4(t0, t7, t6, t5, t4, t3, t2, t1, w[13], 0x137a3be4, rounds) - } - - if rounds == 5 { - t7 = FF_5(t7, t6, t5, t4, t3, t2, t1, t0, w[27], 0xba3bf050, rounds) - t6 = FF_5(t6, t5, t4, t3, t2, t1, t0, t7, w[ 3], 0x7efb2a98, rounds) - t5 = FF_5(t5, t4, t3, t2, t1, t0, t7, t6, w[21], 0xa1f1651d, rounds) - t4 = FF_5(t4, t3, t2, t1, t0, t7, t6, t5, w[26], 0x39af0176, rounds) - t3 = FF_5(t3, t2, t1, t0, t7, t6, t5, t4, w[17], 0x66ca593e, rounds) - t2 = FF_5(t2, t1, t0, t7, t6, t5, t4, t3, w[11], 0x82430e88, rounds) - t1 = FF_5(t1, t0, t7, t6, t5, t4, t3, t2, w[20], 0x8cee8619, rounds) - t0 = FF_5(t0, t7, t6, t5, t4, t3, t2, t1, w[29], 0x456f9fb4, rounds) - - t7 = FF_5(t7, t6, t5, t4, t3, t2, t1, t0, w[19], 0x7d84a5c3, rounds) - t6 = FF_5(t6, t5, t4, t3, t2, t1, t0, t7, w[ 0], 0x3b8b5ebe, rounds) - t5 = FF_5(t5, t4, t3, t2, t1, t0, t7, t6, w[12], 0xe06f75d8, rounds) - t4 = FF_5(t4, t3, t2, t1, t0, t7, t6, t5, w[ 7], 0x85c12073, rounds) - t3 = FF_5(t3, t2, t1, t0, t7, t6, t5, t4, w[13], 0x401a449f, rounds) - t2 = FF_5(t2, t1, t0, t7, t6, t5, t4, t3, w[ 8], 0x56c16aa6, rounds) - t1 = FF_5(t1, t0, t7, t6, t5, t4, t3, t2, w[31], 0x4ed3aa62, rounds) - t0 = FF_5(t0, t7, t6, t5, t4, t3, t2, t1, w[10], 0x363f7706, rounds) - - t7 = FF_5(t7, t6, t5, t4, t3, t2, t1, t0, w[ 5], 0x1bfedf72, rounds) - t6 = FF_5(t6, t5, t4, t3, t2, t1, t0, t7, w[ 9], 0x429b023d, rounds) - t5 = FF_5(t5, t4, t3, t2, t1, t0, t7, t6, w[14], 0x37d0d724, rounds) - t4 = FF_5(t4, t3, t2, t1, t0, t7, t6, t5, w[30], 0xd00a1248, rounds) - t3 = FF_5(t3, t2, t1, t0, t7, t6, t5, t4, w[18], 0xdb0fead3, rounds) - t2 = FF_5(t2, t1, t0, t7, t6, t5, t4, t3, w[ 6], 0x49f1c09b, rounds) - t1 = FF_5(t1, t0, t7, t6, t5, t4, t3, t2, w[28], 0x075372c9, rounds) - t0 = FF_5(t0, t7, t6, t5, t4, t3, t2, t1, w[24], 0x80991b7b, rounds) - - t7 = FF_5(t7, t6, t5, t4, t3, t2, t1, t0, w[ 2], 0x25d479d8, rounds) - t6 = FF_5(t6, t5, t4, t3, t2, t1, t0, t7, w[23], 0xf6e8def7, rounds) - t5 = FF_5(t5, t4, t3, t2, t1, t0, t7, t6, w[16], 0xe3fe501a, rounds) - t4 = FF_5(t4, t3, t2, t1, t0, t7, t6, t5, w[22], 0xb6794c3b, rounds) - t3 = FF_5(t3, t2, t1, t0, t7, t6, t5, t4, w[ 4], 0x976ce0bd, rounds) - t2 = FF_5(t2, t1, t0, t7, t6, t5, t4, t3, w[ 1], 0x04c006ba, rounds) - t1 = FF_5(t1, t0, t7, t6, t5, t4, t3, t2, w[25], 0xc1a94fb6, rounds) - t0 = FF_5(t0, t7, t6, t5, t4, t3, t2, t1, w[15], 0x409f60c4, rounds) - } - - ctx.fingerprint[0] += t0 - ctx.fingerprint[1] += t1 - ctx.fingerprint[2] += t2 - ctx.fingerprint[3] += t3 - ctx.fingerprint[4] += t4 - ctx.fingerprint[5] += t5 - ctx.fingerprint[6] += t6 - ctx.fingerprint[7] += t7 -} - -tailor :: proc(ctx: ^Haval_Context, size: u32) { - temp: u32 - switch size { - case 128: - temp = (ctx.fingerprint[7] & 0x000000ff) | - (ctx.fingerprint[6] & 0xff000000) | - (ctx.fingerprint[5] & 0x00ff0000) | - (ctx.fingerprint[4] & 0x0000ff00) - ctx.fingerprint[0] += util.ROTR32(temp, 8) - - temp = (ctx.fingerprint[7] & 0x0000ff00) | - (ctx.fingerprint[6] & 0x000000ff) | - (ctx.fingerprint[5] & 0xff000000) | - (ctx.fingerprint[4] & 0x00ff0000) - ctx.fingerprint[1] += util.ROTR32(temp, 16) - - temp = (ctx.fingerprint[7] & 0x00ff0000) | - (ctx.fingerprint[6] & 0x0000ff00) | - (ctx.fingerprint[5] & 0x000000ff) | - (ctx.fingerprint[4] & 0xff000000) - ctx.fingerprint[2] += util.ROTR32(temp, 24) - - temp = (ctx.fingerprint[7] & 0xff000000) | - (ctx.fingerprint[6] & 0x00ff0000) | - (ctx.fingerprint[5] & 0x0000ff00) | - (ctx.fingerprint[4] & 0x000000ff) - ctx.fingerprint[3] += temp - case 160: - temp = (ctx.fingerprint[7] & u32(0x3f)) | - (ctx.fingerprint[6] & u32(0x7f << 25)) | - (ctx.fingerprint[5] & u32(0x3f << 19)) - ctx.fingerprint[0] += util.ROTR32(temp, 19) - - temp = (ctx.fingerprint[7] & u32(0x3f << 6)) | - (ctx.fingerprint[6] & u32(0x3f)) | - (ctx.fingerprint[5] & u32(0x7f << 25)) - ctx.fingerprint[1] += util.ROTR32(temp, 25) - - temp = (ctx.fingerprint[7] & u32(0x7f << 12)) | - (ctx.fingerprint[6] & u32(0x3f << 6)) | - (ctx.fingerprint[5] & u32(0x3f)) - ctx.fingerprint[2] += temp - - temp = (ctx.fingerprint[7] & u32(0x3f << 19)) | - (ctx.fingerprint[6] & u32(0x7f << 12)) | - (ctx.fingerprint[5] & u32(0x3f << 6)) - ctx.fingerprint[3] += temp >> 6 - - temp = (ctx.fingerprint[7] & u32(0x7f << 25)) | - (ctx.fingerprint[6] & u32(0x3f << 19)) | - (ctx.fingerprint[5] & u32(0x7f << 12)) - ctx.fingerprint[4] += temp >> 12 - case 192: - temp = (ctx.fingerprint[7] & u32(0x1f)) | - (ctx.fingerprint[6] & u32(0x3f << 26)) - ctx.fingerprint[0] += util.ROTR32(temp, 26) - - temp = (ctx.fingerprint[7] & u32(0x1f << 5)) | - (ctx.fingerprint[6] & u32(0x1f)) - ctx.fingerprint[1] += temp - - temp = (ctx.fingerprint[7] & u32(0x3f << 10)) | - (ctx.fingerprint[6] & u32(0x1f << 5)) - ctx.fingerprint[2] += temp >> 5 - - temp = (ctx.fingerprint[7] & u32(0x1f << 16)) | - (ctx.fingerprint[6] & u32(0x3f << 10)) - ctx.fingerprint[3] += temp >> 10 - - temp = (ctx.fingerprint[7] & u32(0x1f << 21)) | - (ctx.fingerprint[6] & u32(0x1f << 16)) - ctx.fingerprint[4] += temp >> 16 - - temp = (ctx.fingerprint[7] & u32(0x3f << 26)) | - (ctx.fingerprint[6] & u32(0x1f << 21)) - ctx.fingerprint[5] += temp >> 21 - case 224: - ctx.fingerprint[0] += (ctx.fingerprint[7] >> 27) & 0x1f - ctx.fingerprint[1] += (ctx.fingerprint[7] >> 22) & 0x1f - ctx.fingerprint[2] += (ctx.fingerprint[7] >> 18) & 0x0f - ctx.fingerprint[3] += (ctx.fingerprint[7] >> 13) & 0x1f - ctx.fingerprint[4] += (ctx.fingerprint[7] >> 9) & 0x0f - ctx.fingerprint[5] += (ctx.fingerprint[7] >> 4) & 0x1f - ctx.fingerprint[6] += ctx.fingerprint[7] & 0x0f - } -} diff --git a/core/crypto/jh/jh.odin b/core/crypto/jh/jh.odin deleted file mode 100644 index 5dc6c4e6b..000000000 --- a/core/crypto/jh/jh.odin +++ /dev/null @@ -1,584 +0,0 @@ -package jh - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the JH hashing algorithm, as defined in -*/ - -import "core:os" -import "core:io" - -/* - High level API -*/ - -DIGEST_SIZE_224 :: 28 -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_384 :: 48 -DIGEST_SIZE_512 :: 64 - -// hash_string_224 will hash the given input and return the -// computed hash -hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) -} - -// hash_bytes_224 will hash the given input and return the -// computed hash -hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Jh_Context - ctx.hashbitlen = 224 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Jh_Context - ctx.hashbitlen = 224 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_224 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: Jh_Context - ctx.hashbitlen = 224 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224 will read the file provided by the given handle -// and compute a hash -hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, -} - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Jh_Context - ctx.hashbitlen = 256 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Jh_Context - ctx.hashbitlen = 256 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Jh_Context - ctx.hashbitlen = 256 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_384 will hash the given input and return the -// computed hash -hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) -} - -// hash_bytes_384 will hash the given input and return the -// computed hash -hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: Jh_Context - ctx.hashbitlen = 384 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_384 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_384 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: Jh_Context - ctx.hashbitlen = 384 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_384 will read the stream in chunks and compute a -// hash from its contents -hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { - hash: [DIGEST_SIZE_384]byte - ctx: Jh_Context - ctx.hashbitlen = 384 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_384 will read the file provided by the given handle -// and compute a hash -hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false -} - -hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, -} - -// hash_string_512 will hash the given input and return the -// computed hash -hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) -} - -// hash_bytes_512 will hash the given input and return the -// computed hash -hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: Jh_Context - ctx.hashbitlen = 512 - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_512 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_512 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: Jh_Context - ctx.hashbitlen = 512 - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_512 will read the stream in chunks and compute a -// hash from its contents -hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: Jh_Context - ctx.hashbitlen = 512 - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_512 will read the file provided by the given handle -// and compute a hash -hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false -} - -hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Jh_Context) { - assert(ctx.hashbitlen == 224 || ctx.hashbitlen == 256 || ctx.hashbitlen == 384 || ctx.hashbitlen == 512, "hashbitlen must be set to 224, 256, 384 or 512") - ctx.H[1] = byte(ctx.hashbitlen) & 0xff - ctx.H[0] = byte(ctx.hashbitlen >> 8) & 0xff - F8(ctx) -} - -update :: proc(ctx: ^Jh_Context, data: []byte) { - databitlen := u64(len(data)) * 8 - ctx.databitlen += databitlen - i := u64(0) - - if (ctx.buffer_size > 0) && ((ctx.buffer_size + databitlen) < 512) { - if (databitlen & 7) == 0 { - copy(ctx.buffer[ctx.buffer_size >> 3:], data[:64 - (ctx.buffer_size >> 3)]) - } else { - copy(ctx.buffer[ctx.buffer_size >> 3:], data[:64 - (ctx.buffer_size >> 3) + 1]) - } - ctx.buffer_size += databitlen - databitlen = 0 - } - - if (ctx.buffer_size > 0 ) && ((ctx.buffer_size + databitlen) >= 512) { - copy(ctx.buffer[ctx.buffer_size >> 3:], data[:64 - (ctx.buffer_size >> 3)]) - i = 64 - (ctx.buffer_size >> 3) - databitlen = databitlen - (512 - ctx.buffer_size) - F8(ctx) - ctx.buffer_size = 0 - } - - for databitlen >= 512 { - copy(ctx.buffer[:], data[i:i + 64]) - F8(ctx) - i += 64 - databitlen -= 512 - } - - if databitlen > 0 { - if (databitlen & 7) == 0 { - copy(ctx.buffer[:], data[i:i + ((databitlen & 0x1ff) >> 3)]) - } else { - copy(ctx.buffer[:], data[i:i + ((databitlen & 0x1ff) >> 3) + 1]) - } - ctx.buffer_size = databitlen - } -} - -final :: proc(ctx: ^Jh_Context, hash: []byte) { - if ctx.databitlen & 0x1ff == 0 { - for i := 0; i < 64; i += 1 { - ctx.buffer[i] = 0 - } - ctx.buffer[0] = 0x80 - ctx.buffer[63] = byte(ctx.databitlen) & 0xff - ctx.buffer[62] = byte(ctx.databitlen >> 8) & 0xff - ctx.buffer[61] = byte(ctx.databitlen >> 16) & 0xff - ctx.buffer[60] = byte(ctx.databitlen >> 24) & 0xff - ctx.buffer[59] = byte(ctx.databitlen >> 32) & 0xff - ctx.buffer[58] = byte(ctx.databitlen >> 40) & 0xff - ctx.buffer[57] = byte(ctx.databitlen >> 48) & 0xff - ctx.buffer[56] = byte(ctx.databitlen >> 56) & 0xff - F8(ctx) - } else { - if ctx.buffer_size & 7 == 0 { - for i := (ctx.databitlen & 0x1ff) >> 3; i < 64; i += 1 { - ctx.buffer[i] = 0 - } - } else { - for i := ((ctx.databitlen & 0x1ff) >> 3) + 1; i < 64; i += 1 { - ctx.buffer[i] = 0 - } - } - ctx.buffer[(ctx.databitlen & 0x1ff) >> 3] |= 1 << (7 - (ctx.databitlen & 7)) - F8(ctx) - for i := 0; i < 64; i += 1 { - ctx.buffer[i] = 0 - } - ctx.buffer[63] = byte(ctx.databitlen) & 0xff - ctx.buffer[62] = byte(ctx.databitlen >> 8) & 0xff - ctx.buffer[61] = byte(ctx.databitlen >> 16) & 0xff - ctx.buffer[60] = byte(ctx.databitlen >> 24) & 0xff - ctx.buffer[59] = byte(ctx.databitlen >> 32) & 0xff - ctx.buffer[58] = byte(ctx.databitlen >> 40) & 0xff - ctx.buffer[57] = byte(ctx.databitlen >> 48) & 0xff - ctx.buffer[56] = byte(ctx.databitlen >> 56) & 0xff - F8(ctx) - } - switch ctx.hashbitlen { - case 224: copy(hash[:], ctx.H[100:128]) - case 256: copy(hash[:], ctx.H[96:128]) - case 384: copy(hash[:], ctx.H[80:128]) - case 512: copy(hash[:], ctx.H[64:128]) - } -} - -/* - JH implementation -*/ - -ROUNDCONSTANT_ZERO := [64]byte { - 0x6, 0xa, 0x0, 0x9, 0xe, 0x6, 0x6, 0x7, - 0xf, 0x3, 0xb, 0xc, 0xc, 0x9, 0x0, 0x8, - 0xb, 0x2, 0xf, 0xb, 0x1, 0x3, 0x6, 0x6, - 0xe, 0xa, 0x9, 0x5, 0x7, 0xd, 0x3, 0xe, - 0x3, 0xa, 0xd, 0xe, 0xc, 0x1, 0x7, 0x5, - 0x1, 0x2, 0x7, 0x7, 0x5, 0x0, 0x9, 0x9, - 0xd, 0xa, 0x2, 0xf, 0x5, 0x9, 0x0, 0xb, - 0x0, 0x6, 0x6, 0x7, 0x3, 0x2, 0x2, 0xa, -} - -SBOX := [2][16]byte { - {9, 0, 4, 11, 13, 12, 3, 15, 1, 10, 2, 6, 7, 5, 8, 14}, - {3, 12, 6, 13, 5, 7, 1, 9, 15, 2, 0, 4, 11, 10, 14, 8}, -} - -Jh_Context :: struct { - hashbitlen: int, - databitlen: u64, - buffer_size: u64, - H: [128]byte, - A: [256]byte, - roundconstant: [64]byte, - buffer: [64]byte, -} - -E8_finaldegroup :: proc(ctx: ^Jh_Context) { - t0,t1,t2,t3: byte - tem: [256]byte - for i := 0; i < 128; i += 1 { - tem[i] = ctx.A[i << 1] - tem[i + 128] = ctx.A[(i << 1) + 1] - } - for i := 0; i < 128; i += 1 { - ctx.H[i] = 0 - } - for i := 0; i < 256; i += 1 { - t0 = (tem[i] >> 3) & 1 - t1 = (tem[i] >> 2) & 1 - t2 = (tem[i] >> 1) & 1 - t3 = (tem[i] >> 0) & 1 - - ctx.H[uint(i) >> 3] |= t0 << (7 - (uint(i) & 7)) - ctx.H[(uint(i) + 256) >> 3] |= t1 << (7 - (uint(i) & 7)) - ctx.H[(uint(i) + 512) >> 3] |= t2 << (7 - (uint(i) & 7)) - ctx.H[(uint(i) + 768) >> 3] |= t3 << (7 - (uint(i) & 7)) - } -} - -update_roundconstant :: proc(ctx: ^Jh_Context) { - tem: [64]byte - t: byte - for i := 0; i < 64; i += 1 { - tem[i] = SBOX[0][ctx.roundconstant[i]] - } - for i := 0; i < 64; i += 2 { - tem[i + 1] ~= ((tem[i] << 1) ~ (tem[i] >> 3) ~ ((tem[i] >> 2) & 2)) & 0xf - tem[i] ~= ((tem[i + 1] << 1) ~ (tem[i + 1] >> 3) ~ ((tem[i + 1] >> 2) & 2)) & 0xf - } - for i := 0; i < 64; i += 4 { - t = tem[i + 2] - tem[i + 2] = tem[i + 3] - tem[i + 3] = t - } - for i := 0; i < 32; i += 1 { - ctx.roundconstant[i] = tem[i << 1] - ctx.roundconstant[i + 32] = tem[(i << 1) + 1] - } - for i := 32; i < 64; i += 2 { - t = ctx.roundconstant[i] - ctx.roundconstant[i] = ctx.roundconstant[i + 1] - ctx.roundconstant[i + 1] = t - } -} - -R8 :: proc(ctx: ^Jh_Context) { - t: byte - tem, roundconstant_expanded: [256]byte - for i := u32(0); i < 256; i += 1 { - roundconstant_expanded[i] = (ctx.roundconstant[i >> 2] >> (3 - (i & 3)) ) & 1 - } - for i := 0; i < 256; i += 1 { - tem[i] = SBOX[roundconstant_expanded[i]][ctx.A[i]] - } - for i := 0; i < 256; i += 2 { - tem[i+1] ~= ((tem[i] << 1) ~ (tem[i] >> 3) ~ ((tem[i] >> 2) & 2)) & 0xf - tem[i] ~= ((tem[i + 1] << 1) ~ (tem[i + 1] >> 3) ~ ((tem[i + 1] >> 2) & 2)) & 0xf - } - for i := 0; i < 256; i += 4 { - t = tem[i + 2] - tem[i+2] = tem[i + 3] - tem[i+3] = t - } - for i := 0; i < 128; i += 1 { - ctx.A[i] = tem[i << 1] - ctx.A[i + 128] = tem[(i << 1) + 1] - } - for i := 128; i < 256; i += 2 { - t = ctx.A[i] - ctx.A[i] = ctx.A[i + 1] - ctx.A[i + 1] = t - } -} - -E8_initialgroup :: proc(ctx: ^Jh_Context) { - t0, t1, t2, t3: byte - tem: [256]byte - for i := u32(0); i < 256; i += 1 { - t0 = (ctx.H[i >> 3] >> (7 - (i & 7))) & 1 - t1 = (ctx.H[(i + 256) >> 3] >> (7 - (i & 7))) & 1 - t2 = (ctx.H[(i + 512) >> 3] >> (7 - (i & 7))) & 1 - t3 = (ctx.H[(i + 768) >> 3] >> (7 - (i & 7))) & 1 - tem[i] = (t0 << 3) | (t1 << 2) | (t2 << 1) | (t3 << 0) - } - for i := 0; i < 128; i += 1 { - ctx.A[i << 1] = tem[i] - ctx.A[(i << 1) + 1] = tem[i + 128] - } -} - -E8 :: proc(ctx: ^Jh_Context) { - for i := 0; i < 64; i += 1 { - ctx.roundconstant[i] = ROUNDCONSTANT_ZERO[i] - } - E8_initialgroup(ctx) - for i := 0; i < 42; i += 1 { - R8(ctx) - update_roundconstant(ctx) - } - E8_finaldegroup(ctx) -} - -F8 :: proc(ctx: ^Jh_Context) { - for i := 0; i < 64; i += 1 { - ctx.H[i] ~= ctx.buffer[i] - } - E8(ctx) - for i := 0; i < 64; i += 1 { - ctx.H[i + 64] ~= ctx.buffer[i] - } -} diff --git a/core/crypto/keccak/keccak.odin b/core/crypto/keccak/keccak.odin deleted file mode 100644 index 4c74858d2..000000000 --- a/core/crypto/keccak/keccak.odin +++ /dev/null @@ -1,374 +0,0 @@ -package keccak - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Interface for the Keccak hashing algorithm. - This is done because the padding in the SHA3 standard was changed by the NIST, resulting in a different output. -*/ - -import "core:os" -import "core:io" - -import "../_sha3" - - -/* - High level API -*/ - -DIGEST_SIZE_224 :: 28 -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_384 :: 48 -DIGEST_SIZE_512 :: 64 - -// hash_string_224 will hash the given input and return the -// computed hash -hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) -} - -// hash_bytes_224 will hash the given input and return the -// computed hash -hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_224 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_224 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) -} - -// hash_stream_224 will read the stream in chunks and compute a -// hash from its contents -hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - ctx.is_keccak = true - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_224 will read the file provided by the given handle -// and compute a hash -hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false -} - -hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, -} - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - ctx.is_keccak = true - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_384 will hash the given input and return the -// computed hash -hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) -} - -// hash_bytes_384 will hash the given input and return the -// computed hash -hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_384 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_384 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) -} - -// hash_stream_384 will read the stream in chunks and compute a -// hash from its contents -hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { - hash: [DIGEST_SIZE_384]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - ctx.is_keccak = true - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_384 will read the file provided by the given handle -// and compute a hash -hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false -} - -hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, -} - -// hash_string_512 will hash the given input and return the -// computed hash -hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) -} - -// hash_bytes_512 will hash the given input and return the -// computed hash -hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_512 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_512 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - ctx.is_keccak = true - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) -} - -// hash_stream_512 will read the stream in chunks and compute a -// hash from its contents -hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - ctx.is_keccak = true - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_512 will read the file provided by the given handle -// and compute a hash -hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false -} - -hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, -} - -/* - Low level API -*/ - -Keccak_Context :: _sha3.Sha3_Context - -init :: proc(ctx: ^_sha3.Sha3_Context) { - ctx.is_keccak = true - _sha3.init(ctx) -} - -update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) { - _sha3.update(ctx, data) -} - -final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) { - _sha3.final(ctx, hash) -} diff --git a/core/crypto/legacy/README.md b/core/crypto/legacy/README.md new file mode 100644 index 000000000..e1ba6f54b --- /dev/null +++ b/core/crypto/legacy/README.md @@ -0,0 +1,10 @@ +# crypto/legacy + +These are algorithms that are shipped solely for the purpose of +interoperability with legacy systems. The use of these packages in +any other capacity is discouraged, especially those that are known +to be broken. + +- keccak - The draft version of the algorithm that became SHA-3 +- MD5 - Broken (https://eprint.iacr.org/2005/075) +- SHA-1 - Broken (https://eprint.iacr.org/2017/190) diff --git a/core/crypto/legacy/keccak/keccak.odin b/core/crypto/legacy/keccak/keccak.odin new file mode 100644 index 000000000..09db853a6 --- /dev/null +++ b/core/crypto/legacy/keccak/keccak.odin @@ -0,0 +1,377 @@ +package keccak + +/* + Copyright 2021 zhibog + Made available under the BSD-3 license. + + List of contributors: + zhibog, dotbmp: Initial implementation. + + Interface for the Keccak hashing algorithm. + This is done because the padding in the SHA3 standard was changed by the NIST, resulting in a different output. +*/ + +import "core:io" +import "core:os" + +import "../../_sha3" + +/* + High level API +*/ + +DIGEST_SIZE_224 :: 28 +DIGEST_SIZE_256 :: 32 +DIGEST_SIZE_384 :: 48 +DIGEST_SIZE_512 :: 64 + +// hash_string_224 will hash the given input and return the +// computed hash +hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { + return hash_bytes_224(transmute([]byte)(data)) +} + +// hash_bytes_224 will hash the given input and return the +// computed hash +hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { + hash: [DIGEST_SIZE_224]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer_224 will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer_224(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer_224 will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream_224 will read the stream in chunks and compute a +// hash from its contents +hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { + hash: [DIGEST_SIZE_224]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + ctx.is_keccak = true + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file_224 will read the file provided by the given handle +// and compute a hash +hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { + if !load_at_once { + return hash_stream_224(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_224(buf[:]), ok + } + } + return [DIGEST_SIZE_224]byte{}, false +} + +hash_224 :: proc { + hash_stream_224, + hash_file_224, + hash_bytes_224, + hash_string_224, + hash_bytes_to_buffer_224, + hash_string_to_buffer_224, +} + +// hash_string_256 will hash the given input and return the +// computed hash +hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { + return hash_bytes_256(transmute([]byte)(data)) +} + +// hash_bytes_256 will hash the given input and return the +// computed hash +hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer_256 will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer_256 will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream_256 will read the stream in chunks and compute a +// hash from its contents +hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + ctx.is_keccak = true + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file_256 will read the file provided by the given handle +// and compute a hash +hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { + if !load_at_once { + return hash_stream_256(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_256(buf[:]), ok + } + } + return [DIGEST_SIZE_256]byte{}, false +} + +hash_256 :: proc { + hash_stream_256, + hash_file_256, + hash_bytes_256, + hash_string_256, + hash_bytes_to_buffer_256, + hash_string_to_buffer_256, +} + +// hash_string_384 will hash the given input and return the +// computed hash +hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { + return hash_bytes_384(transmute([]byte)(data)) +} + +// hash_bytes_384 will hash the given input and return the +// computed hash +hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { + hash: [DIGEST_SIZE_384]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer_384 will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer_384(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer_384 will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream_384 will read the stream in chunks and compute a +// hash from its contents +hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { + hash: [DIGEST_SIZE_384]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + ctx.is_keccak = true + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file_384 will read the file provided by the given handle +// and compute a hash +hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { + if !load_at_once { + return hash_stream_384(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_384(buf[:]), ok + } + } + return [DIGEST_SIZE_384]byte{}, false +} + +hash_384 :: proc { + hash_stream_384, + hash_file_384, + hash_bytes_384, + hash_string_384, + hash_bytes_to_buffer_384, + hash_string_to_buffer_384, +} + +// hash_string_512 will hash the given input and return the +// computed hash +hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { + return hash_bytes_512(transmute([]byte)(data)) +} + +// hash_bytes_512 will hash the given input and return the +// computed hash +hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { + hash: [DIGEST_SIZE_512]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer_512 will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer_512 will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + ctx.is_keccak = true + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream_512 will read the stream in chunks and compute a +// hash from its contents +hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { + hash: [DIGEST_SIZE_512]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + ctx.is_keccak = true + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file_512 will read the file provided by the given handle +// and compute a hash +hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { + if !load_at_once { + return hash_stream_512(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_512(buf[:]), ok + } + } + return [DIGEST_SIZE_512]byte{}, false +} + +hash_512 :: proc { + hash_stream_512, + hash_file_512, + hash_bytes_512, + hash_string_512, + hash_bytes_to_buffer_512, + hash_string_to_buffer_512, +} + +/* + Low level API +*/ + +Context :: _sha3.Sha3_Context + +init :: proc(ctx: ^Context) { + ctx.is_keccak = true + _sha3.init(ctx) +} + +update :: proc(ctx: ^Context, data: []byte) { + _sha3.update(ctx, data) +} + +final :: proc(ctx: ^Context, hash: []byte) { + _sha3.final(ctx, hash) +} diff --git a/core/crypto/legacy/md5/md5.odin b/core/crypto/legacy/md5/md5.odin new file mode 100644 index 000000000..69ae087e4 --- /dev/null +++ b/core/crypto/legacy/md5/md5.odin @@ -0,0 +1,295 @@ +package md5 + +/* + Copyright 2021 zhibog + Made available under the BSD-3 license. + + List of contributors: + zhibog, dotbmp: Initial implementation. + + Implementation of the MD5 hashing algorithm, as defined in RFC 1321 +*/ + +import "core:encoding/endian" +import "core:io" +import "core:math/bits" +import "core:mem" +import "core:os" + +/* + High level API +*/ + +DIGEST_SIZE :: 16 + +// hash_string will hash the given input and return the +// computed hash +hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { + return hash_bytes(transmute([]byte)(data)) +} + +// hash_bytes will hash the given input and return the +// computed hash +hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer :: proc(data, hash: []byte) { + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream will read the stream in chunks and compute a +// hash from its contents +hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file will read the file provided by the given handle +// and compute a hash +hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { + if !load_at_once { + return hash_stream(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes(buf[:]), ok + } + } + return [DIGEST_SIZE]byte{}, false +} + +hash :: proc { + hash_stream, + hash_file, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, +} + +/* + Low level API +*/ + +init :: proc(ctx: ^Context) { + ctx.state[0] = 0x67452301 + ctx.state[1] = 0xefcdab89 + ctx.state[2] = 0x98badcfe + ctx.state[3] = 0x10325476 + + ctx.bitlen = 0 + ctx.datalen = 0 + + ctx.is_initialized = true +} + +update :: proc(ctx: ^Context, data: []byte) { + assert(ctx.is_initialized) + + for i := 0; i < len(data); i += 1 { + ctx.data[ctx.datalen] = data[i] + ctx.datalen += 1 + if (ctx.datalen == BLOCK_SIZE) { + transform(ctx, ctx.data[:]) + ctx.bitlen += 512 + ctx.datalen = 0 + } + } +} + +final :: proc(ctx: ^Context, hash: []byte) { + assert(ctx.is_initialized) + + if len(hash) < DIGEST_SIZE { + panic("crypto/md5: invalid destination digest size") + } + + i := ctx.datalen + + if ctx.datalen < 56 { + ctx.data[i] = 0x80 + i += 1 + for i < 56 { + ctx.data[i] = 0x00 + i += 1 + } + } else if ctx.datalen >= 56 { + ctx.data[i] = 0x80 + i += 1 + for i < BLOCK_SIZE { + ctx.data[i] = 0x00 + i += 1 + } + transform(ctx, ctx.data[:]) + mem.set(&ctx.data, 0, 56) + } + + ctx.bitlen += u64(ctx.datalen * 8) + endian.unchecked_put_u64le(ctx.data[56:], ctx.bitlen) + transform(ctx, ctx.data[:]) + + for i = 0; i < DIGEST_SIZE / 4; i += 1 { + endian.unchecked_put_u32le(hash[i * 4:], ctx.state[i]) + } + + ctx.is_initialized = false +} + +/* + MD5 implementation +*/ + +BLOCK_SIZE :: 64 + +Context :: struct { + data: [BLOCK_SIZE]byte, + state: [4]u32, + bitlen: u64, + datalen: u32, + + is_initialized: bool, +} + +/* + @note(zh): F, G, H and I, as mentioned in the RFC, have been inlined into FF, GG, HH + and II respectively, instead of declaring them separately. +*/ + +@(private) +FF :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { + return b + bits.rotate_left32(a + ((b & c) | (~b & d)) + m + t, s) +} + +@(private) +GG :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { + return b + bits.rotate_left32(a + ((b & d) | (c & ~d)) + m + t, s) +} + +@(private) +HH :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { + return b + bits.rotate_left32(a + (b ~ c ~ d) + m + t, s) +} + +@(private) +II :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { + return b + bits.rotate_left32(a + (c ~ (b | ~d)) + m + t, s) +} + +@(private) +transform :: proc "contextless" (ctx: ^Context, data: []byte) { + m: [DIGEST_SIZE]u32 + + for i := 0; i < DIGEST_SIZE; i += 1 { + m[i] = endian.unchecked_get_u32le(data[i * 4:]) + } + + a := ctx.state[0] + b := ctx.state[1] + c := ctx.state[2] + d := ctx.state[3] + + a = FF(a, b, c, d, m[0], 7, 0xd76aa478) + d = FF(d, a, b, c, m[1], 12, 0xe8c7b756) + c = FF(c, d, a, b, m[2], 17, 0x242070db) + b = FF(b, c, d, a, m[3], 22, 0xc1bdceee) + a = FF(a, b, c, d, m[4], 7, 0xf57c0faf) + d = FF(d, a, b, c, m[5], 12, 0x4787c62a) + c = FF(c, d, a, b, m[6], 17, 0xa8304613) + b = FF(b, c, d, a, m[7], 22, 0xfd469501) + a = FF(a, b, c, d, m[8], 7, 0x698098d8) + d = FF(d, a, b, c, m[9], 12, 0x8b44f7af) + c = FF(c, d, a, b, m[10], 17, 0xffff5bb1) + b = FF(b, c, d, a, m[11], 22, 0x895cd7be) + a = FF(a, b, c, d, m[12], 7, 0x6b901122) + d = FF(d, a, b, c, m[13], 12, 0xfd987193) + c = FF(c, d, a, b, m[14], 17, 0xa679438e) + b = FF(b, c, d, a, m[15], 22, 0x49b40821) + + a = GG(a, b, c, d, m[1], 5, 0xf61e2562) + d = GG(d, a, b, c, m[6], 9, 0xc040b340) + c = GG(c, d, a, b, m[11], 14, 0x265e5a51) + b = GG(b, c, d, a, m[0], 20, 0xe9b6c7aa) + a = GG(a, b, c, d, m[5], 5, 0xd62f105d) + d = GG(d, a, b, c, m[10], 9, 0x02441453) + c = GG(c, d, a, b, m[15], 14, 0xd8a1e681) + b = GG(b, c, d, a, m[4], 20, 0xe7d3fbc8) + a = GG(a, b, c, d, m[9], 5, 0x21e1cde6) + d = GG(d, a, b, c, m[14], 9, 0xc33707d6) + c = GG(c, d, a, b, m[3], 14, 0xf4d50d87) + b = GG(b, c, d, a, m[8], 20, 0x455a14ed) + a = GG(a, b, c, d, m[13], 5, 0xa9e3e905) + d = GG(d, a, b, c, m[2], 9, 0xfcefa3f8) + c = GG(c, d, a, b, m[7], 14, 0x676f02d9) + b = GG(b, c, d, a, m[12], 20, 0x8d2a4c8a) + + a = HH(a, b, c, d, m[5], 4, 0xfffa3942) + d = HH(d, a, b, c, m[8], 11, 0x8771f681) + c = HH(c, d, a, b, m[11], 16, 0x6d9d6122) + b = HH(b, c, d, a, m[14], 23, 0xfde5380c) + a = HH(a, b, c, d, m[1], 4, 0xa4beea44) + d = HH(d, a, b, c, m[4], 11, 0x4bdecfa9) + c = HH(c, d, a, b, m[7], 16, 0xf6bb4b60) + b = HH(b, c, d, a, m[10], 23, 0xbebfbc70) + a = HH(a, b, c, d, m[13], 4, 0x289b7ec6) + d = HH(d, a, b, c, m[0], 11, 0xeaa127fa) + c = HH(c, d, a, b, m[3], 16, 0xd4ef3085) + b = HH(b, c, d, a, m[6], 23, 0x04881d05) + a = HH(a, b, c, d, m[9], 4, 0xd9d4d039) + d = HH(d, a, b, c, m[12], 11, 0xe6db99e5) + c = HH(c, d, a, b, m[15], 16, 0x1fa27cf8) + b = HH(b, c, d, a, m[2], 23, 0xc4ac5665) + + a = II(a, b, c, d, m[0], 6, 0xf4292244) + d = II(d, a, b, c, m[7], 10, 0x432aff97) + c = II(c, d, a, b, m[14], 15, 0xab9423a7) + b = II(b, c, d, a, m[5], 21, 0xfc93a039) + a = II(a, b, c, d, m[12], 6, 0x655b59c3) + d = II(d, a, b, c, m[3], 10, 0x8f0ccc92) + c = II(c, d, a, b, m[10], 15, 0xffeff47d) + b = II(b, c, d, a, m[1], 21, 0x85845dd1) + a = II(a, b, c, d, m[8], 6, 0x6fa87e4f) + d = II(d, a, b, c, m[15], 10, 0xfe2ce6e0) + c = II(c, d, a, b, m[6], 15, 0xa3014314) + b = II(b, c, d, a, m[13], 21, 0x4e0811a1) + a = II(a, b, c, d, m[4], 6, 0xf7537e82) + d = II(d, a, b, c, m[11], 10, 0xbd3af235) + c = II(c, d, a, b, m[2], 15, 0x2ad7d2bb) + b = II(b, c, d, a, m[9], 21, 0xeb86d391) + + ctx.state[0] += a + ctx.state[1] += b + ctx.state[2] += c + ctx.state[3] += d +} diff --git a/core/crypto/legacy/sha1/sha1.odin b/core/crypto/legacy/sha1/sha1.odin new file mode 100644 index 000000000..6c4407067 --- /dev/null +++ b/core/crypto/legacy/sha1/sha1.odin @@ -0,0 +1,252 @@ +package sha1 + +/* + Copyright 2021 zhibog + Made available under the BSD-3 license. + + List of contributors: + zhibog, dotbmp: Initial implementation. + + Implementation of the SHA1 hashing algorithm, as defined in RFC 3174 +*/ + +import "core:encoding/endian" +import "core:io" +import "core:math/bits" +import "core:mem" +import "core:os" + +/* + High level API +*/ + +DIGEST_SIZE :: 20 + +// hash_string will hash the given input and return the +// computed hash +hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { + return hash_bytes(transmute([]byte)(data)) +} + +// hash_bytes will hash the given input and return the +// computed hash +hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer :: proc(data, hash: []byte) { + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream will read the stream in chunks and compute a +// hash from its contents +hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file will read the file provided by the given handle +// and compute a hash +hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { + if !load_at_once { + return hash_stream(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes(buf[:]), ok + } + } + return [DIGEST_SIZE]byte{}, false +} + +hash :: proc { + hash_stream, + hash_file, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, +} + +/* + Low level API +*/ + +init :: proc(ctx: ^Context) { + ctx.state[0] = 0x67452301 + ctx.state[1] = 0xefcdab89 + ctx.state[2] = 0x98badcfe + ctx.state[3] = 0x10325476 + ctx.state[4] = 0xc3d2e1f0 + ctx.k[0] = 0x5a827999 + ctx.k[1] = 0x6ed9eba1 + ctx.k[2] = 0x8f1bbcdc + ctx.k[3] = 0xca62c1d6 + + ctx.datalen = 0 + ctx.bitlen = 0 + + ctx.is_initialized = true +} + +update :: proc(ctx: ^Context, data: []byte) { + assert(ctx.is_initialized) + + for i := 0; i < len(data); i += 1 { + ctx.data[ctx.datalen] = data[i] + ctx.datalen += 1 + if (ctx.datalen == BLOCK_SIZE) { + transform(ctx, ctx.data[:]) + ctx.bitlen += 512 + ctx.datalen = 0 + } + } +} + +final :: proc(ctx: ^Context, hash: []byte) { + assert(ctx.is_initialized) + + if len(hash) < DIGEST_SIZE { + panic("crypto/sha1: invalid destination digest size") + } + + i := ctx.datalen + + if ctx.datalen < 56 { + ctx.data[i] = 0x80 + i += 1 + for i < 56 { + ctx.data[i] = 0x00 + i += 1 + } + } else { + ctx.data[i] = 0x80 + i += 1 + for i < BLOCK_SIZE { + ctx.data[i] = 0x00 + i += 1 + } + transform(ctx, ctx.data[:]) + mem.set(&ctx.data, 0, 56) + } + + ctx.bitlen += u64(ctx.datalen * 8) + endian.unchecked_put_u64be(ctx.data[56:], ctx.bitlen) + transform(ctx, ctx.data[:]) + + for i = 0; i < DIGEST_SIZE / 4; i += 1 { + endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i]) + } + + ctx.is_initialized = false +} + +/* + SHA1 implementation +*/ + +BLOCK_SIZE :: 64 + +Context :: struct { + data: [BLOCK_SIZE]byte, + datalen: u32, + bitlen: u64, + state: [5]u32, + k: [4]u32, + + is_initialized: bool, +} + +@(private) +transform :: proc "contextless" (ctx: ^Context, data: []byte) { + a, b, c, d, e, i, t: u32 + m: [80]u32 + + for i = 0; i < 16; i += 1 { + m[i] = endian.unchecked_get_u32be(data[i * 4:]) + } + for i < 80 { + m[i] = (m[i - 3] ~ m[i - 8] ~ m[i - 14] ~ m[i - 16]) + m[i] = (m[i] << 1) | (m[i] >> 31) + i += 1 + } + + a = ctx.state[0] + b = ctx.state[1] + c = ctx.state[2] + d = ctx.state[3] + e = ctx.state[4] + + for i = 0; i < 20; i += 1 { + t = bits.rotate_left32(a, 5) + ((b & c) ~ (~b & d)) + e + ctx.k[0] + m[i] + e = d + d = c + c = bits.rotate_left32(b, 30) + b = a + a = t + } + for i < 40 { + t = bits.rotate_left32(a, 5) + (b ~ c ~ d) + e + ctx.k[1] + m[i] + e = d + d = c + c = bits.rotate_left32(b, 30) + b = a + a = t + i += 1 + } + for i < 60 { + t = bits.rotate_left32(a, 5) + ((b & c) ~ (b & d) ~ (c & d)) + e + ctx.k[2] + m[i] + e = d + d = c + c = bits.rotate_left32(b, 30) + b = a + a = t + i += 1 + } + for i < 80 { + t = bits.rotate_left32(a, 5) + (b ~ c ~ d) + e + ctx.k[3] + m[i] + e = d + d = c + c = bits.rotate_left32(b, 30) + b = a + a = t + i += 1 + } + + ctx.state[0] += a + ctx.state[1] += b + ctx.state[2] += c + ctx.state[3] += d + ctx.state[4] += e +} diff --git a/core/crypto/md2/md2.odin b/core/crypto/md2/md2.odin deleted file mode 100644 index 4942183e1..000000000 --- a/core/crypto/md2/md2.odin +++ /dev/null @@ -1,182 +0,0 @@ -package md2 - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the MD2 hashing algorithm, as defined in RFC 1319 -*/ - -import "core:os" -import "core:io" - -/* - High level API -*/ - -DIGEST_SIZE :: 16 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Md2_Context - // init(&ctx) No-op - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Md2_Context - // init(&ctx) No-op - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Md2_Context - // init(&ctx) No-op - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -@(warning="Init is a no-op for MD2") -init :: proc(ctx: ^Md2_Context) { - // No action needed here -} - -update :: proc(ctx: ^Md2_Context, data: []byte) { - for i := 0; i < len(data); i += 1 { - ctx.data[ctx.datalen] = data[i] - ctx.datalen += 1 - if (ctx.datalen == DIGEST_SIZE) { - transform(ctx, ctx.data[:]) - ctx.datalen = 0 - } - } -} - -final :: proc(ctx: ^Md2_Context, hash: []byte) { - to_pad := byte(DIGEST_SIZE - ctx.datalen) - for ctx.datalen < DIGEST_SIZE { - ctx.data[ctx.datalen] = to_pad - ctx.datalen += 1 - } - transform(ctx, ctx.data[:]) - transform(ctx, ctx.checksum[:]) - for i := 0; i < DIGEST_SIZE; i += 1 { - hash[i] = ctx.state[i] - } -} - -/* - MD2 implementation -*/ - -Md2_Context :: struct { - data: [DIGEST_SIZE]byte, - state: [DIGEST_SIZE * 3]byte, - checksum: [DIGEST_SIZE]byte, - datalen: int, -} - -PI_TABLE := [?]byte { - 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, - 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, - 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, - 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, - 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, - 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, - 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, - 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, - 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, - 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, - 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, - 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, - 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, - 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, - 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, - 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, - 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, - 20, -} - -transform :: proc(ctx: ^Md2_Context, data: []byte) { - j,k,t: byte - for j = 0; j < DIGEST_SIZE; j += 1 { - ctx.state[j + DIGEST_SIZE] = data[j] - ctx.state[j + DIGEST_SIZE * 2] = (ctx.state[j + DIGEST_SIZE] ~ ctx.state[j]) - } - t = 0 - for j = 0; j < DIGEST_SIZE + 2; j += 1 { - for k = 0; k < DIGEST_SIZE * 3; k += 1 { - ctx.state[k] ~= PI_TABLE[t] - t = ctx.state[k] - } - t = (t + j) & 0xff - } - t = ctx.checksum[DIGEST_SIZE - 1] - for j = 0; j < DIGEST_SIZE; j += 1 { - ctx.checksum[j] ~= PI_TABLE[data[j] ~ t] - t = ctx.checksum[j] - } -} diff --git a/core/crypto/md4/md4.odin b/core/crypto/md4/md4.odin deleted file mode 100644 index 8efdbb5a5..000000000 --- a/core/crypto/md4/md4.odin +++ /dev/null @@ -1,263 +0,0 @@ -package md4 - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - Jeroen van Rijn: Context design to be able to change from Odin implementation to bindings. - - Implementation of the MD4 hashing algorithm, as defined in RFC 1320 -*/ - -import "core:mem" -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE :: 16 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Md4_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Md4_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Md4_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Md4_Context) { - ctx.state[0] = 0x67452301 - ctx.state[1] = 0xefcdab89 - ctx.state[2] = 0x98badcfe - ctx.state[3] = 0x10325476 -} - -update :: proc(ctx: ^Md4_Context, data: []byte) { - for i := 0; i < len(data); i += 1 { - ctx.data[ctx.datalen] = data[i] - ctx.datalen += 1 - if(ctx.datalen == BLOCK_SIZE) { - transform(ctx, ctx.data[:]) - ctx.bitlen += 512 - ctx.datalen = 0 - } - } -} - -final :: proc(ctx: ^Md4_Context, hash: []byte) { - i := ctx.datalen - if ctx.datalen < 56 { - ctx.data[i] = 0x80 - i += 1 - for i < 56 { - ctx.data[i] = 0x00 - i += 1 - } - } else if ctx.datalen >= 56 { - ctx.data[i] = 0x80 - i += 1 - for i < BLOCK_SIZE { - ctx.data[i] = 0x00 - i += 1 - } - transform(ctx, ctx.data[:]) - mem.set(&ctx.data, 0, 56) - } - - ctx.bitlen += u64(ctx.datalen * 8) - ctx.data[56] = byte(ctx.bitlen) - ctx.data[57] = byte(ctx.bitlen >> 8) - ctx.data[58] = byte(ctx.bitlen >> 16) - ctx.data[59] = byte(ctx.bitlen >> 24) - ctx.data[60] = byte(ctx.bitlen >> 32) - ctx.data[61] = byte(ctx.bitlen >> 40) - ctx.data[62] = byte(ctx.bitlen >> 48) - ctx.data[63] = byte(ctx.bitlen >> 56) - transform(ctx, ctx.data[:]) - - for i = 0; i < 4; i += 1 { - hash[i] = byte(ctx.state[0] >> (i * 8)) & 0x000000ff - hash[i + 4] = byte(ctx.state[1] >> (i * 8)) & 0x000000ff - hash[i + 8] = byte(ctx.state[2] >> (i * 8)) & 0x000000ff - hash[i + 12] = byte(ctx.state[3] >> (i * 8)) & 0x000000ff - } -} - -/* - MD4 implementation -*/ - -BLOCK_SIZE :: 64 - -Md4_Context :: struct { - data: [64]byte, - state: [4]u32, - bitlen: u64, - datalen: u32, -} - -/* - @note(zh): F, G and H, as mentioned in the RFC, have been inlined into FF, GG - and HH respectively, instead of declaring them separately. -*/ - -FF :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 { - return util.ROTL32(a + ((b & c) | (~b & d)) + x, s) -} - -GG :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 { - return util.ROTL32(a + ((b & c) | (b & d) | (c & d)) + x + 0x5a827999, s) -} - -HH :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 { - return util.ROTL32(a + (b ~ c ~ d) + x + 0x6ed9eba1, s) -} - -transform :: proc(ctx: ^Md4_Context, data: []byte) { - a, b, c, d, i, j: u32 - m: [DIGEST_SIZE]u32 - - for i, j = 0, 0; i < DIGEST_SIZE; i += 1 { - m[i] = u32(data[j]) | (u32(data[j + 1]) << 8) | (u32(data[j + 2]) << 16) | (u32(data[j + 3]) << 24) - j += 4 - } - - a = ctx.state[0] - b = ctx.state[1] - c = ctx.state[2] - d = ctx.state[3] - - a = FF(a, b, c, d, m[0], 3) - d = FF(d, a, b, c, m[1], 7) - c = FF(c, d, a, b, m[2], 11) - b = FF(b, c, d, a, m[3], 19) - a = FF(a, b, c, d, m[4], 3) - d = FF(d, a, b, c, m[5], 7) - c = FF(c, d, a, b, m[6], 11) - b = FF(b, c, d, a, m[7], 19) - a = FF(a, b, c, d, m[8], 3) - d = FF(d, a, b, c, m[9], 7) - c = FF(c, d, a, b, m[10], 11) - b = FF(b, c, d, a, m[11], 19) - a = FF(a, b, c, d, m[12], 3) - d = FF(d, a, b, c, m[13], 7) - c = FF(c, d, a, b, m[14], 11) - b = FF(b, c, d, a, m[15], 19) - - a = GG(a, b, c, d, m[0], 3) - d = GG(d, a, b, c, m[4], 5) - c = GG(c, d, a, b, m[8], 9) - b = GG(b, c, d, a, m[12], 13) - a = GG(a, b, c, d, m[1], 3) - d = GG(d, a, b, c, m[5], 5) - c = GG(c, d, a, b, m[9], 9) - b = GG(b, c, d, a, m[13], 13) - a = GG(a, b, c, d, m[2], 3) - d = GG(d, a, b, c, m[6], 5) - c = GG(c, d, a, b, m[10], 9) - b = GG(b, c, d, a, m[14], 13) - a = GG(a, b, c, d, m[3], 3) - d = GG(d, a, b, c, m[7], 5) - c = GG(c, d, a, b, m[11], 9) - b = GG(b, c, d, a, m[15], 13) - - a = HH(a, b, c, d, m[0], 3) - d = HH(d, a, b, c, m[8], 9) - c = HH(c, d, a, b, m[4], 11) - b = HH(b, c, d, a, m[12], 15) - a = HH(a, b, c, d, m[2], 3) - d = HH(d, a, b, c, m[10], 9) - c = HH(c, d, a, b, m[6], 11) - b = HH(b, c, d, a, m[14], 15) - a = HH(a, b, c, d, m[1], 3) - d = HH(d, a, b, c, m[9], 9) - c = HH(c, d, a, b, m[5], 11) - b = HH(b, c, d, a, m[13], 15) - a = HH(a, b, c, d, m[3], 3) - d = HH(d, a, b, c, m[11], 9) - c = HH(c, d, a, b, m[7], 11) - b = HH(b, c, d, a, m[15], 15) - - ctx.state[0] += a - ctx.state[1] += b - ctx.state[2] += c - ctx.state[3] += d -} diff --git a/core/crypto/md5/md5.odin b/core/crypto/md5/md5.odin deleted file mode 100644 index 858480b04..000000000 --- a/core/crypto/md5/md5.odin +++ /dev/null @@ -1,285 +0,0 @@ -package md5 - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the MD5 hashing algorithm, as defined in RFC 1321 -*/ - -import "core:mem" -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE :: 16 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Md5_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Md5_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Md5_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Md5_Context) { - ctx.state[0] = 0x67452301 - ctx.state[1] = 0xefcdab89 - ctx.state[2] = 0x98badcfe - ctx.state[3] = 0x10325476 -} - -update :: proc(ctx: ^Md5_Context, data: []byte) { - for i := 0; i < len(data); i += 1 { - ctx.data[ctx.datalen] = data[i] - ctx.datalen += 1 - if(ctx.datalen == BLOCK_SIZE) { - transform(ctx, ctx.data[:]) - ctx.bitlen += 512 - ctx.datalen = 0 - } - } -} - -final :: proc(ctx: ^Md5_Context, hash: []byte){ - i : u32 - i = ctx.datalen - - if ctx.datalen < 56 { - ctx.data[i] = 0x80 - i += 1 - for i < 56 { - ctx.data[i] = 0x00 - i += 1 - } - } else if ctx.datalen >= 56 { - ctx.data[i] = 0x80 - i += 1 - for i < BLOCK_SIZE { - ctx.data[i] = 0x00 - i += 1 - } - transform(ctx, ctx.data[:]) - mem.set(&ctx.data, 0, 56) - } - - ctx.bitlen += u64(ctx.datalen * 8) - ctx.data[56] = byte(ctx.bitlen) - ctx.data[57] = byte(ctx.bitlen >> 8) - ctx.data[58] = byte(ctx.bitlen >> 16) - ctx.data[59] = byte(ctx.bitlen >> 24) - ctx.data[60] = byte(ctx.bitlen >> 32) - ctx.data[61] = byte(ctx.bitlen >> 40) - ctx.data[62] = byte(ctx.bitlen >> 48) - ctx.data[63] = byte(ctx.bitlen >> 56) - transform(ctx, ctx.data[:]) - - for i = 0; i < 4; i += 1 { - hash[i] = byte(ctx.state[0] >> (i * 8)) & 0x000000ff - hash[i + 4] = byte(ctx.state[1] >> (i * 8)) & 0x000000ff - hash[i + 8] = byte(ctx.state[2] >> (i * 8)) & 0x000000ff - hash[i + 12] = byte(ctx.state[3] >> (i * 8)) & 0x000000ff - } -} - -/* - MD4 implementation -*/ - -BLOCK_SIZE :: 64 - -Md5_Context :: struct { - data: [BLOCK_SIZE]byte, - state: [4]u32, - bitlen: u64, - datalen: u32, -} - -/* - @note(zh): F, G, H and I, as mentioned in the RFC, have been inlined into FF, GG, HH - and II respectively, instead of declaring them separately. -*/ - -FF :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { - return b + util.ROTL32(a + ((b & c) | (~b & d)) + m + t, s) -} - -GG :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { - return b + util.ROTL32(a + ((b & d) | (c & ~d)) + m + t, s) -} - -HH :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { - return b + util.ROTL32(a + (b ~ c ~ d) + m + t, s) -} - -II :: #force_inline proc "contextless" (a, b, c, d, m: u32, s: int, t: u32) -> u32 { - return b + util.ROTL32(a + (c ~ (b | ~d)) + m + t, s) -} - -transform :: proc(ctx: ^Md5_Context, data: []byte) { - i, j: u32 - m: [DIGEST_SIZE]u32 - - for i, j = 0, 0; i < DIGEST_SIZE; i+=1 { - m[i] = u32(data[j]) + u32(data[j + 1]) << 8 + u32(data[j + 2]) << 16 + u32(data[j + 3]) << 24 - j += 4 - } - - a := ctx.state[0] - b := ctx.state[1] - c := ctx.state[2] - d := ctx.state[3] - - a = FF(a, b, c, d, m[0], 7, 0xd76aa478) - d = FF(d, a, b, c, m[1], 12, 0xe8c7b756) - c = FF(c, d, a, b, m[2], 17, 0x242070db) - b = FF(b, c, d, a, m[3], 22, 0xc1bdceee) - a = FF(a, b, c, d, m[4], 7, 0xf57c0faf) - d = FF(d, a, b, c, m[5], 12, 0x4787c62a) - c = FF(c, d, a, b, m[6], 17, 0xa8304613) - b = FF(b, c, d, a, m[7], 22, 0xfd469501) - a = FF(a, b, c, d, m[8], 7, 0x698098d8) - d = FF(d, a, b, c, m[9], 12, 0x8b44f7af) - c = FF(c, d, a, b, m[10], 17, 0xffff5bb1) - b = FF(b, c, d, a, m[11], 22, 0x895cd7be) - a = FF(a, b, c, d, m[12], 7, 0x6b901122) - d = FF(d, a, b, c, m[13], 12, 0xfd987193) - c = FF(c, d, a, b, m[14], 17, 0xa679438e) - b = FF(b, c, d, a, m[15], 22, 0x49b40821) - - a = GG(a, b, c, d, m[1], 5, 0xf61e2562) - d = GG(d, a, b, c, m[6], 9, 0xc040b340) - c = GG(c, d, a, b, m[11], 14, 0x265e5a51) - b = GG(b, c, d, a, m[0], 20, 0xe9b6c7aa) - a = GG(a, b, c, d, m[5], 5, 0xd62f105d) - d = GG(d, a, b, c, m[10], 9, 0x02441453) - c = GG(c, d, a, b, m[15], 14, 0xd8a1e681) - b = GG(b, c, d, a, m[4], 20, 0xe7d3fbc8) - a = GG(a, b, c, d, m[9], 5, 0x21e1cde6) - d = GG(d, a, b, c, m[14], 9, 0xc33707d6) - c = GG(c, d, a, b, m[3], 14, 0xf4d50d87) - b = GG(b, c, d, a, m[8], 20, 0x455a14ed) - a = GG(a, b, c, d, m[13], 5, 0xa9e3e905) - d = GG(d, a, b, c, m[2], 9, 0xfcefa3f8) - c = GG(c, d, a, b, m[7], 14, 0x676f02d9) - b = GG(b, c, d, a, m[12], 20, 0x8d2a4c8a) - - a = HH(a, b, c, d, m[5], 4, 0xfffa3942) - d = HH(d, a, b, c, m[8], 11, 0x8771f681) - c = HH(c, d, a, b, m[11], 16, 0x6d9d6122) - b = HH(b, c, d, a, m[14], 23, 0xfde5380c) - a = HH(a, b, c, d, m[1], 4, 0xa4beea44) - d = HH(d, a, b, c, m[4], 11, 0x4bdecfa9) - c = HH(c, d, a, b, m[7], 16, 0xf6bb4b60) - b = HH(b, c, d, a, m[10], 23, 0xbebfbc70) - a = HH(a, b, c, d, m[13], 4, 0x289b7ec6) - d = HH(d, a, b, c, m[0], 11, 0xeaa127fa) - c = HH(c, d, a, b, m[3], 16, 0xd4ef3085) - b = HH(b, c, d, a, m[6], 23, 0x04881d05) - a = HH(a, b, c, d, m[9], 4, 0xd9d4d039) - d = HH(d, a, b, c, m[12], 11, 0xe6db99e5) - c = HH(c, d, a, b, m[15], 16, 0x1fa27cf8) - b = HH(b, c, d, a, m[2], 23, 0xc4ac5665) - - a = II(a, b, c, d, m[0], 6, 0xf4292244) - d = II(d, a, b, c, m[7], 10, 0x432aff97) - c = II(c, d, a, b, m[14], 15, 0xab9423a7) - b = II(b, c, d, a, m[5], 21, 0xfc93a039) - a = II(a, b, c, d, m[12], 6, 0x655b59c3) - d = II(d, a, b, c, m[3], 10, 0x8f0ccc92) - c = II(c, d, a, b, m[10], 15, 0xffeff47d) - b = II(b, c, d, a, m[1], 21, 0x85845dd1) - a = II(a, b, c, d, m[8], 6, 0x6fa87e4f) - d = II(d, a, b, c, m[15], 10, 0xfe2ce6e0) - c = II(c, d, a, b, m[6], 15, 0xa3014314) - b = II(b, c, d, a, m[13], 21, 0x4e0811a1) - a = II(a, b, c, d, m[4], 6, 0xf7537e82) - d = II(d, a, b, c, m[11], 10, 0xbd3af235) - c = II(c, d, a, b, m[2], 15, 0x2ad7d2bb) - b = II(b, c, d, a, m[9], 21, 0xeb86d391) - - ctx.state[0] += a - ctx.state[1] += b - ctx.state[2] += c - ctx.state[3] += d -} diff --git a/core/crypto/poly1305/poly1305.odin b/core/crypto/poly1305/poly1305.odin index ab320c80c..cf60f7166 100644 --- a/core/crypto/poly1305/poly1305.odin +++ b/core/crypto/poly1305/poly1305.odin @@ -1,8 +1,8 @@ package poly1305 import "core:crypto" -import "core:crypto/util" import field "core:crypto/_fiat/field_poly1305" +import "core:encoding/endian" import "core:mem" KEY_SIZE :: 32 @@ -52,8 +52,8 @@ init :: proc (ctx: ^Context, key: []byte) { // r = le_bytes_to_num(key[0..15]) // r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff) - tmp_lo := util.U64_LE(key[0:8]) & 0x0ffffffc0fffffff - tmp_hi := util.U64_LE(key[8:16]) & 0xffffffc0ffffffc + tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff + tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0xffffffc0ffffffc field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi) // s = le_bytes_to_num(key[16..31]) @@ -151,7 +151,7 @@ _blocks :: proc (ctx: ^Context, msg: []byte, final := false) { data_len := len(data) for data_len >= _BLOCK_SIZE { // n = le_bytes_to_num(msg[((i-1)*16)..*i*16] | [0x01]) - field.fe_from_bytes(&n, data[:_BLOCK_SIZE], final_byte, false) + field.fe_from_bytes(&n, data[:_BLOCK_SIZE], final_byte) // a += n field.fe_add(field.fe_relax_cast(&ctx._a), &ctx._a, &n) // _a unreduced diff --git a/core/crypto/ripemd/ripemd.odin b/core/crypto/ripemd/ripemd.odin deleted file mode 100644 index f9edb121b..000000000 --- a/core/crypto/ripemd/ripemd.odin +++ /dev/null @@ -1,919 +0,0 @@ -package ripemd - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation for the RIPEMD hashing algorithm as defined in -*/ - -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE_128 :: 16 -DIGEST_SIZE_160 :: 20 -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_320 :: 40 - -// hash_string_128 will hash the given input and return the -// computed hash -hash_string_128 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128(transmute([]byte)(data)) -} - -// hash_bytes_128 will hash the given input and return the -// computed hash -hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: Ripemd128_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: Ripemd128_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_128 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: Ripemd128_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128 will read the file provided by the given handle -// and compute a hash -hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128 :: proc { - hash_stream_128, - hash_file_128, - hash_bytes_128, - hash_string_128, - hash_bytes_to_buffer_128, - hash_string_to_buffer_128, -} - -// hash_string_160 will hash the given input and return the -// computed hash -hash_string_160 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160(transmute([]byte)(data)) -} - -// hash_bytes_160 will hash the given input and return the -// computed hash -hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: Ripemd160_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: Ripemd160_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_160 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: Ripemd160_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160 will read the file provided by the given handle -// and compute a hash -hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160 :: proc { - hash_stream_160, - hash_file_160, - hash_bytes_160, - hash_string_160, - hash_bytes_to_buffer_160, - hash_string_to_buffer_160, -} - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Ripemd256_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Ripemd256_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Ripemd256_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_320 will hash the given input and return the -// computed hash -hash_string_320 :: proc(data: string) -> [DIGEST_SIZE_320]byte { - return hash_bytes_320(transmute([]byte)(data)) -} - -// hash_bytes_320 will hash the given input and return the -// computed hash -hash_bytes_320 :: proc(data: []byte) -> [DIGEST_SIZE_320]byte { - hash: [DIGEST_SIZE_320]byte - ctx: Ripemd320_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_320 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_320 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_320(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_320 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_320 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_320, "Size of destination buffer is smaller than the digest size") - ctx: Ripemd320_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream_320 will read the stream in chunks and compute a -// hash from its contents -hash_stream_320 :: proc(s: io.Stream) -> ([DIGEST_SIZE_320]byte, bool) { - hash: [DIGEST_SIZE_320]byte - ctx: Ripemd320_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_320 will read the file provided by the given handle -// and compute a hash -hash_file_320 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_320]byte, bool) { - if !load_at_once { - return hash_stream_320(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_320(buf[:]), ok - } - } - return [DIGEST_SIZE_320]byte{}, false -} - -hash_320 :: proc { - hash_stream_320, - hash_file_320, - hash_bytes_320, - hash_string_320, - hash_bytes_to_buffer_320, - hash_string_to_buffer_320, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^$T) { - when T == Ripemd128_Context { - ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3] = S0, S1, S2, S3 - } else when T == Ripemd160_Context { - ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3], ctx.s[4] = S0, S1, S2, S3, S4 - } else when T == Ripemd256_Context { - ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3] = S0, S1, S2, S3 - ctx.s[4], ctx.s[5], ctx.s[6], ctx.s[7] = S5, S6, S7, S8 - } else when T == Ripemd320_Context { - ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3], ctx.s[4] = S0, S1, S2, S3, S4 - ctx.s[5], ctx.s[6], ctx.s[7], ctx.s[8], ctx.s[9] = S5, S6, S7, S8, S9 - } -} - -update :: proc(ctx: ^$T, data: []byte) { - ctx.tc += u64(len(data)) - data := data - if ctx.nx > 0 { - n := len(data) - - when T == Ripemd128_Context { - if n > RIPEMD_128_BLOCK_SIZE - ctx.nx { - n = RIPEMD_128_BLOCK_SIZE - ctx.nx - } - } else when T == Ripemd160_Context { - if n > RIPEMD_160_BLOCK_SIZE - ctx.nx { - n = RIPEMD_160_BLOCK_SIZE - ctx.nx - } - } else when T == Ripemd256_Context{ - if n > RIPEMD_256_BLOCK_SIZE - ctx.nx { - n = RIPEMD_256_BLOCK_SIZE - ctx.nx - } - } else when T == Ripemd320_Context{ - if n > RIPEMD_320_BLOCK_SIZE - ctx.nx { - n = RIPEMD_320_BLOCK_SIZE - ctx.nx - } - } - - for i := 0; i < n; i += 1 { - ctx.x[ctx.nx + i] = data[i] - } - - ctx.nx += n - when T == Ripemd128_Context { - if ctx.nx == RIPEMD_128_BLOCK_SIZE { - block(ctx, ctx.x[0:]) - ctx.nx = 0 - } - } else when T == Ripemd160_Context { - if ctx.nx == RIPEMD_160_BLOCK_SIZE { - block(ctx, ctx.x[0:]) - ctx.nx = 0 - } - } else when T == Ripemd256_Context{ - if ctx.nx == RIPEMD_256_BLOCK_SIZE { - block(ctx, ctx.x[0:]) - ctx.nx = 0 - } - } else when T == Ripemd320_Context{ - if ctx.nx == RIPEMD_320_BLOCK_SIZE { - block(ctx, ctx.x[0:]) - ctx.nx = 0 - } - } - data = data[n:] - } - n := block(ctx, data) - data = data[n:] - if len(data) > 0 { - ctx.nx = copy(ctx.x[:], data) - } -} - -final :: proc(ctx: ^$T, hash: []byte) { - d := ctx - tc := d.tc - tmp: [64]byte - tmp[0] = 0x80 - - if tc % 64 < 56 { - update(d, tmp[0:56 - tc % 64]) - } else { - update(d, tmp[0:64 + 56 - tc % 64]) - } - - tc <<= 3 - for i : u32 = 0; i < 8; i += 1 { - tmp[i] = byte(tc >> (8 * i)) - } - - update(d, tmp[0:8]) - - when T == Ripemd128_Context { - size :: RIPEMD_128_SIZE - } else when T == Ripemd160_Context { - size :: RIPEMD_160_SIZE - } else when T == Ripemd256_Context{ - size :: RIPEMD_256_SIZE - } else when T == Ripemd320_Context{ - size :: RIPEMD_320_SIZE - } - - digest: [size]byte - for s, i in d.s { - digest[i * 4] = byte(s) - digest[i * 4 + 1] = byte(s >> 8) - digest[i * 4 + 2] = byte(s >> 16) - digest[i * 4 + 3] = byte(s >> 24) - } - copy(hash[:], digest[:]) -} - - -/* - RIPEMD implementation -*/ - -Ripemd128_Context :: struct { - s: [4]u32, - x: [RIPEMD_128_BLOCK_SIZE]byte, - nx: int, - tc: u64, -} - -Ripemd160_Context :: struct { - s: [5]u32, - x: [RIPEMD_160_BLOCK_SIZE]byte, - nx: int, - tc: u64, -} - -Ripemd256_Context :: struct { - s: [8]u32, - x: [RIPEMD_256_BLOCK_SIZE]byte, - nx: int, - tc: u64, -} - -Ripemd320_Context :: struct { - s: [10]u32, - x: [RIPEMD_320_BLOCK_SIZE]byte, - nx: int, - tc: u64, -} - -RIPEMD_128_SIZE :: 16 -RIPEMD_128_BLOCK_SIZE :: 64 -RIPEMD_160_SIZE :: 20 -RIPEMD_160_BLOCK_SIZE :: 64 -RIPEMD_256_SIZE :: 32 -RIPEMD_256_BLOCK_SIZE :: 64 -RIPEMD_320_SIZE :: 40 -RIPEMD_320_BLOCK_SIZE :: 64 - -S0 :: 0x67452301 -S1 :: 0xefcdab89 -S2 :: 0x98badcfe -S3 :: 0x10325476 -S4 :: 0xc3d2e1f0 -S5 :: 0x76543210 -S6 :: 0xfedcba98 -S7 :: 0x89abcdef -S8 :: 0x01234567 -S9 :: 0x3c2d1e0f - -RIPEMD_128_N0 := [64]uint { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, -} - -RIPEMD_128_R0 := [64]uint { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, -} - -RIPEMD_128_N1 := [64]uint { - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, -} - -RIPEMD_128_R1 := [64]uint { - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, -} - -RIPEMD_160_N0 := [80]uint { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, -} - -RIPEMD_160_R0 := [80]uint { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, -} - -RIPEMD_160_N1 := [80]uint { - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, -} - -RIPEMD_160_R1 := [80]uint { - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, -} - -block :: #force_inline proc (ctx: ^$T, p: []byte) -> int { - when T == Ripemd128_Context { - return ripemd_128_block(ctx, p) - } - else when T == Ripemd160_Context { - return ripemd_160_block(ctx, p) - } - else when T == Ripemd256_Context { - return ripemd_256_block(ctx, p) - } - else when T == Ripemd320_Context { - return ripemd_320_block(ctx, p) - } -} - -ripemd_128_block :: proc(ctx: ^$T, p: []byte) -> int { - n := 0 - x: [16]u32 = --- - alpha: u32 = --- - p := p - for len(p) >= RIPEMD_128_BLOCK_SIZE { - a, b, c, d := ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3] - aa, bb, cc, dd := a, b, c, d - for i,j := 0, 0; i < 16; i, j = i+1, j+4 { - x[i] = u32(p[j]) | u32(p[j+1])<<8 | u32(p[j+2])<<16 | u32(p[j+3])<<24 - } - i := 0 - for i < 16 { - alpha = a + (b ~ c ~ d) + x[RIPEMD_128_N0[i]] - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (bb & dd | cc &~ dd) + x[RIPEMD_128_N1[i]] + 0x50a28be6 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd= dd, alpha, bb, cc - i += 1 - } - for i < 32 { - alpha = a + (d ~ (b & (c~d))) + x[RIPEMD_128_N0[i]] + 0x5a827999 - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (dd ~ (bb | ~cc)) + x[RIPEMD_128_N1[i]] + 0x5c4dd124 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - for i < 48 { - alpha = a + (d ~ (b | ~c)) + x[RIPEMD_128_N0[i]] + 0x6ed9eba1 - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (dd ~ (bb & (cc~dd))) + x[RIPEMD_128_N1[i]] + 0x6d703ef3 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - for i < 64 { - alpha = a + (c ~ (d & (b~c))) + x[RIPEMD_128_N0[i]] + 0x8f1bbcdc - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (bb ~ cc ~ dd) + x[RIPEMD_128_N1[i]] - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - c = ctx.s[1] + c + dd - ctx.s[1] = ctx.s[2] + d + aa - ctx.s[2] = ctx.s[3] + a + bb - ctx.s[3] = ctx.s[0] + b + cc - ctx.s[0] = c - p = p[RIPEMD_128_BLOCK_SIZE:] - n += RIPEMD_128_BLOCK_SIZE - } - return n -} - -ripemd_160_block :: proc(ctx: ^$T, p: []byte) -> int { - n := 0 - x: [16]u32 = --- - alpha, beta: u32 = ---, --- - p := p - for len(p) >= RIPEMD_160_BLOCK_SIZE { - a, b, c, d, e := ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3], ctx.s[4] - aa, bb, cc, dd, ee := a, b, c, d, e - for i,j := 0, 0; i < 16; i, j = i+1, j+4 { - x[i] = u32(p[j]) | u32(p[j+1])<<8 | u32(p[j+2])<<16 | u32(p[j+3])<<24 - } - i := 0 - for i < 16 { - alpha = a + (b ~ c ~ d) + x[RIPEMD_160_N0[i]] - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb ~ (cc | ~dd)) + x[RIPEMD_160_N1[i]] + 0x50a28be6 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - for i < 32 { - alpha = a + (b&c | ~b&d) + x[RIPEMD_160_N0[i]] + 0x5a827999 - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb&dd | cc&~dd) + x[RIPEMD_160_N1[i]] + 0x5c4dd124 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - for i < 48 { - alpha = a + (b | ~c ~ d) + x[RIPEMD_160_N0[i]] + 0x6ed9eba1 - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb | ~cc ~ dd) + x[RIPEMD_160_N1[i]] + 0x6d703ef3 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - for i < 64 { - alpha = a + (b&d | c&~d) + x[RIPEMD_160_N0[i]] + 0x8f1bbcdc - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb&cc | ~bb&dd) + x[RIPEMD_160_N1[i]] + 0x7a6d76e9 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - for i < 80 { - alpha = a + (b ~ (c | ~d)) + x[RIPEMD_160_N0[i]] + 0xa953fd4e - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb ~ cc ~ dd) + x[RIPEMD_160_N1[i]] - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - dd += c + ctx.s[1] - ctx.s[1] = ctx.s[2] + d + ee - ctx.s[2] = ctx.s[3] + e + aa - ctx.s[3] = ctx.s[4] + a + bb - ctx.s[4] = ctx.s[0] + b + cc - ctx.s[0] = dd - p = p[RIPEMD_160_BLOCK_SIZE:] - n += RIPEMD_160_BLOCK_SIZE - } - return n -} - -ripemd_256_block :: proc(ctx: ^$T, p: []byte) -> int { - n := 0 - x: [16]u32 = --- - alpha: u32 = --- - p := p - for len(p) >= RIPEMD_256_BLOCK_SIZE { - a, b, c, d := ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3] - aa, bb, cc, dd := ctx.s[4], ctx.s[5], ctx.s[6], ctx.s[7] - for i,j := 0, 0; i < 16; i, j = i+1, j+4 { - x[i] = u32(p[j]) | u32(p[j+1])<<8 | u32(p[j+2])<<16 | u32(p[j+3])<<24 - } - i := 0 - for i < 16 { - alpha = a + (b ~ c ~ d) + x[RIPEMD_128_N0[i]] - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (bb & dd | cc &~ dd) + x[RIPEMD_128_N1[i]] + 0x50a28be6 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd= dd, alpha, bb, cc - i += 1 - } - t := a - a = aa - aa = t - for i < 32 { - alpha = a + (d ~ (b & (c~d))) + x[RIPEMD_128_N0[i]] + 0x5a827999 - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (dd ~ (bb | ~cc)) + x[RIPEMD_128_N1[i]] + 0x5c4dd124 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - t = b - b = bb - bb = t - for i < 48 { - alpha = a + (d ~ (b | ~c)) + x[RIPEMD_128_N0[i]] + 0x6ed9eba1 - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (dd ~ (bb & (cc~dd))) + x[RIPEMD_128_N1[i]] + 0x6d703ef3 - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - t = c - c = cc - cc = t - for i < 64 { - alpha = a + (c ~ (d & (b~c))) + x[RIPEMD_128_N0[i]] + 0x8f1bbcdc - s := int(RIPEMD_128_R0[i]) - alpha = util.ROTL32(alpha, s) - a, b, c, d = d, alpha, b, c - alpha = aa + (bb ~ cc ~ dd) + x[RIPEMD_128_N1[i]] - s = int(RIPEMD_128_R1[i]) - alpha = util.ROTL32(alpha, s) - aa, bb, cc, dd = dd, alpha, bb, cc - i += 1 - } - t = d - d = dd - dd = t - ctx.s[0] += a - ctx.s[1] += b - ctx.s[2] += c - ctx.s[3] += d - ctx.s[4] += aa - ctx.s[5] += bb - ctx.s[6] += cc - ctx.s[7] += dd - p = p[RIPEMD_256_BLOCK_SIZE:] - n += RIPEMD_256_BLOCK_SIZE - } - return n -} - -ripemd_320_block :: proc(ctx: ^$T, p: []byte) -> int { - n := 0 - x: [16]u32 = --- - alpha, beta: u32 = ---, --- - p := p - for len(p) >= RIPEMD_320_BLOCK_SIZE { - a, b, c, d, e := ctx.s[0], ctx.s[1], ctx.s[2], ctx.s[3], ctx.s[4] - aa, bb, cc, dd, ee := ctx.s[5], ctx.s[6], ctx.s[7], ctx.s[8], ctx.s[9] - for i,j := 0, 0; i < 16; i, j = i+1, j+4 { - x[i] = u32(p[j]) | u32(p[j+1])<<8 | u32(p[j+2])<<16 | u32(p[j+3])<<24 - } - i := 0 - for i < 16 { - alpha = a + (b ~ c ~ d) + x[RIPEMD_160_N0[i]] - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb ~ (cc | ~dd)) + x[RIPEMD_160_N1[i]] + 0x50a28be6 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - t := b - b = bb - bb = t - for i < 32 { - alpha = a + (b&c | ~b&d) + x[RIPEMD_160_N0[i]] + 0x5a827999 - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb&dd | cc&~dd) + x[RIPEMD_160_N1[i]] + 0x5c4dd124 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - t = d - d = dd - dd = t - for i < 48 { - alpha = a + (b | ~c ~ d) + x[RIPEMD_160_N0[i]] + 0x6ed9eba1 - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb | ~cc ~ dd) + x[RIPEMD_160_N1[i]] + 0x6d703ef3 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - t = a - a = aa - aa = t - for i < 64 { - alpha = a + (b&d | c&~d) + x[RIPEMD_160_N0[i]] + 0x8f1bbcdc - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb&cc | ~bb&dd) + x[RIPEMD_160_N1[i]] + 0x7a6d76e9 - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - t = c - c = cc - cc = t - for i < 80 { - alpha = a + (b ~ (c | ~d)) + x[RIPEMD_160_N0[i]] + 0xa953fd4e - s := int(RIPEMD_160_R0[i]) - alpha = util.ROTL32(alpha, s) + e - beta = util.ROTL32(c, 10) - a, b, c, d, e = e, alpha, b, beta, d - alpha = aa + (bb ~ cc ~ dd) + x[RIPEMD_160_N1[i]] - s = int(RIPEMD_160_R1[i]) - alpha = util.ROTL32(alpha, s) + ee - beta = util.ROTL32(cc, 10) - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - i += 1 - } - t = e - e = ee - ee = t - ctx.s[0] += a - ctx.s[1] += b - ctx.s[2] += c - ctx.s[3] += d - ctx.s[4] += e - ctx.s[5] += aa - ctx.s[6] += bb - ctx.s[7] += cc - ctx.s[8] += dd - ctx.s[9] += ee - p = p[RIPEMD_320_BLOCK_SIZE:] - n += RIPEMD_320_BLOCK_SIZE - } - return n -} diff --git a/core/crypto/sha1/sha1.odin b/core/crypto/sha1/sha1.odin deleted file mode 100644 index 599d1791e..000000000 --- a/core/crypto/sha1/sha1.odin +++ /dev/null @@ -1,246 +0,0 @@ -package sha1 - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the SHA1 hashing algorithm, as defined in RFC 3174 -*/ - -import "core:mem" -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE :: 20 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Sha1_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Sha1_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Sha1_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Sha1_Context) { - ctx.state[0] = 0x67452301 - ctx.state[1] = 0xefcdab89 - ctx.state[2] = 0x98badcfe - ctx.state[3] = 0x10325476 - ctx.state[4] = 0xc3d2e1f0 - ctx.k[0] = 0x5a827999 - ctx.k[1] = 0x6ed9eba1 - ctx.k[2] = 0x8f1bbcdc - ctx.k[3] = 0xca62c1d6 -} - -update :: proc(ctx: ^Sha1_Context, data: []byte) { - for i := 0; i < len(data); i += 1 { - ctx.data[ctx.datalen] = data[i] - ctx.datalen += 1 - if (ctx.datalen == BLOCK_SIZE) { - transform(ctx, ctx.data[:]) - ctx.bitlen += 512 - ctx.datalen = 0 - } - } -} - -final :: proc(ctx: ^Sha1_Context, hash: []byte) { - i := ctx.datalen - - if ctx.datalen < 56 { - ctx.data[i] = 0x80 - i += 1 - for i < 56 { - ctx.data[i] = 0x00 - i += 1 - } - } - else { - ctx.data[i] = 0x80 - i += 1 - for i < BLOCK_SIZE { - ctx.data[i] = 0x00 - i += 1 - } - transform(ctx, ctx.data[:]) - mem.set(&ctx.data, 0, 56) - } - - ctx.bitlen += u64(ctx.datalen * 8) - ctx.data[63] = u8(ctx.bitlen) - ctx.data[62] = u8(ctx.bitlen >> 8) - ctx.data[61] = u8(ctx.bitlen >> 16) - ctx.data[60] = u8(ctx.bitlen >> 24) - ctx.data[59] = u8(ctx.bitlen >> 32) - ctx.data[58] = u8(ctx.bitlen >> 40) - ctx.data[57] = u8(ctx.bitlen >> 48) - ctx.data[56] = u8(ctx.bitlen >> 56) - transform(ctx, ctx.data[:]) - - for j: u32 = 0; j < 4; j += 1 { - hash[j] = u8(ctx.state[0] >> (24 - j * 8)) & 0x000000ff - hash[j + 4] = u8(ctx.state[1] >> (24 - j * 8)) & 0x000000ff - hash[j + 8] = u8(ctx.state[2] >> (24 - j * 8)) & 0x000000ff - hash[j + 12] = u8(ctx.state[3] >> (24 - j * 8)) & 0x000000ff - hash[j + 16] = u8(ctx.state[4] >> (24 - j * 8)) & 0x000000ff - } -} - -/* - SHA1 implementation -*/ - -BLOCK_SIZE :: 64 - -Sha1_Context :: struct { - data: [BLOCK_SIZE]byte, - datalen: u32, - bitlen: u64, - state: [5]u32, - k: [4]u32, -} - -transform :: proc(ctx: ^Sha1_Context, data: []byte) { - a, b, c, d, e, i, j, t: u32 - m: [80]u32 - - for i, j = 0, 0; i < 16; i += 1 { - m[i] = u32(data[j]) << 24 + u32(data[j + 1]) << 16 + u32(data[j + 2]) << 8 + u32(data[j + 3]) - j += 4 - } - for i < 80 { - m[i] = (m[i - 3] ~ m[i - 8] ~ m[i - 14] ~ m[i - 16]) - m[i] = (m[i] << 1) | (m[i] >> 31) - i += 1 - } - - a = ctx.state[0] - b = ctx.state[1] - c = ctx.state[2] - d = ctx.state[3] - e = ctx.state[4] - - for i = 0; i < 20; i += 1 { - t = util.ROTL32(a, 5) + ((b & c) ~ (~b & d)) + e + ctx.k[0] + m[i] - e = d - d = c - c = util.ROTL32(b, 30) - b = a - a = t - } - for i < 40 { - t = util.ROTL32(a, 5) + (b ~ c ~ d) + e + ctx.k[1] + m[i] - e = d - d = c - c = util.ROTL32(b, 30) - b = a - a = t - i += 1 - } - for i < 60 { - t = util.ROTL32(a, 5) + ((b & c) ~ (b & d) ~ (c & d)) + e + ctx.k[2] + m[i] - e = d - d = c - c = util.ROTL32(b, 30) - b = a - a = t - i += 1 - } - for i < 80 { - t = util.ROTL32(a, 5) + (b ~ c ~ d) + e + ctx.k[3] + m[i] - e = d - d = c - c = util.ROTL32(b, 30) - b = a - a = t - i += 1 - } - - ctx.state[0] += a - ctx.state[1] += b - ctx.state[2] += c - ctx.state[3] += d - ctx.state[4] += e -} diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index 0f55c4be1..10ac73ab6 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -7,15 +7,14 @@ package sha2 List of contributors: zhibog, dotbmp: Initial implementation. - Implementation of the SHA2 hashing algorithm, as defined in + Implementation of the SHA2 hashing algorithm, as defined in and in RFC 3874 */ -import "core:mem" -import "core:os" +import "core:encoding/endian" import "core:io" - -import "../util" +import "core:math/bits" +import "core:os" /* High level API @@ -25,321 +24,406 @@ DIGEST_SIZE_224 :: 28 DIGEST_SIZE_256 :: 32 DIGEST_SIZE_384 :: 48 DIGEST_SIZE_512 :: 64 +DIGEST_SIZE_512_256 :: 32 // hash_string_224 will hash the given input and return the // computed hash hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) + return hash_bytes_224(transmute([]byte)(data)) } // hash_bytes_224 will hash the given input and return the // computed hash hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: Sha256_Context - ctx.is224 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_224]byte + ctx: Context_256 + ctx.md_bits = 224 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_224 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) + hash_bytes_to_buffer_224(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_224 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: Sha256_Context - ctx.is224 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash) + ctx: Context_256 + ctx.md_bits = 224 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_224 will read the stream in chunks and compute a // hash from its contents hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { hash: [DIGEST_SIZE_224]byte - ctx: Sha512_Context - ctx.is384 = false - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true + ctx: Context_256 + ctx.md_bits = 224 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_224 will read the file provided by the given handle // and compute a hash hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false + if !load_at_once { + return hash_stream_224(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_224(buf[:]), ok + } + } + return [DIGEST_SIZE_224]byte{}, false } hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, + hash_stream_224, + hash_file_224, + hash_bytes_224, + hash_string_224, + hash_bytes_to_buffer_224, + hash_string_to_buffer_224, } // hash_string_256 will hash the given input and return the // computed hash hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) + return hash_bytes_256(transmute([]byte)(data)) } // hash_bytes_256 will hash the given input and return the // computed hash hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Sha256_Context - ctx.is224 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_256]byte + ctx: Context_256 + ctx.md_bits = 256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_256 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Sha256_Context - ctx.is224 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash) + ctx: Context_256 + ctx.md_bits = 256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_256 will read the stream in chunks and compute a // hash from its contents hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { hash: [DIGEST_SIZE_256]byte - ctx: Sha512_Context - ctx.is384 = false - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true + ctx: Context_256 + ctx.md_bits = 256 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_256 will read the file provided by the given handle // and compute a hash hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false + if !load_at_once { + return hash_stream_256(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_256(buf[:]), ok + } + } + return [DIGEST_SIZE_256]byte{}, false } hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, + hash_stream_256, + hash_file_256, + hash_bytes_256, + hash_string_256, + hash_bytes_to_buffer_256, + hash_string_to_buffer_256, } // hash_string_384 will hash the given input and return the // computed hash hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) + return hash_bytes_384(transmute([]byte)(data)) } // hash_bytes_384 will hash the given input and return the // computed hash hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: Sha512_Context - ctx.is384 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_384]byte + ctx: Context_512 + ctx.md_bits = 384 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_384 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) + hash_bytes_to_buffer_384(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_384 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: Sha512_Context - ctx.is384 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash) + ctx: Context_512 + ctx.md_bits = 384 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_384 will read the stream in chunks and compute a // hash from its contents hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { hash: [DIGEST_SIZE_384]byte - ctx: Sha512_Context - ctx.is384 = true - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true + ctx: Context_512 + ctx.md_bits = 384 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_384 will read the file provided by the given handle // and compute a hash hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false + if !load_at_once { + return hash_stream_384(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_384(buf[:]), ok + } + } + return [DIGEST_SIZE_384]byte{}, false } hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, + hash_stream_384, + hash_file_384, + hash_bytes_384, + hash_string_384, + hash_bytes_to_buffer_384, + hash_string_to_buffer_384, } // hash_string_512 will hash the given input and return the // computed hash hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) + return hash_bytes_512(transmute([]byte)(data)) } // hash_bytes_512 will hash the given input and return the // computed hash hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: Sha512_Context - ctx.is384 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_512]byte + ctx: Context_512 + ctx.md_bits = 512 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_512 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: Sha512_Context - ctx.is384 = false - init(&ctx) - update(&ctx, data) - final(&ctx, hash) + ctx: Context_512 + ctx.md_bits = 512 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_512 will read the stream in chunks and compute a // hash from its contents hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: Sha512_Context - ctx.is384 = false + hash: [DIGEST_SIZE_512]byte + ctx: Context_512 + ctx.md_bits = 512 init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_512 will read the file provided by the given handle // and compute a hash hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false + if !load_at_once { + return hash_stream_512(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_512(buf[:]), ok + } + } + return [DIGEST_SIZE_512]byte{}, false } hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, + hash_stream_512, + hash_file_512, + hash_bytes_512, + hash_string_512, + hash_bytes_to_buffer_512, + hash_string_to_buffer_512, +} + +// hash_string_512_256 will hash the given input and return the +// computed hash +hash_string_512_256 :: proc(data: string) -> [DIGEST_SIZE_512_256]byte { + return hash_bytes_512_256(transmute([]byte)(data)) +} + +// hash_bytes_512_256 will hash the given input and return the +// computed hash +hash_bytes_512_256 :: proc(data: []byte) -> [DIGEST_SIZE_512_256]byte { + hash: [DIGEST_SIZE_512_256]byte + ctx: Context_512 + ctx.md_bits = 256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash +} + +// hash_string_to_buffer_512_256 will hash the given input and assign the +// computed hash to the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_string_to_buffer_512_256 :: proc(data: string, hash: []byte) { + hash_bytes_to_buffer_512_256(transmute([]byte)(data), hash) +} + +// hash_bytes_to_buffer_512_256 will hash the given input and write the +// computed hash into the second parameter. +// It requires that the destination buffer is at least as big as the digest size +hash_bytes_to_buffer_512_256 :: proc(data, hash: []byte) { + ctx: Context_512 + ctx.md_bits = 256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) +} + +// hash_stream_512_256 will read the stream in chunks and compute a +// hash from its contents +hash_stream_512_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512_256]byte, bool) { + hash: [DIGEST_SIZE_512_256]byte + ctx: Context_512 + ctx.md_bits = 256 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true +} + +// hash_file_512_256 will read the file provided by the given handle +// and compute a hash +hash_file_512_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512_256]byte, bool) { + if !load_at_once { + return hash_stream_512_256(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_512_256(buf[:]), ok + } + } + return [DIGEST_SIZE_512_256]byte{}, false +} + +hash_512_256 :: proc { + hash_stream_512_256, + hash_file_512_256, + hash_bytes_512_256, + hash_string_512_256, + hash_bytes_to_buffer_512_256, + hash_string_to_buffer_512_256, } /* @@ -347,122 +431,153 @@ hash_512 :: proc { */ init :: proc(ctx: ^$T) { - when T == Sha256_Context { - if ctx.is224 { - ctx.h[0] = 0xc1059ed8 - ctx.h[1] = 0x367cd507 - ctx.h[2] = 0x3070dd17 - ctx.h[3] = 0xf70e5939 - ctx.h[4] = 0xffc00b31 - ctx.h[5] = 0x68581511 - ctx.h[6] = 0x64f98fa7 - ctx.h[7] = 0xbefa4fa4 - } else { - ctx.h[0] = 0x6a09e667 - ctx.h[1] = 0xbb67ae85 - ctx.h[2] = 0x3c6ef372 - ctx.h[3] = 0xa54ff53a - ctx.h[4] = 0x510e527f - ctx.h[5] = 0x9b05688c - ctx.h[6] = 0x1f83d9ab - ctx.h[7] = 0x5be0cd19 - } - } else when T == Sha512_Context { - if ctx.is384 { - ctx.h[0] = 0xcbbb9d5dc1059ed8 - ctx.h[1] = 0x629a292a367cd507 - ctx.h[2] = 0x9159015a3070dd17 - ctx.h[3] = 0x152fecd8f70e5939 - ctx.h[4] = 0x67332667ffc00b31 - ctx.h[5] = 0x8eb44a8768581511 - ctx.h[6] = 0xdb0c2e0d64f98fa7 - ctx.h[7] = 0x47b5481dbefa4fa4 - } else { - ctx.h[0] = 0x6a09e667f3bcc908 - ctx.h[1] = 0xbb67ae8584caa73b - ctx.h[2] = 0x3c6ef372fe94f82b - ctx.h[3] = 0xa54ff53a5f1d36f1 - ctx.h[4] = 0x510e527fade682d1 - ctx.h[5] = 0x9b05688c2b3e6c1f - ctx.h[6] = 0x1f83d9abfb41bd6b - ctx.h[7] = 0x5be0cd19137e2179 - } - } + when T == Context_256 { + switch ctx.md_bits { + case 224: + ctx.h[0] = 0xc1059ed8 + ctx.h[1] = 0x367cd507 + ctx.h[2] = 0x3070dd17 + ctx.h[3] = 0xf70e5939 + ctx.h[4] = 0xffc00b31 + ctx.h[5] = 0x68581511 + ctx.h[6] = 0x64f98fa7 + ctx.h[7] = 0xbefa4fa4 + case 256: + ctx.h[0] = 0x6a09e667 + ctx.h[1] = 0xbb67ae85 + ctx.h[2] = 0x3c6ef372 + ctx.h[3] = 0xa54ff53a + ctx.h[4] = 0x510e527f + ctx.h[5] = 0x9b05688c + ctx.h[6] = 0x1f83d9ab + ctx.h[7] = 0x5be0cd19 + case: + panic("crypto/sha2: invalid digest output length") + } + } else when T == Context_512 { + switch ctx.md_bits { + case 256: + // SHA-512/256 + ctx.h[0] = 0x22312194fc2bf72c + ctx.h[1] = 0x9f555fa3c84c64c2 + ctx.h[2] = 0x2393b86b6f53b151 + ctx.h[3] = 0x963877195940eabd + ctx.h[4] = 0x96283ee2a88effe3 + ctx.h[5] = 0xbe5e1e2553863992 + ctx.h[6] = 0x2b0199fc2c85b8aa + ctx.h[7] = 0x0eb72ddc81c52ca2 + case 384: + // SHA-384 + ctx.h[0] = 0xcbbb9d5dc1059ed8 + ctx.h[1] = 0x629a292a367cd507 + ctx.h[2] = 0x9159015a3070dd17 + ctx.h[3] = 0x152fecd8f70e5939 + ctx.h[4] = 0x67332667ffc00b31 + ctx.h[5] = 0x8eb44a8768581511 + ctx.h[6] = 0xdb0c2e0d64f98fa7 + ctx.h[7] = 0x47b5481dbefa4fa4 + case 512: + // SHA-512 + ctx.h[0] = 0x6a09e667f3bcc908 + ctx.h[1] = 0xbb67ae8584caa73b + ctx.h[2] = 0x3c6ef372fe94f82b + ctx.h[3] = 0xa54ff53a5f1d36f1 + ctx.h[4] = 0x510e527fade682d1 + ctx.h[5] = 0x9b05688c2b3e6c1f + ctx.h[6] = 0x1f83d9abfb41bd6b + ctx.h[7] = 0x5be0cd19137e2179 + case: + panic("crypto/sha2: invalid digest output length") + } + } + + ctx.length = 0 + ctx.bitlength = 0 + + ctx.is_initialized = true } update :: proc(ctx: ^$T, data: []byte) { - length := uint(len(data)) - block_nb: uint - new_len, rem_len, tmp_len: uint - shifted_message := make([]byte, length) + assert(ctx.is_initialized) - when T == Sha256_Context { - CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE - } else when T == Sha512_Context { - CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE - } + when T == Context_256 { + CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE + } else when T == Context_512 { + CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE + } - tmp_len = CURR_BLOCK_SIZE - ctx.length - rem_len = length < tmp_len ? length : tmp_len - copy(ctx.block[ctx.length:], data[:rem_len]) + data := data + ctx.length += u64(len(data)) - if ctx.length + length < CURR_BLOCK_SIZE { - ctx.length += length - return - } - - new_len = length - rem_len - block_nb = new_len / CURR_BLOCK_SIZE - shifted_message = data[rem_len:] - - sha2_transf(ctx, ctx.block[:], 1) - sha2_transf(ctx, shifted_message, block_nb) - - rem_len = new_len % CURR_BLOCK_SIZE - if rem_len > 0 { - when T == Sha256_Context {copy(ctx.block[:], shifted_message[block_nb << 6:rem_len])} - else when T == Sha512_Context {copy(ctx.block[:], shifted_message[block_nb << 7:rem_len])} - } - - ctx.length = rem_len - when T == Sha256_Context {ctx.tot_len += (block_nb + 1) << 6} - else when T == Sha512_Context {ctx.tot_len += (block_nb + 1) << 7} + if ctx.bitlength > 0 { + n := copy(ctx.block[ctx.bitlength:], data[:]) + ctx.bitlength += u64(n) + if ctx.bitlength == CURR_BLOCK_SIZE { + sha2_transf(ctx, ctx.block[:]) + ctx.bitlength = 0 + } + data = data[n:] + } + if len(data) >= CURR_BLOCK_SIZE { + n := len(data) &~ (CURR_BLOCK_SIZE - 1) + sha2_transf(ctx, data[:n]) + data = data[n:] + } + if len(data) > 0 { + ctx.bitlength = u64(copy(ctx.block[:], data[:])) + } } final :: proc(ctx: ^$T, hash: []byte) { - block_nb, pm_len, len_b: u32 - i: i32 + assert(ctx.is_initialized) - when T == Sha256_Context {CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE} - else when T == Sha512_Context {CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE} + if len(hash) * 8 < ctx.md_bits { + panic("crypto/sha2: invalid destination digest size") + } - when T == Sha256_Context {block_nb = 1 + ((CURR_BLOCK_SIZE - 9) < (ctx.length % CURR_BLOCK_SIZE) ? 1 : 0)} - else when T == Sha512_Context {block_nb = 1 + ((CURR_BLOCK_SIZE - 17) < (ctx.length % CURR_BLOCK_SIZE) ? 1 : 0)} + length := ctx.length - len_b = u32(ctx.tot_len + ctx.length) << 3 - when T == Sha256_Context {pm_len = block_nb << 6} - else when T == Sha512_Context {pm_len = block_nb << 7} + raw_pad: [SHA512_BLOCK_SIZE]byte + when T == Context_256 { + CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE + pm_len := 8 // 64-bits for length + } else when T == Context_512 { + CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE + pm_len := 16 // 128-bits for length + } + pad := raw_pad[:CURR_BLOCK_SIZE] + pad_len := u64(CURR_BLOCK_SIZE - pm_len) - mem.set(rawptr(&(ctx.block[ctx.length:])[0]), 0, int(uint(pm_len) - ctx.length)) - ctx.block[ctx.length] = 0x80 + pad[0] = 0x80 + if length % CURR_BLOCK_SIZE < pad_len { + update(ctx, pad[0:pad_len - length % CURR_BLOCK_SIZE]) + } else { + update(ctx, pad[0:CURR_BLOCK_SIZE + pad_len - length % CURR_BLOCK_SIZE]) + } - util.PUT_U32_BE(ctx.block[pm_len - 4:], len_b) + length_hi, length_lo := bits.mul_u64(length, 8) // Length in bits + when T == Context_256 { + _ = length_hi + endian.unchecked_put_u64be(pad[:], length_lo) + update(ctx, pad[:8]) + } else when T == Context_512 { + endian.unchecked_put_u64be(pad[:], length_hi) + endian.unchecked_put_u64be(pad[8:], length_lo) + update(ctx, pad[0:16]) + } + assert(ctx.bitlength == 0) - sha2_transf(ctx, ctx.block[:], uint(block_nb)) + when T == Context_256 { + for i := 0; i < ctx.md_bits / 32; i += 1 { + endian.unchecked_put_u32be(hash[i * 4:], ctx.h[i]) + } + } else when T == Context_512 { + for i := 0; i < ctx.md_bits / 64; i += 1 { + endian.unchecked_put_u64be(hash[i * 8:], ctx.h[i]) + } + } - when T == Sha256_Context { - if ctx.is224 { - for i = 0; i < 7; i += 1 {util.PUT_U32_BE(hash[i << 2:], ctx.h[i])} - } else { - for i = 0; i < 8; i += 1 {util.PUT_U32_BE(hash[i << 2:], ctx.h[i])} - } - } else when T == Sha512_Context { - if ctx.is384 { - for i = 0; i < 6; i += 1 {util.PUT_U64_BE(hash[i << 3:], ctx.h[i])} - } else { - for i = 0; i < 8; i += 1 {util.PUT_U64_BE(hash[i << 3:], ctx.h[i])} - } - } + ctx.is_initialized = false } /* @@ -472,186 +587,191 @@ final :: proc(ctx: ^$T, hash: []byte) { SHA256_BLOCK_SIZE :: 64 SHA512_BLOCK_SIZE :: 128 -Sha256_Context :: struct { - tot_len: uint, - length: uint, - block: [128]byte, - h: [8]u32, - is224: bool, +Context_256 :: struct { + block: [SHA256_BLOCK_SIZE]byte, + h: [8]u32, + bitlength: u64, + length: u64, + md_bits: int, + + is_initialized: bool, } -Sha512_Context :: struct { - tot_len: uint, - length: uint, - block: [256]byte, - h: [8]u64, - is384: bool, +Context_512 :: struct { + block: [SHA512_BLOCK_SIZE]byte, + h: [8]u64, + bitlength: u64, + length: u64, + md_bits: int, + + is_initialized: bool, } +@(private) sha256_k := [64]u32 { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, } +@(private) sha512_k := [80]u64 { - 0x428a2f98d728ae22, 0x7137449123ef65cd, - 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, - 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, - 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, - 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, - 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, - 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, - 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, - 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, - 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, - 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, - 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, - 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, - 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, + 0x428a2f98d728ae22, 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, + 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, + 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, + 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, + 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, + 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, } -SHA256_CH :: #force_inline proc "contextless"(x, y, z: u32) -> u32 { - return (x & y) ~ (~x & z) +@(private) +SHA256_CH :: #force_inline proc "contextless" (x, y, z: u32) -> u32 { + return (x & y) ~ (~x & z) } -SHA256_MAJ :: #force_inline proc "contextless"(x, y, z: u32) -> u32 { - return (x & y) ~ (x & z) ~ (y & z) +@(private) +SHA256_MAJ :: #force_inline proc "contextless" (x, y, z: u32) -> u32 { + return (x & y) ~ (x & z) ~ (y & z) } -SHA512_CH :: #force_inline proc "contextless"(x, y, z: u64) -> u64 { - return (x & y) ~ (~x & z) +@(private) +SHA512_CH :: #force_inline proc "contextless" (x, y, z: u64) -> u64 { + return (x & y) ~ (~x & z) } -SHA512_MAJ :: #force_inline proc "contextless"(x, y, z: u64) -> u64 { - return (x & y) ~ (x & z) ~ (y & z) +@(private) +SHA512_MAJ :: #force_inline proc "contextless" (x, y, z: u64) -> u64 { + return (x & y) ~ (x & z) ~ (y & z) } -SHA256_F1 :: #force_inline proc "contextless"(x: u32) -> u32 { - return util.ROTR32(x, 2) ~ util.ROTR32(x, 13) ~ util.ROTR32(x, 22) +@(private) +SHA256_F1 :: #force_inline proc "contextless" (x: u32) -> u32 { + return bits.rotate_left32(x, 30) ~ bits.rotate_left32(x, 19) ~ bits.rotate_left32(x, 10) } -SHA256_F2 :: #force_inline proc "contextless"(x: u32) -> u32 { - return util.ROTR32(x, 6) ~ util.ROTR32(x, 11) ~ util.ROTR32(x, 25) +@(private) +SHA256_F2 :: #force_inline proc "contextless" (x: u32) -> u32 { + return bits.rotate_left32(x, 26) ~ bits.rotate_left32(x, 21) ~ bits.rotate_left32(x, 7) } -SHA256_F3 :: #force_inline proc "contextless"(x: u32) -> u32 { - return util.ROTR32(x, 7) ~ util.ROTR32(x, 18) ~ (x >> 3) +@(private) +SHA256_F3 :: #force_inline proc "contextless" (x: u32) -> u32 { + return bits.rotate_left32(x, 25) ~ bits.rotate_left32(x, 14) ~ (x >> 3) } -SHA256_F4 :: #force_inline proc "contextless"(x: u32) -> u32 { - return util.ROTR32(x, 17) ~ util.ROTR32(x, 19) ~ (x >> 10) +@(private) +SHA256_F4 :: #force_inline proc "contextless" (x: u32) -> u32 { + return bits.rotate_left32(x, 15) ~ bits.rotate_left32(x, 13) ~ (x >> 10) } -SHA512_F1 :: #force_inline proc "contextless"(x: u64) -> u64 { - return util.ROTR64(x, 28) ~ util.ROTR64(x, 34) ~ util.ROTR64(x, 39) +@(private) +SHA512_F1 :: #force_inline proc "contextless" (x: u64) -> u64 { + return bits.rotate_left64(x, 36) ~ bits.rotate_left64(x, 30) ~ bits.rotate_left64(x, 25) } -SHA512_F2 :: #force_inline proc "contextless"(x: u64) -> u64 { - return util.ROTR64(x, 14) ~ util.ROTR64(x, 18) ~ util.ROTR64(x, 41) +@(private) +SHA512_F2 :: #force_inline proc "contextless" (x: u64) -> u64 { + return bits.rotate_left64(x, 50) ~ bits.rotate_left64(x, 46) ~ bits.rotate_left64(x, 23) } -SHA512_F3 :: #force_inline proc "contextless"(x: u64) -> u64 { - return util.ROTR64(x, 1) ~ util.ROTR64(x, 8) ~ (x >> 7) +@(private) +SHA512_F3 :: #force_inline proc "contextless" (x: u64) -> u64 { + return bits.rotate_left64(x, 63) ~ bits.rotate_left64(x, 56) ~ (x >> 7) } -SHA512_F4 :: #force_inline proc "contextless"(x: u64) -> u64 { - return util.ROTR64(x, 19) ~ util.ROTR64(x, 61) ~ (x >> 6) +@(private) +SHA512_F4 :: #force_inline proc "contextless" (x: u64) -> u64 { + return bits.rotate_left64(x, 45) ~ bits.rotate_left64(x, 3) ~ (x >> 6) } -PACK32 :: #force_inline proc "contextless"(b: []byte, x: ^u32) { - x^ = u32(b[3]) | u32(b[2]) << 8 | u32(b[1]) << 16 | u32(b[0]) << 24 -} - -PACK64 :: #force_inline proc "contextless"(b: []byte, x: ^u64) { - x^ = u64(b[7]) | u64(b[6]) << 8 | u64(b[5]) << 16 | u64(b[4]) << 24 | u64(b[3]) << 32 | u64(b[2]) << 40 | u64(b[1]) << 48 | u64(b[0]) << 56 -} - -sha2_transf :: proc(ctx: ^$T, data: []byte, block_nb: uint) { - when T == Sha256_Context { +@(private) +sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { + when T == Context_256 { w: [64]u32 wv: [8]u32 t1, t2: u32 - } else when T == Sha512_Context { + CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE + } else when T == Context_512 { w: [80]u64 wv: [8]u64 t1, t2: u64 + CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE } - sub_block := make([]byte, len(data)) - i, j: i32 - - for i = 0; i < i32(block_nb); i += 1 { - when T == Sha256_Context { - sub_block = data[i << 6:] - } else when T == Sha512_Context { - sub_block = data[i << 7:] - } - - for j = 0; j < 16; j += 1 { - when T == Sha256_Context { - PACK32(sub_block[j << 2:], &w[j]) - } else when T == Sha512_Context { - PACK64(sub_block[j << 3:], &w[j]) + data := data + for len(data) >= CURR_BLOCK_SIZE { + for i := 0; i < 16; i += 1 { + when T == Context_256 { + w[i] = endian.unchecked_get_u32be(data[i * 4:]) + } else when T == Context_512 { + w[i] = endian.unchecked_get_u64be(data[i * 8:]) } } - when T == Sha256_Context { - for j = 16; j < 64; j += 1 { - w[j] = SHA256_F4(w[j - 2]) + w[j - 7] + SHA256_F3(w[j - 15]) + w[j - 16] + when T == Context_256 { + for i := 16; i < 64; i += 1 { + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16] } - } else when T == Sha512_Context { - for j = 16; j < 80; j += 1 { - w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16] + } else when T == Context_512 { + for i := 16; i < 80; i += 1 { + w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16] } } - for j = 0; j < 8; j += 1 { - wv[j] = ctx.h[j] + for i := 0; i < 8; i += 1 { + wv[i] = ctx.h[i] } - when T == Sha256_Context { - for j = 0; j < 64; j += 1 { - t1 = wv[7] + SHA256_F2(wv[4]) + SHA256_CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j] + when T == Context_256 { + for i := 0; i < 64; i += 1 { + t1 = wv[7] + SHA256_F2(wv[4]) + SHA256_CH(wv[4], wv[5], wv[6]) + sha256_k[i] + w[i] t2 = SHA256_F1(wv[0]) + SHA256_MAJ(wv[0], wv[1], wv[2]) wv[7] = wv[6] wv[6] = wv[5] @@ -662,9 +782,9 @@ sha2_transf :: proc(ctx: ^$T, data: []byte, block_nb: uint) { wv[1] = wv[0] wv[0] = t1 + t2 } - } else when T == Sha512_Context { - for j = 0; j < 80; j += 1 { - t1 = wv[7] + SHA512_F2(wv[4]) + SHA512_CH(wv[4], wv[5], wv[6]) + sha512_k[j] + w[j] + } else when T == Context_512 { + for i := 0; i < 80; i += 1 { + t1 = wv[7] + SHA512_F2(wv[4]) + SHA512_CH(wv[4], wv[5], wv[6]) + sha512_k[i] + w[i] t2 = SHA512_F1(wv[0]) + SHA512_MAJ(wv[0], wv[1], wv[2]) wv[7] = wv[6] wv[6] = wv[5] @@ -677,8 +797,10 @@ sha2_transf :: proc(ctx: ^$T, data: []byte, block_nb: uint) { } } - for j = 0; j < 8; j += 1 { - ctx.h[j] += wv[j] + for i := 0; i < 8; i += 1 { + ctx.h[i] += wv[i] } + + data = data[CURR_BLOCK_SIZE:] } } diff --git a/core/crypto/sha3/sha3.odin b/core/crypto/sha3/sha3.odin index 5d8ad2106..f91baad3d 100644 --- a/core/crypto/sha3/sha3.odin +++ b/core/crypto/sha3/sha3.odin @@ -11,8 +11,8 @@ package sha3 If you wish to compute a Keccak hash, you can use the keccak package, it will use the original padding. */ -import "core:os" import "core:io" +import "core:os" import "../_sha3" @@ -28,333 +28,337 @@ DIGEST_SIZE_512 :: 64 // hash_string_224 will hash the given input and return the // computed hash hash_string_224 :: proc(data: string) -> [DIGEST_SIZE_224]byte { - return hash_bytes_224(transmute([]byte)(data)) + return hash_bytes_224(transmute([]byte)(data)) } // hash_bytes_224 will hash the given input and return the // computed hash hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte { - hash: [DIGEST_SIZE_224]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_224]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_224 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_224 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_224(transmute([]byte)(data), hash) + hash_bytes_to_buffer_224(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_224 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_224 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_224, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_224 will read the stream in chunks and compute a // hash from its contents hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) { - hash: [DIGEST_SIZE_224]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_224 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_224]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_224 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_224 will read the file provided by the given handle // and compute a hash hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_224]byte, bool) { - if !load_at_once { - return hash_stream_224(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_224(buf[:]), ok - } - } - return [DIGEST_SIZE_224]byte{}, false + if !load_at_once { + return hash_stream_224(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_224(buf[:]), ok + } + } + return [DIGEST_SIZE_224]byte{}, false } hash_224 :: proc { - hash_stream_224, - hash_file_224, - hash_bytes_224, - hash_string_224, - hash_bytes_to_buffer_224, - hash_string_to_buffer_224, + hash_stream_224, + hash_file_224, + hash_bytes_224, + hash_string_224, + hash_bytes_to_buffer_224, + hash_string_to_buffer_224, } // hash_string_256 will hash the given input and return the // computed hash hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) + return hash_bytes_256(transmute([]byte)(data)) } // hash_bytes_256 will hash the given input and return the // computed hash hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_256 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_256 will read the stream in chunks and compute a // hash from its contents hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_256 will read the file provided by the given handle // and compute a hash hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false + if !load_at_once { + return hash_stream_256(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_256(buf[:]), ok + } + } + return [DIGEST_SIZE_256]byte{}, false } hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, + hash_stream_256, + hash_file_256, + hash_bytes_256, + hash_string_256, + hash_bytes_to_buffer_256, + hash_string_to_buffer_256, } // hash_string_384 will hash the given input and return the // computed hash hash_string_384 :: proc(data: string) -> [DIGEST_SIZE_384]byte { - return hash_bytes_384(transmute([]byte)(data)) + return hash_bytes_384(transmute([]byte)(data)) } // hash_bytes_384 will hash the given input and return the // computed hash hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte { - hash: [DIGEST_SIZE_384]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_384]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_384 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_384 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_384(transmute([]byte)(data), hash) + hash_bytes_to_buffer_384(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_384 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_384 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_384, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_384 will read the stream in chunks and compute a // hash from its contents hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) { - hash: [DIGEST_SIZE_384]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_384 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_384]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_384 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_384 will read the file provided by the given handle // and compute a hash hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_384]byte, bool) { - if !load_at_once { - return hash_stream_384(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_384(buf[:]), ok - } - } - return [DIGEST_SIZE_384]byte{}, false + if !load_at_once { + return hash_stream_384(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_384(buf[:]), ok + } + } + return [DIGEST_SIZE_384]byte{}, false } hash_384 :: proc { - hash_stream_384, - hash_file_384, - hash_bytes_384, - hash_string_384, - hash_bytes_to_buffer_384, - hash_string_to_buffer_384, + hash_stream_384, + hash_file_384, + hash_bytes_384, + hash_string_384, + hash_bytes_to_buffer_384, + hash_string_to_buffer_384, } // hash_string_512 will hash the given input and return the // computed hash hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) + return hash_bytes_512(transmute([]byte)(data)) } // hash_bytes_512 will hash the given input and return the // computed hash hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_512]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_512 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) + hash_bytes_to_buffer_512(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_512 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.final(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_512 will read the stream in chunks and compute a // hash from its contents hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_512 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_512]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_512 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_512 will read the file provided by the given handle // and compute a hash hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false + if !load_at_once { + return hash_stream_512(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_512(buf[:]), ok + } + } + return [DIGEST_SIZE_512]byte{}, false } hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, + hash_stream_512, + hash_file_512, + hash_bytes_512, + hash_string_512, + hash_bytes_to_buffer_512, + hash_string_to_buffer_512, } /* Low level API */ -Sha3_Context :: _sha3.Sha3_Context +Context :: _sha3.Sha3_Context -init :: proc(ctx: ^_sha3.Sha3_Context) { - _sha3.init(ctx) +init :: proc(ctx: ^Context) { + _sha3.init(ctx) } -update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) { - _sha3.update(ctx, data) +update :: proc(ctx: ^Context, data: []byte) { + _sha3.update(ctx, data) } -final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) { - _sha3.final(ctx, hash) +final :: proc(ctx: ^Context, hash: []byte) { + _sha3.final(ctx, hash) } diff --git a/core/crypto/shake/shake.odin b/core/crypto/shake/shake.odin index 020ba68f3..e4b4c1e31 100644 --- a/core/crypto/shake/shake.odin +++ b/core/crypto/shake/shake.odin @@ -9,10 +9,13 @@ package shake Interface for the SHAKE hashing algorithm. The SHA3 functionality can be found in package sha3. + + TODO: This should provide an incremental squeeze interface, in addition + to the one-shot final call. */ -import "core:os" import "core:io" +import "core:os" import "../_sha3" @@ -26,182 +29,178 @@ DIGEST_SIZE_256 :: 32 // hash_string_128 will hash the given input and return the // computed hash hash_string_128 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128(transmute([]byte)(data)) + return hash_bytes_128(transmute([]byte)(data)) } // hash_bytes_128 will hash the given input and return the // computed hash hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_128 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_128]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_128 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_128 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash) + hash_bytes_to_buffer_128(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_128 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_128 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_128 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_128 + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream_128 will read the stream in chunks and compute a // hash from its contents hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_128 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_128]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_128 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_128 will read the file provided by the given handle // and compute a hash hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false + if !load_at_once { + return hash_stream_128(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_128(buf[:]), ok + } + } + return [DIGEST_SIZE_128]byte{}, false } hash_128 :: proc { - hash_stream_128, - hash_file_128, - hash_bytes_128, - hash_string_128, - hash_bytes_to_buffer_128, - hash_string_to_buffer_128, + hash_stream_128, + hash_file_128, + hash_bytes_128, + hash_string_128, + hash_bytes_to_buffer_128, + hash_string_to_buffer_128, } // hash_string_256 will hash the given input and return the // computed hash hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) + return hash_bytes_256(transmute([]byte)(data)) } // hash_bytes_256 will hash the given input and return the // computed hash hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer_256 will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) + hash_bytes_to_buffer_256(transmute([]byte)(data), hash) } // hash_bytes_to_buffer_256 will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - _sha3.update(&ctx, data) - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash) + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) } // hash_stream_256 will read the stream in chunks and compute a // hash from its contents hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: _sha3.Sha3_Context - ctx.mdlen = DIGEST_SIZE_256 - _sha3.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _sha3.update(&ctx, buf[:read]) - } - } - _sha3.shake_xof(&ctx) - _sha3.shake_out(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE_256]byte + ctx: Context + ctx.mdlen = DIGEST_SIZE_256 + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file_256 will read the file provided by the given handle // and compute a hash hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false + if !load_at_once { + return hash_stream_256(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes_256(buf[:]), ok + } + } + return [DIGEST_SIZE_256]byte{}, false } hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, + hash_stream_256, + hash_file_256, + hash_bytes_256, + hash_string_256, + hash_bytes_to_buffer_256, + hash_string_to_buffer_256, } /* Low level API */ -Shake_Context :: _sha3.Sha3_Context +Context :: _sha3.Sha3_Context -init :: proc(ctx: ^_sha3.Sha3_Context) { - _sha3.init(ctx) +init :: proc(ctx: ^Context) { + _sha3.init(ctx) } -update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) { - _sha3.update(ctx, data) +update :: proc(ctx: ^Context, data: []byte) { + _sha3.update(ctx, data) } -final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) { - _sha3.shake_xof(ctx) - _sha3.shake_out(ctx, hash[:]) +final :: proc(ctx: ^Context, hash: []byte) { + _sha3.shake_xof(ctx) + _sha3.shake_out(ctx, hash[:]) } diff --git a/core/crypto/siphash/siphash.odin b/core/crypto/siphash/siphash.odin index 2d03829c2..c51e38ab0 100644 --- a/core/crypto/siphash/siphash.odin +++ b/core/crypto/siphash/siphash.odin @@ -13,202 +13,200 @@ package siphash */ import "core:crypto" -import "core:crypto/util" +import "core:encoding/endian" +import "core:math/bits" /* High level API */ -KEY_SIZE :: 16 +KEY_SIZE :: 16 DIGEST_SIZE :: 8 // sum_string_1_3 will hash the given message with the key and return // the computed hash as a u64 sum_string_1_3 :: proc(msg, key: string) -> u64 { - return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key)) + return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key)) } // sum_bytes_1_3 will hash the given message with the key and return // the computed hash as a u64 -sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 { - ctx: Context - hash: u64 - init(&ctx, key, 1, 3) - update(&ctx, msg) - final(&ctx, &hash) - return hash +sum_bytes_1_3 :: proc(msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 1, 3) + update(&ctx, msg) + final(&ctx, &hash) + return hash } // sum_string_to_buffer_1_3 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) { - sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst) + sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst) } // sum_bytes_to_buffer_1_3 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) { - assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") - hash := sum_bytes_1_3(msg, key) - _collect_output(dst[:], hash) + hash := sum_bytes_1_3(msg, key) + _collect_output(dst[:], hash) } sum_1_3 :: proc { - sum_string_1_3, - sum_bytes_1_3, - sum_string_to_buffer_1_3, - sum_bytes_to_buffer_1_3, + sum_string_1_3, + sum_bytes_1_3, + sum_string_to_buffer_1_3, + sum_bytes_to_buffer_1_3, } -// verify_u64_1_3 will check if the supplied tag matches with the output you +// verify_u64_1_3 will check if the supplied tag matches with the output you // will get from the provided message and key -verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool { - return sum_bytes_1_3(msg, key) == tag +verify_u64_1_3 :: proc(tag: u64, msg, key: []byte) -> bool { + return sum_bytes_1_3(msg, key) == tag } -// verify_bytes will check if the supplied tag matches with the output you +// verify_bytes will check if the supplied tag matches with the output you // will get from the provided message and key -verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool { - derived_tag: [8]byte - sum_bytes_to_buffer_1_3(msg, key, derived_tag[:]) - return crypto.compare_constant_time(derived_tag[:], tag) == 1 +verify_bytes_1_3 :: proc(tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_1_3(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 } verify_1_3 :: proc { - verify_bytes_1_3, - verify_u64_1_3, + verify_bytes_1_3, + verify_u64_1_3, } // sum_string_2_4 will hash the given message with the key and return // the computed hash as a u64 sum_string_2_4 :: proc(msg, key: string) -> u64 { - return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key)) + return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key)) } // sum_bytes_2_4 will hash the given message with the key and return // the computed hash as a u64 -sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 { - ctx: Context - hash: u64 - init(&ctx, key, 2, 4) - update(&ctx, msg) - final(&ctx, &hash) - return hash +sum_bytes_2_4 :: proc(msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 2, 4) + update(&ctx, msg) + final(&ctx, &hash) + return hash } // sum_string_to_buffer_2_4 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) { - sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst) + sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst) } // sum_bytes_to_buffer_2_4 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) { - assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") - hash := sum_bytes_2_4(msg, key) - _collect_output(dst[:], hash) + hash := sum_bytes_2_4(msg, key) + _collect_output(dst[:], hash) } sum_2_4 :: proc { - sum_string_2_4, - sum_bytes_2_4, - sum_string_to_buffer_2_4, - sum_bytes_to_buffer_2_4, + sum_string_2_4, + sum_bytes_2_4, + sum_string_to_buffer_2_4, + sum_bytes_to_buffer_2_4, } -sum_string :: sum_string_2_4 -sum_bytes :: sum_bytes_2_4 +sum_string :: sum_string_2_4 +sum_bytes :: sum_bytes_2_4 sum_string_to_buffer :: sum_string_to_buffer_2_4 -sum_bytes_to_buffer :: sum_bytes_to_buffer_2_4 +sum_bytes_to_buffer :: sum_bytes_to_buffer_2_4 sum :: proc { - sum_string, - sum_bytes, - sum_string_to_buffer, - sum_bytes_to_buffer, + sum_string, + sum_bytes, + sum_string_to_buffer, + sum_bytes_to_buffer, } -// verify_u64_2_4 will check if the supplied tag matches with the output you +// verify_u64_2_4 will check if the supplied tag matches with the output you // will get from the provided message and key -verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool { - return sum_bytes_2_4(msg, key) == tag +verify_u64_2_4 :: proc(tag: u64, msg, key: []byte) -> bool { + return sum_bytes_2_4(msg, key) == tag } -// verify_bytes will check if the supplied tag matches with the output you +// verify_bytes will check if the supplied tag matches with the output you // will get from the provided message and key -verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool { - derived_tag: [8]byte - sum_bytes_to_buffer_2_4(msg, key, derived_tag[:]) - return crypto.compare_constant_time(derived_tag[:], tag) == 1 +verify_bytes_2_4 :: proc(tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_2_4(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 } verify_2_4 :: proc { - verify_bytes_2_4, - verify_u64_2_4, + verify_bytes_2_4, + verify_u64_2_4, } verify_bytes :: verify_bytes_2_4 -verify_u64 :: verify_u64_2_4 +verify_u64 :: verify_u64_2_4 verify :: proc { - verify_bytes, - verify_u64, + verify_bytes, + verify_u64, } // sum_string_4_8 will hash the given message with the key and return // the computed hash as a u64 sum_string_4_8 :: proc(msg, key: string) -> u64 { - return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key)) + return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key)) } // sum_bytes_4_8 will hash the given message with the key and return // the computed hash as a u64 -sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 { - ctx: Context - hash: u64 - init(&ctx, key, 4, 8) - update(&ctx, msg) - final(&ctx, &hash) - return hash +sum_bytes_4_8 :: proc(msg, key: []byte) -> u64 { + ctx: Context + hash: u64 + init(&ctx, key, 4, 8) + update(&ctx, msg) + final(&ctx, &hash) + return hash } // sum_string_to_buffer_4_8 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) { - sum_bytes_to_buffer_4_8(transmute([]byte)(msg), transmute([]byte)(key), dst) + sum_bytes_to_buffer_4_8(transmute([]byte)(msg), transmute([]byte)(key), dst) } // sum_bytes_to_buffer_4_8 will hash the given message with the key and write // the computed hash into the provided destination buffer sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) { - assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8") - hash := sum_bytes_4_8(msg, key) - _collect_output(dst[:], hash) + hash := sum_bytes_4_8(msg, key) + _collect_output(dst[:], hash) } sum_4_8 :: proc { - sum_string_4_8, - sum_bytes_4_8, - sum_string_to_buffer_4_8, - sum_bytes_to_buffer_4_8, + sum_string_4_8, + sum_bytes_4_8, + sum_string_to_buffer_4_8, + sum_bytes_to_buffer_4_8, } -// verify_u64_4_8 will check if the supplied tag matches with the output you +// verify_u64_4_8 will check if the supplied tag matches with the output you // will get from the provided message and key -verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool { - return sum_bytes_4_8(msg, key) == tag +verify_u64_4_8 :: proc(tag: u64, msg, key: []byte) -> bool { + return sum_bytes_4_8(msg, key) == tag } -// verify_bytes will check if the supplied tag matches with the output you +// verify_bytes will check if the supplied tag matches with the output you // will get from the provided message and key -verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool { - derived_tag: [8]byte - sum_bytes_to_buffer_4_8(msg, key, derived_tag[:]) - return crypto.compare_constant_time(derived_tag[:], tag) == 1 +verify_bytes_4_8 :: proc(tag, msg, key: []byte) -> bool { + derived_tag: [8]byte + sum_bytes_to_buffer_4_8(msg, key, derived_tag[:]) + return crypto.compare_constant_time(derived_tag[:], tag) == 1 } verify_4_8 :: proc { - verify_bytes_4_8, - verify_u64_4_8, + verify_bytes_4_8, + verify_u64_4_8, } /* @@ -216,120 +214,150 @@ verify_4_8 :: proc { */ init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { - assert(len(key) == KEY_SIZE, "crypto/siphash: Invalid key size, want 16") - ctx.c_rounds = c_rounds - ctx.d_rounds = d_rounds - is_valid_setting := (ctx.c_rounds == 1 && ctx.d_rounds == 3) || - (ctx.c_rounds == 2 && ctx.d_rounds == 4) || - (ctx.c_rounds == 4 && ctx.d_rounds == 8) - assert(is_valid_setting, "crypto/siphash: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)") - ctx.k0 = util.U64_LE(key[:8]) - ctx.k1 = util.U64_LE(key[8:]) - ctx.v0 = 0x736f6d6570736575 ~ ctx.k0 - ctx.v1 = 0x646f72616e646f6d ~ ctx.k1 - ctx.v2 = 0x6c7967656e657261 ~ ctx.k0 - ctx.v3 = 0x7465646279746573 ~ ctx.k1 - ctx.is_initialized = true + if len(key) != KEY_SIZE { + panic("crypto/siphash; invalid key size") + } + ctx.c_rounds = c_rounds + ctx.d_rounds = d_rounds + is_valid_setting := + (ctx.c_rounds == 1 && ctx.d_rounds == 3) || + (ctx.c_rounds == 2 && ctx.d_rounds == 4) || + (ctx.c_rounds == 4 && ctx.d_rounds == 8) + if !is_valid_setting { + panic("crypto/siphash: incorrect rounds set up") + } + ctx.k0 = endian.unchecked_get_u64le(key[:8]) + ctx.k1 = endian.unchecked_get_u64le(key[8:]) + ctx.v0 = 0x736f6d6570736575 ~ ctx.k0 + ctx.v1 = 0x646f72616e646f6d ~ ctx.k1 + ctx.v2 = 0x6c7967656e657261 ~ ctx.k0 + ctx.v3 = 0x7465646279746573 ~ ctx.k1 + + ctx.last_block = 0 + ctx.total_length = 0 + + ctx.is_initialized = true } update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized, "crypto/siphash: Context is not initialized") - ctx.last_block = len(data) / 8 * 8 - ctx.buf = data - i := 0 - m: u64 - for i < ctx.last_block { - m = u64(ctx.buf[i] & 0xff) - i += 1 + assert(ctx.is_initialized, "crypto/siphash: context is not initialized") - for r in u64(1)..<8 { - m |= u64(ctx.buf[i] & 0xff) << (r * 8) - i += 1 - } - - ctx.v3 ~= m - for _ in 0.. 0 { + n := copy(ctx.buf[ctx.last_block:], data) + ctx.last_block += n + if ctx.last_block == BLOCK_SIZE { + block(ctx, ctx.buf[:]) + ctx.last_block = 0 + } + data = data[n:] + } + if len(data) >= BLOCK_SIZE { + n := len(data) &~ (BLOCK_SIZE - 1) + block(ctx, data[:n]) + data = data[n:] + } + if len(data) > 0 { + ctx.last_block = copy(ctx.buf[:], data) + } } final :: proc(ctx: ^Context, dst: ^u64) { - m: u64 - for i := len(ctx.buf) - 1; i >= ctx.last_block; i -= 1 { - m <<= 8 - m |= u64(ctx.buf[i] & 0xff) - } - m |= u64(len(ctx.buf) << 56) + assert(ctx.is_initialized, "crypto/siphash: context is not initialized") - ctx.v3 ~= m + tmp: [BLOCK_SIZE]byte + copy(tmp[:], ctx.buf[:ctx.last_block]) + tmp[7] = byte(ctx.total_length & 0xff) + block(ctx, tmp[:]) - for _ in 0..= BLOCK_SIZE { + m := endian.unchecked_get_u64le(buf) + + ctx.v3 ~= m + for _ in 0 ..< ctx.c_rounds { + _compress(ctx) + } + + ctx.v0 ~= m + + buf = buf[BLOCK_SIZE:] + } +} + +@(private) _get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byte { - return byte(into >> (((~byte_num) & (size_of(u64) - 1)) << 3)) + return byte(into >> (((~byte_num) & (size_of(u64) - 1)) << 3)) } -_collect_output :: #force_inline proc "contextless" (dst: []byte, hash: u64) { - dst[0] = _get_byte(7, hash) - dst[1] = _get_byte(6, hash) - dst[2] = _get_byte(5, hash) - dst[3] = _get_byte(4, hash) - dst[4] = _get_byte(3, hash) - dst[5] = _get_byte(2, hash) - dst[6] = _get_byte(1, hash) - dst[7] = _get_byte(0, hash) +@(private) +_collect_output :: #force_inline proc(dst: []byte, hash: u64) { + if len(dst) < DIGEST_SIZE { + panic("crypto/siphash: invalid tag size") + } + dst[0] = _get_byte(7, hash) + dst[1] = _get_byte(6, hash) + dst[2] = _get_byte(5, hash) + dst[3] = _get_byte(4, hash) + dst[4] = _get_byte(3, hash) + dst[5] = _get_byte(2, hash) + dst[6] = _get_byte(1, hash) + dst[7] = _get_byte(0, hash) } +@(private) _compress :: #force_inline proc "contextless" (ctx: ^Context) { - ctx.v0 += ctx.v1 - ctx.v1 = util.ROTL64(ctx.v1, 13) - ctx.v1 ~= ctx.v0 - ctx.v0 = util.ROTL64(ctx.v0, 32) - ctx.v2 += ctx.v3 - ctx.v3 = util.ROTL64(ctx.v3, 16) - ctx.v3 ~= ctx.v2 - ctx.v0 += ctx.v3 - ctx.v3 = util.ROTL64(ctx.v3, 21) - ctx.v3 ~= ctx.v0 - ctx.v2 += ctx.v1 - ctx.v1 = util.ROTL64(ctx.v1, 17) - ctx.v1 ~= ctx.v2 - ctx.v2 = util.ROTL64(ctx.v2, 32) + ctx.v0 += ctx.v1 + ctx.v1 = bits.rotate_left64(ctx.v1, 13) + ctx.v1 ~= ctx.v0 + ctx.v0 = bits.rotate_left64(ctx.v0, 32) + ctx.v2 += ctx.v3 + ctx.v3 = bits.rotate_left64(ctx.v3, 16) + ctx.v3 ~= ctx.v2 + ctx.v0 += ctx.v3 + ctx.v3 = bits.rotate_left64(ctx.v3, 21) + ctx.v3 ~= ctx.v0 + ctx.v2 += ctx.v1 + ctx.v1 = bits.rotate_left64(ctx.v1, 17) + ctx.v1 ~= ctx.v2 + ctx.v2 = bits.rotate_left64(ctx.v2, 32) } diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin index 9e684ff08..7a7a0b8a6 100644 --- a/core/crypto/sm3/sm3.odin +++ b/core/crypto/sm3/sm3.odin @@ -10,10 +10,10 @@ package sm3 Implementation of the SM3 hashing algorithm, as defined in */ -import "core:os" +import "core:encoding/endian" import "core:io" - -import "../util" +import "core:math/bits" +import "core:os" /* High level API @@ -24,227 +24,256 @@ DIGEST_SIZE :: 32 // hash_string will hash the given input and return the // computed hash hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) + return hash_bytes(transmute([]byte)(data)) } // hash_bytes will hash the given input and return the // computed hash hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Sm3_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash[:]) + return hash } // hash_string_to_buffer will hash the given input and assign the // computed hash to the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) + hash_bytes_to_buffer(transmute([]byte)(data), hash) } // hash_bytes_to_buffer will hash the given input and write the // computed hash into the second parameter. // It requires that the destination buffer is at least as big as the digest size hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Sm3_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash) + ctx: Context + init(&ctx) + update(&ctx, data) + final(&ctx, hash) } // hash_stream will read the stream in chunks and compute a // hash from its contents hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Sm3_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true + hash: [DIGEST_SIZE]byte + ctx: Context + init(&ctx) + + buf := make([]byte, 512) + defer delete(buf) + + read := 1 + for read > 0 { + read, _ = io.read(s, buf) + if read > 0 { + update(&ctx, buf[:read]) + } + } + final(&ctx, hash[:]) + return hash, true } // hash_file will read the file provided by the given handle // and compute a hash hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false + if !load_at_once { + return hash_stream(os.stream_from_handle(hd)) + } else { + if buf, ok := os.read_entire_file(hd); ok { + return hash_bytes(buf[:]), ok + } + } + return [DIGEST_SIZE]byte{}, false } hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, + hash_stream, + hash_file, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, } /* Low level API */ -init :: proc(ctx: ^Sm3_Context) { - ctx.state[0] = IV[0] - ctx.state[1] = IV[1] - ctx.state[2] = IV[2] - ctx.state[3] = IV[3] - ctx.state[4] = IV[4] - ctx.state[5] = IV[5] - ctx.state[6] = IV[6] - ctx.state[7] = IV[7] +init :: proc(ctx: ^Context) { + ctx.state[0] = IV[0] + ctx.state[1] = IV[1] + ctx.state[2] = IV[2] + ctx.state[3] = IV[3] + ctx.state[4] = IV[4] + ctx.state[5] = IV[5] + ctx.state[6] = IV[6] + ctx.state[7] = IV[7] + + ctx.length = 0 + ctx.bitlength = 0 + + ctx.is_initialized = true } -update :: proc(ctx: ^Sm3_Context, data: []byte) { - data := data - ctx.length += u64(len(data)) +update :: proc(ctx: ^Context, data: []byte) { + assert(ctx.is_initialized) - if ctx.bitlength > 0 { - n := copy(ctx.x[ctx.bitlength:], data[:]) - ctx.bitlength += u64(n) - if ctx.bitlength == 64 { - block(ctx, ctx.x[:]) - ctx.bitlength = 0 - } - data = data[n:] - } - if len(data) >= 64 { - n := len(data) &~ (64 - 1) - block(ctx, data[:n]) - data = data[n:] - } - if len(data) > 0 { - ctx.bitlength = u64(copy(ctx.x[:], data[:])) - } + data := data + ctx.length += u64(len(data)) + + if ctx.bitlength > 0 { + n := copy(ctx.x[ctx.bitlength:], data[:]) + ctx.bitlength += u64(n) + if ctx.bitlength == BLOCK_SIZE { + block(ctx, ctx.x[:]) + ctx.bitlength = 0 + } + data = data[n:] + } + if len(data) >= BLOCK_SIZE { + n := len(data) &~ (BLOCK_SIZE - 1) + block(ctx, data[:n]) + data = data[n:] + } + if len(data) > 0 { + ctx.bitlength = u64(copy(ctx.x[:], data[:])) + } } -final :: proc(ctx: ^Sm3_Context, hash: []byte) { - length := ctx.length +final :: proc(ctx: ^Context, hash: []byte) { + assert(ctx.is_initialized) - pad: [64]byte - pad[0] = 0x80 - if length % 64 < 56 { - update(ctx, pad[0: 56 - length % 64]) - } else { - update(ctx, pad[0: 64 + 56 - length % 64]) - } + if len(hash) < DIGEST_SIZE { + panic("crypto/sm3: invalid destination digest size") + } - length <<= 3 - util.PUT_U64_BE(pad[:], length) - update(ctx, pad[0: 8]) - assert(ctx.bitlength == 0) + length := ctx.length - util.PUT_U32_BE(hash[0:], ctx.state[0]) - util.PUT_U32_BE(hash[4:], ctx.state[1]) - util.PUT_U32_BE(hash[8:], ctx.state[2]) - util.PUT_U32_BE(hash[12:], ctx.state[3]) - util.PUT_U32_BE(hash[16:], ctx.state[4]) - util.PUT_U32_BE(hash[20:], ctx.state[5]) - util.PUT_U32_BE(hash[24:], ctx.state[6]) - util.PUT_U32_BE(hash[28:], ctx.state[7]) + pad: [BLOCK_SIZE]byte + pad[0] = 0x80 + if length % BLOCK_SIZE < 56 { + update(ctx, pad[0:56 - length % BLOCK_SIZE]) + } else { + update(ctx, pad[0:BLOCK_SIZE + 56 - length % BLOCK_SIZE]) + } + + length <<= 3 + endian.unchecked_put_u64be(pad[:], length) + update(ctx, pad[0:8]) + assert(ctx.bitlength == 0) + + for i := 0; i < DIGEST_SIZE / 4; i += 1 { + endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i]) + } + + ctx.is_initialized = false } /* SM3 implementation */ -Sm3_Context :: struct { - state: [8]u32, - x: [64]byte, - bitlength: u64, - length: u64, +BLOCK_SIZE :: 64 + +Context :: struct { + state: [8]u32, + x: [BLOCK_SIZE]byte, + bitlength: u64, + length: u64, + + is_initialized: bool, } +@(private) IV := [8]u32 { - 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, - 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e, + 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, + 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e, } -block :: proc "contextless" (ctx: ^Sm3_Context, buf: []byte) { - buf := buf +@(private) +block :: proc "contextless" (ctx: ^Context, buf: []byte) { + buf := buf - w: [68]u32 - wp: [64]u32 + w: [68]u32 + wp: [64]u32 - state0, state1, state2, state3 := ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3] - state4, state5, state6, state7 := ctx.state[4], ctx.state[5], ctx.state[6], ctx.state[7] + state0, state1, state2, state3 := ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3] + state4, state5, state6, state7 := ctx.state[4], ctx.state[5], ctx.state[6], ctx.state[7] - for len(buf) >= 64 { - for i := 0; i < 16; i += 1 { - j := i * 4 - w[i] = u32(buf[j]) << 24 | u32(buf[j + 1]) << 16 | u32(buf[j + 2]) << 8 | u32(buf[j + 3]) - } - for i := 16; i < 68; i += 1 { - p1v := w[i - 16] ~ w[i - 9] ~ util.ROTL32(w[i - 3], 15) - // @note(zh): inlined P1 - w[i] = p1v ~ util.ROTL32(p1v, 15) ~ util.ROTL32(p1v, 23) ~ util.ROTL32(w[i - 13], 7) ~ w[i - 6] - } - for i := 0; i < 64; i += 1 { - wp[i] = w[i] ~ w[i + 4] - } + for len(buf) >= BLOCK_SIZE { + for i := 0; i < 16; i += 1 { + w[i] = endian.unchecked_get_u32be(buf[i * 4:]) + } + for i := 16; i < 68; i += 1 { + p1v := w[i - 16] ~ w[i - 9] ~ bits.rotate_left32(w[i - 3], 15) + // @note(zh): inlined P1 + w[i] = + p1v ~ + bits.rotate_left32(p1v, 15) ~ + bits.rotate_left32(p1v, 23) ~ + bits.rotate_left32(w[i - 13], 7) ~ + w[i - 6] + } + for i := 0; i < 64; i += 1 { + wp[i] = w[i] ~ w[i + 4] + } - a, b, c, d := state0, state1, state2, state3 - e, f, g, h := state4, state5, state6, state7 + a, b, c, d := state0, state1, state2, state3 + e, f, g, h := state4, state5, state6, state7 - for i := 0; i < 16; i += 1 { - v1 := util.ROTL32(u32(a), 12) - ss1 := util.ROTL32(v1 + u32(e) + util.ROTL32(0x79cc4519, i), 7) - ss2 := ss1 ~ v1 + for i := 0; i < 16; i += 1 { + v1 := bits.rotate_left32(u32(a), 12) + ss1 := bits.rotate_left32(v1 + u32(e) + bits.rotate_left32(0x79cc4519, i), 7) + ss2 := ss1 ~ v1 - // @note(zh): inlined FF1 - tt1 := u32(a ~ b ~ c) + u32(d) + ss2 + wp[i] - // @note(zh): inlined GG1 - tt2 := u32(e ~ f ~ g) + u32(h) + ss1 + w[i] + // @note(zh): inlined FF1 + tt1 := u32(a ~ b ~ c) + u32(d) + ss2 + wp[i] + // @note(zh): inlined GG1 + tt2 := u32(e ~ f ~ g) + u32(h) + ss1 + w[i] - a, b, c, d = tt1, a, util.ROTL32(u32(b), 9), c - // @note(zh): inlined P0 - e, f, g, h = (tt2 ~ util.ROTL32(tt2, 9) ~ util.ROTL32(tt2, 17)), e, util.ROTL32(u32(f), 19), g - } + a, b, c, d = tt1, a, bits.rotate_left32(u32(b), 9), c + // @note(zh): inlined P0 + e, f, g, h = + (tt2 ~ bits.rotate_left32(tt2, 9) ~ bits.rotate_left32(tt2, 17)), + e, + bits.rotate_left32(u32(f), 19), + g + } - for i := 16; i < 64; i += 1 { - v := util.ROTL32(u32(a), 12) - ss1 := util.ROTL32(v + u32(e) + util.ROTL32(0x7a879d8a, i % 32), 7) - ss2 := ss1 ~ v + for i := 16; i < 64; i += 1 { + v := bits.rotate_left32(u32(a), 12) + ss1 := bits.rotate_left32(v + u32(e) + bits.rotate_left32(0x7a879d8a, i % 32), 7) + ss2 := ss1 ~ v - // @note(zh): inlined FF2 - tt1 := u32(((a & b) | (a & c) | (b & c)) + d) + ss2 + wp[i] - // @note(zh): inlined GG2 - tt2 := u32(((e & f) | ((~e) & g)) + h) + ss1 + w[i] + // @note(zh): inlined FF2 + tt1 := u32(((a & b) | (a & c) | (b & c)) + d) + ss2 + wp[i] + // @note(zh): inlined GG2 + tt2 := u32(((e & f) | ((~e) & g)) + h) + ss1 + w[i] - a, b, c, d = tt1, a, util.ROTL32(u32(b), 9), c - // @note(zh): inlined P0 - e, f, g, h = (tt2 ~ util.ROTL32(tt2, 9) ~ util.ROTL32(tt2, 17)), e, util.ROTL32(u32(f), 19), g - } + a, b, c, d = tt1, a, bits.rotate_left32(u32(b), 9), c + // @note(zh): inlined P0 + e, f, g, h = + (tt2 ~ bits.rotate_left32(tt2, 9) ~ bits.rotate_left32(tt2, 17)), + e, + bits.rotate_left32(u32(f), 19), + g + } - state0 ~= a - state1 ~= b - state2 ~= c - state3 ~= d - state4 ~= e - state5 ~= f - state6 ~= g - state7 ~= h + state0 ~= a + state1 ~= b + state2 ~= c + state3 ~= d + state4 ~= e + state5 ~= f + state6 ~= g + state7 ~= h - buf = buf[64:] - } + buf = buf[BLOCK_SIZE:] + } - ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3] = state0, state1, state2, state3 - ctx.state[4], ctx.state[5], ctx.state[6], ctx.state[7] = state4, state5, state6, state7 + ctx.state[0], ctx.state[1], ctx.state[2], ctx.state[3] = state0, state1, state2, state3 + ctx.state[4], ctx.state[5], ctx.state[6], ctx.state[7] = state4, state5, state6, state7 } diff --git a/core/crypto/streebog/streebog.odin b/core/crypto/streebog/streebog.odin deleted file mode 100644 index 42da1e695..000000000 --- a/core/crypto/streebog/streebog.odin +++ /dev/null @@ -1,517 +0,0 @@ -package streebog - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the Streebog hashing algorithm, standardized as GOST R 34.11-2012 in RFC 6986 -*/ - -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE_256 :: 32 -DIGEST_SIZE_512 :: 64 - -// hash_string_256 will hash the given input and return the -// computed hash -hash_string_256 :: proc(data: string) -> [DIGEST_SIZE_256]byte { - return hash_bytes_256(transmute([]byte)(data)) -} - -// hash_bytes_256 will hash the given input and return the -// computed hash -hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte { - hash: [DIGEST_SIZE_256]byte - ctx: Streebog_Context - ctx.is256 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_256 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_256 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_256(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_256 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_256 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_256, "Size of destination buffer is smaller than the digest size") - ctx: Streebog_Context - ctx.is256 = true - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) -} - -// hash_stream_256 will read the stream in chunks and compute a -// hash from its contents -hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) { - hash: [DIGEST_SIZE_256]byte - ctx: Streebog_Context - ctx.is256 = true - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_256 will read the file provided by the given handle -// and compute a hash -hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_256]byte, bool) { - if !load_at_once { - return hash_stream_256(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_256(buf[:]), ok - } - } - return [DIGEST_SIZE_256]byte{}, false -} - -hash_256 :: proc { - hash_stream_256, - hash_file_256, - hash_bytes_256, - hash_string_256, - hash_bytes_to_buffer_256, - hash_string_to_buffer_256, -} - -// hash_string_512 will hash the given input and return the -// computed hash -hash_string_512 :: proc(data: string) -> [DIGEST_SIZE_512]byte { - return hash_bytes_512(transmute([]byte)(data)) -} - -// hash_bytes_512 will hash the given input and return the -// computed hash -hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte { - hash: [DIGEST_SIZE_512]byte - ctx: Streebog_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_512 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_512 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_512(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_512 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_512 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_512, "Size of destination buffer is smaller than the digest size") - ctx: Streebog_Context - init(&ctx) - update(&ctx, data) - final(&ctx, hash[:]) -} - -// hash_stream_512 will read the stream in chunks and compute a -// hash from its contents -hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) { - hash: [DIGEST_SIZE_512]byte - ctx: Streebog_Context - init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file_512 will read the file provided by the given handle -// and compute a hash -hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_512]byte, bool) { - if !load_at_once { - return hash_stream_512(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_512(buf[:]), ok - } - } - return [DIGEST_SIZE_512]byte{}, false -} - -hash_512 :: proc { - hash_stream_512, - hash_file_512, - hash_bytes_512, - hash_string_512, - hash_bytes_to_buffer_512, - hash_string_to_buffer_512, -} - -/* - Low level API -*/ - -init :: proc(ctx: ^Streebog_Context) { - if ctx.is256 { - ctx.hash_size = 256 - for _, i in ctx.h { - ctx.h[i] = 0x01 - } - } else { - ctx.hash_size = 512 - } - ctx.v_512[1] = 0x02 -} - -update :: proc(ctx: ^Streebog_Context, data: []byte) { - length := u64(len(data)) - chk_size: u64 - data := data - for (length > 63) && (ctx.buf_size == 0) { - stage2(ctx, data) - data = data[64:] - length -= 64 - } - - for length != 0 { - chk_size = 64 - ctx.buf_size - if chk_size > length { - chk_size = length - } - copy(ctx.buffer[ctx.buf_size:], data[:chk_size]) - ctx.buf_size += chk_size - length -= chk_size - data = data[chk_size:] - if ctx.buf_size == 64 { - stage2(ctx, ctx.buffer[:]) - ctx.buf_size = 0 - } - } -} - -final :: proc(ctx: ^Streebog_Context, hash: []byte) { - t: [64]byte - t[1] = byte((ctx.buf_size * 8) >> 8) & 0xff - t[0] = byte((ctx.buf_size) * 8) & 0xff - - padding(ctx) - - G(ctx.h[:], ctx.n[:], ctx.buffer[:]) - - add_mod_512(ctx.n[:], t[:], ctx.n[:]) - add_mod_512(ctx.sigma[:], ctx.buffer[:], ctx.sigma[:]) - - G(ctx.h[:], ctx.v_0[:], ctx.n[:]) - G(ctx.h[:], ctx.v_0[:], ctx.sigma[:]) - - if ctx.is256 { - copy(hash[:], ctx.h[32:]) - } else { - copy(hash[:], ctx.h[:]) - } -} - -/* - Streebog implementation -*/ - -PI := [256]byte { - 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, - 233, 119, 240, 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, - 249, 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, 139, 1, 142, 79, - 5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, 211, 31, - 235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, - 181, 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, - 21, 161, 150, 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, 178, 177, - 50, 117, 25, 61, 255, 53, 138, 126, 109, 84, 198, 128, 195, 189, 13, 87, - 223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, 3, - 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, - 167, 151, 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, - 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165, 125, 105, 213, 149, 59, - 7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, - 225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, - 32, 113, 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, - 89, 166, 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182, -} - -TAU := [64]byte { - 0, 8, 16, 24, 32, 40, 48, 56, - 1, 9, 17, 25, 33, 41, 49, 57, - 2, 10, 18, 26, 34, 42, 50, 58, - 3, 11, 19, 27, 35, 43, 51, 59, - 4, 12, 20, 28, 36, 44, 52, 60, - 5, 13, 21, 29, 37, 45, 53, 61, - 6, 14, 22, 30, 38, 46, 54, 62, - 7, 15, 23, 31, 39, 47, 55, 63, -} - -STREEBOG_A := [64]u64 { - 0x8e20faa72ba0b470, 0x47107ddd9b505a38, 0xad08b0e0c3282d1c, 0xd8045870ef14980e, - 0x6c022c38f90a4c07, 0x3601161cf205268d, 0x1b8e0b0e798c13c8, 0x83478b07b2468764, - 0xa011d380818e8f40, 0x5086e740ce47c920, 0x2843fd2067adea10, 0x14aff010bdd87508, - 0x0ad97808d06cb404, 0x05e23c0468365a02, 0x8c711e02341b2d01, 0x46b60f011a83988e, - 0x90dab52a387ae76f, 0x486dd4151c3dfdb9, 0x24b86a840e90f0d2, 0x125c354207487869, - 0x092e94218d243cba, 0x8a174a9ec8121e5d, 0x4585254f64090fa0, 0xaccc9ca9328a8950, - 0x9d4df05d5f661451, 0xc0a878a0a1330aa6, 0x60543c50de970553, 0x302a1e286fc58ca7, - 0x18150f14b9ec46dd, 0x0c84890ad27623e0, 0x0642ca05693b9f70, 0x0321658cba93c138, - 0x86275df09ce8aaa8, 0x439da0784e745554, 0xafc0503c273aa42a, 0xd960281e9d1d5215, - 0xe230140fc0802984, 0x71180a8960409a42, 0xb60c05ca30204d21, 0x5b068c651810a89e, - 0x456c34887a3805b9, 0xac361a443d1c8cd2, 0x561b0d22900e4669, 0x2b838811480723ba, - 0x9bcf4486248d9f5d, 0xc3e9224312c8c1a0, 0xeffa11af0964ee50, 0xf97d86d98a327728, - 0xe4fa2054a80b329c, 0x727d102a548b194e, 0x39b008152acb8227, 0x9258048415eb419d, - 0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18, - 0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8, - 0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083, -} - -STREEBOG_C := [12][64]byte { - { - 0x07, 0x45, 0xa6, 0xf2, 0x59, 0x65, 0x80, 0xdd, - 0x23, 0x4d, 0x74, 0xcc, 0x36, 0x74, 0x76, 0x05, - 0x15, 0xd3, 0x60, 0xa4, 0x08, 0x2a, 0x42, 0xa2, - 0x01, 0x69, 0x67, 0x92, 0x91, 0xe0, 0x7c, 0x4b, - 0xfc, 0xc4, 0x85, 0x75, 0x8d, 0xb8, 0x4e, 0x71, - 0x16, 0xd0, 0x45, 0x2e, 0x43, 0x76, 0x6a, 0x2f, - 0x1f, 0x7c, 0x65, 0xc0, 0x81, 0x2f, 0xcb, 0xeb, - 0xe9, 0xda, 0xca, 0x1e, 0xda, 0x5b, 0x08, 0xb1, - }, - { - 0xb7, 0x9b, 0xb1, 0x21, 0x70, 0x04, 0x79, 0xe6, - 0x56, 0xcd, 0xcb, 0xd7, 0x1b, 0xa2, 0xdd, 0x55, - 0xca, 0xa7, 0x0a, 0xdb, 0xc2, 0x61, 0xb5, 0x5c, - 0x58, 0x99, 0xd6, 0x12, 0x6b, 0x17, 0xb5, 0x9a, - 0x31, 0x01, 0xb5, 0x16, 0x0f, 0x5e, 0xd5, 0x61, - 0x98, 0x2b, 0x23, 0x0a, 0x72, 0xea, 0xfe, 0xf3, - 0xd7, 0xb5, 0x70, 0x0f, 0x46, 0x9d, 0xe3, 0x4f, - 0x1a, 0x2f, 0x9d, 0xa9, 0x8a, 0xb5, 0xa3, 0x6f, - }, - { - 0xb2, 0x0a, 0xba, 0x0a, 0xf5, 0x96, 0x1e, 0x99, - 0x31, 0xdb, 0x7a, 0x86, 0x43, 0xf4, 0xb6, 0xc2, - 0x09, 0xdb, 0x62, 0x60, 0x37, 0x3a, 0xc9, 0xc1, - 0xb1, 0x9e, 0x35, 0x90, 0xe4, 0x0f, 0xe2, 0xd3, - 0x7b, 0x7b, 0x29, 0xb1, 0x14, 0x75, 0xea, 0xf2, - 0x8b, 0x1f, 0x9c, 0x52, 0x5f, 0x5e, 0xf1, 0x06, - 0x35, 0x84, 0x3d, 0x6a, 0x28, 0xfc, 0x39, 0x0a, - 0xc7, 0x2f, 0xce, 0x2b, 0xac, 0xdc, 0x74, 0xf5, - }, - { - 0x2e, 0xd1, 0xe3, 0x84, 0xbc, 0xbe, 0x0c, 0x22, - 0xf1, 0x37, 0xe8, 0x93, 0xa1, 0xea, 0x53, 0x34, - 0xbe, 0x03, 0x52, 0x93, 0x33, 0x13, 0xb7, 0xd8, - 0x75, 0xd6, 0x03, 0xed, 0x82, 0x2c, 0xd7, 0xa9, - 0x3f, 0x35, 0x5e, 0x68, 0xad, 0x1c, 0x72, 0x9d, - 0x7d, 0x3c, 0x5c, 0x33, 0x7e, 0x85, 0x8e, 0x48, - 0xdd, 0xe4, 0x71, 0x5d, 0xa0, 0xe1, 0x48, 0xf9, - 0xd2, 0x66, 0x15, 0xe8, 0xb3, 0xdf, 0x1f, 0xef, - }, - { - 0x57, 0xfe, 0x6c, 0x7c, 0xfd, 0x58, 0x17, 0x60, - 0xf5, 0x63, 0xea, 0xa9, 0x7e, 0xa2, 0x56, 0x7a, - 0x16, 0x1a, 0x27, 0x23, 0xb7, 0x00, 0xff, 0xdf, - 0xa3, 0xf5, 0x3a, 0x25, 0x47, 0x17, 0xcd, 0xbf, - 0xbd, 0xff, 0x0f, 0x80, 0xd7, 0x35, 0x9e, 0x35, - 0x4a, 0x10, 0x86, 0x16, 0x1f, 0x1c, 0x15, 0x7f, - 0x63, 0x23, 0xa9, 0x6c, 0x0c, 0x41, 0x3f, 0x9a, - 0x99, 0x47, 0x47, 0xad, 0xac, 0x6b, 0xea, 0x4b, - }, - { - 0x6e, 0x7d, 0x64, 0x46, 0x7a, 0x40, 0x68, 0xfa, - 0x35, 0x4f, 0x90, 0x36, 0x72, 0xc5, 0x71, 0xbf, - 0xb6, 0xc6, 0xbe, 0xc2, 0x66, 0x1f, 0xf2, 0x0a, - 0xb4, 0xb7, 0x9a, 0x1c, 0xb7, 0xa6, 0xfa, 0xcf, - 0xc6, 0x8e, 0xf0, 0x9a, 0xb4, 0x9a, 0x7f, 0x18, - 0x6c, 0xa4, 0x42, 0x51, 0xf9, 0xc4, 0x66, 0x2d, - 0xc0, 0x39, 0x30, 0x7a, 0x3b, 0xc3, 0xa4, 0x6f, - 0xd9, 0xd3, 0x3a, 0x1d, 0xae, 0xae, 0x4f, 0xae, - }, - { - 0x93, 0xd4, 0x14, 0x3a, 0x4d, 0x56, 0x86, 0x88, - 0xf3, 0x4a, 0x3c, 0xa2, 0x4c, 0x45, 0x17, 0x35, - 0x04, 0x05, 0x4a, 0x28, 0x83, 0x69, 0x47, 0x06, - 0x37, 0x2c, 0x82, 0x2d, 0xc5, 0xab, 0x92, 0x09, - 0xc9, 0x93, 0x7a, 0x19, 0x33, 0x3e, 0x47, 0xd3, - 0xc9, 0x87, 0xbf, 0xe6, 0xc7, 0xc6, 0x9e, 0x39, - 0x54, 0x09, 0x24, 0xbf, 0xfe, 0x86, 0xac, 0x51, - 0xec, 0xc5, 0xaa, 0xee, 0x16, 0x0e, 0xc7, 0xf4, - }, - { - 0x1e, 0xe7, 0x02, 0xbf, 0xd4, 0x0d, 0x7f, 0xa4, - 0xd9, 0xa8, 0x51, 0x59, 0x35, 0xc2, 0xac, 0x36, - 0x2f, 0xc4, 0xa5, 0xd1, 0x2b, 0x8d, 0xd1, 0x69, - 0x90, 0x06, 0x9b, 0x92, 0xcb, 0x2b, 0x89, 0xf4, - 0x9a, 0xc4, 0xdb, 0x4d, 0x3b, 0x44, 0xb4, 0x89, - 0x1e, 0xde, 0x36, 0x9c, 0x71, 0xf8, 0xb7, 0x4e, - 0x41, 0x41, 0x6e, 0x0c, 0x02, 0xaa, 0xe7, 0x03, - 0xa7, 0xc9, 0x93, 0x4d, 0x42, 0x5b, 0x1f, 0x9b, - }, - { - 0xdb, 0x5a, 0x23, 0x83, 0x51, 0x44, 0x61, 0x72, - 0x60, 0x2a, 0x1f, 0xcb, 0x92, 0xdc, 0x38, 0x0e, - 0x54, 0x9c, 0x07, 0xa6, 0x9a, 0x8a, 0x2b, 0x7b, - 0xb1, 0xce, 0xb2, 0xdb, 0x0b, 0x44, 0x0a, 0x80, - 0x84, 0x09, 0x0d, 0xe0, 0xb7, 0x55, 0xd9, 0x3c, - 0x24, 0x42, 0x89, 0x25, 0x1b, 0x3a, 0x7d, 0x3a, - 0xde, 0x5f, 0x16, 0xec, 0xd8, 0x9a, 0x4c, 0x94, - 0x9b, 0x22, 0x31, 0x16, 0x54, 0x5a, 0x8f, 0x37, - }, - { - 0xed, 0x9c, 0x45, 0x98, 0xfb, 0xc7, 0xb4, 0x74, - 0xc3, 0xb6, 0x3b, 0x15, 0xd1, 0xfa, 0x98, 0x36, - 0xf4, 0x52, 0x76, 0x3b, 0x30, 0x6c, 0x1e, 0x7a, - 0x4b, 0x33, 0x69, 0xaf, 0x02, 0x67, 0xe7, 0x9f, - 0x03, 0x61, 0x33, 0x1b, 0x8a, 0xe1, 0xff, 0x1f, - 0xdb, 0x78, 0x8a, 0xff, 0x1c, 0xe7, 0x41, 0x89, - 0xf3, 0xf3, 0xe4, 0xb2, 0x48, 0xe5, 0x2a, 0x38, - 0x52, 0x6f, 0x05, 0x80, 0xa6, 0xde, 0xbe, 0xab, - }, - { - 0x1b, 0x2d, 0xf3, 0x81, 0xcd, 0xa4, 0xca, 0x6b, - 0x5d, 0xd8, 0x6f, 0xc0, 0x4a, 0x59, 0xa2, 0xde, - 0x98, 0x6e, 0x47, 0x7d, 0x1d, 0xcd, 0xba, 0xef, - 0xca, 0xb9, 0x48, 0xea, 0xef, 0x71, 0x1d, 0x8a, - 0x79, 0x66, 0x84, 0x14, 0x21, 0x80, 0x01, 0x20, - 0x61, 0x07, 0xab, 0xeb, 0xbb, 0x6b, 0xfa, 0xd8, - 0x94, 0xfe, 0x5a, 0x63, 0xcd, 0xc6, 0x02, 0x30, - 0xfb, 0x89, 0xc8, 0xef, 0xd0, 0x9e, 0xcd, 0x7b, - }, - { - 0x20, 0xd7, 0x1b, 0xf1, 0x4a, 0x92, 0xbc, 0x48, - 0x99, 0x1b, 0xb2, 0xd9, 0xd5, 0x17, 0xf4, 0xfa, - 0x52, 0x28, 0xe1, 0x88, 0xaa, 0xa4, 0x1d, 0xe7, - 0x86, 0xcc, 0x91, 0x18, 0x9d, 0xef, 0x80, 0x5d, - 0x9b, 0x9f, 0x21, 0x30, 0xd4, 0x12, 0x20, 0xf8, - 0x77, 0x1d, 0xdf, 0xbc, 0x32, 0x3c, 0xa4, 0xcd, - 0x7a, 0xb1, 0x49, 0x04, 0xb0, 0x80, 0x13, 0xd2, - 0xba, 0x31, 0x16, 0xf1, 0x67, 0xe7, 0x8e, 0x37, - }, -} - -Streebog_Context :: struct { - buffer: [64]byte, - h: [64]byte, - n: [64]byte, - sigma: [64]byte, - v_0: [64]byte, - v_512: [64]byte, - buf_size: u64, - hash_size: int, - is256: bool, -} - -add_mod_512 :: proc(first_vector, second_vector, result_vector: []byte) { - t: i32 = 0 - for i: i32 = 0; i < 64; i += 1 { - t = i32(first_vector[i]) + i32(second_vector[i]) + (t >> 8) - result_vector[i] = byte(t & 0xff) - } -} - -X :: #force_inline proc(a, k, out: []byte) { - for i := 0; i < 64; i += 1 { - out[i] = a[i] ~ k[i] - } -} - -S :: #force_inline proc(state: []byte) { - t: [64]byte - for i: i32 = 63; i >= 0; i -= 1 { - t[i] = PI[state[i]] - } - copy(state, t[:]) -} - -P :: #force_inline proc(state: []byte) { - t: [64]byte - for i: i32 = 63; i >= 0; i -= 1 { - t[i] = state[TAU[i]] - } - copy(state, t[:]) -} - -L :: #force_inline proc(state: []byte) { - ins := util.cast_slice([]u64, state) - out: [8]u64 - for i: i32 = 7; i >= 0; i -= 1 { - for j: i32 = 63; j >= 0; j -= 1 { - if (ins[i] >> u32(j)) & 1 != 0 { - out[i] ~= STREEBOG_A[63 - j] - } - } - } - copy(state, util.cast_slice([]byte, out[:])) -} - -E :: #force_inline proc(K, m, state: []byte) { - X(m, K, state) - for i: i32 = 0; i < 12; i += 1 { - S(state) - P(state) - L(state) - get_key(K, i) - X(state, K, state) - } -} - -get_key :: #force_inline proc(K: []byte, i: i32) { - X(K, STREEBOG_C[i][:], K) - S(K) - P(K) - L(K) -} - -G :: #force_inline proc(h, N, m: []byte) { - t, K: [64]byte - X(N, h, K[:]) - S(K[:]) - P(K[:]) - L(K[:]) - E(K[:], m, t[:]) - X(t[:], h, t[:]) - X(t[:], m, h) -} - -stage2 :: proc(ctx: ^Streebog_Context, m: []byte) { - G(ctx.h[:], ctx.n[:], m) - add_mod_512(ctx.n[:], ctx.v_512[:], ctx.n[:]) - add_mod_512(ctx.sigma[:], m, ctx.sigma[:]) -} - -padding :: proc(ctx: ^Streebog_Context) { - if ctx.buf_size < 64 { - t: [64]byte - copy(t[:], ctx.buffer[:int(ctx.buf_size)]) - t[ctx.buf_size] = 0x01 - copy(ctx.buffer[:], t[:]) - } -} diff --git a/core/crypto/tiger/tiger.odin b/core/crypto/tiger/tiger.odin deleted file mode 100644 index 614926129..000000000 --- a/core/crypto/tiger/tiger.odin +++ /dev/null @@ -1,280 +0,0 @@ -package tiger - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Interface for the Tiger1 variant of the Tiger hashing algorithm as defined in -*/ - -import "core:os" -import "core:io" - -import "../_tiger" - -/* - High level API -*/ - -DIGEST_SIZE_128 :: 16 -DIGEST_SIZE_160 :: 20 -DIGEST_SIZE_192 :: 24 - -// hash_string_128 will hash the given input and return the -// computed hash -hash_string_128 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128(transmute([]byte)(data)) -} - -// hash_bytes_128 will hash the given input and return the -// computed hash -hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_128 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128 will read the file provided by the given handle -// and compute a hash -hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128 :: proc { - hash_stream_128, - hash_file_128, - hash_bytes_128, - hash_string_128, - hash_bytes_to_buffer_128, - hash_string_to_buffer_128, -} - -// hash_string_160 will hash the given input and return the -// computed hash -hash_string_160 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160(transmute([]byte)(data)) -} - -// hash_bytes_160 will hash the given input and return the -// computed hash -hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_160 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160 will read the file provided by the given handle -// and compute a hash -hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160 :: proc { - hash_stream_160, - hash_file_160, - hash_bytes_160, - hash_string_160, - hash_bytes_to_buffer_160, - hash_string_to_buffer_160, -} - -// hash_string_192 will hash the given input and return the -// computed hash -hash_string_192 :: proc(data: string) -> [DIGEST_SIZE_192]byte { - return hash_bytes_192(transmute([]byte)(data)) -} - -// hash_bytes_192 will hash the given input and return the -// computed hash -hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { - hash: [DIGEST_SIZE_192]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_192 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_192 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_192 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_192 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_192, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_192 will read the stream in chunks and compute a -// hash from its contents -hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) { - hash: [DIGEST_SIZE_192]byte - ctx: _tiger.Tiger_Context - ctx.ver = 1 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_192 will read the file provided by the given handle -// and compute a hash -hash_file_192 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_192]byte, bool) { - if !load_at_once { - return hash_stream_192(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_192(buf[:]), ok - } - } - return [DIGEST_SIZE_192]byte{}, false -} - -hash_192 :: proc { - hash_stream_192, - hash_file_192, - hash_bytes_192, - hash_string_192, - hash_bytes_to_buffer_192, - hash_string_to_buffer_192, -} - -/* - Low level API -*/ - -Tiger_Context :: _tiger.Tiger_Context - -init :: proc(ctx: ^_tiger.Tiger_Context) { - ctx.ver = 1 - _tiger.init(ctx) -} - -update :: proc(ctx: ^_tiger.Tiger_Context, data: []byte) { - _tiger.update(ctx, data) -} - -final :: proc(ctx: ^_tiger.Tiger_Context, hash: []byte) { - _tiger.final(ctx, hash) -} \ No newline at end of file diff --git a/core/crypto/tiger2/tiger2.odin b/core/crypto/tiger2/tiger2.odin deleted file mode 100644 index ead874d56..000000000 --- a/core/crypto/tiger2/tiger2.odin +++ /dev/null @@ -1,280 +0,0 @@ -package tiger2 - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Interface for the Tiger2 variant of the Tiger hashing algorithm as defined in -*/ - -import "core:os" -import "core:io" - -import "../_tiger" - -/* - High level API -*/ - -DIGEST_SIZE_128 :: 16 -DIGEST_SIZE_160 :: 20 -DIGEST_SIZE_192 :: 24 - -// hash_string_128 will hash the given input and return the -// computed hash -hash_string_128 :: proc(data: string) -> [DIGEST_SIZE_128]byte { - return hash_bytes_128(transmute([]byte)(data)) -} - -// hash_bytes_128 will hash the given input and return the -// computed hash -hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte { - hash: [DIGEST_SIZE_128]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_128 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_128 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_128(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_128 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_128 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_128, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_128 will read the stream in chunks and compute a -// hash from its contents -hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) { - hash: [DIGEST_SIZE_128]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_128 will read the file provided by the given handle -// and compute a hash -hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_128]byte, bool) { - if !load_at_once { - return hash_stream_128(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_128(buf[:]), ok - } - } - return [DIGEST_SIZE_128]byte{}, false -} - -hash_128 :: proc { - hash_stream_128, - hash_file_128, - hash_bytes_128, - hash_string_128, - hash_bytes_to_buffer_128, - hash_string_to_buffer_128, -} - -// hash_string_160 will hash the given input and return the -// computed hash -hash_string_160 :: proc(data: string) -> [DIGEST_SIZE_160]byte { - return hash_bytes_160(transmute([]byte)(data)) -} - -// hash_bytes_160 will hash the given input and return the -// computed hash -hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte { - hash: [DIGEST_SIZE_160]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_160 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_160 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_160(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_160 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_160 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_160, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_160 will read the stream in chunks and compute a -// hash from its contents -hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) { - hash: [DIGEST_SIZE_160]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_160 will read the file provided by the given handle -// and compute a hash -hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_160]byte, bool) { - if !load_at_once { - return hash_stream_160(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_160(buf[:]), ok - } - } - return [DIGEST_SIZE_160]byte{}, false -} - -hash_160 :: proc { - hash_stream_160, - hash_file_160, - hash_bytes_160, - hash_string_160, - hash_bytes_to_buffer_160, - hash_string_to_buffer_160, -} - -// hash_string_192 will hash the given input and return the -// computed hash -hash_string_192 :: proc(data: string) -> [DIGEST_SIZE_192]byte { - return hash_bytes_192(transmute([]byte)(data)) -} - -// hash_bytes_192 will hash the given input and return the -// computed hash -hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte { - hash: [DIGEST_SIZE_192]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer_192 will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer_192 :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer_192(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer_192 will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer_192 :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE_192, "Size of destination buffer is smaller than the digest size") - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - _tiger.update(&ctx, data) - _tiger.final(&ctx, hash) -} - -// hash_stream_192 will read the stream in chunks and compute a -// hash from its contents -hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) { - hash: [DIGEST_SIZE_192]byte - ctx: _tiger.Tiger_Context - ctx.ver = 2 - _tiger.init(&ctx) - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - _tiger.update(&ctx, buf[:read]) - } - } - _tiger.final(&ctx, hash[:]) - return hash, true -} - -// hash_file_192 will read the file provided by the given handle -// and compute a hash -hash_file_192 :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE_192]byte, bool) { - if !load_at_once { - return hash_stream_192(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes_192(buf[:]), ok - } - } - return [DIGEST_SIZE_192]byte{}, false -} - -hash_192 :: proc { - hash_stream_192, - hash_file_192, - hash_bytes_192, - hash_string_192, - hash_bytes_to_buffer_192, - hash_string_to_buffer_192, -} - -/* - Low level API -*/ - -Tiger_Context :: _tiger.Tiger_Context - -init :: proc(ctx: ^_tiger.Tiger_Context) { - ctx.ver = 2 - _tiger.init(ctx) -} - -update :: proc(ctx: ^_tiger.Tiger_Context, data: []byte) { - _tiger.update(ctx, data) -} - -final :: proc(ctx: ^_tiger.Tiger_Context, hash: []byte) { - _tiger.final(ctx, hash) -} \ No newline at end of file diff --git a/core/crypto/util/util.odin b/core/crypto/util/util.odin deleted file mode 100644 index b9b80124a..000000000 --- a/core/crypto/util/util.odin +++ /dev/null @@ -1,146 +0,0 @@ -package util - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Various utility procedures -*/ - -import "core:mem" -// Keep vet happy -_ :: mem - -// @note(bp): this can replace the other two -cast_slice :: #force_inline proc "contextless" ($D: typeid/[]$DE, src: $S/[]$SE) -> D { - src := src - dst := (^mem.Raw_Slice)(&src) - - when size_of(DE) < size_of(SE) { - when size_of(DE) % size_of(SE) == 0 { - dst.len /= size_of(SE) / size_of(DE) - } else { - dst.len *= size_of(SE) - dst.len /= size_of(DE) - } - } else when size_of(DE) > size_of(SE) { - when size_of(DE) % size_of(SE) == 0 { - dst.len *= size_of(DE) / size_of(SE) - } else { - dst.len *= size_of(SE) - dst.len /= size_of(DE) - } - } else when size_of(DE) != size_of(SE) { - #assert(size_of(DE) % size_of(SE) == 0, "Different size detected") - dst.len *= size_of(SE) - dst.len /= size_of(DE) - } - - return (^D)(dst)^ -} - -bytes_to_slice :: #force_inline proc "contextless" ($T: typeid/[]$E, bytes: []byte) -> T { - s := transmute(mem.Raw_Slice)bytes - s.len /= size_of(E) - return transmute(T)s -} - -slice_to_bytes :: #force_inline proc "contextless" (slice: $E/[]$T) -> []byte { - s := transmute(mem.Raw_Slice)slice - s.len *= size_of(T) - return transmute([]byte)s -} - -ROTL16 :: #force_inline proc "contextless" (a, b: u16) -> u16 { - return ((a << b) | (a >> (16 - b))) -} - -ROTR16 :: #force_inline proc "contextless" (a, b: u16) -> u16 { - return ((a >> b) | (a << (16 - b))) -} - -ROTL32 :: #force_inline proc "contextless"(a: u32, b: int) -> u32 { - s := uint(b) & 31 - return (a << s) | (a >> (32 - s)) -} - -ROTR32 :: #force_inline proc "contextless" (a: u32, b: int) -> u32 { - s := uint(b) & 31 - return (a >> s) | (a << (32 - s)) -} - -ROTL64 :: #force_inline proc "contextless" (a, b: u64) -> u64 { - return ((a << b) | (a >> (64 - b))) -} - -ROTR64 :: #force_inline proc "contextless" (a, b: u64) -> u64 { - return ((a >> b) | (a << (64 - b))) -} - -ROTL128 :: #force_inline proc "contextless" (a, b, c, d: ^u32, n: uint) { - a, b, c, d := a, b, c, d - t := a^ >> (32 - n) - a^ = ((a^ << n) | (b^ >> (32 - n))) - b^ = ((b^ << n) | (c^ >> (32 - n))) - c^ = ((c^ << n) | (d^ >> (32 - n))) - d^ = ((d^ << n) | t) -} - -U32_LE :: #force_inline proc "contextless" (b: []byte) -> u32 { - return u32(b[0]) | u32(b[1]) << 8 | u32(b[2]) << 16 | u32(b[3]) << 24 -} - -U64_LE :: #force_inline proc "contextless" (b: []byte) -> u64 { - return u64(b[0]) | u64(b[1]) << 8 | u64(b[2]) << 16 | u64(b[3]) << 24 | - u64(b[4]) << 32 | u64(b[5]) << 40 | u64(b[6]) << 48 | u64(b[7]) << 56 -} - -U64_BE :: #force_inline proc "contextless" (b: []byte) -> u64 { - return u64(b[7]) | u64(b[6]) << 8 | u64(b[5]) << 16 | u64(b[4]) << 24 | - u64(b[3]) << 32 | u64(b[2]) << 40 | u64(b[1]) << 48 | u64(b[0]) << 56 -} - -PUT_U64_LE :: #force_inline proc "contextless" (b: []byte, v: u64) { - b[0] = byte(v) - b[1] = byte(v >> 8) - b[2] = byte(v >> 16) - b[3] = byte(v >> 24) - b[4] = byte(v >> 32) - b[5] = byte(v >> 40) - b[6] = byte(v >> 48) - b[7] = byte(v >> 56) -} - -PUT_U32_LE :: #force_inline proc "contextless" (b: []byte, v: u32) { - b[0] = byte(v) - b[1] = byte(v >> 8) - b[2] = byte(v >> 16) - b[3] = byte(v >> 24) -} - -PUT_U32_BE :: #force_inline proc "contextless" (b: []byte, v: u32) { - b[0] = byte(v >> 24) - b[1] = byte(v >> 16) - b[2] = byte(v >> 8) - b[3] = byte(v) -} - -PUT_U64_BE :: #force_inline proc "contextless" (b: []byte, v: u64) { - b[0] = byte(v >> 56) - b[1] = byte(v >> 48) - b[2] = byte(v >> 40) - b[3] = byte(v >> 32) - b[4] = byte(v >> 24) - b[5] = byte(v >> 16) - b[6] = byte(v >> 8) - b[7] = byte(v) -} - -XOR_BUF :: #force_inline proc "contextless" (input, output: []byte) { - for i := 0; i < len(input); i += 1 { - output[i] ~= input[i] - } -} diff --git a/core/crypto/whirlpool/whirlpool.odin b/core/crypto/whirlpool/whirlpool.odin deleted file mode 100644 index cf0bf6490..000000000 --- a/core/crypto/whirlpool/whirlpool.odin +++ /dev/null @@ -1,806 +0,0 @@ -package whirlpool - -/* - Copyright 2021 zhibog - Made available under the BSD-3 license. - - List of contributors: - zhibog, dotbmp: Initial implementation. - - Implementation of the Whirlpool hashing algorithm, as defined in -*/ - -import "core:os" -import "core:io" - -import "../util" - -/* - High level API -*/ - -DIGEST_SIZE :: 64 - -// hash_string will hash the given input and return the -// computed hash -hash_string :: proc(data: string) -> [DIGEST_SIZE]byte { - return hash_bytes(transmute([]byte)(data)) -} - -// hash_bytes will hash the given input and return the -// computed hash -hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte { - hash: [DIGEST_SIZE]byte - ctx: Whirlpool_Context - // init(&ctx) No-op - update(&ctx, data) - final(&ctx, hash[:]) - return hash -} - -// hash_string_to_buffer will hash the given input and assign the -// computed hash to the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_string_to_buffer :: proc(data: string, hash: []byte) { - hash_bytes_to_buffer(transmute([]byte)(data), hash) -} - -// hash_bytes_to_buffer will hash the given input and write the -// computed hash into the second parameter. -// It requires that the destination buffer is at least as big as the digest size -hash_bytes_to_buffer :: proc(data, hash: []byte) { - assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size") - ctx: Whirlpool_Context - // init(&ctx) No-op - update(&ctx, data) - final(&ctx, hash) -} - -// hash_stream will read the stream in chunks and compute a -// hash from its contents -hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) { - hash: [DIGEST_SIZE]byte - ctx: Whirlpool_Context - // init(&ctx) No-op - buf := make([]byte, 512) - defer delete(buf) - read := 1 - for read > 0 { - read, _ = io.read(s, buf) - if read > 0 { - update(&ctx, buf[:read]) - } - } - final(&ctx, hash[:]) - return hash, true -} - -// hash_file will read the file provided by the given handle -// and compute a hash -hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) { - if !load_at_once { - return hash_stream(os.stream_from_handle(hd)) - } else { - if buf, ok := os.read_entire_file(hd); ok { - return hash_bytes(buf[:]), ok - } - } - return [DIGEST_SIZE]byte{}, false -} - -hash :: proc { - hash_stream, - hash_file, - hash_bytes, - hash_string, - hash_bytes_to_buffer, - hash_string_to_buffer, -} - -/* - Low level API -*/ - -@(warning="Init is a no-op for Whirlpool") -init :: proc(ctx: ^Whirlpool_Context) { - // No action needed here -} - -update :: proc(ctx: ^Whirlpool_Context, source: []byte) { - source_pos: int - nn := len(source) - source_bits := u64(nn * 8) - source_gap := u32((8 - (int(source_bits & 7))) & 7) - buffer_rem := uint(ctx.buffer_bits & 7) - b: u32 - - for i, carry, value := 31, u32(0), u32(source_bits); i >= 0 && (carry != 0 || value != 0); i -= 1 { - carry += u32(ctx.bitlength[i]) + (u32(value & 0xff)) - ctx.bitlength[i] = byte(carry) - carry >>= 8 - value >>= 8 - } - - for source_bits > 8 { - b = u32(u32((source[source_pos] << source_gap) & 0xff) | u32((source[source_pos+1] & 0xff) >> (8 - source_gap))) - - ctx.buffer[ctx.buffer_pos] |= u8(b >> buffer_rem) - ctx.buffer_pos += 1 - ctx.buffer_bits += int(8 - buffer_rem) - - if ctx.buffer_bits == 512 { - transform(ctx) - ctx.buffer_bits = 0 - ctx.buffer_pos = 0 - } - ctx.buffer[ctx.buffer_pos] = byte(b << (8 - buffer_rem)) - ctx.buffer_bits += int(buffer_rem) - source_bits -= 8 - source_pos += 1 - } - - if source_bits > 0 { - b = u32((source[source_pos] << source_gap) & 0xff) - ctx.buffer[ctx.buffer_pos] |= byte(b) >> buffer_rem - } else {b = 0} - - if u64(buffer_rem) + source_bits < 8 { - ctx.buffer_bits += int(source_bits) - } else { - ctx.buffer_pos += 1 - ctx.buffer_bits += 8 - int(buffer_rem) - source_bits -= u64(8 - buffer_rem) - - if ctx.buffer_bits == 512 { - transform(ctx) - ctx.buffer_bits = 0 - ctx.buffer_pos = 0 - } - ctx.buffer[ctx.buffer_pos] = byte(b << (8 - buffer_rem)) - ctx.buffer_bits += int(source_bits) - } -} - -final :: proc(ctx: ^Whirlpool_Context, hash: []byte) { - n := ctx - n.buffer[n.buffer_pos] |= 0x80 >> (uint(n.buffer_bits) & 7) - n.buffer_pos += 1 - - if n.buffer_pos > 64 - 32 { - if n.buffer_pos < 64 { - for i := 0; i < 64 - n.buffer_pos; i += 1 { - n.buffer[n.buffer_pos + i] = 0 - } - } - transform(ctx) - n.buffer_pos = 0 - } - - if n.buffer_pos < 64 - 32 { - for i := 0; i < (64 - 32) - n.buffer_pos; i += 1 { - n.buffer[n.buffer_pos + i] = 0 - } - } - n.buffer_pos = 64 - 32 - - for i := 0; i < 32; i += 1 { - n.buffer[n.buffer_pos + i] = n.bitlength[i] - } - transform(ctx) - - for i := 0; i < 8; i += 1 { - hash[i * 8] = byte(n.hash[i] >> 56) - hash[i * 8 + 1] = byte(n.hash[i] >> 48) - hash[i * 8 + 2] = byte(n.hash[i] >> 40) - hash[i * 8 + 3] = byte(n.hash[i] >> 32) - hash[i * 8 + 4] = byte(n.hash[i] >> 24) - hash[i * 8 + 5] = byte(n.hash[i] >> 16) - hash[i * 8 + 6] = byte(n.hash[i] >> 8) - hash[i * 8 + 7] = byte(n.hash[i]) - } -} - -/* - Whirlpool implementation -*/ - -ROUNDS :: 10 - -Whirlpool_Context :: struct { - bitlength: [32]byte, - buffer: [64]byte, - buffer_bits: int, - buffer_pos: int, - hash: [8]u64, -} - -C0 := [256]u64 { - 0x18186018c07830d8, 0x23238c2305af4626, 0xc6c63fc67ef991b8, 0xe8e887e8136fcdfb, - 0x878726874ca113cb, 0xb8b8dab8a9626d11, 0x0101040108050209, 0x4f4f214f426e9e0d, - 0x3636d836adee6c9b, 0xa6a6a2a6590451ff, 0xd2d26fd2debdb90c, 0xf5f5f3f5fb06f70e, - 0x7979f979ef80f296, 0x6f6fa16f5fcede30, 0x91917e91fcef3f6d, 0x52525552aa07a4f8, - 0x60609d6027fdc047, 0xbcbccabc89766535, 0x9b9b569baccd2b37, 0x8e8e028e048c018a, - 0xa3a3b6a371155bd2, 0x0c0c300c603c186c, 0x7b7bf17bff8af684, 0x3535d435b5e16a80, - 0x1d1d741de8693af5, 0xe0e0a7e05347ddb3, 0xd7d77bd7f6acb321, 0xc2c22fc25eed999c, - 0x2e2eb82e6d965c43, 0x4b4b314b627a9629, 0xfefedffea321e15d, 0x575741578216aed5, - 0x15155415a8412abd, 0x7777c1779fb6eee8, 0x3737dc37a5eb6e92, 0xe5e5b3e57b56d79e, - 0x9f9f469f8cd92313, 0xf0f0e7f0d317fd23, 0x4a4a354a6a7f9420, 0xdada4fda9e95a944, - 0x58587d58fa25b0a2, 0xc9c903c906ca8fcf, 0x2929a429558d527c, 0x0a0a280a5022145a, - 0xb1b1feb1e14f7f50, 0xa0a0baa0691a5dc9, 0x6b6bb16b7fdad614, 0x85852e855cab17d9, - 0xbdbdcebd8173673c, 0x5d5d695dd234ba8f, 0x1010401080502090, 0xf4f4f7f4f303f507, - 0xcbcb0bcb16c08bdd, 0x3e3ef83eedc67cd3, 0x0505140528110a2d, 0x676781671fe6ce78, - 0xe4e4b7e47353d597, 0x27279c2725bb4e02, 0x4141194132588273, 0x8b8b168b2c9d0ba7, - 0xa7a7a6a7510153f6, 0x7d7de97dcf94fab2, 0x95956e95dcfb3749, 0xd8d847d88e9fad56, - 0xfbfbcbfb8b30eb70, 0xeeee9fee2371c1cd, 0x7c7ced7cc791f8bb, 0x6666856617e3cc71, - 0xdddd53dda68ea77b, 0x17175c17b84b2eaf, 0x4747014702468e45, 0x9e9e429e84dc211a, - 0xcaca0fca1ec589d4, 0x2d2db42d75995a58, 0xbfbfc6bf9179632e, 0x07071c07381b0e3f, - 0xadad8ead012347ac, 0x5a5a755aea2fb4b0, 0x838336836cb51bef, 0x3333cc3385ff66b6, - 0x636391633ff2c65c, 0x02020802100a0412, 0xaaaa92aa39384993, 0x7171d971afa8e2de, - 0xc8c807c80ecf8dc6, 0x19196419c87d32d1, 0x494939497270923b, 0xd9d943d9869aaf5f, - 0xf2f2eff2c31df931, 0xe3e3abe34b48dba8, 0x5b5b715be22ab6b9, 0x88881a8834920dbc, - 0x9a9a529aa4c8293e, 0x262698262dbe4c0b, 0x3232c8328dfa64bf, 0xb0b0fab0e94a7d59, - 0xe9e983e91b6acff2, 0x0f0f3c0f78331e77, 0xd5d573d5e6a6b733, 0x80803a8074ba1df4, - 0xbebec2be997c6127, 0xcdcd13cd26de87eb, 0x3434d034bde46889, 0x48483d487a759032, - 0xffffdbffab24e354, 0x7a7af57af78ff48d, 0x90907a90f4ea3d64, 0x5f5f615fc23ebe9d, - 0x202080201da0403d, 0x6868bd6867d5d00f, 0x1a1a681ad07234ca, 0xaeae82ae192c41b7, - 0xb4b4eab4c95e757d, 0x54544d549a19a8ce, 0x93937693ece53b7f, 0x222288220daa442f, - 0x64648d6407e9c863, 0xf1f1e3f1db12ff2a, 0x7373d173bfa2e6cc, 0x12124812905a2482, - 0x40401d403a5d807a, 0x0808200840281048, 0xc3c32bc356e89b95, 0xecec97ec337bc5df, - 0xdbdb4bdb9690ab4d, 0xa1a1bea1611f5fc0, 0x8d8d0e8d1c830791, 0x3d3df43df5c97ac8, - 0x97976697ccf1335b, 0x0000000000000000, 0xcfcf1bcf36d483f9, 0x2b2bac2b4587566e, - 0x7676c57697b3ece1, 0x8282328264b019e6, 0xd6d67fd6fea9b128, 0x1b1b6c1bd87736c3, - 0xb5b5eeb5c15b7774, 0xafaf86af112943be, 0x6a6ab56a77dfd41d, 0x50505d50ba0da0ea, - 0x45450945124c8a57, 0xf3f3ebf3cb18fb38, 0x3030c0309df060ad, 0xefef9bef2b74c3c4, - 0x3f3ffc3fe5c37eda, 0x55554955921caac7, 0xa2a2b2a2791059db, 0xeaea8fea0365c9e9, - 0x656589650fecca6a, 0xbabad2bab9686903, 0x2f2fbc2f65935e4a, 0xc0c027c04ee79d8e, - 0xdede5fdebe81a160, 0x1c1c701ce06c38fc, 0xfdfdd3fdbb2ee746, 0x4d4d294d52649a1f, - 0x92927292e4e03976, 0x7575c9758fbceafa, 0x06061806301e0c36, 0x8a8a128a249809ae, - 0xb2b2f2b2f940794b, 0xe6e6bfe66359d185, 0x0e0e380e70361c7e, 0x1f1f7c1ff8633ee7, - 0x6262956237f7c455, 0xd4d477d4eea3b53a, 0xa8a89aa829324d81, 0x96966296c4f43152, - 0xf9f9c3f99b3aef62, 0xc5c533c566f697a3, 0x2525942535b14a10, 0x59597959f220b2ab, - 0x84842a8454ae15d0, 0x7272d572b7a7e4c5, 0x3939e439d5dd72ec, 0x4c4c2d4c5a619816, - 0x5e5e655eca3bbc94, 0x7878fd78e785f09f, 0x3838e038ddd870e5, 0x8c8c0a8c14860598, - 0xd1d163d1c6b2bf17, 0xa5a5aea5410b57e4, 0xe2e2afe2434dd9a1, 0x616199612ff8c24e, - 0xb3b3f6b3f1457b42, 0x2121842115a54234, 0x9c9c4a9c94d62508, 0x1e1e781ef0663cee, - 0x4343114322528661, 0xc7c73bc776fc93b1, 0xfcfcd7fcb32be54f, 0x0404100420140824, - 0x51515951b208a2e3, 0x99995e99bcc72f25, 0x6d6da96d4fc4da22, 0x0d0d340d68391a65, - 0xfafacffa8335e979, 0xdfdf5bdfb684a369, 0x7e7ee57ed79bfca9, 0x242490243db44819, - 0x3b3bec3bc5d776fe, 0xabab96ab313d4b9a, 0xcece1fce3ed181f0, 0x1111441188552299, - 0x8f8f068f0c890383, 0x4e4e254e4a6b9c04, 0xb7b7e6b7d1517366, 0xebeb8beb0b60cbe0, - 0x3c3cf03cfdcc78c1, 0x81813e817cbf1ffd, 0x94946a94d4fe3540, 0xf7f7fbf7eb0cf31c, - 0xb9b9deb9a1676f18, 0x13134c13985f268b, 0x2c2cb02c7d9c5851, 0xd3d36bd3d6b8bb05, - 0xe7e7bbe76b5cd38c, 0x6e6ea56e57cbdc39, 0xc4c437c46ef395aa, 0x03030c03180f061b, - 0x565645568a13acdc, 0x44440d441a49885e, 0x7f7fe17fdf9efea0, 0xa9a99ea921374f88, - 0x2a2aa82a4d825467, 0xbbbbd6bbb16d6b0a, 0xc1c123c146e29f87, 0x53535153a202a6f1, - 0xdcdc57dcae8ba572, 0x0b0b2c0b58271653, 0x9d9d4e9d9cd32701, 0x6c6cad6c47c1d82b, - 0x3131c43195f562a4, 0x7474cd7487b9e8f3, 0xf6f6fff6e309f115, 0x464605460a438c4c, - 0xacac8aac092645a5, 0x89891e893c970fb5, 0x14145014a04428b4, 0xe1e1a3e15b42dfba, - 0x16165816b04e2ca6, 0x3a3ae83acdd274f7, 0x6969b9696fd0d206, 0x09092409482d1241, - 0x7070dd70a7ade0d7, 0xb6b6e2b6d954716f, 0xd0d067d0ceb7bd1e, 0xeded93ed3b7ec7d6, - 0xcccc17cc2edb85e2, 0x424215422a578468, 0x98985a98b4c22d2c, 0xa4a4aaa4490e55ed, - 0x2828a0285d885075, 0x5c5c6d5cda31b886, 0xf8f8c7f8933fed6b, 0x8686228644a411c2, -} - -C1 := [256]u64 { - 0xd818186018c07830, 0x2623238c2305af46, 0xb8c6c63fc67ef991, 0xfbe8e887e8136fcd, - 0xcb878726874ca113, 0x11b8b8dab8a9626d, 0x0901010401080502, 0x0d4f4f214f426e9e, - 0x9b3636d836adee6c, 0xffa6a6a2a6590451, 0x0cd2d26fd2debdb9, 0x0ef5f5f3f5fb06f7, - 0x967979f979ef80f2, 0x306f6fa16f5fcede, 0x6d91917e91fcef3f, 0xf852525552aa07a4, - 0x4760609d6027fdc0, 0x35bcbccabc897665, 0x379b9b569baccd2b, 0x8a8e8e028e048c01, - 0xd2a3a3b6a371155b, 0x6c0c0c300c603c18, 0x847b7bf17bff8af6, 0x803535d435b5e16a, - 0xf51d1d741de8693a, 0xb3e0e0a7e05347dd, 0x21d7d77bd7f6acb3, 0x9cc2c22fc25eed99, - 0x432e2eb82e6d965c, 0x294b4b314b627a96, 0x5dfefedffea321e1, 0xd5575741578216ae, - 0xbd15155415a8412a, 0xe87777c1779fb6ee, 0x923737dc37a5eb6e, 0x9ee5e5b3e57b56d7, - 0x139f9f469f8cd923, 0x23f0f0e7f0d317fd, 0x204a4a354a6a7f94, 0x44dada4fda9e95a9, - 0xa258587d58fa25b0, 0xcfc9c903c906ca8f, 0x7c2929a429558d52, 0x5a0a0a280a502214, - 0x50b1b1feb1e14f7f, 0xc9a0a0baa0691a5d, 0x146b6bb16b7fdad6, 0xd985852e855cab17, - 0x3cbdbdcebd817367, 0x8f5d5d695dd234ba, 0x9010104010805020, 0x07f4f4f7f4f303f5, - 0xddcbcb0bcb16c08b, 0xd33e3ef83eedc67c, 0x2d0505140528110a, 0x78676781671fe6ce, - 0x97e4e4b7e47353d5, 0x0227279c2725bb4e, 0x7341411941325882, 0xa78b8b168b2c9d0b, - 0xf6a7a7a6a7510153, 0xb27d7de97dcf94fa, 0x4995956e95dcfb37, 0x56d8d847d88e9fad, - 0x70fbfbcbfb8b30eb, 0xcdeeee9fee2371c1, 0xbb7c7ced7cc791f8, 0x716666856617e3cc, - 0x7bdddd53dda68ea7, 0xaf17175c17b84b2e, 0x454747014702468e, 0x1a9e9e429e84dc21, - 0xd4caca0fca1ec589, 0x582d2db42d75995a, 0x2ebfbfc6bf917963, 0x3f07071c07381b0e, - 0xacadad8ead012347, 0xb05a5a755aea2fb4, 0xef838336836cb51b, 0xb63333cc3385ff66, - 0x5c636391633ff2c6, 0x1202020802100a04, 0x93aaaa92aa393849, 0xde7171d971afa8e2, - 0xc6c8c807c80ecf8d, 0xd119196419c87d32, 0x3b49493949727092, 0x5fd9d943d9869aaf, - 0x31f2f2eff2c31df9, 0xa8e3e3abe34b48db, 0xb95b5b715be22ab6, 0xbc88881a8834920d, - 0x3e9a9a529aa4c829, 0x0b262698262dbe4c, 0xbf3232c8328dfa64, 0x59b0b0fab0e94a7d, - 0xf2e9e983e91b6acf, 0x770f0f3c0f78331e, 0x33d5d573d5e6a6b7, 0xf480803a8074ba1d, - 0x27bebec2be997c61, 0xebcdcd13cd26de87, 0x893434d034bde468, 0x3248483d487a7590, - 0x54ffffdbffab24e3, 0x8d7a7af57af78ff4, 0x6490907a90f4ea3d, 0x9d5f5f615fc23ebe, - 0x3d202080201da040, 0x0f6868bd6867d5d0, 0xca1a1a681ad07234, 0xb7aeae82ae192c41, - 0x7db4b4eab4c95e75, 0xce54544d549a19a8, 0x7f93937693ece53b, 0x2f222288220daa44, - 0x6364648d6407e9c8, 0x2af1f1e3f1db12ff, 0xcc7373d173bfa2e6, 0x8212124812905a24, - 0x7a40401d403a5d80, 0x4808082008402810, 0x95c3c32bc356e89b, 0xdfecec97ec337bc5, - 0x4ddbdb4bdb9690ab, 0xc0a1a1bea1611f5f, 0x918d8d0e8d1c8307, 0xc83d3df43df5c97a, - 0x5b97976697ccf133, 0x0000000000000000, 0xf9cfcf1bcf36d483, 0x6e2b2bac2b458756, - 0xe17676c57697b3ec, 0xe68282328264b019, 0x28d6d67fd6fea9b1, 0xc31b1b6c1bd87736, - 0x74b5b5eeb5c15b77, 0xbeafaf86af112943, 0x1d6a6ab56a77dfd4, 0xea50505d50ba0da0, - 0x5745450945124c8a, 0x38f3f3ebf3cb18fb, 0xad3030c0309df060, 0xc4efef9bef2b74c3, - 0xda3f3ffc3fe5c37e, 0xc755554955921caa, 0xdba2a2b2a2791059, 0xe9eaea8fea0365c9, - 0x6a656589650fecca, 0x03babad2bab96869, 0x4a2f2fbc2f65935e, 0x8ec0c027c04ee79d, - 0x60dede5fdebe81a1, 0xfc1c1c701ce06c38, 0x46fdfdd3fdbb2ee7, 0x1f4d4d294d52649a, - 0x7692927292e4e039, 0xfa7575c9758fbcea, 0x3606061806301e0c, 0xae8a8a128a249809, - 0x4bb2b2f2b2f94079, 0x85e6e6bfe66359d1, 0x7e0e0e380e70361c, 0xe71f1f7c1ff8633e, - 0x556262956237f7c4, 0x3ad4d477d4eea3b5, 0x81a8a89aa829324d, 0x5296966296c4f431, - 0x62f9f9c3f99b3aef, 0xa3c5c533c566f697, 0x102525942535b14a, 0xab59597959f220b2, - 0xd084842a8454ae15, 0xc57272d572b7a7e4, 0xec3939e439d5dd72, 0x164c4c2d4c5a6198, - 0x945e5e655eca3bbc, 0x9f7878fd78e785f0, 0xe53838e038ddd870, 0x988c8c0a8c148605, - 0x17d1d163d1c6b2bf, 0xe4a5a5aea5410b57, 0xa1e2e2afe2434dd9, 0x4e616199612ff8c2, - 0x42b3b3f6b3f1457b, 0x342121842115a542, 0x089c9c4a9c94d625, 0xee1e1e781ef0663c, - 0x6143431143225286, 0xb1c7c73bc776fc93, 0x4ffcfcd7fcb32be5, 0x2404041004201408, - 0xe351515951b208a2, 0x2599995e99bcc72f, 0x226d6da96d4fc4da, 0x650d0d340d68391a, - 0x79fafacffa8335e9, 0x69dfdf5bdfb684a3, 0xa97e7ee57ed79bfc, 0x19242490243db448, - 0xfe3b3bec3bc5d776, 0x9aabab96ab313d4b, 0xf0cece1fce3ed181, 0x9911114411885522, - 0x838f8f068f0c8903, 0x044e4e254e4a6b9c, 0x66b7b7e6b7d15173, 0xe0ebeb8beb0b60cb, - 0xc13c3cf03cfdcc78, 0xfd81813e817cbf1f, 0x4094946a94d4fe35, 0x1cf7f7fbf7eb0cf3, - 0x18b9b9deb9a1676f, 0x8b13134c13985f26, 0x512c2cb02c7d9c58, 0x05d3d36bd3d6b8bb, - 0x8ce7e7bbe76b5cd3, 0x396e6ea56e57cbdc, 0xaac4c437c46ef395, 0x1b03030c03180f06, - 0xdc565645568a13ac, 0x5e44440d441a4988, 0xa07f7fe17fdf9efe, 0x88a9a99ea921374f, - 0x672a2aa82a4d8254, 0x0abbbbd6bbb16d6b, 0x87c1c123c146e29f, 0xf153535153a202a6, - 0x72dcdc57dcae8ba5, 0x530b0b2c0b582716, 0x019d9d4e9d9cd327, 0x2b6c6cad6c47c1d8, - 0xa43131c43195f562, 0xf37474cd7487b9e8, 0x15f6f6fff6e309f1, 0x4c464605460a438c, - 0xa5acac8aac092645, 0xb589891e893c970f, 0xb414145014a04428, 0xbae1e1a3e15b42df, - 0xa616165816b04e2c, 0xf73a3ae83acdd274, 0x066969b9696fd0d2, 0x4109092409482d12, - 0xd77070dd70a7ade0, 0x6fb6b6e2b6d95471, 0x1ed0d067d0ceb7bd, 0xd6eded93ed3b7ec7, - 0xe2cccc17cc2edb85, 0x68424215422a5784, 0x2c98985a98b4c22d, 0xeda4a4aaa4490e55, - 0x752828a0285d8850, 0x865c5c6d5cda31b8, 0x6bf8f8c7f8933fed, 0xc28686228644a411, -} - -C2 := [256]u64 { - 0x30d818186018c078, 0x462623238c2305af, 0x91b8c6c63fc67ef9, 0xcdfbe8e887e8136f, - 0x13cb878726874ca1, 0x6d11b8b8dab8a962, 0x0209010104010805, 0x9e0d4f4f214f426e, - 0x6c9b3636d836adee, 0x51ffa6a6a2a65904, 0xb90cd2d26fd2debd, 0xf70ef5f5f3f5fb06, - 0xf2967979f979ef80, 0xde306f6fa16f5fce, 0x3f6d91917e91fcef, 0xa4f852525552aa07, - 0xc04760609d6027fd, 0x6535bcbccabc8976, 0x2b379b9b569baccd, 0x018a8e8e028e048c, - 0x5bd2a3a3b6a37115, 0x186c0c0c300c603c, 0xf6847b7bf17bff8a, 0x6a803535d435b5e1, - 0x3af51d1d741de869, 0xddb3e0e0a7e05347, 0xb321d7d77bd7f6ac, 0x999cc2c22fc25eed, - 0x5c432e2eb82e6d96, 0x96294b4b314b627a, 0xe15dfefedffea321, 0xaed5575741578216, - 0x2abd15155415a841, 0xeee87777c1779fb6, 0x6e923737dc37a5eb, 0xd79ee5e5b3e57b56, - 0x23139f9f469f8cd9, 0xfd23f0f0e7f0d317, 0x94204a4a354a6a7f, 0xa944dada4fda9e95, - 0xb0a258587d58fa25, 0x8fcfc9c903c906ca, 0x527c2929a429558d, 0x145a0a0a280a5022, - 0x7f50b1b1feb1e14f, 0x5dc9a0a0baa0691a, 0xd6146b6bb16b7fda, 0x17d985852e855cab, - 0x673cbdbdcebd8173, 0xba8f5d5d695dd234, 0x2090101040108050, 0xf507f4f4f7f4f303, - 0x8bddcbcb0bcb16c0, 0x7cd33e3ef83eedc6, 0x0a2d050514052811, 0xce78676781671fe6, - 0xd597e4e4b7e47353, 0x4e0227279c2725bb, 0x8273414119413258, 0x0ba78b8b168b2c9d, - 0x53f6a7a7a6a75101, 0xfab27d7de97dcf94, 0x374995956e95dcfb, 0xad56d8d847d88e9f, - 0xeb70fbfbcbfb8b30, 0xc1cdeeee9fee2371, 0xf8bb7c7ced7cc791, 0xcc716666856617e3, - 0xa77bdddd53dda68e, 0x2eaf17175c17b84b, 0x8e45474701470246, 0x211a9e9e429e84dc, - 0x89d4caca0fca1ec5, 0x5a582d2db42d7599, 0x632ebfbfc6bf9179, 0x0e3f07071c07381b, - 0x47acadad8ead0123, 0xb4b05a5a755aea2f, 0x1bef838336836cb5, 0x66b63333cc3385ff, - 0xc65c636391633ff2, 0x041202020802100a, 0x4993aaaa92aa3938, 0xe2de7171d971afa8, - 0x8dc6c8c807c80ecf, 0x32d119196419c87d, 0x923b494939497270, 0xaf5fd9d943d9869a, - 0xf931f2f2eff2c31d, 0xdba8e3e3abe34b48, 0xb6b95b5b715be22a, 0x0dbc88881a883492, - 0x293e9a9a529aa4c8, 0x4c0b262698262dbe, 0x64bf3232c8328dfa, 0x7d59b0b0fab0e94a, - 0xcff2e9e983e91b6a, 0x1e770f0f3c0f7833, 0xb733d5d573d5e6a6, 0x1df480803a8074ba, - 0x6127bebec2be997c, 0x87ebcdcd13cd26de, 0x68893434d034bde4, 0x903248483d487a75, - 0xe354ffffdbffab24, 0xf48d7a7af57af78f, 0x3d6490907a90f4ea, 0xbe9d5f5f615fc23e, - 0x403d202080201da0, 0xd00f6868bd6867d5, 0x34ca1a1a681ad072, 0x41b7aeae82ae192c, - 0x757db4b4eab4c95e, 0xa8ce54544d549a19, 0x3b7f93937693ece5, 0x442f222288220daa, - 0xc86364648d6407e9, 0xff2af1f1e3f1db12, 0xe6cc7373d173bfa2, 0x248212124812905a, - 0x807a40401d403a5d, 0x1048080820084028, 0x9b95c3c32bc356e8, 0xc5dfecec97ec337b, - 0xab4ddbdb4bdb9690, 0x5fc0a1a1bea1611f, 0x07918d8d0e8d1c83, 0x7ac83d3df43df5c9, - 0x335b97976697ccf1, 0x0000000000000000, 0x83f9cfcf1bcf36d4, 0x566e2b2bac2b4587, - 0xece17676c57697b3, 0x19e68282328264b0, 0xb128d6d67fd6fea9, 0x36c31b1b6c1bd877, - 0x7774b5b5eeb5c15b, 0x43beafaf86af1129, 0xd41d6a6ab56a77df, 0xa0ea50505d50ba0d, - 0x8a5745450945124c, 0xfb38f3f3ebf3cb18, 0x60ad3030c0309df0, 0xc3c4efef9bef2b74, - 0x7eda3f3ffc3fe5c3, 0xaac755554955921c, 0x59dba2a2b2a27910, 0xc9e9eaea8fea0365, - 0xca6a656589650fec, 0x6903babad2bab968, 0x5e4a2f2fbc2f6593, 0x9d8ec0c027c04ee7, - 0xa160dede5fdebe81, 0x38fc1c1c701ce06c, 0xe746fdfdd3fdbb2e, 0x9a1f4d4d294d5264, - 0x397692927292e4e0, 0xeafa7575c9758fbc, 0x0c3606061806301e, 0x09ae8a8a128a2498, - 0x794bb2b2f2b2f940, 0xd185e6e6bfe66359, 0x1c7e0e0e380e7036, 0x3ee71f1f7c1ff863, - 0xc4556262956237f7, 0xb53ad4d477d4eea3, 0x4d81a8a89aa82932, 0x315296966296c4f4, - 0xef62f9f9c3f99b3a, 0x97a3c5c533c566f6, 0x4a102525942535b1, 0xb2ab59597959f220, - 0x15d084842a8454ae, 0xe4c57272d572b7a7, 0x72ec3939e439d5dd, 0x98164c4c2d4c5a61, - 0xbc945e5e655eca3b, 0xf09f7878fd78e785, 0x70e53838e038ddd8, 0x05988c8c0a8c1486, - 0xbf17d1d163d1c6b2, 0x57e4a5a5aea5410b, 0xd9a1e2e2afe2434d, 0xc24e616199612ff8, - 0x7b42b3b3f6b3f145, 0x42342121842115a5, 0x25089c9c4a9c94d6, 0x3cee1e1e781ef066, - 0x8661434311432252, 0x93b1c7c73bc776fc, 0xe54ffcfcd7fcb32b, 0x0824040410042014, - 0xa2e351515951b208, 0x2f2599995e99bcc7, 0xda226d6da96d4fc4, 0x1a650d0d340d6839, - 0xe979fafacffa8335, 0xa369dfdf5bdfb684, 0xfca97e7ee57ed79b, 0x4819242490243db4, - 0x76fe3b3bec3bc5d7, 0x4b9aabab96ab313d, 0x81f0cece1fce3ed1, 0x2299111144118855, - 0x03838f8f068f0c89, 0x9c044e4e254e4a6b, 0x7366b7b7e6b7d151, 0xcbe0ebeb8beb0b60, - 0x78c13c3cf03cfdcc, 0x1ffd81813e817cbf, 0x354094946a94d4fe, 0xf31cf7f7fbf7eb0c, - 0x6f18b9b9deb9a167, 0x268b13134c13985f, 0x58512c2cb02c7d9c, 0xbb05d3d36bd3d6b8, - 0xd38ce7e7bbe76b5c, 0xdc396e6ea56e57cb, 0x95aac4c437c46ef3, 0x061b03030c03180f, - 0xacdc565645568a13, 0x885e44440d441a49, 0xfea07f7fe17fdf9e, 0x4f88a9a99ea92137, - 0x54672a2aa82a4d82, 0x6b0abbbbd6bbb16d, 0x9f87c1c123c146e2, 0xa6f153535153a202, - 0xa572dcdc57dcae8b, 0x16530b0b2c0b5827, 0x27019d9d4e9d9cd3, 0xd82b6c6cad6c47c1, - 0x62a43131c43195f5, 0xe8f37474cd7487b9, 0xf115f6f6fff6e309, 0x8c4c464605460a43, - 0x45a5acac8aac0926, 0x0fb589891e893c97, 0x28b414145014a044, 0xdfbae1e1a3e15b42, - 0x2ca616165816b04e, 0x74f73a3ae83acdd2, 0xd2066969b9696fd0, 0x124109092409482d, - 0xe0d77070dd70a7ad, 0x716fb6b6e2b6d954, 0xbd1ed0d067d0ceb7, 0xc7d6eded93ed3b7e, - 0x85e2cccc17cc2edb, 0x8468424215422a57, 0x2d2c98985a98b4c2, 0x55eda4a4aaa4490e, - 0x50752828a0285d88, 0xb8865c5c6d5cda31, 0xed6bf8f8c7f8933f, 0x11c28686228644a4, -} - -C3 := [256]u64 { - 0x7830d818186018c0, 0xaf462623238c2305, 0xf991b8c6c63fc67e, 0x6fcdfbe8e887e813, - 0xa113cb878726874c, 0x626d11b8b8dab8a9, 0x0502090101040108, 0x6e9e0d4f4f214f42, - 0xee6c9b3636d836ad, 0x0451ffa6a6a2a659, 0xbdb90cd2d26fd2de, 0x06f70ef5f5f3f5fb, - 0x80f2967979f979ef, 0xcede306f6fa16f5f, 0xef3f6d91917e91fc, 0x07a4f852525552aa, - 0xfdc04760609d6027, 0x766535bcbccabc89, 0xcd2b379b9b569bac, 0x8c018a8e8e028e04, - 0x155bd2a3a3b6a371, 0x3c186c0c0c300c60, 0x8af6847b7bf17bff, 0xe16a803535d435b5, - 0x693af51d1d741de8, 0x47ddb3e0e0a7e053, 0xacb321d7d77bd7f6, 0xed999cc2c22fc25e, - 0x965c432e2eb82e6d, 0x7a96294b4b314b62, 0x21e15dfefedffea3, 0x16aed55757415782, - 0x412abd15155415a8, 0xb6eee87777c1779f, 0xeb6e923737dc37a5, 0x56d79ee5e5b3e57b, - 0xd923139f9f469f8c, 0x17fd23f0f0e7f0d3, 0x7f94204a4a354a6a, 0x95a944dada4fda9e, - 0x25b0a258587d58fa, 0xca8fcfc9c903c906, 0x8d527c2929a42955, 0x22145a0a0a280a50, - 0x4f7f50b1b1feb1e1, 0x1a5dc9a0a0baa069, 0xdad6146b6bb16b7f, 0xab17d985852e855c, - 0x73673cbdbdcebd81, 0x34ba8f5d5d695dd2, 0x5020901010401080, 0x03f507f4f4f7f4f3, - 0xc08bddcbcb0bcb16, 0xc67cd33e3ef83eed, 0x110a2d0505140528, 0xe6ce78676781671f, - 0x53d597e4e4b7e473, 0xbb4e0227279c2725, 0x5882734141194132, 0x9d0ba78b8b168b2c, - 0x0153f6a7a7a6a751, 0x94fab27d7de97dcf, 0xfb374995956e95dc, 0x9fad56d8d847d88e, - 0x30eb70fbfbcbfb8b, 0x71c1cdeeee9fee23, 0x91f8bb7c7ced7cc7, 0xe3cc716666856617, - 0x8ea77bdddd53dda6, 0x4b2eaf17175c17b8, 0x468e454747014702, 0xdc211a9e9e429e84, - 0xc589d4caca0fca1e, 0x995a582d2db42d75, 0x79632ebfbfc6bf91, 0x1b0e3f07071c0738, - 0x2347acadad8ead01, 0x2fb4b05a5a755aea, 0xb51bef838336836c, 0xff66b63333cc3385, - 0xf2c65c636391633f, 0x0a04120202080210, 0x384993aaaa92aa39, 0xa8e2de7171d971af, - 0xcf8dc6c8c807c80e, 0x7d32d119196419c8, 0x70923b4949394972, 0x9aaf5fd9d943d986, - 0x1df931f2f2eff2c3, 0x48dba8e3e3abe34b, 0x2ab6b95b5b715be2, 0x920dbc88881a8834, - 0xc8293e9a9a529aa4, 0xbe4c0b262698262d, 0xfa64bf3232c8328d, 0x4a7d59b0b0fab0e9, - 0x6acff2e9e983e91b, 0x331e770f0f3c0f78, 0xa6b733d5d573d5e6, 0xba1df480803a8074, - 0x7c6127bebec2be99, 0xde87ebcdcd13cd26, 0xe468893434d034bd, 0x75903248483d487a, - 0x24e354ffffdbffab, 0x8ff48d7a7af57af7, 0xea3d6490907a90f4, 0x3ebe9d5f5f615fc2, - 0xa0403d202080201d, 0xd5d00f6868bd6867, 0x7234ca1a1a681ad0, 0x2c41b7aeae82ae19, - 0x5e757db4b4eab4c9, 0x19a8ce54544d549a, 0xe53b7f93937693ec, 0xaa442f222288220d, - 0xe9c86364648d6407, 0x12ff2af1f1e3f1db, 0xa2e6cc7373d173bf, 0x5a24821212481290, - 0x5d807a40401d403a, 0x2810480808200840, 0xe89b95c3c32bc356, 0x7bc5dfecec97ec33, - 0x90ab4ddbdb4bdb96, 0x1f5fc0a1a1bea161, 0x8307918d8d0e8d1c, 0xc97ac83d3df43df5, - 0xf1335b97976697cc, 0x0000000000000000, 0xd483f9cfcf1bcf36, 0x87566e2b2bac2b45, - 0xb3ece17676c57697, 0xb019e68282328264, 0xa9b128d6d67fd6fe, 0x7736c31b1b6c1bd8, - 0x5b7774b5b5eeb5c1, 0x2943beafaf86af11, 0xdfd41d6a6ab56a77, 0x0da0ea50505d50ba, - 0x4c8a574545094512, 0x18fb38f3f3ebf3cb, 0xf060ad3030c0309d, 0x74c3c4efef9bef2b, - 0xc37eda3f3ffc3fe5, 0x1caac75555495592, 0x1059dba2a2b2a279, 0x65c9e9eaea8fea03, - 0xecca6a656589650f, 0x686903babad2bab9, 0x935e4a2f2fbc2f65, 0xe79d8ec0c027c04e, - 0x81a160dede5fdebe, 0x6c38fc1c1c701ce0, 0x2ee746fdfdd3fdbb, 0x649a1f4d4d294d52, - 0xe0397692927292e4, 0xbceafa7575c9758f, 0x1e0c360606180630, 0x9809ae8a8a128a24, - 0x40794bb2b2f2b2f9, 0x59d185e6e6bfe663, 0x361c7e0e0e380e70, 0x633ee71f1f7c1ff8, - 0xf7c4556262956237, 0xa3b53ad4d477d4ee, 0x324d81a8a89aa829, 0xf4315296966296c4, - 0x3aef62f9f9c3f99b, 0xf697a3c5c533c566, 0xb14a102525942535, 0x20b2ab59597959f2, - 0xae15d084842a8454, 0xa7e4c57272d572b7, 0xdd72ec3939e439d5, 0x6198164c4c2d4c5a, - 0x3bbc945e5e655eca, 0x85f09f7878fd78e7, 0xd870e53838e038dd, 0x8605988c8c0a8c14, - 0xb2bf17d1d163d1c6, 0x0b57e4a5a5aea541, 0x4dd9a1e2e2afe243, 0xf8c24e616199612f, - 0x457b42b3b3f6b3f1, 0xa542342121842115, 0xd625089c9c4a9c94, 0x663cee1e1e781ef0, - 0x5286614343114322, 0xfc93b1c7c73bc776, 0x2be54ffcfcd7fcb3, 0x1408240404100420, - 0x08a2e351515951b2, 0xc72f2599995e99bc, 0xc4da226d6da96d4f, 0x391a650d0d340d68, - 0x35e979fafacffa83, 0x84a369dfdf5bdfb6, 0x9bfca97e7ee57ed7, 0xb44819242490243d, - 0xd776fe3b3bec3bc5, 0x3d4b9aabab96ab31, 0xd181f0cece1fce3e, 0x5522991111441188, - 0x8903838f8f068f0c, 0x6b9c044e4e254e4a, 0x517366b7b7e6b7d1, 0x60cbe0ebeb8beb0b, - 0xcc78c13c3cf03cfd, 0xbf1ffd81813e817c, 0xfe354094946a94d4, 0x0cf31cf7f7fbf7eb, - 0x676f18b9b9deb9a1, 0x5f268b13134c1398, 0x9c58512c2cb02c7d, 0xb8bb05d3d36bd3d6, - 0x5cd38ce7e7bbe76b, 0xcbdc396e6ea56e57, 0xf395aac4c437c46e, 0x0f061b03030c0318, - 0x13acdc565645568a, 0x49885e44440d441a, 0x9efea07f7fe17fdf, 0x374f88a9a99ea921, - 0x8254672a2aa82a4d, 0x6d6b0abbbbd6bbb1, 0xe29f87c1c123c146, 0x02a6f153535153a2, - 0x8ba572dcdc57dcae, 0x2716530b0b2c0b58, 0xd327019d9d4e9d9c, 0xc1d82b6c6cad6c47, - 0xf562a43131c43195, 0xb9e8f37474cd7487, 0x09f115f6f6fff6e3, 0x438c4c464605460a, - 0x2645a5acac8aac09, 0x970fb589891e893c, 0x4428b414145014a0, 0x42dfbae1e1a3e15b, - 0x4e2ca616165816b0, 0xd274f73a3ae83acd, 0xd0d2066969b9696f, 0x2d12410909240948, - 0xade0d77070dd70a7, 0x54716fb6b6e2b6d9, 0xb7bd1ed0d067d0ce, 0x7ec7d6eded93ed3b, - 0xdb85e2cccc17cc2e, 0x578468424215422a, 0xc22d2c98985a98b4, 0x0e55eda4a4aaa449, - 0x8850752828a0285d, 0x31b8865c5c6d5cda, 0x3fed6bf8f8c7f893, 0xa411c28686228644, -} - -C4 := [256]u64 { - 0xc07830d818186018, 0x05af462623238c23, 0x7ef991b8c6c63fc6, 0x136fcdfbe8e887e8, - 0x4ca113cb87872687, 0xa9626d11b8b8dab8, 0x0805020901010401, 0x426e9e0d4f4f214f, - 0xadee6c9b3636d836, 0x590451ffa6a6a2a6, 0xdebdb90cd2d26fd2, 0xfb06f70ef5f5f3f5, - 0xef80f2967979f979, 0x5fcede306f6fa16f, 0xfcef3f6d91917e91, 0xaa07a4f852525552, - 0x27fdc04760609d60, 0x89766535bcbccabc, 0xaccd2b379b9b569b, 0x048c018a8e8e028e, - 0x71155bd2a3a3b6a3, 0x603c186c0c0c300c, 0xff8af6847b7bf17b, 0xb5e16a803535d435, - 0xe8693af51d1d741d, 0x5347ddb3e0e0a7e0, 0xf6acb321d7d77bd7, 0x5eed999cc2c22fc2, - 0x6d965c432e2eb82e, 0x627a96294b4b314b, 0xa321e15dfefedffe, 0x8216aed557574157, - 0xa8412abd15155415, 0x9fb6eee87777c177, 0xa5eb6e923737dc37, 0x7b56d79ee5e5b3e5, - 0x8cd923139f9f469f, 0xd317fd23f0f0e7f0, 0x6a7f94204a4a354a, 0x9e95a944dada4fda, - 0xfa25b0a258587d58, 0x06ca8fcfc9c903c9, 0x558d527c2929a429, 0x5022145a0a0a280a, - 0xe14f7f50b1b1feb1, 0x691a5dc9a0a0baa0, 0x7fdad6146b6bb16b, 0x5cab17d985852e85, - 0x8173673cbdbdcebd, 0xd234ba8f5d5d695d, 0x8050209010104010, 0xf303f507f4f4f7f4, - 0x16c08bddcbcb0bcb, 0xedc67cd33e3ef83e, 0x28110a2d05051405, 0x1fe6ce7867678167, - 0x7353d597e4e4b7e4, 0x25bb4e0227279c27, 0x3258827341411941, 0x2c9d0ba78b8b168b, - 0x510153f6a7a7a6a7, 0xcf94fab27d7de97d, 0xdcfb374995956e95, 0x8e9fad56d8d847d8, - 0x8b30eb70fbfbcbfb, 0x2371c1cdeeee9fee, 0xc791f8bb7c7ced7c, 0x17e3cc7166668566, - 0xa68ea77bdddd53dd, 0xb84b2eaf17175c17, 0x02468e4547470147, 0x84dc211a9e9e429e, - 0x1ec589d4caca0fca, 0x75995a582d2db42d, 0x9179632ebfbfc6bf, 0x381b0e3f07071c07, - 0x012347acadad8ead, 0xea2fb4b05a5a755a, 0x6cb51bef83833683, 0x85ff66b63333cc33, - 0x3ff2c65c63639163, 0x100a041202020802, 0x39384993aaaa92aa, 0xafa8e2de7171d971, - 0x0ecf8dc6c8c807c8, 0xc87d32d119196419, 0x7270923b49493949, 0x869aaf5fd9d943d9, - 0xc31df931f2f2eff2, 0x4b48dba8e3e3abe3, 0xe22ab6b95b5b715b, 0x34920dbc88881a88, - 0xa4c8293e9a9a529a, 0x2dbe4c0b26269826, 0x8dfa64bf3232c832, 0xe94a7d59b0b0fab0, - 0x1b6acff2e9e983e9, 0x78331e770f0f3c0f, 0xe6a6b733d5d573d5, 0x74ba1df480803a80, - 0x997c6127bebec2be, 0x26de87ebcdcd13cd, 0xbde468893434d034, 0x7a75903248483d48, - 0xab24e354ffffdbff, 0xf78ff48d7a7af57a, 0xf4ea3d6490907a90, 0xc23ebe9d5f5f615f, - 0x1da0403d20208020, 0x67d5d00f6868bd68, 0xd07234ca1a1a681a, 0x192c41b7aeae82ae, - 0xc95e757db4b4eab4, 0x9a19a8ce54544d54, 0xece53b7f93937693, 0x0daa442f22228822, - 0x07e9c86364648d64, 0xdb12ff2af1f1e3f1, 0xbfa2e6cc7373d173, 0x905a248212124812, - 0x3a5d807a40401d40, 0x4028104808082008, 0x56e89b95c3c32bc3, 0x337bc5dfecec97ec, - 0x9690ab4ddbdb4bdb, 0x611f5fc0a1a1bea1, 0x1c8307918d8d0e8d, 0xf5c97ac83d3df43d, - 0xccf1335b97976697, 0x0000000000000000, 0x36d483f9cfcf1bcf, 0x4587566e2b2bac2b, - 0x97b3ece17676c576, 0x64b019e682823282, 0xfea9b128d6d67fd6, 0xd87736c31b1b6c1b, - 0xc15b7774b5b5eeb5, 0x112943beafaf86af, 0x77dfd41d6a6ab56a, 0xba0da0ea50505d50, - 0x124c8a5745450945, 0xcb18fb38f3f3ebf3, 0x9df060ad3030c030, 0x2b74c3c4efef9bef, - 0xe5c37eda3f3ffc3f, 0x921caac755554955, 0x791059dba2a2b2a2, 0x0365c9e9eaea8fea, - 0x0fecca6a65658965, 0xb9686903babad2ba, 0x65935e4a2f2fbc2f, 0x4ee79d8ec0c027c0, - 0xbe81a160dede5fde, 0xe06c38fc1c1c701c, 0xbb2ee746fdfdd3fd, 0x52649a1f4d4d294d, - 0xe4e0397692927292, 0x8fbceafa7575c975, 0x301e0c3606061806, 0x249809ae8a8a128a, - 0xf940794bb2b2f2b2, 0x6359d185e6e6bfe6, 0x70361c7e0e0e380e, 0xf8633ee71f1f7c1f, - 0x37f7c45562629562, 0xeea3b53ad4d477d4, 0x29324d81a8a89aa8, 0xc4f4315296966296, - 0x9b3aef62f9f9c3f9, 0x66f697a3c5c533c5, 0x35b14a1025259425, 0xf220b2ab59597959, - 0x54ae15d084842a84, 0xb7a7e4c57272d572, 0xd5dd72ec3939e439, 0x5a6198164c4c2d4c, - 0xca3bbc945e5e655e, 0xe785f09f7878fd78, 0xddd870e53838e038, 0x148605988c8c0a8c, - 0xc6b2bf17d1d163d1, 0x410b57e4a5a5aea5, 0x434dd9a1e2e2afe2, 0x2ff8c24e61619961, - 0xf1457b42b3b3f6b3, 0x15a5423421218421, 0x94d625089c9c4a9c, 0xf0663cee1e1e781e, - 0x2252866143431143, 0x76fc93b1c7c73bc7, 0xb32be54ffcfcd7fc, 0x2014082404041004, - 0xb208a2e351515951, 0xbcc72f2599995e99, 0x4fc4da226d6da96d, 0x68391a650d0d340d, - 0x8335e979fafacffa, 0xb684a369dfdf5bdf, 0xd79bfca97e7ee57e, 0x3db4481924249024, - 0xc5d776fe3b3bec3b, 0x313d4b9aabab96ab, 0x3ed181f0cece1fce, 0x8855229911114411, - 0x0c8903838f8f068f, 0x4a6b9c044e4e254e, 0xd1517366b7b7e6b7, 0x0b60cbe0ebeb8beb, - 0xfdcc78c13c3cf03c, 0x7cbf1ffd81813e81, 0xd4fe354094946a94, 0xeb0cf31cf7f7fbf7, - 0xa1676f18b9b9deb9, 0x985f268b13134c13, 0x7d9c58512c2cb02c, 0xd6b8bb05d3d36bd3, - 0x6b5cd38ce7e7bbe7, 0x57cbdc396e6ea56e, 0x6ef395aac4c437c4, 0x180f061b03030c03, - 0x8a13acdc56564556, 0x1a49885e44440d44, 0xdf9efea07f7fe17f, 0x21374f88a9a99ea9, - 0x4d8254672a2aa82a, 0xb16d6b0abbbbd6bb, 0x46e29f87c1c123c1, 0xa202a6f153535153, - 0xae8ba572dcdc57dc, 0x582716530b0b2c0b, 0x9cd327019d9d4e9d, 0x47c1d82b6c6cad6c, - 0x95f562a43131c431, 0x87b9e8f37474cd74, 0xe309f115f6f6fff6, 0x0a438c4c46460546, - 0x092645a5acac8aac, 0x3c970fb589891e89, 0xa04428b414145014, 0x5b42dfbae1e1a3e1, - 0xb04e2ca616165816, 0xcdd274f73a3ae83a, 0x6fd0d2066969b969, 0x482d124109092409, - 0xa7ade0d77070dd70, 0xd954716fb6b6e2b6, 0xceb7bd1ed0d067d0, 0x3b7ec7d6eded93ed, - 0x2edb85e2cccc17cc, 0x2a57846842421542, 0xb4c22d2c98985a98, 0x490e55eda4a4aaa4, - 0x5d8850752828a028, 0xda31b8865c5c6d5c, 0x933fed6bf8f8c7f8, 0x44a411c286862286, -} - -C5 := [256]u64 { - 0x18c07830d8181860, 0x2305af462623238c, 0xc67ef991b8c6c63f, 0xe8136fcdfbe8e887, - 0x874ca113cb878726, 0xb8a9626d11b8b8da, 0x0108050209010104, 0x4f426e9e0d4f4f21, - 0x36adee6c9b3636d8, 0xa6590451ffa6a6a2, 0xd2debdb90cd2d26f, 0xf5fb06f70ef5f5f3, - 0x79ef80f2967979f9, 0x6f5fcede306f6fa1, 0x91fcef3f6d91917e, 0x52aa07a4f8525255, - 0x6027fdc04760609d, 0xbc89766535bcbcca, 0x9baccd2b379b9b56, 0x8e048c018a8e8e02, - 0xa371155bd2a3a3b6, 0x0c603c186c0c0c30, 0x7bff8af6847b7bf1, 0x35b5e16a803535d4, - 0x1de8693af51d1d74, 0xe05347ddb3e0e0a7, 0xd7f6acb321d7d77b, 0xc25eed999cc2c22f, - 0x2e6d965c432e2eb8, 0x4b627a96294b4b31, 0xfea321e15dfefedf, 0x578216aed5575741, - 0x15a8412abd151554, 0x779fb6eee87777c1, 0x37a5eb6e923737dc, 0xe57b56d79ee5e5b3, - 0x9f8cd923139f9f46, 0xf0d317fd23f0f0e7, 0x4a6a7f94204a4a35, 0xda9e95a944dada4f, - 0x58fa25b0a258587d, 0xc906ca8fcfc9c903, 0x29558d527c2929a4, 0x0a5022145a0a0a28, - 0xb1e14f7f50b1b1fe, 0xa0691a5dc9a0a0ba, 0x6b7fdad6146b6bb1, 0x855cab17d985852e, - 0xbd8173673cbdbdce, 0x5dd234ba8f5d5d69, 0x1080502090101040, 0xf4f303f507f4f4f7, - 0xcb16c08bddcbcb0b, 0x3eedc67cd33e3ef8, 0x0528110a2d050514, 0x671fe6ce78676781, - 0xe47353d597e4e4b7, 0x2725bb4e0227279c, 0x4132588273414119, 0x8b2c9d0ba78b8b16, - 0xa7510153f6a7a7a6, 0x7dcf94fab27d7de9, 0x95dcfb374995956e, 0xd88e9fad56d8d847, - 0xfb8b30eb70fbfbcb, 0xee2371c1cdeeee9f, 0x7cc791f8bb7c7ced, 0x6617e3cc71666685, - 0xdda68ea77bdddd53, 0x17b84b2eaf17175c, 0x4702468e45474701, 0x9e84dc211a9e9e42, - 0xca1ec589d4caca0f, 0x2d75995a582d2db4, 0xbf9179632ebfbfc6, 0x07381b0e3f07071c, - 0xad012347acadad8e, 0x5aea2fb4b05a5a75, 0x836cb51bef838336, 0x3385ff66b63333cc, - 0x633ff2c65c636391, 0x02100a0412020208, 0xaa39384993aaaa92, 0x71afa8e2de7171d9, - 0xc80ecf8dc6c8c807, 0x19c87d32d1191964, 0x497270923b494939, 0xd9869aaf5fd9d943, - 0xf2c31df931f2f2ef, 0xe34b48dba8e3e3ab, 0x5be22ab6b95b5b71, 0x8834920dbc88881a, - 0x9aa4c8293e9a9a52, 0x262dbe4c0b262698, 0x328dfa64bf3232c8, 0xb0e94a7d59b0b0fa, - 0xe91b6acff2e9e983, 0x0f78331e770f0f3c, 0xd5e6a6b733d5d573, 0x8074ba1df480803a, - 0xbe997c6127bebec2, 0xcd26de87ebcdcd13, 0x34bde468893434d0, 0x487a75903248483d, - 0xffab24e354ffffdb, 0x7af78ff48d7a7af5, 0x90f4ea3d6490907a, 0x5fc23ebe9d5f5f61, - 0x201da0403d202080, 0x6867d5d00f6868bd, 0x1ad07234ca1a1a68, 0xae192c41b7aeae82, - 0xb4c95e757db4b4ea, 0x549a19a8ce54544d, 0x93ece53b7f939376, 0x220daa442f222288, - 0x6407e9c86364648d, 0xf1db12ff2af1f1e3, 0x73bfa2e6cc7373d1, 0x12905a2482121248, - 0x403a5d807a40401d, 0x0840281048080820, 0xc356e89b95c3c32b, 0xec337bc5dfecec97, - 0xdb9690ab4ddbdb4b, 0xa1611f5fc0a1a1be, 0x8d1c8307918d8d0e, 0x3df5c97ac83d3df4, - 0x97ccf1335b979766, 0x0000000000000000, 0xcf36d483f9cfcf1b, 0x2b4587566e2b2bac, - 0x7697b3ece17676c5, 0x8264b019e6828232, 0xd6fea9b128d6d67f, 0x1bd87736c31b1b6c, - 0xb5c15b7774b5b5ee, 0xaf112943beafaf86, 0x6a77dfd41d6a6ab5, 0x50ba0da0ea50505d, - 0x45124c8a57454509, 0xf3cb18fb38f3f3eb, 0x309df060ad3030c0, 0xef2b74c3c4efef9b, - 0x3fe5c37eda3f3ffc, 0x55921caac7555549, 0xa2791059dba2a2b2, 0xea0365c9e9eaea8f, - 0x650fecca6a656589, 0xbab9686903babad2, 0x2f65935e4a2f2fbc, 0xc04ee79d8ec0c027, - 0xdebe81a160dede5f, 0x1ce06c38fc1c1c70, 0xfdbb2ee746fdfdd3, 0x4d52649a1f4d4d29, - 0x92e4e03976929272, 0x758fbceafa7575c9, 0x06301e0c36060618, 0x8a249809ae8a8a12, - 0xb2f940794bb2b2f2, 0xe66359d185e6e6bf, 0x0e70361c7e0e0e38, 0x1ff8633ee71f1f7c, - 0x6237f7c455626295, 0xd4eea3b53ad4d477, 0xa829324d81a8a89a, 0x96c4f43152969662, - 0xf99b3aef62f9f9c3, 0xc566f697a3c5c533, 0x2535b14a10252594, 0x59f220b2ab595979, - 0x8454ae15d084842a, 0x72b7a7e4c57272d5, 0x39d5dd72ec3939e4, 0x4c5a6198164c4c2d, - 0x5eca3bbc945e5e65, 0x78e785f09f7878fd, 0x38ddd870e53838e0, 0x8c148605988c8c0a, - 0xd1c6b2bf17d1d163, 0xa5410b57e4a5a5ae, 0xe2434dd9a1e2e2af, 0x612ff8c24e616199, - 0xb3f1457b42b3b3f6, 0x2115a54234212184, 0x9c94d625089c9c4a, 0x1ef0663cee1e1e78, - 0x4322528661434311, 0xc776fc93b1c7c73b, 0xfcb32be54ffcfcd7, 0x0420140824040410, - 0x51b208a2e3515159, 0x99bcc72f2599995e, 0x6d4fc4da226d6da9, 0x0d68391a650d0d34, - 0xfa8335e979fafacf, 0xdfb684a369dfdf5b, 0x7ed79bfca97e7ee5, 0x243db44819242490, - 0x3bc5d776fe3b3bec, 0xab313d4b9aabab96, 0xce3ed181f0cece1f, 0x1188552299111144, - 0x8f0c8903838f8f06, 0x4e4a6b9c044e4e25, 0xb7d1517366b7b7e6, 0xeb0b60cbe0ebeb8b, - 0x3cfdcc78c13c3cf0, 0x817cbf1ffd81813e, 0x94d4fe354094946a, 0xf7eb0cf31cf7f7fb, - 0xb9a1676f18b9b9de, 0x13985f268b13134c, 0x2c7d9c58512c2cb0, 0xd3d6b8bb05d3d36b, - 0xe76b5cd38ce7e7bb, 0x6e57cbdc396e6ea5, 0xc46ef395aac4c437, 0x03180f061b03030c, - 0x568a13acdc565645, 0x441a49885e44440d, 0x7fdf9efea07f7fe1, 0xa921374f88a9a99e, - 0x2a4d8254672a2aa8, 0xbbb16d6b0abbbbd6, 0xc146e29f87c1c123, 0x53a202a6f1535351, - 0xdcae8ba572dcdc57, 0x0b582716530b0b2c, 0x9d9cd327019d9d4e, 0x6c47c1d82b6c6cad, - 0x3195f562a43131c4, 0x7487b9e8f37474cd, 0xf6e309f115f6f6ff, 0x460a438c4c464605, - 0xac092645a5acac8a, 0x893c970fb589891e, 0x14a04428b4141450, 0xe15b42dfbae1e1a3, - 0x16b04e2ca6161658, 0x3acdd274f73a3ae8, 0x696fd0d2066969b9, 0x09482d1241090924, - 0x70a7ade0d77070dd, 0xb6d954716fb6b6e2, 0xd0ceb7bd1ed0d067, 0xed3b7ec7d6eded93, - 0xcc2edb85e2cccc17, 0x422a578468424215, 0x98b4c22d2c98985a, 0xa4490e55eda4a4aa, - 0x285d8850752828a0, 0x5cda31b8865c5c6d, 0xf8933fed6bf8f8c7, 0x8644a411c2868622, -} - -C6 := [256]u64 { - 0x6018c07830d81818, 0x8c2305af46262323, 0x3fc67ef991b8c6c6, 0x87e8136fcdfbe8e8, - 0x26874ca113cb8787, 0xdab8a9626d11b8b8, 0x0401080502090101, 0x214f426e9e0d4f4f, - 0xd836adee6c9b3636, 0xa2a6590451ffa6a6, 0x6fd2debdb90cd2d2, 0xf3f5fb06f70ef5f5, - 0xf979ef80f2967979, 0xa16f5fcede306f6f, 0x7e91fcef3f6d9191, 0x5552aa07a4f85252, - 0x9d6027fdc0476060, 0xcabc89766535bcbc, 0x569baccd2b379b9b, 0x028e048c018a8e8e, - 0xb6a371155bd2a3a3, 0x300c603c186c0c0c, 0xf17bff8af6847b7b, 0xd435b5e16a803535, - 0x741de8693af51d1d, 0xa7e05347ddb3e0e0, 0x7bd7f6acb321d7d7, 0x2fc25eed999cc2c2, - 0xb82e6d965c432e2e, 0x314b627a96294b4b, 0xdffea321e15dfefe, 0x41578216aed55757, - 0x5415a8412abd1515, 0xc1779fb6eee87777, 0xdc37a5eb6e923737, 0xb3e57b56d79ee5e5, - 0x469f8cd923139f9f, 0xe7f0d317fd23f0f0, 0x354a6a7f94204a4a, 0x4fda9e95a944dada, - 0x7d58fa25b0a25858, 0x03c906ca8fcfc9c9, 0xa429558d527c2929, 0x280a5022145a0a0a, - 0xfeb1e14f7f50b1b1, 0xbaa0691a5dc9a0a0, 0xb16b7fdad6146b6b, 0x2e855cab17d98585, - 0xcebd8173673cbdbd, 0x695dd234ba8f5d5d, 0x4010805020901010, 0xf7f4f303f507f4f4, - 0x0bcb16c08bddcbcb, 0xf83eedc67cd33e3e, 0x140528110a2d0505, 0x81671fe6ce786767, - 0xb7e47353d597e4e4, 0x9c2725bb4e022727, 0x1941325882734141, 0x168b2c9d0ba78b8b, - 0xa6a7510153f6a7a7, 0xe97dcf94fab27d7d, 0x6e95dcfb37499595, 0x47d88e9fad56d8d8, - 0xcbfb8b30eb70fbfb, 0x9fee2371c1cdeeee, 0xed7cc791f8bb7c7c, 0x856617e3cc716666, - 0x53dda68ea77bdddd, 0x5c17b84b2eaf1717, 0x014702468e454747, 0x429e84dc211a9e9e, - 0x0fca1ec589d4caca, 0xb42d75995a582d2d, 0xc6bf9179632ebfbf, 0x1c07381b0e3f0707, - 0x8ead012347acadad, 0x755aea2fb4b05a5a, 0x36836cb51bef8383, 0xcc3385ff66b63333, - 0x91633ff2c65c6363, 0x0802100a04120202, 0x92aa39384993aaaa, 0xd971afa8e2de7171, - 0x07c80ecf8dc6c8c8, 0x6419c87d32d11919, 0x39497270923b4949, 0x43d9869aaf5fd9d9, - 0xeff2c31df931f2f2, 0xabe34b48dba8e3e3, 0x715be22ab6b95b5b, 0x1a8834920dbc8888, - 0x529aa4c8293e9a9a, 0x98262dbe4c0b2626, 0xc8328dfa64bf3232, 0xfab0e94a7d59b0b0, - 0x83e91b6acff2e9e9, 0x3c0f78331e770f0f, 0x73d5e6a6b733d5d5, 0x3a8074ba1df48080, - 0xc2be997c6127bebe, 0x13cd26de87ebcdcd, 0xd034bde468893434, 0x3d487a7590324848, - 0xdbffab24e354ffff, 0xf57af78ff48d7a7a, 0x7a90f4ea3d649090, 0x615fc23ebe9d5f5f, - 0x80201da0403d2020, 0xbd6867d5d00f6868, 0x681ad07234ca1a1a, 0x82ae192c41b7aeae, - 0xeab4c95e757db4b4, 0x4d549a19a8ce5454, 0x7693ece53b7f9393, 0x88220daa442f2222, - 0x8d6407e9c8636464, 0xe3f1db12ff2af1f1, 0xd173bfa2e6cc7373, 0x4812905a24821212, - 0x1d403a5d807a4040, 0x2008402810480808, 0x2bc356e89b95c3c3, 0x97ec337bc5dfecec, - 0x4bdb9690ab4ddbdb, 0xbea1611f5fc0a1a1, 0x0e8d1c8307918d8d, 0xf43df5c97ac83d3d, - 0x6697ccf1335b9797, 0x0000000000000000, 0x1bcf36d483f9cfcf, 0xac2b4587566e2b2b, - 0xc57697b3ece17676, 0x328264b019e68282, 0x7fd6fea9b128d6d6, 0x6c1bd87736c31b1b, - 0xeeb5c15b7774b5b5, 0x86af112943beafaf, 0xb56a77dfd41d6a6a, 0x5d50ba0da0ea5050, - 0x0945124c8a574545, 0xebf3cb18fb38f3f3, 0xc0309df060ad3030, 0x9bef2b74c3c4efef, - 0xfc3fe5c37eda3f3f, 0x4955921caac75555, 0xb2a2791059dba2a2, 0x8fea0365c9e9eaea, - 0x89650fecca6a6565, 0xd2bab9686903baba, 0xbc2f65935e4a2f2f, 0x27c04ee79d8ec0c0, - 0x5fdebe81a160dede, 0x701ce06c38fc1c1c, 0xd3fdbb2ee746fdfd, 0x294d52649a1f4d4d, - 0x7292e4e039769292, 0xc9758fbceafa7575, 0x1806301e0c360606, 0x128a249809ae8a8a, - 0xf2b2f940794bb2b2, 0xbfe66359d185e6e6, 0x380e70361c7e0e0e, 0x7c1ff8633ee71f1f, - 0x956237f7c4556262, 0x77d4eea3b53ad4d4, 0x9aa829324d81a8a8, 0x6296c4f431529696, - 0xc3f99b3aef62f9f9, 0x33c566f697a3c5c5, 0x942535b14a102525, 0x7959f220b2ab5959, - 0x2a8454ae15d08484, 0xd572b7a7e4c57272, 0xe439d5dd72ec3939, 0x2d4c5a6198164c4c, - 0x655eca3bbc945e5e, 0xfd78e785f09f7878, 0xe038ddd870e53838, 0x0a8c148605988c8c, - 0x63d1c6b2bf17d1d1, 0xaea5410b57e4a5a5, 0xafe2434dd9a1e2e2, 0x99612ff8c24e6161, - 0xf6b3f1457b42b3b3, 0x842115a542342121, 0x4a9c94d625089c9c, 0x781ef0663cee1e1e, - 0x1143225286614343, 0x3bc776fc93b1c7c7, 0xd7fcb32be54ffcfc, 0x1004201408240404, - 0x5951b208a2e35151, 0x5e99bcc72f259999, 0xa96d4fc4da226d6d, 0x340d68391a650d0d, - 0xcffa8335e979fafa, 0x5bdfb684a369dfdf, 0xe57ed79bfca97e7e, 0x90243db448192424, - 0xec3bc5d776fe3b3b, 0x96ab313d4b9aabab, 0x1fce3ed181f0cece, 0x4411885522991111, - 0x068f0c8903838f8f, 0x254e4a6b9c044e4e, 0xe6b7d1517366b7b7, 0x8beb0b60cbe0ebeb, - 0xf03cfdcc78c13c3c, 0x3e817cbf1ffd8181, 0x6a94d4fe35409494, 0xfbf7eb0cf31cf7f7, - 0xdeb9a1676f18b9b9, 0x4c13985f268b1313, 0xb02c7d9c58512c2c, 0x6bd3d6b8bb05d3d3, - 0xbbe76b5cd38ce7e7, 0xa56e57cbdc396e6e, 0x37c46ef395aac4c4, 0x0c03180f061b0303, - 0x45568a13acdc5656, 0x0d441a49885e4444, 0xe17fdf9efea07f7f, 0x9ea921374f88a9a9, - 0xa82a4d8254672a2a, 0xd6bbb16d6b0abbbb, 0x23c146e29f87c1c1, 0x5153a202a6f15353, - 0x57dcae8ba572dcdc, 0x2c0b582716530b0b, 0x4e9d9cd327019d9d, 0xad6c47c1d82b6c6c, - 0xc43195f562a43131, 0xcd7487b9e8f37474, 0xfff6e309f115f6f6, 0x05460a438c4c4646, - 0x8aac092645a5acac, 0x1e893c970fb58989, 0x5014a04428b41414, 0xa3e15b42dfbae1e1, - 0x5816b04e2ca61616, 0xe83acdd274f73a3a, 0xb9696fd0d2066969, 0x2409482d12410909, - 0xdd70a7ade0d77070, 0xe2b6d954716fb6b6, 0x67d0ceb7bd1ed0d0, 0x93ed3b7ec7d6eded, - 0x17cc2edb85e2cccc, 0x15422a5784684242, 0x5a98b4c22d2c9898, 0xaaa4490e55eda4a4, - 0xa0285d8850752828, 0x6d5cda31b8865c5c, 0xc7f8933fed6bf8f8, 0x228644a411c28686, -} - -C7 := [256]u64 { - 0x186018c07830d818, 0x238c2305af462623, 0xc63fc67ef991b8c6, 0xe887e8136fcdfbe8, - 0x8726874ca113cb87, 0xb8dab8a9626d11b8, 0x0104010805020901, 0x4f214f426e9e0d4f, - 0x36d836adee6c9b36, 0xa6a2a6590451ffa6, 0xd26fd2debdb90cd2, 0xf5f3f5fb06f70ef5, - 0x79f979ef80f29679, 0x6fa16f5fcede306f, 0x917e91fcef3f6d91, 0x525552aa07a4f852, - 0x609d6027fdc04760, 0xbccabc89766535bc, 0x9b569baccd2b379b, 0x8e028e048c018a8e, - 0xa3b6a371155bd2a3, 0x0c300c603c186c0c, 0x7bf17bff8af6847b, 0x35d435b5e16a8035, - 0x1d741de8693af51d, 0xe0a7e05347ddb3e0, 0xd77bd7f6acb321d7, 0xc22fc25eed999cc2, - 0x2eb82e6d965c432e, 0x4b314b627a96294b, 0xfedffea321e15dfe, 0x5741578216aed557, - 0x155415a8412abd15, 0x77c1779fb6eee877, 0x37dc37a5eb6e9237, 0xe5b3e57b56d79ee5, - 0x9f469f8cd923139f, 0xf0e7f0d317fd23f0, 0x4a354a6a7f94204a, 0xda4fda9e95a944da, - 0x587d58fa25b0a258, 0xc903c906ca8fcfc9, 0x29a429558d527c29, 0x0a280a5022145a0a, - 0xb1feb1e14f7f50b1, 0xa0baa0691a5dc9a0, 0x6bb16b7fdad6146b, 0x852e855cab17d985, - 0xbdcebd8173673cbd, 0x5d695dd234ba8f5d, 0x1040108050209010, 0xf4f7f4f303f507f4, - 0xcb0bcb16c08bddcb, 0x3ef83eedc67cd33e, 0x05140528110a2d05, 0x6781671fe6ce7867, - 0xe4b7e47353d597e4, 0x279c2725bb4e0227, 0x4119413258827341, 0x8b168b2c9d0ba78b, - 0xa7a6a7510153f6a7, 0x7de97dcf94fab27d, 0x956e95dcfb374995, 0xd847d88e9fad56d8, - 0xfbcbfb8b30eb70fb, 0xee9fee2371c1cdee, 0x7ced7cc791f8bb7c, 0x66856617e3cc7166, - 0xdd53dda68ea77bdd, 0x175c17b84b2eaf17, 0x47014702468e4547, 0x9e429e84dc211a9e, - 0xca0fca1ec589d4ca, 0x2db42d75995a582d, 0xbfc6bf9179632ebf, 0x071c07381b0e3f07, - 0xad8ead012347acad, 0x5a755aea2fb4b05a, 0x8336836cb51bef83, 0x33cc3385ff66b633, - 0x6391633ff2c65c63, 0x020802100a041202, 0xaa92aa39384993aa, 0x71d971afa8e2de71, - 0xc807c80ecf8dc6c8, 0x196419c87d32d119, 0x4939497270923b49, 0xd943d9869aaf5fd9, - 0xf2eff2c31df931f2, 0xe3abe34b48dba8e3, 0x5b715be22ab6b95b, 0x881a8834920dbc88, - 0x9a529aa4c8293e9a, 0x2698262dbe4c0b26, 0x32c8328dfa64bf32, 0xb0fab0e94a7d59b0, - 0xe983e91b6acff2e9, 0x0f3c0f78331e770f, 0xd573d5e6a6b733d5, 0x803a8074ba1df480, - 0xbec2be997c6127be, 0xcd13cd26de87ebcd, 0x34d034bde4688934, 0x483d487a75903248, - 0xffdbffab24e354ff, 0x7af57af78ff48d7a, 0x907a90f4ea3d6490, 0x5f615fc23ebe9d5f, - 0x2080201da0403d20, 0x68bd6867d5d00f68, 0x1a681ad07234ca1a, 0xae82ae192c41b7ae, - 0xb4eab4c95e757db4, 0x544d549a19a8ce54, 0x937693ece53b7f93, 0x2288220daa442f22, - 0x648d6407e9c86364, 0xf1e3f1db12ff2af1, 0x73d173bfa2e6cc73, 0x124812905a248212, - 0x401d403a5d807a40, 0x0820084028104808, 0xc32bc356e89b95c3, 0xec97ec337bc5dfec, - 0xdb4bdb9690ab4ddb, 0xa1bea1611f5fc0a1, 0x8d0e8d1c8307918d, 0x3df43df5c97ac83d, - 0x976697ccf1335b97, 0x0000000000000000, 0xcf1bcf36d483f9cf, 0x2bac2b4587566e2b, - 0x76c57697b3ece176, 0x82328264b019e682, 0xd67fd6fea9b128d6, 0x1b6c1bd87736c31b, - 0xb5eeb5c15b7774b5, 0xaf86af112943beaf, 0x6ab56a77dfd41d6a, 0x505d50ba0da0ea50, - 0x450945124c8a5745, 0xf3ebf3cb18fb38f3, 0x30c0309df060ad30, 0xef9bef2b74c3c4ef, - 0x3ffc3fe5c37eda3f, 0x554955921caac755, 0xa2b2a2791059dba2, 0xea8fea0365c9e9ea, - 0x6589650fecca6a65, 0xbad2bab9686903ba, 0x2fbc2f65935e4a2f, 0xc027c04ee79d8ec0, - 0xde5fdebe81a160de, 0x1c701ce06c38fc1c, 0xfdd3fdbb2ee746fd, 0x4d294d52649a1f4d, - 0x927292e4e0397692, 0x75c9758fbceafa75, 0x061806301e0c3606, 0x8a128a249809ae8a, - 0xb2f2b2f940794bb2, 0xe6bfe66359d185e6, 0x0e380e70361c7e0e, 0x1f7c1ff8633ee71f, - 0x62956237f7c45562, 0xd477d4eea3b53ad4, 0xa89aa829324d81a8, 0x966296c4f4315296, - 0xf9c3f99b3aef62f9, 0xc533c566f697a3c5, 0x25942535b14a1025, 0x597959f220b2ab59, - 0x842a8454ae15d084, 0x72d572b7a7e4c572, 0x39e439d5dd72ec39, 0x4c2d4c5a6198164c, - 0x5e655eca3bbc945e, 0x78fd78e785f09f78, 0x38e038ddd870e538, 0x8c0a8c148605988c, - 0xd163d1c6b2bf17d1, 0xa5aea5410b57e4a5, 0xe2afe2434dd9a1e2, 0x6199612ff8c24e61, - 0xb3f6b3f1457b42b3, 0x21842115a5423421, 0x9c4a9c94d625089c, 0x1e781ef0663cee1e, - 0x4311432252866143, 0xc73bc776fc93b1c7, 0xfcd7fcb32be54ffc, 0x0410042014082404, - 0x515951b208a2e351, 0x995e99bcc72f2599, 0x6da96d4fc4da226d, 0x0d340d68391a650d, - 0xfacffa8335e979fa, 0xdf5bdfb684a369df, 0x7ee57ed79bfca97e, 0x2490243db4481924, - 0x3bec3bc5d776fe3b, 0xab96ab313d4b9aab, 0xce1fce3ed181f0ce, 0x1144118855229911, - 0x8f068f0c8903838f, 0x4e254e4a6b9c044e, 0xb7e6b7d1517366b7, 0xeb8beb0b60cbe0eb, - 0x3cf03cfdcc78c13c, 0x813e817cbf1ffd81, 0x946a94d4fe354094, 0xf7fbf7eb0cf31cf7, - 0xb9deb9a1676f18b9, 0x134c13985f268b13, 0x2cb02c7d9c58512c, 0xd36bd3d6b8bb05d3, - 0xe7bbe76b5cd38ce7, 0x6ea56e57cbdc396e, 0xc437c46ef395aac4, 0x030c03180f061b03, - 0x5645568a13acdc56, 0x440d441a49885e44, 0x7fe17fdf9efea07f, 0xa99ea921374f88a9, - 0x2aa82a4d8254672a, 0xbbd6bbb16d6b0abb, 0xc123c146e29f87c1, 0x535153a202a6f153, - 0xdc57dcae8ba572dc, 0x0b2c0b582716530b, 0x9d4e9d9cd327019d, 0x6cad6c47c1d82b6c, - 0x31c43195f562a431, 0x74cd7487b9e8f374, 0xf6fff6e309f115f6, 0x4605460a438c4c46, - 0xac8aac092645a5ac, 0x891e893c970fb589, 0x145014a04428b414, 0xe1a3e15b42dfbae1, - 0x165816b04e2ca616, 0x3ae83acdd274f73a, 0x69b9696fd0d20669, 0x092409482d124109, - 0x70dd70a7ade0d770, 0xb6e2b6d954716fb6, 0xd067d0ceb7bd1ed0, 0xed93ed3b7ec7d6ed, - 0xcc17cc2edb85e2cc, 0x4215422a57846842, 0x985a98b4c22d2c98, 0xa4aaa4490e55eda4, - 0x28a0285d88507528, 0x5c6d5cda31b8865c, 0xf8c7f8933fed6bf8, 0x86228644a411c286, -} - -RC := [ROUNDS + 1]u64 { - 0x0000000000000000, - 0x1823c6e887b8014f, - 0x36a6d2f5796f9152, - 0x60bc9b8ea30c7b35, - 0x1de0d7c22e4bfe57, - 0x157737e59ff04ada, - 0x58c9290ab1a06b85, - 0xbd5d10f4cb3e0567, - 0xe427418ba77d95d8, - 0xfbee7c66dd17479e, - 0xca2dbf07ad5a8333, -} - -transform :: proc (ctx: ^Whirlpool_Context) { - K, block, state, L: [8]u64 - - for i := 0; i < 8; i += 1 {block[i] = util.U64_BE(ctx.buffer[8 * i:])} - - for i := 0; i < 8; i += 1 { - K[i] = ctx.hash[i] - state[i] = block[i] ~ K[i] - } - - for r := 1; r <= ROUNDS; r += 1 { - for i := 0; i < 8; i += 1 { - L[i] = C0[byte(K[i % 8] >> 56)] ~ - C1[byte(K[(i + 7) % 8] >> 48)] ~ - C2[byte(K[(i + 6) % 8] >> 40)] ~ - C3[byte(K[(i + 5) % 8] >> 32)] ~ - C4[byte(K[(i + 4) % 8] >> 24)] ~ - C5[byte(K[(i + 3) % 8] >> 16)] ~ - C6[byte(K[(i + 2) % 8] >> 8)] ~ - C7[byte(K[(i + 1) % 8])] - } - L[0] ~= RC[r] - - for i := 0; i < 8; i += 1 {K[i] = L[i]} - - for i := 0; i < 8; i += 1 { - L[i] = C0[byte(state[i % 8] >> 56)] ~ - C1[byte(state[(i + 7) % 8] >> 48)] ~ - C2[byte(state[(i + 6) % 8] >> 40)] ~ - C3[byte(state[(i + 5) % 8] >> 32)] ~ - C4[byte(state[(i + 4) % 8] >> 24)] ~ - C5[byte(state[(i + 3) % 8] >> 16)] ~ - C6[byte(state[(i + 2) % 8] >> 8)] ~ - C7[byte(state[(i + 1) % 8])] ~ - K[i % 8] - } - for i := 0; i < 8; i += 1 {state[i] = L[i]} - } - for i := 0; i < 8; i += 1 {ctx.hash[i] ~= state[i] ~ block[i]} -} diff --git a/core/dynlib/doc.odin b/core/dynlib/doc.odin index 812fb02d5..849e03a71 100644 --- a/core/dynlib/doc.odin +++ b/core/dynlib/doc.odin @@ -1,7 +1,11 @@ +//+build ignore /* Package core:dynlib implements loading of shared libraries/DLLs and their symbols. The behaviour of dynamically loaded libraries is specific to the target platform of the program. For in depth detail on the underlying behaviour please refer to your target platform's documentation. + +See `example` directory for an example library exporting 3 symbols and a host program loading them automatically +by defining a symbol table struct. */ -package dynlib +package dynlib \ No newline at end of file diff --git a/core/dynlib/example/example.odin b/core/dynlib/example/example.odin new file mode 100644 index 000000000..f12233b0a --- /dev/null +++ b/core/dynlib/example/example.odin @@ -0,0 +1,45 @@ +package example + +import "core:dynlib" +import "core:fmt" + +Symbols :: struct { + // `foo_` is prefixed, so we look for the symbol `foo_add`. + add: proc "c" (int, int) -> int, + // We use the tag here to override the symbol to look for, namely `bar_sub`. + sub: proc "c" (int, int) -> int `dynlib:"bar_sub"`, + + // Exported global (if exporting an i32, the type must be ^i32 because the symbol is a pointer to the export.) + // If it's not a pointer or procedure type, we'll skip the struct field. + hellope: ^i32, + + // Handle to free library. + // We can have more than one of these so we can match symbols for more than one DLL with one struct. + _my_lib_handle: dynlib.Library, +} + +main :: proc() { + sym: Symbols + + // Load symbols from `lib.dll` into Symbols struct. + // Each struct field is prefixed with `foo_` before lookup in the DLL's symbol table. + // The library's Handle (to unload) will be stored in `sym._my_lib_handle`. This way you can load multiple DLLs in one struct. + count, ok := dynlib.initialize_symbols(&sym, "lib.dll", "foo_", "_my_lib_handle") + defer dynlib.unload_library(sym._my_lib_handle) + fmt.printf("(Initial DLL Load) ok: %v. %v symbols loaded from lib.dll (%p).\n", ok, count, sym._my_lib_handle) + + if count > 0 { + fmt.println("42 + 42 =", sym.add(42, 42)) + fmt.println("84 - 13 =", sym.sub(84, 13)) + fmt.println("hellope =", sym.hellope^) + } + + count, ok = dynlib.initialize_symbols(&sym, "lib.dll", "foo_", "_my_lib_handle") + fmt.printf("(DLL Reload) ok: %v. %v symbols loaded from lib.dll (%p).\n", ok, count, sym._my_lib_handle) + + if count > 0 { + fmt.println("42 + 42 =", sym.add(42, 42)) + fmt.println("84 - 13 =", sym.sub(84, 13)) + fmt.println("hellope =", sym.hellope^) + } +} \ No newline at end of file diff --git a/core/dynlib/example/lib.odin b/core/dynlib/example/lib.odin new file mode 100644 index 000000000..25687a653 --- /dev/null +++ b/core/dynlib/example/lib.odin @@ -0,0 +1,14 @@ +package library + +@(export) +foo_add :: proc "c" (a, b: int) -> (res: int) { + return a + b +} + +@(export) +bar_sub :: proc "c" (a, b: int) -> (res: int) { + return a - b +} + +@(export) +foo_hellope: i32 = 42 \ No newline at end of file diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin index b5cb16e3c..e9ee77d2c 100644 --- a/core/dynlib/lib.odin +++ b/core/dynlib/lib.odin @@ -1,5 +1,12 @@ package dynlib +import "core:intrinsics" +import "core:reflect" +import "core:runtime" +_ :: intrinsics +_ :: reflect +_ :: runtime + /* A handle to a dynamically loaded library. */ @@ -12,11 +19,11 @@ library available to resolve references in subsequently loaded libraries. The paramater `global_symbols` is only used for the platforms `linux`, `darwin`, `freebsd` and `openbsd`. On `windows` this paramater is ignored. -The underlying behaviour is platform specific. -On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlopen`. +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlopen`. On `windows` refer to `LoadLibraryW`. -**Implicit Allocators** +**Implicit Allocators** `context.temp_allocator` Example: @@ -27,6 +34,7 @@ Example: LIBRARY_PATH :: "my_library.dll" library, ok := dynlib.load_library(LIBRARY_PATH) if ! ok { + fmt.eprintln(dynlib.last_error()) return } fmt.println("The library %q was successfully loaded", LIBRARY_PATH) @@ -39,8 +47,8 @@ load_library :: proc(path: string, global_symbols := false) -> (library: Library /* Unloads a dynamic library. -The underlying behaviour is platform specific. -On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlclose`. +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlclose`. On `windows` refer to `FreeLibrary`. Example: @@ -51,10 +59,12 @@ Example: LIBRARY_PATH :: "my_library.dll" library, ok := dynlib.load_library(LIBRARY_PATH) if ! ok { + fmt.eprintln(dynlib.last_error()) return } did_unload := dynlib.unload_library(library) if ! did_unload { + fmt.eprintln(dynlib.last_error()) return } fmt.println("The library %q was successfully unloaded", LIBRARY_PATH) @@ -67,11 +77,11 @@ unload_library :: proc(library: Library) -> (did_unload: bool) { /* Loads the address of a procedure/variable from a dynamic library. -The underlying behaviour is platform specific. -On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`. +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`. On `windows` refer to `GetProcAddress`. -**Implicit Allocators** +**Implicit Allocators** `context.temp_allocator` Example: @@ -82,13 +92,101 @@ Example: LIBRARY_PATH :: "my_library.dll" library, ok := dynlib.load_library(LIBRARY_PATH) if ! ok { + fmt.eprintln(dynlib.last_error()) return } a, found_a := dynlib.symbol_address(library, "a") - if found_a do fmt.printf("The symbol %q was found at the address %v", "a", a) + if found_a { + fmt.printf("The symbol %q was found at the address %v", "a", a) + } else { + fmt.eprintln(dynlib.last_error()) + } } */ symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) #optional_ok { return _symbol_address(library, symbol) } + +/* +Scans a dynamic library for symbols matching a struct's members, assigning found procedure pointers to the corresponding entry. +Optionally takes a symbol prefix added to the struct's member name to construct the symbol looked up in the library. +Optionally also takes the struct member to assign the library handle to, `__handle` by default. + +This allows using one struct to hold library handles and symbol pointers for more than 1 dynamic library. + +Loading the same library twice unloads the previous incarnation, allowing for straightforward hot reload support. + +Returns: +* `-1, false` if the library could not be loaded. +* The number of symbols assigned on success. `ok` = true if `count` > 0 + +See doc.odin for an example. +*/ +initialize_symbols :: proc(symbol_table: ^$T, library_path: string, symbol_prefix := "", handle_field_name := "__handle") -> (count: int, ok: bool) where intrinsics.type_is_struct(T) { + assert(symbol_table != nil) + handle: Library + + if handle, ok = load_library(library_path); !ok { + return -1, false + } + + // `symbol_table` must be a struct because of the where clause, so this can't fail. + ti := runtime.type_info_base(type_info_of(T)) + s, _ := ti.variant.(runtime.Type_Info_Struct) + + // Buffer to concatenate the prefix + symbol name. + prefixed_symbol_buf: [2048]u8 = --- + + sym_ptr: rawptr + for field_name, i in s.names { + // Calculate address of struct member + field_ptr := rawptr(uintptr(rawptr(symbol_table)) + uintptr(s.offsets[i])) + + // If we've come across the struct member for the handle, store it and continue scanning for other symbols. + if field_name == handle_field_name { + // We appear to be hot reloading. Unload previous incarnation of the library. + if old_handle := (^Library)(field_ptr)^; old_handle != nil { + if ok = unload_library(old_handle); !ok { + return count, ok + } + } + (^Library)(field_ptr)^ = handle + continue + } + + // We're not the library handle, so the field needs to be a pointer type, be it a procedure pointer or an exported global. + if !(reflect.is_procedure(s.types[i]) || reflect.is_pointer(s.types[i])) { + continue + } + + // Let's look up or construct the symbol name to find in the library + prefixed_name: string + + // Do we have a symbol override tag? + if override, tag_ok := reflect.struct_tag_lookup(reflect.Struct_Tag(s.tags[i]), "dynlib"); tag_ok { + prefixed_name = string(override) + } + + // No valid symbol override tag found, fall back to `name`. + if len(prefixed_name) == 0 { + offset := copy(prefixed_symbol_buf[:], symbol_prefix) + copy(prefixed_symbol_buf[offset:], field_name) + prefixed_name = string(prefixed_symbol_buf[:len(symbol_prefix) + len(field_name)]) + } + + // Assign procedure (or global) pointer if found. + if sym_ptr, ok = symbol_address(handle, prefixed_name); ok { + (^rawptr)(field_ptr)^ = sym_ptr + count += 1 + } + } + return count, count > 0 +} + +/* +Returns an error message for the last failed procedure call. +*/ +last_error :: proc() -> string { + return _last_error() +} diff --git a/core/dynlib/lib_js.odin b/core/dynlib/lib_js.odin index ace1b0939..866874ee8 100644 --- a/core/dynlib/lib_js.odin +++ b/core/dynlib/lib_js.odin @@ -13,3 +13,7 @@ _unload_library :: proc(library: Library) -> bool { _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) { return nil, false } + +_last_error :: proc() -> string { + return "" +} diff --git a/core/dynlib/lib_unix.odin b/core/dynlib/lib_unix.odin index b0cc37e99..97f70b576 100644 --- a/core/dynlib/lib_unix.odin +++ b/core/dynlib/lib_unix.odin @@ -22,3 +22,8 @@ _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found found = ptr != nil return } + +_last_error :: proc() -> string { + err := os.dlerror() + return "unknown" if err == "" else err +} diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin index 67880df4b..9a1b5f998 100644 --- a/core/dynlib/lib_windows.odin +++ b/core/dynlib/lib_windows.odin @@ -5,6 +5,7 @@ package dynlib import win32 "core:sys/windows" import "core:strings" import "core:runtime" +import "core:reflect" _load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { // NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL @@ -27,3 +28,9 @@ _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found found = ptr != nil return } + +_last_error :: proc() -> string { + err := win32.System_Error(win32.GetLastError()) + err_msg := reflect.enum_string(err) + return "unknown" if err_msg == "" else err_msg +} diff --git a/core/encoding/endian/doc.odin b/core/encoding/endian/doc.odin index 754ffa583..8ebefd0a4 100644 --- a/core/encoding/endian/doc.odin +++ b/core/encoding/endian/doc.odin @@ -1,5 +1,5 @@ /* - Package endian implements sa simple translation between bytes and numbers with + Package endian implements a simple translation between bytes and numbers with specific endian encodings. buf: [100]u8 diff --git a/core/encoding/endian/endian.odin b/core/encoding/endian/endian.odin index 08bde3139..d70d873be 100644 --- a/core/encoding/endian/endian.odin +++ b/core/encoding/endian/endian.odin @@ -1,5 +1,8 @@ package encoding_endian +import "core:intrinsics" +import "core:math/bits" + Byte_Order :: enum u8 { Little, Big, @@ -7,147 +10,154 @@ Byte_Order :: enum u8 { PLATFORM_BYTE_ORDER :: Byte_Order.Little when ODIN_ENDIAN == .Little else Byte_Order.Big -get_u16 :: proc(b: []byte, order: Byte_Order) -> (v: u16, ok: bool) { +unchecked_get_u16le :: #force_inline proc "contextless" (b: []byte) -> u16 { + return bits.from_le_u16(intrinsics.unaligned_load((^u16)(raw_data(b)))) +} +unchecked_get_u32le :: #force_inline proc "contextless" (b: []byte) -> u32 { + return bits.from_le_u32(intrinsics.unaligned_load((^u32)(raw_data(b)))) +} +unchecked_get_u64le :: #force_inline proc "contextless" (b: []byte) -> u64 { + return bits.from_le_u64(intrinsics.unaligned_load((^u64)(raw_data(b)))) +} +unchecked_get_u16be :: #force_inline proc "contextless" (b: []byte) -> u16 { + return bits.from_be_u16(intrinsics.unaligned_load((^u16)(raw_data(b)))) +} +unchecked_get_u32be :: #force_inline proc "contextless" (b: []byte) -> u32 { + return bits.from_be_u32(intrinsics.unaligned_load((^u32)(raw_data(b)))) +} +unchecked_get_u64be :: #force_inline proc "contextless" (b: []byte) -> u64 { + return bits.from_be_u64(intrinsics.unaligned_load((^u64)(raw_data(b)))) +} + +get_u16 :: proc "contextless" (b: []byte, order: Byte_Order) -> (v: u16, ok: bool) { if len(b) < 2 { return 0, false } - #no_bounds_check if order == .Little { - v = u16(b[0]) | u16(b[1])<<8 + if order == .Little { + v = unchecked_get_u16le(b) } else { - v = u16(b[1]) | u16(b[0])<<8 + v = unchecked_get_u16be(b) } return v, true } -get_u32 :: proc(b: []byte, order: Byte_Order) -> (v: u32, ok: bool) { +get_u32 :: proc "contextless" (b: []byte, order: Byte_Order) -> (v: u32, ok: bool) { if len(b) < 4 { return 0, false } - #no_bounds_check if order == .Little { - v = u32(b[0]) | u32(b[1])<<8 | u32(b[2])<<16 | u32(b[3])<<24 + if order == .Little { + v = unchecked_get_u32le(b) } else { - v = u32(b[3]) | u32(b[2])<<8 | u32(b[1])<<16 | u32(b[0])<<24 + v = unchecked_get_u32be(b) } return v, true } - -get_u64 :: proc(b: []byte, order: Byte_Order) -> (v: u64, ok: bool) { +get_u64 :: proc "contextless" (b: []byte, order: Byte_Order) -> (v: u64, ok: bool) { if len(b) < 8 { return 0, false } - #no_bounds_check if order == .Little { - v = u64(b[0]) | u64(b[1])<<8 | u64(b[2])<<16 | u64(b[3])<<24 | - u64(b[4])<<32 | u64(b[5])<<40 | u64(b[6])<<48 | u64(b[7])<<56 + if order == .Little { + v = unchecked_get_u64le(b) } else { - v = u64(b[7]) | u64(b[6])<<8 | u64(b[5])<<16 | u64(b[4])<<24 | - u64(b[3])<<32 | u64(b[2])<<40 | u64(b[1])<<48 | u64(b[0])<<56 + v = unchecked_get_u64be(b) } return v, true } -get_i16 :: proc(b: []byte, order: Byte_Order) -> (i16, bool) { +get_i16 :: proc "contextless" (b: []byte, order: Byte_Order) -> (i16, bool) { v, ok := get_u16(b, order) return i16(v), ok } -get_i32 :: proc(b: []byte, order: Byte_Order) -> (i32, bool) { +get_i32 :: proc "contextless" (b: []byte, order: Byte_Order) -> (i32, bool) { v, ok := get_u32(b, order) return i32(v), ok } -get_i64 :: proc(b: []byte, order: Byte_Order) -> (i64, bool) { +get_i64 :: proc "contextless" (b: []byte, order: Byte_Order) -> (i64, bool) { v, ok := get_u64(b, order) return i64(v), ok } -get_f16 :: proc(b: []byte, order: Byte_Order) -> (f16, bool) { +get_f16 :: proc "contextless" (b: []byte, order: Byte_Order) -> (f16, bool) { v, ok := get_u16(b, order) return transmute(f16)v, ok } -get_f32 :: proc(b: []byte, order: Byte_Order) -> (f32, bool) { +get_f32 :: proc "contextless" (b: []byte, order: Byte_Order) -> (f32, bool) { v, ok := get_u32(b, order) return transmute(f32)v, ok } -get_f64 :: proc(b: []byte, order: Byte_Order) -> (f64, bool) { +get_f64 :: proc "contextless" (b: []byte, order: Byte_Order) -> (f64, bool) { v, ok := get_u64(b, order) return transmute(f64)v, ok } +unchecked_put_u16le :: #force_inline proc "contextless" (b: []byte, v: u16) { + intrinsics.unaligned_store((^u16)(raw_data(b)), bits.to_le_u16(v)) +} +unchecked_put_u32le :: #force_inline proc "contextless" (b: []byte, v: u32) { + intrinsics.unaligned_store((^u32)(raw_data(b)), bits.to_le_u32(v)) +} +unchecked_put_u64le :: #force_inline proc "contextless" (b: []byte, v: u64) { + intrinsics.unaligned_store((^u64)(raw_data(b)), bits.to_le_u64(v)) +} +unchecked_put_u16be :: #force_inline proc "contextless" (b: []byte, v: u16) { + intrinsics.unaligned_store((^u16)(raw_data(b)), bits.to_be_u16(v)) +} +unchecked_put_u32be :: #force_inline proc "contextless" (b: []byte, v: u32) { + intrinsics.unaligned_store((^u32)(raw_data(b)), bits.to_be_u32(v)) +} +unchecked_put_u64be :: #force_inline proc "contextless" (b: []byte, v: u64) { + intrinsics.unaligned_store((^u64)(raw_data(b)), bits.to_be_u64(v)) +} -put_u16 :: proc(b: []byte, order: Byte_Order, v: u16) -> bool { +put_u16 :: proc "contextless" (b: []byte, order: Byte_Order, v: u16) -> bool { if len(b) < 2 { return false } - #no_bounds_check if order == .Little { - b[0] = byte(v) - b[1] = byte(v >> 8) + if order == .Little { + unchecked_put_u16le(b, v) } else { - b[0] = byte(v >> 8) - b[1] = byte(v) + unchecked_put_u16be(b, v) } return true } -put_u32 :: proc(b: []byte, order: Byte_Order, v: u32) -> bool { +put_u32 :: proc "contextless" (b: []byte, order: Byte_Order, v: u32) -> bool { if len(b) < 4 { return false } - #no_bounds_check if order == .Little { - b[0] = byte(v) - b[1] = byte(v >> 8) - b[2] = byte(v >> 16) - b[3] = byte(v >> 24) + if order == .Little { + unchecked_put_u32le(b, v) } else { - b[0] = byte(v >> 24) - b[1] = byte(v >> 16) - b[2] = byte(v >> 8) - b[3] = byte(v) + unchecked_put_u32be(b, v) } return true } -put_u64 :: proc(b: []byte, order: Byte_Order, v: u64) -> bool { +put_u64 :: proc "contextless" (b: []byte, order: Byte_Order, v: u64) -> bool { if len(b) < 8 { return false } - #no_bounds_check if order == .Little { - b[0] = byte(v >> 0) - b[1] = byte(v >> 8) - b[2] = byte(v >> 16) - b[3] = byte(v >> 24) - b[4] = byte(v >> 32) - b[5] = byte(v >> 40) - b[6] = byte(v >> 48) - b[7] = byte(v >> 56) + if order == .Little { + unchecked_put_u64le(b, v) } else { - b[0] = byte(v >> 56) - b[1] = byte(v >> 48) - b[2] = byte(v >> 40) - b[3] = byte(v >> 32) - b[4] = byte(v >> 24) - b[5] = byte(v >> 16) - b[6] = byte(v >> 8) - b[7] = byte(v) + unchecked_put_u64be(b, v) } return true } -put_i16 :: proc(b: []byte, order: Byte_Order, v: i16) -> bool { +put_i16 :: proc "contextless" (b: []byte, order: Byte_Order, v: i16) -> bool { return put_u16(b, order, u16(v)) } - -put_i32 :: proc(b: []byte, order: Byte_Order, v: i32) -> bool { +put_i32 :: proc "contextless" (b: []byte, order: Byte_Order, v: i32) -> bool { return put_u32(b, order, u32(v)) } - -put_i64 :: proc(b: []byte, order: Byte_Order, v: i64) -> bool { +put_i64 :: proc "contextless" (b: []byte, order: Byte_Order, v: i64) -> bool { return put_u64(b, order, u64(v)) } - -put_f16 :: proc(b: []byte, order: Byte_Order, v: f16) -> bool { +put_f16 :: proc "contextless" (b: []byte, order: Byte_Order, v: f16) -> bool { return put_u16(b, order, transmute(u16)v) } - -put_f32 :: proc(b: []byte, order: Byte_Order, v: f32) -> bool { +put_f32 :: proc "contextless" (b: []byte, order: Byte_Order, v: f32) -> bool { return put_u32(b, order, transmute(u32)v) } - -put_f64 :: proc(b: []byte, order: Byte_Order, v: f64) -> bool { +put_f64 :: proc "contextless" (b: []byte, order: Byte_Order, v: f64) -> bool { return put_u64(b, order, transmute(u64)v) } diff --git a/core/encoding/entity/example/entity_example.odin b/core/encoding/entity/example/entity_example.odin index 6301eb263..1a6b8e9ba 100644 --- a/core/encoding/entity/example/entity_example.odin +++ b/core/encoding/entity/example/entity_example.odin @@ -47,8 +47,6 @@ _entities :: proc() { } _main :: proc() { - using fmt - options := xml.Options{ flags = { .Ignore_Unsupported, .Intern_Comments, .Unbox_CDATA, .Decode_SGML_Entities }} doc, _ := xml.parse(#load("test.html"), options) @@ -58,8 +56,6 @@ _main :: proc() { } main :: proc() { - using fmt - track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) context.allocator = mem.tracking_allocator(&track) @@ -68,9 +64,9 @@ main :: proc() { _entities() if len(track.allocation_map) > 0 { - println() + fmt.println() for _, v in track.allocation_map { - printf("%v Leaked %v bytes.\n", v.location, v.size) + fmt.printf("%v Leaked %v bytes.\n", v.location, v.size) } } } \ No newline at end of file diff --git a/core/encoding/entity/generated.odin b/core/encoding/entity/generated.odin index 9afdcae6d..3d1c02513 100644 --- a/core/encoding/entity/generated.odin +++ b/core/encoding/entity/generated.odin @@ -5,7 +5,7 @@ package unicode_entity */ /* - This file is generated from "https://www.w3.org/2003/entities/2007xml/unicode.xml". + This file is generated from "https://github.com/w3c/xml-entities/blob/gh-pages/unicode.xml". UPDATE: - Ensure the XML file was downloaded using "tests\core\download_assets.py". @@ -13,15 +13,21 @@ package unicode_entity Odin unicode generated tables: https://github.com/odin-lang/Odin/tree/master/core/encoding/entity - Copyright © 2021 World Wide Web Consortium, (Massachusetts Institute of Technology, - European Research Consortium for Informatics and Mathematics, Keio University, Beihang). + Copyright David Carlisle 1999-2023 - All Rights Reserved. + Use and distribution of this code are permitted under the terms of the + W3C Software Notice and License. + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html - This work is distributed under the W3C® Software License [1] in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - [1] http://www.w3.org/Consortium/Legal/copyright-software + + This file is a collection of information about how to map + Unicode entities to LaTeX, and various SGML/XML entity + sets (ISO and MathML/HTML). A Unicode character may be mapped + to several entities. + + Originally designed by Sebastian Rahtz in conjunction with + Barbara Beeton for the STIX project See also: LICENSE_table.md */ @@ -55,7433 +61,5025 @@ named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) { case 'A': switch name { - case "AElig": - // LATIN CAPITAL LETTER AE + case "AElig": // LATIN CAPITAL LETTER AE return rune(0xc6), true - case "AMP": - // AMPERSAND + case "AMP": // AMPERSAND return rune(0x26), true - case "Aacgr": - // GREEK CAPITAL LETTER ALPHA WITH TONOS + case "Aacgr": // GREEK CAPITAL LETTER ALPHA WITH TONOS return rune(0x0386), true - case "Aacute": - // LATIN CAPITAL LETTER A WITH ACUTE + case "Aacute": // LATIN CAPITAL LETTER A WITH ACUTE return rune(0xc1), true - case "Abreve": - // LATIN CAPITAL LETTER A WITH BREVE + case "Abreve": // LATIN CAPITAL LETTER A WITH BREVE return rune(0x0102), true - case "Acirc": - // LATIN CAPITAL LETTER A WITH CIRCUMFLEX + case "Acirc": // LATIN CAPITAL LETTER A WITH CIRCUMFLEX return rune(0xc2), true - case "Acy": - // CYRILLIC CAPITAL LETTER A + case "Acy": // CYRILLIC CAPITAL LETTER A return rune(0x0410), true - case "Afr": - // MATHEMATICAL FRAKTUR CAPITAL A + case "Afr": // MATHEMATICAL FRAKTUR CAPITAL A return rune(0x01d504), true - case "Agrave": - // LATIN CAPITAL LETTER A WITH GRAVE + case "Agr": // GREEK CAPITAL LETTER ALPHA + return rune(0x0391), true + case "Agrave": // LATIN CAPITAL LETTER A WITH GRAVE return rune(0xc0), true - case "Agr": - // GREEK CAPITAL LETTER ALPHA + case "Alpha": // GREEK CAPITAL LETTER ALPHA return rune(0x0391), true - case "Alpha": - // GREEK CAPITAL LETTER ALPHA - return rune(0x0391), true - case "Amacr": - // LATIN CAPITAL LETTER A WITH MACRON + case "Amacr": // LATIN CAPITAL LETTER A WITH MACRON return rune(0x0100), true - case "And": - // DOUBLE LOGICAL AND + case "And": // DOUBLE LOGICAL AND return rune(0x2a53), true - case "Aogon": - // LATIN CAPITAL LETTER A WITH OGONEK + case "Aogon": // LATIN CAPITAL LETTER A WITH OGONEK return rune(0x0104), true - case "Aopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL A + case "Aopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL A return rune(0x01d538), true - case "ApplyFunction": - // FUNCTION APPLICATION + case "ApplyFunction": // FUNCTION APPLICATION return rune(0x2061), true - case "Aring": - // LATIN CAPITAL LETTER A WITH RING ABOVE + case "Aring": // LATIN CAPITAL LETTER A WITH RING ABOVE return rune(0xc5), true - case "Ascr": - // MATHEMATICAL SCRIPT CAPITAL A + case "Ascr": // MATHEMATICAL SCRIPT CAPITAL A return rune(0x01d49c), true - case "Assign": - // COLON EQUALS + case "Assign": // COLON EQUALS return rune(0x2254), true - case "Ast": - // TWO ASTERISKS ALIGNED VERTICALLY + case "Ast": // TWO ASTERISKS ALIGNED VERTICALLY return rune(0x2051), true - case "Atilde": - // LATIN CAPITAL LETTER A WITH TILDE + case "Atilde": // LATIN CAPITAL LETTER A WITH TILDE return rune(0xc3), true - case "Auml": - // LATIN CAPITAL LETTER A WITH DIAERESIS + case "Auml": // LATIN CAPITAL LETTER A WITH DIAERESIS return rune(0xc4), true } case 'B': switch name { - case "Backslash": - // SET MINUS + case "Backslash": // SET MINUS return rune(0x2216), true - case "Barint": - // INTEGRAL WITH DOUBLE STROKE + case "Barint": // INTEGRAL WITH DOUBLE STROKE return rune(0x2a0e), true - case "Barv": - // SHORT DOWN TACK WITH OVERBAR + case "Barv": // SHORT DOWN TACK WITH OVERBAR return rune(0x2ae7), true - case "Barwedl": - // LOGICAL AND WITH DOUBLE OVERBAR - return rune(0x2a5e), true - case "Barwed": - // PERSPECTIVE + case "Barwed": // PERSPECTIVE return rune(0x2306), true - case "Bcy": - // CYRILLIC CAPITAL LETTER BE + case "Barwedl": // LOGICAL AND WITH DOUBLE OVERBAR + return rune(0x2a5e), true + case "Bcy": // CYRILLIC CAPITAL LETTER BE return rune(0x0411), true - case "Because": - // BECAUSE + case "Because": // BECAUSE return rune(0x2235), true - case "Bernoullis": - // SCRIPT CAPITAL B + case "Bernoullis": // SCRIPT CAPITAL B return rune(0x212c), true - case "Beta": - // GREEK CAPITAL LETTER BETA + case "Beta": // GREEK CAPITAL LETTER BETA return rune(0x0392), true - case "Bfr": - // MATHEMATICAL FRAKTUR CAPITAL B + case "Bfr": // MATHEMATICAL FRAKTUR CAPITAL B return rune(0x01d505), true - case "Bgr": - // GREEK CAPITAL LETTER BETA + case "Bgr": // GREEK CAPITAL LETTER BETA return rune(0x0392), true - case "Bopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL B + case "Bopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL B return rune(0x01d539), true - case "Breve": - // BREVE + case "Breve": // BREVE return rune(0x02d8), true - case "Bscr": - // SCRIPT CAPITAL B + case "Bscr": // SCRIPT CAPITAL B return rune(0x212c), true - case "Bumpeq": - // GEOMETRICALLY EQUIVALENT TO + case "Bumpeq": // GEOMETRICALLY EQUIVALENT TO return rune(0x224e), true - case "Bvert": - // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL + case "Bvert": // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL return rune(0x2506), true } case 'C': switch name { - case "CHcy": - // CYRILLIC CAPITAL LETTER CHE + case "CHcy": // CYRILLIC CAPITAL LETTER CHE return rune(0x0427), true - case "COPY": - // COPYRIGHT SIGN + case "COPY": // COPYRIGHT SIGN return rune(0xa9), true - case "Cacute": - // LATIN CAPITAL LETTER C WITH ACUTE + case "Cacute": // LATIN CAPITAL LETTER C WITH ACUTE return rune(0x0106), true - case "CapitalDifferentialD": - // DOUBLE-STRUCK ITALIC CAPITAL D - return rune(0x2145), true - case "Cap": - // DOUBLE INTERSECTION + case "Cap": // DOUBLE INTERSECTION return rune(0x22d2), true - case "Cayleys": - // BLACK-LETTER CAPITAL C + case "CapitalDifferentialD": // DOUBLE-STRUCK ITALIC CAPITAL D + return rune(0x2145), true + case "Cayleys": // BLACK-LETTER CAPITAL C return rune(0x212d), true - case "Ccaron": - // LATIN CAPITAL LETTER C WITH CARON + case "Ccaron": // LATIN CAPITAL LETTER C WITH CARON return rune(0x010c), true - case "Ccedil": - // LATIN CAPITAL LETTER C WITH CEDILLA + case "Ccedil": // LATIN CAPITAL LETTER C WITH CEDILLA return rune(0xc7), true - case "Ccirc": - // LATIN CAPITAL LETTER C WITH CIRCUMFLEX + case "Ccirc": // LATIN CAPITAL LETTER C WITH CIRCUMFLEX return rune(0x0108), true - case "Cconint": - // VOLUME INTEGRAL + case "Cconint": // VOLUME INTEGRAL return rune(0x2230), true - case "Cdot": - // LATIN CAPITAL LETTER C WITH DOT ABOVE + case "Cdot": // LATIN CAPITAL LETTER C WITH DOT ABOVE return rune(0x010a), true - case "Cedilla": - // CEDILLA + case "Cedilla": // CEDILLA return rune(0xb8), true - case "CenterDot": - // MIDDLE DOT + case "CenterDot": // MIDDLE DOT return rune(0xb7), true - case "Cfr": - // BLACK-LETTER CAPITAL C + case "Cfr": // BLACK-LETTER CAPITAL C return rune(0x212d), true - case "Chi": - // GREEK CAPITAL LETTER CHI + case "Chi": // GREEK CAPITAL LETTER CHI return rune(0x03a7), true - case "CircleDot": - // CIRCLED DOT OPERATOR + case "CircleDot": // CIRCLED DOT OPERATOR return rune(0x2299), true - case "CircleMinus": - // CIRCLED MINUS + case "CircleMinus": // CIRCLED MINUS return rune(0x2296), true - case "CirclePlus": - // CIRCLED PLUS + case "CirclePlus": // CIRCLED PLUS return rune(0x2295), true - case "CircleTimes": - // CIRCLED TIMES + case "CircleTimes": // CIRCLED TIMES return rune(0x2297), true - case "ClockwiseContourIntegral": - // CLOCKWISE CONTOUR INTEGRAL + case "ClockwiseContourIntegral": // CLOCKWISE CONTOUR INTEGRAL return rune(0x2232), true - case "CloseCurlyDoubleQuote": - // RIGHT DOUBLE QUOTATION MARK + case "CloseCurlyDoubleQuote": // RIGHT DOUBLE QUOTATION MARK return rune(0x201d), true - case "CloseCurlyQuote": - // RIGHT SINGLE QUOTATION MARK + case "CloseCurlyQuote": // RIGHT SINGLE QUOTATION MARK return rune(0x2019), true - case "Colon": - // PROPORTION + case "Colon": // PROPORTION return rune(0x2237), true - case "Colone": - // DOUBLE COLON EQUAL + case "Colone": // DOUBLE COLON EQUAL return rune(0x2a74), true - case "Congruent": - // IDENTICAL TO + case "Congruent": // IDENTICAL TO return rune(0x2261), true - case "Conint": - // SURFACE INTEGRAL + case "Conint": // SURFACE INTEGRAL return rune(0x222f), true - case "ContourIntegral": - // CONTOUR INTEGRAL + case "ContourIntegral": // CONTOUR INTEGRAL return rune(0x222e), true - case "Copf": - // DOUBLE-STRUCK CAPITAL C + case "Copf": // DOUBLE-STRUCK CAPITAL C return rune(0x2102), true - case "Coproduct": - // N-ARY COPRODUCT + case "Coproduct": // N-ARY COPRODUCT return rune(0x2210), true - case "CounterClockwiseContourIntegral": - // ANTICLOCKWISE CONTOUR INTEGRAL + case "CounterClockwiseContourIntegral": // ANTICLOCKWISE CONTOUR INTEGRAL return rune(0x2233), true - case "Cross": - // VECTOR OR CROSS PRODUCT + case "Cross": // VECTOR OR CROSS PRODUCT return rune(0x2a2f), true - case "Cscr": - // MATHEMATICAL SCRIPT CAPITAL C + case "Cscr": // MATHEMATICAL SCRIPT CAPITAL C return rune(0x01d49e), true - case "CupCap": - // EQUIVALENT TO - return rune(0x224d), true - case "Cup": - // DOUBLE UNION + case "Cup": // DOUBLE UNION return rune(0x22d3), true + case "CupCap": // EQUIVALENT TO + return rune(0x224d), true } case 'D': switch name { - case "DD": - // DOUBLE-STRUCK ITALIC CAPITAL D + case "DD": // DOUBLE-STRUCK ITALIC CAPITAL D return rune(0x2145), true - case "DDotrahd": - // RIGHTWARDS ARROW WITH DOTTED STEM + case "DDotrahd": // RIGHTWARDS ARROW WITH DOTTED STEM return rune(0x2911), true - case "DJcy": - // CYRILLIC CAPITAL LETTER DJE + case "DJcy": // CYRILLIC CAPITAL LETTER DJE return rune(0x0402), true - case "DScy": - // CYRILLIC CAPITAL LETTER DZE + case "DScy": // CYRILLIC CAPITAL LETTER DZE return rune(0x0405), true - case "DZcy": - // CYRILLIC CAPITAL LETTER DZHE + case "DZcy": // CYRILLIC CAPITAL LETTER DZHE return rune(0x040f), true - case "Dagger": - // DOUBLE DAGGER + case "Dagger": // DOUBLE DAGGER return rune(0x2021), true - case "Darr": - // DOWNWARDS TWO HEADED ARROW + case "Darr": // DOWNWARDS TWO HEADED ARROW return rune(0x21a1), true - case "Dashv": - // VERTICAL BAR DOUBLE LEFT TURNSTILE + case "Dashv": // VERTICAL BAR DOUBLE LEFT TURNSTILE return rune(0x2ae4), true - case "Dcaron": - // LATIN CAPITAL LETTER D WITH CARON + case "Dcaron": // LATIN CAPITAL LETTER D WITH CARON return rune(0x010e), true - case "Dcy": - // CYRILLIC CAPITAL LETTER DE + case "Dcy": // CYRILLIC CAPITAL LETTER DE return rune(0x0414), true - case "Del": - // NABLA + case "Del": // NABLA return rune(0x2207), true - case "Delta": - // GREEK CAPITAL LETTER DELTA + case "Delta": // GREEK CAPITAL LETTER DELTA return rune(0x0394), true - case "Dfr": - // MATHEMATICAL FRAKTUR CAPITAL D + case "Dfr": // MATHEMATICAL FRAKTUR CAPITAL D return rune(0x01d507), true - case "Dgr": - // GREEK CAPITAL LETTER DELTA + case "Dgr": // GREEK CAPITAL LETTER DELTA return rune(0x0394), true - case "DiacriticalAcute": - // ACUTE ACCENT + case "DiacriticalAcute": // ACUTE ACCENT return rune(0xb4), true - case "DiacriticalDot": - // DOT ABOVE + case "DiacriticalDot": // DOT ABOVE return rune(0x02d9), true - case "DiacriticalDoubleAcute": - // DOUBLE ACUTE ACCENT + case "DiacriticalDoubleAcute": // DOUBLE ACUTE ACCENT return rune(0x02dd), true - case "DiacriticalGrave": - // GRAVE ACCENT + case "DiacriticalGrave": // GRAVE ACCENT return rune(0x60), true - case "DiacriticalTilde": - // SMALL TILDE + case "DiacriticalTilde": // SMALL TILDE return rune(0x02dc), true - case "Diamond": - // DIAMOND OPERATOR + case "Diamond": // DIAMOND OPERATOR return rune(0x22c4), true - case "DifferentialD": - // DOUBLE-STRUCK ITALIC SMALL D + case "DifferentialD": // DOUBLE-STRUCK ITALIC SMALL D return rune(0x2146), true - case "Dopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL D + case "Dopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL D return rune(0x01d53b), true - case "Dot": - // DIAERESIS + case "Dot": // DIAERESIS return rune(0xa8), true - case "DotDot": - // COMBINING FOUR DOTS ABOVE + case "DotDot": // COMBINING FOUR DOTS ABOVE return rune(0x20dc), true - case "DotEqual": - // APPROACHES THE LIMIT + case "DotEqual": // APPROACHES THE LIMIT return rune(0x2250), true - case "DoubleContourIntegral": - // SURFACE INTEGRAL + case "DoubleContourIntegral": // SURFACE INTEGRAL return rune(0x222f), true - case "DoubleDot": - // DIAERESIS + case "DoubleDot": // DIAERESIS return rune(0xa8), true - case "DoubleDownArrow": - // DOWNWARDS DOUBLE ARROW + case "DoubleDownArrow": // DOWNWARDS DOUBLE ARROW return rune(0x21d3), true - case "DoubleLeftArrow": - // LEFTWARDS DOUBLE ARROW + case "DoubleLeftArrow": // LEFTWARDS DOUBLE ARROW return rune(0x21d0), true - case "DoubleLeftRightArrow": - // LEFT RIGHT DOUBLE ARROW + case "DoubleLeftRightArrow": // LEFT RIGHT DOUBLE ARROW return rune(0x21d4), true - case "DoubleLeftTee": - // VERTICAL BAR DOUBLE LEFT TURNSTILE + case "DoubleLeftTee": // VERTICAL BAR DOUBLE LEFT TURNSTILE return rune(0x2ae4), true - case "DoubleLongLeftArrow": - // LONG LEFTWARDS DOUBLE ARROW + case "DoubleLongLeftArrow": // LONG LEFTWARDS DOUBLE ARROW return rune(0x27f8), true - case "DoubleLongLeftRightArrow": - // LONG LEFT RIGHT DOUBLE ARROW + case "DoubleLongLeftRightArrow": // LONG LEFT RIGHT DOUBLE ARROW return rune(0x27fa), true - case "DoubleLongRightArrow": - // LONG RIGHTWARDS DOUBLE ARROW + case "DoubleLongRightArrow": // LONG RIGHTWARDS DOUBLE ARROW return rune(0x27f9), true - case "DoubleRightArrow": - // RIGHTWARDS DOUBLE ARROW + case "DoubleRightArrow": // RIGHTWARDS DOUBLE ARROW return rune(0x21d2), true - case "DoubleRightTee": - // TRUE + case "DoubleRightTee": // TRUE return rune(0x22a8), true - case "DoubleUpArrow": - // UPWARDS DOUBLE ARROW + case "DoubleUpArrow": // UPWARDS DOUBLE ARROW return rune(0x21d1), true - case "DoubleUpDownArrow": - // UP DOWN DOUBLE ARROW + case "DoubleUpDownArrow": // UP DOWN DOUBLE ARROW return rune(0x21d5), true - case "DoubleVerticalBar": - // PARALLEL TO + case "DoubleVerticalBar": // PARALLEL TO return rune(0x2225), true - case "DownArrowUpArrow": - // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW - return rune(0x21f5), true - case "DownArrow": - // DOWNWARDS ARROW + case "DownArrow": // DOWNWARDS ARROW return rune(0x2193), true - case "DownArrowBar": - // DOWNWARDS ARROW TO BAR + case "DownArrowBar": // DOWNWARDS ARROW TO BAR return rune(0x2913), true - case "DownBreve": - // COMBINING INVERTED BREVE + case "DownArrowUpArrow": // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW + return rune(0x21f5), true + case "DownBreve": // COMBINING INVERTED BREVE return rune(0x0311), true - case "DownLeftRightVector": - // LEFT BARB DOWN RIGHT BARB DOWN HARPOON + case "DownLeftRightVector": // LEFT BARB DOWN RIGHT BARB DOWN HARPOON return rune(0x2950), true - case "DownLeftTeeVector": - // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR + case "DownLeftTeeVector": // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR return rune(0x295e), true - case "DownLeftVector": - // LEFTWARDS HARPOON WITH BARB DOWNWARDS + case "DownLeftVector": // LEFTWARDS HARPOON WITH BARB DOWNWARDS return rune(0x21bd), true - case "DownLeftVectorBar": - // LEFTWARDS HARPOON WITH BARB DOWN TO BAR + case "DownLeftVectorBar": // LEFTWARDS HARPOON WITH BARB DOWN TO BAR return rune(0x2956), true - case "DownRightTeeVector": - // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR + case "DownRightTeeVector": // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR return rune(0x295f), true - case "DownRightVector": - // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + case "DownRightVector": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS return rune(0x21c1), true - case "DownRightVectorBar": - // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR + case "DownRightVectorBar": // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR return rune(0x2957), true - case "DownTeeArrow": - // DOWNWARDS ARROW FROM BAR - return rune(0x21a7), true - case "DownTee": - // DOWN TACK + case "DownTee": // DOWN TACK return rune(0x22a4), true - case "Downarrow": - // DOWNWARDS DOUBLE ARROW + case "DownTeeArrow": // DOWNWARDS ARROW FROM BAR + return rune(0x21a7), true + case "Downarrow": // DOWNWARDS DOUBLE ARROW return rune(0x21d3), true - case "Dscr": - // MATHEMATICAL SCRIPT CAPITAL D + case "Dscr": // MATHEMATICAL SCRIPT CAPITAL D return rune(0x01d49f), true - case "Dstrok": - // LATIN CAPITAL LETTER D WITH STROKE + case "Dstrok": // LATIN CAPITAL LETTER D WITH STROKE return rune(0x0110), true } case 'E': switch name { - case "EEacgr": - // GREEK CAPITAL LETTER ETA WITH TONOS + case "EEacgr": // GREEK CAPITAL LETTER ETA WITH TONOS return rune(0x0389), true - case "EEgr": - // GREEK CAPITAL LETTER ETA + case "EEgr": // GREEK CAPITAL LETTER ETA return rune(0x0397), true - case "ENG": - // LATIN CAPITAL LETTER ENG + case "ENG": // LATIN CAPITAL LETTER ENG return rune(0x014a), true - case "ETH": - // LATIN CAPITAL LETTER ETH + case "ETH": // LATIN CAPITAL LETTER ETH return rune(0xd0), true - case "Eacgr": - // GREEK CAPITAL LETTER EPSILON WITH TONOS + case "Eacgr": // GREEK CAPITAL LETTER EPSILON WITH TONOS return rune(0x0388), true - case "Eacute": - // LATIN CAPITAL LETTER E WITH ACUTE + case "Eacute": // LATIN CAPITAL LETTER E WITH ACUTE return rune(0xc9), true - case "Ecaron": - // LATIN CAPITAL LETTER E WITH CARON + case "Ecaron": // LATIN CAPITAL LETTER E WITH CARON return rune(0x011a), true - case "Ecirc": - // LATIN CAPITAL LETTER E WITH CIRCUMFLEX + case "Ecirc": // LATIN CAPITAL LETTER E WITH CIRCUMFLEX return rune(0xca), true - case "Ecy": - // CYRILLIC CAPITAL LETTER E + case "Ecy": // CYRILLIC CAPITAL LETTER E return rune(0x042d), true - case "Edot": - // LATIN CAPITAL LETTER E WITH DOT ABOVE + case "Edot": // LATIN CAPITAL LETTER E WITH DOT ABOVE return rune(0x0116), true - case "Efr": - // MATHEMATICAL FRAKTUR CAPITAL E + case "Efr": // MATHEMATICAL FRAKTUR CAPITAL E return rune(0x01d508), true - case "Egrave": - // LATIN CAPITAL LETTER E WITH GRAVE + case "Egr": // GREEK CAPITAL LETTER EPSILON + return rune(0x0395), true + case "Egrave": // LATIN CAPITAL LETTER E WITH GRAVE return rune(0xc8), true - case "Egr": - // GREEK CAPITAL LETTER EPSILON - return rune(0x0395), true - case "Element": - // ELEMENT OF + case "Element": // ELEMENT OF return rune(0x2208), true - case "Emacr": - // LATIN CAPITAL LETTER E WITH MACRON + case "Emacr": // LATIN CAPITAL LETTER E WITH MACRON return rune(0x0112), true - case "EmptySmallSquare": - // WHITE MEDIUM SQUARE + case "EmptySmallSquare": // WHITE MEDIUM SQUARE return rune(0x25fb), true - case "EmptyVerySmallSquare": - // WHITE SMALL SQUARE + case "EmptyVerySmallSquare": // WHITE SMALL SQUARE return rune(0x25ab), true - case "Eogon": - // LATIN CAPITAL LETTER E WITH OGONEK + case "Eogon": // LATIN CAPITAL LETTER E WITH OGONEK return rune(0x0118), true - case "Eopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL E + case "Eopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL E return rune(0x01d53c), true - case "Epsilon": - // GREEK CAPITAL LETTER EPSILON + case "Epsilon": // GREEK CAPITAL LETTER EPSILON return rune(0x0395), true - case "EqualTilde": - // MINUS TILDE - return rune(0x2242), true - case "Equal": - // TWO CONSECUTIVE EQUALS SIGNS + case "Equal": // TWO CONSECUTIVE EQUALS SIGNS return rune(0x2a75), true - case "Equilibrium": - // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + case "EqualTilde": // MINUS TILDE + return rune(0x2242), true + case "Equilibrium": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON return rune(0x21cc), true - case "Escr": - // SCRIPT CAPITAL E + case "Escr": // SCRIPT CAPITAL E return rune(0x2130), true - case "Esim": - // EQUALS SIGN ABOVE TILDE OPERATOR + case "Esim": // EQUALS SIGN ABOVE TILDE OPERATOR return rune(0x2a73), true - case "Eta": - // GREEK CAPITAL LETTER ETA + case "Eta": // GREEK CAPITAL LETTER ETA return rune(0x0397), true - case "Euml": - // LATIN CAPITAL LETTER E WITH DIAERESIS + case "Euml": // LATIN CAPITAL LETTER E WITH DIAERESIS return rune(0xcb), true - case "Exists": - // THERE EXISTS + case "Exists": // THERE EXISTS return rune(0x2203), true - case "ExponentialE": - // DOUBLE-STRUCK ITALIC SMALL E + case "ExponentialE": // DOUBLE-STRUCK ITALIC SMALL E return rune(0x2147), true } case 'F': switch name { - case "Fcy": - // CYRILLIC CAPITAL LETTER EF + case "Fcy": // CYRILLIC CAPITAL LETTER EF return rune(0x0424), true - case "Ffr": - // MATHEMATICAL FRAKTUR CAPITAL F + case "Ffr": // MATHEMATICAL FRAKTUR CAPITAL F return rune(0x01d509), true - case "FilledSmallSquare": - // BLACK MEDIUM SQUARE + case "FilledSmallSquare": // BLACK MEDIUM SQUARE return rune(0x25fc), true - case "FilledVerySmallSquare": - // BLACK SMALL SQUARE + case "FilledVerySmallSquare": // BLACK SMALL SQUARE return rune(0x25aa), true - case "Fopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL F + case "Fopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL F return rune(0x01d53d), true - case "ForAll": - // FOR ALL + case "ForAll": // FOR ALL return rune(0x2200), true - case "Fouriertrf": - // SCRIPT CAPITAL F + case "Fouriertrf": // SCRIPT CAPITAL F return rune(0x2131), true - case "Fscr": - // SCRIPT CAPITAL F + case "Fscr": // SCRIPT CAPITAL F return rune(0x2131), true } case 'G': switch name { - case "GJcy": - // CYRILLIC CAPITAL LETTER GJE + case "GJcy": // CYRILLIC CAPITAL LETTER GJE return rune(0x0403), true - case "GT": - // GREATER-THAN SIGN + case "GT": // GREATER-THAN SIGN return rune(0x3e), true - case "Game": - // TURNED SANS-SERIF CAPITAL G + case "Game": // TURNED SANS-SERIF CAPITAL G return rune(0x2141), true - case "Gamma": - // GREEK CAPITAL LETTER GAMMA + case "Gamma": // GREEK CAPITAL LETTER GAMMA return rune(0x0393), true - case "Gammad": - // GREEK LETTER DIGAMMA + case "Gammad": // GREEK LETTER DIGAMMA return rune(0x03dc), true - case "Gbreve": - // LATIN CAPITAL LETTER G WITH BREVE + case "Gbreve": // LATIN CAPITAL LETTER G WITH BREVE return rune(0x011e), true - case "Gcedil": - // LATIN CAPITAL LETTER G WITH CEDILLA + case "Gcedil": // LATIN CAPITAL LETTER G WITH CEDILLA return rune(0x0122), true - case "Gcirc": - // LATIN CAPITAL LETTER G WITH CIRCUMFLEX + case "Gcirc": // LATIN CAPITAL LETTER G WITH CIRCUMFLEX return rune(0x011c), true - case "Gcy": - // CYRILLIC CAPITAL LETTER GHE + case "Gcy": // CYRILLIC CAPITAL LETTER GHE return rune(0x0413), true - case "Gdot": - // LATIN CAPITAL LETTER G WITH DOT ABOVE + case "Gdot": // LATIN CAPITAL LETTER G WITH DOT ABOVE return rune(0x0120), true - case "Gfr": - // MATHEMATICAL FRAKTUR CAPITAL G + case "Gfr": // MATHEMATICAL FRAKTUR CAPITAL G return rune(0x01d50a), true - case "Ggr": - // GREEK CAPITAL LETTER GAMMA - return rune(0x0393), true - case "Gg": - // VERY MUCH GREATER-THAN + case "Gg": // VERY MUCH GREATER-THAN return rune(0x22d9), true - case "Gopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL G + case "Ggr": // GREEK CAPITAL LETTER GAMMA + return rune(0x0393), true + case "Gopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL G return rune(0x01d53e), true - case "GreaterEqual": - // GREATER-THAN OR EQUAL TO + case "GreaterEqual": // GREATER-THAN OR EQUAL TO return rune(0x2265), true - case "GreaterEqualLess": - // GREATER-THAN EQUAL TO OR LESS-THAN + case "GreaterEqualLess": // GREATER-THAN EQUAL TO OR LESS-THAN return rune(0x22db), true - case "GreaterFullEqual": - // GREATER-THAN OVER EQUAL TO + case "GreaterFullEqual": // GREATER-THAN OVER EQUAL TO return rune(0x2267), true - case "GreaterGreater": - // DOUBLE NESTED GREATER-THAN + case "GreaterGreater": // DOUBLE NESTED GREATER-THAN return rune(0x2aa2), true - case "GreaterLess": - // GREATER-THAN OR LESS-THAN + case "GreaterLess": // GREATER-THAN OR LESS-THAN return rune(0x2277), true - case "GreaterSlantEqual": - // GREATER-THAN OR SLANTED EQUAL TO + case "GreaterSlantEqual": // GREATER-THAN OR SLANTED EQUAL TO return rune(0x2a7e), true - case "GreaterTilde": - // GREATER-THAN OR EQUIVALENT TO + case "GreaterTilde": // GREATER-THAN OR EQUIVALENT TO return rune(0x2273), true - case "Gscr": - // MATHEMATICAL SCRIPT CAPITAL G + case "Gscr": // MATHEMATICAL SCRIPT CAPITAL G return rune(0x01d4a2), true - case "Gt": - // MUCH GREATER-THAN + case "Gt": // MUCH GREATER-THAN return rune(0x226b), true } case 'H': switch name { - case "HARDcy": - // CYRILLIC CAPITAL LETTER HARD SIGN + case "HARDcy": // CYRILLIC CAPITAL LETTER HARD SIGN return rune(0x042a), true - case "Hacek": - // CARON + case "Hacek": // CARON return rune(0x02c7), true - case "Hat": - // CIRCUMFLEX ACCENT + case "Hat": // CIRCUMFLEX ACCENT return rune(0x5e), true - case "Hcirc": - // LATIN CAPITAL LETTER H WITH CIRCUMFLEX + case "Hcirc": // LATIN CAPITAL LETTER H WITH CIRCUMFLEX return rune(0x0124), true - case "Hfr": - // BLACK-LETTER CAPITAL H + case "Hfr": // BLACK-LETTER CAPITAL H return rune(0x210c), true - case "HilbertSpace": - // SCRIPT CAPITAL H + case "HilbertSpace": // SCRIPT CAPITAL H return rune(0x210b), true - case "Hopf": - // DOUBLE-STRUCK CAPITAL H + case "Hopf": // DOUBLE-STRUCK CAPITAL H return rune(0x210d), true - case "HorizontalLine": - // BOX DRAWINGS LIGHT HORIZONTAL + case "HorizontalLine": // BOX DRAWINGS LIGHT HORIZONTAL return rune(0x2500), true - case "Hscr": - // SCRIPT CAPITAL H + case "Hscr": // SCRIPT CAPITAL H return rune(0x210b), true - case "Hstrok": - // LATIN CAPITAL LETTER H WITH STROKE + case "Hstrok": // LATIN CAPITAL LETTER H WITH STROKE return rune(0x0126), true - case "HumpDownHump": - // GEOMETRICALLY EQUIVALENT TO + case "HumpDownHump": // GEOMETRICALLY EQUIVALENT TO return rune(0x224e), true - case "HumpEqual": - // DIFFERENCE BETWEEN + case "HumpEqual": // DIFFERENCE BETWEEN return rune(0x224f), true } case 'I': switch name { - case "IEcy": - // CYRILLIC CAPITAL LETTER IE + case "IEcy": // CYRILLIC CAPITAL LETTER IE return rune(0x0415), true - case "IJlig": - // LATIN CAPITAL LIGATURE IJ + case "IJlig": // LATIN CAPITAL LIGATURE IJ return rune(0x0132), true - case "IOcy": - // CYRILLIC CAPITAL LETTER IO + case "IOcy": // CYRILLIC CAPITAL LETTER IO return rune(0x0401), true - case "Iacgr": - // GREEK CAPITAL LETTER IOTA WITH TONOS + case "Iacgr": // GREEK CAPITAL LETTER IOTA WITH TONOS return rune(0x038a), true - case "Iacute": - // LATIN CAPITAL LETTER I WITH ACUTE + case "Iacute": // LATIN CAPITAL LETTER I WITH ACUTE return rune(0xcd), true - case "Icirc": - // LATIN CAPITAL LETTER I WITH CIRCUMFLEX + case "Icirc": // LATIN CAPITAL LETTER I WITH CIRCUMFLEX return rune(0xce), true - case "Icy": - // CYRILLIC CAPITAL LETTER I + case "Icy": // CYRILLIC CAPITAL LETTER I return rune(0x0418), true - case "Idigr": - // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + case "Idigr": // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA return rune(0x03aa), true - case "Idot": - // LATIN CAPITAL LETTER I WITH DOT ABOVE + case "Idot": // LATIN CAPITAL LETTER I WITH DOT ABOVE return rune(0x0130), true - case "Ifr": - // BLACK-LETTER CAPITAL I + case "Ifr": // BLACK-LETTER CAPITAL I return rune(0x2111), true - case "Igrave": - // LATIN CAPITAL LETTER I WITH GRAVE + case "Igr": // GREEK CAPITAL LETTER IOTA + return rune(0x0399), true + case "Igrave": // LATIN CAPITAL LETTER I WITH GRAVE return rune(0xcc), true - case "Igr": - // GREEK CAPITAL LETTER IOTA - return rune(0x0399), true - case "Imacr": - // LATIN CAPITAL LETTER I WITH MACRON - return rune(0x012a), true - case "ImaginaryI": - // DOUBLE-STRUCK ITALIC SMALL I - return rune(0x2148), true - case "Implies": - // RIGHTWARDS DOUBLE ARROW - return rune(0x21d2), true - case "Im": - // BLACK-LETTER CAPITAL I + case "Im": // BLACK-LETTER CAPITAL I return rune(0x2111), true - case "Integral": - // INTEGRAL - return rune(0x222b), true - case "Int": - // DOUBLE INTEGRAL + case "Imacr": // LATIN CAPITAL LETTER I WITH MACRON + return rune(0x012a), true + case "ImaginaryI": // DOUBLE-STRUCK ITALIC SMALL I + return rune(0x2148), true + case "Implies": // RIGHTWARDS DOUBLE ARROW + return rune(0x21d2), true + case "Int": // DOUBLE INTEGRAL return rune(0x222c), true - case "Intersection": - // N-ARY INTERSECTION + case "Integral": // INTEGRAL + return rune(0x222b), true + case "Intersection": // N-ARY INTERSECTION return rune(0x22c2), true - case "InvisibleComma": - // INVISIBLE SEPARATOR + case "InvisibleComma": // INVISIBLE SEPARATOR return rune(0x2063), true - case "InvisibleTimes": - // INVISIBLE TIMES + case "InvisibleTimes": // INVISIBLE TIMES return rune(0x2062), true - case "Iogon": - // LATIN CAPITAL LETTER I WITH OGONEK + case "Iogon": // LATIN CAPITAL LETTER I WITH OGONEK return rune(0x012e), true - case "Iopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL I + case "Iopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL I return rune(0x01d540), true - case "Iota": - // GREEK CAPITAL LETTER IOTA + case "Iota": // GREEK CAPITAL LETTER IOTA return rune(0x0399), true - case "Iscr": - // SCRIPT CAPITAL I + case "Iscr": // SCRIPT CAPITAL I return rune(0x2110), true - case "Itilde": - // LATIN CAPITAL LETTER I WITH TILDE + case "Itilde": // LATIN CAPITAL LETTER I WITH TILDE return rune(0x0128), true - case "Iukcy": - // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + case "Iukcy": // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I return rune(0x0406), true - case "Iuml": - // LATIN CAPITAL LETTER I WITH DIAERESIS + case "Iuml": // LATIN CAPITAL LETTER I WITH DIAERESIS return rune(0xcf), true } case 'J': switch name { - case "Jcirc": - // LATIN CAPITAL LETTER J WITH CIRCUMFLEX + case "Jcirc": // LATIN CAPITAL LETTER J WITH CIRCUMFLEX return rune(0x0134), true - case "Jcy": - // CYRILLIC CAPITAL LETTER SHORT I + case "Jcy": // CYRILLIC CAPITAL LETTER SHORT I return rune(0x0419), true - case "Jfr": - // MATHEMATICAL FRAKTUR CAPITAL J + case "Jfr": // MATHEMATICAL FRAKTUR CAPITAL J return rune(0x01d50d), true - case "Jopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL J + case "Jopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL J return rune(0x01d541), true - case "Jscr": - // MATHEMATICAL SCRIPT CAPITAL J + case "Jscr": // MATHEMATICAL SCRIPT CAPITAL J return rune(0x01d4a5), true - case "Jsercy": - // CYRILLIC CAPITAL LETTER JE + case "Jsercy": // CYRILLIC CAPITAL LETTER JE return rune(0x0408), true - case "Jukcy": - // CYRILLIC CAPITAL LETTER UKRAINIAN IE + case "Jukcy": // CYRILLIC CAPITAL LETTER UKRAINIAN IE return rune(0x0404), true } case 'K': switch name { - case "KHcy": - // CYRILLIC CAPITAL LETTER HA + case "KHcy": // CYRILLIC CAPITAL LETTER HA return rune(0x0425), true - case "KHgr": - // GREEK CAPITAL LETTER CHI + case "KHgr": // GREEK CAPITAL LETTER CHI return rune(0x03a7), true - case "KJcy": - // CYRILLIC CAPITAL LETTER KJE + case "KJcy": // CYRILLIC CAPITAL LETTER KJE return rune(0x040c), true - case "Kappa": - // GREEK CAPITAL LETTER KAPPA + case "Kappa": // GREEK CAPITAL LETTER KAPPA return rune(0x039a), true - case "Kcedil": - // LATIN CAPITAL LETTER K WITH CEDILLA + case "Kcedil": // LATIN CAPITAL LETTER K WITH CEDILLA return rune(0x0136), true - case "Kcy": - // CYRILLIC CAPITAL LETTER KA + case "Kcy": // CYRILLIC CAPITAL LETTER KA return rune(0x041a), true - case "Kfr": - // MATHEMATICAL FRAKTUR CAPITAL K + case "Kfr": // MATHEMATICAL FRAKTUR CAPITAL K return rune(0x01d50e), true - case "Kgr": - // GREEK CAPITAL LETTER KAPPA + case "Kgr": // GREEK CAPITAL LETTER KAPPA return rune(0x039a), true - case "Kopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL K + case "Kopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL K return rune(0x01d542), true - case "Kscr": - // MATHEMATICAL SCRIPT CAPITAL K + case "Kscr": // MATHEMATICAL SCRIPT CAPITAL K return rune(0x01d4a6), true } case 'L': switch name { - case "LJcy": - // CYRILLIC CAPITAL LETTER LJE + case "LJcy": // CYRILLIC CAPITAL LETTER LJE return rune(0x0409), true - case "LT": - // LESS-THAN SIGN + case "LT": // LESS-THAN SIGN return rune(0x3c), true - case "Lacute": - // LATIN CAPITAL LETTER L WITH ACUTE + case "Lacute": // LATIN CAPITAL LETTER L WITH ACUTE return rune(0x0139), true - case "Lambda": - // GREEK CAPITAL LETTER LAMDA + case "Lambda": // GREEK CAPITAL LETTER LAMDA return rune(0x039b), true - case "Lang": - // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET + case "Lang": // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET return rune(0x27ea), true - case "Laplacetrf": - // SCRIPT CAPITAL L + case "Laplacetrf": // SCRIPT CAPITAL L return rune(0x2112), true - case "Larr": - // LEFTWARDS TWO HEADED ARROW + case "Larr": // LEFTWARDS TWO HEADED ARROW return rune(0x219e), true - case "Lcaron": - // LATIN CAPITAL LETTER L WITH CARON + case "Lcaron": // LATIN CAPITAL LETTER L WITH CARON return rune(0x013d), true - case "Lcedil": - // LATIN CAPITAL LETTER L WITH CEDILLA + case "Lcedil": // LATIN CAPITAL LETTER L WITH CEDILLA return rune(0x013b), true - case "Lcy": - // CYRILLIC CAPITAL LETTER EL + case "Lcy": // CYRILLIC CAPITAL LETTER EL return rune(0x041b), true - case "LeftAngleBracket": - // MATHEMATICAL LEFT ANGLE BRACKET + case "LeftAngleBracket": // MATHEMATICAL LEFT ANGLE BRACKET return rune(0x27e8), true - case "LeftArrowBar": - // LEFTWARDS ARROW TO BAR - return rune(0x21e4), true - case "LeftArrowRightArrow": - // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true - case "LeftArrow": - // LEFTWARDS ARROW + case "LeftArrow": // LEFTWARDS ARROW return rune(0x2190), true - case "LeftCeiling": - // LEFT CEILING + case "LeftArrowBar": // LEFTWARDS ARROW TO BAR + return rune(0x21e4), true + case "LeftArrowRightArrow": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + return rune(0x21c6), true + case "LeftCeiling": // LEFT CEILING return rune(0x2308), true - case "LeftDoubleBracket": - // MATHEMATICAL LEFT WHITE SQUARE BRACKET + case "LeftDoubleBracket": // MATHEMATICAL LEFT WHITE SQUARE BRACKET return rune(0x27e6), true - case "LeftDownTeeVector": - // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR + case "LeftDownTeeVector": // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR return rune(0x2961), true - case "LeftDownVector": - // DOWNWARDS HARPOON WITH BARB LEFTWARDS + case "LeftDownVector": // DOWNWARDS HARPOON WITH BARB LEFTWARDS return rune(0x21c3), true - case "LeftDownVectorBar": - // DOWNWARDS HARPOON WITH BARB LEFT TO BAR + case "LeftDownVectorBar": // DOWNWARDS HARPOON WITH BARB LEFT TO BAR return rune(0x2959), true - case "LeftFloor": - // LEFT FLOOR + case "LeftFloor": // LEFT FLOOR return rune(0x230a), true - case "LeftRightArrow": - // LEFT RIGHT ARROW + case "LeftRightArrow": // LEFT RIGHT ARROW return rune(0x2194), true - case "LeftRightVector": - // LEFT BARB UP RIGHT BARB UP HARPOON + case "LeftRightVector": // LEFT BARB UP RIGHT BARB UP HARPOON return rune(0x294e), true - case "LeftTeeArrow": - // LEFTWARDS ARROW FROM BAR - return rune(0x21a4), true - case "LeftTeeVector": - // LEFTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295a), true - case "LeftTee": - // LEFT TACK + case "LeftTee": // LEFT TACK return rune(0x22a3), true - case "LeftTriangleBar": - // LEFT TRIANGLE BESIDE VERTICAL BAR - return rune(0x29cf), true - case "LeftTriangle": - // NORMAL SUBGROUP OF + case "LeftTeeArrow": // LEFTWARDS ARROW FROM BAR + return rune(0x21a4), true + case "LeftTeeVector": // LEFTWARDS HARPOON WITH BARB UP FROM BAR + return rune(0x295a), true + case "LeftTriangle": // NORMAL SUBGROUP OF return rune(0x22b2), true - case "LeftTriangleEqual": - // NORMAL SUBGROUP OF OR EQUAL TO + case "LeftTriangleBar": // LEFT TRIANGLE BESIDE VERTICAL BAR + return rune(0x29cf), true + case "LeftTriangleEqual": // NORMAL SUBGROUP OF OR EQUAL TO return rune(0x22b4), true - case "LeftUpDownVector": - // UP BARB LEFT DOWN BARB LEFT HARPOON + case "LeftUpDownVector": // UP BARB LEFT DOWN BARB LEFT HARPOON return rune(0x2951), true - case "LeftUpTeeVector": - // UPWARDS HARPOON WITH BARB LEFT FROM BAR + case "LeftUpTeeVector": // UPWARDS HARPOON WITH BARB LEFT FROM BAR return rune(0x2960), true - case "LeftUpVector": - // UPWARDS HARPOON WITH BARB LEFTWARDS + case "LeftUpVector": // UPWARDS HARPOON WITH BARB LEFTWARDS return rune(0x21bf), true - case "LeftUpVectorBar": - // UPWARDS HARPOON WITH BARB LEFT TO BAR + case "LeftUpVectorBar": // UPWARDS HARPOON WITH BARB LEFT TO BAR return rune(0x2958), true - case "LeftVector": - // LEFTWARDS HARPOON WITH BARB UPWARDS + case "LeftVector": // LEFTWARDS HARPOON WITH BARB UPWARDS return rune(0x21bc), true - case "LeftVectorBar": - // LEFTWARDS HARPOON WITH BARB UP TO BAR + case "LeftVectorBar": // LEFTWARDS HARPOON WITH BARB UP TO BAR return rune(0x2952), true - case "Leftarrow": - // LEFTWARDS DOUBLE ARROW + case "Leftarrow": // LEFTWARDS DOUBLE ARROW return rune(0x21d0), true - case "Leftrightarrow": - // LEFT RIGHT DOUBLE ARROW + case "Leftrightarrow": // LEFT RIGHT DOUBLE ARROW return rune(0x21d4), true - case "LessEqualGreater": - // LESS-THAN EQUAL TO OR GREATER-THAN + case "LessEqualGreater": // LESS-THAN EQUAL TO OR GREATER-THAN return rune(0x22da), true - case "LessFullEqual": - // LESS-THAN OVER EQUAL TO + case "LessFullEqual": // LESS-THAN OVER EQUAL TO return rune(0x2266), true - case "LessGreater": - // LESS-THAN OR GREATER-THAN + case "LessGreater": // LESS-THAN OR GREATER-THAN return rune(0x2276), true - case "LessLess": - // DOUBLE NESTED LESS-THAN + case "LessLess": // DOUBLE NESTED LESS-THAN return rune(0x2aa1), true - case "LessSlantEqual": - // LESS-THAN OR SLANTED EQUAL TO + case "LessSlantEqual": // LESS-THAN OR SLANTED EQUAL TO return rune(0x2a7d), true - case "LessTilde": - // LESS-THAN OR EQUIVALENT TO + case "LessTilde": // LESS-THAN OR EQUIVALENT TO return rune(0x2272), true - case "Lfr": - // MATHEMATICAL FRAKTUR CAPITAL L + case "Lfr": // MATHEMATICAL FRAKTUR CAPITAL L return rune(0x01d50f), true - case "Lgr": - // GREEK CAPITAL LETTER LAMDA + case "Lgr": // GREEK CAPITAL LETTER LAMDA return rune(0x039b), true - case "Lleftarrow": - // LEFTWARDS TRIPLE ARROW - return rune(0x21da), true - case "Ll": - // VERY MUCH LESS-THAN + case "Ll": // VERY MUCH LESS-THAN return rune(0x22d8), true - case "Lmidot": - // LATIN CAPITAL LETTER L WITH MIDDLE DOT + case "Lleftarrow": // LEFTWARDS TRIPLE ARROW + return rune(0x21da), true + case "Lmidot": // LATIN CAPITAL LETTER L WITH MIDDLE DOT return rune(0x013f), true - case "LongLeftArrow": - // LONG LEFTWARDS ARROW + case "LongLeftArrow": // LONG LEFTWARDS ARROW return rune(0x27f5), true - case "LongLeftRightArrow": - // LONG LEFT RIGHT ARROW + case "LongLeftRightArrow": // LONG LEFT RIGHT ARROW return rune(0x27f7), true - case "LongRightArrow": - // LONG RIGHTWARDS ARROW + case "LongRightArrow": // LONG RIGHTWARDS ARROW return rune(0x27f6), true - case "Longleftarrow": - // LONG LEFTWARDS DOUBLE ARROW + case "Longleftarrow": // LONG LEFTWARDS DOUBLE ARROW return rune(0x27f8), true - case "Longleftrightarrow": - // LONG LEFT RIGHT DOUBLE ARROW + case "Longleftrightarrow": // LONG LEFT RIGHT DOUBLE ARROW return rune(0x27fa), true - case "Longrightarrow": - // LONG RIGHTWARDS DOUBLE ARROW + case "Longrightarrow": // LONG RIGHTWARDS DOUBLE ARROW return rune(0x27f9), true - case "Lopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL L + case "Lopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL L return rune(0x01d543), true - case "LowerLeftArrow": - // SOUTH WEST ARROW + case "LowerLeftArrow": // SOUTH WEST ARROW return rune(0x2199), true - case "LowerRightArrow": - // SOUTH EAST ARROW + case "LowerRightArrow": // SOUTH EAST ARROW return rune(0x2198), true - case "Lscr": - // SCRIPT CAPITAL L + case "Lscr": // SCRIPT CAPITAL L return rune(0x2112), true - case "Lsh": - // UPWARDS ARROW WITH TIP LEFTWARDS + case "Lsh": // UPWARDS ARROW WITH TIP LEFTWARDS return rune(0x21b0), true - case "Lstrok": - // LATIN CAPITAL LETTER L WITH STROKE + case "Lstrok": // LATIN CAPITAL LETTER L WITH STROKE return rune(0x0141), true - case "Ltbar": - // DOUBLE NESTED LESS-THAN WITH UNDERBAR - return rune(0x2aa3), true - case "Lt": - // MUCH LESS-THAN + case "Lt": // MUCH LESS-THAN return rune(0x226a), true + case "Ltbar": // DOUBLE NESTED LESS-THAN WITH UNDERBAR + return rune(0x2aa3), true } case 'M': switch name { - case "Mapfrom": - // LEFTWARDS DOUBLE ARROW FROM BAR - return rune(0x2906), true - case "Mapto": - // RIGHTWARDS DOUBLE ARROW FROM BAR - return rune(0x2907), true - case "Map": - // RIGHTWARDS TWO-HEADED ARROW FROM BAR + case "Map": // RIGHTWARDS TWO-HEADED ARROW FROM BAR return rune(0x2905), true - case "Mcy": - // CYRILLIC CAPITAL LETTER EM + case "Mapfrom": // LEFTWARDS DOUBLE ARROW FROM BAR + return rune(0x2906), true + case "Mapto": // RIGHTWARDS DOUBLE ARROW FROM BAR + return rune(0x2907), true + case "Mcy": // CYRILLIC CAPITAL LETTER EM return rune(0x041c), true - case "MediumSpace": - // MEDIUM MATHEMATICAL SPACE + case "MediumSpace": // MEDIUM MATHEMATICAL SPACE return rune(0x205f), true - case "Mellintrf": - // SCRIPT CAPITAL M + case "Mellintrf": // SCRIPT CAPITAL M return rune(0x2133), true - case "Mfr": - // MATHEMATICAL FRAKTUR CAPITAL M + case "Mfr": // MATHEMATICAL FRAKTUR CAPITAL M return rune(0x01d510), true - case "Mgr": - // GREEK CAPITAL LETTER MU + case "Mgr": // GREEK CAPITAL LETTER MU return rune(0x039c), true - case "MinusPlus": - // MINUS-OR-PLUS SIGN + case "MinusPlus": // MINUS-OR-PLUS SIGN return rune(0x2213), true - case "Mopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL M + case "Mopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL M return rune(0x01d544), true - case "Mscr": - // SCRIPT CAPITAL M + case "Mscr": // SCRIPT CAPITAL M return rune(0x2133), true - case "Mu": - // GREEK CAPITAL LETTER MU + case "Mu": // GREEK CAPITAL LETTER MU return rune(0x039c), true } case 'N': switch name { - case "NJcy": - // CYRILLIC CAPITAL LETTER NJE + case "NJcy": // CYRILLIC CAPITAL LETTER NJE return rune(0x040a), true - case "Nacute": - // LATIN CAPITAL LETTER N WITH ACUTE + case "Nacute": // LATIN CAPITAL LETTER N WITH ACUTE return rune(0x0143), true - case "Ncaron": - // LATIN CAPITAL LETTER N WITH CARON + case "Ncaron": // LATIN CAPITAL LETTER N WITH CARON return rune(0x0147), true - case "Ncedil": - // LATIN CAPITAL LETTER N WITH CEDILLA + case "Ncedil": // LATIN CAPITAL LETTER N WITH CEDILLA return rune(0x0145), true - case "Ncy": - // CYRILLIC CAPITAL LETTER EN + case "Ncy": // CYRILLIC CAPITAL LETTER EN return rune(0x041d), true - case "NegativeMediumSpace": - // ZERO WIDTH SPACE + case "NegativeMediumSpace": // ZERO WIDTH SPACE return rune(0x200b), true - case "NegativeThickSpace": - // ZERO WIDTH SPACE + case "NegativeThickSpace": // ZERO WIDTH SPACE return rune(0x200b), true - case "NegativeThinSpace": - // ZERO WIDTH SPACE + case "NegativeThinSpace": // ZERO WIDTH SPACE return rune(0x200b), true - case "NegativeVeryThinSpace": - // ZERO WIDTH SPACE + case "NegativeVeryThinSpace": // ZERO WIDTH SPACE return rune(0x200b), true - case "NestedGreaterGreater": - // MUCH GREATER-THAN + case "NestedGreaterGreater": // MUCH GREATER-THAN return rune(0x226b), true - case "NestedLessLess": - // MUCH LESS-THAN + case "NestedLessLess": // MUCH LESS-THAN return rune(0x226a), true - case "NewLine": - // LINE FEED (LF) + case "NewLine": // LINE FEED (LF) return rune(0x0a), true - case "Nfr": - // MATHEMATICAL FRAKTUR CAPITAL N + case "Nfr": // MATHEMATICAL FRAKTUR CAPITAL N return rune(0x01d511), true - case "Ngr": - // GREEK CAPITAL LETTER NU + case "Ngr": // GREEK CAPITAL LETTER NU return rune(0x039d), true - case "NoBreak": - // WORD JOINER + case "NoBreak": // WORD JOINER return rune(0x2060), true - case "NonBreakingSpace": - // NO-BREAK SPACE + case "NonBreakingSpace": // NO-BREAK SPACE return rune(0xa0), true - case "Nopf": - // DOUBLE-STRUCK CAPITAL N + case "Nopf": // DOUBLE-STRUCK CAPITAL N return rune(0x2115), true - case "NotDoubleVerticalBar": - // NOT PARALLEL TO - return rune(0x2226), true - case "NotElement": - // NOT AN ELEMENT OF - return rune(0x2209), true - case "NotEqualTilde": - // MINUS TILDE with slash - return rune(0x2242), true - case "NotEqual": - // NOT EQUAL TO - return rune(0x2260), true - case "NotExists": - // THERE DOES NOT EXIST - return rune(0x2204), true - case "NotHumpDownHump": - // GEOMETRICALLY EQUIVALENT TO with slash - return rune(0x224e), true - case "NotHumpEqual": - // DIFFERENCE BETWEEN with slash - return rune(0x224f), true - case "NotLessGreater": - // NEITHER LESS-THAN NOR GREATER-THAN - return rune(0x2278), true - case "NotReverseElement": - // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true - case "NotTilde": - // NOT TILDE - return rune(0x2241), true - case "NotTildeEqual": - // NOT ASYMPTOTICALLY EQUAL TO - return rune(0x2244), true - case "NotTildeFullEqual": - // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO - return rune(0x2247), true - case "NotTildeTilde": - // NOT ALMOST EQUAL TO - return rune(0x2249), true - case "NotVerticalBar": - // DOES NOT DIVIDE - return rune(0x2224), true - case "Not": - // DOUBLE STROKE NOT SIGN + case "Not": // DOUBLE STROKE NOT SIGN return rune(0x2aec), true - case "NotCongruent": - // NOT IDENTICAL TO + case "NotCongruent": // NOT IDENTICAL TO return rune(0x2262), true - case "NotCupCap": - // NOT EQUIVALENT TO + case "NotCupCap": // NOT EQUIVALENT TO return rune(0x226d), true - case "NotGreaterFullEqual": - // GREATER-THAN OVER EQUAL TO with slash - return rune(0x2267), true - case "NotGreaterGreater": - // MUCH GREATER THAN with slash - return rune(0x226b), true - case "NotGreaterSlantEqual": - // GREATER-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7e), true - case "NotGreater": - // NOT GREATER-THAN + case "NotDoubleVerticalBar": // NOT PARALLEL TO + return rune(0x2226), true + case "NotElement": // NOT AN ELEMENT OF + return rune(0x2209), true + case "NotEqual": // NOT EQUAL TO + return rune(0x2260), true + case "NotEqualTilde": // MINUS TILDE with slash + return rune(0x2242), true + case "NotExists": // THERE DOES NOT EXIST + return rune(0x2204), true + case "NotGreater": // NOT GREATER-THAN return rune(0x226f), true - case "NotGreaterEqual": - // NEITHER GREATER-THAN NOR EQUAL TO + case "NotGreaterEqual": // NEITHER GREATER-THAN NOR EQUAL TO return rune(0x2271), true - case "NotGreaterLess": - // NEITHER GREATER-THAN NOR LESS-THAN + case "NotGreaterFullEqual": // GREATER-THAN OVER EQUAL TO with slash + return rune(0x2267), true + case "NotGreaterGreater": // MUCH GREATER THAN with slash + return rune(0x226b), true + case "NotGreaterLess": // NEITHER GREATER-THAN NOR LESS-THAN return rune(0x2279), true - case "NotGreaterTilde": - // NEITHER GREATER-THAN NOR EQUIVALENT TO + case "NotGreaterSlantEqual": // GREATER-THAN OR SLANTED EQUAL TO with slash + return rune(0x2a7e), true + case "NotGreaterTilde": // NEITHER GREATER-THAN NOR EQUIVALENT TO return rune(0x2275), true - case "NotLeftTriangleBar": - // LEFT TRIANGLE BESIDE VERTICAL BAR with slash - return rune(0x29cf), true - case "NotLeftTriangle": - // NOT NORMAL SUBGROUP OF + case "NotHumpDownHump": // GEOMETRICALLY EQUIVALENT TO with slash + return rune(0x224e), true + case "NotHumpEqual": // DIFFERENCE BETWEEN with slash + return rune(0x224f), true + case "NotLeftTriangle": // NOT NORMAL SUBGROUP OF return rune(0x22ea), true - case "NotLeftTriangleEqual": - // NOT NORMAL SUBGROUP OF OR EQUAL TO + case "NotLeftTriangleBar": // LEFT TRIANGLE BESIDE VERTICAL BAR with slash + return rune(0x29cf), true + case "NotLeftTriangleEqual": // NOT NORMAL SUBGROUP OF OR EQUAL TO return rune(0x22ec), true - case "NotLessLess": - // MUCH LESS THAN with slash - return rune(0x226a), true - case "NotLessSlantEqual": - // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true - case "NotLess": - // NOT LESS-THAN + case "NotLess": // NOT LESS-THAN return rune(0x226e), true - case "NotLessEqual": - // NEITHER LESS-THAN NOR EQUAL TO + case "NotLessEqual": // NEITHER LESS-THAN NOR EQUAL TO return rune(0x2270), true - case "NotLessTilde": - // NEITHER LESS-THAN NOR EQUIVALENT TO + case "NotLessGreater": // NEITHER LESS-THAN NOR GREATER-THAN + return rune(0x2278), true + case "NotLessLess": // MUCH LESS THAN with slash + return rune(0x226a), true + case "NotLessSlantEqual": // LESS-THAN OR SLANTED EQUAL TO with slash + return rune(0x2a7d), true + case "NotLessTilde": // NEITHER LESS-THAN NOR EQUIVALENT TO return rune(0x2274), true - case "NotNestedGreaterGreater": - // DOUBLE NESTED GREATER-THAN with slash + case "NotNestedGreaterGreater": // DOUBLE NESTED GREATER-THAN with slash return rune(0x2aa2), true - case "NotNestedLessLess": - // DOUBLE NESTED LESS-THAN with slash + case "NotNestedLessLess": // DOUBLE NESTED LESS-THAN with slash return rune(0x2aa1), true - case "NotPrecedesEqual": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2aaf), true - case "NotPrecedes": - // DOES NOT PRECEDE + case "NotPrecedes": // DOES NOT PRECEDE return rune(0x2280), true - case "NotPrecedesSlantEqual": - // DOES NOT PRECEDE OR EQUAL + case "NotPrecedesEqual": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + return rune(0x2aaf), true + case "NotPrecedesSlantEqual": // DOES NOT PRECEDE OR EQUAL return rune(0x22e0), true - case "NotRightTriangleBar": - // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash - return rune(0x29d0), true - case "NotRightTriangle": - // DOES NOT CONTAIN AS NORMAL SUBGROUP + case "NotReverseElement": // DOES NOT CONTAIN AS MEMBER + return rune(0x220c), true + case "NotRightTriangle": // DOES NOT CONTAIN AS NORMAL SUBGROUP return rune(0x22eb), true - case "NotRightTriangleEqual": - // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL + case "NotRightTriangleBar": // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash + return rune(0x29d0), true + case "NotRightTriangleEqual": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL return rune(0x22ed), true - case "NotSquareSubset": - // SQUARE IMAGE OF with slash + case "NotSquareSubset": // SQUARE IMAGE OF with slash return rune(0x228f), true - case "NotSquareSubsetEqual": - // NOT SQUARE IMAGE OF OR EQUAL TO + case "NotSquareSubsetEqual": // NOT SQUARE IMAGE OF OR EQUAL TO return rune(0x22e2), true - case "NotSquareSuperset": - // SQUARE ORIGINAL OF with slash + case "NotSquareSuperset": // SQUARE ORIGINAL OF with slash return rune(0x2290), true - case "NotSquareSupersetEqual": - // NOT SQUARE ORIGINAL OF OR EQUAL TO + case "NotSquareSupersetEqual": // NOT SQUARE ORIGINAL OF OR EQUAL TO return rune(0x22e3), true - case "NotSubset": - // SUBSET OF with vertical line + case "NotSubset": // SUBSET OF with vertical line return rune(0x2282), true - case "NotSubsetEqual": - // NEITHER A SUBSET OF NOR EQUAL TO + case "NotSubsetEqual": // NEITHER A SUBSET OF NOR EQUAL TO return rune(0x2288), true - case "NotSucceedsEqual": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2ab0), true - case "NotSucceedsTilde": - // SUCCEEDS OR EQUIVALENT TO with slash - return rune(0x227f), true - case "NotSucceeds": - // DOES NOT SUCCEED + case "NotSucceeds": // DOES NOT SUCCEED return rune(0x2281), true - case "NotSucceedsSlantEqual": - // DOES NOT SUCCEED OR EQUAL + case "NotSucceedsEqual": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + return rune(0x2ab0), true + case "NotSucceedsSlantEqual": // DOES NOT SUCCEED OR EQUAL return rune(0x22e1), true - case "NotSuperset": - // SUPERSET OF with vertical line + case "NotSucceedsTilde": // SUCCEEDS OR EQUIVALENT TO with slash + return rune(0x227f), true + case "NotSuperset": // SUPERSET OF with vertical line return rune(0x2283), true - case "NotSupersetEqual": - // NEITHER A SUPERSET OF NOR EQUAL TO + case "NotSupersetEqual": // NEITHER A SUPERSET OF NOR EQUAL TO return rune(0x2289), true - case "Nscr": - // MATHEMATICAL SCRIPT CAPITAL N + case "NotTilde": // NOT TILDE + return rune(0x2241), true + case "NotTildeEqual": // NOT ASYMPTOTICALLY EQUAL TO + return rune(0x2244), true + case "NotTildeFullEqual": // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO + return rune(0x2247), true + case "NotTildeTilde": // NOT ALMOST EQUAL TO + return rune(0x2249), true + case "NotVerticalBar": // DOES NOT DIVIDE + return rune(0x2224), true + case "Nscr": // MATHEMATICAL SCRIPT CAPITAL N return rune(0x01d4a9), true - case "Ntilde": - // LATIN CAPITAL LETTER N WITH TILDE + case "Ntilde": // LATIN CAPITAL LETTER N WITH TILDE return rune(0xd1), true - case "Nu": - // GREEK CAPITAL LETTER NU + case "Nu": // GREEK CAPITAL LETTER NU return rune(0x039d), true } case 'O': switch name { - case "OElig": - // LATIN CAPITAL LIGATURE OE + case "OElig": // LATIN CAPITAL LIGATURE OE return rune(0x0152), true - case "OHacgr": - // GREEK CAPITAL LETTER OMEGA WITH TONOS + case "OHacgr": // GREEK CAPITAL LETTER OMEGA WITH TONOS return rune(0x038f), true - case "OHgr": - // GREEK CAPITAL LETTER OMEGA + case "OHgr": // GREEK CAPITAL LETTER OMEGA return rune(0x03a9), true - case "Oacgr": - // GREEK CAPITAL LETTER OMICRON WITH TONOS + case "Oacgr": // GREEK CAPITAL LETTER OMICRON WITH TONOS return rune(0x038c), true - case "Oacute": - // LATIN CAPITAL LETTER O WITH ACUTE + case "Oacute": // LATIN CAPITAL LETTER O WITH ACUTE return rune(0xd3), true - case "Ocirc": - // LATIN CAPITAL LETTER O WITH CIRCUMFLEX + case "Ocirc": // LATIN CAPITAL LETTER O WITH CIRCUMFLEX return rune(0xd4), true - case "Ocy": - // CYRILLIC CAPITAL LETTER O + case "Ocy": // CYRILLIC CAPITAL LETTER O return rune(0x041e), true - case "Odblac": - // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + case "Odblac": // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE return rune(0x0150), true - case "Ofr": - // MATHEMATICAL FRAKTUR CAPITAL O + case "Ofr": // MATHEMATICAL FRAKTUR CAPITAL O return rune(0x01d512), true - case "Ograve": - // LATIN CAPITAL LETTER O WITH GRAVE + case "Ogr": // GREEK CAPITAL LETTER OMICRON + return rune(0x039f), true + case "Ograve": // LATIN CAPITAL LETTER O WITH GRAVE return rune(0xd2), true - case "Ogr": - // GREEK CAPITAL LETTER OMICRON - return rune(0x039f), true - case "Omacr": - // LATIN CAPITAL LETTER O WITH MACRON + case "Omacr": // LATIN CAPITAL LETTER O WITH MACRON return rune(0x014c), true - case "Omega": - // GREEK CAPITAL LETTER OMEGA + case "Omega": // GREEK CAPITAL LETTER OMEGA return rune(0x03a9), true - case "Omicron": - // GREEK CAPITAL LETTER OMICRON + case "Omicron": // GREEK CAPITAL LETTER OMICRON return rune(0x039f), true - case "Oopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL O + case "Oopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL O return rune(0x01d546), true - case "OpenCurlyDoubleQuote": - // LEFT DOUBLE QUOTATION MARK + case "OpenCurlyDoubleQuote": // LEFT DOUBLE QUOTATION MARK return rune(0x201c), true - case "OpenCurlyQuote": - // LEFT SINGLE QUOTATION MARK + case "OpenCurlyQuote": // LEFT SINGLE QUOTATION MARK return rune(0x2018), true - case "Or": - // DOUBLE LOGICAL OR + case "Or": // DOUBLE LOGICAL OR return rune(0x2a54), true - case "Oscr": - // MATHEMATICAL SCRIPT CAPITAL O + case "Oscr": // MATHEMATICAL SCRIPT CAPITAL O return rune(0x01d4aa), true - case "Oslash": - // LATIN CAPITAL LETTER O WITH STROKE + case "Oslash": // LATIN CAPITAL LETTER O WITH STROKE return rune(0xd8), true - case "Otilde": - // LATIN CAPITAL LETTER O WITH TILDE + case "Otilde": // LATIN CAPITAL LETTER O WITH TILDE return rune(0xd5), true - case "Otimes": - // MULTIPLICATION SIGN IN DOUBLE CIRCLE + case "Otimes": // MULTIPLICATION SIGN IN DOUBLE CIRCLE return rune(0x2a37), true - case "Ouml": - // LATIN CAPITAL LETTER O WITH DIAERESIS + case "Ouml": // LATIN CAPITAL LETTER O WITH DIAERESIS return rune(0xd6), true - case "OverBar": - // OVERLINE + case "OverBar": // OVERLINE return rune(0x203e), true - case "OverBrace": - // TOP CURLY BRACKET + case "OverBrace": // TOP CURLY BRACKET return rune(0x23de), true - case "OverBracket": - // TOP SQUARE BRACKET + case "OverBracket": // TOP SQUARE BRACKET return rune(0x23b4), true - case "OverParenthesis": - // TOP PARENTHESIS + case "OverParenthesis": // TOP PARENTHESIS return rune(0x23dc), true } case 'P': switch name { - case "PHgr": - // GREEK CAPITAL LETTER PHI + case "PHgr": // GREEK CAPITAL LETTER PHI return rune(0x03a6), true - case "PSgr": - // GREEK CAPITAL LETTER PSI + case "PSgr": // GREEK CAPITAL LETTER PSI return rune(0x03a8), true - case "PartialD": - // PARTIAL DIFFERENTIAL + case "PartialD": // PARTIAL DIFFERENTIAL return rune(0x2202), true - case "Pcy": - // CYRILLIC CAPITAL LETTER PE + case "Pcy": // CYRILLIC CAPITAL LETTER PE return rune(0x041f), true - case "Pfr": - // MATHEMATICAL FRAKTUR CAPITAL P + case "Pfr": // MATHEMATICAL FRAKTUR CAPITAL P return rune(0x01d513), true - case "Pgr": - // GREEK CAPITAL LETTER PI + case "Pgr": // GREEK CAPITAL LETTER PI return rune(0x03a0), true - case "Phi": - // GREEK CAPITAL LETTER PHI + case "Phi": // GREEK CAPITAL LETTER PHI return rune(0x03a6), true - case "Pi": - // GREEK CAPITAL LETTER PI + case "Pi": // GREEK CAPITAL LETTER PI return rune(0x03a0), true - case "PlusMinus": - // PLUS-MINUS SIGN + case "PlusMinus": // PLUS-MINUS SIGN return rune(0xb1), true - case "Poincareplane": - // BLACK-LETTER CAPITAL H + case "Poincareplane": // BLACK-LETTER CAPITAL H return rune(0x210c), true - case "Popf": - // DOUBLE-STRUCK CAPITAL P + case "Popf": // DOUBLE-STRUCK CAPITAL P return rune(0x2119), true - case "Product": - // N-ARY PRODUCT - return rune(0x220f), true - case "Proportional": - // PROPORTIONAL TO - return rune(0x221d), true - case "Proportion": - // PROPORTION - return rune(0x2237), true - case "Pr": - // DOUBLE PRECEDES + case "Pr": // DOUBLE PRECEDES return rune(0x2abb), true - case "PrecedesEqual": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2aaf), true - case "Precedes": - // PRECEDES + case "Precedes": // PRECEDES return rune(0x227a), true - case "PrecedesSlantEqual": - // PRECEDES OR EQUAL TO + case "PrecedesEqual": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + return rune(0x2aaf), true + case "PrecedesSlantEqual": // PRECEDES OR EQUAL TO return rune(0x227c), true - case "PrecedesTilde": - // PRECEDES OR EQUIVALENT TO + case "PrecedesTilde": // PRECEDES OR EQUIVALENT TO return rune(0x227e), true - case "Prime": - // DOUBLE PRIME + case "Prime": // DOUBLE PRIME return rune(0x2033), true - case "Pscr": - // MATHEMATICAL SCRIPT CAPITAL P + case "Product": // N-ARY PRODUCT + return rune(0x220f), true + case "Proportion": // PROPORTION + return rune(0x2237), true + case "Proportional": // PROPORTIONAL TO + return rune(0x221d), true + case "Pscr": // MATHEMATICAL SCRIPT CAPITAL P return rune(0x01d4ab), true - case "Psi": - // GREEK CAPITAL LETTER PSI + case "Psi": // GREEK CAPITAL LETTER PSI return rune(0x03a8), true } case 'Q': switch name { - case "QUOT": - // QUOTATION MARK + case "QUOT": // QUOTATION MARK return rune(0x22), true - case "Qfr": - // MATHEMATICAL FRAKTUR CAPITAL Q + case "Qfr": // MATHEMATICAL FRAKTUR CAPITAL Q return rune(0x01d514), true - case "Qopf": - // DOUBLE-STRUCK CAPITAL Q + case "Qopf": // DOUBLE-STRUCK CAPITAL Q return rune(0x211a), true - case "Qscr": - // MATHEMATICAL SCRIPT CAPITAL Q + case "Qscr": // MATHEMATICAL SCRIPT CAPITAL Q return rune(0x01d4ac), true } case 'R': switch name { - case "RBarr": - // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW + case "RBarr": // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW return rune(0x2910), true - case "REG": - // REGISTERED SIGN + case "REG": // REGISTERED SIGN return rune(0xae), true - case "Racute": - // LATIN CAPITAL LETTER R WITH ACUTE + case "Racute": // LATIN CAPITAL LETTER R WITH ACUTE return rune(0x0154), true - case "Rang": - // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET + case "Rang": // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET return rune(0x27eb), true - case "Rarr": - // RIGHTWARDS TWO HEADED ARROW + case "Rarr": // RIGHTWARDS TWO HEADED ARROW return rune(0x21a0), true - case "Rarrtl": - // RIGHTWARDS TWO-HEADED ARROW WITH TAIL + case "Rarrtl": // RIGHTWARDS TWO-HEADED ARROW WITH TAIL return rune(0x2916), true - case "Rcaron": - // LATIN CAPITAL LETTER R WITH CARON + case "Rcaron": // LATIN CAPITAL LETTER R WITH CARON return rune(0x0158), true - case "Rcedil": - // LATIN CAPITAL LETTER R WITH CEDILLA + case "Rcedil": // LATIN CAPITAL LETTER R WITH CEDILLA return rune(0x0156), true - case "Rcy": - // CYRILLIC CAPITAL LETTER ER + case "Rcy": // CYRILLIC CAPITAL LETTER ER return rune(0x0420), true - case "ReverseElement": - // CONTAINS AS MEMBER + case "Re": // BLACK-LETTER CAPITAL R + return rune(0x211c), true + case "ReverseElement": // CONTAINS AS MEMBER return rune(0x220b), true - case "ReverseEquilibrium": - // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + case "ReverseEquilibrium": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON return rune(0x21cb), true - case "Re": - // BLACK-LETTER CAPITAL R - return rune(0x211c), true - case "ReverseUpEquilibrium": - // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + case "ReverseUpEquilibrium": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT return rune(0x296f), true - case "Rfr": - // BLACK-LETTER CAPITAL R + case "Rfr": // BLACK-LETTER CAPITAL R return rune(0x211c), true - case "Rgr": - // GREEK CAPITAL LETTER RHO + case "Rgr": // GREEK CAPITAL LETTER RHO return rune(0x03a1), true - case "Rho": - // GREEK CAPITAL LETTER RHO + case "Rho": // GREEK CAPITAL LETTER RHO return rune(0x03a1), true - case "RightAngleBracket": - // MATHEMATICAL RIGHT ANGLE BRACKET + case "RightAngleBracket": // MATHEMATICAL RIGHT ANGLE BRACKET return rune(0x27e9), true - case "RightArrowBar": - // RIGHTWARDS ARROW TO BAR - return rune(0x21e5), true - case "RightArrow": - // RIGHTWARDS ARROW + case "RightArrow": // RIGHTWARDS ARROW return rune(0x2192), true - case "RightArrowLeftArrow": - // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + case "RightArrowBar": // RIGHTWARDS ARROW TO BAR + return rune(0x21e5), true + case "RightArrowLeftArrow": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW return rune(0x21c4), true - case "RightCeiling": - // RIGHT CEILING + case "RightCeiling": // RIGHT CEILING return rune(0x2309), true - case "RightDoubleBracket": - // MATHEMATICAL RIGHT WHITE SQUARE BRACKET + case "RightDoubleBracket": // MATHEMATICAL RIGHT WHITE SQUARE BRACKET return rune(0x27e7), true - case "RightDownTeeVector": - // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR + case "RightDownTeeVector": // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR return rune(0x295d), true - case "RightDownVector": - // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + case "RightDownVector": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS return rune(0x21c2), true - case "RightDownVectorBar": - // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR + case "RightDownVectorBar": // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR return rune(0x2955), true - case "RightFloor": - // RIGHT FLOOR + case "RightFloor": // RIGHT FLOOR return rune(0x230b), true - case "RightTeeArrow": - // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true - case "RightTeeVector": - // RIGHTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295b), true - case "RightTee": - // RIGHT TACK + case "RightTee": // RIGHT TACK return rune(0x22a2), true - case "RightTriangleBar": - // VERTICAL BAR BESIDE RIGHT TRIANGLE - return rune(0x29d0), true - case "RightTriangle": - // CONTAINS AS NORMAL SUBGROUP + case "RightTeeArrow": // RIGHTWARDS ARROW FROM BAR + return rune(0x21a6), true + case "RightTeeVector": // RIGHTWARDS HARPOON WITH BARB UP FROM BAR + return rune(0x295b), true + case "RightTriangle": // CONTAINS AS NORMAL SUBGROUP return rune(0x22b3), true - case "RightTriangleEqual": - // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + case "RightTriangleBar": // VERTICAL BAR BESIDE RIGHT TRIANGLE + return rune(0x29d0), true + case "RightTriangleEqual": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO return rune(0x22b5), true - case "RightUpDownVector": - // UP BARB RIGHT DOWN BARB RIGHT HARPOON + case "RightUpDownVector": // UP BARB RIGHT DOWN BARB RIGHT HARPOON return rune(0x294f), true - case "RightUpTeeVector": - // UPWARDS HARPOON WITH BARB RIGHT FROM BAR + case "RightUpTeeVector": // UPWARDS HARPOON WITH BARB RIGHT FROM BAR return rune(0x295c), true - case "RightUpVector": - // UPWARDS HARPOON WITH BARB RIGHTWARDS + case "RightUpVector": // UPWARDS HARPOON WITH BARB RIGHTWARDS return rune(0x21be), true - case "RightUpVectorBar": - // UPWARDS HARPOON WITH BARB RIGHT TO BAR + case "RightUpVectorBar": // UPWARDS HARPOON WITH BARB RIGHT TO BAR return rune(0x2954), true - case "RightVector": - // RIGHTWARDS HARPOON WITH BARB UPWARDS + case "RightVector": // RIGHTWARDS HARPOON WITH BARB UPWARDS return rune(0x21c0), true - case "RightVectorBar": - // RIGHTWARDS HARPOON WITH BARB UP TO BAR + case "RightVectorBar": // RIGHTWARDS HARPOON WITH BARB UP TO BAR return rune(0x2953), true - case "Rightarrow": - // RIGHTWARDS DOUBLE ARROW + case "Rightarrow": // RIGHTWARDS DOUBLE ARROW return rune(0x21d2), true - case "Ropf": - // DOUBLE-STRUCK CAPITAL R + case "Ropf": // DOUBLE-STRUCK CAPITAL R return rune(0x211d), true - case "RoundImplies": - // RIGHT DOUBLE ARROW WITH ROUNDED HEAD + case "RoundImplies": // RIGHT DOUBLE ARROW WITH ROUNDED HEAD return rune(0x2970), true - case "Rrightarrow": - // RIGHTWARDS TRIPLE ARROW + case "Rrightarrow": // RIGHTWARDS TRIPLE ARROW return rune(0x21db), true - case "Rscr": - // SCRIPT CAPITAL R + case "Rscr": // SCRIPT CAPITAL R return rune(0x211b), true - case "Rsh": - // UPWARDS ARROW WITH TIP RIGHTWARDS + case "Rsh": // UPWARDS ARROW WITH TIP RIGHTWARDS return rune(0x21b1), true - case "RuleDelayed": - // RULE-DELAYED + case "RuleDelayed": // RULE-DELAYED return rune(0x29f4), true } case 'S': switch name { - case "SHCHcy": - // CYRILLIC CAPITAL LETTER SHCHA + case "SHCHcy": // CYRILLIC CAPITAL LETTER SHCHA return rune(0x0429), true - case "SHcy": - // CYRILLIC CAPITAL LETTER SHA + case "SHcy": // CYRILLIC CAPITAL LETTER SHA return rune(0x0428), true - case "SOFTcy": - // CYRILLIC CAPITAL LETTER SOFT SIGN + case "SOFTcy": // CYRILLIC CAPITAL LETTER SOFT SIGN return rune(0x042c), true - case "Sacute": - // LATIN CAPITAL LETTER S WITH ACUTE + case "Sacute": // LATIN CAPITAL LETTER S WITH ACUTE return rune(0x015a), true - case "Sc": - // DOUBLE SUCCEEDS + case "Sc": // DOUBLE SUCCEEDS return rune(0x2abc), true - case "Scaron": - // LATIN CAPITAL LETTER S WITH CARON + case "Scaron": // LATIN CAPITAL LETTER S WITH CARON return rune(0x0160), true - case "Scedil": - // LATIN CAPITAL LETTER S WITH CEDILLA + case "Scedil": // LATIN CAPITAL LETTER S WITH CEDILLA return rune(0x015e), true - case "Scirc": - // LATIN CAPITAL LETTER S WITH CIRCUMFLEX + case "Scirc": // LATIN CAPITAL LETTER S WITH CIRCUMFLEX return rune(0x015c), true - case "Scy": - // CYRILLIC CAPITAL LETTER ES + case "Scy": // CYRILLIC CAPITAL LETTER ES return rune(0x0421), true - case "Sfr": - // MATHEMATICAL FRAKTUR CAPITAL S + case "Sfr": // MATHEMATICAL FRAKTUR CAPITAL S return rune(0x01d516), true - case "Sgr": - // GREEK CAPITAL LETTER SIGMA + case "Sgr": // GREEK CAPITAL LETTER SIGMA return rune(0x03a3), true - case "ShortDownArrow": - // DOWNWARDS ARROW + case "ShortDownArrow": // DOWNWARDS ARROW return rune(0x2193), true - case "ShortLeftArrow": - // LEFTWARDS ARROW + case "ShortLeftArrow": // LEFTWARDS ARROW return rune(0x2190), true - case "ShortRightArrow": - // RIGHTWARDS ARROW + case "ShortRightArrow": // RIGHTWARDS ARROW return rune(0x2192), true - case "ShortUpArrow": - // UPWARDS ARROW + case "ShortUpArrow": // UPWARDS ARROW return rune(0x2191), true - case "Sigma": - // GREEK CAPITAL LETTER SIGMA + case "Sigma": // GREEK CAPITAL LETTER SIGMA return rune(0x03a3), true - case "SmallCircle": - // RING OPERATOR + case "SmallCircle": // RING OPERATOR return rune(0x2218), true - case "Sopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL S + case "Sopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL S return rune(0x01d54a), true - case "Sqrt": - // SQUARE ROOT + case "Sqrt": // SQUARE ROOT return rune(0x221a), true - case "SquareIntersection": - // SQUARE CAP - return rune(0x2293), true - case "SquareSubset": - // SQUARE IMAGE OF - return rune(0x228f), true - case "SquareSubsetEqual": - // SQUARE IMAGE OF OR EQUAL TO - return rune(0x2291), true - case "Square": - // WHITE SQUARE + case "Square": // WHITE SQUARE return rune(0x25a1), true - case "SquareSuperset": - // SQUARE ORIGINAL OF + case "SquareIntersection": // SQUARE CAP + return rune(0x2293), true + case "SquareSubset": // SQUARE IMAGE OF + return rune(0x228f), true + case "SquareSubsetEqual": // SQUARE IMAGE OF OR EQUAL TO + return rune(0x2291), true + case "SquareSuperset": // SQUARE ORIGINAL OF return rune(0x2290), true - case "SquareSupersetEqual": - // SQUARE ORIGINAL OF OR EQUAL TO + case "SquareSupersetEqual": // SQUARE ORIGINAL OF OR EQUAL TO return rune(0x2292), true - case "SquareUnion": - // SQUARE CUP + case "SquareUnion": // SQUARE CUP return rune(0x2294), true - case "Sscr": - // MATHEMATICAL SCRIPT CAPITAL S + case "Sscr": // MATHEMATICAL SCRIPT CAPITAL S return rune(0x01d4ae), true - case "Star": - // STAR OPERATOR + case "Star": // STAR OPERATOR return rune(0x22c6), true - case "Sub": - // DOUBLE SUBSET + case "Sub": // DOUBLE SUBSET return rune(0x22d0), true - case "Subset": - // DOUBLE SUBSET + case "Subset": // DOUBLE SUBSET return rune(0x22d0), true - case "SubsetEqual": - // SUBSET OF OR EQUAL TO + case "SubsetEqual": // SUBSET OF OR EQUAL TO return rune(0x2286), true - case "Succeeds": - // SUCCEEDS + case "Succeeds": // SUCCEEDS return rune(0x227b), true - case "SucceedsEqual": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + case "SucceedsEqual": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN return rune(0x2ab0), true - case "SucceedsSlantEqual": - // SUCCEEDS OR EQUAL TO + case "SucceedsSlantEqual": // SUCCEEDS OR EQUAL TO return rune(0x227d), true - case "SucceedsTilde": - // SUCCEEDS OR EQUIVALENT TO + case "SucceedsTilde": // SUCCEEDS OR EQUIVALENT TO return rune(0x227f), true - case "SuchThat": - // CONTAINS AS MEMBER + case "SuchThat": // CONTAINS AS MEMBER return rune(0x220b), true - case "Sum": - // N-ARY SUMMATION + case "Sum": // N-ARY SUMMATION return rune(0x2211), true - case "SupersetEqual": - // SUPERSET OF OR EQUAL TO - return rune(0x2287), true - case "Sup": - // DOUBLE SUPERSET + case "Sup": // DOUBLE SUPERSET return rune(0x22d1), true - case "Superset": - // SUPERSET OF + case "Superset": // SUPERSET OF return rune(0x2283), true - case "Supset": - // DOUBLE SUPERSET + case "SupersetEqual": // SUPERSET OF OR EQUAL TO + return rune(0x2287), true + case "Supset": // DOUBLE SUPERSET return rune(0x22d1), true } case 'T': switch name { - case "THORN": - // LATIN CAPITAL LETTER THORN + case "THORN": // LATIN CAPITAL LETTER THORN return rune(0xde), true - case "THgr": - // GREEK CAPITAL LETTER THETA + case "THgr": // GREEK CAPITAL LETTER THETA return rune(0x0398), true - case "TRADE": - // TRADE MARK SIGN + case "TRADE": // TRADE MARK SIGN return rune(0x2122), true - case "TSHcy": - // CYRILLIC CAPITAL LETTER TSHE + case "TSHcy": // CYRILLIC CAPITAL LETTER TSHE return rune(0x040b), true - case "TScy": - // CYRILLIC CAPITAL LETTER TSE + case "TScy": // CYRILLIC CAPITAL LETTER TSE return rune(0x0426), true - case "Tab": - // CHARACTER TABULATION + case "Tab": // CHARACTER TABULATION return rune(0x09), true - case "Tau": - // GREEK CAPITAL LETTER TAU + case "Tau": // GREEK CAPITAL LETTER TAU return rune(0x03a4), true - case "Tcaron": - // LATIN CAPITAL LETTER T WITH CARON + case "Tcaron": // LATIN CAPITAL LETTER T WITH CARON return rune(0x0164), true - case "Tcedil": - // LATIN CAPITAL LETTER T WITH CEDILLA + case "Tcedil": // LATIN CAPITAL LETTER T WITH CEDILLA return rune(0x0162), true - case "Tcy": - // CYRILLIC CAPITAL LETTER TE + case "Tcy": // CYRILLIC CAPITAL LETTER TE return rune(0x0422), true - case "Tfr": - // MATHEMATICAL FRAKTUR CAPITAL T + case "Tfr": // MATHEMATICAL FRAKTUR CAPITAL T return rune(0x01d517), true - case "Tgr": - // GREEK CAPITAL LETTER TAU + case "Tgr": // GREEK CAPITAL LETTER TAU return rune(0x03a4), true - case "Therefore": - // THEREFORE + case "Therefore": // THEREFORE return rune(0x2234), true - case "Theta": - // GREEK CAPITAL LETTER THETA + case "Theta": // GREEK CAPITAL LETTER THETA return rune(0x0398), true - case "Thetav": - // GREEK CAPITAL THETA SYMBOL + case "Thetav": // GREEK CAPITAL THETA SYMBOL return rune(0x03f4), true - case "ThickSpace": - // space of width 5/18 em + case "ThickSpace": // space of width 5/18 em return rune(0x205f), true - case "ThinSpace": - // THIN SPACE + case "ThinSpace": // THIN SPACE return rune(0x2009), true - case "Tilde": - // TILDE OPERATOR + case "Tilde": // TILDE OPERATOR return rune(0x223c), true - case "TildeEqual": - // ASYMPTOTICALLY EQUAL TO + case "TildeEqual": // ASYMPTOTICALLY EQUAL TO return rune(0x2243), true - case "TildeFullEqual": - // APPROXIMATELY EQUAL TO + case "TildeFullEqual": // APPROXIMATELY EQUAL TO return rune(0x2245), true - case "TildeTilde": - // ALMOST EQUAL TO + case "TildeTilde": // ALMOST EQUAL TO return rune(0x2248), true - case "Topf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL T + case "Topf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL T return rune(0x01d54b), true - case "TripleDot": - // COMBINING THREE DOTS ABOVE + case "TripleDot": // COMBINING THREE DOTS ABOVE return rune(0x20db), true - case "Tscr": - // MATHEMATICAL SCRIPT CAPITAL T + case "Tscr": // MATHEMATICAL SCRIPT CAPITAL T return rune(0x01d4af), true - case "Tstrok": - // LATIN CAPITAL LETTER T WITH STROKE + case "Tstrok": // LATIN CAPITAL LETTER T WITH STROKE return rune(0x0166), true } case 'U': switch name { - case "Uacgr": - // GREEK CAPITAL LETTER UPSILON WITH TONOS + case "Uacgr": // GREEK CAPITAL LETTER UPSILON WITH TONOS return rune(0x038e), true - case "Uacute": - // LATIN CAPITAL LETTER U WITH ACUTE + case "Uacute": // LATIN CAPITAL LETTER U WITH ACUTE return rune(0xda), true - case "Uarrocir": - // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE - return rune(0x2949), true - case "Uarr": - // UPWARDS TWO HEADED ARROW + case "Uarr": // UPWARDS TWO HEADED ARROW return rune(0x219f), true - case "Ubrcy": - // CYRILLIC CAPITAL LETTER SHORT U + case "Uarrocir": // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE + return rune(0x2949), true + case "Ubrcy": // CYRILLIC CAPITAL LETTER SHORT U return rune(0x040e), true - case "Ubreve": - // LATIN CAPITAL LETTER U WITH BREVE + case "Ubreve": // LATIN CAPITAL LETTER U WITH BREVE return rune(0x016c), true - case "Ucirc": - // LATIN CAPITAL LETTER U WITH CIRCUMFLEX + case "Ucirc": // LATIN CAPITAL LETTER U WITH CIRCUMFLEX return rune(0xdb), true - case "Ucy": - // CYRILLIC CAPITAL LETTER U + case "Ucy": // CYRILLIC CAPITAL LETTER U return rune(0x0423), true - case "Udblac": - // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + case "Udblac": // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE return rune(0x0170), true - case "Udigr": - // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + case "Udigr": // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA return rune(0x03ab), true - case "Ufr": - // MATHEMATICAL FRAKTUR CAPITAL U + case "Ufr": // MATHEMATICAL FRAKTUR CAPITAL U return rune(0x01d518), true - case "Ugrave": - // LATIN CAPITAL LETTER U WITH GRAVE + case "Ugr": // GREEK CAPITAL LETTER UPSILON + return rune(0x03a5), true + case "Ugrave": // LATIN CAPITAL LETTER U WITH GRAVE return rune(0xd9), true - case "Ugr": - // GREEK CAPITAL LETTER UPSILON - return rune(0x03a5), true - case "Umacr": - // LATIN CAPITAL LETTER U WITH MACRON + case "Umacr": // LATIN CAPITAL LETTER U WITH MACRON return rune(0x016a), true - case "UnderBar": - // LOW LINE + case "UnderBar": // LOW LINE return rune(0x5f), true - case "UnderBrace": - // BOTTOM CURLY BRACKET + case "UnderBrace": // BOTTOM CURLY BRACKET return rune(0x23df), true - case "UnderBracket": - // BOTTOM SQUARE BRACKET + case "UnderBracket": // BOTTOM SQUARE BRACKET return rune(0x23b5), true - case "UnderParenthesis": - // BOTTOM PARENTHESIS + case "UnderParenthesis": // BOTTOM PARENTHESIS return rune(0x23dd), true - case "Union": - // N-ARY UNION + case "Union": // N-ARY UNION return rune(0x22c3), true - case "UnionPlus": - // MULTISET UNION + case "UnionPlus": // MULTISET UNION return rune(0x228e), true - case "Uogon": - // LATIN CAPITAL LETTER U WITH OGONEK + case "Uogon": // LATIN CAPITAL LETTER U WITH OGONEK return rune(0x0172), true - case "Uopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL U + case "Uopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL U return rune(0x01d54c), true - case "UpArrow": - // UPWARDS ARROW + case "UpArrow": // UPWARDS ARROW return rune(0x2191), true - case "UpArrowBar": - // UPWARDS ARROW TO BAR + case "UpArrowBar": // UPWARDS ARROW TO BAR return rune(0x2912), true - case "UpArrowDownArrow": - // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW + case "UpArrowDownArrow": // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW return rune(0x21c5), true - case "UpDownArrow": - // UP DOWN ARROW + case "UpDownArrow": // UP DOWN ARROW return rune(0x2195), true - case "UpEquilibrium": - // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + case "UpEquilibrium": // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT return rune(0x296e), true - case "UpTee": - // UP TACK + case "UpTee": // UP TACK return rune(0x22a5), true - case "UpTeeArrow": - // UPWARDS ARROW FROM BAR + case "UpTeeArrow": // UPWARDS ARROW FROM BAR return rune(0x21a5), true - case "Uparrow": - // UPWARDS DOUBLE ARROW + case "Uparrow": // UPWARDS DOUBLE ARROW return rune(0x21d1), true - case "Updownarrow": - // UP DOWN DOUBLE ARROW + case "Updownarrow": // UP DOWN DOUBLE ARROW return rune(0x21d5), true - case "UpperLeftArrow": - // NORTH WEST ARROW + case "UpperLeftArrow": // NORTH WEST ARROW return rune(0x2196), true - case "UpperRightArrow": - // NORTH EAST ARROW + case "UpperRightArrow": // NORTH EAST ARROW return rune(0x2197), true - case "Upsilon": - // GREEK CAPITAL LETTER UPSILON - return rune(0x03a5), true - case "Upsi": - // GREEK UPSILON WITH HOOK SYMBOL + case "Upsi": // GREEK UPSILON WITH HOOK SYMBOL return rune(0x03d2), true - case "Uring": - // LATIN CAPITAL LETTER U WITH RING ABOVE + case "Upsilon": // GREEK CAPITAL LETTER UPSILON + return rune(0x03a5), true + case "Uring": // LATIN CAPITAL LETTER U WITH RING ABOVE return rune(0x016e), true - case "Uscr": - // MATHEMATICAL SCRIPT CAPITAL U + case "Uscr": // MATHEMATICAL SCRIPT CAPITAL U return rune(0x01d4b0), true - case "Utilde": - // LATIN CAPITAL LETTER U WITH TILDE + case "Utilde": // LATIN CAPITAL LETTER U WITH TILDE return rune(0x0168), true - case "Uuml": - // LATIN CAPITAL LETTER U WITH DIAERESIS + case "Uuml": // LATIN CAPITAL LETTER U WITH DIAERESIS return rune(0xdc), true } case 'V': switch name { - case "VDash": - // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE + case "VDash": // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE return rune(0x22ab), true - case "Vbar": - // DOUBLE UP TACK + case "Vbar": // DOUBLE UP TACK return rune(0x2aeb), true - case "Vcy": - // CYRILLIC CAPITAL LETTER VE + case "Vcy": // CYRILLIC CAPITAL LETTER VE return rune(0x0412), true - case "Vdashl": - // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL - return rune(0x2ae6), true - case "Vdash": - // FORCES + case "Vdash": // FORCES return rune(0x22a9), true - case "Vee": - // N-ARY LOGICAL OR + case "Vdashl": // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL + return rune(0x2ae6), true + case "Vee": // N-ARY LOGICAL OR return rune(0x22c1), true - case "Verbar": - // DOUBLE VERTICAL LINE + case "Verbar": // DOUBLE VERTICAL LINE return rune(0x2016), true - case "Vert": - // DOUBLE VERTICAL LINE + case "Vert": // DOUBLE VERTICAL LINE return rune(0x2016), true - case "VerticalBar": - // DIVIDES + case "VerticalBar": // DIVIDES return rune(0x2223), true - case "VerticalLine": - // VERTICAL LINE + case "VerticalLine": // VERTICAL LINE return rune(0x7c), true - case "VerticalSeparator": - // LIGHT VERTICAL BAR + case "VerticalSeparator": // LIGHT VERTICAL BAR return rune(0x2758), true - case "VerticalTilde": - // WREATH PRODUCT + case "VerticalTilde": // WREATH PRODUCT return rune(0x2240), true - case "VeryThinSpace": - // HAIR SPACE + case "VeryThinSpace": // HAIR SPACE return rune(0x200a), true - case "Vfr": - // MATHEMATICAL FRAKTUR CAPITAL V + case "Vfr": // MATHEMATICAL FRAKTUR CAPITAL V return rune(0x01d519), true - case "Vopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL V + case "Vopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL V return rune(0x01d54d), true - case "Vscr": - // MATHEMATICAL SCRIPT CAPITAL V + case "Vscr": // MATHEMATICAL SCRIPT CAPITAL V return rune(0x01d4b1), true - case "Vvdash": - // TRIPLE VERTICAL BAR RIGHT TURNSTILE + case "Vvdash": // TRIPLE VERTICAL BAR RIGHT TURNSTILE return rune(0x22aa), true } case 'W': switch name { - case "Wcirc": - // LATIN CAPITAL LETTER W WITH CIRCUMFLEX + case "Wcirc": // LATIN CAPITAL LETTER W WITH CIRCUMFLEX return rune(0x0174), true - case "Wedge": - // N-ARY LOGICAL AND + case "Wedge": // N-ARY LOGICAL AND return rune(0x22c0), true - case "Wfr": - // MATHEMATICAL FRAKTUR CAPITAL W + case "Wfr": // MATHEMATICAL FRAKTUR CAPITAL W return rune(0x01d51a), true - case "Wopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL W + case "Wopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL W return rune(0x01d54e), true - case "Wscr": - // MATHEMATICAL SCRIPT CAPITAL W + case "Wscr": // MATHEMATICAL SCRIPT CAPITAL W return rune(0x01d4b2), true } case 'X': switch name { - case "Xfr": - // MATHEMATICAL FRAKTUR CAPITAL X + case "Xfr": // MATHEMATICAL FRAKTUR CAPITAL X return rune(0x01d51b), true - case "Xgr": - // GREEK CAPITAL LETTER XI + case "Xgr": // GREEK CAPITAL LETTER XI return rune(0x039e), true - case "Xi": - // GREEK CAPITAL LETTER XI + case "Xi": // GREEK CAPITAL LETTER XI return rune(0x039e), true - case "Xopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL X + case "Xopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL X return rune(0x01d54f), true - case "Xscr": - // MATHEMATICAL SCRIPT CAPITAL X + case "Xscr": // MATHEMATICAL SCRIPT CAPITAL X return rune(0x01d4b3), true } case 'Y': switch name { - case "YAcy": - // CYRILLIC CAPITAL LETTER YA + case "YAcy": // CYRILLIC CAPITAL LETTER YA return rune(0x042f), true - case "YIcy": - // CYRILLIC CAPITAL LETTER YI + case "YIcy": // CYRILLIC CAPITAL LETTER YI return rune(0x0407), true - case "YUcy": - // CYRILLIC CAPITAL LETTER YU + case "YUcy": // CYRILLIC CAPITAL LETTER YU return rune(0x042e), true - case "Yacute": - // LATIN CAPITAL LETTER Y WITH ACUTE + case "Yacute": // LATIN CAPITAL LETTER Y WITH ACUTE return rune(0xdd), true - case "Ycirc": - // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + case "Ycirc": // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX return rune(0x0176), true - case "Ycy": - // CYRILLIC CAPITAL LETTER YERU + case "Ycy": // CYRILLIC CAPITAL LETTER YERU return rune(0x042b), true - case "Yfr": - // MATHEMATICAL FRAKTUR CAPITAL Y + case "Yfr": // MATHEMATICAL FRAKTUR CAPITAL Y return rune(0x01d51c), true - case "Yopf": - // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + case "Yopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y return rune(0x01d550), true - case "Yscr": - // MATHEMATICAL SCRIPT CAPITAL Y + case "Yscr": // MATHEMATICAL SCRIPT CAPITAL Y return rune(0x01d4b4), true - case "Yuml": - // LATIN CAPITAL LETTER Y WITH DIAERESIS + case "Yuml": // LATIN CAPITAL LETTER Y WITH DIAERESIS return rune(0x0178), true } case 'Z': switch name { - case "ZHcy": - // CYRILLIC CAPITAL LETTER ZHE + case "ZHcy": // CYRILLIC CAPITAL LETTER ZHE return rune(0x0416), true - case "Zacute": - // LATIN CAPITAL LETTER Z WITH ACUTE + case "Zacute": // LATIN CAPITAL LETTER Z WITH ACUTE return rune(0x0179), true - case "Zcaron": - // LATIN CAPITAL LETTER Z WITH CARON + case "Zcaron": // LATIN CAPITAL LETTER Z WITH CARON return rune(0x017d), true - case "Zcy": - // CYRILLIC CAPITAL LETTER ZE + case "Zcy": // CYRILLIC CAPITAL LETTER ZE return rune(0x0417), true - case "Zdot": - // LATIN CAPITAL LETTER Z WITH DOT ABOVE + case "Zdot": // LATIN CAPITAL LETTER Z WITH DOT ABOVE return rune(0x017b), true - case "ZeroWidthSpace": - // ZERO WIDTH SPACE + case "ZeroWidthSpace": // ZERO WIDTH SPACE return rune(0x200b), true - case "Zeta": - // GREEK CAPITAL LETTER ZETA + case "Zeta": // GREEK CAPITAL LETTER ZETA return rune(0x0396), true - case "Zfr": - // BLACK-LETTER CAPITAL Z + case "Zfr": // BLACK-LETTER CAPITAL Z return rune(0x2128), true - case "Zgr": - // GREEK CAPITAL LETTER ZETA + case "Zgr": // GREEK CAPITAL LETTER ZETA return rune(0x0396), true - case "Zopf": - // DOUBLE-STRUCK CAPITAL Z + case "Zopf": // DOUBLE-STRUCK CAPITAL Z return rune(0x2124), true - case "Zscr": - // MATHEMATICAL SCRIPT CAPITAL Z + case "Zscr": // MATHEMATICAL SCRIPT CAPITAL Z return rune(0x01d4b5), true } case 'a': switch name { - case "aacgr": - // GREEK SMALL LETTER ALPHA WITH TONOS + case "aacgr": // GREEK SMALL LETTER ALPHA WITH TONOS return rune(0x03ac), true - case "aacute": - // LATIN SMALL LETTER A WITH ACUTE + case "aacute": // LATIN SMALL LETTER A WITH ACUTE return rune(0xe1), true - case "abreve": - // LATIN SMALL LETTER A WITH BREVE + case "abreve": // LATIN SMALL LETTER A WITH BREVE return rune(0x0103), true - case "acE": - // INVERTED LAZY S with double underline + case "ac": // INVERTED LAZY S return rune(0x223e), true - case "acd": - // SINE WAVE + case "acE": // INVERTED LAZY S with double underline + return rune(0x223e), true + case "acd": // SINE WAVE return rune(0x223f), true - case "acute": - // ACUTE ACCENT - return rune(0xb4), true - case "ac": - // INVERTED LAZY S - return rune(0x223e), true - case "acirc": - // LATIN SMALL LETTER A WITH CIRCUMFLEX + case "acirc": // LATIN SMALL LETTER A WITH CIRCUMFLEX return rune(0xe2), true - case "actuary": - // COMBINING ANNUITY SYMBOL + case "actuary": // COMBINING ANNUITY SYMBOL return rune(0x20e7), true - case "acy": - // CYRILLIC SMALL LETTER A + case "acute": // ACUTE ACCENT + return rune(0xb4), true + case "acy": // CYRILLIC SMALL LETTER A return rune(0x0430), true - case "aelig": - // LATIN SMALL LETTER AE + case "aelig": // LATIN SMALL LETTER AE return rune(0xe6), true - case "af": - // FUNCTION APPLICATION + case "af": // FUNCTION APPLICATION return rune(0x2061), true - case "afr": - // MATHEMATICAL FRAKTUR SMALL A + case "afr": // MATHEMATICAL FRAKTUR SMALL A return rune(0x01d51e), true - case "agr": - // GREEK SMALL LETTER ALPHA + case "agr": // GREEK SMALL LETTER ALPHA return rune(0x03b1), true - case "agrave": - // LATIN SMALL LETTER A WITH GRAVE + case "agrave": // LATIN SMALL LETTER A WITH GRAVE return rune(0xe0), true - case "alefsym": - // ALEF SYMBOL + case "alefsym": // ALEF SYMBOL return rune(0x2135), true - case "aleph": - // ALEF SYMBOL + case "aleph": // ALEF SYMBOL return rune(0x2135), true - case "alpha": - // GREEK SMALL LETTER ALPHA + case "alpha": // GREEK SMALL LETTER ALPHA return rune(0x03b1), true - case "amacr": - // LATIN SMALL LETTER A WITH MACRON + case "amacr": // LATIN SMALL LETTER A WITH MACRON return rune(0x0101), true - case "amalg": - // AMALGAMATION OR COPRODUCT + case "amalg": // AMALGAMATION OR COPRODUCT return rune(0x2a3f), true - case "amp": - // AMPERSAND + case "amp": // AMPERSAND return rune(0x26), true - case "andand": - // TWO INTERSECTING LOGICAL AND - return rune(0x2a55), true - case "andd": - // LOGICAL AND WITH HORIZONTAL DASH - return rune(0x2a5c), true - case "andslope": - // SLOPING LARGE AND - return rune(0x2a58), true - case "andv": - // LOGICAL AND WITH MIDDLE STEM - return rune(0x2a5a), true - case "and": - // LOGICAL AND + case "and": // LOGICAL AND return rune(0x2227), true - case "angdnl": - // TURNED ANGLE + case "andand": // TWO INTERSECTING LOGICAL AND + return rune(0x2a55), true + case "andd": // LOGICAL AND WITH HORIZONTAL DASH + return rune(0x2a5c), true + case "andslope": // SLOPING LARGE AND + return rune(0x2a58), true + case "andv": // LOGICAL AND WITH MIDDLE STEM + return rune(0x2a5a), true + case "ang": // ANGLE + return rune(0x2220), true + case "ang90": // RIGHT ANGLE + return rune(0x221f), true + case "angdnl": // TURNED ANGLE return rune(0x29a2), true - case "angdnr": - // ACUTE ANGLE + case "angdnr": // ACUTE ANGLE return rune(0x299f), true - case "ange": - // ANGLE WITH UNDERBAR + case "ange": // ANGLE WITH UNDERBAR return rune(0x29a4), true - case "angles": - // ANGLE WITH S INSIDE + case "angle": // ANGLE + return rune(0x2220), true + case "angles": // ANGLE WITH S INSIDE return rune(0x299e), true - case "angle": - // ANGLE - return rune(0x2220), true - case "angmsdaa": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT - return rune(0x29a8), true - case "angmsdab": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT - return rune(0x29a9), true - case "angmsdac": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT - return rune(0x29aa), true - case "angmsdad": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT - return rune(0x29ab), true - case "angmsdae": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP - return rune(0x29ac), true - case "angmsdaf": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP - return rune(0x29ad), true - case "angmsdag": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN - return rune(0x29ae), true - case "angmsdah": - // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN - return rune(0x29af), true - case "angmsd": - // MEASURED ANGLE + case "angmsd": // MEASURED ANGLE return rune(0x2221), true - case "angrtvbd": - // MEASURED RIGHT ANGLE WITH DOT - return rune(0x299d), true - case "angrtvb": - // RIGHT ANGLE WITH ARC + case "angmsdaa": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT + return rune(0x29a8), true + case "angmsdab": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT + return rune(0x29a9), true + case "angmsdac": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT + return rune(0x29aa), true + case "angmsdad": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT + return rune(0x29ab), true + case "angmsdae": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP + return rune(0x29ac), true + case "angmsdaf": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP + return rune(0x29ad), true + case "angmsdag": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN + return rune(0x29ae), true + case "angmsdah": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN + return rune(0x29af), true + case "angrt": // RIGHT ANGLE + return rune(0x221f), true + case "angrtvb": // RIGHT ANGLE WITH ARC return rune(0x22be), true - case "angsph": - // SPHERICAL ANGLE + case "angrtvbd": // MEASURED RIGHT ANGLE WITH DOT + return rune(0x299d), true + case "angsph": // SPHERICAL ANGLE return rune(0x2222), true - case "angst": - // LATIN CAPITAL LETTER A WITH RING ABOVE + case "angst": // LATIN CAPITAL LETTER A WITH RING ABOVE return rune(0xc5), true - case "angupl": - // REVERSED ANGLE + case "angupl": // REVERSED ANGLE return rune(0x29a3), true - case "angzarr": - // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW + case "angzarr": // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW return rune(0x237c), true - case "ang": - // ANGLE - return rune(0x2220), true - case "ang90": - // RIGHT ANGLE - return rune(0x221f), true - case "angrt": - // RIGHT ANGLE - return rune(0x221f), true - case "aogon": - // LATIN SMALL LETTER A WITH OGONEK + case "aogon": // LATIN SMALL LETTER A WITH OGONEK return rune(0x0105), true - case "aopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL A + case "aopf": // MATHEMATICAL DOUBLE-STRUCK SMALL A return rune(0x01d552), true - case "apE": - // APPROXIMATELY EQUAL OR EQUAL TO + case "ap": // ALMOST EQUAL TO + return rune(0x2248), true + case "apE": // APPROXIMATELY EQUAL OR EQUAL TO return rune(0x2a70), true - case "apacir": - // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT + case "apacir": // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT return rune(0x2a6f), true - case "ape": - // ALMOST EQUAL OR EQUAL TO + case "ape": // ALMOST EQUAL OR EQUAL TO return rune(0x224a), true - case "apid": - // TRIPLE TILDE + case "apid": // TRIPLE TILDE return rune(0x224b), true - case "approxeq": - // ALMOST EQUAL OR EQUAL TO - return rune(0x224a), true - case "approx": - // ALMOST EQUAL TO - return rune(0x2248), true - case "ap": - // ALMOST EQUAL TO - return rune(0x2248), true - case "apos": - // APOSTROPHE + case "apos": // APOSTROPHE return rune(0x27), true - case "aring": - // LATIN SMALL LETTER A WITH RING ABOVE - return rune(0xe5), true - case "arrllsr": - // LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW - return rune(0x2943), true - case "arrlrsl": - // RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW - return rune(0x2942), true - case "arrsrll": - // SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW - return rune(0x2944), true - case "ascr": - // MATHEMATICAL SCRIPT SMALL A - return rune(0x01d4b6), true - case "astb": - // SQUARED ASTERISK - return rune(0x29c6), true - case "ast": - // ASTERISK - return rune(0x2a), true - case "asympeq": - // EQUIVALENT TO - return rune(0x224d), true - case "asymp": - // ALMOST EQUAL TO + case "approx": // ALMOST EQUAL TO return rune(0x2248), true - case "atilde": - // LATIN SMALL LETTER A WITH TILDE + case "approxeq": // ALMOST EQUAL OR EQUAL TO + return rune(0x224a), true + case "aring": // LATIN SMALL LETTER A WITH RING ABOVE + return rune(0xe5), true + case "arrllsr": // LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW + return rune(0x2943), true + case "arrlrsl": // RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW + return rune(0x2942), true + case "arrsrll": // SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW + return rune(0x2944), true + case "ascr": // MATHEMATICAL SCRIPT SMALL A + return rune(0x01d4b6), true + case "ast": // ASTERISK + return rune(0x2a), true + case "astb": // SQUARED ASTERISK + return rune(0x29c6), true + case "asymp": // ALMOST EQUAL TO + return rune(0x2248), true + case "asympeq": // EQUIVALENT TO + return rune(0x224d), true + case "atilde": // LATIN SMALL LETTER A WITH TILDE return rune(0xe3), true - case "auml": - // LATIN SMALL LETTER A WITH DIAERESIS + case "auml": // LATIN SMALL LETTER A WITH DIAERESIS return rune(0xe4), true - case "awconint": - // ANTICLOCKWISE CONTOUR INTEGRAL + case "awconint": // ANTICLOCKWISE CONTOUR INTEGRAL return rune(0x2233), true - case "awint": - // ANTICLOCKWISE INTEGRATION + case "awint": // ANTICLOCKWISE INTEGRATION return rune(0x2a11), true } case 'b': switch name { - case "b.Delta": - // MATHEMATICAL BOLD CAPITAL DELTA + case "b.Delta": // MATHEMATICAL BOLD CAPITAL DELTA return rune(0x01d6ab), true - case "b.Gamma": - // MATHEMATICAL BOLD CAPITAL GAMMA + case "b.Gamma": // MATHEMATICAL BOLD CAPITAL GAMMA return rune(0x01d6aa), true - case "b.Gammad": - // MATHEMATICAL BOLD CAPITAL DIGAMMA + case "b.Gammad": // MATHEMATICAL BOLD CAPITAL DIGAMMA return rune(0x01d7ca), true - case "b.Lambda": - // MATHEMATICAL BOLD CAPITAL LAMDA + case "b.Lambda": // MATHEMATICAL BOLD CAPITAL LAMDA return rune(0x01d6b2), true - case "b.Omega": - // MATHEMATICAL BOLD CAPITAL OMEGA + case "b.Omega": // MATHEMATICAL BOLD CAPITAL OMEGA return rune(0x01d6c0), true - case "b.Phi": - // MATHEMATICAL BOLD CAPITAL PHI + case "b.Phi": // MATHEMATICAL BOLD CAPITAL PHI return rune(0x01d6bd), true - case "b.Pi": - // MATHEMATICAL BOLD CAPITAL PI + case "b.Pi": // MATHEMATICAL BOLD CAPITAL PI return rune(0x01d6b7), true - case "b.Psi": - // MATHEMATICAL BOLD CAPITAL PSI + case "b.Psi": // MATHEMATICAL BOLD CAPITAL PSI return rune(0x01d6bf), true - case "b.Sigma": - // MATHEMATICAL BOLD CAPITAL SIGMA + case "b.Sigma": // MATHEMATICAL BOLD CAPITAL SIGMA return rune(0x01d6ba), true - case "b.Theta": - // MATHEMATICAL BOLD CAPITAL THETA + case "b.Theta": // MATHEMATICAL BOLD CAPITAL THETA return rune(0x01d6af), true - case "b.Upsi": - // MATHEMATICAL BOLD CAPITAL UPSILON + case "b.Upsi": // MATHEMATICAL BOLD CAPITAL UPSILON return rune(0x01d6bc), true - case "b.Xi": - // MATHEMATICAL BOLD CAPITAL XI + case "b.Xi": // MATHEMATICAL BOLD CAPITAL XI return rune(0x01d6b5), true - case "b.alpha": - // MATHEMATICAL BOLD SMALL ALPHA + case "b.alpha": // MATHEMATICAL BOLD SMALL ALPHA return rune(0x01d6c2), true - case "b.beta": - // MATHEMATICAL BOLD SMALL BETA + case "b.beta": // MATHEMATICAL BOLD SMALL BETA return rune(0x01d6c3), true - case "b.chi": - // MATHEMATICAL BOLD SMALL CHI + case "b.chi": // MATHEMATICAL BOLD SMALL CHI return rune(0x01d6d8), true - case "b.delta": - // MATHEMATICAL BOLD SMALL DELTA + case "b.delta": // MATHEMATICAL BOLD SMALL DELTA return rune(0x01d6c5), true - case "b.epsi": - // MATHEMATICAL BOLD SMALL EPSILON + case "b.epsi": // MATHEMATICAL BOLD SMALL EPSILON return rune(0x01d6c6), true - case "b.epsiv": - // MATHEMATICAL BOLD EPSILON SYMBOL + case "b.epsiv": // MATHEMATICAL BOLD EPSILON SYMBOL return rune(0x01d6dc), true - case "b.eta": - // MATHEMATICAL BOLD SMALL ETA + case "b.eta": // MATHEMATICAL BOLD SMALL ETA return rune(0x01d6c8), true - case "b.gammad": - // MATHEMATICAL BOLD SMALL DIGAMMA - return rune(0x01d7cb), true - case "b.gamma": - // MATHEMATICAL BOLD SMALL GAMMA + case "b.gamma": // MATHEMATICAL BOLD SMALL GAMMA return rune(0x01d6c4), true - case "b.iota": - // MATHEMATICAL BOLD SMALL IOTA + case "b.gammad": // MATHEMATICAL BOLD SMALL DIGAMMA + return rune(0x01d7cb), true + case "b.iota": // MATHEMATICAL BOLD SMALL IOTA return rune(0x01d6ca), true - case "b.kappa": - // MATHEMATICAL BOLD SMALL KAPPA + case "b.kappa": // MATHEMATICAL BOLD SMALL KAPPA return rune(0x01d6cb), true - case "b.kappav": - // MATHEMATICAL BOLD KAPPA SYMBOL + case "b.kappav": // MATHEMATICAL BOLD KAPPA SYMBOL return rune(0x01d6de), true - case "b.lambda": - // MATHEMATICAL BOLD SMALL LAMDA + case "b.lambda": // MATHEMATICAL BOLD SMALL LAMDA return rune(0x01d6cc), true - case "b.mu": - // MATHEMATICAL BOLD SMALL MU + case "b.mu": // MATHEMATICAL BOLD SMALL MU return rune(0x01d6cd), true - case "b.nu": - // MATHEMATICAL BOLD SMALL NU + case "b.nu": // MATHEMATICAL BOLD SMALL NU return rune(0x01d6ce), true - case "b.omega": - // MATHEMATICAL BOLD SMALL OMEGA + case "b.omega": // MATHEMATICAL BOLD SMALL OMEGA return rune(0x01d6da), true - case "b.phi": - // MATHEMATICAL BOLD SMALL PHI + case "b.phi": // MATHEMATICAL BOLD SMALL PHI return rune(0x01d6d7), true - case "b.phiv": - // MATHEMATICAL BOLD PHI SYMBOL + case "b.phiv": // MATHEMATICAL BOLD PHI SYMBOL return rune(0x01d6df), true - case "b.pi": - // MATHEMATICAL BOLD SMALL PI + case "b.pi": // MATHEMATICAL BOLD SMALL PI return rune(0x01d6d1), true - case "b.piv": - // MATHEMATICAL BOLD PI SYMBOL + case "b.piv": // MATHEMATICAL BOLD PI SYMBOL return rune(0x01d6e1), true - case "b.psi": - // MATHEMATICAL BOLD SMALL PSI + case "b.psi": // MATHEMATICAL BOLD SMALL PSI return rune(0x01d6d9), true - case "b.rho": - // MATHEMATICAL BOLD SMALL RHO + case "b.rho": // MATHEMATICAL BOLD SMALL RHO return rune(0x01d6d2), true - case "b.rhov": - // MATHEMATICAL BOLD RHO SYMBOL + case "b.rhov": // MATHEMATICAL BOLD RHO SYMBOL return rune(0x01d6e0), true - case "b.sigmav": - // MATHEMATICAL BOLD SMALL FINAL SIGMA - return rune(0x01d6d3), true - case "b.sigma": - // MATHEMATICAL BOLD SMALL SIGMA + case "b.sigma": // MATHEMATICAL BOLD SMALL SIGMA return rune(0x01d6d4), true - case "b.tau": - // MATHEMATICAL BOLD SMALL TAU + case "b.sigmav": // MATHEMATICAL BOLD SMALL FINAL SIGMA + return rune(0x01d6d3), true + case "b.tau": // MATHEMATICAL BOLD SMALL TAU return rune(0x01d6d5), true - case "b.thetas": - // MATHEMATICAL BOLD SMALL THETA + case "b.thetas": // MATHEMATICAL BOLD SMALL THETA return rune(0x01d6c9), true - case "b.thetav": - // MATHEMATICAL BOLD THETA SYMBOL + case "b.thetav": // MATHEMATICAL BOLD THETA SYMBOL return rune(0x01d6dd), true - case "b.upsi": - // MATHEMATICAL BOLD SMALL UPSILON + case "b.upsi": // MATHEMATICAL BOLD SMALL UPSILON return rune(0x01d6d6), true - case "b.xi": - // MATHEMATICAL BOLD SMALL XI + case "b.xi": // MATHEMATICAL BOLD SMALL XI return rune(0x01d6cf), true - case "b.zeta": - // MATHEMATICAL BOLD SMALL ZETA + case "b.zeta": // MATHEMATICAL BOLD SMALL ZETA return rune(0x01d6c7), true - case "bNot": - // REVERSED DOUBLE STROKE NOT SIGN + case "bNot": // REVERSED DOUBLE STROKE NOT SIGN return rune(0x2aed), true - case "backcong": - // ALL EQUAL TO + case "backcong": // ALL EQUAL TO return rune(0x224c), true - case "backepsilon": - // GREEK REVERSED LUNATE EPSILON SYMBOL + case "backepsilon": // GREEK REVERSED LUNATE EPSILON SYMBOL return rune(0x03f6), true - case "backprime": - // REVERSED PRIME + case "backprime": // REVERSED PRIME return rune(0x2035), true - case "backsimeq": - // REVERSED TILDE EQUALS - return rune(0x22cd), true - case "backsim": - // REVERSED TILDE + case "backsim": // REVERSED TILDE return rune(0x223d), true - case "barV": - // DOUBLE DOWN TACK + case "backsimeq": // REVERSED TILDE EQUALS + return rune(0x22cd), true + case "barV": // DOUBLE DOWN TACK return rune(0x2aea), true - case "barvee": - // NOR + case "barvee": // NOR return rune(0x22bd), true - case "barwed": - // PROJECTIVE + case "barwed": // PROJECTIVE return rune(0x2305), true - case "barwedge": - // PROJECTIVE + case "barwedge": // PROJECTIVE return rune(0x2305), true - case "bbrk": - // BOTTOM SQUARE BRACKET + case "bbrk": // BOTTOM SQUARE BRACKET return rune(0x23b5), true - case "bbrktbrk": - // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET + case "bbrktbrk": // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET return rune(0x23b6), true - case "bcong": - // ALL EQUAL TO + case "bcong": // ALL EQUAL TO return rune(0x224c), true - case "bcy": - // CYRILLIC SMALL LETTER BE + case "bcy": // CYRILLIC SMALL LETTER BE return rune(0x0431), true - case "bdlhar": - // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR + case "bdlhar": // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR return rune(0x2961), true - case "bdquo": - // DOUBLE LOW-9 QUOTATION MARK + case "bdquo": // DOUBLE LOW-9 QUOTATION MARK return rune(0x201e), true - case "bdrhar": - // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR + case "bdrhar": // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR return rune(0x295d), true - case "because": - // BECAUSE + case "becaus": // BECAUSE return rune(0x2235), true - case "becaus": - // BECAUSE + case "because": // BECAUSE return rune(0x2235), true - case "bemptyv": - // REVERSED EMPTY SET + case "bemptyv": // REVERSED EMPTY SET return rune(0x29b0), true - case "bepsi": - // GREEK REVERSED LUNATE EPSILON SYMBOL + case "bepsi": // GREEK REVERSED LUNATE EPSILON SYMBOL return rune(0x03f6), true - case "bernou": - // SCRIPT CAPITAL B + case "bernou": // SCRIPT CAPITAL B return rune(0x212c), true - case "beta": - // GREEK SMALL LETTER BETA + case "beta": // GREEK SMALL LETTER BETA return rune(0x03b2), true - case "beth": - // BET SYMBOL + case "beth": // BET SYMBOL return rune(0x2136), true - case "between": - // BETWEEN + case "between": // BETWEEN return rune(0x226c), true - case "bfr": - // MATHEMATICAL FRAKTUR SMALL B + case "bfr": // MATHEMATICAL FRAKTUR SMALL B return rune(0x01d51f), true - case "bgr": - // GREEK SMALL LETTER BETA + case "bgr": // GREEK SMALL LETTER BETA return rune(0x03b2), true - case "bigcap": - // N-ARY INTERSECTION + case "bigcap": // N-ARY INTERSECTION return rune(0x22c2), true - case "bigcirc": - // LARGE CIRCLE + case "bigcirc": // LARGE CIRCLE return rune(0x25ef), true - case "bigcup": - // N-ARY UNION + case "bigcup": // N-ARY UNION return rune(0x22c3), true - case "bigodot": - // N-ARY CIRCLED DOT OPERATOR + case "bigodot": // N-ARY CIRCLED DOT OPERATOR return rune(0x2a00), true - case "bigoplus": - // N-ARY CIRCLED PLUS OPERATOR + case "bigoplus": // N-ARY CIRCLED PLUS OPERATOR return rune(0x2a01), true - case "bigotimes": - // N-ARY CIRCLED TIMES OPERATOR + case "bigotimes": // N-ARY CIRCLED TIMES OPERATOR return rune(0x2a02), true - case "bigsqcup": - // N-ARY SQUARE UNION OPERATOR + case "bigsqcup": // N-ARY SQUARE UNION OPERATOR return rune(0x2a06), true - case "bigstar": - // BLACK STAR + case "bigstar": // BLACK STAR return rune(0x2605), true - case "bigtriangledown": - // WHITE DOWN-POINTING TRIANGLE + case "bigtriangledown": // WHITE DOWN-POINTING TRIANGLE return rune(0x25bd), true - case "bigtriangleup": - // WHITE UP-POINTING TRIANGLE + case "bigtriangleup": // WHITE UP-POINTING TRIANGLE return rune(0x25b3), true - case "biguplus": - // N-ARY UNION OPERATOR WITH PLUS + case "biguplus": // N-ARY UNION OPERATOR WITH PLUS return rune(0x2a04), true - case "bigvee": - // N-ARY LOGICAL OR + case "bigvee": // N-ARY LOGICAL OR return rune(0x22c1), true - case "bigwedge": - // N-ARY LOGICAL AND + case "bigwedge": // N-ARY LOGICAL AND return rune(0x22c0), true - case "bkarow": - // RIGHTWARDS DOUBLE DASH ARROW + case "bkarow": // RIGHTWARDS DOUBLE DASH ARROW return rune(0x290d), true - case "blacklozenge": - // BLACK LOZENGE + case "blacklozenge": // BLACK LOZENGE return rune(0x29eb), true - case "blacksquare": - // BLACK SMALL SQUARE + case "blacksquare": // BLACK SMALL SQUARE return rune(0x25aa), true - case "blacktriangledown": - // BLACK DOWN-POINTING SMALL TRIANGLE - return rune(0x25be), true - case "blacktriangleleft": - // BLACK LEFT-POINTING SMALL TRIANGLE - return rune(0x25c2), true - case "blacktriangleright": - // BLACK RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b8), true - case "blacktriangle": - // BLACK UP-POINTING SMALL TRIANGLE + case "blacktriangle": // BLACK UP-POINTING SMALL TRIANGLE return rune(0x25b4), true - case "blank": - // BLANK SYMBOL + case "blacktriangledown": // BLACK DOWN-POINTING SMALL TRIANGLE + return rune(0x25be), true + case "blacktriangleleft": // BLACK LEFT-POINTING SMALL TRIANGLE + return rune(0x25c2), true + case "blacktriangleright": // BLACK RIGHT-POINTING SMALL TRIANGLE + return rune(0x25b8), true + case "blank": // BLANK SYMBOL return rune(0x2422), true - case "bldhar": - // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR + case "bldhar": // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR return rune(0x295e), true - case "blk12": - // MEDIUM SHADE + case "blk12": // MEDIUM SHADE return rune(0x2592), true - case "blk14": - // LIGHT SHADE + case "blk14": // LIGHT SHADE return rune(0x2591), true - case "blk34": - // DARK SHADE + case "blk34": // DARK SHADE return rune(0x2593), true - case "block": - // FULL BLOCK + case "block": // FULL BLOCK return rune(0x2588), true - case "bluhar": - // LEFTWARDS HARPOON WITH BARB UP FROM BAR + case "bluhar": // LEFTWARDS HARPOON WITH BARB UP FROM BAR return rune(0x295a), true - case "bnequiv": - // IDENTICAL TO with reverse slash - return rune(0x2261), true - case "bne": - // EQUALS SIGN with reverse slash + case "bne": // EQUALS SIGN with reverse slash return rune(0x3d), true - case "bnot": - // REVERSED NOT SIGN + case "bnequiv": // IDENTICAL TO with reverse slash + return rune(0x2261), true + case "bnot": // REVERSED NOT SIGN return rune(0x2310), true - case "bopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL B + case "bopf": // MATHEMATICAL DOUBLE-STRUCK SMALL B return rune(0x01d553), true - case "bot": - // UP TACK + case "bot": // UP TACK return rune(0x22a5), true - case "bottom": - // UP TACK + case "bottom": // UP TACK return rune(0x22a5), true - case "bowtie": - // BOWTIE + case "bowtie": // BOWTIE return rune(0x22c8), true - case "boxDL": - // BOX DRAWINGS DOUBLE DOWN AND LEFT + case "boxDL": // BOX DRAWINGS DOUBLE DOWN AND LEFT return rune(0x2557), true - case "boxDR": - // BOX DRAWINGS DOUBLE DOWN AND RIGHT + case "boxDR": // BOX DRAWINGS DOUBLE DOWN AND RIGHT return rune(0x2554), true - case "boxDl": - // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + case "boxDl": // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE return rune(0x2556), true - case "boxDr": - // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + case "boxDr": // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE return rune(0x2553), true - case "boxHD": - // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - return rune(0x2566), true - case "boxHU": - // BOX DRAWINGS DOUBLE UP AND HORIZONTAL - return rune(0x2569), true - case "boxHd": - // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - return rune(0x2564), true - case "boxHu": - // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - return rune(0x2567), true - case "boxH": - // BOX DRAWINGS DOUBLE HORIZONTAL + case "boxH": // BOX DRAWINGS DOUBLE HORIZONTAL return rune(0x2550), true - case "boxUL": - // BOX DRAWINGS DOUBLE UP AND LEFT + case "boxHD": // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + return rune(0x2566), true + case "boxHU": // BOX DRAWINGS DOUBLE UP AND HORIZONTAL + return rune(0x2569), true + case "boxHd": // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + return rune(0x2564), true + case "boxHu": // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + return rune(0x2567), true + case "boxUL": // BOX DRAWINGS DOUBLE UP AND LEFT return rune(0x255d), true - case "boxUR": - // BOX DRAWINGS DOUBLE UP AND RIGHT + case "boxUR": // BOX DRAWINGS DOUBLE UP AND RIGHT return rune(0x255a), true - case "boxUl": - // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + case "boxUl": // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE return rune(0x255c), true - case "boxUr": - // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + case "boxUr": // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE return rune(0x2559), true - case "boxVH": - // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - return rune(0x256c), true - case "boxVL": - // BOX DRAWINGS DOUBLE VERTICAL AND LEFT - return rune(0x2563), true - case "boxVR": - // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - return rune(0x2560), true - case "boxVh": - // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - return rune(0x256b), true - case "boxVl": - // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - return rune(0x2562), true - case "boxVr": - // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - return rune(0x255f), true - case "boxV": - // BOX DRAWINGS DOUBLE VERTICAL + case "boxV": // BOX DRAWINGS DOUBLE VERTICAL return rune(0x2551), true - case "boxbox": - // TWO JOINED SQUARES + case "boxVH": // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + return rune(0x256c), true + case "boxVL": // BOX DRAWINGS DOUBLE VERTICAL AND LEFT + return rune(0x2563), true + case "boxVR": // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + return rune(0x2560), true + case "boxVh": // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + return rune(0x256b), true + case "boxVl": // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + return rune(0x2562), true + case "boxVr": // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + return rune(0x255f), true + case "boxbox": // TWO JOINED SQUARES return rune(0x29c9), true - case "boxdL": - // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + case "boxdL": // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE return rune(0x2555), true - case "boxdR": - // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + case "boxdR": // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE return rune(0x2552), true - case "boxdl": - // BOX DRAWINGS LIGHT DOWN AND LEFT + case "boxdl": // BOX DRAWINGS LIGHT DOWN AND LEFT return rune(0x2510), true - case "boxdr": - // BOX DRAWINGS LIGHT DOWN AND RIGHT + case "boxdr": // BOX DRAWINGS LIGHT DOWN AND RIGHT return rune(0x250c), true - case "boxhU": - // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - return rune(0x2568), true - case "boxh": - // BOX DRAWINGS LIGHT HORIZONTAL + case "boxh": // BOX DRAWINGS LIGHT HORIZONTAL return rune(0x2500), true - case "boxhD": - // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + case "boxhD": // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE return rune(0x2565), true - case "boxhd": - // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + case "boxhU": // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + return rune(0x2568), true + case "boxhd": // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL return rune(0x252c), true - case "boxhu": - // BOX DRAWINGS LIGHT UP AND HORIZONTAL + case "boxhu": // BOX DRAWINGS LIGHT UP AND HORIZONTAL return rune(0x2534), true - case "boxminus": - // SQUARED MINUS + case "boxminus": // SQUARED MINUS return rune(0x229f), true - case "boxplus": - // SQUARED PLUS + case "boxplus": // SQUARED PLUS return rune(0x229e), true - case "boxtimes": - // SQUARED TIMES + case "boxtimes": // SQUARED TIMES return rune(0x22a0), true - case "boxuL": - // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + case "boxuL": // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE return rune(0x255b), true - case "boxuR": - // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + case "boxuR": // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE return rune(0x2558), true - case "boxul": - // BOX DRAWINGS LIGHT UP AND LEFT + case "boxul": // BOX DRAWINGS LIGHT UP AND LEFT return rune(0x2518), true - case "boxur": - // BOX DRAWINGS LIGHT UP AND RIGHT + case "boxur": // BOX DRAWINGS LIGHT UP AND RIGHT return rune(0x2514), true - case "boxvL": - // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - return rune(0x2561), true - case "boxvR": - // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - return rune(0x255e), true - case "boxvl": - // BOX DRAWINGS LIGHT VERTICAL AND LEFT - return rune(0x2524), true - case "boxvr": - // BOX DRAWINGS LIGHT VERTICAL AND RIGHT - return rune(0x251c), true - case "boxv": - // BOX DRAWINGS LIGHT VERTICAL + case "boxv": // BOX DRAWINGS LIGHT VERTICAL return rune(0x2502), true - case "boxvH": - // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + case "boxvH": // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE return rune(0x256a), true - case "boxvh": - // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + case "boxvL": // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + return rune(0x2561), true + case "boxvR": // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + return rune(0x255e), true + case "boxvh": // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL return rune(0x253c), true - case "bprime": - // REVERSED PRIME + case "boxvl": // BOX DRAWINGS LIGHT VERTICAL AND LEFT + return rune(0x2524), true + case "boxvr": // BOX DRAWINGS LIGHT VERTICAL AND RIGHT + return rune(0x251c), true + case "bprime": // REVERSED PRIME return rune(0x2035), true - case "brdhar": - // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR + case "brdhar": // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR return rune(0x295f), true - case "breve": - // BREVE + case "breve": // BREVE return rune(0x02d8), true - case "bruhar": - // RIGHTWARDS HARPOON WITH BARB UP FROM BAR + case "bruhar": // RIGHTWARDS HARPOON WITH BARB UP FROM BAR return rune(0x295b), true - case "brvbar": - // BROKEN BAR + case "brvbar": // BROKEN BAR return rune(0xa6), true - case "bscr": - // MATHEMATICAL SCRIPT SMALL B + case "bscr": // MATHEMATICAL SCRIPT SMALL B return rune(0x01d4b7), true - case "bsemi": - // REVERSED SEMICOLON + case "bsemi": // REVERSED SEMICOLON return rune(0x204f), true - case "bsim": - // REVERSED TILDE + case "bsim": // REVERSED TILDE return rune(0x223d), true - case "bsime": - // REVERSED TILDE EQUALS + case "bsime": // REVERSED TILDE EQUALS return rune(0x22cd), true - case "bsolb": - // SQUARED FALLING DIAGONAL SLASH - return rune(0x29c5), true - case "bsolhsub": - // REVERSE SOLIDUS PRECEDING SUBSET - return rune(0x27c8), true - case "bsol": - // REVERSE SOLIDUS + case "bsol": // REVERSE SOLIDUS return rune(0x5c), true - case "btimes": - // SEMIDIRECT PRODUCT WITH BOTTOM CLOSED + case "bsolb": // SQUARED FALLING DIAGONAL SLASH + return rune(0x29c5), true + case "bsolhsub": // REVERSE SOLIDUS PRECEDING SUBSET + return rune(0x27c8), true + case "btimes": // SEMIDIRECT PRODUCT WITH BOTTOM CLOSED return rune(0x2a32), true - case "bulhar": - // UPWARDS HARPOON WITH BARB LEFT FROM BAR + case "bulhar": // UPWARDS HARPOON WITH BARB LEFT FROM BAR return rune(0x2960), true - case "bullet": - // BULLET + case "bull": // BULLET return rune(0x2022), true - case "bull": - // BULLET + case "bullet": // BULLET return rune(0x2022), true - case "bump": - // GEOMETRICALLY EQUIVALENT TO + case "bump": // GEOMETRICALLY EQUIVALENT TO return rune(0x224e), true - case "bumpE": - // EQUALS SIGN WITH BUMPY ABOVE + case "bumpE": // EQUALS SIGN WITH BUMPY ABOVE return rune(0x2aae), true - case "bumpe": - // DIFFERENCE BETWEEN + case "bumpe": // DIFFERENCE BETWEEN return rune(0x224f), true - case "bumpeq": - // DIFFERENCE BETWEEN + case "bumpeq": // DIFFERENCE BETWEEN return rune(0x224f), true - case "burhar": - // UPWARDS HARPOON WITH BARB RIGHT FROM BAR + case "burhar": // UPWARDS HARPOON WITH BARB RIGHT FROM BAR return rune(0x295c), true } case 'c': switch name { - case "cacute": - // LATIN SMALL LETTER C WITH ACUTE + case "cacute": // LATIN SMALL LETTER C WITH ACUTE return rune(0x0107), true - case "cap": - // INTERSECTION + case "cap": // INTERSECTION return rune(0x2229), true - case "capand": - // INTERSECTION WITH LOGICAL AND + case "capand": // INTERSECTION WITH LOGICAL AND return rune(0x2a44), true - case "capbrcup": - // INTERSECTION ABOVE BAR ABOVE UNION + case "capbrcup": // INTERSECTION ABOVE BAR ABOVE UNION return rune(0x2a49), true - case "capcap": - // INTERSECTION BESIDE AND JOINED WITH INTERSECTION + case "capcap": // INTERSECTION BESIDE AND JOINED WITH INTERSECTION return rune(0x2a4b), true - case "capcup": - // INTERSECTION ABOVE UNION + case "capcup": // INTERSECTION ABOVE UNION return rune(0x2a47), true - case "capdot": - // INTERSECTION WITH DOT + case "capdot": // INTERSECTION WITH DOT return rune(0x2a40), true - case "capint": - // INTEGRAL WITH INTERSECTION + case "capint": // INTEGRAL WITH INTERSECTION return rune(0x2a19), true - case "caps": - // INTERSECTION with serifs + case "caps": // INTERSECTION with serifs return rune(0x2229), true - case "caret": - // CARET INSERTION POINT + case "caret": // CARET INSERTION POINT return rune(0x2041), true - case "caron": - // CARON + case "caron": // CARON return rune(0x02c7), true - case "ccaps": - // CLOSED INTERSECTION WITH SERIFS + case "ccaps": // CLOSED INTERSECTION WITH SERIFS return rune(0x2a4d), true - case "ccaron": - // LATIN SMALL LETTER C WITH CARON + case "ccaron": // LATIN SMALL LETTER C WITH CARON return rune(0x010d), true - case "ccedil": - // LATIN SMALL LETTER C WITH CEDILLA + case "ccedil": // LATIN SMALL LETTER C WITH CEDILLA return rune(0xe7), true - case "ccirc": - // LATIN SMALL LETTER C WITH CIRCUMFLEX + case "ccirc": // LATIN SMALL LETTER C WITH CIRCUMFLEX return rune(0x0109), true - case "ccups": - // CLOSED UNION WITH SERIFS + case "ccups": // CLOSED UNION WITH SERIFS return rune(0x2a4c), true - case "ccupssm": - // CLOSED UNION WITH SERIFS AND SMASH PRODUCT + case "ccupssm": // CLOSED UNION WITH SERIFS AND SMASH PRODUCT return rune(0x2a50), true - case "cdot": - // LATIN SMALL LETTER C WITH DOT ABOVE + case "cdot": // LATIN SMALL LETTER C WITH DOT ABOVE return rune(0x010b), true - case "cedil": - // CEDILLA + case "cedil": // CEDILLA return rune(0xb8), true - case "cemptyv": - // EMPTY SET WITH SMALL CIRCLE ABOVE + case "cemptyv": // EMPTY SET WITH SMALL CIRCLE ABOVE return rune(0x29b2), true - case "centerdot": - // MIDDLE DOT - return rune(0xb7), true - case "cent": - // CENT SIGN + case "cent": // CENT SIGN return rune(0xa2), true - case "cfr": - // MATHEMATICAL FRAKTUR SMALL C + case "centerdot": // MIDDLE DOT + return rune(0xb7), true + case "cfr": // MATHEMATICAL FRAKTUR SMALL C return rune(0x01d520), true - case "chcy": - // CYRILLIC SMALL LETTER CHE + case "chcy": // CYRILLIC SMALL LETTER CHE return rune(0x0447), true - case "check": - // CHECK MARK + case "check": // CHECK MARK return rune(0x2713), true - case "checkmark": - // CHECK MARK + case "checkmark": // CHECK MARK return rune(0x2713), true - case "chi": - // GREEK SMALL LETTER CHI + case "chi": // GREEK SMALL LETTER CHI return rune(0x03c7), true - case "circeq": - // RING EQUAL TO - return rune(0x2257), true - case "circlearrowleft": - // ANTICLOCKWISE OPEN CIRCLE ARROW - return rune(0x21ba), true - case "circlearrowright": - // CLOCKWISE OPEN CIRCLE ARROW - return rune(0x21bb), true - case "circledS": - // CIRCLED LATIN CAPITAL LETTER S - return rune(0x24c8), true - case "circledast": - // CIRCLED ASTERISK OPERATOR - return rune(0x229b), true - case "circledcirc": - // CIRCLED RING OPERATOR - return rune(0x229a), true - case "circleddash": - // CIRCLED DASH - return rune(0x229d), true - case "cire": - // RING EQUAL TO - return rune(0x2257), true - case "cir": - // WHITE CIRCLE + case "cir": // WHITE CIRCLE return rune(0x25cb), true - case "cirE": - // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT + case "cirE": // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT return rune(0x29c3), true - case "cirb": - // SQUARED SMALL CIRCLE + case "cirb": // SQUARED SMALL CIRCLE return rune(0x29c7), true - case "circ": - // MODIFIER LETTER CIRCUMFLEX ACCENT + case "circ": // MODIFIER LETTER CIRCUMFLEX ACCENT return rune(0x02c6), true - case "circledR": - // REGISTERED SIGN + case "circeq": // RING EQUAL TO + return rune(0x2257), true + case "circlearrowleft": // ANTICLOCKWISE OPEN CIRCLE ARROW + return rune(0x21ba), true + case "circlearrowright": // CLOCKWISE OPEN CIRCLE ARROW + return rune(0x21bb), true + case "circledR": // REGISTERED SIGN return rune(0xae), true - case "cirdarr": - // WHITE CIRCLE WITH DOWN ARROW + case "circledS": // CIRCLED LATIN CAPITAL LETTER S + return rune(0x24c8), true + case "circledast": // CIRCLED ASTERISK OPERATOR + return rune(0x229b), true + case "circledcirc": // CIRCLED RING OPERATOR + return rune(0x229a), true + case "circleddash": // CIRCLED DASH + return rune(0x229d), true + case "cirdarr": // WHITE CIRCLE WITH DOWN ARROW return rune(0x29ec), true - case "cirerr": - // ERROR-BARRED WHITE CIRCLE + case "cire": // RING EQUAL TO + return rune(0x2257), true + case "cirerr": // ERROR-BARRED WHITE CIRCLE return rune(0x29f2), true - case "cirfdarr": - // BLACK CIRCLE WITH DOWN ARROW + case "cirfdarr": // BLACK CIRCLE WITH DOWN ARROW return rune(0x29ed), true - case "cirferr": - // ERROR-BARRED BLACK CIRCLE + case "cirferr": // ERROR-BARRED BLACK CIRCLE return rune(0x29f3), true - case "cirfnint": - // CIRCULATION FUNCTION + case "cirfnint": // CIRCULATION FUNCTION return rune(0x2a10), true - case "cirmid": - // VERTICAL LINE WITH CIRCLE ABOVE + case "cirmid": // VERTICAL LINE WITH CIRCLE ABOVE return rune(0x2aef), true - case "cirscir": - // CIRCLE WITH SMALL CIRCLE TO THE RIGHT + case "cirscir": // CIRCLE WITH SMALL CIRCLE TO THE RIGHT return rune(0x29c2), true - case "closur": - // CLOSE UP + case "closur": // CLOSE UP return rune(0x2050), true - case "clubs": - // BLACK CLUB SUIT + case "clubs": // BLACK CLUB SUIT return rune(0x2663), true - case "clubsuit": - // BLACK CLUB SUIT + case "clubsuit": // BLACK CLUB SUIT return rune(0x2663), true - case "colone": - // COLON EQUALS - return rune(0x2254), true - case "coloneq": - // COLON EQUALS - return rune(0x2254), true - case "colon": - // COLON + case "colon": // COLON return rune(0x3a), true - case "commat": - // COMMERCIAL AT - return rune(0x40), true - case "comma": - // COMMA + case "colone": // COLON EQUALS + return rune(0x2254), true + case "coloneq": // COLON EQUALS + return rune(0x2254), true + case "comma": // COMMA return rune(0x2c), true - case "comp": - // COMPLEMENT + case "commat": // COMMERCIAL AT + return rune(0x40), true + case "comp": // COMPLEMENT return rune(0x2201), true - case "compfn": - // RING OPERATOR + case "compfn": // RING OPERATOR return rune(0x2218), true - case "complement": - // COMPLEMENT + case "complement": // COMPLEMENT return rune(0x2201), true - case "complexes": - // DOUBLE-STRUCK CAPITAL C + case "complexes": // DOUBLE-STRUCK CAPITAL C return rune(0x2102), true - case "cong": - // APPROXIMATELY EQUAL TO + case "cong": // APPROXIMATELY EQUAL TO return rune(0x2245), true - case "congdot": - // CONGRUENT WITH DOT ABOVE + case "congdot": // CONGRUENT WITH DOT ABOVE return rune(0x2a6d), true - case "conint": - // CONTOUR INTEGRAL + case "conint": // CONTOUR INTEGRAL return rune(0x222e), true - case "copf": - // MATHEMATICAL DOUBLE-STRUCK SMALL C + case "copf": // MATHEMATICAL DOUBLE-STRUCK SMALL C return rune(0x01d554), true - case "coprod": - // N-ARY COPRODUCT + case "coprod": // N-ARY COPRODUCT return rune(0x2210), true - case "copysr": - // SOUND RECORDING COPYRIGHT - return rune(0x2117), true - case "copy": - // COPYRIGHT SIGN + case "copy": // COPYRIGHT SIGN return rune(0xa9), true - case "crarr": - // DOWNWARDS ARROW WITH CORNER LEFTWARDS + case "copysr": // SOUND RECORDING COPYRIGHT + return rune(0x2117), true + case "crarr": // DOWNWARDS ARROW WITH CORNER LEFTWARDS return rune(0x21b5), true - case "cross": - // BALLOT X + case "cross": // BALLOT X return rune(0x2717), true - case "cscr": - // MATHEMATICAL SCRIPT SMALL C + case "cscr": // MATHEMATICAL SCRIPT SMALL C return rune(0x01d4b8), true - case "csub": - // CLOSED SUBSET + case "csub": // CLOSED SUBSET return rune(0x2acf), true - case "csube": - // CLOSED SUBSET OR EQUAL TO + case "csube": // CLOSED SUBSET OR EQUAL TO return rune(0x2ad1), true - case "csup": - // CLOSED SUPERSET + case "csup": // CLOSED SUPERSET return rune(0x2ad0), true - case "csupe": - // CLOSED SUPERSET OR EQUAL TO + case "csupe": // CLOSED SUPERSET OR EQUAL TO return rune(0x2ad2), true - case "ctdot": - // MIDLINE HORIZONTAL ELLIPSIS + case "ctdot": // MIDLINE HORIZONTAL ELLIPSIS return rune(0x22ef), true - case "cudarrl": - // RIGHT-SIDE ARC CLOCKWISE ARROW + case "cudarrl": // RIGHT-SIDE ARC CLOCKWISE ARROW return rune(0x2938), true - case "cudarrr": - // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS + case "cudarrr": // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS return rune(0x2935), true - case "cuepr": - // EQUAL TO OR PRECEDES + case "cuepr": // EQUAL TO OR PRECEDES return rune(0x22de), true - case "cuesc": - // EQUAL TO OR SUCCEEDS + case "cuesc": // EQUAL TO OR SUCCEEDS return rune(0x22df), true - case "cularr": - // ANTICLOCKWISE TOP SEMICIRCLE ARROW + case "cularr": // ANTICLOCKWISE TOP SEMICIRCLE ARROW return rune(0x21b6), true - case "cularrp": - // TOP ARC ANTICLOCKWISE ARROW WITH PLUS + case "cularrp": // TOP ARC ANTICLOCKWISE ARROW WITH PLUS return rune(0x293d), true - case "cup": - // UNION + case "cup": // UNION return rune(0x222a), true - case "cupbrcap": - // UNION ABOVE BAR ABOVE INTERSECTION + case "cupbrcap": // UNION ABOVE BAR ABOVE INTERSECTION return rune(0x2a48), true - case "cupcap": - // UNION ABOVE INTERSECTION + case "cupcap": // UNION ABOVE INTERSECTION return rune(0x2a46), true - case "cupcup": - // UNION BESIDE AND JOINED WITH UNION + case "cupcup": // UNION BESIDE AND JOINED WITH UNION return rune(0x2a4a), true - case "cupdot": - // MULTISET MULTIPLICATION + case "cupdot": // MULTISET MULTIPLICATION return rune(0x228d), true - case "cupint": - // INTEGRAL WITH UNION + case "cupint": // INTEGRAL WITH UNION return rune(0x2a1a), true - case "cupor": - // UNION WITH LOGICAL OR + case "cupor": // UNION WITH LOGICAL OR return rune(0x2a45), true - case "cupre": - // PRECEDES OR EQUAL TO + case "cupre": // PRECEDES OR EQUAL TO return rune(0x227c), true - case "cups": - // UNION with serifs + case "cups": // UNION with serifs return rune(0x222a), true - case "curarr": - // CLOCKWISE TOP SEMICIRCLE ARROW + case "curarr": // CLOCKWISE TOP SEMICIRCLE ARROW return rune(0x21b7), true - case "curarrm": - // TOP ARC CLOCKWISE ARROW WITH MINUS + case "curarrm": // TOP ARC CLOCKWISE ARROW WITH MINUS return rune(0x293c), true - case "curlyeqprec": - // EQUAL TO OR PRECEDES + case "curlyeqprec": // EQUAL TO OR PRECEDES return rune(0x22de), true - case "curlyeqsucc": - // EQUAL TO OR SUCCEEDS + case "curlyeqsucc": // EQUAL TO OR SUCCEEDS return rune(0x22df), true - case "curlyvee": - // CURLY LOGICAL OR + case "curlyvee": // CURLY LOGICAL OR return rune(0x22ce), true - case "curlywedge": - // CURLY LOGICAL AND + case "curlywedge": // CURLY LOGICAL AND return rune(0x22cf), true - case "curren": - // CURRENCY SIGN + case "curren": // CURRENCY SIGN return rune(0xa4), true - case "curvearrowleft": - // ANTICLOCKWISE TOP SEMICIRCLE ARROW + case "curvearrowleft": // ANTICLOCKWISE TOP SEMICIRCLE ARROW return rune(0x21b6), true - case "curvearrowright": - // CLOCKWISE TOP SEMICIRCLE ARROW + case "curvearrowright": // CLOCKWISE TOP SEMICIRCLE ARROW return rune(0x21b7), true - case "cuvee": - // CURLY LOGICAL OR + case "cuvee": // CURLY LOGICAL OR return rune(0x22ce), true - case "cuwed": - // CURLY LOGICAL AND + case "cuwed": // CURLY LOGICAL AND return rune(0x22cf), true - case "cwconint": - // CLOCKWISE CONTOUR INTEGRAL + case "cwconint": // CLOCKWISE CONTOUR INTEGRAL return rune(0x2232), true - case "cwint": - // CLOCKWISE INTEGRAL + case "cwint": // CLOCKWISE INTEGRAL return rune(0x2231), true - case "cylcty": - // CYLINDRICITY + case "cylcty": // CYLINDRICITY return rune(0x232d), true } case 'd': switch name { - case "dAarr": - // DOWNWARDS TRIPLE ARROW + case "dAarr": // DOWNWARDS TRIPLE ARROW return rune(0x290b), true - case "dArr": - // DOWNWARDS DOUBLE ARROW + case "dArr": // DOWNWARDS DOUBLE ARROW return rune(0x21d3), true - case "dHar": - // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + case "dHar": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT return rune(0x2965), true - case "dagger": - // DAGGER + case "dagger": // DAGGER return rune(0x2020), true - case "dalembrt": - // SQUARE WITH CONTOURED OUTLINE + case "dalembrt": // SQUARE WITH CONTOURED OUTLINE return rune(0x29e0), true - case "daleth": - // DALET SYMBOL + case "daleth": // DALET SYMBOL return rune(0x2138), true - case "darr2": - // DOWNWARDS PAIRED ARROWS - return rune(0x21ca), true - case "darr": - // DOWNWARDS ARROW + case "darr": // DOWNWARDS ARROW return rune(0x2193), true - case "darrb": - // DOWNWARDS ARROW TO BAR + case "darr2": // DOWNWARDS PAIRED ARROWS + return rune(0x21ca), true + case "darrb": // DOWNWARDS ARROW TO BAR return rune(0x2913), true - case "darrln": - // DOWNWARDS ARROW WITH HORIZONTAL STROKE + case "darrln": // DOWNWARDS ARROW WITH HORIZONTAL STROKE return rune(0x2908), true - case "dashv": - // LEFT TACK - return rune(0x22a3), true - case "dash": - // HYPHEN + case "dash": // HYPHEN return rune(0x2010), true - case "dashV": - // DOUBLE VERTICAL BAR LEFT TURNSTILE + case "dashV": // DOUBLE VERTICAL BAR LEFT TURNSTILE return rune(0x2ae3), true - case "dbkarow": - // RIGHTWARDS TRIPLE DASH ARROW + case "dashv": // LEFT TACK + return rune(0x22a3), true + case "dbkarow": // RIGHTWARDS TRIPLE DASH ARROW return rune(0x290f), true - case "dblac": - // DOUBLE ACUTE ACCENT + case "dblac": // DOUBLE ACUTE ACCENT return rune(0x02dd), true - case "dcaron": - // LATIN SMALL LETTER D WITH CARON + case "dcaron": // LATIN SMALL LETTER D WITH CARON return rune(0x010f), true - case "dcy": - // CYRILLIC SMALL LETTER DE + case "dcy": // CYRILLIC SMALL LETTER DE return rune(0x0434), true - case "ddarr": - // DOWNWARDS PAIRED ARROWS - return rune(0x21ca), true - case "dd": - // DOUBLE-STRUCK ITALIC SMALL D + case "dd": // DOUBLE-STRUCK ITALIC SMALL D return rune(0x2146), true - case "ddagger": - // DOUBLE DAGGER + case "ddagger": // DOUBLE DAGGER return rune(0x2021), true - case "ddotseq": - // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW - return rune(0x2a77), true - case "deg": - // DEGREE SIGN - return rune(0xb0), true - case "delta": - // GREEK SMALL LETTER DELTA - return rune(0x03b4), true - case "demptyv": - // EMPTY SET WITH OVERBAR - return rune(0x29b1), true - case "dfisht": - // DOWN FISH TAIL - return rune(0x297f), true - case "dfr": - // MATHEMATICAL FRAKTUR SMALL D - return rune(0x01d521), true - case "dgr": - // GREEK SMALL LETTER DELTA - return rune(0x03b4), true - case "dharl": - // DOWNWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21c3), true - case "dharr": - // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21c2), true - case "diam": - // DIAMOND OPERATOR - return rune(0x22c4), true - case "diamdarr": - // BLACK DIAMOND WITH DOWN ARROW - return rune(0x29ea), true - case "diamerr": - // ERROR-BARRED WHITE DIAMOND - return rune(0x29f0), true - case "diamerrf": - // ERROR-BARRED BLACK DIAMOND - return rune(0x29f1), true - case "diamond": - // DIAMOND OPERATOR - return rune(0x22c4), true - case "diamondsuit": - // BLACK DIAMOND SUIT - return rune(0x2666), true - case "diams": - // BLACK DIAMOND SUIT - return rune(0x2666), true - case "die": - // DIAERESIS - return rune(0xa8), true - case "digamma": - // GREEK SMALL LETTER DIGAMMA - return rune(0x03dd), true - case "disin": - // ELEMENT OF WITH LONG HORIZONTAL STROKE - return rune(0x22f2), true - case "divideontimes": - // DIVISION TIMES - return rune(0x22c7), true - case "divonx": - // DIVISION TIMES - return rune(0x22c7), true - case "div": - // DIVISION SIGN - return rune(0xf7), true - case "divide": - // DIVISION SIGN - return rune(0xf7), true - case "djcy": - // CYRILLIC SMALL LETTER DJE - return rune(0x0452), true - case "dlarr": - // SOUTH WEST ARROW - return rune(0x2199), true - case "dlcorn": - // BOTTOM LEFT CORNER - return rune(0x231e), true - case "dlcrop": - // BOTTOM LEFT CROP - return rune(0x230d), true - case "dlharb": - // DOWNWARDS HARPOON WITH BARB LEFT TO BAR - return rune(0x2959), true - case "dollar": - // DOLLAR SIGN - return rune(0x24), true - case "dopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL D - return rune(0x01d555), true - case "doteq": - // APPROACHES THE LIMIT - return rune(0x2250), true - case "doteqdot": - // GEOMETRICALLY EQUAL TO - return rune(0x2251), true - case "dotminus": - // DOT MINUS - return rune(0x2238), true - case "dotplus": - // DOT PLUS - return rune(0x2214), true - case "dotsquare": - // SQUARED DOT OPERATOR - return rune(0x22a1), true - case "dot": - // DOT ABOVE - return rune(0x02d9), true - case "doublebarwedge": - // PERSPECTIVE - return rune(0x2306), true - case "downarrow": - // DOWNWARDS ARROW - return rune(0x2193), true - case "downdownarrows": - // DOWNWARDS PAIRED ARROWS + case "ddarr": // DOWNWARDS PAIRED ARROWS return rune(0x21ca), true - case "downharpoonleft": - // DOWNWARDS HARPOON WITH BARB LEFTWARDS + case "ddotseq": // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW + return rune(0x2a77), true + case "deg": // DEGREE SIGN + return rune(0xb0), true + case "delta": // GREEK SMALL LETTER DELTA + return rune(0x03b4), true + case "demptyv": // EMPTY SET WITH OVERBAR + return rune(0x29b1), true + case "dfisht": // DOWN FISH TAIL + return rune(0x297f), true + case "dfr": // MATHEMATICAL FRAKTUR SMALL D + return rune(0x01d521), true + case "dgr": // GREEK SMALL LETTER DELTA + return rune(0x03b4), true + case "dharl": // DOWNWARDS HARPOON WITH BARB LEFTWARDS return rune(0x21c3), true - case "downharpoonright": - // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + case "dharr": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS return rune(0x21c2), true - case "drarr": - // SOUTH EAST ARROW + case "diam": // DIAMOND OPERATOR + return rune(0x22c4), true + case "diamdarr": // BLACK DIAMOND WITH DOWN ARROW + return rune(0x29ea), true + case "diamerr": // ERROR-BARRED WHITE DIAMOND + return rune(0x29f0), true + case "diamerrf": // ERROR-BARRED BLACK DIAMOND + return rune(0x29f1), true + case "diamond": // DIAMOND OPERATOR + return rune(0x22c4), true + case "diamondsuit": // BLACK DIAMOND SUIT + return rune(0x2666), true + case "diams": // BLACK DIAMOND SUIT + return rune(0x2666), true + case "die": // DIAERESIS + return rune(0xa8), true + case "digamma": // GREEK SMALL LETTER DIGAMMA + return rune(0x03dd), true + case "disin": // ELEMENT OF WITH LONG HORIZONTAL STROKE + return rune(0x22f2), true + case "div": // DIVISION SIGN + return rune(0xf7), true + case "divide": // DIVISION SIGN + return rune(0xf7), true + case "divideontimes": // DIVISION TIMES + return rune(0x22c7), true + case "divonx": // DIVISION TIMES + return rune(0x22c7), true + case "djcy": // CYRILLIC SMALL LETTER DJE + return rune(0x0452), true + case "dlarr": // SOUTH WEST ARROW + return rune(0x2199), true + case "dlcorn": // BOTTOM LEFT CORNER + return rune(0x231e), true + case "dlcrop": // BOTTOM LEFT CROP + return rune(0x230d), true + case "dlharb": // DOWNWARDS HARPOON WITH BARB LEFT TO BAR + return rune(0x2959), true + case "dollar": // DOLLAR SIGN + return rune(0x24), true + case "dopf": // MATHEMATICAL DOUBLE-STRUCK SMALL D + return rune(0x01d555), true + case "dot": // DOT ABOVE + return rune(0x02d9), true + case "doteq": // APPROACHES THE LIMIT + return rune(0x2250), true + case "doteqdot": // GEOMETRICALLY EQUAL TO + return rune(0x2251), true + case "dotminus": // DOT MINUS + return rune(0x2238), true + case "dotplus": // DOT PLUS + return rune(0x2214), true + case "dotsquare": // SQUARED DOT OPERATOR + return rune(0x22a1), true + case "doublebarwedge": // PERSPECTIVE + return rune(0x2306), true + case "downarrow": // DOWNWARDS ARROW + return rune(0x2193), true + case "downdownarrows": // DOWNWARDS PAIRED ARROWS + return rune(0x21ca), true + case "downharpoonleft": // DOWNWARDS HARPOON WITH BARB LEFTWARDS + return rune(0x21c3), true + case "downharpoonright": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + return rune(0x21c2), true + case "drarr": // SOUTH EAST ARROW return rune(0x2198), true - case "drbkarow": - // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW + case "drbkarow": // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW return rune(0x2910), true - case "drcorn": - // BOTTOM RIGHT CORNER + case "drcorn": // BOTTOM RIGHT CORNER return rune(0x231f), true - case "drcrop": - // BOTTOM RIGHT CROP + case "drcrop": // BOTTOM RIGHT CROP return rune(0x230c), true - case "drharb": - // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR + case "drharb": // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR return rune(0x2955), true - case "dscr": - // MATHEMATICAL SCRIPT SMALL D + case "dscr": // MATHEMATICAL SCRIPT SMALL D return rune(0x01d4b9), true - case "dscy": - // CYRILLIC SMALL LETTER DZE + case "dscy": // CYRILLIC SMALL LETTER DZE return rune(0x0455), true - case "dsol": - // SOLIDUS WITH OVERBAR + case "dsol": // SOLIDUS WITH OVERBAR return rune(0x29f6), true - case "dstrok": - // LATIN SMALL LETTER D WITH STROKE + case "dstrok": // LATIN SMALL LETTER D WITH STROKE return rune(0x0111), true - case "dtdot": - // DOWN RIGHT DIAGONAL ELLIPSIS + case "dtdot": // DOWN RIGHT DIAGONAL ELLIPSIS return rune(0x22f1), true - case "dtrif": - // BLACK DOWN-POINTING SMALL TRIANGLE - return rune(0x25be), true - case "dtri": - // WHITE DOWN-POINTING SMALL TRIANGLE + case "dtri": // WHITE DOWN-POINTING SMALL TRIANGLE return rune(0x25bf), true - case "dtrilf": - // DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK + case "dtrif": // BLACK DOWN-POINTING SMALL TRIANGLE + return rune(0x25be), true + case "dtrilf": // DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK return rune(0x29e8), true - case "dtrirf": - // DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK + case "dtrirf": // DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK return rune(0x29e9), true - case "duarr": - // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW + case "duarr": // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW return rune(0x21f5), true - case "duhar": - // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + case "duhar": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT return rune(0x296f), true - case "dumap": - // DOUBLE-ENDED MULTIMAP + case "dumap": // DOUBLE-ENDED MULTIMAP return rune(0x29df), true - case "dwangle": - // OBLIQUE ANGLE OPENING UP + case "dwangle": // OBLIQUE ANGLE OPENING UP return rune(0x29a6), true - case "dzcy": - // CYRILLIC SMALL LETTER DZHE + case "dzcy": // CYRILLIC SMALL LETTER DZHE return rune(0x045f), true - case "dzigrarr": - // LONG RIGHTWARDS SQUIGGLE ARROW + case "dzigrarr": // LONG RIGHTWARDS SQUIGGLE ARROW return rune(0x27ff), true } case 'e': switch name { - case "eDDot": - // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW + case "eDDot": // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW return rune(0x2a77), true - case "eDot": - // GEOMETRICALLY EQUAL TO + case "eDot": // GEOMETRICALLY EQUAL TO return rune(0x2251), true - case "eacgr": - // GREEK SMALL LETTER EPSILON WITH TONOS + case "eacgr": // GREEK SMALL LETTER EPSILON WITH TONOS return rune(0x03ad), true - case "eacute": - // LATIN SMALL LETTER E WITH ACUTE + case "eacute": // LATIN SMALL LETTER E WITH ACUTE return rune(0xe9), true - case "easter": - // EQUALS WITH ASTERISK + case "easter": // EQUALS WITH ASTERISK return rune(0x2a6e), true - case "ecaron": - // LATIN SMALL LETTER E WITH CARON + case "ecaron": // LATIN SMALL LETTER E WITH CARON return rune(0x011b), true - case "ecir": - // RING IN EQUAL TO + case "ecir": // RING IN EQUAL TO return rune(0x2256), true - case "ecirc": - // LATIN SMALL LETTER E WITH CIRCUMFLEX + case "ecirc": // LATIN SMALL LETTER E WITH CIRCUMFLEX return rune(0xea), true - case "ecolon": - // EQUALS COLON + case "ecolon": // EQUALS COLON return rune(0x2255), true - case "ecy": - // CYRILLIC SMALL LETTER E + case "ecy": // CYRILLIC SMALL LETTER E return rune(0x044d), true - case "edot": - // LATIN SMALL LETTER E WITH DOT ABOVE + case "edot": // LATIN SMALL LETTER E WITH DOT ABOVE return rune(0x0117), true - case "ee": - // DOUBLE-STRUCK ITALIC SMALL E + case "ee": // DOUBLE-STRUCK ITALIC SMALL E return rune(0x2147), true - case "eeacgr": - // GREEK SMALL LETTER ETA WITH TONOS + case "eeacgr": // GREEK SMALL LETTER ETA WITH TONOS return rune(0x03ae), true - case "eegr": - // GREEK SMALL LETTER ETA + case "eegr": // GREEK SMALL LETTER ETA return rune(0x03b7), true - case "efDot": - // APPROXIMATELY EQUAL TO OR THE IMAGE OF + case "efDot": // APPROXIMATELY EQUAL TO OR THE IMAGE OF return rune(0x2252), true - case "efr": - // MATHEMATICAL FRAKTUR SMALL E + case "efr": // MATHEMATICAL FRAKTUR SMALL E return rune(0x01d522), true - case "egr": - // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true - case "egs": - // SLANTED EQUAL TO OR GREATER-THAN - return rune(0x2a96), true - case "egsdot": - // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE - return rune(0x2a98), true - case "eg": - // DOUBLE-LINE EQUAL TO OR GREATER-THAN + case "eg": // DOUBLE-LINE EQUAL TO OR GREATER-THAN return rune(0x2a9a), true - case "egrave": - // LATIN SMALL LETTER E WITH GRAVE + case "egr": // GREEK SMALL LETTER EPSILON + return rune(0x03b5), true + case "egrave": // LATIN SMALL LETTER E WITH GRAVE return rune(0xe8), true - case "elinters": - // ELECTRICAL INTERSECTION - return rune(0x23e7), true - case "ell": - // SCRIPT SMALL L - return rune(0x2113), true - case "els": - // SLANTED EQUAL TO OR LESS-THAN - return rune(0x2a95), true - case "elsdot": - // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE - return rune(0x2a97), true - case "el": - // DOUBLE-LINE EQUAL TO OR LESS-THAN - return rune(0x2a99), true - case "emacr": - // LATIN SMALL LETTER E WITH MACRON - return rune(0x0113), true - case "empty": - // EMPTY SET - return rune(0x2205), true - case "emptyset": - // EMPTY SET - return rune(0x2205), true - case "emptyv": - // EMPTY SET - return rune(0x2205), true - case "emsp13": - // THREE-PER-EM SPACE - return rune(0x2004), true - case "emsp14": - // FOUR-PER-EM SPACE - return rune(0x2005), true - case "emsp": - // EM SPACE - return rune(0x2003), true - case "eng": - // LATIN SMALL LETTER ENG - return rune(0x014b), true - case "ensp": - // EN SPACE - return rune(0x2002), true - case "eogon": - // LATIN SMALL LETTER E WITH OGONEK - return rune(0x0119), true - case "eopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL E - return rune(0x01d556), true - case "epar": - // EQUAL AND PARALLEL TO - return rune(0x22d5), true - case "eparsl": - // EQUALS SIGN AND SLANTED PARALLEL - return rune(0x29e3), true - case "eplus": - // EQUALS SIGN ABOVE PLUS SIGN - return rune(0x2a71), true - case "epsilon": - // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true - case "epsis": - // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true - case "epsiv": - // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true - case "epsi": - // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true - case "eqcirc": - // RING IN EQUAL TO - return rune(0x2256), true - case "eqcolon": - // EQUALS COLON - return rune(0x2255), true - case "eqeq": - // TWO CONSECUTIVE EQUALS SIGNS - return rune(0x2a75), true - case "eqsim": - // MINUS TILDE - return rune(0x2242), true - case "eqslantgtr": - // SLANTED EQUAL TO OR GREATER-THAN + case "egs": // SLANTED EQUAL TO OR GREATER-THAN return rune(0x2a96), true - case "eqslantless": - // SLANTED EQUAL TO OR LESS-THAN + case "egsdot": // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE + return rune(0x2a98), true + case "el": // DOUBLE-LINE EQUAL TO OR LESS-THAN + return rune(0x2a99), true + case "elinters": // ELECTRICAL INTERSECTION + return rune(0x23e7), true + case "ell": // SCRIPT SMALL L + return rune(0x2113), true + case "els": // SLANTED EQUAL TO OR LESS-THAN return rune(0x2a95), true - case "equals": - // EQUALS SIGN - return rune(0x3d), true - case "equest": - // QUESTIONED EQUAL TO - return rune(0x225f), true - case "equiv": - // IDENTICAL TO - return rune(0x2261), true - case "equivDD": - // EQUIVALENT WITH FOUR DOTS ABOVE - return rune(0x2a78), true - case "eqvparsl": - // IDENTICAL TO AND SLANTED PARALLEL - return rune(0x29e5), true - case "erDot": - // IMAGE OF OR APPROXIMATELY EQUAL TO - return rune(0x2253), true - case "erarr": - // EQUALS SIGN ABOVE RIGHTWARDS ARROW - return rune(0x2971), true - case "escr": - // SCRIPT SMALL E - return rune(0x212f), true - case "esdot": - // APPROACHES THE LIMIT - return rune(0x2250), true - case "esim": - // MINUS TILDE + case "elsdot": // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE + return rune(0x2a97), true + case "emacr": // LATIN SMALL LETTER E WITH MACRON + return rune(0x0113), true + case "empty": // EMPTY SET + return rune(0x2205), true + case "emptyset": // EMPTY SET + return rune(0x2205), true + case "emptyv": // EMPTY SET + return rune(0x2205), true + case "emsp": // EM SPACE + return rune(0x2003), true + case "emsp13": // THREE-PER-EM SPACE + return rune(0x2004), true + case "emsp14": // FOUR-PER-EM SPACE + return rune(0x2005), true + case "eng": // LATIN SMALL LETTER ENG + return rune(0x014b), true + case "ensp": // EN SPACE + return rune(0x2002), true + case "eogon": // LATIN SMALL LETTER E WITH OGONEK + return rune(0x0119), true + case "eopf": // MATHEMATICAL DOUBLE-STRUCK SMALL E + return rune(0x01d556), true + case "epar": // EQUAL AND PARALLEL TO + return rune(0x22d5), true + case "eparsl": // EQUALS SIGN AND SLANTED PARALLEL + return rune(0x29e3), true + case "eplus": // EQUALS SIGN ABOVE PLUS SIGN + return rune(0x2a71), true + case "epsi": // GREEK SMALL LETTER EPSILON + return rune(0x03b5), true + case "epsilon": // GREEK SMALL LETTER EPSILON + return rune(0x03b5), true + case "epsis": // GREEK LUNATE EPSILON SYMBOL + return rune(0x03f5), true + case "epsiv": // GREEK LUNATE EPSILON SYMBOL + return rune(0x03f5), true + case "eqcirc": // RING IN EQUAL TO + return rune(0x2256), true + case "eqcolon": // EQUALS COLON + return rune(0x2255), true + case "eqeq": // TWO CONSECUTIVE EQUALS SIGNS + return rune(0x2a75), true + case "eqsim": // MINUS TILDE return rune(0x2242), true - case "eta": - // GREEK SMALL LETTER ETA + case "eqslantgtr": // SLANTED EQUAL TO OR GREATER-THAN + return rune(0x2a96), true + case "eqslantless": // SLANTED EQUAL TO OR LESS-THAN + return rune(0x2a95), true + case "equals": // EQUALS SIGN + return rune(0x3d), true + case "equest": // QUESTIONED EQUAL TO + return rune(0x225f), true + case "equiv": // IDENTICAL TO + return rune(0x2261), true + case "equivDD": // EQUIVALENT WITH FOUR DOTS ABOVE + return rune(0x2a78), true + case "eqvparsl": // IDENTICAL TO AND SLANTED PARALLEL + return rune(0x29e5), true + case "erDot": // IMAGE OF OR APPROXIMATELY EQUAL TO + return rune(0x2253), true + case "erarr": // EQUALS SIGN ABOVE RIGHTWARDS ARROW + return rune(0x2971), true + case "escr": // SCRIPT SMALL E + return rune(0x212f), true + case "esdot": // APPROACHES THE LIMIT + return rune(0x2250), true + case "esim": // MINUS TILDE + return rune(0x2242), true + case "eta": // GREEK SMALL LETTER ETA return rune(0x03b7), true - case "eth": - // LATIN SMALL LETTER ETH + case "eth": // LATIN SMALL LETTER ETH return rune(0xf0), true - case "euml": - // LATIN SMALL LETTER E WITH DIAERESIS + case "euml": // LATIN SMALL LETTER E WITH DIAERESIS return rune(0xeb), true - case "euro": - // EURO SIGN + case "euro": // EURO SIGN return rune(0x20ac), true - case "excl": - // EXCLAMATION MARK + case "excl": // EXCLAMATION MARK return rune(0x21), true - case "exist": - // THERE EXISTS + case "exist": // THERE EXISTS return rune(0x2203), true - case "expectation": - // SCRIPT CAPITAL E + case "expectation": // SCRIPT CAPITAL E return rune(0x2130), true - case "exponentiale": - // DOUBLE-STRUCK ITALIC SMALL E + case "exponentiale": // DOUBLE-STRUCK ITALIC SMALL E return rune(0x2147), true } case 'f': switch name { - case "fallingdotseq": - // APPROXIMATELY EQUAL TO OR THE IMAGE OF + case "fallingdotseq": // APPROXIMATELY EQUAL TO OR THE IMAGE OF return rune(0x2252), true - case "fbowtie": - // BLACK BOWTIE + case "fbowtie": // BLACK BOWTIE return rune(0x29d3), true - case "fcy": - // CYRILLIC SMALL LETTER EF + case "fcy": // CYRILLIC SMALL LETTER EF return rune(0x0444), true - case "fdiag": - // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT + case "fdiag": // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT return rune(0x2572), true - case "fdiordi": - // FALLING DIAGONAL CROSSING RISING DIAGONAL + case "fdiordi": // FALLING DIAGONAL CROSSING RISING DIAGONAL return rune(0x292c), true - case "fdonearr": - // FALLING DIAGONAL CROSSING NORTH EAST ARROW + case "fdonearr": // FALLING DIAGONAL CROSSING NORTH EAST ARROW return rune(0x292f), true - case "female": - // FEMALE SIGN + case "female": // FEMALE SIGN return rune(0x2640), true - case "ffilig": - // LATIN SMALL LIGATURE FFI + case "ffilig": // LATIN SMALL LIGATURE FFI return rune(0xfb03), true - case "fflig": - // LATIN SMALL LIGATURE FF + case "fflig": // LATIN SMALL LIGATURE FF return rune(0xfb00), true - case "ffllig": - // LATIN SMALL LIGATURE FFL + case "ffllig": // LATIN SMALL LIGATURE FFL return rune(0xfb04), true - case "ffr": - // MATHEMATICAL FRAKTUR SMALL F + case "ffr": // MATHEMATICAL FRAKTUR SMALL F return rune(0x01d523), true - case "fhrglass": - // BLACK HOURGLASS + case "fhrglass": // BLACK HOURGLASS return rune(0x29d7), true - case "filig": - // LATIN SMALL LIGATURE FI + case "filig": // LATIN SMALL LIGATURE FI return rune(0xfb01), true - case "fjlig": - // fj ligature + case "fjlig": // fj ligature return rune(0x66), true - case "flat": - // MUSIC FLAT SIGN + case "flat": // MUSIC FLAT SIGN return rune(0x266d), true - case "fllig": - // LATIN SMALL LIGATURE FL + case "fllig": // LATIN SMALL LIGATURE FL return rune(0xfb02), true - case "fltns": - // WHITE PARALLELOGRAM + case "fltns": // WHITE PARALLELOGRAM return rune(0x25b1), true - case "fnof": - // LATIN SMALL LETTER F WITH HOOK + case "fnof": // LATIN SMALL LETTER F WITH HOOK return rune(0x0192), true - case "fopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL F + case "fopf": // MATHEMATICAL DOUBLE-STRUCK SMALL F return rune(0x01d557), true - case "forall": - // FOR ALL + case "forall": // FOR ALL return rune(0x2200), true - case "fork": - // PITCHFORK + case "fork": // PITCHFORK return rune(0x22d4), true - case "forkv": - // ELEMENT OF OPENING DOWNWARDS + case "forkv": // ELEMENT OF OPENING DOWNWARDS return rune(0x2ad9), true - case "fpartint": - // FINITE PART INTEGRAL + case "fpartint": // FINITE PART INTEGRAL return rune(0x2a0d), true - case "frac12": - // VULGAR FRACTION ONE HALF + case "frac12": // VULGAR FRACTION ONE HALF return rune(0xbd), true - case "frac13": - // VULGAR FRACTION ONE THIRD + case "frac13": // VULGAR FRACTION ONE THIRD return rune(0x2153), true - case "frac14": - // VULGAR FRACTION ONE QUARTER + case "frac14": // VULGAR FRACTION ONE QUARTER return rune(0xbc), true - case "frac15": - // VULGAR FRACTION ONE FIFTH + case "frac15": // VULGAR FRACTION ONE FIFTH return rune(0x2155), true - case "frac16": - // VULGAR FRACTION ONE SIXTH + case "frac16": // VULGAR FRACTION ONE SIXTH return rune(0x2159), true - case "frac18": - // VULGAR FRACTION ONE EIGHTH + case "frac18": // VULGAR FRACTION ONE EIGHTH return rune(0x215b), true - case "frac23": - // VULGAR FRACTION TWO THIRDS + case "frac23": // VULGAR FRACTION TWO THIRDS return rune(0x2154), true - case "frac25": - // VULGAR FRACTION TWO FIFTHS + case "frac25": // VULGAR FRACTION TWO FIFTHS return rune(0x2156), true - case "frac34": - // VULGAR FRACTION THREE QUARTERS + case "frac34": // VULGAR FRACTION THREE QUARTERS return rune(0xbe), true - case "frac35": - // VULGAR FRACTION THREE FIFTHS + case "frac35": // VULGAR FRACTION THREE FIFTHS return rune(0x2157), true - case "frac38": - // VULGAR FRACTION THREE EIGHTHS + case "frac38": // VULGAR FRACTION THREE EIGHTHS return rune(0x215c), true - case "frac45": - // VULGAR FRACTION FOUR FIFTHS + case "frac45": // VULGAR FRACTION FOUR FIFTHS return rune(0x2158), true - case "frac56": - // VULGAR FRACTION FIVE SIXTHS + case "frac56": // VULGAR FRACTION FIVE SIXTHS return rune(0x215a), true - case "frac58": - // VULGAR FRACTION FIVE EIGHTHS + case "frac58": // VULGAR FRACTION FIVE EIGHTHS return rune(0x215d), true - case "frac78": - // VULGAR FRACTION SEVEN EIGHTHS + case "frac78": // VULGAR FRACTION SEVEN EIGHTHS return rune(0x215e), true - case "frasl": - // FRACTION SLASH + case "frasl": // FRACTION SLASH return rune(0x2044), true - case "frown": - // FROWN + case "frown": // FROWN return rune(0x2322), true - case "fscr": - // MATHEMATICAL SCRIPT SMALL F + case "fscr": // MATHEMATICAL SCRIPT SMALL F return rune(0x01d4bb), true } case 'g': switch name { - case "gE": - // GREATER-THAN OVER EQUAL TO + case "gE": // GREATER-THAN OVER EQUAL TO return rune(0x2267), true - case "gEl": - // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN + case "gEl": // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN return rune(0x2a8c), true - case "gacute": - // LATIN SMALL LETTER G WITH ACUTE + case "gacute": // LATIN SMALL LETTER G WITH ACUTE return rune(0x01f5), true - case "gammad": - // GREEK SMALL LETTER DIGAMMA + case "gamma": // GREEK SMALL LETTER GAMMA + return rune(0x03b3), true + case "gammad": // GREEK SMALL LETTER DIGAMMA return rune(0x03dd), true - case "gamma": - // GREEK SMALL LETTER GAMMA - return rune(0x03b3), true - case "gap": - // GREATER-THAN OR APPROXIMATE + case "gap": // GREATER-THAN OR APPROXIMATE return rune(0x2a86), true - case "gbreve": - // LATIN SMALL LETTER G WITH BREVE + case "gbreve": // LATIN SMALL LETTER G WITH BREVE return rune(0x011f), true - case "gcedil": - // LATIN SMALL LETTER G WITH CEDILLA + case "gcedil": // LATIN SMALL LETTER G WITH CEDILLA return rune(0x0123), true - case "gcirc": - // LATIN SMALL LETTER G WITH CIRCUMFLEX + case "gcirc": // LATIN SMALL LETTER G WITH CIRCUMFLEX return rune(0x011d), true - case "gcy": - // CYRILLIC SMALL LETTER GHE + case "gcy": // CYRILLIC SMALL LETTER GHE return rune(0x0433), true - case "gdot": - // LATIN SMALL LETTER G WITH DOT ABOVE + case "gdot": // LATIN SMALL LETTER G WITH DOT ABOVE return rune(0x0121), true - case "ge": - // GREATER-THAN OR EQUAL TO + case "ge": // GREATER-THAN OR EQUAL TO return rune(0x2265), true - case "gel": - // GREATER-THAN EQUAL TO OR LESS-THAN + case "gel": // GREATER-THAN EQUAL TO OR LESS-THAN return rune(0x22db), true - case "geq": - // GREATER-THAN OR EQUAL TO + case "geq": // GREATER-THAN OR EQUAL TO return rune(0x2265), true - case "geqq": - // GREATER-THAN OVER EQUAL TO + case "geqq": // GREATER-THAN OVER EQUAL TO return rune(0x2267), true - case "geqslant": - // GREATER-THAN OR SLANTED EQUAL TO + case "geqslant": // GREATER-THAN OR SLANTED EQUAL TO return rune(0x2a7e), true - case "gesl": - // GREATER-THAN slanted EQUAL TO OR LESS-THAN - return rune(0x22db), true - case "ges": - // GREATER-THAN OR SLANTED EQUAL TO + case "ges": // GREATER-THAN OR SLANTED EQUAL TO return rune(0x2a7e), true - case "gescc": - // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL + case "gescc": // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL return rune(0x2aa9), true - case "gesdot": - // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE + case "gesdot": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE return rune(0x2a80), true - case "gesdoto": - // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE + case "gesdoto": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE return rune(0x2a82), true - case "gesdotol": - // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT + case "gesdotol": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT return rune(0x2a84), true - case "gesles": - // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL - return rune(0x2a94), true - case "gfr": - // MATHEMATICAL FRAKTUR SMALL G - return rune(0x01d524), true - case "gg": - // MUCH GREATER-THAN - return rune(0x226b), true - case "ggg": - // VERY MUCH GREATER-THAN - return rune(0x22d9), true - case "ggr": - // GREEK SMALL LETTER GAMMA - return rune(0x03b3), true - case "gimel": - // GIMEL SYMBOL - return rune(0x2137), true - case "gjcy": - // CYRILLIC SMALL LETTER GJE - return rune(0x0453), true - case "gl": - // GREATER-THAN OR LESS-THAN - return rune(0x2277), true - case "glE": - // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL - return rune(0x2a92), true - case "gla": - // GREATER-THAN BESIDE LESS-THAN - return rune(0x2aa5), true - case "glj": - // GREATER-THAN OVERLAPPING LESS-THAN - return rune(0x2aa4), true - case "gnE": - // GREATER-THAN BUT NOT EQUAL TO - return rune(0x2269), true - case "gnap": - // GREATER-THAN AND NOT APPROXIMATE - return rune(0x2a8a), true - case "gnapprox": - // GREATER-THAN AND NOT APPROXIMATE - return rune(0x2a8a), true - case "gneqq": - // GREATER-THAN BUT NOT EQUAL TO - return rune(0x2269), true - case "gne": - // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a88), true - case "gneq": - // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a88), true - case "gnsim": - // GREATER-THAN BUT NOT EQUIVALENT TO - return rune(0x22e7), true - case "gopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL G - return rune(0x01d558), true - case "grave": - // GRAVE ACCENT - return rune(0x60), true - case "gscr": - // SCRIPT SMALL G - return rune(0x210a), true - case "gsdot": - // GREATER-THAN WITH DOT - return rune(0x22d7), true - case "gsim": - // GREATER-THAN OR EQUIVALENT TO - return rune(0x2273), true - case "gsime": - // GREATER-THAN ABOVE SIMILAR OR EQUAL - return rune(0x2a8e), true - case "gsiml": - // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN - return rune(0x2a90), true - case "gtcc": - // GREATER-THAN CLOSED BY CURVE - return rune(0x2aa7), true - case "gtcir": - // GREATER-THAN WITH CIRCLE INSIDE - return rune(0x2a7a), true - case "gtdot": - // GREATER-THAN WITH DOT - return rune(0x22d7), true - case "gtlPar": - // DOUBLE LEFT ARC GREATER-THAN BRACKET - return rune(0x2995), true - case "gtquest": - // GREATER-THAN WITH QUESTION MARK ABOVE - return rune(0x2a7c), true - case "gtrapprox": - // GREATER-THAN OR APPROXIMATE - return rune(0x2a86), true - case "gtrarr": - // GREATER-THAN ABOVE RIGHTWARDS ARROW - return rune(0x2978), true - case "gtrdot": - // GREATER-THAN WITH DOT - return rune(0x22d7), true - case "gtreqless": - // GREATER-THAN EQUAL TO OR LESS-THAN + case "gesl": // GREATER-THAN slanted EQUAL TO OR LESS-THAN return rune(0x22db), true - case "gtreqqless": - // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN - return rune(0x2a8c), true - case "gtrless": - // GREATER-THAN OR LESS-THAN + case "gesles": // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL + return rune(0x2a94), true + case "gfr": // MATHEMATICAL FRAKTUR SMALL G + return rune(0x01d524), true + case "gg": // MUCH GREATER-THAN + return rune(0x226b), true + case "ggg": // VERY MUCH GREATER-THAN + return rune(0x22d9), true + case "ggr": // GREEK SMALL LETTER GAMMA + return rune(0x03b3), true + case "gimel": // GIMEL SYMBOL + return rune(0x2137), true + case "gjcy": // CYRILLIC SMALL LETTER GJE + return rune(0x0453), true + case "gl": // GREATER-THAN OR LESS-THAN return rune(0x2277), true - case "gtrpar": - // SPHERICAL ANGLE OPENING LEFT - return rune(0x29a0), true - case "gtrsim": - // GREATER-THAN OR EQUIVALENT TO - return rune(0x2273), true - case "gt": - // GREATER-THAN SIGN - return rune(0x3e), true - case "gvertneqq": - // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + case "glE": // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL + return rune(0x2a92), true + case "gla": // GREATER-THAN BESIDE LESS-THAN + return rune(0x2aa5), true + case "glj": // GREATER-THAN OVERLAPPING LESS-THAN + return rune(0x2aa4), true + case "gnE": // GREATER-THAN BUT NOT EQUAL TO return rune(0x2269), true - case "gvnE": - // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + case "gnap": // GREATER-THAN AND NOT APPROXIMATE + return rune(0x2a8a), true + case "gnapprox": // GREATER-THAN AND NOT APPROXIMATE + return rune(0x2a8a), true + case "gne": // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO + return rune(0x2a88), true + case "gneq": // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO + return rune(0x2a88), true + case "gneqq": // GREATER-THAN BUT NOT EQUAL TO + return rune(0x2269), true + case "gnsim": // GREATER-THAN BUT NOT EQUIVALENT TO + return rune(0x22e7), true + case "gopf": // MATHEMATICAL DOUBLE-STRUCK SMALL G + return rune(0x01d558), true + case "grave": // GRAVE ACCENT + return rune(0x60), true + case "gscr": // SCRIPT SMALL G + return rune(0x210a), true + case "gsdot": // GREATER-THAN WITH DOT + return rune(0x22d7), true + case "gsim": // GREATER-THAN OR EQUIVALENT TO + return rune(0x2273), true + case "gsime": // GREATER-THAN ABOVE SIMILAR OR EQUAL + return rune(0x2a8e), true + case "gsiml": // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN + return rune(0x2a90), true + case "gt": // GREATER-THAN SIGN + return rune(0x3e), true + case "gtcc": // GREATER-THAN CLOSED BY CURVE + return rune(0x2aa7), true + case "gtcir": // GREATER-THAN WITH CIRCLE INSIDE + return rune(0x2a7a), true + case "gtdot": // GREATER-THAN WITH DOT + return rune(0x22d7), true + case "gtlPar": // DOUBLE LEFT ARC GREATER-THAN BRACKET + return rune(0x2995), true + case "gtquest": // GREATER-THAN WITH QUESTION MARK ABOVE + return rune(0x2a7c), true + case "gtrapprox": // GREATER-THAN OR APPROXIMATE + return rune(0x2a86), true + case "gtrarr": // GREATER-THAN ABOVE RIGHTWARDS ARROW + return rune(0x2978), true + case "gtrdot": // GREATER-THAN WITH DOT + return rune(0x22d7), true + case "gtreqless": // GREATER-THAN EQUAL TO OR LESS-THAN + return rune(0x22db), true + case "gtreqqless": // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN + return rune(0x2a8c), true + case "gtrless": // GREATER-THAN OR LESS-THAN + return rune(0x2277), true + case "gtrpar": // SPHERICAL ANGLE OPENING LEFT + return rune(0x29a0), true + case "gtrsim": // GREATER-THAN OR EQUIVALENT TO + return rune(0x2273), true + case "gvertneqq": // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + return rune(0x2269), true + case "gvnE": // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke return rune(0x2269), true } case 'h': switch name { - case "hArr": - // LEFT RIGHT DOUBLE ARROW + case "hArr": // LEFT RIGHT DOUBLE ARROW return rune(0x21d4), true - case "hairsp": - // HAIR SPACE + case "hairsp": // HAIR SPACE return rune(0x200a), true - case "half": - // VULGAR FRACTION ONE HALF + case "half": // VULGAR FRACTION ONE HALF return rune(0xbd), true - case "hamilt": - // SCRIPT CAPITAL H + case "hamilt": // SCRIPT CAPITAL H return rune(0x210b), true - case "hardcy": - // CYRILLIC SMALL LETTER HARD SIGN + case "hardcy": // CYRILLIC SMALL LETTER HARD SIGN return rune(0x044a), true - case "harrw": - // LEFT RIGHT WAVE ARROW - return rune(0x21ad), true - case "harr": - // LEFT RIGHT ARROW + case "harr": // LEFT RIGHT ARROW return rune(0x2194), true - case "harrcir": - // LEFT RIGHT ARROW THROUGH SMALL CIRCLE + case "harrcir": // LEFT RIGHT ARROW THROUGH SMALL CIRCLE return rune(0x2948), true - case "hbar": - // PLANCK CONSTANT OVER TWO PI + case "harrw": // LEFT RIGHT WAVE ARROW + return rune(0x21ad), true + case "hbar": // PLANCK CONSTANT OVER TWO PI return rune(0x210f), true - case "hcirc": - // LATIN SMALL LETTER H WITH CIRCUMFLEX + case "hcirc": // LATIN SMALL LETTER H WITH CIRCUMFLEX return rune(0x0125), true - case "hearts": - // BLACK HEART SUIT + case "hearts": // BLACK HEART SUIT return rune(0x2665), true - case "heartsuit": - // BLACK HEART SUIT + case "heartsuit": // BLACK HEART SUIT return rune(0x2665), true - case "hellip": - // HORIZONTAL ELLIPSIS + case "hellip": // HORIZONTAL ELLIPSIS return rune(0x2026), true - case "hercon": - // HERMITIAN CONJUGATE MATRIX + case "hercon": // HERMITIAN CONJUGATE MATRIX return rune(0x22b9), true - case "hfr": - // MATHEMATICAL FRAKTUR SMALL H + case "hfr": // MATHEMATICAL FRAKTUR SMALL H return rune(0x01d525), true - case "hksearow": - // SOUTH EAST ARROW WITH HOOK + case "hksearow": // SOUTH EAST ARROW WITH HOOK return rune(0x2925), true - case "hkswarow": - // SOUTH WEST ARROW WITH HOOK + case "hkswarow": // SOUTH WEST ARROW WITH HOOK return rune(0x2926), true - case "hoarr": - // LEFT RIGHT OPEN-HEADED ARROW + case "hoarr": // LEFT RIGHT OPEN-HEADED ARROW return rune(0x21ff), true - case "homtht": - // HOMOTHETIC + case "homtht": // HOMOTHETIC return rune(0x223b), true - case "hookleftarrow": - // LEFTWARDS ARROW WITH HOOK + case "hookleftarrow": // LEFTWARDS ARROW WITH HOOK return rune(0x21a9), true - case "hookrightarrow": - // RIGHTWARDS ARROW WITH HOOK + case "hookrightarrow": // RIGHTWARDS ARROW WITH HOOK return rune(0x21aa), true - case "hopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL H + case "hopf": // MATHEMATICAL DOUBLE-STRUCK SMALL H return rune(0x01d559), true - case "horbar": - // HORIZONTAL BAR + case "horbar": // HORIZONTAL BAR return rune(0x2015), true - case "hrglass": - // WHITE HOURGLASS + case "hrglass": // WHITE HOURGLASS return rune(0x29d6), true - case "hscr": - // MATHEMATICAL SCRIPT SMALL H + case "hscr": // MATHEMATICAL SCRIPT SMALL H return rune(0x01d4bd), true - case "hslash": - // PLANCK CONSTANT OVER TWO PI + case "hslash": // PLANCK CONSTANT OVER TWO PI return rune(0x210f), true - case "hstrok": - // LATIN SMALL LETTER H WITH STROKE + case "hstrok": // LATIN SMALL LETTER H WITH STROKE return rune(0x0127), true - case "htimes": - // VECTOR OR CROSS PRODUCT + case "htimes": // VECTOR OR CROSS PRODUCT return rune(0x2a2f), true - case "hybull": - // HYPHEN BULLET + case "hybull": // HYPHEN BULLET return rune(0x2043), true - case "hyphen": - // HYPHEN + case "hyphen": // HYPHEN return rune(0x2010), true } case 'i': switch name { - case "iacgr": - // GREEK SMALL LETTER IOTA WITH TONOS + case "iacgr": // GREEK SMALL LETTER IOTA WITH TONOS return rune(0x03af), true - case "iacute": - // LATIN SMALL LETTER I WITH ACUTE + case "iacute": // LATIN SMALL LETTER I WITH ACUTE return rune(0xed), true - case "ic": - // INVISIBLE SEPARATOR + case "ic": // INVISIBLE SEPARATOR return rune(0x2063), true - case "icirc": - // LATIN SMALL LETTER I WITH CIRCUMFLEX + case "icirc": // LATIN SMALL LETTER I WITH CIRCUMFLEX return rune(0xee), true - case "icy": - // CYRILLIC SMALL LETTER I + case "icy": // CYRILLIC SMALL LETTER I return rune(0x0438), true - case "idiagr": - // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + case "idiagr": // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS return rune(0x0390), true - case "idigr": - // GREEK SMALL LETTER IOTA WITH DIALYTIKA + case "idigr": // GREEK SMALL LETTER IOTA WITH DIALYTIKA return rune(0x03ca), true - case "iecy": - // CYRILLIC SMALL LETTER IE + case "iecy": // CYRILLIC SMALL LETTER IE return rune(0x0435), true - case "iexcl": - // INVERTED EXCLAMATION MARK + case "iexcl": // INVERTED EXCLAMATION MARK return rune(0xa1), true - case "iff": - // LEFT RIGHT DOUBLE ARROW + case "iff": // LEFT RIGHT DOUBLE ARROW return rune(0x21d4), true - case "ifr": - // MATHEMATICAL FRAKTUR SMALL I + case "ifr": // MATHEMATICAL FRAKTUR SMALL I return rune(0x01d526), true - case "igr": - // GREEK SMALL LETTER IOTA + case "igr": // GREEK SMALL LETTER IOTA return rune(0x03b9), true - case "igrave": - // LATIN SMALL LETTER I WITH GRAVE + case "igrave": // LATIN SMALL LETTER I WITH GRAVE return rune(0xec), true - case "iiint": - // TRIPLE INTEGRAL - return rune(0x222d), true - case "ii": - // DOUBLE-STRUCK ITALIC SMALL I + case "ii": // DOUBLE-STRUCK ITALIC SMALL I return rune(0x2148), true - case "iiiint": - // QUADRUPLE INTEGRAL OPERATOR + case "iiiint": // QUADRUPLE INTEGRAL OPERATOR return rune(0x2a0c), true - case "iinfin": - // INCOMPLETE INFINITY + case "iiint": // TRIPLE INTEGRAL + return rune(0x222d), true + case "iinfin": // INCOMPLETE INFINITY return rune(0x29dc), true - case "iiota": - // TURNED GREEK SMALL LETTER IOTA + case "iiota": // TURNED GREEK SMALL LETTER IOTA return rune(0x2129), true - case "ijlig": - // LATIN SMALL LIGATURE IJ + case "ijlig": // LATIN SMALL LIGATURE IJ return rune(0x0133), true - case "imacr": - // LATIN SMALL LETTER I WITH MACRON + case "imacr": // LATIN SMALL LETTER I WITH MACRON return rune(0x012b), true - case "image": - // BLACK-LETTER CAPITAL I + case "image": // BLACK-LETTER CAPITAL I return rune(0x2111), true - case "imagline": - // SCRIPT CAPITAL I + case "imagline": // SCRIPT CAPITAL I return rune(0x2110), true - case "imagpart": - // BLACK-LETTER CAPITAL I + case "imagpart": // BLACK-LETTER CAPITAL I return rune(0x2111), true - case "imath": - // LATIN SMALL LETTER DOTLESS I + case "imath": // LATIN SMALL LETTER DOTLESS I return rune(0x0131), true - case "imof": - // IMAGE OF + case "imof": // IMAGE OF return rune(0x22b7), true - case "imped": - // LATIN CAPITAL LETTER Z WITH STROKE + case "imped": // LATIN CAPITAL LETTER Z WITH STROKE return rune(0x01b5), true - case "in": - // ELEMENT OF + case "in": // ELEMENT OF return rune(0x2208), true - case "incare": - // CARE OF + case "incare": // CARE OF return rune(0x2105), true - case "infin": - // INFINITY + case "infin": // INFINITY return rune(0x221e), true - case "infintie": - // TIE OVER INFINITY + case "infintie": // TIE OVER INFINITY return rune(0x29dd), true - case "inodot": - // LATIN SMALL LETTER DOTLESS I + case "inodot": // LATIN SMALL LETTER DOTLESS I return rune(0x0131), true - case "int": - // INTEGRAL + case "int": // INTEGRAL return rune(0x222b), true - case "intcal": - // INTERCALATE + case "intcal": // INTERCALATE return rune(0x22ba), true - case "integers": - // DOUBLE-STRUCK CAPITAL Z + case "integers": // DOUBLE-STRUCK CAPITAL Z return rune(0x2124), true - case "intercal": - // INTERCALATE + case "intercal": // INTERCALATE return rune(0x22ba), true - case "intlarhk": - // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK + case "intlarhk": // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK return rune(0x2a17), true - case "intprod": - // INTERIOR PRODUCT + case "intprod": // INTERIOR PRODUCT return rune(0x2a3c), true - case "iocy": - // CYRILLIC SMALL LETTER IO + case "iocy": // CYRILLIC SMALL LETTER IO return rune(0x0451), true - case "iogon": - // LATIN SMALL LETTER I WITH OGONEK + case "iogon": // LATIN SMALL LETTER I WITH OGONEK return rune(0x012f), true - case "iopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL I + case "iopf": // MATHEMATICAL DOUBLE-STRUCK SMALL I return rune(0x01d55a), true - case "iota": - // GREEK SMALL LETTER IOTA + case "iota": // GREEK SMALL LETTER IOTA return rune(0x03b9), true - case "iprod": - // INTERIOR PRODUCT + case "iprod": // INTERIOR PRODUCT return rune(0x2a3c), true - case "iprodr": - // RIGHTHAND INTERIOR PRODUCT + case "iprodr": // RIGHTHAND INTERIOR PRODUCT return rune(0x2a3d), true - case "iquest": - // INVERTED QUESTION MARK + case "iquest": // INVERTED QUESTION MARK return rune(0xbf), true - case "iscr": - // MATHEMATICAL SCRIPT SMALL I + case "iscr": // MATHEMATICAL SCRIPT SMALL I return rune(0x01d4be), true - case "isin": - // ELEMENT OF + case "isin": // ELEMENT OF return rune(0x2208), true - case "isinE": - // ELEMENT OF WITH TWO HORIZONTAL STROKES + case "isinE": // ELEMENT OF WITH TWO HORIZONTAL STROKES return rune(0x22f9), true - case "isindot": - // ELEMENT OF WITH DOT ABOVE + case "isindot": // ELEMENT OF WITH DOT ABOVE return rune(0x22f5), true - case "isinsv": - // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - return rune(0x22f3), true - case "isins": - // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + case "isins": // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE return rune(0x22f4), true - case "isinv": - // ELEMENT OF + case "isinsv": // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + return rune(0x22f3), true + case "isinv": // ELEMENT OF return rune(0x2208), true - case "isinvb": - // ELEMENT OF WITH UNDERBAR + case "isinvb": // ELEMENT OF WITH UNDERBAR return rune(0x22f8), true - case "it": - // INVISIBLE TIMES + case "it": // INVISIBLE TIMES return rune(0x2062), true - case "itilde": - // LATIN SMALL LETTER I WITH TILDE + case "itilde": // LATIN SMALL LETTER I WITH TILDE return rune(0x0129), true - case "iukcy": - // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + case "iukcy": // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I return rune(0x0456), true - case "iuml": - // LATIN SMALL LETTER I WITH DIAERESIS + case "iuml": // LATIN SMALL LETTER I WITH DIAERESIS return rune(0xef), true } case 'j': switch name { - case "jcirc": - // LATIN SMALL LETTER J WITH CIRCUMFLEX + case "jcirc": // LATIN SMALL LETTER J WITH CIRCUMFLEX return rune(0x0135), true - case "jcy": - // CYRILLIC SMALL LETTER SHORT I + case "jcy": // CYRILLIC SMALL LETTER SHORT I return rune(0x0439), true - case "jfr": - // MATHEMATICAL FRAKTUR SMALL J + case "jfr": // MATHEMATICAL FRAKTUR SMALL J return rune(0x01d527), true - case "jmath": - // LATIN SMALL LETTER DOTLESS J + case "jmath": // LATIN SMALL LETTER DOTLESS J return rune(0x0237), true - case "jnodot": - // LATIN SMALL LETTER DOTLESS J + case "jnodot": // LATIN SMALL LETTER DOTLESS J return rune(0x0237), true - case "jopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL J + case "jopf": // MATHEMATICAL DOUBLE-STRUCK SMALL J return rune(0x01d55b), true - case "jscr": - // MATHEMATICAL SCRIPT SMALL J + case "jscr": // MATHEMATICAL SCRIPT SMALL J return rune(0x01d4bf), true - case "jsercy": - // CYRILLIC SMALL LETTER JE + case "jsercy": // CYRILLIC SMALL LETTER JE return rune(0x0458), true - case "jukcy": - // CYRILLIC SMALL LETTER UKRAINIAN IE + case "jukcy": // CYRILLIC SMALL LETTER UKRAINIAN IE return rune(0x0454), true } case 'k': switch name { - case "kappav": - // GREEK KAPPA SYMBOL + case "kappa": // GREEK SMALL LETTER KAPPA + return rune(0x03ba), true + case "kappav": // GREEK KAPPA SYMBOL return rune(0x03f0), true - case "kappa": - // GREEK SMALL LETTER KAPPA - return rune(0x03ba), true - case "kcedil": - // LATIN SMALL LETTER K WITH CEDILLA + case "kcedil": // LATIN SMALL LETTER K WITH CEDILLA return rune(0x0137), true - case "kcy": - // CYRILLIC SMALL LETTER KA + case "kcy": // CYRILLIC SMALL LETTER KA return rune(0x043a), true - case "kfr": - // MATHEMATICAL FRAKTUR SMALL K + case "kfr": // MATHEMATICAL FRAKTUR SMALL K return rune(0x01d528), true - case "kgr": - // GREEK SMALL LETTER KAPPA + case "kgr": // GREEK SMALL LETTER KAPPA return rune(0x03ba), true - case "kgreen": - // LATIN SMALL LETTER KRA + case "kgreen": // LATIN SMALL LETTER KRA return rune(0x0138), true - case "khcy": - // CYRILLIC SMALL LETTER HA + case "khcy": // CYRILLIC SMALL LETTER HA return rune(0x0445), true - case "khgr": - // GREEK SMALL LETTER CHI + case "khgr": // GREEK SMALL LETTER CHI return rune(0x03c7), true - case "kjcy": - // CYRILLIC SMALL LETTER KJE + case "kjcy": // CYRILLIC SMALL LETTER KJE return rune(0x045c), true - case "kopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL K + case "kopf": // MATHEMATICAL DOUBLE-STRUCK SMALL K return rune(0x01d55c), true - case "koppa": - // GREEK LETTER KOPPA + case "koppa": // GREEK LETTER KOPPA return rune(0x03de), true - case "kscr": - // MATHEMATICAL SCRIPT SMALL K + case "kscr": // MATHEMATICAL SCRIPT SMALL K return rune(0x01d4c0), true } case 'l': switch name { - case "lAarr": - // LEFTWARDS TRIPLE ARROW + case "lAarr": // LEFTWARDS TRIPLE ARROW return rune(0x21da), true - case "lArr": - // LEFTWARDS DOUBLE ARROW + case "lArr": // LEFTWARDS DOUBLE ARROW return rune(0x21d0), true - case "lAtail": - // LEFTWARDS DOUBLE ARROW-TAIL + case "lAtail": // LEFTWARDS DOUBLE ARROW-TAIL return rune(0x291b), true - case "lBarr": - // LEFTWARDS TRIPLE DASH ARROW + case "lBarr": // LEFTWARDS TRIPLE DASH ARROW return rune(0x290e), true - case "lE": - // LESS-THAN OVER EQUAL TO + case "lE": // LESS-THAN OVER EQUAL TO return rune(0x2266), true - case "lEg": - // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN + case "lEg": // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN return rune(0x2a8b), true - case "lHar": - // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN + case "lHar": // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN return rune(0x2962), true - case "lacute": - // LATIN SMALL LETTER L WITH ACUTE + case "lacute": // LATIN SMALL LETTER L WITH ACUTE return rune(0x013a), true - case "laemptyv": - // EMPTY SET WITH LEFT ARROW ABOVE + case "laemptyv": // EMPTY SET WITH LEFT ARROW ABOVE return rune(0x29b4), true - case "lagran": - // SCRIPT CAPITAL L + case "lagran": // SCRIPT CAPITAL L return rune(0x2112), true - case "lambda": - // GREEK SMALL LETTER LAMDA + case "lambda": // GREEK SMALL LETTER LAMDA return rune(0x03bb), true - case "lang": - // MATHEMATICAL LEFT ANGLE BRACKET + case "lang": // MATHEMATICAL LEFT ANGLE BRACKET return rune(0x27e8), true - case "langd": - // LEFT ANGLE BRACKET WITH DOT + case "langd": // LEFT ANGLE BRACKET WITH DOT return rune(0x2991), true - case "langle": - // MATHEMATICAL LEFT ANGLE BRACKET + case "langle": // MATHEMATICAL LEFT ANGLE BRACKET return rune(0x27e8), true - case "lap": - // LESS-THAN OR APPROXIMATE + case "lap": // LESS-THAN OR APPROXIMATE return rune(0x2a85), true - case "laquo": - // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + case "laquo": // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK return rune(0xab), true - case "larr2": - // LEFTWARDS PAIRED ARROWS + case "larr": // LEFTWARDS ARROW + return rune(0x2190), true + case "larr2": // LEFTWARDS PAIRED ARROWS return rune(0x21c7), true - case "larrb": - // LEFTWARDS ARROW TO BAR + case "larrb": // LEFTWARDS ARROW TO BAR return rune(0x21e4), true - case "larrhk": - // LEFTWARDS ARROW WITH HOOK - return rune(0x21a9), true - case "larrlp": - // LEFTWARDS ARROW WITH LOOP - return rune(0x21ab), true - case "larrtl": - // LEFTWARDS ARROW WITH TAIL - return rune(0x21a2), true - case "larr": - // LEFTWARDS ARROW - return rune(0x2190), true - case "larrbfs": - // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND + case "larrbfs": // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND return rune(0x291f), true - case "larrfs": - // LEFTWARDS ARROW TO BLACK DIAMOND + case "larrfs": // LEFTWARDS ARROW TO BLACK DIAMOND return rune(0x291d), true - case "larrpl": - // LEFT-SIDE ARC ANTICLOCKWISE ARROW - return rune(0x2939), true - case "larrsim": - // LEFTWARDS ARROW ABOVE TILDE OPERATOR - return rune(0x2973), true - case "latail": - // LEFTWARDS ARROW-TAIL - return rune(0x2919), true - case "lat": - // LARGER THAN - return rune(0x2aab), true - case "late": - // LARGER THAN OR EQUAL TO - return rune(0x2aad), true - case "lates": - // LARGER THAN OR slanted EQUAL - return rune(0x2aad), true - case "lbarr": - // LEFTWARDS DOUBLE DASH ARROW - return rune(0x290c), true - case "lbbrk": - // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT - return rune(0x2772), true - case "lbrace": - // LEFT CURLY BRACKET - return rune(0x7b), true - case "lbrack": - // LEFT SQUARE BRACKET - return rune(0x5b), true - case "lbrke": - // LEFT SQUARE BRACKET WITH UNDERBAR - return rune(0x298b), true - case "lbrksld": - // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - return rune(0x298f), true - case "lbrkslu": - // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER - return rune(0x298d), true - case "lcaron": - // LATIN SMALL LETTER L WITH CARON - return rune(0x013e), true - case "lcedil": - // LATIN SMALL LETTER L WITH CEDILLA - return rune(0x013c), true - case "lceil": - // LEFT CEILING - return rune(0x2308), true - case "lcub": - // LEFT CURLY BRACKET - return rune(0x7b), true - case "lcy": - // CYRILLIC SMALL LETTER EL - return rune(0x043b), true - case "ldca": - // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS - return rune(0x2936), true - case "ldharb": - // LEFTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2956), true - case "ldot": - // LESS-THAN WITH DOT - return rune(0x22d6), true - case "ldquor": - // DOUBLE LOW-9 QUOTATION MARK - return rune(0x201e), true - case "ldquo": - // LEFT DOUBLE QUOTATION MARK - return rune(0x201c), true - case "ldrdhar": - // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN - return rune(0x2967), true - case "ldrdshar": - // LEFT BARB DOWN RIGHT BARB DOWN HARPOON - return rune(0x2950), true - case "ldrushar": - // LEFT BARB DOWN RIGHT BARB UP HARPOON - return rune(0x294b), true - case "ldsh": - // DOWNWARDS ARROW WITH TIP LEFTWARDS - return rune(0x21b2), true - case "leftarrowtail": - // LEFTWARDS ARROW WITH TAIL - return rune(0x21a2), true - case "leftarrow": - // LEFTWARDS ARROW - return rune(0x2190), true - case "leftharpoondown": - // LEFTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21bd), true - case "leftharpoonup": - // LEFTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21bc), true - case "leftleftarrows": - // LEFTWARDS PAIRED ARROWS - return rune(0x21c7), true - case "leftrightarrows": - // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true - case "leftrightarrow": - // LEFT RIGHT ARROW - return rune(0x2194), true - case "leftrightharpoons": - // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true - case "leftrightsquigarrow": - // LEFT RIGHT WAVE ARROW - return rune(0x21ad), true - case "le": - // LESS-THAN OR EQUAL TO - return rune(0x2264), true - case "leftthreetimes": - // LEFT SEMIDIRECT PRODUCT - return rune(0x22cb), true - case "leg": - // LESS-THAN EQUAL TO OR GREATER-THAN - return rune(0x22da), true - case "leq": - // LESS-THAN OR EQUAL TO - return rune(0x2264), true - case "leqq": - // LESS-THAN OVER EQUAL TO - return rune(0x2266), true - case "leqslant": - // LESS-THAN OR SLANTED EQUAL TO - return rune(0x2a7d), true - case "lesg": - // LESS-THAN slanted EQUAL TO OR GREATER-THAN - return rune(0x22da), true - case "lessdot": - // LESS-THAN WITH DOT - return rune(0x22d6), true - case "lesseqgtr": - // LESS-THAN EQUAL TO OR GREATER-THAN - return rune(0x22da), true - case "lessgtr": - // LESS-THAN OR GREATER-THAN - return rune(0x2276), true - case "lesssim": - // LESS-THAN OR EQUIVALENT TO - return rune(0x2272), true - case "les": - // LESS-THAN OR SLANTED EQUAL TO - return rune(0x2a7d), true - case "lescc": - // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL - return rune(0x2aa8), true - case "lesdot": - // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE - return rune(0x2a7f), true - case "lesdoto": - // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE - return rune(0x2a81), true - case "lesdotor": - // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT - return rune(0x2a83), true - case "lesges": - // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL - return rune(0x2a93), true - case "lessapprox": - // LESS-THAN OR APPROXIMATE - return rune(0x2a85), true - case "lesseqqgtr": - // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN - return rune(0x2a8b), true - case "lfbowtie": - // BOWTIE WITH LEFT HALF BLACK - return rune(0x29d1), true - case "lfisht": - // LEFT FISH TAIL - return rune(0x297c), true - case "lfloor": - // LEFT FLOOR - return rune(0x230a), true - case "lfr": - // MATHEMATICAL FRAKTUR SMALL L - return rune(0x01d529), true - case "lftimes": - // TIMES WITH LEFT HALF BLACK - return rune(0x29d4), true - case "lg": - // LESS-THAN OR GREATER-THAN - return rune(0x2276), true - case "lgE": - // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL - return rune(0x2a91), true - case "lgr": - // GREEK SMALL LETTER LAMDA - return rune(0x03bb), true - case "lhard": - // LEFTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21bd), true - case "lharu": - // LEFTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21bc), true - case "lharul": - // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - return rune(0x296a), true - case "lhblk": - // LOWER HALF BLOCK - return rune(0x2584), true - case "ljcy": - // CYRILLIC SMALL LETTER LJE - return rune(0x0459), true - case "llarr": - // LEFTWARDS PAIRED ARROWS - return rune(0x21c7), true - case "ll": - // MUCH LESS-THAN - return rune(0x226a), true - case "llcorner": - // BOTTOM LEFT CORNER - return rune(0x231e), true - case "llhard": - // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - return rune(0x296b), true - case "lltrif": - // BLACK LOWER LEFT TRIANGLE - return rune(0x25e3), true - case "lltri": - // LOWER LEFT TRIANGLE - return rune(0x25fa), true - case "lmidot": - // LATIN SMALL LETTER L WITH MIDDLE DOT - return rune(0x0140), true - case "lmoust": - // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - return rune(0x23b0), true - case "lmoustache": - // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - return rune(0x23b0), true - case "lnE": - // LESS-THAN BUT NOT EQUAL TO - return rune(0x2268), true - case "lnap": - // LESS-THAN AND NOT APPROXIMATE - return rune(0x2a89), true - case "lnapprox": - // LESS-THAN AND NOT APPROXIMATE - return rune(0x2a89), true - case "lneqq": - // LESS-THAN BUT NOT EQUAL TO - return rune(0x2268), true - case "lne": - // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a87), true - case "lneq": - // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a87), true - case "lnsim": - // LESS-THAN BUT NOT EQUIVALENT TO - return rune(0x22e6), true - case "loang": - // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET - return rune(0x27ec), true - case "loarr": - // LEFTWARDS OPEN-HEADED ARROW - return rune(0x21fd), true - case "lobrk": - // MATHEMATICAL LEFT WHITE SQUARE BRACKET - return rune(0x27e6), true - case "locub": - // LEFT WHITE CURLY BRACKET - return rune(0x2983), true - case "longleftarrow": - // LONG LEFTWARDS ARROW - return rune(0x27f5), true - case "longleftrightarrow": - // LONG LEFT RIGHT ARROW - return rune(0x27f7), true - case "longmapsto": - // LONG RIGHTWARDS ARROW FROM BAR - return rune(0x27fc), true - case "longrightarrow": - // LONG RIGHTWARDS ARROW - return rune(0x27f6), true - case "looparrowleft": - // LEFTWARDS ARROW WITH LOOP + case "larrhk": // LEFTWARDS ARROW WITH HOOK + return rune(0x21a9), true + case "larrlp": // LEFTWARDS ARROW WITH LOOP return rune(0x21ab), true - case "looparrowright": - // RIGHTWARDS ARROW WITH LOOP - return rune(0x21ac), true - case "lopar": - // LEFT WHITE PARENTHESIS - return rune(0x2985), true - case "lopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL L - return rune(0x01d55d), true - case "loplus": - // PLUS SIGN IN LEFT HALF CIRCLE - return rune(0x2a2d), true - case "lotimes": - // MULTIPLICATION SIGN IN LEFT HALF CIRCLE - return rune(0x2a34), true - case "lowast": - // LOW ASTERISK - return rune(0x204e), true - case "lowbar": - // LOW LINE - return rune(0x5f), true - case "lowint": - // INTEGRAL WITH UNDERBAR - return rune(0x2a1c), true - case "loz": - // LOZENGE - return rune(0x25ca), true - case "lozenge": - // LOZENGE - return rune(0x25ca), true - case "lozf": - // BLACK LOZENGE - return rune(0x29eb), true - case "lpargt": - // SPHERICAL ANGLE OPENING LEFT - return rune(0x29a0), true - case "lparlt": - // LEFT ARC LESS-THAN BRACKET - return rune(0x2993), true - case "lpar": - // LEFT PARENTHESIS - return rune(0x28), true - case "lrarr2": - // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true - case "lrarr": - // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true - case "lrcorner": - // BOTTOM RIGHT CORNER - return rune(0x231f), true - case "lrhar": - // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true - case "lrhar2": - // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true - case "lrhard": - // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - return rune(0x296d), true - case "lrm": - // LEFT-TO-RIGHT MARK - return rune(0x200e), true - case "lrtri": - // RIGHT TRIANGLE - return rune(0x22bf), true - case "lsaquo": - // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - return rune(0x2039), true - case "lscr": - // MATHEMATICAL SCRIPT SMALL L - return rune(0x01d4c1), true - case "lsh": - // UPWARDS ARROW WITH TIP LEFTWARDS - return rune(0x21b0), true - case "lsim": - // LESS-THAN OR EQUIVALENT TO - return rune(0x2272), true - case "lsime": - // LESS-THAN ABOVE SIMILAR OR EQUAL - return rune(0x2a8d), true - case "lsimg": - // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN - return rune(0x2a8f), true - case "lsqb": - // LEFT SQUARE BRACKET + case "larrpl": // LEFT-SIDE ARC ANTICLOCKWISE ARROW + return rune(0x2939), true + case "larrsim": // LEFTWARDS ARROW ABOVE TILDE OPERATOR + return rune(0x2973), true + case "larrtl": // LEFTWARDS ARROW WITH TAIL + return rune(0x21a2), true + case "lat": // LARGER THAN + return rune(0x2aab), true + case "latail": // LEFTWARDS ARROW-TAIL + return rune(0x2919), true + case "late": // LARGER THAN OR EQUAL TO + return rune(0x2aad), true + case "lates": // LARGER THAN OR slanted EQUAL + return rune(0x2aad), true + case "lbarr": // LEFTWARDS DOUBLE DASH ARROW + return rune(0x290c), true + case "lbbrk": // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + return rune(0x2772), true + case "lbrace": // LEFT CURLY BRACKET + return rune(0x7b), true + case "lbrack": // LEFT SQUARE BRACKET return rune(0x5b), true - case "lsquor": - // SINGLE LOW-9 QUOTATION MARK - return rune(0x201a), true - case "lsquo": - // LEFT SINGLE QUOTATION MARK - return rune(0x2018), true - case "lstrok": - // LATIN SMALL LETTER L WITH STROKE - return rune(0x0142), true - case "ltcc": - // LESS-THAN CLOSED BY CURVE - return rune(0x2aa6), true - case "ltcir": - // LESS-THAN WITH CIRCLE INSIDE - return rune(0x2a79), true - case "ltdot": - // LESS-THAN WITH DOT + case "lbrke": // LEFT SQUARE BRACKET WITH UNDERBAR + return rune(0x298b), true + case "lbrksld": // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + return rune(0x298f), true + case "lbrkslu": // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER + return rune(0x298d), true + case "lcaron": // LATIN SMALL LETTER L WITH CARON + return rune(0x013e), true + case "lcedil": // LATIN SMALL LETTER L WITH CEDILLA + return rune(0x013c), true + case "lceil": // LEFT CEILING + return rune(0x2308), true + case "lcub": // LEFT CURLY BRACKET + return rune(0x7b), true + case "lcy": // CYRILLIC SMALL LETTER EL + return rune(0x043b), true + case "ldca": // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS + return rune(0x2936), true + case "ldharb": // LEFTWARDS HARPOON WITH BARB DOWN TO BAR + return rune(0x2956), true + case "ldot": // LESS-THAN WITH DOT return rune(0x22d6), true - case "lthree": - // LEFT SEMIDIRECT PRODUCT + case "ldquo": // LEFT DOUBLE QUOTATION MARK + return rune(0x201c), true + case "ldquor": // DOUBLE LOW-9 QUOTATION MARK + return rune(0x201e), true + case "ldrdhar": // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN + return rune(0x2967), true + case "ldrdshar": // LEFT BARB DOWN RIGHT BARB DOWN HARPOON + return rune(0x2950), true + case "ldrushar": // LEFT BARB DOWN RIGHT BARB UP HARPOON + return rune(0x294b), true + case "ldsh": // DOWNWARDS ARROW WITH TIP LEFTWARDS + return rune(0x21b2), true + case "le": // LESS-THAN OR EQUAL TO + return rune(0x2264), true + case "leftarrow": // LEFTWARDS ARROW + return rune(0x2190), true + case "leftarrowtail": // LEFTWARDS ARROW WITH TAIL + return rune(0x21a2), true + case "leftharpoondown": // LEFTWARDS HARPOON WITH BARB DOWNWARDS + return rune(0x21bd), true + case "leftharpoonup": // LEFTWARDS HARPOON WITH BARB UPWARDS + return rune(0x21bc), true + case "leftleftarrows": // LEFTWARDS PAIRED ARROWS + return rune(0x21c7), true + case "leftrightarrow": // LEFT RIGHT ARROW + return rune(0x2194), true + case "leftrightarrows": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + return rune(0x21c6), true + case "leftrightharpoons": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + return rune(0x21cb), true + case "leftrightsquigarrow": // LEFT RIGHT WAVE ARROW + return rune(0x21ad), true + case "leftthreetimes": // LEFT SEMIDIRECT PRODUCT return rune(0x22cb), true - case "ltimes": - // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT - return rune(0x22c9), true - case "ltlarr": - // LESS-THAN ABOVE LEFTWARDS ARROW - return rune(0x2976), true - case "ltquest": - // LESS-THAN WITH QUESTION MARK ABOVE - return rune(0x2a7b), true - case "ltrPar": - // DOUBLE RIGHT ARC LESS-THAN BRACKET - return rune(0x2996), true - case "ltrie": - // NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22b4), true - case "ltrif": - // BLACK LEFT-POINTING SMALL TRIANGLE - return rune(0x25c2), true - case "ltri": - // WHITE LEFT-POINTING SMALL TRIANGLE - return rune(0x25c3), true - case "ltrivb": - // LEFT TRIANGLE BESIDE VERTICAL BAR - return rune(0x29cf), true - case "lt": - // LESS-THAN SIGN - return rune(0x3c), true - case "luharb": - // LEFTWARDS HARPOON WITH BARB UP TO BAR - return rune(0x2952), true - case "lurdshar": - // LEFT BARB UP RIGHT BARB DOWN HARPOON - return rune(0x294a), true - case "luruhar": - // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP - return rune(0x2966), true - case "lurushar": - // LEFT BARB UP RIGHT BARB UP HARPOON - return rune(0x294e), true - case "lvertneqq": - // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + case "leg": // LESS-THAN EQUAL TO OR GREATER-THAN + return rune(0x22da), true + case "leq": // LESS-THAN OR EQUAL TO + return rune(0x2264), true + case "leqq": // LESS-THAN OVER EQUAL TO + return rune(0x2266), true + case "leqslant": // LESS-THAN OR SLANTED EQUAL TO + return rune(0x2a7d), true + case "les": // LESS-THAN OR SLANTED EQUAL TO + return rune(0x2a7d), true + case "lescc": // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL + return rune(0x2aa8), true + case "lesdot": // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE + return rune(0x2a7f), true + case "lesdoto": // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE + return rune(0x2a81), true + case "lesdotor": // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT + return rune(0x2a83), true + case "lesg": // LESS-THAN slanted EQUAL TO OR GREATER-THAN + return rune(0x22da), true + case "lesges": // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL + return rune(0x2a93), true + case "lessapprox": // LESS-THAN OR APPROXIMATE + return rune(0x2a85), true + case "lessdot": // LESS-THAN WITH DOT + return rune(0x22d6), true + case "lesseqgtr": // LESS-THAN EQUAL TO OR GREATER-THAN + return rune(0x22da), true + case "lesseqqgtr": // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN + return rune(0x2a8b), true + case "lessgtr": // LESS-THAN OR GREATER-THAN + return rune(0x2276), true + case "lesssim": // LESS-THAN OR EQUIVALENT TO + return rune(0x2272), true + case "lfbowtie": // BOWTIE WITH LEFT HALF BLACK + return rune(0x29d1), true + case "lfisht": // LEFT FISH TAIL + return rune(0x297c), true + case "lfloor": // LEFT FLOOR + return rune(0x230a), true + case "lfr": // MATHEMATICAL FRAKTUR SMALL L + return rune(0x01d529), true + case "lftimes": // TIMES WITH LEFT HALF BLACK + return rune(0x29d4), true + case "lg": // LESS-THAN OR GREATER-THAN + return rune(0x2276), true + case "lgE": // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL + return rune(0x2a91), true + case "lgr": // GREEK SMALL LETTER LAMDA + return rune(0x03bb), true + case "lhard": // LEFTWARDS HARPOON WITH BARB DOWNWARDS + return rune(0x21bd), true + case "lharu": // LEFTWARDS HARPOON WITH BARB UPWARDS + return rune(0x21bc), true + case "lharul": // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH + return rune(0x296a), true + case "lhblk": // LOWER HALF BLOCK + return rune(0x2584), true + case "ljcy": // CYRILLIC SMALL LETTER LJE + return rune(0x0459), true + case "ll": // MUCH LESS-THAN + return rune(0x226a), true + case "llarr": // LEFTWARDS PAIRED ARROWS + return rune(0x21c7), true + case "llcorner": // BOTTOM LEFT CORNER + return rune(0x231e), true + case "llhard": // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH + return rune(0x296b), true + case "lltri": // LOWER LEFT TRIANGLE + return rune(0x25fa), true + case "lltrif": // BLACK LOWER LEFT TRIANGLE + return rune(0x25e3), true + case "lmidot": // LATIN SMALL LETTER L WITH MIDDLE DOT + return rune(0x0140), true + case "lmoust": // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION + return rune(0x23b0), true + case "lmoustache": // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION + return rune(0x23b0), true + case "lnE": // LESS-THAN BUT NOT EQUAL TO return rune(0x2268), true - case "lvnE": - // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + case "lnap": // LESS-THAN AND NOT APPROXIMATE + return rune(0x2a89), true + case "lnapprox": // LESS-THAN AND NOT APPROXIMATE + return rune(0x2a89), true + case "lne": // LESS-THAN AND SINGLE-LINE NOT EQUAL TO + return rune(0x2a87), true + case "lneq": // LESS-THAN AND SINGLE-LINE NOT EQUAL TO + return rune(0x2a87), true + case "lneqq": // LESS-THAN BUT NOT EQUAL TO + return rune(0x2268), true + case "lnsim": // LESS-THAN BUT NOT EQUIVALENT TO + return rune(0x22e6), true + case "loang": // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET + return rune(0x27ec), true + case "loarr": // LEFTWARDS OPEN-HEADED ARROW + return rune(0x21fd), true + case "lobrk": // MATHEMATICAL LEFT WHITE SQUARE BRACKET + return rune(0x27e6), true + case "locub": // LEFT WHITE CURLY BRACKET + return rune(0x2983), true + case "longleftarrow": // LONG LEFTWARDS ARROW + return rune(0x27f5), true + case "longleftrightarrow": // LONG LEFT RIGHT ARROW + return rune(0x27f7), true + case "longmapsto": // LONG RIGHTWARDS ARROW FROM BAR + return rune(0x27fc), true + case "longrightarrow": // LONG RIGHTWARDS ARROW + return rune(0x27f6), true + case "looparrowleft": // LEFTWARDS ARROW WITH LOOP + return rune(0x21ab), true + case "looparrowright": // RIGHTWARDS ARROW WITH LOOP + return rune(0x21ac), true + case "lopar": // LEFT WHITE PARENTHESIS + return rune(0x2985), true + case "lopf": // MATHEMATICAL DOUBLE-STRUCK SMALL L + return rune(0x01d55d), true + case "loplus": // PLUS SIGN IN LEFT HALF CIRCLE + return rune(0x2a2d), true + case "lotimes": // MULTIPLICATION SIGN IN LEFT HALF CIRCLE + return rune(0x2a34), true + case "lowast": // LOW ASTERISK + return rune(0x204e), true + case "lowbar": // LOW LINE + return rune(0x5f), true + case "lowint": // INTEGRAL WITH UNDERBAR + return rune(0x2a1c), true + case "loz": // LOZENGE + return rune(0x25ca), true + case "lozenge": // LOZENGE + return rune(0x25ca), true + case "lozf": // BLACK LOZENGE + return rune(0x29eb), true + case "lpar": // LEFT PARENTHESIS + return rune(0x28), true + case "lpargt": // SPHERICAL ANGLE OPENING LEFT + return rune(0x29a0), true + case "lparlt": // LEFT ARC LESS-THAN BRACKET + return rune(0x2993), true + case "lrarr": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + return rune(0x21c6), true + case "lrarr2": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + return rune(0x21c6), true + case "lrcorner": // BOTTOM RIGHT CORNER + return rune(0x231f), true + case "lrhar": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + return rune(0x21cb), true + case "lrhar2": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + return rune(0x21cb), true + case "lrhard": // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH + return rune(0x296d), true + case "lrm": // LEFT-TO-RIGHT MARK + return rune(0x200e), true + case "lrtri": // RIGHT TRIANGLE + return rune(0x22bf), true + case "lsaquo": // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + return rune(0x2039), true + case "lscr": // MATHEMATICAL SCRIPT SMALL L + return rune(0x01d4c1), true + case "lsh": // UPWARDS ARROW WITH TIP LEFTWARDS + return rune(0x21b0), true + case "lsim": // LESS-THAN OR EQUIVALENT TO + return rune(0x2272), true + case "lsime": // LESS-THAN ABOVE SIMILAR OR EQUAL + return rune(0x2a8d), true + case "lsimg": // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN + return rune(0x2a8f), true + case "lsqb": // LEFT SQUARE BRACKET + return rune(0x5b), true + case "lsquo": // LEFT SINGLE QUOTATION MARK + return rune(0x2018), true + case "lsquor": // SINGLE LOW-9 QUOTATION MARK + return rune(0x201a), true + case "lstrok": // LATIN SMALL LETTER L WITH STROKE + return rune(0x0142), true + case "lt": // LESS-THAN SIGN + return rune(0x3c), true + case "ltcc": // LESS-THAN CLOSED BY CURVE + return rune(0x2aa6), true + case "ltcir": // LESS-THAN WITH CIRCLE INSIDE + return rune(0x2a79), true + case "ltdot": // LESS-THAN WITH DOT + return rune(0x22d6), true + case "lthree": // LEFT SEMIDIRECT PRODUCT + return rune(0x22cb), true + case "ltimes": // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT + return rune(0x22c9), true + case "ltlarr": // LESS-THAN ABOVE LEFTWARDS ARROW + return rune(0x2976), true + case "ltquest": // LESS-THAN WITH QUESTION MARK ABOVE + return rune(0x2a7b), true + case "ltrPar": // DOUBLE RIGHT ARC LESS-THAN BRACKET + return rune(0x2996), true + case "ltri": // WHITE LEFT-POINTING SMALL TRIANGLE + return rune(0x25c3), true + case "ltrie": // NORMAL SUBGROUP OF OR EQUAL TO + return rune(0x22b4), true + case "ltrif": // BLACK LEFT-POINTING SMALL TRIANGLE + return rune(0x25c2), true + case "ltrivb": // LEFT TRIANGLE BESIDE VERTICAL BAR + return rune(0x29cf), true + case "luharb": // LEFTWARDS HARPOON WITH BARB UP TO BAR + return rune(0x2952), true + case "lurdshar": // LEFT BARB UP RIGHT BARB DOWN HARPOON + return rune(0x294a), true + case "luruhar": // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP + return rune(0x2966), true + case "lurushar": // LEFT BARB UP RIGHT BARB UP HARPOON + return rune(0x294e), true + case "lvertneqq": // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + return rune(0x2268), true + case "lvnE": // LESS-THAN BUT NOT EQUAL TO - with vertical stroke return rune(0x2268), true } case 'm': switch name { - case "mDDot": - // GEOMETRIC PROPORTION + case "mDDot": // GEOMETRIC PROPORTION return rune(0x223a), true - case "macr": - // MACRON + case "macr": // MACRON return rune(0xaf), true - case "male": - // MALE SIGN + case "male": // MALE SIGN return rune(0x2642), true - case "malt": - // MALTESE CROSS + case "malt": // MALTESE CROSS return rune(0x2720), true - case "maltese": - // MALTESE CROSS + case "maltese": // MALTESE CROSS return rune(0x2720), true - case "mapstodown": - // DOWNWARDS ARROW FROM BAR + case "map": // RIGHTWARDS ARROW FROM BAR + return rune(0x21a6), true + case "mapsto": // RIGHTWARDS ARROW FROM BAR + return rune(0x21a6), true + case "mapstodown": // DOWNWARDS ARROW FROM BAR return rune(0x21a7), true - case "mapsto": - // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true - case "map": - // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true - case "mapstoleft": - // LEFTWARDS ARROW FROM BAR + case "mapstoleft": // LEFTWARDS ARROW FROM BAR return rune(0x21a4), true - case "mapstoup": - // UPWARDS ARROW FROM BAR + case "mapstoup": // UPWARDS ARROW FROM BAR return rune(0x21a5), true - case "marker": - // BLACK VERTICAL RECTANGLE + case "marker": // BLACK VERTICAL RECTANGLE return rune(0x25ae), true - case "mcomma": - // MINUS SIGN WITH COMMA ABOVE + case "mcomma": // MINUS SIGN WITH COMMA ABOVE return rune(0x2a29), true - case "mcy": - // CYRILLIC SMALL LETTER EM + case "mcy": // CYRILLIC SMALL LETTER EM return rune(0x043c), true - case "mdash": - // EM DASH + case "mdash": // EM DASH return rune(0x2014), true - case "measuredangle": - // MEASURED ANGLE + case "measuredangle": // MEASURED ANGLE return rune(0x2221), true - case "mfr": - // MATHEMATICAL FRAKTUR SMALL M + case "mfr": // MATHEMATICAL FRAKTUR SMALL M return rune(0x01d52a), true - case "mgr": - // GREEK SMALL LETTER MU + case "mgr": // GREEK SMALL LETTER MU return rune(0x03bc), true - case "mho": - // INVERTED OHM SIGN + case "mho": // INVERTED OHM SIGN return rune(0x2127), true - case "micro": - // MICRO SIGN + case "micro": // MICRO SIGN return rune(0xb5), true - case "mid": - // DIVIDES + case "mid": // DIVIDES return rune(0x2223), true - case "midast": - // ASTERISK + case "midast": // ASTERISK return rune(0x2a), true - case "midcir": - // VERTICAL LINE WITH CIRCLE BELOW + case "midcir": // VERTICAL LINE WITH CIRCLE BELOW return rune(0x2af0), true - case "middot": - // MIDDLE DOT + case "middot": // MIDDLE DOT return rune(0xb7), true - case "minus": - // MINUS SIGN + case "minus": // MINUS SIGN return rune(0x2212), true - case "minusb": - // SQUARED MINUS + case "minusb": // SQUARED MINUS return rune(0x229f), true - case "minusd": - // DOT MINUS + case "minusd": // DOT MINUS return rune(0x2238), true - case "minusdu": - // MINUS SIGN WITH DOT BELOW + case "minusdu": // MINUS SIGN WITH DOT BELOW return rune(0x2a2a), true - case "mlcp": - // TRANSVERSAL INTERSECTION + case "mlcp": // TRANSVERSAL INTERSECTION return rune(0x2adb), true - case "mldr": - // HORIZONTAL ELLIPSIS + case "mldr": // HORIZONTAL ELLIPSIS return rune(0x2026), true - case "mnplus": - // MINUS-OR-PLUS SIGN + case "mnplus": // MINUS-OR-PLUS SIGN return rune(0x2213), true - case "models": - // MODELS + case "models": // MODELS return rune(0x22a7), true - case "mopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL M + case "mopf": // MATHEMATICAL DOUBLE-STRUCK SMALL M return rune(0x01d55e), true - case "mp": - // MINUS-OR-PLUS SIGN + case "mp": // MINUS-OR-PLUS SIGN return rune(0x2213), true - case "mscr": - // MATHEMATICAL SCRIPT SMALL M + case "mscr": // MATHEMATICAL SCRIPT SMALL M return rune(0x01d4c2), true - case "mstpos": - // INVERTED LAZY S + case "mstpos": // INVERTED LAZY S return rune(0x223e), true - case "multimap": - // MULTIMAP - return rune(0x22b8), true - case "mumap": - // MULTIMAP - return rune(0x22b8), true - case "mu": - // GREEK SMALL LETTER MU + case "mu": // GREEK SMALL LETTER MU return rune(0x03bc), true + case "multimap": // MULTIMAP + return rune(0x22b8), true + case "mumap": // MULTIMAP + return rune(0x22b8), true } case 'n': switch name { - case "nGg": - // VERY MUCH GREATER-THAN with slash + case "nGg": // VERY MUCH GREATER-THAN with slash return rune(0x22d9), true - case "nGtv": - // MUCH GREATER THAN with slash + case "nGt": // MUCH GREATER THAN with vertical line return rune(0x226b), true - case "nGt": - // MUCH GREATER THAN with vertical line + case "nGtv": // MUCH GREATER THAN with slash return rune(0x226b), true - case "nLeftarrow": - // LEFTWARDS DOUBLE ARROW WITH STROKE + case "nLeftarrow": // LEFTWARDS DOUBLE ARROW WITH STROKE return rune(0x21cd), true - case "nLeftrightarrow": - // LEFT RIGHT DOUBLE ARROW WITH STROKE + case "nLeftrightarrow": // LEFT RIGHT DOUBLE ARROW WITH STROKE return rune(0x21ce), true - case "nLl": - // VERY MUCH LESS-THAN with slash + case "nLl": // VERY MUCH LESS-THAN with slash return rune(0x22d8), true - case "nLtv": - // MUCH LESS THAN with slash + case "nLt": // MUCH LESS THAN with vertical line return rune(0x226a), true - case "nLt": - // MUCH LESS THAN with vertical line + case "nLtv": // MUCH LESS THAN with slash return rune(0x226a), true - case "nRightarrow": - // RIGHTWARDS DOUBLE ARROW WITH STROKE + case "nRightarrow": // RIGHTWARDS DOUBLE ARROW WITH STROKE return rune(0x21cf), true - case "nVDash": - // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE + case "nVDash": // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE return rune(0x22af), true - case "nVdash": - // DOES NOT FORCE + case "nVdash": // DOES NOT FORCE return rune(0x22ae), true - case "nabla": - // NABLA + case "nabla": // NABLA return rune(0x2207), true - case "nacute": - // LATIN SMALL LETTER N WITH ACUTE + case "nacute": // LATIN SMALL LETTER N WITH ACUTE return rune(0x0144), true - case "nang": - // ANGLE with vertical line + case "nang": // ANGLE with vertical line return rune(0x2220), true - case "nap": - // NOT ALMOST EQUAL TO + case "nap": // NOT ALMOST EQUAL TO return rune(0x2249), true - case "napE": - // APPROXIMATELY EQUAL OR EQUAL TO with slash + case "napE": // APPROXIMATELY EQUAL OR EQUAL TO with slash return rune(0x2a70), true - case "napid": - // TRIPLE TILDE with slash + case "napid": // TRIPLE TILDE with slash return rune(0x224b), true - case "napos": - // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + case "napos": // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE return rune(0x0149), true - case "napprox": - // NOT ALMOST EQUAL TO + case "napprox": // NOT ALMOST EQUAL TO return rune(0x2249), true - case "naturals": - // DOUBLE-STRUCK CAPITAL N + case "natur": // MUSIC NATURAL SIGN + return rune(0x266e), true + case "natural": // MUSIC NATURAL SIGN + return rune(0x266e), true + case "naturals": // DOUBLE-STRUCK CAPITAL N return rune(0x2115), true - case "natur": - // MUSIC NATURAL SIGN - return rune(0x266e), true - case "natural": - // MUSIC NATURAL SIGN - return rune(0x266e), true - case "nbsp": - // NO-BREAK SPACE + case "nbsp": // NO-BREAK SPACE return rune(0xa0), true - case "nbump": - // GEOMETRICALLY EQUIVALENT TO with slash + case "nbump": // GEOMETRICALLY EQUIVALENT TO with slash return rune(0x224e), true - case "nbumpe": - // DIFFERENCE BETWEEN with slash + case "nbumpe": // DIFFERENCE BETWEEN with slash return rune(0x224f), true - case "ncap": - // INTERSECTION WITH OVERBAR + case "ncap": // INTERSECTION WITH OVERBAR return rune(0x2a43), true - case "ncaron": - // LATIN SMALL LETTER N WITH CARON + case "ncaron": // LATIN SMALL LETTER N WITH CARON return rune(0x0148), true - case "ncedil": - // LATIN SMALL LETTER N WITH CEDILLA + case "ncedil": // LATIN SMALL LETTER N WITH CEDILLA return rune(0x0146), true - case "ncong": - // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO + case "ncong": // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO return rune(0x2247), true - case "ncongdot": - // CONGRUENT WITH DOT ABOVE with slash + case "ncongdot": // CONGRUENT WITH DOT ABOVE with slash return rune(0x2a6d), true - case "ncup": - // UNION WITH OVERBAR + case "ncup": // UNION WITH OVERBAR return rune(0x2a42), true - case "ncy": - // CYRILLIC SMALL LETTER EN + case "ncy": // CYRILLIC SMALL LETTER EN return rune(0x043d), true - case "ndash": - // EN DASH + case "ndash": // EN DASH return rune(0x2013), true - case "neArr": - // NORTH EAST DOUBLE ARROW - return rune(0x21d7), true - case "nearrow": - // NORTH EAST ARROW - return rune(0x2197), true - case "nearr": - // NORTH EAST ARROW - return rune(0x2197), true - case "nedot": - // APPROACHES THE LIMIT with slash - return rune(0x2250), true - case "nesim": - // MINUS TILDE with slash - return rune(0x2242), true - case "nexist": - // THERE DOES NOT EXIST - return rune(0x2204), true - case "nexists": - // THERE DOES NOT EXIST - return rune(0x2204), true - case "ne": - // NOT EQUAL TO + case "ne": // NOT EQUAL TO return rune(0x2260), true - case "nearhk": - // NORTH EAST ARROW WITH HOOK + case "neArr": // NORTH EAST DOUBLE ARROW + return rune(0x21d7), true + case "nearhk": // NORTH EAST ARROW WITH HOOK return rune(0x2924), true - case "neonwarr": - // NORTH EAST ARROW CROSSING NORTH WEST ARROW + case "nearr": // NORTH EAST ARROW + return rune(0x2197), true + case "nearrow": // NORTH EAST ARROW + return rune(0x2197), true + case "nedot": // APPROACHES THE LIMIT with slash + return rune(0x2250), true + case "neonwarr": // NORTH EAST ARROW CROSSING NORTH WEST ARROW return rune(0x2931), true - case "neosearr": - // NORTH EAST ARROW CROSSING SOUTH EAST ARROW + case "neosearr": // NORTH EAST ARROW CROSSING SOUTH EAST ARROW return rune(0x292e), true - case "nequiv": - // NOT IDENTICAL TO + case "nequiv": // NOT IDENTICAL TO return rune(0x2262), true - case "nesear": - // NORTH EAST ARROW AND SOUTH EAST ARROW + case "nesear": // NORTH EAST ARROW AND SOUTH EAST ARROW return rune(0x2928), true - case "neswsarr": - // NORTH EAST AND SOUTH WEST ARROW + case "nesim": // MINUS TILDE with slash + return rune(0x2242), true + case "neswsarr": // NORTH EAST AND SOUTH WEST ARROW return rune(0x2922), true - case "nfr": - // MATHEMATICAL FRAKTUR SMALL N + case "nexist": // THERE DOES NOT EXIST + return rune(0x2204), true + case "nexists": // THERE DOES NOT EXIST + return rune(0x2204), true + case "nfr": // MATHEMATICAL FRAKTUR SMALL N return rune(0x01d52b), true - case "ngE": - // GREATER-THAN OVER EQUAL TO with slash + case "ngE": // GREATER-THAN OVER EQUAL TO with slash return rune(0x2267), true - case "ngeqq": - // GREATER-THAN OVER EQUAL TO with slash + case "nge": // NEITHER GREATER-THAN NOR EQUAL TO + return rune(0x2271), true + case "ngeq": // NEITHER GREATER-THAN NOR EQUAL TO + return rune(0x2271), true + case "ngeqq": // GREATER-THAN OVER EQUAL TO with slash return rune(0x2267), true - case "nge": - // NEITHER GREATER-THAN NOR EQUAL TO - return rune(0x2271), true - case "ngeq": - // NEITHER GREATER-THAN NOR EQUAL TO - return rune(0x2271), true - case "ngeqslant": - // GREATER-THAN OR SLANTED EQUAL TO with slash + case "ngeqslant": // GREATER-THAN OR SLANTED EQUAL TO with slash return rune(0x2a7e), true - case "nges": - // GREATER-THAN OR SLANTED EQUAL TO with slash + case "nges": // GREATER-THAN OR SLANTED EQUAL TO with slash return rune(0x2a7e), true - case "ngr": - // GREEK SMALL LETTER NU + case "ngr": // GREEK SMALL LETTER NU return rune(0x03bd), true - case "ngsim": - // NEITHER GREATER-THAN NOR EQUIVALENT TO + case "ngsim": // NEITHER GREATER-THAN NOR EQUIVALENT TO return rune(0x2275), true - case "ngt": - // NOT GREATER-THAN + case "ngt": // NOT GREATER-THAN return rune(0x226f), true - case "ngtr": - // NOT GREATER-THAN + case "ngtr": // NOT GREATER-THAN return rune(0x226f), true - case "nhArr": - // LEFT RIGHT DOUBLE ARROW WITH STROKE + case "nhArr": // LEFT RIGHT DOUBLE ARROW WITH STROKE return rune(0x21ce), true - case "nharr": - // LEFT RIGHT ARROW WITH STROKE + case "nharr": // LEFT RIGHT ARROW WITH STROKE return rune(0x21ae), true - case "nhpar": - // PARALLEL WITH HORIZONTAL STROKE + case "nhpar": // PARALLEL WITH HORIZONTAL STROKE return rune(0x2af2), true - case "niv": - // CONTAINS AS MEMBER + case "ni": // CONTAINS AS MEMBER return rune(0x220b), true - case "ni": - // CONTAINS AS MEMBER - return rune(0x220b), true - case "nisd": - // CONTAINS WITH LONG HORIZONTAL STROKE - return rune(0x22fa), true - case "nis": - // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + case "nis": // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE return rune(0x22fc), true - case "njcy": - // CYRILLIC SMALL LETTER NJE + case "nisd": // CONTAINS WITH LONG HORIZONTAL STROKE + return rune(0x22fa), true + case "niv": // CONTAINS AS MEMBER + return rune(0x220b), true + case "njcy": // CYRILLIC SMALL LETTER NJE return rune(0x045a), true - case "nlArr": - // LEFTWARDS DOUBLE ARROW WITH STROKE + case "nlArr": // LEFTWARDS DOUBLE ARROW WITH STROKE return rune(0x21cd), true - case "nlE": - // LESS-THAN OVER EQUAL TO with slash + case "nlE": // LESS-THAN OVER EQUAL TO with slash return rune(0x2266), true - case "nlarr": - // LEFTWARDS ARROW WITH STROKE + case "nlarr": // LEFTWARDS ARROW WITH STROKE return rune(0x219a), true - case "nldr": - // TWO DOT LEADER + case "nldr": // TWO DOT LEADER return rune(0x2025), true - case "nleftarrow": - // LEFTWARDS ARROW WITH STROKE + case "nle": // NEITHER LESS-THAN NOR EQUAL TO + return rune(0x2270), true + case "nleftarrow": // LEFTWARDS ARROW WITH STROKE return rune(0x219a), true - case "nleftrightarrow": - // LEFT RIGHT ARROW WITH STROKE + case "nleftrightarrow": // LEFT RIGHT ARROW WITH STROKE return rune(0x21ae), true - case "nleqq": - // LESS-THAN OVER EQUAL TO with slash + case "nleq": // NEITHER LESS-THAN NOR EQUAL TO + return rune(0x2270), true + case "nleqq": // LESS-THAN OVER EQUAL TO with slash return rune(0x2266), true - case "nless": - // NOT LESS-THAN + case "nleqslant": // LESS-THAN OR SLANTED EQUAL TO with slash + return rune(0x2a7d), true + case "nles": // LESS-THAN OR SLANTED EQUAL TO with slash + return rune(0x2a7d), true + case "nless": // NOT LESS-THAN return rune(0x226e), true - case "nle": - // NEITHER LESS-THAN NOR EQUAL TO - return rune(0x2270), true - case "nleq": - // NEITHER LESS-THAN NOR EQUAL TO - return rune(0x2270), true - case "nleqslant": - // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true - case "nles": - // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true - case "nlsim": - // NEITHER LESS-THAN NOR EQUIVALENT TO + case "nlsim": // NEITHER LESS-THAN NOR EQUIVALENT TO return rune(0x2274), true - case "nlt": - // NOT LESS-THAN + case "nlt": // NOT LESS-THAN return rune(0x226e), true - case "nltri": - // NOT NORMAL SUBGROUP OF + case "nltri": // NOT NORMAL SUBGROUP OF return rune(0x22ea), true - case "nltrie": - // NOT NORMAL SUBGROUP OF OR EQUAL TO + case "nltrie": // NOT NORMAL SUBGROUP OF OR EQUAL TO return rune(0x22ec), true - case "nltrivb": - // LEFT TRIANGLE BESIDE VERTICAL BAR with slash + case "nltrivb": // LEFT TRIANGLE BESIDE VERTICAL BAR with slash return rune(0x29cf), true - case "nmid": - // DOES NOT DIVIDE + case "nmid": // DOES NOT DIVIDE return rune(0x2224), true - case "nopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL N + case "nopf": // MATHEMATICAL DOUBLE-STRUCK SMALL N return rune(0x01d55f), true - case "notin": - // NOT AN ELEMENT OF - return rune(0x2209), true - case "notinE": - // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash - return rune(0x22f9), true - case "notindot": - // ELEMENT OF WITH DOT ABOVE with slash - return rune(0x22f5), true - case "notinva": - // NOT AN ELEMENT OF - return rune(0x2209), true - case "notinvb": - // SMALL ELEMENT OF WITH OVERBAR - return rune(0x22f7), true - case "notinvc": - // ELEMENT OF WITH OVERBAR - return rune(0x22f6), true - case "notni": - // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true - case "notniva": - // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true - case "notnivb": - // SMALL CONTAINS WITH OVERBAR - return rune(0x22fe), true - case "notnivc": - // CONTAINS WITH OVERBAR - return rune(0x22fd), true - case "not": - // NOT SIGN + case "not": // NOT SIGN return rune(0xac), true - case "npart": - // PARTIAL DIFFERENTIAL with slash - return rune(0x2202), true - case "npar": - // NOT PARALLEL TO + case "notin": // NOT AN ELEMENT OF + return rune(0x2209), true + case "notinE": // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash + return rune(0x22f9), true + case "notindot": // ELEMENT OF WITH DOT ABOVE with slash + return rune(0x22f5), true + case "notinva": // NOT AN ELEMENT OF + return rune(0x2209), true + case "notinvb": // SMALL ELEMENT OF WITH OVERBAR + return rune(0x22f7), true + case "notinvc": // ELEMENT OF WITH OVERBAR + return rune(0x22f6), true + case "notni": // DOES NOT CONTAIN AS MEMBER + return rune(0x220c), true + case "notniva": // DOES NOT CONTAIN AS MEMBER + return rune(0x220c), true + case "notnivb": // SMALL CONTAINS WITH OVERBAR + return rune(0x22fe), true + case "notnivc": // CONTAINS WITH OVERBAR + return rune(0x22fd), true + case "npar": // NOT PARALLEL TO return rune(0x2226), true - case "nparallel": - // NOT PARALLEL TO + case "nparallel": // NOT PARALLEL TO return rune(0x2226), true - case "nparsl": - // DOUBLE SOLIDUS OPERATOR with reverse slash + case "nparsl": // DOUBLE SOLIDUS OPERATOR with reverse slash return rune(0x2afd), true - case "npolint": - // LINE INTEGRATION NOT INCLUDING THE POLE + case "npart": // PARTIAL DIFFERENTIAL with slash + return rune(0x2202), true + case "npolint": // LINE INTEGRATION NOT INCLUDING THE POLE return rune(0x2a14), true - case "nprsim": - // PRECEDES OR EQUIVALENT TO with slash - return rune(0x227e), true - case "npr": - // DOES NOT PRECEDE + case "npr": // DOES NOT PRECEDE return rune(0x2280), true - case "nprcue": - // DOES NOT PRECEDE OR EQUAL + case "nprcue": // DOES NOT PRECEDE OR EQUAL return rune(0x22e0), true - case "nprec": - // DOES NOT PRECEDE + case "npre": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + return rune(0x2aaf), true + case "nprec": // DOES NOT PRECEDE return rune(0x2280), true - case "npre": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + case "npreceq": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash return rune(0x2aaf), true - case "npreceq": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2aaf), true - case "nrArr": - // RIGHTWARDS DOUBLE ARROW WITH STROKE + case "nprsim": // PRECEDES OR EQUIVALENT TO with slash + return rune(0x227e), true + case "nrArr": // RIGHTWARDS DOUBLE ARROW WITH STROKE return rune(0x21cf), true - case "nrarrw": - // RIGHTWARDS WAVE ARROW with slash - return rune(0x219d), true - case "nrarr": - // RIGHTWARDS ARROW WITH STROKE + case "nrarr": // RIGHTWARDS ARROW WITH STROKE return rune(0x219b), true - case "nrarrc": - // WAVE ARROW POINTING DIRECTLY RIGHT with slash + case "nrarrc": // WAVE ARROW POINTING DIRECTLY RIGHT with slash return rune(0x2933), true - case "nrightarrow": - // RIGHTWARDS ARROW WITH STROKE + case "nrarrw": // RIGHTWARDS WAVE ARROW with slash + return rune(0x219d), true + case "nrightarrow": // RIGHTWARDS ARROW WITH STROKE return rune(0x219b), true - case "nrtri": - // DOES NOT CONTAIN AS NORMAL SUBGROUP + case "nrtri": // DOES NOT CONTAIN AS NORMAL SUBGROUP return rune(0x22eb), true - case "nrtrie": - // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL + case "nrtrie": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL return rune(0x22ed), true - case "nsGt": - // DOUBLE NESTED GREATER-THAN with slash + case "nsGt": // DOUBLE NESTED GREATER-THAN with slash return rune(0x2aa2), true - case "nsLt": - // DOUBLE NESTED LESS-THAN with slash + case "nsLt": // DOUBLE NESTED LESS-THAN with slash return rune(0x2aa1), true - case "nscsim": - // SUCCEEDS OR EQUIVALENT TO with slash - return rune(0x227f), true - case "nsc": - // DOES NOT SUCCEED + case "nsc": // DOES NOT SUCCEED return rune(0x2281), true - case "nsccue": - // DOES NOT SUCCEED OR EQUAL + case "nsccue": // DOES NOT SUCCEED OR EQUAL return rune(0x22e1), true - case "nsce": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + case "nsce": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash return rune(0x2ab0), true - case "nscr": - // MATHEMATICAL SCRIPT SMALL N + case "nscr": // MATHEMATICAL SCRIPT SMALL N return rune(0x01d4c3), true - case "nshortmid": - // DOES NOT DIVIDE + case "nscsim": // SUCCEEDS OR EQUIVALENT TO with slash + return rune(0x227f), true + case "nshortmid": // DOES NOT DIVIDE return rune(0x2224), true - case "nshortparallel": - // NOT PARALLEL TO + case "nshortparallel": // NOT PARALLEL TO return rune(0x2226), true - case "nsim": - // NOT TILDE + case "nsim": // NOT TILDE return rune(0x2241), true - case "nsime": - // NOT ASYMPTOTICALLY EQUAL TO + case "nsime": // NOT ASYMPTOTICALLY EQUAL TO return rune(0x2244), true - case "nsimeq": - // NOT ASYMPTOTICALLY EQUAL TO + case "nsimeq": // NOT ASYMPTOTICALLY EQUAL TO return rune(0x2244), true - case "nsmid": - // DOES NOT DIVIDE + case "nsmid": // DOES NOT DIVIDE return rune(0x2224), true - case "nspar": - // NOT PARALLEL TO + case "nspar": // NOT PARALLEL TO return rune(0x2226), true - case "nsqsub": - // SQUARE IMAGE OF with slash + case "nsqsub": // SQUARE IMAGE OF with slash return rune(0x228f), true - case "nsqsube": - // NOT SQUARE IMAGE OF OR EQUAL TO + case "nsqsube": // NOT SQUARE IMAGE OF OR EQUAL TO return rune(0x22e2), true - case "nsqsup": - // SQUARE ORIGINAL OF with slash + case "nsqsup": // SQUARE ORIGINAL OF with slash return rune(0x2290), true - case "nsqsupe": - // NOT SQUARE ORIGINAL OF OR EQUAL TO + case "nsqsupe": // NOT SQUARE ORIGINAL OF OR EQUAL TO return rune(0x22e3), true - case "nsubset": - // SUBSET OF with vertical line - return rune(0x2282), true - case "nsub": - // NOT A SUBSET OF + case "nsub": // NOT A SUBSET OF return rune(0x2284), true - case "nsubE": - // SUBSET OF ABOVE EQUALS SIGN with slash + case "nsubE": // SUBSET OF ABOVE EQUALS SIGN with slash return rune(0x2ac5), true - case "nsube": - // NEITHER A SUBSET OF NOR EQUAL TO + case "nsube": // NEITHER A SUBSET OF NOR EQUAL TO return rune(0x2288), true - case "nsubseteq": - // NEITHER A SUBSET OF NOR EQUAL TO + case "nsubset": // SUBSET OF with vertical line + return rune(0x2282), true + case "nsubseteq": // NEITHER A SUBSET OF NOR EQUAL TO return rune(0x2288), true - case "nsubseteqq": - // SUBSET OF ABOVE EQUALS SIGN with slash + case "nsubseteqq": // SUBSET OF ABOVE EQUALS SIGN with slash return rune(0x2ac5), true - case "nsucc": - // DOES NOT SUCCEED + case "nsucc": // DOES NOT SUCCEED return rune(0x2281), true - case "nsucceq": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + case "nsucceq": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash return rune(0x2ab0), true - case "nsupset": - // SUPERSET OF with vertical line - return rune(0x2283), true - case "nsup": - // NOT A SUPERSET OF + case "nsup": // NOT A SUPERSET OF return rune(0x2285), true - case "nsupE": - // SUPERSET OF ABOVE EQUALS SIGN with slash + case "nsupE": // SUPERSET OF ABOVE EQUALS SIGN with slash return rune(0x2ac6), true - case "nsupe": - // NEITHER A SUPERSET OF NOR EQUAL TO + case "nsupe": // NEITHER A SUPERSET OF NOR EQUAL TO return rune(0x2289), true - case "nsupseteq": - // NEITHER A SUPERSET OF NOR EQUAL TO + case "nsupset": // SUPERSET OF with vertical line + return rune(0x2283), true + case "nsupseteq": // NEITHER A SUPERSET OF NOR EQUAL TO return rune(0x2289), true - case "nsupseteqq": - // SUPERSET OF ABOVE EQUALS SIGN with slash + case "nsupseteqq": // SUPERSET OF ABOVE EQUALS SIGN with slash return rune(0x2ac6), true - case "ntgl": - // NEITHER GREATER-THAN NOR LESS-THAN + case "ntgl": // NEITHER GREATER-THAN NOR LESS-THAN return rune(0x2279), true - case "ntilde": - // LATIN SMALL LETTER N WITH TILDE + case "ntilde": // LATIN SMALL LETTER N WITH TILDE return rune(0xf1), true - case "ntlg": - // NEITHER LESS-THAN NOR GREATER-THAN + case "ntlg": // NEITHER LESS-THAN NOR GREATER-THAN return rune(0x2278), true - case "ntriangleleft": - // NOT NORMAL SUBGROUP OF + case "ntriangleleft": // NOT NORMAL SUBGROUP OF return rune(0x22ea), true - case "ntrianglelefteq": - // NOT NORMAL SUBGROUP OF OR EQUAL TO + case "ntrianglelefteq": // NOT NORMAL SUBGROUP OF OR EQUAL TO return rune(0x22ec), true - case "ntriangleright": - // DOES NOT CONTAIN AS NORMAL SUBGROUP + case "ntriangleright": // DOES NOT CONTAIN AS NORMAL SUBGROUP return rune(0x22eb), true - case "ntrianglerighteq": - // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL + case "ntrianglerighteq": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL return rune(0x22ed), true - case "numero": - // NUMERO SIGN - return rune(0x2116), true - case "numsp": - // FIGURE SPACE - return rune(0x2007), true - case "nu": - // GREEK SMALL LETTER NU + case "nu": // GREEK SMALL LETTER NU return rune(0x03bd), true - case "num": - // NUMBER SIGN + case "num": // NUMBER SIGN return rune(0x23), true - case "nvDash": - // NOT TRUE + case "numero": // NUMERO SIGN + return rune(0x2116), true + case "numsp": // FIGURE SPACE + return rune(0x2007), true + case "nvDash": // NOT TRUE return rune(0x22ad), true - case "nvHarr": - // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE + case "nvHarr": // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE return rune(0x2904), true - case "nvap": - // EQUIVALENT TO with vertical line + case "nvap": // EQUIVALENT TO with vertical line return rune(0x224d), true - case "nvbrtri": - // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash + case "nvbrtri": // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash return rune(0x29d0), true - case "nvdash": - // DOES NOT PROVE + case "nvdash": // DOES NOT PROVE return rune(0x22ac), true - case "nvge": - // GREATER-THAN OR EQUAL TO with vertical line + case "nvge": // GREATER-THAN OR EQUAL TO with vertical line return rune(0x2265), true - case "nvgt": - // GREATER-THAN SIGN with vertical line + case "nvgt": // GREATER-THAN SIGN with vertical line return rune(0x3e), true - case "nvinfin": - // INFINITY NEGATED WITH VERTICAL BAR + case "nvinfin": // INFINITY NEGATED WITH VERTICAL BAR return rune(0x29de), true - case "nvlArr": - // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE + case "nvlArr": // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE return rune(0x2902), true - case "nvle": - // LESS-THAN OR EQUAL TO with vertical line + case "nvle": // LESS-THAN OR EQUAL TO with vertical line return rune(0x2264), true - case "nvltrie": - // NORMAL SUBGROUP OF OR EQUAL TO with vertical line - return rune(0x22b4), true - case "nvlt": - // LESS-THAN SIGN with vertical line + case "nvlt": // LESS-THAN SIGN with vertical line return rune(0x3c), true - case "nvrArr": - // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE + case "nvltrie": // NORMAL SUBGROUP OF OR EQUAL TO with vertical line + return rune(0x22b4), true + case "nvrArr": // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE return rune(0x2903), true - case "nvrtrie": - // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line + case "nvrtrie": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line return rune(0x22b5), true - case "nvsim": - // TILDE OPERATOR with vertical line + case "nvsim": // TILDE OPERATOR with vertical line return rune(0x223c), true - case "nwArr": - // NORTH WEST DOUBLE ARROW + case "nwArr": // NORTH WEST DOUBLE ARROW return rune(0x21d6), true - case "nwarhk": - // NORTH WEST ARROW WITH HOOK + case "nwarhk": // NORTH WEST ARROW WITH HOOK return rune(0x2923), true - case "nwarrow": - // NORTH WEST ARROW + case "nwarr": // NORTH WEST ARROW return rune(0x2196), true - case "nwarr": - // NORTH WEST ARROW + case "nwarrow": // NORTH WEST ARROW return rune(0x2196), true - case "nwnear": - // NORTH WEST ARROW AND NORTH EAST ARROW + case "nwnear": // NORTH WEST ARROW AND NORTH EAST ARROW return rune(0x2927), true - case "nwonearr": - // NORTH WEST ARROW CROSSING NORTH EAST ARROW + case "nwonearr": // NORTH WEST ARROW CROSSING NORTH EAST ARROW return rune(0x2932), true - case "nwsesarr": - // NORTH WEST AND SOUTH EAST ARROW + case "nwsesarr": // NORTH WEST AND SOUTH EAST ARROW return rune(0x2921), true } case 'o': switch name { - case "oS": - // CIRCLED LATIN CAPITAL LETTER S + case "oS": // CIRCLED LATIN CAPITAL LETTER S return rune(0x24c8), true - case "oacgr": - // GREEK SMALL LETTER OMICRON WITH TONOS + case "oacgr": // GREEK SMALL LETTER OMICRON WITH TONOS return rune(0x03cc), true - case "oacute": - // LATIN SMALL LETTER O WITH ACUTE + case "oacute": // LATIN SMALL LETTER O WITH ACUTE return rune(0xf3), true - case "oast": - // CIRCLED ASTERISK OPERATOR + case "oast": // CIRCLED ASTERISK OPERATOR return rune(0x229b), true - case "obsol": - // CIRCLED REVERSE SOLIDUS + case "obsol": // CIRCLED REVERSE SOLIDUS return rune(0x29b8), true - case "ocir": - // CIRCLED RING OPERATOR + case "ocir": // CIRCLED RING OPERATOR return rune(0x229a), true - case "ocirc": - // LATIN SMALL LETTER O WITH CIRCUMFLEX + case "ocirc": // LATIN SMALL LETTER O WITH CIRCUMFLEX return rune(0xf4), true - case "ocy": - // CYRILLIC SMALL LETTER O + case "ocy": // CYRILLIC SMALL LETTER O return rune(0x043e), true - case "odash": - // CIRCLED DASH + case "odash": // CIRCLED DASH return rune(0x229d), true - case "odblac": - // LATIN SMALL LETTER O WITH DOUBLE ACUTE + case "odblac": // LATIN SMALL LETTER O WITH DOUBLE ACUTE return rune(0x0151), true - case "odiv": - // CIRCLED DIVISION SIGN + case "odiv": // CIRCLED DIVISION SIGN return rune(0x2a38), true - case "odot": - // CIRCLED DOT OPERATOR + case "odot": // CIRCLED DOT OPERATOR return rune(0x2299), true - case "odsold": - // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN + case "odsold": // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN return rune(0x29bc), true - case "oelig": - // LATIN SMALL LIGATURE OE + case "oelig": // LATIN SMALL LIGATURE OE return rune(0x0153), true - case "ofcir": - // CIRCLED BULLET + case "ofcir": // CIRCLED BULLET return rune(0x29bf), true - case "ofr": - // MATHEMATICAL FRAKTUR SMALL O + case "ofr": // MATHEMATICAL FRAKTUR SMALL O return rune(0x01d52c), true - case "ogon": - // OGONEK + case "ogon": // OGONEK return rune(0x02db), true - case "ogr": - // GREEK SMALL LETTER OMICRON + case "ogr": // GREEK SMALL LETTER OMICRON return rune(0x03bf), true - case "ograve": - // LATIN SMALL LETTER O WITH GRAVE + case "ograve": // LATIN SMALL LETTER O WITH GRAVE return rune(0xf2), true - case "ogt": - // CIRCLED GREATER-THAN + case "ogt": // CIRCLED GREATER-THAN return rune(0x29c1), true - case "ohacgr": - // GREEK SMALL LETTER OMEGA WITH TONOS + case "ohacgr": // GREEK SMALL LETTER OMEGA WITH TONOS return rune(0x03ce), true - case "ohbar": - // CIRCLE WITH HORIZONTAL BAR + case "ohbar": // CIRCLE WITH HORIZONTAL BAR return rune(0x29b5), true - case "ohgr": - // GREEK SMALL LETTER OMEGA + case "ohgr": // GREEK SMALL LETTER OMEGA return rune(0x03c9), true - case "ohm": - // GREEK CAPITAL LETTER OMEGA + case "ohm": // GREEK CAPITAL LETTER OMEGA return rune(0x03a9), true - case "oint": - // CONTOUR INTEGRAL + case "oint": // CONTOUR INTEGRAL return rune(0x222e), true - case "olarr": - // ANTICLOCKWISE OPEN CIRCLE ARROW + case "olarr": // ANTICLOCKWISE OPEN CIRCLE ARROW return rune(0x21ba), true - case "olcir": - // CIRCLED WHITE BULLET + case "olcir": // CIRCLED WHITE BULLET return rune(0x29be), true - case "olcross": - // CIRCLE WITH SUPERIMPOSED X + case "olcross": // CIRCLE WITH SUPERIMPOSED X return rune(0x29bb), true - case "oline": - // OVERLINE + case "oline": // OVERLINE return rune(0x203e), true - case "olt": - // CIRCLED LESS-THAN + case "olt": // CIRCLED LESS-THAN return rune(0x29c0), true - case "omacr": - // LATIN SMALL LETTER O WITH MACRON + case "omacr": // LATIN SMALL LETTER O WITH MACRON return rune(0x014d), true - case "omega": - // GREEK SMALL LETTER OMEGA + case "omega": // GREEK SMALL LETTER OMEGA return rune(0x03c9), true - case "omicron": - // GREEK SMALL LETTER OMICRON + case "omicron": // GREEK SMALL LETTER OMICRON return rune(0x03bf), true - case "omid": - // CIRCLED VERTICAL BAR + case "omid": // CIRCLED VERTICAL BAR return rune(0x29b6), true - case "ominus": - // CIRCLED MINUS + case "ominus": // CIRCLED MINUS return rune(0x2296), true - case "oopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL O + case "oopf": // MATHEMATICAL DOUBLE-STRUCK SMALL O return rune(0x01d560), true - case "opar": - // CIRCLED PARALLEL + case "opar": // CIRCLED PARALLEL return rune(0x29b7), true - case "operp": - // CIRCLED PERPENDICULAR + case "operp": // CIRCLED PERPENDICULAR return rune(0x29b9), true - case "opfgamma": - // DOUBLE-STRUCK SMALL GAMMA + case "opfgamma": // DOUBLE-STRUCK SMALL GAMMA return rune(0x213d), true - case "opfpi": - // DOUBLE-STRUCK CAPITAL PI + case "opfpi": // DOUBLE-STRUCK CAPITAL PI return rune(0x213f), true - case "opfsum": - // DOUBLE-STRUCK N-ARY SUMMATION + case "opfsum": // DOUBLE-STRUCK N-ARY SUMMATION return rune(0x2140), true - case "oplus": - // CIRCLED PLUS + case "oplus": // CIRCLED PLUS return rune(0x2295), true - case "orarr": - // CLOCKWISE OPEN CIRCLE ARROW - return rune(0x21bb), true - case "or": - // LOGICAL OR + case "or": // LOGICAL OR return rune(0x2228), true - case "orderof": - // SCRIPT SMALL O - return rune(0x2134), true - case "order": - // SCRIPT SMALL O - return rune(0x2134), true - case "ord": - // LOGICAL OR WITH HORIZONTAL DASH + case "orarr": // CLOCKWISE OPEN CIRCLE ARROW + return rune(0x21bb), true + case "ord": // LOGICAL OR WITH HORIZONTAL DASH return rune(0x2a5d), true - case "ordf": - // FEMININE ORDINAL INDICATOR - return rune(0xaa), true - case "ordm": - // MASCULINE ORDINAL INDICATOR - return rune(0xba), true - case "origof": - // ORIGINAL OF - return rune(0x22b6), true - case "oror": - // TWO INTERSECTING LOGICAL OR - return rune(0x2a56), true - case "orslope": - // SLOPING LARGE OR - return rune(0x2a57), true - case "orv": - // LOGICAL OR WITH MIDDLE STEM - return rune(0x2a5b), true - case "oscr": - // SCRIPT SMALL O + case "order": // SCRIPT SMALL O return rune(0x2134), true - case "oslash": - // LATIN SMALL LETTER O WITH STROKE + case "orderof": // SCRIPT SMALL O + return rune(0x2134), true + case "ordf": // FEMININE ORDINAL INDICATOR + return rune(0xaa), true + case "ordm": // MASCULINE ORDINAL INDICATOR + return rune(0xba), true + case "origof": // ORIGINAL OF + return rune(0x22b6), true + case "oror": // TWO INTERSECTING LOGICAL OR + return rune(0x2a56), true + case "orslope": // SLOPING LARGE OR + return rune(0x2a57), true + case "orv": // LOGICAL OR WITH MIDDLE STEM + return rune(0x2a5b), true + case "oscr": // SCRIPT SMALL O + return rune(0x2134), true + case "oslash": // LATIN SMALL LETTER O WITH STROKE return rune(0xf8), true - case "osol": - // CIRCLED DIVISION SLASH + case "osol": // CIRCLED DIVISION SLASH return rune(0x2298), true - case "otilde": - // LATIN SMALL LETTER O WITH TILDE + case "otilde": // LATIN SMALL LETTER O WITH TILDE return rune(0xf5), true - case "otimes": - // CIRCLED TIMES + case "otimes": // CIRCLED TIMES return rune(0x2297), true - case "otimesas": - // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT + case "otimesas": // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT return rune(0x2a36), true - case "ouml": - // LATIN SMALL LETTER O WITH DIAERESIS + case "ouml": // LATIN SMALL LETTER O WITH DIAERESIS return rune(0xf6), true - case "ovbar": - // APL FUNCTIONAL SYMBOL CIRCLE STILE + case "ovbar": // APL FUNCTIONAL SYMBOL CIRCLE STILE return rune(0x233d), true - case "ovrbrk": - // TOP SQUARE BRACKET + case "ovrbrk": // TOP SQUARE BRACKET return rune(0x23b4), true - case "ovrcub": - // TOP CURLY BRACKET + case "ovrcub": // TOP CURLY BRACKET return rune(0x23de), true - case "ovrpar": - // TOP PARENTHESIS + case "ovrpar": // TOP PARENTHESIS return rune(0x23dc), true - case "oxuarr": - // UP ARROW THROUGH CIRCLE + case "oxuarr": // UP ARROW THROUGH CIRCLE return rune(0x29bd), true } case 'p': switch name { - case "part": - // PARTIAL DIFFERENTIAL - return rune(0x2202), true - case "par": - // PARALLEL TO + case "par": // PARALLEL TO return rune(0x2225), true - case "parallel": - // PARALLEL TO - return rune(0x2225), true - case "para": - // PILCROW SIGN + case "para": // PILCROW SIGN return rune(0xb6), true - case "parsim": - // PARALLEL WITH TILDE OPERATOR + case "parallel": // PARALLEL TO + return rune(0x2225), true + case "parsim": // PARALLEL WITH TILDE OPERATOR return rune(0x2af3), true - case "parsl": - // DOUBLE SOLIDUS OPERATOR + case "parsl": // DOUBLE SOLIDUS OPERATOR return rune(0x2afd), true - case "pcy": - // CYRILLIC SMALL LETTER PE + case "part": // PARTIAL DIFFERENTIAL + return rune(0x2202), true + case "pcy": // CYRILLIC SMALL LETTER PE return rune(0x043f), true - case "percnt": - // PERCENT SIGN + case "percnt": // PERCENT SIGN return rune(0x25), true - case "period": - // FULL STOP + case "period": // FULL STOP return rune(0x2e), true - case "permil": - // PER MILLE SIGN + case "permil": // PER MILLE SIGN return rune(0x2030), true - case "perp": - // UP TACK + case "perp": // UP TACK return rune(0x22a5), true - case "pertenk": - // PER TEN THOUSAND SIGN + case "pertenk": // PER TEN THOUSAND SIGN return rune(0x2031), true - case "pfr": - // MATHEMATICAL FRAKTUR SMALL P + case "pfr": // MATHEMATICAL FRAKTUR SMALL P return rune(0x01d52d), true - case "pgr": - // GREEK SMALL LETTER PI + case "pgr": // GREEK SMALL LETTER PI return rune(0x03c0), true - case "phgr": - // GREEK SMALL LETTER PHI + case "phgr": // GREEK SMALL LETTER PHI return rune(0x03c6), true - case "phis": - // GREEK PHI SYMBOL - return rune(0x03d5), true - case "phiv": - // GREEK PHI SYMBOL - return rune(0x03d5), true - case "phi": - // GREEK SMALL LETTER PHI + case "phi": // GREEK SMALL LETTER PHI return rune(0x03c6), true - case "phmmat": - // SCRIPT CAPITAL M + case "phis": // GREEK PHI SYMBOL + return rune(0x03d5), true + case "phiv": // GREEK PHI SYMBOL + return rune(0x03d5), true + case "phmmat": // SCRIPT CAPITAL M return rune(0x2133), true - case "phone": - // BLACK TELEPHONE + case "phone": // BLACK TELEPHONE return rune(0x260e), true - case "pitchfork": - // PITCHFORK - return rune(0x22d4), true - case "piv": - // GREEK PI SYMBOL - return rune(0x03d6), true - case "pi": - // GREEK SMALL LETTER PI + case "pi": // GREEK SMALL LETTER PI return rune(0x03c0), true - case "planck": - // PLANCK CONSTANT OVER TWO PI + case "pitchfork": // PITCHFORK + return rune(0x22d4), true + case "piv": // GREEK PI SYMBOL + return rune(0x03d6), true + case "planck": // PLANCK CONSTANT OVER TWO PI return rune(0x210f), true - case "planckh": - // PLANCK CONSTANT + case "planckh": // PLANCK CONSTANT return rune(0x210e), true - case "plankv": - // PLANCK CONSTANT OVER TWO PI + case "plankv": // PLANCK CONSTANT OVER TWO PI return rune(0x210f), true - case "plusacir": - // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE - return rune(0x2a23), true - case "plusb": - // SQUARED PLUS - return rune(0x229e), true - case "pluscir": - // PLUS SIGN WITH SMALL CIRCLE ABOVE - return rune(0x2a22), true - case "plusdo": - // DOT PLUS - return rune(0x2214), true - case "plusdu": - // PLUS SIGN WITH DOT BELOW - return rune(0x2a25), true - case "pluse": - // PLUS SIGN ABOVE EQUALS SIGN - return rune(0x2a72), true - case "plusmn": - // PLUS-MINUS SIGN - return rune(0xb1), true - case "plussim": - // PLUS SIGN WITH TILDE BELOW - return rune(0x2a26), true - case "plustrif": - // PLUS SIGN WITH BLACK TRIANGLE - return rune(0x2a28), true - case "plustwo": - // PLUS SIGN WITH SUBSCRIPT TWO - return rune(0x2a27), true - case "plus": - // PLUS SIGN + case "plus": // PLUS SIGN return rune(0x2b), true - case "pm": - // PLUS-MINUS SIGN + case "plusacir": // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE + return rune(0x2a23), true + case "plusb": // SQUARED PLUS + return rune(0x229e), true + case "pluscir": // PLUS SIGN WITH SMALL CIRCLE ABOVE + return rune(0x2a22), true + case "plusdo": // DOT PLUS + return rune(0x2214), true + case "plusdu": // PLUS SIGN WITH DOT BELOW + return rune(0x2a25), true + case "pluse": // PLUS SIGN ABOVE EQUALS SIGN + return rune(0x2a72), true + case "plusmn": // PLUS-MINUS SIGN return rune(0xb1), true - case "pointint": - // INTEGRAL AROUND A POINT OPERATOR + case "plussim": // PLUS SIGN WITH TILDE BELOW + return rune(0x2a26), true + case "plustrif": // PLUS SIGN WITH BLACK TRIANGLE + return rune(0x2a28), true + case "plustwo": // PLUS SIGN WITH SUBSCRIPT TWO + return rune(0x2a27), true + case "pm": // PLUS-MINUS SIGN + return rune(0xb1), true + case "pointint": // INTEGRAL AROUND A POINT OPERATOR return rune(0x2a15), true - case "popf": - // MATHEMATICAL DOUBLE-STRUCK SMALL P + case "popf": // MATHEMATICAL DOUBLE-STRUCK SMALL P return rune(0x01d561), true - case "pound": - // POUND SIGN + case "pound": // POUND SIGN return rune(0xa3), true - case "prod": - // N-ARY PRODUCT - return rune(0x220f), true - case "prop": - // PROPORTIONAL TO - return rune(0x221d), true - case "propto": - // PROPORTIONAL TO - return rune(0x221d), true - case "pr": - // PRECEDES + case "pr": // PRECEDES return rune(0x227a), true - case "prE": - // PRECEDES ABOVE EQUALS SIGN + case "prE": // PRECEDES ABOVE EQUALS SIGN return rune(0x2ab3), true - case "prap": - // PRECEDES ABOVE ALMOST EQUAL TO + case "prap": // PRECEDES ABOVE ALMOST EQUAL TO return rune(0x2ab7), true - case "prcue": - // PRECEDES OR EQUAL TO + case "prcue": // PRECEDES OR EQUAL TO return rune(0x227c), true - case "prec": - // PRECEDES + case "pre": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + return rune(0x2aaf), true + case "prec": // PRECEDES return rune(0x227a), true - case "preccurlyeq": - // PRECEDES OR EQUAL TO - return rune(0x227c), true - case "precnsim": - // PRECEDES BUT NOT EQUIVALENT TO - return rune(0x22e8), true - case "precsim": - // PRECEDES OR EQUIVALENT TO - return rune(0x227e), true - case "pre": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2aaf), true - case "precapprox": - // PRECEDES ABOVE ALMOST EQUAL TO + case "precapprox": // PRECEDES ABOVE ALMOST EQUAL TO return rune(0x2ab7), true - case "preceq": - // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + case "preccurlyeq": // PRECEDES OR EQUAL TO + return rune(0x227c), true + case "preceq": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN return rune(0x2aaf), true - case "precnapprox": - // PRECEDES ABOVE NOT ALMOST EQUAL TO + case "precnapprox": // PRECEDES ABOVE NOT ALMOST EQUAL TO return rune(0x2ab9), true - case "precneqq": - // PRECEDES ABOVE NOT EQUAL TO + case "precneqq": // PRECEDES ABOVE NOT EQUAL TO return rune(0x2ab5), true - case "primes": - // DOUBLE-STRUCK CAPITAL P - return rune(0x2119), true - case "prime": - // PRIME - return rune(0x2032), true - case "prnE": - // PRECEDES ABOVE NOT EQUAL TO - return rune(0x2ab5), true - case "prnap": - // PRECEDES ABOVE NOT ALMOST EQUAL TO - return rune(0x2ab9), true - case "prnsim": - // PRECEDES BUT NOT EQUIVALENT TO + case "precnsim": // PRECEDES BUT NOT EQUIVALENT TO return rune(0x22e8), true - case "profalar": - // ALL AROUND-PROFILE - return rune(0x232e), true - case "profline": - // ARC - return rune(0x2312), true - case "profsurf": - // SEGMENT - return rune(0x2313), true - case "prsim": - // PRECEDES OR EQUIVALENT TO + case "precsim": // PRECEDES OR EQUIVALENT TO return rune(0x227e), true - case "prurel": - // PRECEDES UNDER RELATION + case "prime": // PRIME + return rune(0x2032), true + case "primes": // DOUBLE-STRUCK CAPITAL P + return rune(0x2119), true + case "prnE": // PRECEDES ABOVE NOT EQUAL TO + return rune(0x2ab5), true + case "prnap": // PRECEDES ABOVE NOT ALMOST EQUAL TO + return rune(0x2ab9), true + case "prnsim": // PRECEDES BUT NOT EQUIVALENT TO + return rune(0x22e8), true + case "prod": // N-ARY PRODUCT + return rune(0x220f), true + case "profalar": // ALL AROUND-PROFILE + return rune(0x232e), true + case "profline": // ARC + return rune(0x2312), true + case "profsurf": // SEGMENT + return rune(0x2313), true + case "prop": // PROPORTIONAL TO + return rune(0x221d), true + case "propto": // PROPORTIONAL TO + return rune(0x221d), true + case "prsim": // PRECEDES OR EQUIVALENT TO + return rune(0x227e), true + case "prurel": // PRECEDES UNDER RELATION return rune(0x22b0), true - case "pscr": - // MATHEMATICAL SCRIPT SMALL P + case "pscr": // MATHEMATICAL SCRIPT SMALL P return rune(0x01d4c5), true - case "psgr": - // GREEK SMALL LETTER PSI + case "psgr": // GREEK SMALL LETTER PSI return rune(0x03c8), true - case "psi": - // GREEK SMALL LETTER PSI + case "psi": // GREEK SMALL LETTER PSI return rune(0x03c8), true - case "puncsp": - // PUNCTUATION SPACE + case "puncsp": // PUNCTUATION SPACE return rune(0x2008), true } case 'q': switch name { - case "qfr": - // MATHEMATICAL FRAKTUR SMALL Q + case "qfr": // MATHEMATICAL FRAKTUR SMALL Q return rune(0x01d52e), true - case "qint": - // QUADRUPLE INTEGRAL OPERATOR + case "qint": // QUADRUPLE INTEGRAL OPERATOR return rune(0x2a0c), true - case "qopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL Q + case "qopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Q return rune(0x01d562), true - case "qprime": - // QUADRUPLE PRIME + case "qprime": // QUADRUPLE PRIME return rune(0x2057), true - case "qscr": - // MATHEMATICAL SCRIPT SMALL Q + case "qscr": // MATHEMATICAL SCRIPT SMALL Q return rune(0x01d4c6), true - case "quaternions": - // DOUBLE-STRUCK CAPITAL H + case "quaternions": // DOUBLE-STRUCK CAPITAL H return rune(0x210d), true - case "quatint": - // QUATERNION INTEGRAL OPERATOR + case "quatint": // QUATERNION INTEGRAL OPERATOR return rune(0x2a16), true - case "questeq": - // QUESTIONED EQUAL TO - return rune(0x225f), true - case "quest": - // QUESTION MARK + case "quest": // QUESTION MARK return rune(0x3f), true - case "quot": - // QUOTATION MARK + case "questeq": // QUESTIONED EQUAL TO + return rune(0x225f), true + case "quot": // QUOTATION MARK return rune(0x22), true } case 'r': switch name { - case "rAarr": - // RIGHTWARDS TRIPLE ARROW + case "rAarr": // RIGHTWARDS TRIPLE ARROW return rune(0x21db), true - case "rArr": - // RIGHTWARDS DOUBLE ARROW + case "rArr": // RIGHTWARDS DOUBLE ARROW return rune(0x21d2), true - case "rAtail": - // RIGHTWARDS DOUBLE ARROW-TAIL + case "rAtail": // RIGHTWARDS DOUBLE ARROW-TAIL return rune(0x291c), true - case "rBarr": - // RIGHTWARDS TRIPLE DASH ARROW + case "rBarr": // RIGHTWARDS TRIPLE DASH ARROW return rune(0x290f), true - case "rHar": - // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN + case "rHar": // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN return rune(0x2964), true - case "race": - // REVERSED TILDE with underline + case "race": // REVERSED TILDE with underline return rune(0x223d), true - case "racute": - // LATIN SMALL LETTER R WITH ACUTE + case "racute": // LATIN SMALL LETTER R WITH ACUTE return rune(0x0155), true - case "radic": - // SQUARE ROOT + case "radic": // SQUARE ROOT return rune(0x221a), true - case "raemptyv": - // EMPTY SET WITH RIGHT ARROW ABOVE + case "raemptyv": // EMPTY SET WITH RIGHT ARROW ABOVE return rune(0x29b3), true - case "rang": - // MATHEMATICAL RIGHT ANGLE BRACKET + case "rang": // MATHEMATICAL RIGHT ANGLE BRACKET return rune(0x27e9), true - case "rangd": - // RIGHT ANGLE BRACKET WITH DOT + case "rangd": // RIGHT ANGLE BRACKET WITH DOT return rune(0x2992), true - case "range": - // REVERSED ANGLE WITH UNDERBAR + case "range": // REVERSED ANGLE WITH UNDERBAR return rune(0x29a5), true - case "rangle": - // MATHEMATICAL RIGHT ANGLE BRACKET + case "rangle": // MATHEMATICAL RIGHT ANGLE BRACKET return rune(0x27e9), true - case "raquo": - // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + case "raquo": // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK return rune(0xbb), true - case "rarr2": - // RIGHTWARDS PAIRED ARROWS + case "rarr": // RIGHTWARDS ARROW + return rune(0x2192), true + case "rarr2": // RIGHTWARDS PAIRED ARROWS return rune(0x21c9), true - case "rarr3": - // THREE RIGHTWARDS ARROWS + case "rarr3": // THREE RIGHTWARDS ARROWS return rune(0x21f6), true - case "rarrb": - // RIGHTWARDS ARROW TO BAR - return rune(0x21e5), true - case "rarrhk": - // RIGHTWARDS ARROW WITH HOOK - return rune(0x21aa), true - case "rarrlp": - // RIGHTWARDS ARROW WITH LOOP - return rune(0x21ac), true - case "rarrtl": - // RIGHTWARDS ARROW WITH TAIL - return rune(0x21a3), true - case "rarrw": - // RIGHTWARDS WAVE ARROW - return rune(0x219d), true - case "rarr": - // RIGHTWARDS ARROW - return rune(0x2192), true - case "rarrap": - // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO + case "rarrap": // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO return rune(0x2975), true - case "rarrbfs": - // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND + case "rarrb": // RIGHTWARDS ARROW TO BAR + return rune(0x21e5), true + case "rarrbfs": // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND return rune(0x2920), true - case "rarrc": - // WAVE ARROW POINTING DIRECTLY RIGHT + case "rarrc": // WAVE ARROW POINTING DIRECTLY RIGHT return rune(0x2933), true - case "rarrfs": - // RIGHTWARDS ARROW TO BLACK DIAMOND + case "rarrfs": // RIGHTWARDS ARROW TO BLACK DIAMOND return rune(0x291e), true - case "rarrpl": - // RIGHTWARDS ARROW WITH PLUS BELOW + case "rarrhk": // RIGHTWARDS ARROW WITH HOOK + return rune(0x21aa), true + case "rarrlp": // RIGHTWARDS ARROW WITH LOOP + return rune(0x21ac), true + case "rarrpl": // RIGHTWARDS ARROW WITH PLUS BELOW return rune(0x2945), true - case "rarrsim": - // RIGHTWARDS ARROW ABOVE TILDE OPERATOR + case "rarrsim": // RIGHTWARDS ARROW ABOVE TILDE OPERATOR return rune(0x2974), true - case "rarrx": - // RIGHTWARDS ARROW THROUGH X - return rune(0x2947), true - case "ratail": - // RIGHTWARDS ARROW-TAIL - return rune(0x291a), true - case "ratio": - // RATIO - return rune(0x2236), true - case "rationals": - // DOUBLE-STRUCK CAPITAL Q - return rune(0x211a), true - case "rbarr": - // RIGHTWARDS DOUBLE DASH ARROW - return rune(0x290d), true - case "rbbrk": - // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT - return rune(0x2773), true - case "rbrace": - // RIGHT CURLY BRACKET - return rune(0x7d), true - case "rbrack": - // RIGHT SQUARE BRACKET - return rune(0x5d), true - case "rbrke": - // RIGHT SQUARE BRACKET WITH UNDERBAR - return rune(0x298c), true - case "rbrksld": - // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - return rune(0x298e), true - case "rbrkslu": - // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER - return rune(0x2990), true - case "rcaron": - // LATIN SMALL LETTER R WITH CARON - return rune(0x0159), true - case "rcedil": - // LATIN SMALL LETTER R WITH CEDILLA - return rune(0x0157), true - case "rceil": - // RIGHT CEILING - return rune(0x2309), true - case "rcub": - // RIGHT CURLY BRACKET - return rune(0x7d), true - case "rcy": - // CYRILLIC SMALL LETTER ER - return rune(0x0440), true - case "rdca": - // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS - return rune(0x2937), true - case "rdharb": - // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2957), true - case "rdiag": - // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT - return rune(0x2571), true - case "rdiofdi": - // RISING DIAGONAL CROSSING FALLING DIAGONAL - return rune(0x292b), true - case "rdldhar": - // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN - return rune(0x2969), true - case "rdosearr": - // RISING DIAGONAL CROSSING SOUTH EAST ARROW - return rune(0x2930), true - case "rdquor": - // RIGHT DOUBLE QUOTATION MARK - return rune(0x201d), true - case "rdquo": - // RIGHT DOUBLE QUOTATION MARK - return rune(0x201d), true - case "rdsh": - // DOWNWARDS ARROW WITH TIP RIGHTWARDS - return rune(0x21b3), true - case "realpart": - // BLACK-LETTER CAPITAL R - return rune(0x211c), true - case "reals": - // DOUBLE-STRUCK CAPITAL R - return rune(0x211d), true - case "real": - // BLACK-LETTER CAPITAL R - return rune(0x211c), true - case "realine": - // SCRIPT CAPITAL R - return rune(0x211b), true - case "rect": - // WHITE RECTANGLE - return rune(0x25ad), true - case "reg": - // REGISTERED SIGN - return rune(0xae), true - case "rfbowtie": - // BOWTIE WITH RIGHT HALF BLACK - return rune(0x29d2), true - case "rfisht": - // RIGHT FISH TAIL - return rune(0x297d), true - case "rfloor": - // RIGHT FLOOR - return rune(0x230b), true - case "rfr": - // MATHEMATICAL FRAKTUR SMALL R - return rune(0x01d52f), true - case "rftimes": - // TIMES WITH RIGHT HALF BLACK - return rune(0x29d5), true - case "rgr": - // GREEK SMALL LETTER RHO - return rune(0x03c1), true - case "rhard": - // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21c1), true - case "rharu": - // RIGHTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21c0), true - case "rharul": - // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - return rune(0x296c), true - case "rhov": - // GREEK RHO SYMBOL - return rune(0x03f1), true - case "rho": - // GREEK SMALL LETTER RHO - return rune(0x03c1), true - case "rightarrowtail": - // RIGHTWARDS ARROW WITH TAIL + case "rarrtl": // RIGHTWARDS ARROW WITH TAIL return rune(0x21a3), true - case "rightarrow": - // RIGHTWARDS ARROW - return rune(0x2192), true - case "rightharpoondown": - // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21c1), true - case "rightharpoonup": - // RIGHTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21c0), true - case "rightleftarrows": - // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true - case "rightleftharpoons": - // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true - case "rightrightarrows": - // RIGHTWARDS PAIRED ARROWS - return rune(0x21c9), true - case "rightsquigarrow": - // RIGHTWARDS WAVE ARROW + case "rarrw": // RIGHTWARDS WAVE ARROW return rune(0x219d), true - case "rightthreetimes": - // RIGHT SEMIDIRECT PRODUCT - return rune(0x22cc), true - case "rimply": - // RIGHT DOUBLE ARROW WITH ROUNDED HEAD - return rune(0x2970), true - case "ring": - // RING ABOVE - return rune(0x02da), true - case "risingdotseq": - // IMAGE OF OR APPROXIMATELY EQUAL TO - return rune(0x2253), true - case "rlarr2": - // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true - case "rlarr": - // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true - case "rlhar": - // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true - case "rlhar2": - // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true - case "rlm": - // RIGHT-TO-LEFT MARK - return rune(0x200f), true - case "rmoust": - // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - return rune(0x23b1), true - case "rmoustache": - // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - return rune(0x23b1), true - case "rnmid": - // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH - return rune(0x2aee), true - case "roang": - // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET - return rune(0x27ed), true - case "roarr": - // RIGHTWARDS OPEN-HEADED ARROW - return rune(0x21fe), true - case "robrk": - // MATHEMATICAL RIGHT WHITE SQUARE BRACKET - return rune(0x27e7), true - case "rocub": - // RIGHT WHITE CURLY BRACKET - return rune(0x2984), true - case "ropar": - // RIGHT WHITE PARENTHESIS - return rune(0x2986), true - case "ropf": - // MATHEMATICAL DOUBLE-STRUCK SMALL R - return rune(0x01d563), true - case "roplus": - // PLUS SIGN IN RIGHT HALF CIRCLE - return rune(0x2a2e), true - case "rotimes": - // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE - return rune(0x2a35), true - case "rpargt": - // RIGHT ARC GREATER-THAN BRACKET - return rune(0x2994), true - case "rpar": - // RIGHT PARENTHESIS - return rune(0x29), true - case "rppolint": - // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE - return rune(0x2a12), true - case "rrarr": - // RIGHTWARDS PAIRED ARROWS - return rune(0x21c9), true - case "rsaquo": - // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - return rune(0x203a), true - case "rscr": - // MATHEMATICAL SCRIPT SMALL R - return rune(0x01d4c7), true - case "rsh": - // UPWARDS ARROW WITH TIP RIGHTWARDS - return rune(0x21b1), true - case "rsolbar": - // REVERSE SOLIDUS WITH HORIZONTAL STROKE - return rune(0x29f7), true - case "rsqb": - // RIGHT SQUARE BRACKET + case "rarrx": // RIGHTWARDS ARROW THROUGH X + return rune(0x2947), true + case "ratail": // RIGHTWARDS ARROW-TAIL + return rune(0x291a), true + case "ratio": // RATIO + return rune(0x2236), true + case "rationals": // DOUBLE-STRUCK CAPITAL Q + return rune(0x211a), true + case "rbarr": // RIGHTWARDS DOUBLE DASH ARROW + return rune(0x290d), true + case "rbbrk": // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + return rune(0x2773), true + case "rbrace": // RIGHT CURLY BRACKET + return rune(0x7d), true + case "rbrack": // RIGHT SQUARE BRACKET return rune(0x5d), true - case "rsquor": - // RIGHT SINGLE QUOTATION MARK - return rune(0x2019), true - case "rsquo": - // RIGHT SINGLE QUOTATION MARK - return rune(0x2019), true - case "rthree": - // RIGHT SEMIDIRECT PRODUCT + case "rbrke": // RIGHT SQUARE BRACKET WITH UNDERBAR + return rune(0x298c), true + case "rbrksld": // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + return rune(0x298e), true + case "rbrkslu": // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER + return rune(0x2990), true + case "rcaron": // LATIN SMALL LETTER R WITH CARON + return rune(0x0159), true + case "rcedil": // LATIN SMALL LETTER R WITH CEDILLA + return rune(0x0157), true + case "rceil": // RIGHT CEILING + return rune(0x2309), true + case "rcub": // RIGHT CURLY BRACKET + return rune(0x7d), true + case "rcy": // CYRILLIC SMALL LETTER ER + return rune(0x0440), true + case "rdca": // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS + return rune(0x2937), true + case "rdharb": // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR + return rune(0x2957), true + case "rdiag": // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT + return rune(0x2571), true + case "rdiofdi": // RISING DIAGONAL CROSSING FALLING DIAGONAL + return rune(0x292b), true + case "rdldhar": // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN + return rune(0x2969), true + case "rdosearr": // RISING DIAGONAL CROSSING SOUTH EAST ARROW + return rune(0x2930), true + case "rdquo": // RIGHT DOUBLE QUOTATION MARK + return rune(0x201d), true + case "rdquor": // RIGHT DOUBLE QUOTATION MARK + return rune(0x201d), true + case "rdsh": // DOWNWARDS ARROW WITH TIP RIGHTWARDS + return rune(0x21b3), true + case "real": // BLACK-LETTER CAPITAL R + return rune(0x211c), true + case "realine": // SCRIPT CAPITAL R + return rune(0x211b), true + case "realpart": // BLACK-LETTER CAPITAL R + return rune(0x211c), true + case "reals": // DOUBLE-STRUCK CAPITAL R + return rune(0x211d), true + case "rect": // WHITE RECTANGLE + return rune(0x25ad), true + case "reg": // REGISTERED SIGN + return rune(0xae), true + case "rfbowtie": // BOWTIE WITH RIGHT HALF BLACK + return rune(0x29d2), true + case "rfisht": // RIGHT FISH TAIL + return rune(0x297d), true + case "rfloor": // RIGHT FLOOR + return rune(0x230b), true + case "rfr": // MATHEMATICAL FRAKTUR SMALL R + return rune(0x01d52f), true + case "rftimes": // TIMES WITH RIGHT HALF BLACK + return rune(0x29d5), true + case "rgr": // GREEK SMALL LETTER RHO + return rune(0x03c1), true + case "rhard": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + return rune(0x21c1), true + case "rharu": // RIGHTWARDS HARPOON WITH BARB UPWARDS + return rune(0x21c0), true + case "rharul": // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH + return rune(0x296c), true + case "rho": // GREEK SMALL LETTER RHO + return rune(0x03c1), true + case "rhov": // GREEK RHO SYMBOL + return rune(0x03f1), true + case "rightarrow": // RIGHTWARDS ARROW + return rune(0x2192), true + case "rightarrowtail": // RIGHTWARDS ARROW WITH TAIL + return rune(0x21a3), true + case "rightharpoondown": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + return rune(0x21c1), true + case "rightharpoonup": // RIGHTWARDS HARPOON WITH BARB UPWARDS + return rune(0x21c0), true + case "rightleftarrows": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + return rune(0x21c4), true + case "rightleftharpoons": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + return rune(0x21cc), true + case "rightrightarrows": // RIGHTWARDS PAIRED ARROWS + return rune(0x21c9), true + case "rightsquigarrow": // RIGHTWARDS WAVE ARROW + return rune(0x219d), true + case "rightthreetimes": // RIGHT SEMIDIRECT PRODUCT return rune(0x22cc), true - case "rtimes": - // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT + case "rimply": // RIGHT DOUBLE ARROW WITH ROUNDED HEAD + return rune(0x2970), true + case "ring": // RING ABOVE + return rune(0x02da), true + case "risingdotseq": // IMAGE OF OR APPROXIMATELY EQUAL TO + return rune(0x2253), true + case "rlarr": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + return rune(0x21c4), true + case "rlarr2": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + return rune(0x21c4), true + case "rlhar": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + return rune(0x21cc), true + case "rlhar2": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + return rune(0x21cc), true + case "rlm": // RIGHT-TO-LEFT MARK + return rune(0x200f), true + case "rmoust": // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION + return rune(0x23b1), true + case "rmoustache": // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION + return rune(0x23b1), true + case "rnmid": // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH + return rune(0x2aee), true + case "roang": // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET + return rune(0x27ed), true + case "roarr": // RIGHTWARDS OPEN-HEADED ARROW + return rune(0x21fe), true + case "robrk": // MATHEMATICAL RIGHT WHITE SQUARE BRACKET + return rune(0x27e7), true + case "rocub": // RIGHT WHITE CURLY BRACKET + return rune(0x2984), true + case "ropar": // RIGHT WHITE PARENTHESIS + return rune(0x2986), true + case "ropf": // MATHEMATICAL DOUBLE-STRUCK SMALL R + return rune(0x01d563), true + case "roplus": // PLUS SIGN IN RIGHT HALF CIRCLE + return rune(0x2a2e), true + case "rotimes": // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE + return rune(0x2a35), true + case "rpar": // RIGHT PARENTHESIS + return rune(0x29), true + case "rpargt": // RIGHT ARC GREATER-THAN BRACKET + return rune(0x2994), true + case "rppolint": // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE + return rune(0x2a12), true + case "rrarr": // RIGHTWARDS PAIRED ARROWS + return rune(0x21c9), true + case "rsaquo": // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + return rune(0x203a), true + case "rscr": // MATHEMATICAL SCRIPT SMALL R + return rune(0x01d4c7), true + case "rsh": // UPWARDS ARROW WITH TIP RIGHTWARDS + return rune(0x21b1), true + case "rsolbar": // REVERSE SOLIDUS WITH HORIZONTAL STROKE + return rune(0x29f7), true + case "rsqb": // RIGHT SQUARE BRACKET + return rune(0x5d), true + case "rsquo": // RIGHT SINGLE QUOTATION MARK + return rune(0x2019), true + case "rsquor": // RIGHT SINGLE QUOTATION MARK + return rune(0x2019), true + case "rthree": // RIGHT SEMIDIRECT PRODUCT + return rune(0x22cc), true + case "rtimes": // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT return rune(0x22ca), true - case "rtrie": - // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - return rune(0x22b5), true - case "rtrif": - // BLACK RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b8), true - case "rtri": - // WHITE RIGHT-POINTING SMALL TRIANGLE + case "rtri": // WHITE RIGHT-POINTING SMALL TRIANGLE return rune(0x25b9), true - case "rtriltri": - // RIGHT TRIANGLE ABOVE LEFT TRIANGLE + case "rtrie": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + return rune(0x22b5), true + case "rtrif": // BLACK RIGHT-POINTING SMALL TRIANGLE + return rune(0x25b8), true + case "rtriltri": // RIGHT TRIANGLE ABOVE LEFT TRIANGLE return rune(0x29ce), true - case "ruharb": - // RIGHTWARDS HARPOON WITH BARB UP TO BAR + case "ruharb": // RIGHTWARDS HARPOON WITH BARB UP TO BAR return rune(0x2953), true - case "ruluhar": - // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP + case "ruluhar": // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP return rune(0x2968), true - case "rx": - // PRESCRIPTION TAKE + case "rx": // PRESCRIPTION TAKE return rune(0x211e), true } case 's': switch name { - case "sacute": - // LATIN SMALL LETTER S WITH ACUTE + case "sacute": // LATIN SMALL LETTER S WITH ACUTE return rune(0x015b), true - case "samalg": - // N-ARY COPRODUCT + case "samalg": // N-ARY COPRODUCT return rune(0x2210), true - case "sampi": - // GREEK LETTER SAMPI + case "sampi": // GREEK LETTER SAMPI return rune(0x03e0), true - case "sbquo": - // SINGLE LOW-9 QUOTATION MARK + case "sbquo": // SINGLE LOW-9 QUOTATION MARK return rune(0x201a), true - case "sbsol": - // SMALL REVERSE SOLIDUS + case "sbsol": // SMALL REVERSE SOLIDUS return rune(0xfe68), true - case "sc": - // SUCCEEDS + case "sc": // SUCCEEDS return rune(0x227b), true - case "scE": - // SUCCEEDS ABOVE EQUALS SIGN + case "scE": // SUCCEEDS ABOVE EQUALS SIGN return rune(0x2ab4), true - case "scap": - // SUCCEEDS ABOVE ALMOST EQUAL TO + case "scap": // SUCCEEDS ABOVE ALMOST EQUAL TO return rune(0x2ab8), true - case "scaron": - // LATIN SMALL LETTER S WITH CARON + case "scaron": // LATIN SMALL LETTER S WITH CARON return rune(0x0161), true - case "sccue": - // SUCCEEDS OR EQUAL TO + case "sccue": // SUCCEEDS OR EQUAL TO return rune(0x227d), true - case "scedil": - // LATIN SMALL LETTER S WITH CEDILLA + case "sce": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + return rune(0x2ab0), true + case "scedil": // LATIN SMALL LETTER S WITH CEDILLA return rune(0x015f), true - case "sce": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2ab0), true - case "scirc": - // LATIN SMALL LETTER S WITH CIRCUMFLEX + case "scirc": // LATIN SMALL LETTER S WITH CIRCUMFLEX return rune(0x015d), true - case "scnE": - // SUCCEEDS ABOVE NOT EQUAL TO + case "scnE": // SUCCEEDS ABOVE NOT EQUAL TO return rune(0x2ab6), true - case "scnap": - // SUCCEEDS ABOVE NOT ALMOST EQUAL TO + case "scnap": // SUCCEEDS ABOVE NOT ALMOST EQUAL TO return rune(0x2aba), true - case "scnsim": - // SUCCEEDS BUT NOT EQUIVALENT TO + case "scnsim": // SUCCEEDS BUT NOT EQUIVALENT TO return rune(0x22e9), true - case "scpolint": - // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE + case "scpolint": // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE return rune(0x2a13), true - case "scsim": - // SUCCEEDS OR EQUIVALENT TO + case "scsim": // SUCCEEDS OR EQUIVALENT TO return rune(0x227f), true - case "scy": - // CYRILLIC SMALL LETTER ES + case "scy": // CYRILLIC SMALL LETTER ES return rune(0x0441), true - case "sdotb": - // SQUARED DOT OPERATOR - return rune(0x22a1), true - case "sdot": - // DOT OPERATOR + case "sdot": // DOT OPERATOR return rune(0x22c5), true - case "sdote": - // EQUALS SIGN WITH DOT BELOW + case "sdotb": // SQUARED DOT OPERATOR + return rune(0x22a1), true + case "sdote": // EQUALS SIGN WITH DOT BELOW return rune(0x2a66), true - case "seArr": - // SOUTH EAST DOUBLE ARROW + case "seArr": // SOUTH EAST DOUBLE ARROW return rune(0x21d8), true - case "searhk": - // SOUTH EAST ARROW WITH HOOK + case "searhk": // SOUTH EAST ARROW WITH HOOK return rune(0x2925), true - case "searrow": - // SOUTH EAST ARROW + case "searr": // SOUTH EAST ARROW return rune(0x2198), true - case "searr": - // SOUTH EAST ARROW + case "searrow": // SOUTH EAST ARROW return rune(0x2198), true - case "sect": - // SECTION SIGN + case "sect": // SECTION SIGN return rune(0xa7), true - case "semi": - // SEMICOLON + case "semi": // SEMICOLON return rune(0x3b), true - case "seonearr": - // SOUTH EAST ARROW CROSSING NORTH EAST ARROW + case "seonearr": // SOUTH EAST ARROW CROSSING NORTH EAST ARROW return rune(0x292d), true - case "seswar": - // SOUTH EAST ARROW AND SOUTH WEST ARROW + case "seswar": // SOUTH EAST ARROW AND SOUTH WEST ARROW return rune(0x2929), true - case "setminus": - // SET MINUS + case "setminus": // SET MINUS return rune(0x2216), true - case "setmn": - // SET MINUS + case "setmn": // SET MINUS return rune(0x2216), true - case "sext": - // SIX POINTED BLACK STAR + case "sext": // SIX POINTED BLACK STAR return rune(0x2736), true - case "sfgr": - // GREEK SMALL LETTER FINAL SIGMA + case "sfgr": // GREEK SMALL LETTER FINAL SIGMA return rune(0x03c2), true - case "sfrown": - // FROWN - return rune(0x2322), true - case "sfr": - // MATHEMATICAL FRAKTUR SMALL S + case "sfr": // MATHEMATICAL FRAKTUR SMALL S return rune(0x01d530), true - case "sgr": - // GREEK SMALL LETTER SIGMA + case "sfrown": // FROWN + return rune(0x2322), true + case "sgr": // GREEK SMALL LETTER SIGMA return rune(0x03c3), true - case "sharp": - // MUSIC SHARP SIGN + case "sharp": // MUSIC SHARP SIGN return rune(0x266f), true - case "shchcy": - // CYRILLIC SMALL LETTER SHCHA + case "shchcy": // CYRILLIC SMALL LETTER SHCHA return rune(0x0449), true - case "shcy": - // CYRILLIC SMALL LETTER SHA + case "shcy": // CYRILLIC SMALL LETTER SHA return rune(0x0448), true - case "shortmid": - // DIVIDES + case "shortmid": // DIVIDES return rune(0x2223), true - case "shortparallel": - // PARALLEL TO + case "shortparallel": // PARALLEL TO return rune(0x2225), true - case "shuffle": - // SHUFFLE PRODUCT + case "shuffle": // SHUFFLE PRODUCT return rune(0x29e2), true - case "shy": - // SOFT HYPHEN + case "shy": // SOFT HYPHEN return rune(0xad), true - case "sigma": - // GREEK SMALL LETTER SIGMA + case "sigma": // GREEK SMALL LETTER SIGMA return rune(0x03c3), true - case "sigmaf": - // GREEK SMALL LETTER FINAL SIGMA + case "sigmaf": // GREEK SMALL LETTER FINAL SIGMA return rune(0x03c2), true - case "sigmav": - // GREEK SMALL LETTER FINAL SIGMA + case "sigmav": // GREEK SMALL LETTER FINAL SIGMA return rune(0x03c2), true - case "sim": - // TILDE OPERATOR + case "sim": // TILDE OPERATOR return rune(0x223c), true - case "simdot": - // TILDE OPERATOR WITH DOT ABOVE + case "simdot": // TILDE OPERATOR WITH DOT ABOVE return rune(0x2a6a), true - case "sime": - // ASYMPTOTICALLY EQUAL TO + case "sime": // ASYMPTOTICALLY EQUAL TO return rune(0x2243), true - case "simeq": - // ASYMPTOTICALLY EQUAL TO + case "simeq": // ASYMPTOTICALLY EQUAL TO return rune(0x2243), true - case "simg": - // SIMILAR OR GREATER-THAN + case "simg": // SIMILAR OR GREATER-THAN return rune(0x2a9e), true - case "simgE": - // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN + case "simgE": // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN return rune(0x2aa0), true - case "siml": - // SIMILAR OR LESS-THAN + case "siml": // SIMILAR OR LESS-THAN return rune(0x2a9d), true - case "simlE": - // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN + case "simlE": // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN return rune(0x2a9f), true - case "simne": - // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO + case "simne": // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO return rune(0x2246), true - case "simplus": - // PLUS SIGN WITH TILDE ABOVE + case "simplus": // PLUS SIGN WITH TILDE ABOVE return rune(0x2a24), true - case "simrarr": - // TILDE OPERATOR ABOVE RIGHTWARDS ARROW + case "simrarr": // TILDE OPERATOR ABOVE RIGHTWARDS ARROW return rune(0x2972), true - case "slarr": - // LEFTWARDS ARROW + case "slarr": // LEFTWARDS ARROW return rune(0x2190), true - case "slint": - // INTEGRAL AVERAGE WITH SLASH + case "slint": // INTEGRAL AVERAGE WITH SLASH return rune(0x2a0f), true - case "smallsetminus": - // SET MINUS + case "smallsetminus": // SET MINUS return rune(0x2216), true - case "smashp": - // SMASH PRODUCT + case "smashp": // SMASH PRODUCT return rune(0x2a33), true - case "smeparsl": - // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE + case "smeparsl": // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE return rune(0x29e4), true - case "smid": - // DIVIDES + case "smid": // DIVIDES return rune(0x2223), true - case "smile": - // SMILE + case "smile": // SMILE return rune(0x2323), true - case "smt": - // SMALLER THAN + case "smt": // SMALLER THAN return rune(0x2aaa), true - case "smte": - // SMALLER THAN OR EQUAL TO + case "smte": // SMALLER THAN OR EQUAL TO return rune(0x2aac), true - case "smtes": - // SMALLER THAN OR slanted EQUAL + case "smtes": // SMALLER THAN OR slanted EQUAL return rune(0x2aac), true - case "softcy": - // CYRILLIC SMALL LETTER SOFT SIGN + case "softcy": // CYRILLIC SMALL LETTER SOFT SIGN return rune(0x044c), true - case "solbar": - // APL FUNCTIONAL SYMBOL SLASH BAR - return rune(0x233f), true - case "solb": - // SQUARED RISING DIAGONAL SLASH - return rune(0x29c4), true - case "sol": - // SOLIDUS + case "sol": // SOLIDUS return rune(0x2f), true - case "sopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL S + case "solb": // SQUARED RISING DIAGONAL SLASH + return rune(0x29c4), true + case "solbar": // APL FUNCTIONAL SYMBOL SLASH BAR + return rune(0x233f), true + case "sopf": // MATHEMATICAL DOUBLE-STRUCK SMALL S return rune(0x01d564), true - case "spades": - // BLACK SPADE SUIT + case "spades": // BLACK SPADE SUIT return rune(0x2660), true - case "spadesuit": - // BLACK SPADE SUIT + case "spadesuit": // BLACK SPADE SUIT return rune(0x2660), true - case "spar": - // PARALLEL TO + case "spar": // PARALLEL TO return rune(0x2225), true - case "sqcap": - // SQUARE CAP + case "sqcap": // SQUARE CAP return rune(0x2293), true - case "sqcaps": - // SQUARE CAP with serifs + case "sqcaps": // SQUARE CAP with serifs return rune(0x2293), true - case "sqcup": - // SQUARE CUP + case "sqcup": // SQUARE CUP return rune(0x2294), true - case "sqcups": - // SQUARE CUP with serifs + case "sqcups": // SQUARE CUP with serifs return rune(0x2294), true - case "sqsub": - // SQUARE IMAGE OF + case "sqsub": // SQUARE IMAGE OF return rune(0x228f), true - case "sqsube": - // SQUARE IMAGE OF OR EQUAL TO + case "sqsube": // SQUARE IMAGE OF OR EQUAL TO return rune(0x2291), true - case "sqsubset": - // SQUARE IMAGE OF + case "sqsubset": // SQUARE IMAGE OF return rune(0x228f), true - case "sqsubseteq": - // SQUARE IMAGE OF OR EQUAL TO + case "sqsubseteq": // SQUARE IMAGE OF OR EQUAL TO return rune(0x2291), true - case "sqsup": - // SQUARE ORIGINAL OF + case "sqsup": // SQUARE ORIGINAL OF return rune(0x2290), true - case "sqsupe": - // SQUARE ORIGINAL OF OR EQUAL TO + case "sqsupe": // SQUARE ORIGINAL OF OR EQUAL TO return rune(0x2292), true - case "sqsupset": - // SQUARE ORIGINAL OF + case "sqsupset": // SQUARE ORIGINAL OF return rune(0x2290), true - case "sqsupseteq": - // SQUARE ORIGINAL OF OR EQUAL TO + case "sqsupseteq": // SQUARE ORIGINAL OF OR EQUAL TO return rune(0x2292), true - case "squ": - // WHITE SQUARE + case "squ": // WHITE SQUARE return rune(0x25a1), true - case "square": - // WHITE SQUARE + case "square": // WHITE SQUARE return rune(0x25a1), true - case "squarf": - // BLACK SMALL SQUARE + case "squarf": // BLACK SMALL SQUARE return rune(0x25aa), true - case "squb": - // SQUARED SQUARE + case "squb": // SQUARED SQUARE return rune(0x29c8), true - case "squerr": - // ERROR-BARRED WHITE SQUARE + case "squerr": // ERROR-BARRED WHITE SQUARE return rune(0x29ee), true - case "squf": - // BLACK SMALL SQUARE + case "squf": // BLACK SMALL SQUARE return rune(0x25aa), true - case "squferr": - // ERROR-BARRED BLACK SQUARE + case "squferr": // ERROR-BARRED BLACK SQUARE return rune(0x29ef), true - case "srarr": - // RIGHTWARDS ARROW + case "srarr": // RIGHTWARDS ARROW return rune(0x2192), true - case "sscr": - // MATHEMATICAL SCRIPT SMALL S + case "sscr": // MATHEMATICAL SCRIPT SMALL S return rune(0x01d4c8), true - case "ssetmn": - // SET MINUS + case "ssetmn": // SET MINUS return rune(0x2216), true - case "ssmile": - // SMILE + case "ssmile": // SMILE return rune(0x2323), true - case "sstarf": - // STAR OPERATOR + case "sstarf": // STAR OPERATOR return rune(0x22c6), true - case "starf": - // BLACK STAR - return rune(0x2605), true - case "star": - // WHITE STAR + case "star": // WHITE STAR return rune(0x2606), true - case "stigma": - // GREEK LETTER STIGMA + case "starf": // BLACK STAR + return rune(0x2605), true + case "stigma": // GREEK LETTER STIGMA return rune(0x03da), true - case "straightepsilon": - // GREEK LUNATE EPSILON SYMBOL + case "straightepsilon": // GREEK LUNATE EPSILON SYMBOL return rune(0x03f5), true - case "straightphi": - // GREEK PHI SYMBOL + case "straightphi": // GREEK PHI SYMBOL return rune(0x03d5), true - case "strns": - // MACRON + case "strns": // MACRON return rune(0xaf), true - case "sub": - // SUBSET OF + case "sub": // SUBSET OF return rune(0x2282), true - case "subE": - // SUBSET OF ABOVE EQUALS SIGN + case "subE": // SUBSET OF ABOVE EQUALS SIGN return rune(0x2ac5), true - case "subdot": - // SUBSET WITH DOT + case "subdot": // SUBSET WITH DOT return rune(0x2abd), true - case "sube": - // SUBSET OF OR EQUAL TO + case "sube": // SUBSET OF OR EQUAL TO return rune(0x2286), true - case "subedot": - // SUBSET OF OR EQUAL TO WITH DOT ABOVE + case "subedot": // SUBSET OF OR EQUAL TO WITH DOT ABOVE return rune(0x2ac3), true - case "submult": - // SUBSET WITH MULTIPLICATION SIGN BELOW + case "submult": // SUBSET WITH MULTIPLICATION SIGN BELOW return rune(0x2ac1), true - case "subnE": - // SUBSET OF ABOVE NOT EQUAL TO + case "subnE": // SUBSET OF ABOVE NOT EQUAL TO return rune(0x2acb), true - case "subne": - // SUBSET OF WITH NOT EQUAL TO + case "subne": // SUBSET OF WITH NOT EQUAL TO return rune(0x228a), true - case "subplus": - // SUBSET WITH PLUS SIGN BELOW + case "subplus": // SUBSET WITH PLUS SIGN BELOW return rune(0x2abf), true - case "subrarr": - // SUBSET ABOVE RIGHTWARDS ARROW + case "subrarr": // SUBSET ABOVE RIGHTWARDS ARROW return rune(0x2979), true - case "subset": - // SUBSET OF + case "subset": // SUBSET OF return rune(0x2282), true - case "subseteq": - // SUBSET OF OR EQUAL TO + case "subseteq": // SUBSET OF OR EQUAL TO return rune(0x2286), true - case "subseteqq": - // SUBSET OF ABOVE EQUALS SIGN + case "subseteqq": // SUBSET OF ABOVE EQUALS SIGN return rune(0x2ac5), true - case "subsetneq": - // SUBSET OF WITH NOT EQUAL TO + case "subsetneq": // SUBSET OF WITH NOT EQUAL TO return rune(0x228a), true - case "subsetneqq": - // SUBSET OF ABOVE NOT EQUAL TO + case "subsetneqq": // SUBSET OF ABOVE NOT EQUAL TO return rune(0x2acb), true - case "subsim": - // SUBSET OF ABOVE TILDE OPERATOR + case "subsim": // SUBSET OF ABOVE TILDE OPERATOR return rune(0x2ac7), true - case "subsub": - // SUBSET ABOVE SUBSET + case "subsub": // SUBSET ABOVE SUBSET return rune(0x2ad5), true - case "subsup": - // SUBSET ABOVE SUPERSET + case "subsup": // SUBSET ABOVE SUPERSET return rune(0x2ad3), true - case "succ": - // SUCCEEDS + case "succ": // SUCCEEDS return rune(0x227b), true - case "succapprox": - // SUCCEEDS ABOVE ALMOST EQUAL TO + case "succapprox": // SUCCEEDS ABOVE ALMOST EQUAL TO return rune(0x2ab8), true - case "succcurlyeq": - // SUCCEEDS OR EQUAL TO + case "succcurlyeq": // SUCCEEDS OR EQUAL TO return rune(0x227d), true - case "succeq": - // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + case "succeq": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN return rune(0x2ab0), true - case "succnapprox": - // SUCCEEDS ABOVE NOT ALMOST EQUAL TO + case "succnapprox": // SUCCEEDS ABOVE NOT ALMOST EQUAL TO return rune(0x2aba), true - case "succneqq": - // SUCCEEDS ABOVE NOT EQUAL TO + case "succneqq": // SUCCEEDS ABOVE NOT EQUAL TO return rune(0x2ab6), true - case "succnsim": - // SUCCEEDS BUT NOT EQUIVALENT TO + case "succnsim": // SUCCEEDS BUT NOT EQUIVALENT TO return rune(0x22e9), true - case "succsim": - // SUCCEEDS OR EQUIVALENT TO + case "succsim": // SUCCEEDS OR EQUIVALENT TO return rune(0x227f), true - case "sum": - // N-ARY SUMMATION + case "sum": // N-ARY SUMMATION return rune(0x2211), true - case "sumint": - // SUMMATION WITH INTEGRAL + case "sumint": // SUMMATION WITH INTEGRAL return rune(0x2a0b), true - case "sung": - // EIGHTH NOTE + case "sung": // EIGHTH NOTE return rune(0x266a), true - case "sup": - // SUPERSET OF + case "sup": // SUPERSET OF return rune(0x2283), true - case "sup1": - // SUPERSCRIPT ONE + case "sup1": // SUPERSCRIPT ONE return rune(0xb9), true - case "sup2": - // SUPERSCRIPT TWO + case "sup2": // SUPERSCRIPT TWO return rune(0xb2), true - case "sup3": - // SUPERSCRIPT THREE + case "sup3": // SUPERSCRIPT THREE return rune(0xb3), true - case "supE": - // SUPERSET OF ABOVE EQUALS SIGN + case "supE": // SUPERSET OF ABOVE EQUALS SIGN return rune(0x2ac6), true - case "supdot": - // SUPERSET WITH DOT + case "supdot": // SUPERSET WITH DOT return rune(0x2abe), true - case "supdsub": - // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET + case "supdsub": // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET return rune(0x2ad8), true - case "supe": - // SUPERSET OF OR EQUAL TO + case "supe": // SUPERSET OF OR EQUAL TO return rune(0x2287), true - case "supedot": - // SUPERSET OF OR EQUAL TO WITH DOT ABOVE + case "supedot": // SUPERSET OF OR EQUAL TO WITH DOT ABOVE return rune(0x2ac4), true - case "suphsol": - // SUPERSET PRECEDING SOLIDUS + case "suphsol": // SUPERSET PRECEDING SOLIDUS return rune(0x27c9), true - case "suphsub": - // SUPERSET BESIDE SUBSET + case "suphsub": // SUPERSET BESIDE SUBSET return rune(0x2ad7), true - case "suplarr": - // SUPERSET ABOVE LEFTWARDS ARROW + case "suplarr": // SUPERSET ABOVE LEFTWARDS ARROW return rune(0x297b), true - case "supmult": - // SUPERSET WITH MULTIPLICATION SIGN BELOW + case "supmult": // SUPERSET WITH MULTIPLICATION SIGN BELOW return rune(0x2ac2), true - case "supnE": - // SUPERSET OF ABOVE NOT EQUAL TO + case "supnE": // SUPERSET OF ABOVE NOT EQUAL TO return rune(0x2acc), true - case "supne": - // SUPERSET OF WITH NOT EQUAL TO + case "supne": // SUPERSET OF WITH NOT EQUAL TO return rune(0x228b), true - case "supplus": - // SUPERSET WITH PLUS SIGN BELOW + case "supplus": // SUPERSET WITH PLUS SIGN BELOW return rune(0x2ac0), true - case "supset": - // SUPERSET OF + case "supset": // SUPERSET OF return rune(0x2283), true - case "supseteq": - // SUPERSET OF OR EQUAL TO + case "supseteq": // SUPERSET OF OR EQUAL TO return rune(0x2287), true - case "supseteqq": - // SUPERSET OF ABOVE EQUALS SIGN + case "supseteqq": // SUPERSET OF ABOVE EQUALS SIGN return rune(0x2ac6), true - case "supsetneq": - // SUPERSET OF WITH NOT EQUAL TO + case "supsetneq": // SUPERSET OF WITH NOT EQUAL TO return rune(0x228b), true - case "supsetneqq": - // SUPERSET OF ABOVE NOT EQUAL TO + case "supsetneqq": // SUPERSET OF ABOVE NOT EQUAL TO return rune(0x2acc), true - case "supsim": - // SUPERSET OF ABOVE TILDE OPERATOR + case "supsim": // SUPERSET OF ABOVE TILDE OPERATOR return rune(0x2ac8), true - case "supsub": - // SUPERSET ABOVE SUBSET + case "supsub": // SUPERSET ABOVE SUBSET return rune(0x2ad4), true - case "supsup": - // SUPERSET ABOVE SUPERSET + case "supsup": // SUPERSET ABOVE SUPERSET return rune(0x2ad6), true - case "swArr": - // SOUTH WEST DOUBLE ARROW + case "swArr": // SOUTH WEST DOUBLE ARROW return rune(0x21d9), true - case "swarhk": - // SOUTH WEST ARROW WITH HOOK + case "swarhk": // SOUTH WEST ARROW WITH HOOK return rune(0x2926), true - case "swarrow": - // SOUTH WEST ARROW + case "swarr": // SOUTH WEST ARROW return rune(0x2199), true - case "swarr": - // SOUTH WEST ARROW + case "swarrow": // SOUTH WEST ARROW return rune(0x2199), true - case "swnwar": - // SOUTH WEST ARROW AND NORTH WEST ARROW + case "swnwar": // SOUTH WEST ARROW AND NORTH WEST ARROW return rune(0x292a), true - case "szlig": - // LATIN SMALL LETTER SHARP S + case "szlig": // LATIN SMALL LETTER SHARP S return rune(0xdf), true } case 't': switch name { - case "target": - // POSITION INDICATOR + case "target": // POSITION INDICATOR return rune(0x2316), true - case "tau": - // GREEK SMALL LETTER TAU + case "tau": // GREEK SMALL LETTER TAU return rune(0x03c4), true - case "tbrk": - // TOP SQUARE BRACKET + case "tbrk": // TOP SQUARE BRACKET return rune(0x23b4), true - case "tcaron": - // LATIN SMALL LETTER T WITH CARON + case "tcaron": // LATIN SMALL LETTER T WITH CARON return rune(0x0165), true - case "tcedil": - // LATIN SMALL LETTER T WITH CEDILLA + case "tcedil": // LATIN SMALL LETTER T WITH CEDILLA return rune(0x0163), true - case "tcy": - // CYRILLIC SMALL LETTER TE + case "tcy": // CYRILLIC SMALL LETTER TE return rune(0x0442), true - case "tdot": - // COMBINING THREE DOTS ABOVE + case "tdot": // COMBINING THREE DOTS ABOVE return rune(0x20db), true - case "telrec": - // TELEPHONE RECORDER + case "telrec": // TELEPHONE RECORDER return rune(0x2315), true - case "tfr": - // MATHEMATICAL FRAKTUR SMALL T + case "tfr": // MATHEMATICAL FRAKTUR SMALL T return rune(0x01d531), true - case "tgr": - // GREEK SMALL LETTER TAU + case "tgr": // GREEK SMALL LETTER TAU return rune(0x03c4), true - case "there4": - // THEREFORE + case "there4": // THEREFORE return rune(0x2234), true - case "therefore": - // THEREFORE + case "therefore": // THEREFORE return rune(0x2234), true - case "thermod": - // THERMODYNAMIC + case "thermod": // THERMODYNAMIC return rune(0x29e7), true - case "thetasym": - // GREEK THETA SYMBOL + case "theta": // GREEK SMALL LETTER THETA + return rune(0x03b8), true + case "thetas": // GREEK SMALL LETTER THETA + return rune(0x03b8), true + case "thetasym": // GREEK THETA SYMBOL return rune(0x03d1), true - case "thetas": - // GREEK SMALL LETTER THETA - return rune(0x03b8), true - case "thetav": - // GREEK THETA SYMBOL + case "thetav": // GREEK THETA SYMBOL return rune(0x03d1), true - case "theta": - // GREEK SMALL LETTER THETA + case "thgr": // GREEK SMALL LETTER THETA return rune(0x03b8), true - case "thgr": - // GREEK SMALL LETTER THETA - return rune(0x03b8), true - case "thickapprox": - // ALMOST EQUAL TO + case "thickapprox": // ALMOST EQUAL TO return rune(0x2248), true - case "thicksim": - // TILDE OPERATOR + case "thicksim": // TILDE OPERATOR return rune(0x223c), true - case "thinsp": - // THIN SPACE + case "thinsp": // THIN SPACE return rune(0x2009), true - case "thkap": - // ALMOST EQUAL TO + case "thkap": // ALMOST EQUAL TO return rune(0x2248), true - case "thksim": - // TILDE OPERATOR + case "thksim": // TILDE OPERATOR return rune(0x223c), true - case "thorn": - // LATIN SMALL LETTER THORN + case "thorn": // LATIN SMALL LETTER THORN return rune(0xfe), true - case "tilde": - // SMALL TILDE + case "tilde": // SMALL TILDE return rune(0x02dc), true - case "timeint": - // INTEGRAL WITH TIMES SIGN + case "timeint": // INTEGRAL WITH TIMES SIGN return rune(0x2a18), true - case "timesb": - // SQUARED TIMES - return rune(0x22a0), true - case "timesbar": - // MULTIPLICATION SIGN WITH UNDERBAR - return rune(0x2a31), true - case "timesd": - // MULTIPLICATION SIGN WITH DOT ABOVE - return rune(0x2a30), true - case "times": - // MULTIPLICATION SIGN + case "times": // MULTIPLICATION SIGN return rune(0xd7), true - case "tint": - // TRIPLE INTEGRAL + case "timesb": // SQUARED TIMES + return rune(0x22a0), true + case "timesbar": // MULTIPLICATION SIGN WITH UNDERBAR + return rune(0x2a31), true + case "timesd": // MULTIPLICATION SIGN WITH DOT ABOVE + return rune(0x2a30), true + case "tint": // TRIPLE INTEGRAL return rune(0x222d), true - case "toea": - // NORTH EAST ARROW AND SOUTH EAST ARROW + case "toea": // NORTH EAST ARROW AND SOUTH EAST ARROW return rune(0x2928), true - case "top": - // DOWN TACK + case "top": // DOWN TACK return rune(0x22a4), true - case "topbot": - // APL FUNCTIONAL SYMBOL I-BEAM + case "topbot": // APL FUNCTIONAL SYMBOL I-BEAM return rune(0x2336), true - case "topcir": - // DOWN TACK WITH CIRCLE BELOW + case "topcir": // DOWN TACK WITH CIRCLE BELOW return rune(0x2af1), true - case "topfork": - // PITCHFORK WITH TEE TOP - return rune(0x2ada), true - case "topf": - // MATHEMATICAL DOUBLE-STRUCK SMALL T + case "topf": // MATHEMATICAL DOUBLE-STRUCK SMALL T return rune(0x01d565), true - case "tosa": - // SOUTH EAST ARROW AND SOUTH WEST ARROW + case "topfork": // PITCHFORK WITH TEE TOP + return rune(0x2ada), true + case "tosa": // SOUTH EAST ARROW AND SOUTH WEST ARROW return rune(0x2929), true - case "tprime": - // TRIPLE PRIME + case "tprime": // TRIPLE PRIME return rune(0x2034), true - case "trade": - // TRADE MARK SIGN + case "trade": // TRADE MARK SIGN return rune(0x2122), true - case "triS": - // S IN TRIANGLE + case "triS": // S IN TRIANGLE return rune(0x29cc), true - case "trianglelefteq": - // NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22b4), true - case "triangleq": - // DELTA EQUAL TO - return rune(0x225c), true - case "trianglerighteq": - // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - return rune(0x22b5), true - case "triangle": - // WHITE UP-POINTING SMALL TRIANGLE + case "triangle": // WHITE UP-POINTING SMALL TRIANGLE return rune(0x25b5), true - case "triangledown": - // WHITE DOWN-POINTING SMALL TRIANGLE + case "triangledown": // WHITE DOWN-POINTING SMALL TRIANGLE return rune(0x25bf), true - case "triangleleft": - // WHITE LEFT-POINTING SMALL TRIANGLE + case "triangleleft": // WHITE LEFT-POINTING SMALL TRIANGLE return rune(0x25c3), true - case "triangleright": - // WHITE RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b9), true - case "tribar": - // TRIANGLE WITH UNDERBAR - return rune(0x29cb), true - case "tridot": - // WHITE UP-POINTING TRIANGLE WITH DOT - return rune(0x25ec), true - case "tridoto": - // TRIANGLE WITH DOT ABOVE - return rune(0x29ca), true - case "trie": - // DELTA EQUAL TO + case "trianglelefteq": // NORMAL SUBGROUP OF OR EQUAL TO + return rune(0x22b4), true + case "triangleq": // DELTA EQUAL TO return rune(0x225c), true - case "triminus": - // MINUS SIGN IN TRIANGLE + case "triangleright": // WHITE RIGHT-POINTING SMALL TRIANGLE + return rune(0x25b9), true + case "trianglerighteq": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + return rune(0x22b5), true + case "tribar": // TRIANGLE WITH UNDERBAR + return rune(0x29cb), true + case "tridot": // WHITE UP-POINTING TRIANGLE WITH DOT + return rune(0x25ec), true + case "tridoto": // TRIANGLE WITH DOT ABOVE + return rune(0x29ca), true + case "trie": // DELTA EQUAL TO + return rune(0x225c), true + case "triminus": // MINUS SIGN IN TRIANGLE return rune(0x2a3a), true - case "triplus": - // PLUS SIGN IN TRIANGLE + case "triplus": // PLUS SIGN IN TRIANGLE return rune(0x2a39), true - case "trisb": - // TRIANGLE WITH SERIFS AT BOTTOM + case "trisb": // TRIANGLE WITH SERIFS AT BOTTOM return rune(0x29cd), true - case "tritime": - // MULTIPLICATION SIGN IN TRIANGLE + case "tritime": // MULTIPLICATION SIGN IN TRIANGLE return rune(0x2a3b), true - case "trpezium": - // WHITE TRAPEZIUM + case "trpezium": // WHITE TRAPEZIUM return rune(0x23e2), true - case "tscr": - // MATHEMATICAL SCRIPT SMALL T + case "tscr": // MATHEMATICAL SCRIPT SMALL T return rune(0x01d4c9), true - case "tscy": - // CYRILLIC SMALL LETTER TSE + case "tscy": // CYRILLIC SMALL LETTER TSE return rune(0x0446), true - case "tshcy": - // CYRILLIC SMALL LETTER TSHE + case "tshcy": // CYRILLIC SMALL LETTER TSHE return rune(0x045b), true - case "tstrok": - // LATIN SMALL LETTER T WITH STROKE + case "tstrok": // LATIN SMALL LETTER T WITH STROKE return rune(0x0167), true - case "tverbar": - // TRIPLE VERTICAL BAR DELIMITER + case "tverbar": // TRIPLE VERTICAL BAR DELIMITER return rune(0x2980), true - case "twixt": - // BETWEEN + case "twixt": // BETWEEN return rune(0x226c), true - case "twoheadleftarrow": - // LEFTWARDS TWO HEADED ARROW + case "twoheadleftarrow": // LEFTWARDS TWO HEADED ARROW return rune(0x219e), true - case "twoheadrightarrow": - // RIGHTWARDS TWO HEADED ARROW + case "twoheadrightarrow": // RIGHTWARDS TWO HEADED ARROW return rune(0x21a0), true } case 'u': switch name { - case "uAarr": - // UPWARDS TRIPLE ARROW + case "uAarr": // UPWARDS TRIPLE ARROW return rune(0x290a), true - case "uArr": - // UPWARDS DOUBLE ARROW + case "uArr": // UPWARDS DOUBLE ARROW return rune(0x21d1), true - case "uHar": - // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + case "uHar": // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT return rune(0x2963), true - case "uacgr": - // GREEK SMALL LETTER UPSILON WITH TONOS + case "uacgr": // GREEK SMALL LETTER UPSILON WITH TONOS return rune(0x03cd), true - case "uacute": - // LATIN SMALL LETTER U WITH ACUTE + case "uacute": // LATIN SMALL LETTER U WITH ACUTE return rune(0xfa), true - case "uarr2": - // UPWARDS PAIRED ARROWS - return rune(0x21c8), true - case "uarr": - // UPWARDS ARROW + case "uarr": // UPWARDS ARROW return rune(0x2191), true - case "uarrb": - // UPWARDS ARROW TO BAR + case "uarr2": // UPWARDS PAIRED ARROWS + return rune(0x21c8), true + case "uarrb": // UPWARDS ARROW TO BAR return rune(0x2912), true - case "uarrln": - // UPWARDS ARROW WITH HORIZONTAL STROKE + case "uarrln": // UPWARDS ARROW WITH HORIZONTAL STROKE return rune(0x2909), true - case "ubrcy": - // CYRILLIC SMALL LETTER SHORT U + case "ubrcy": // CYRILLIC SMALL LETTER SHORT U return rune(0x045e), true - case "ubreve": - // LATIN SMALL LETTER U WITH BREVE + case "ubreve": // LATIN SMALL LETTER U WITH BREVE return rune(0x016d), true - case "ucirc": - // LATIN SMALL LETTER U WITH CIRCUMFLEX + case "ucirc": // LATIN SMALL LETTER U WITH CIRCUMFLEX return rune(0xfb), true - case "ucy": - // CYRILLIC SMALL LETTER U + case "ucy": // CYRILLIC SMALL LETTER U return rune(0x0443), true - case "udarr": - // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW + case "udarr": // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW return rune(0x21c5), true - case "udblac": - // LATIN SMALL LETTER U WITH DOUBLE ACUTE + case "udblac": // LATIN SMALL LETTER U WITH DOUBLE ACUTE return rune(0x0171), true - case "udhar": - // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + case "udhar": // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT return rune(0x296e), true - case "udiagr": - // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + case "udiagr": // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS return rune(0x03b0), true - case "udigr": - // GREEK SMALL LETTER UPSILON WITH DIALYTIKA + case "udigr": // GREEK SMALL LETTER UPSILON WITH DIALYTIKA return rune(0x03cb), true - case "udrbrk": - // BOTTOM SQUARE BRACKET + case "udrbrk": // BOTTOM SQUARE BRACKET return rune(0x23b5), true - case "udrcub": - // BOTTOM CURLY BRACKET + case "udrcub": // BOTTOM CURLY BRACKET return rune(0x23df), true - case "udrpar": - // BOTTOM PARENTHESIS + case "udrpar": // BOTTOM PARENTHESIS return rune(0x23dd), true - case "ufisht": - // UP FISH TAIL + case "ufisht": // UP FISH TAIL return rune(0x297e), true - case "ufr": - // MATHEMATICAL FRAKTUR SMALL U + case "ufr": // MATHEMATICAL FRAKTUR SMALL U return rune(0x01d532), true - case "ugr": - // GREEK SMALL LETTER UPSILON + case "ugr": // GREEK SMALL LETTER UPSILON return rune(0x03c5), true - case "ugrave": - // LATIN SMALL LETTER U WITH GRAVE + case "ugrave": // LATIN SMALL LETTER U WITH GRAVE return rune(0xf9), true - case "uharl": - // UPWARDS HARPOON WITH BARB LEFTWARDS + case "uharl": // UPWARDS HARPOON WITH BARB LEFTWARDS return rune(0x21bf), true - case "uharr": - // UPWARDS HARPOON WITH BARB RIGHTWARDS + case "uharr": // UPWARDS HARPOON WITH BARB RIGHTWARDS return rune(0x21be), true - case "uhblk": - // UPPER HALF BLOCK + case "uhblk": // UPPER HALF BLOCK return rune(0x2580), true - case "ulcorn": - // TOP LEFT CORNER + case "ulcorn": // TOP LEFT CORNER return rune(0x231c), true - case "ulcorner": - // TOP LEFT CORNER + case "ulcorner": // TOP LEFT CORNER return rune(0x231c), true - case "ulcrop": - // TOP LEFT CROP + case "ulcrop": // TOP LEFT CROP return rune(0x230f), true - case "uldlshar": - // UP BARB LEFT DOWN BARB LEFT HARPOON + case "uldlshar": // UP BARB LEFT DOWN BARB LEFT HARPOON return rune(0x2951), true - case "ulharb": - // UPWARDS HARPOON WITH BARB LEFT TO BAR + case "ulharb": // UPWARDS HARPOON WITH BARB LEFT TO BAR return rune(0x2958), true - case "ultri": - // UPPER LEFT TRIANGLE + case "ultri": // UPPER LEFT TRIANGLE return rune(0x25f8), true - case "umacr": - // LATIN SMALL LETTER U WITH MACRON + case "umacr": // LATIN SMALL LETTER U WITH MACRON return rune(0x016b), true - case "uml": - // DIAERESIS + case "uml": // DIAERESIS return rune(0xa8), true - case "uogon": - // LATIN SMALL LETTER U WITH OGONEK + case "uogon": // LATIN SMALL LETTER U WITH OGONEK return rune(0x0173), true - case "uopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL U + case "uopf": // MATHEMATICAL DOUBLE-STRUCK SMALL U return rune(0x01d566), true - case "uparrow": - // UPWARDS ARROW + case "uparrow": // UPWARDS ARROW return rune(0x2191), true - case "updownarrow": - // UP DOWN ARROW + case "updownarrow": // UP DOWN ARROW return rune(0x2195), true - case "upharpoonleft": - // UPWARDS HARPOON WITH BARB LEFTWARDS + case "upharpoonleft": // UPWARDS HARPOON WITH BARB LEFTWARDS return rune(0x21bf), true - case "upharpoonright": - // UPWARDS HARPOON WITH BARB RIGHTWARDS + case "upharpoonright": // UPWARDS HARPOON WITH BARB RIGHTWARDS return rune(0x21be), true - case "upint": - // INTEGRAL WITH OVERBAR + case "upint": // INTEGRAL WITH OVERBAR return rune(0x2a1b), true - case "uplus": - // MULTISET UNION + case "uplus": // MULTISET UNION return rune(0x228e), true - case "upsih": - // GREEK UPSILON WITH HOOK SYMBOL + case "upsi": // GREEK SMALL LETTER UPSILON + return rune(0x03c5), true + case "upsih": // GREEK UPSILON WITH HOOK SYMBOL return rune(0x03d2), true - case "upsilon": - // GREEK SMALL LETTER UPSILON + case "upsilon": // GREEK SMALL LETTER UPSILON return rune(0x03c5), true - case "upsi": - // GREEK SMALL LETTER UPSILON - return rune(0x03c5), true - case "upuparrows": - // UPWARDS PAIRED ARROWS + case "upuparrows": // UPWARDS PAIRED ARROWS return rune(0x21c8), true - case "urcorn": - // TOP RIGHT CORNER + case "urcorn": // TOP RIGHT CORNER return rune(0x231d), true - case "urcorner": - // TOP RIGHT CORNER + case "urcorner": // TOP RIGHT CORNER return rune(0x231d), true - case "urcrop": - // TOP RIGHT CROP + case "urcrop": // TOP RIGHT CROP return rune(0x230e), true - case "urdrshar": - // UP BARB RIGHT DOWN BARB RIGHT HARPOON + case "urdrshar": // UP BARB RIGHT DOWN BARB RIGHT HARPOON return rune(0x294f), true - case "urharb": - // UPWARDS HARPOON WITH BARB RIGHT TO BAR + case "urharb": // UPWARDS HARPOON WITH BARB RIGHT TO BAR return rune(0x2954), true - case "uring": - // LATIN SMALL LETTER U WITH RING ABOVE + case "uring": // LATIN SMALL LETTER U WITH RING ABOVE return rune(0x016f), true - case "urtrif": - // BLACK UPPER RIGHT TRIANGLE - return rune(0x25e5), true - case "urtri": - // UPPER RIGHT TRIANGLE + case "urtri": // UPPER RIGHT TRIANGLE return rune(0x25f9), true - case "uscr": - // MATHEMATICAL SCRIPT SMALL U + case "urtrif": // BLACK UPPER RIGHT TRIANGLE + return rune(0x25e5), true + case "uscr": // MATHEMATICAL SCRIPT SMALL U return rune(0x01d4ca), true - case "utdot": - // UP RIGHT DIAGONAL ELLIPSIS + case "utdot": // UP RIGHT DIAGONAL ELLIPSIS return rune(0x22f0), true - case "utilde": - // LATIN SMALL LETTER U WITH TILDE + case "utilde": // LATIN SMALL LETTER U WITH TILDE return rune(0x0169), true - case "utrif": - // BLACK UP-POINTING SMALL TRIANGLE - return rune(0x25b4), true - case "utri": - // WHITE UP-POINTING SMALL TRIANGLE + case "utri": // WHITE UP-POINTING SMALL TRIANGLE return rune(0x25b5), true - case "uuarr": - // UPWARDS PAIRED ARROWS + case "utrif": // BLACK UP-POINTING SMALL TRIANGLE + return rune(0x25b4), true + case "uuarr": // UPWARDS PAIRED ARROWS return rune(0x21c8), true - case "uuml": - // LATIN SMALL LETTER U WITH DIAERESIS + case "uuml": // LATIN SMALL LETTER U WITH DIAERESIS return rune(0xfc), true - case "uwangle": - // OBLIQUE ANGLE OPENING DOWN + case "uwangle": // OBLIQUE ANGLE OPENING DOWN return rune(0x29a7), true } case 'v': switch name { - case "vArr": - // UP DOWN DOUBLE ARROW + case "vArr": // UP DOWN DOUBLE ARROW return rune(0x21d5), true - case "vBar": - // SHORT UP TACK WITH UNDERBAR + case "vBar": // SHORT UP TACK WITH UNDERBAR return rune(0x2ae8), true - case "vBarv": - // SHORT UP TACK ABOVE SHORT DOWN TACK + case "vBarv": // SHORT UP TACK ABOVE SHORT DOWN TACK return rune(0x2ae9), true - case "vDash": - // TRUE + case "vDash": // TRUE return rune(0x22a8), true - case "vDdash": - // VERTICAL BAR TRIPLE RIGHT TURNSTILE + case "vDdash": // VERTICAL BAR TRIPLE RIGHT TURNSTILE return rune(0x2ae2), true - case "vangrt": - // RIGHT ANGLE VARIANT WITH SQUARE + case "vangrt": // RIGHT ANGLE VARIANT WITH SQUARE return rune(0x299c), true - case "varepsilon": - // GREEK LUNATE EPSILON SYMBOL + case "varepsilon": // GREEK LUNATE EPSILON SYMBOL return rune(0x03f5), true - case "varkappa": - // GREEK KAPPA SYMBOL + case "varkappa": // GREEK KAPPA SYMBOL return rune(0x03f0), true - case "varnothing": - // EMPTY SET + case "varnothing": // EMPTY SET return rune(0x2205), true - case "varphi": - // GREEK PHI SYMBOL + case "varphi": // GREEK PHI SYMBOL return rune(0x03d5), true - case "varpi": - // GREEK PI SYMBOL + case "varpi": // GREEK PI SYMBOL return rune(0x03d6), true - case "varpropto": - // PROPORTIONAL TO + case "varpropto": // PROPORTIONAL TO return rune(0x221d), true - case "varr": - // UP DOWN ARROW + case "varr": // UP DOWN ARROW return rune(0x2195), true - case "varrho": - // GREEK RHO SYMBOL + case "varrho": // GREEK RHO SYMBOL return rune(0x03f1), true - case "varsigma": - // GREEK SMALL LETTER FINAL SIGMA + case "varsigma": // GREEK SMALL LETTER FINAL SIGMA return rune(0x03c2), true - case "varsubsetneq": - // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + case "varsubsetneq": // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members return rune(0x228a), true - case "varsubsetneqq": - // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + case "varsubsetneqq": // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members return rune(0x2acb), true - case "varsupsetneq": - // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + case "varsupsetneq": // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members return rune(0x228b), true - case "varsupsetneqq": - // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + case "varsupsetneqq": // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members return rune(0x2acc), true - case "vartheta": - // GREEK THETA SYMBOL + case "vartheta": // GREEK THETA SYMBOL return rune(0x03d1), true - case "vartriangleleft": - // NORMAL SUBGROUP OF + case "vartriangleleft": // NORMAL SUBGROUP OF return rune(0x22b2), true - case "vartriangleright": - // CONTAINS AS NORMAL SUBGROUP + case "vartriangleright": // CONTAINS AS NORMAL SUBGROUP return rune(0x22b3), true - case "vbrtri": - // VERTICAL BAR BESIDE RIGHT TRIANGLE + case "vbrtri": // VERTICAL BAR BESIDE RIGHT TRIANGLE return rune(0x29d0), true - case "vcy": - // CYRILLIC SMALL LETTER VE + case "vcy": // CYRILLIC SMALL LETTER VE return rune(0x0432), true - case "vdash": - // RIGHT TACK + case "vdash": // RIGHT TACK return rune(0x22a2), true - case "vee": - // LOGICAL OR + case "vee": // LOGICAL OR return rune(0x2228), true - case "veeBar": - // LOGICAL OR WITH DOUBLE UNDERBAR + case "veeBar": // LOGICAL OR WITH DOUBLE UNDERBAR return rune(0x2a63), true - case "veebar": - // XOR + case "veebar": // XOR return rune(0x22bb), true - case "veeeq": - // EQUIANGULAR TO + case "veeeq": // EQUIANGULAR TO return rune(0x225a), true - case "vellip": - // VERTICAL ELLIPSIS + case "vellip": // VERTICAL ELLIPSIS return rune(0x22ee), true - case "vellip4": - // DOTTED FENCE + case "vellip4": // DOTTED FENCE return rune(0x2999), true - case "vellipv": - // TRIPLE COLON OPERATOR + case "vellipv": // TRIPLE COLON OPERATOR return rune(0x2af6), true - case "verbar": - // VERTICAL LINE + case "verbar": // VERTICAL LINE return rune(0x7c), true - case "vert3": - // TRIPLE VERTICAL BAR BINARY RELATION + case "vert": // VERTICAL LINE + return rune(0x7c), true + case "vert3": // TRIPLE VERTICAL BAR BINARY RELATION return rune(0x2af4), true - case "vert": - // VERTICAL LINE - return rune(0x7c), true - case "vfr": - // MATHEMATICAL FRAKTUR SMALL V + case "vfr": // MATHEMATICAL FRAKTUR SMALL V return rune(0x01d533), true - case "vldash": - // LEFT SQUARE BRACKET LOWER CORNER + case "vldash": // LEFT SQUARE BRACKET LOWER CORNER return rune(0x23a3), true - case "vltri": - // NORMAL SUBGROUP OF + case "vltri": // NORMAL SUBGROUP OF return rune(0x22b2), true - case "vnsub": - // SUBSET OF with vertical line + case "vnsub": // SUBSET OF with vertical line return rune(0x2282), true - case "vnsup": - // SUPERSET OF with vertical line + case "vnsup": // SUPERSET OF with vertical line return rune(0x2283), true - case "vopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL V + case "vopf": // MATHEMATICAL DOUBLE-STRUCK SMALL V return rune(0x01d567), true - case "vprime": - // PRIME + case "vprime": // PRIME return rune(0x2032), true - case "vprop": - // PROPORTIONAL TO + case "vprop": // PROPORTIONAL TO return rune(0x221d), true - case "vrtri": - // CONTAINS AS NORMAL SUBGROUP + case "vrtri": // CONTAINS AS NORMAL SUBGROUP return rune(0x22b3), true - case "vscr": - // MATHEMATICAL SCRIPT SMALL V + case "vscr": // MATHEMATICAL SCRIPT SMALL V return rune(0x01d4cb), true - case "vsubnE": - // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + case "vsubnE": // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members return rune(0x2acb), true - case "vsubne": - // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + case "vsubne": // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members return rune(0x228a), true - case "vsupnE": - // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + case "vsupnE": // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members return rune(0x2acc), true - case "vsupne": - // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members + case "vsupne": // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members return rune(0x228b), true - case "vzigzag": - // VERTICAL ZIGZAG LINE + case "vzigzag": // VERTICAL ZIGZAG LINE return rune(0x299a), true } case 'w': switch name { - case "wcirc": - // LATIN SMALL LETTER W WITH CIRCUMFLEX + case "wcirc": // LATIN SMALL LETTER W WITH CIRCUMFLEX return rune(0x0175), true - case "wedbar": - // LOGICAL AND WITH UNDERBAR + case "wedbar": // LOGICAL AND WITH UNDERBAR return rune(0x2a5f), true - case "wedge": - // LOGICAL AND + case "wedge": // LOGICAL AND return rune(0x2227), true - case "wedgeq": - // ESTIMATES + case "wedgeq": // ESTIMATES return rune(0x2259), true - case "weierp": - // SCRIPT CAPITAL P + case "weierp": // SCRIPT CAPITAL P return rune(0x2118), true - case "wfr": - // MATHEMATICAL FRAKTUR SMALL W + case "wfr": // MATHEMATICAL FRAKTUR SMALL W return rune(0x01d534), true - case "wopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL W + case "wopf": // MATHEMATICAL DOUBLE-STRUCK SMALL W return rune(0x01d568), true - case "wp": - // SCRIPT CAPITAL P + case "wp": // SCRIPT CAPITAL P return rune(0x2118), true - case "wreath": - // WREATH PRODUCT + case "wr": // WREATH PRODUCT return rune(0x2240), true - case "wr": - // WREATH PRODUCT + case "wreath": // WREATH PRODUCT return rune(0x2240), true - case "wscr": - // MATHEMATICAL SCRIPT SMALL W + case "wscr": // MATHEMATICAL SCRIPT SMALL W return rune(0x01d4cc), true } case 'x': switch name { - case "xandand": - // TWO LOGICAL AND OPERATOR + case "xandand": // TWO LOGICAL AND OPERATOR return rune(0x2a07), true - case "xbsol": - // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT + case "xbsol": // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT return rune(0x2571), true - case "xcap": - // N-ARY INTERSECTION + case "xcap": // N-ARY INTERSECTION return rune(0x22c2), true - case "xcirc": - // LARGE CIRCLE + case "xcirc": // LARGE CIRCLE return rune(0x25ef), true - case "xcup": - // N-ARY UNION + case "xcup": // N-ARY UNION return rune(0x22c3), true - case "xcupdot": - // N-ARY UNION OPERATOR WITH DOT + case "xcupdot": // N-ARY UNION OPERATOR WITH DOT return rune(0x2a03), true - case "xdtri": - // WHITE DOWN-POINTING TRIANGLE + case "xdtri": // WHITE DOWN-POINTING TRIANGLE return rune(0x25bd), true - case "xfr": - // MATHEMATICAL FRAKTUR SMALL X + case "xfr": // MATHEMATICAL FRAKTUR SMALL X return rune(0x01d535), true - case "xgr": - // GREEK SMALL LETTER XI + case "xgr": // GREEK SMALL LETTER XI return rune(0x03be), true - case "xhArr": - // LONG LEFT RIGHT DOUBLE ARROW + case "xhArr": // LONG LEFT RIGHT DOUBLE ARROW return rune(0x27fa), true - case "xharr": - // LONG LEFT RIGHT ARROW + case "xharr": // LONG LEFT RIGHT ARROW return rune(0x27f7), true - case "xi": - // GREEK SMALL LETTER XI + case "xi": // GREEK SMALL LETTER XI return rune(0x03be), true - case "xlArr": - // LONG LEFTWARDS DOUBLE ARROW + case "xlArr": // LONG LEFTWARDS DOUBLE ARROW return rune(0x27f8), true - case "xlarr": - // LONG LEFTWARDS ARROW + case "xlarr": // LONG LEFTWARDS ARROW return rune(0x27f5), true - case "xmap": - // LONG RIGHTWARDS ARROW FROM BAR + case "xmap": // LONG RIGHTWARDS ARROW FROM BAR return rune(0x27fc), true - case "xnis": - // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + case "xnis": // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE return rune(0x22fb), true - case "xodot": - // N-ARY CIRCLED DOT OPERATOR + case "xodot": // N-ARY CIRCLED DOT OPERATOR return rune(0x2a00), true - case "xopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL X + case "xopf": // MATHEMATICAL DOUBLE-STRUCK SMALL X return rune(0x01d569), true - case "xoplus": - // N-ARY CIRCLED PLUS OPERATOR + case "xoplus": // N-ARY CIRCLED PLUS OPERATOR return rune(0x2a01), true - case "xoror": - // TWO LOGICAL OR OPERATOR + case "xoror": // TWO LOGICAL OR OPERATOR return rune(0x2a08), true - case "xotime": - // N-ARY CIRCLED TIMES OPERATOR + case "xotime": // N-ARY CIRCLED TIMES OPERATOR return rune(0x2a02), true - case "xrArr": - // LONG RIGHTWARDS DOUBLE ARROW + case "xrArr": // LONG RIGHTWARDS DOUBLE ARROW return rune(0x27f9), true - case "xrarr": - // LONG RIGHTWARDS ARROW + case "xrarr": // LONG RIGHTWARDS ARROW return rune(0x27f6), true - case "xscr": - // MATHEMATICAL SCRIPT SMALL X + case "xscr": // MATHEMATICAL SCRIPT SMALL X return rune(0x01d4cd), true - case "xsol": - // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT + case "xsol": // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT return rune(0x2572), true - case "xsqcap": - // N-ARY SQUARE INTERSECTION OPERATOR + case "xsqcap": // N-ARY SQUARE INTERSECTION OPERATOR return rune(0x2a05), true - case "xsqcup": - // N-ARY SQUARE UNION OPERATOR + case "xsqcup": // N-ARY SQUARE UNION OPERATOR return rune(0x2a06), true - case "xsqu": - // WHITE MEDIUM SQUARE + case "xsqu": // WHITE MEDIUM SQUARE return rune(0x25fb), true - case "xsquf": - // BLACK MEDIUM SQUARE + case "xsquf": // BLACK MEDIUM SQUARE return rune(0x25fc), true - case "xtimes": - // N-ARY TIMES OPERATOR + case "xtimes": // N-ARY TIMES OPERATOR return rune(0x2a09), true - case "xuplus": - // N-ARY UNION OPERATOR WITH PLUS + case "xuplus": // N-ARY UNION OPERATOR WITH PLUS return rune(0x2a04), true - case "xutri": - // WHITE UP-POINTING TRIANGLE + case "xutri": // WHITE UP-POINTING TRIANGLE return rune(0x25b3), true - case "xvee": - // N-ARY LOGICAL OR + case "xvee": // N-ARY LOGICAL OR return rune(0x22c1), true - case "xwedge": - // N-ARY LOGICAL AND + case "xwedge": // N-ARY LOGICAL AND return rune(0x22c0), true } case 'y': switch name { - case "yacute": - // LATIN SMALL LETTER Y WITH ACUTE + case "yacute": // LATIN SMALL LETTER Y WITH ACUTE return rune(0xfd), true - case "yacy": - // CYRILLIC SMALL LETTER YA + case "yacy": // CYRILLIC SMALL LETTER YA return rune(0x044f), true - case "ycirc": - // LATIN SMALL LETTER Y WITH CIRCUMFLEX + case "ycirc": // LATIN SMALL LETTER Y WITH CIRCUMFLEX return rune(0x0177), true - case "ycy": - // CYRILLIC SMALL LETTER YERU + case "ycy": // CYRILLIC SMALL LETTER YERU return rune(0x044b), true - case "yen": - // YEN SIGN + case "yen": // YEN SIGN return rune(0xa5), true - case "yfr": - // MATHEMATICAL FRAKTUR SMALL Y + case "yfr": // MATHEMATICAL FRAKTUR SMALL Y return rune(0x01d536), true - case "yicy": - // CYRILLIC SMALL LETTER YI + case "yicy": // CYRILLIC SMALL LETTER YI return rune(0x0457), true - case "yopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL Y + case "yopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Y return rune(0x01d56a), true - case "yscr": - // MATHEMATICAL SCRIPT SMALL Y + case "yscr": // MATHEMATICAL SCRIPT SMALL Y return rune(0x01d4ce), true - case "yucy": - // CYRILLIC SMALL LETTER YU + case "yucy": // CYRILLIC SMALL LETTER YU return rune(0x044e), true - case "yuml": - // LATIN SMALL LETTER Y WITH DIAERESIS + case "yuml": // LATIN SMALL LETTER Y WITH DIAERESIS return rune(0xff), true } case 'z': switch name { - case "zacute": - // LATIN SMALL LETTER Z WITH ACUTE + case "zacute": // LATIN SMALL LETTER Z WITH ACUTE return rune(0x017a), true - case "zcaron": - // LATIN SMALL LETTER Z WITH CARON + case "zcaron": // LATIN SMALL LETTER Z WITH CARON return rune(0x017e), true - case "zcy": - // CYRILLIC SMALL LETTER ZE + case "zcy": // CYRILLIC SMALL LETTER ZE return rune(0x0437), true - case "zdot": - // LATIN SMALL LETTER Z WITH DOT ABOVE + case "zdot": // LATIN SMALL LETTER Z WITH DOT ABOVE return rune(0x017c), true - case "zeetrf": - // BLACK-LETTER CAPITAL Z + case "zeetrf": // BLACK-LETTER CAPITAL Z return rune(0x2128), true - case "zeta": - // GREEK SMALL LETTER ZETA + case "zeta": // GREEK SMALL LETTER ZETA return rune(0x03b6), true - case "zfr": - // MATHEMATICAL FRAKTUR SMALL Z + case "zfr": // MATHEMATICAL FRAKTUR SMALL Z return rune(0x01d537), true - case "zgr": - // GREEK SMALL LETTER ZETA + case "zgr": // GREEK SMALL LETTER ZETA return rune(0x03b6), true - case "zhcy": - // CYRILLIC SMALL LETTER ZHE + case "zhcy": // CYRILLIC SMALL LETTER ZHE return rune(0x0436), true - case "zigrarr": - // RIGHTWARDS SQUIGGLE ARROW + case "zigrarr": // RIGHTWARDS SQUIGGLE ARROW return rune(0x21dd), true - case "zopf": - // MATHEMATICAL DOUBLE-STRUCK SMALL Z + case "zopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Z return rune(0x01d56b), true - case "zscr": - // MATHEMATICAL SCRIPT SMALL Z + case "zscr": // MATHEMATICAL SCRIPT SMALL Z return rune(0x01d4cf), true - case "zwj": - // ZERO WIDTH JOINER + case "zwj": // ZERO WIDTH JOINER return rune(0x200d), true - case "zwnj": - // ZERO WIDTH NON-JOINER + case "zwnj": // ZERO WIDTH NON-JOINER return rune(0x200c), true } } diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index 85eca50b6..ab2af9561 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -7,6 +7,7 @@ import "core:strconv" import "core:strings" import "core:reflect" import "core:io" +import "core:slice" Marshal_Data_Error :: enum { None, @@ -18,29 +19,40 @@ Marshal_Error :: union #shared_nil { io.Error, } -// careful with MJSON maps & non quotes usage as keys without whitespace will lead to bad results +// careful with MJSON maps & non quotes usage as keys with whitespace will lead to bad results Marshal_Options :: struct { // output based on spec spec: Specification, - // use line breaks & tab|spaces + // Use line breaks & tabs/spaces pretty: bool, - // spacing + // Use spaces for indentation instead of tabs use_spaces: bool, + + // Given use_spaces true, use this many spaces per indent level. 0 means 4 spaces. spaces: int, - // state - indentation: int, - - // option to output uint in JSON5 & MJSON + // Output uint as hex in JSON5 & MJSON write_uint_as_hex: bool, - // mjson output options + // If spec is MJSON and this is true, then keys will be quoted. + // + // WARNING: If your keys contain whitespace and this is false, then the + // output will be bad. mjson_keys_use_quotes: bool, + + // If spec is MJSON and this is true, then use '=' as delimiter between + // keys and values, otherwise ':' is used. mjson_keys_use_equal_sign: bool, - // mjson state + // When outputting a map, sort the output by key. + // + // NOTE: This will temp allocate and sort a list for each map. + sort_maps_by_key: bool, + + // Internal state + indentation: int, mjson_skipped_first_braces_start: bool, mjson_skipped_first_braces_end: bool, } @@ -50,6 +62,9 @@ marshal :: proc(v: any, opt: Marshal_Options = {}, allocator := context.allocato defer if err != nil { strings.builder_destroy(&b) } + + // temp guard in case we are sorting map keys, which will use temp allocations + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = allocator == context.temp_allocator) opt := opt marshal_to_builder(&b, v, &opt) or_return @@ -263,36 +278,81 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: map_cap := uintptr(runtime.map_cap(m^)) ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info) - i := 0 - for bucket_index in 0.. bool { return i.key < j.key }) + + for s, i in sorted { + opt_write_iteration(w, opt, i) or_return + opt_write_key(w, opt, s.key) or_return + marshal_to_writer(w, s.value, opt) or_return + } } } @@ -424,8 +484,9 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err // insert start byte and increase indentation on pretty opt_write_start :: proc(w: io.Writer, opt: ^Marshal_Options, c: byte) -> (err: io.Error) { - // skip mjson starting braces - if opt.spec == .MJSON && !opt.mjson_skipped_first_braces_start { + // Skip MJSON starting braces. We make sure to only do this for c == '{', + // skipping a starting '[' is not allowed. + if opt.spec == .MJSON && !opt.mjson_skipped_first_braces_start && opt.indentation == 0 && c == '{' { opt.mjson_skipped_first_braces_start = true return } @@ -473,11 +534,9 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int) // decrease indent, write spacing and insert end byte opt_write_end :: proc(w: io.Writer, opt: ^Marshal_Options, c: byte) -> (err: io.Error) { - if opt.spec == .MJSON && opt.mjson_skipped_first_braces_start && !opt.mjson_skipped_first_braces_end { - if opt.indentation == 0 { - opt.mjson_skipped_first_braces_end = true - return - } + if opt.spec == .MJSON && opt.mjson_skipped_first_braces_start && !opt.mjson_skipped_first_braces_end && opt.indentation == 0 && c == '}' { + opt.mjson_skipped_first_braces_end = true + return } opt.indentation -= 1 diff --git a/core/encoding/json/types.odin b/core/encoding/json/types.odin index 089fd9c9b..20c806236 100644 --- a/core/encoding/json/types.odin +++ b/core/encoding/json/types.odin @@ -1,5 +1,7 @@ package json +import "core:strings" + /* JSON strict JSON @@ -104,4 +106,27 @@ destroy_value :: proc(value: Value, allocator := context.allocator) { case String: delete(v) } +} + +clone_value :: proc(value: Value, allocator := context.allocator) -> Value { + context.allocator = allocator + + #partial switch &v in value { + case Object: + new_o := make(Object, len(v)) + for key, elem in v { + new_o[strings.clone(key)] = clone_value(elem) + } + return new_o + case Array: + new_a := make(Array, len(v)) + for elem, idx in v { + new_a[idx] = clone_value(elem) + } + return new_a + case String: + return strings.clone(v) + } + + return value } \ No newline at end of file diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index 678f2dcfa..c1905f6b0 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -137,9 +137,9 @@ assign_float :: proc(val: any, f: $T) -> bool { case complex64: dst = complex(f32(f), 0) case complex128: dst = complex(f64(f), 0) - case quaternion64: dst = quaternion(f16(f), 0, 0, 0) - case quaternion128: dst = quaternion(f32(f), 0, 0, 0) - case quaternion256: dst = quaternion(f64(f), 0, 0, 0) + case quaternion64: dst = quaternion(w=f16(f), x=0, y=0, z=0) + case quaternion128: dst = quaternion(w=f32(f), x=0, y=0, z=0) + case quaternion256: dst = quaternion(w=f64(f), x=0, y=0, z=0) case: return false } @@ -201,20 +201,37 @@ unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.T unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token} token := p.curr_token - + v := v ti := reflect.type_info_base(type_info_of(v.id)) - // NOTE: If it's a union with only one variant, then treat it as that variant - if u, ok := ti.variant.(reflect.Type_Info_Union); ok && len(u.variants) == 1 && token.kind != .Null { - variant := u.variants[0] - v.id = variant.id - ti = reflect.type_info_base(variant) - if !reflect.is_pointer_internally(variant) { - tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} - assign_int(tag, 1) + if u, ok := ti.variant.(reflect.Type_Info_Union); ok && token.kind != .Null { + // NOTE: If it's a union with only one variant, then treat it as that variant + if len(u.variants) == 1 { + variant := u.variants[0] + v.id = variant.id + ti = reflect.type_info_base(variant) + if !reflect.is_pointer_internally(variant) { + tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} + assign_int(tag, 1) + } + } else if v.id != Value { + for variant, i in u.variants { + variant_any := any{v.data, variant.id} + variant_p := p^ + if err = unmarshal_value(&variant_p, variant_any); err == nil { + p^ = variant_p + + raw_tag := i + if !u.no_nil { raw_tag += 1 } + tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} + assign_int(tag, raw_tag) + return + } + } + return UNSUPPORTED_TYPE } } - + switch &dst in v { // Handle json.Value as an unknown type case Value: diff --git a/core/encoding/xml/debug_print.odin b/core/encoding/xml/debug_print.odin index b97617a8a..2607bec23 100644 --- a/core/encoding/xml/debug_print.odin +++ b/core/encoding/xml/debug_print.odin @@ -1,3 +1,5 @@ +package xml + /* An XML 1.0 / 1.1 parser @@ -9,7 +11,7 @@ List of contributors: Jeroen van Rijn: Initial implementation. */ -package xml + import "core:io" import "core:fmt" @@ -81,4 +83,4 @@ print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, } return written, .None -} \ No newline at end of file +} diff --git a/core/encoding/xml/example/xml_example.odin b/core/encoding/xml/example/xml_example.odin index aebb8d0ea..9648143db 100644 --- a/core/encoding/xml/example/xml_example.odin +++ b/core/encoding/xml/example/xml_example.odin @@ -20,7 +20,7 @@ example :: proc() { xml.destroy(docs[round]) } - DOC :: #load("../../../../tests/core/assets/XML/unicode.xml") + DOC :: #load("../../../../tests/core/assets/XML/utf8.xml") input := DOC for round in 0.. (res: Element_ID, found: bool) { @@ -47,4 +49,4 @@ find_attribute_val_by_key :: proc(doc: ^Document, parent_id: Element_ID, key: st if attr.key == key { return attr.val, true } } return "", false -} \ No newline at end of file +} diff --git a/core/encoding/xml/tokenizer.odin b/core/encoding/xml/tokenizer.odin index cd055475c..a223a75d6 100644 --- a/core/encoding/xml/tokenizer.odin +++ b/core/encoding/xml/tokenizer.odin @@ -1,3 +1,5 @@ +package xml + /* An XML 1.0 / 1.1 parser @@ -9,7 +11,7 @@ List of contributors: Jeroen van Rijn: Initial implementation. */ -package xml + import "core:fmt" import "core:unicode" @@ -433,4 +435,4 @@ scan :: proc(t: ^Tokenizer) -> Token { lit = string(t.src[offset : t.offset]) } return Token{kind, lit, pos} -} \ No newline at end of file +} diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin index f4f8a4b05..562d519d5 100644 --- a/core/encoding/xml/xml_reader.odin +++ b/core/encoding/xml/xml_reader.odin @@ -1,28 +1,28 @@ /* - An XML 1.0 / 1.1 parser + XML 1.0 / 1.1 parser - Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + 2021-2022 Jeroen van Rijn . + available under Odin's BSD-3 license. - A from-scratch XML implementation, loosely modelled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816). + from-scratch XML implementation, loosely modelled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816). - Features: - - Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage. - - Simple to understand and use. Small. +Features: +- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage. +- Simple to understand and use. Small. - Caveats: - - We do NOT support HTML in this package, as that may or may not be valid XML. - If it works, great. If it doesn't, that's not considered a bug. +Caveats: +- We do NOT support HTML in this package, as that may or may not be valid XML. + If it works, great. If it doesn't, that's not considered a bug. - - We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences. - - <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options. +- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences. +- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options. - MAYBE: - - XML writer? - - Serialize/deserialize Odin types? +MAYBE: +- XML writer? +- Serialize/deserialize Odin types? - List of contributors: - Jeroen van Rijn: Initial implementation. +List of contributors: +- Jeroen van Rijn: Initial implementation. */ package xml // An XML 1.0 / 1.1 parser @@ -43,48 +43,32 @@ DEFAULT_OPTIONS :: Options{ } Option_Flag :: enum { - /* - If the caller says that input may be modified, we can perform in-situ parsing. - If this flag isn't provided, the XML parser first duplicates the input so that it can. - */ + // If the caller says that input may be modified, we can perform in-situ parsing. + // If this flag isn't provided, the XML parser first duplicates the input so that it can. Input_May_Be_Modified, - /* - Document MUST start with ` (doc: ^Document, err: Error) { data := data context.allocator = allocator opts := validate_options(options) or_return - /* - If `.Input_May_Be_Modified` is not specified, we duplicate the input so that we can modify it in-place. - */ + // If `.Input_May_Be_Modified` is not specified, we duplicate the input so that we can modify it in-place. if .Input_May_Be_Modified not_in opts.flags { data = bytes.clone(data) } @@ -252,10 +209,8 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha element, parent: Element_ID open: Token - /* - If a DOCTYPE is present, the root tag has to match. - If an expected DOCTYPE is given in options (i.e. it's non-empty), the DOCTYPE (if present) and root tag have to match. - */ + // If a DOCTYPE is present, the root tag has to match. + // If an expected DOCTYPE is given in options (i.e. it's non-empty), the DOCTYPE (if present) and root tag have to match. expected_doctype := options.expected_doctype loop: for { @@ -263,17 +218,13 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha // NOTE(Jeroen): This is faster as a switch. switch t.ch { case '<': - /* - Consume peeked `<` - */ + // Consume peeked `<` advance_rune(t) open = scan(t) // NOTE(Jeroen): We're not using a switch because this if-else chain ordered by likelihood is 2.5% faster at -o:size and -o:speed. if likely(open.kind, Token_Kind.Ident) == .Ident { - /* - e.g. 0 && expected_doctype != open.text { error(t, t.offset, "Root Tag doesn't match DOCTYPE. Expected: %v, got: %v\n", expected_doctype, open.text) @@ -298,23 +247,17 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha } } - /* - One of these should follow: - - `>`, which means we've just opened this tag and expect a later element to close it. - - `/>`, which means this is an 'empty' or self-closing tag. - */ + // One of these should follow: + // - `>`, which means we've just opened this tag and expect a later element to close it. + // - `/>`, which means this is an 'empty' or self-closing tag. end_token := scan(t) #partial switch end_token.kind { case .Gt: - /* - We're now the new parent. - */ + // We're now the new parent. parent = element case .Slash: - /* - Empty tag. Close it. - */ + // Empty tag. Close it. expect(t, .Gt) or_return parent = doc.elements[element].parent element = parent @@ -325,9 +268,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha } } else if open.kind == .Slash { - /* - Close tag. - */ + // Close tag. ident := expect(t, .Ident) or_return _ = expect(t, .Gt) or_return @@ -339,9 +280,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha element = parent } else if open.kind == .Exclaim { - /* - . - The grammar does not allow a comment to end in ---> - */ + // Comment: . + // The grammar does not allow a comment to end in ---> expect(t, .Dash) comment := scan_comment(t) or_return @@ -395,23 +332,17 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha } } else if open.kind == .Question { - /* - 0 { - /* - We've already seen a prologue. - */ + // We've already seen a prologue. return doc, .Too_Many_Prologs } else { - /* - Could be ` (err: Error) { doc.encoding = .LATIN_1 case: - /* - Unrecognized encoding, assume UTF-8. - */ + // Unrecognized encoding, assume UTF-8. error(t, offset, "[parse_prologue] Warning: Unrecognized encoding: %v\n", attr.val) } @@ -658,11 +583,11 @@ skip_element :: proc(t: ^Tokenizer) -> (err: Error) { parse_doctype :: proc(doc: ^Document) -> (err: Error) { /* - + - - ]> + + ]> */ assert(doc != nil) context.allocator = doc.allocator @@ -675,9 +600,7 @@ parse_doctype :: proc(doc: ^Document) -> (err: Error) { offset := t.offset skip_element(t) or_return - /* - -1 because the current offset is that of the closing tag, so the rest of the DOCTYPE tag ends just before it. - */ + // -1 because the current offset is that of the closing tag, so the rest of the DOCTYPE tag ends just before it. doc.doctype.rest = string(t.src[offset : t.offset - 1]) return .None } @@ -700,4 +623,4 @@ new_element :: proc(doc: ^Document) -> (id: Element_ID) { cur := doc.element_count doc.element_count += 1 return cur -} \ No newline at end of file +} diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 402f783cf..f4fddd18d 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -216,7 +216,7 @@ tprintf :: proc(fmt: string, args: ..any) -> string { // Returns: A formatted string // bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string { - sb := strings.builder_from_bytes(buf[0:len(buf)]) + sb := strings.builder_from_bytes(buf) return sbprint(&sb, ..args, sep=sep) } // Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer. @@ -229,7 +229,7 @@ bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string { // Returns: A formatted string with a newline character at the end // bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string { - sb := strings.builder_from_bytes(buf[0:len(buf)]) + sb := strings.builder_from_bytes(buf) return sbprintln(&sb, ..args, sep=sep) } // Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer. @@ -242,7 +242,7 @@ bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string { // Returns: A formatted string // bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { - sb := strings.builder_from_bytes(buf[0:len(buf)]) + sb := strings.builder_from_bytes(buf) return sbprintf(&sb, fmt, ..args) } // Runtime assertion with a formatted message @@ -253,18 +253,24 @@ bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { // - args: A variadic list of arguments to be formatted // - loc: The location of the caller // -// Returns: True if the condition is met, otherwise triggers a runtime assertion with a formatted message -// -assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool { +@(disabled=ODIN_DISABLE_ASSERT) +assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) { if !condition { - p := context.assertion_failure_proc - if p == nil { - p = runtime.default_assertion_failure_proc + // NOTE(dragos): We are using the same trick as in builtin.assert + // to improve performance to make the CPU not + // execute speculatively, making it about an order of + // magnitude faster + @(cold) + internal :: proc(loc: runtime.Source_Code_Location, fmt: string, args: ..any) { + p := context.assertion_failure_proc + if p == nil { + p = runtime.default_assertion_failure_proc + } + message := tprintf(fmt, ..args) + p("Runtime assertion", message, loc) } - message := tprintf(fmt, ..args) - p("Runtime assertion", message, loc) + internal(loc, fmt, ..args) } - return condition } // Runtime panic with a formatted message // @@ -1232,8 +1238,12 @@ _pad :: proc(fi: ^Info, s: string) { // // NOTE: Can return "NaN", "+Inf", "-Inf", "+", or "-". // -_fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: byte) { - prec := fi.prec if fi.prec_set else 3 +_fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: byte, prec: int) { + prec := prec + if fi.prec_set { + prec = fi.prec + } + buf: [386]byte // Can return "NaN", "+Inf", "-Inf", "+", "-". @@ -1242,7 +1252,7 @@ _fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: b if !fi.plus { // Strip sign from "+" but not "+Inf". if str[0] == '+' && str[1] != 'I' { - str = str[1:] + str = str[1:] } } @@ -1258,11 +1268,13 @@ _fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: b // fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) { switch verb { - case 'f', 'F', 'g', 'G', 'v': - _fmt_float_as(fi, v, bit_size, verb, 'f') + case 'g', 'G', 'v': + _fmt_float_as(fi, v, bit_size, verb, 'g', -1) + case 'f', 'F': + _fmt_float_as(fi, v, bit_size, verb, 'f', 3) case 'e', 'E': // BUG(): "%.3e" returns "3.000e+00" - _fmt_float_as(fi, v, bit_size, verb, 'e') + _fmt_float_as(fi, v, bit_size, verb, 'e', 6) case 'h', 'H': prev_fi := fi^ diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index 1f0ccf412..3d1b0847b 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -1,4 +1,5 @@ -//+build !freestanding !js +//+build !freestanding +//+build !js package fmt import "core:runtime" diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin index 33c4e2b07..c23cbd473 100644 --- a/core/intrinsics/intrinsics.odin +++ b/core/intrinsics/intrinsics.odin @@ -162,7 +162,14 @@ type_is_matrix :: proc($T: typeid) -> bool --- type_has_nil :: proc($T: typeid) -> bool --- type_is_specialization_of :: proc($T, $S: typeid) -> bool --- + type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) --- +type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) --- +type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) --- +type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) --- +type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) --- +type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) --- +type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) --- type_has_field :: proc($T: typeid, $name: string) -> bool --- type_field_type :: proc($T: typeid, $name: string) -> typeid --- diff --git a/core/io/io.odin b/core/io/io.odin index 566e13c54..d3cae7bce 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -34,7 +34,7 @@ Error :: enum i32 { // No_Progress is returned by some implementations of `io.Reader` when many calls // to `read` have failed to return any data or error. - // This is usually a signed of a broken `io.Reader` implementation + // This is usually a sign of a broken `io.Reader` implementation No_Progress, Invalid_Whence, diff --git a/core/log/log.odin b/core/log/log.odin index f3554791b..b4039caa0 100644 --- a/core/log/log.odin +++ b/core/log/log.odin @@ -60,9 +60,9 @@ Logger_Proc :: runtime.Logger_Proc /* Logger :: struct { procedure: Logger_Proc, - data: rawptr, + data: rawptr, lowest_level: Level, - options: Logger_Options, + options: Logger_Options, } */ Logger :: runtime.Logger @@ -116,6 +116,42 @@ panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! runtime.panic("log.panicf", location) } +@(disabled=ODIN_DISABLE_ASSERT) +assert :: proc(condition: bool, message := "", loc := #caller_location) { + if !condition { + @(cold) + internal :: proc(message: string, loc: runtime.Source_Code_Location) { + p := context.assertion_failure_proc + if p == nil { + p = runtime.default_assertion_failure_proc + } + log(.Fatal, message, location=loc) + p("runtime assertion", message, loc) + } + internal(message, loc) + } +} + +@(disabled=ODIN_DISABLE_ASSERT) +assertf :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_location) { + if !condition { + // NOTE(dragos): We are using the same trick as in builtin.assert + // to improve performance to make the CPU not + // execute speculatively, making it about an order of + // magnitude faster + @(cold) + internal :: proc(loc: runtime.Source_Code_Location, fmt_str: string, args: ..any) { + p := context.assertion_failure_proc + if p == nil { + p = runtime.default_assertion_failure_proc + } + message := fmt.tprintf(fmt_str, ..args) + log(.Fatal, message, location=loc) + p("Runtime assertion", message, loc) + } + internal(loc, fmt_str, ..args) + } +} diff --git a/core/log/log_allocator.odin b/core/log/log_allocator.odin index 934f0d643..322c2e717 100644 --- a/core/log/log_allocator.odin +++ b/core/log/log_allocator.odin @@ -1,19 +1,28 @@ package log import "core:runtime" +import "core:fmt" + +Log_Allocator_Format :: enum { + Bytes, // Actual number of bytes. + Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate. +} Log_Allocator :: struct { allocator: runtime.Allocator, level: Level, prefix: string, locked: bool, + size_fmt: Log_Allocator_Format, } -log_allocator_init :: proc(la: ^Log_Allocator, level: Level, allocator := context.allocator, prefix := "") { +log_allocator_init :: proc(la: ^Log_Allocator, level: Level, size_fmt := Log_Allocator_Format.Bytes, + allocator := context.allocator, prefix := "") { la.allocator = allocator la.level = level la.prefix = prefix la.locked = false + la.size_fmt = size_fmt } @@ -29,71 +38,80 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, runtime.Allocator_Error) { la := (^Log_Allocator)(allocator_data) + if context.logger.procedure == nil || la.level < context.logger.lowest_level { + return la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location) + } + padding := " " if la.prefix != "" else "" + buf: [256]byte = --- + if !la.locked { la.locked = true defer la.locked = false switch mode { case .Alloc: - logf( - la.level, - "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)", - la.prefix, padding, size, alignment, - location = location, - ) + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + case .Alloc_Non_Zeroed: - logf( - la.level, - "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)", - la.prefix, padding, size, alignment, - location = location, - ) + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + case .Free: if old_size != 0 { - logf( - la.level, - "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)", - la.prefix, padding, old_memory, old_size, - location = location, - ) + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)" + case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } else { - logf( - la.level, - "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", - la.prefix, padding, old_memory, - location = location, - ) + str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } + case .Free_All: - logf( - la.level, - "%s%s<<< ALLOCATOR(mode=.Free_All)", - la.prefix, padding, - location = location, - ) + str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + case .Resize: - logf( - la.level, - "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)", - la.prefix, padding, old_memory, old_size, size, alignment, - location = location, - ) + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Resize_Non_Zeroed: + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + case .Query_Features: - logf( - la.level, - "%s%ALLOCATOR(mode=.Query_Features)", - la.prefix, padding, - location = location, - ) + str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + case .Query_Info: - logf( - la.level, - "%s%ALLOCATOR(mode=.Query_Info)", - la.prefix, padding, - location = location, - ) + str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } } @@ -102,13 +120,9 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, la.locked = true defer la.locked = false if err != nil { - logf( - la.level, - "%s%ALLOCATOR ERROR=%v", - la.prefix, padding, error, - location = location, - ) + str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } } return data, err -} \ No newline at end of file +} diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 968a26f8f..ca8dbf4c5 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -2856,7 +2856,7 @@ internal_int_random :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator dest.digit[digits - 1] &= ((1 << uint(bits)) - 1) } dest.used = digits - return nil + return internal_clamp(dest) } internal_random :: proc { internal_int_random, } diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin index 5d63bf7be..d347e9c11 100644 --- a/core/math/fixed/fixed.odin +++ b/core/math/fixed/fixed.odin @@ -88,17 +88,19 @@ div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { @(require_results) floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - return x.i >> Fraction_Width + if x.i >= 0 { + return x.i >> Fraction_Width + } else { + return (x.i - (1 << (Fraction_Width - 1)) + (1 << (Fraction_Width - 2))) >> Fraction_Width + } } @(require_results) ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width - return (x.i + (1 << Integer-1)) >> Fraction_Width + return (x.i + (1 << Fraction_Width - 1)) >> Fraction_Width } @(require_results) round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width - return (x.i + (1 << (Integer - 1))) >> Fraction_Width + return (x.i + (1 << (Fraction_Width - 1))) >> Fraction_Width } diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin index b58305c63..60185d64d 100644 --- a/core/math/linalg/general.odin +++ b/core/math/linalg/general.odin @@ -70,7 +70,7 @@ outer_product :: builtin.outer_product @(require_results) quaternion_inverse :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) { - return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0) + return conj(q) * quaternion(w=1.0/dot(q, q), x=0, y=0, z=0) } @@ -217,7 +217,7 @@ quaternion64_mul_vector3 :: proc "contextless" (q: $Q/quaternion64, v: $V/[3]$F/ Raw_Quaternion :: struct {xyz: [3]f16, r: f16} q := transmute(Raw_Quaternion)q - v := transmute([3]f16)v + v := v t := cross(2*q.xyz, v) return V(v + q.r*t + cross(q.xyz, t)) @@ -227,7 +227,7 @@ quaternion128_mul_vector3 :: proc "contextless" (q: $Q/quaternion128, v: $V/[3]$ Raw_Quaternion :: struct {xyz: [3]f32, r: f32} q := transmute(Raw_Quaternion)q - v := transmute([3]f32)v + v := v t := cross(2*q.xyz, v) return V(v + q.r*t + cross(q.xyz, t)) @@ -237,7 +237,7 @@ quaternion256_mul_vector3 :: proc "contextless" (q: $Q/quaternion256, v: $V/[3]$ Raw_Quaternion :: struct {xyz: [3]f64, r: f64} q := transmute(Raw_Quaternion)q - v := transmute([3]f64)v + v := v t := cross(2*q.xyz, v) return V(v + q.r*t + cross(q.xyz, t)) diff --git a/core/math/linalg/specific.odin b/core/math/linalg/specific.odin index 6607b241f..1f96eb178 100644 --- a/core/math/linalg/specific.odin +++ b/core/math/linalg/specific.odin @@ -7,96 +7,96 @@ F16_EPSILON :: 1e-3 F32_EPSILON :: 1e-7 F64_EPSILON :: 1e-15 -Vector2f16 :: distinct [2]f16 -Vector3f16 :: distinct [3]f16 -Vector4f16 :: distinct [4]f16 +Vector2f16 :: [2]f16 +Vector3f16 :: [3]f16 +Vector4f16 :: [4]f16 -Matrix1x1f16 :: distinct matrix[1, 1]f16 -Matrix1x2f16 :: distinct matrix[1, 2]f16 -Matrix1x3f16 :: distinct matrix[1, 3]f16 -Matrix1x4f16 :: distinct matrix[1, 4]f16 +Matrix1x1f16 :: matrix[1, 1]f16 +Matrix1x2f16 :: matrix[1, 2]f16 +Matrix1x3f16 :: matrix[1, 3]f16 +Matrix1x4f16 :: matrix[1, 4]f16 -Matrix2x1f16 :: distinct matrix[2, 1]f16 -Matrix2x2f16 :: distinct matrix[2, 2]f16 -Matrix2x3f16 :: distinct matrix[2, 3]f16 -Matrix2x4f16 :: distinct matrix[2, 4]f16 +Matrix2x1f16 :: matrix[2, 1]f16 +Matrix2x2f16 :: matrix[2, 2]f16 +Matrix2x3f16 :: matrix[2, 3]f16 +Matrix2x4f16 :: matrix[2, 4]f16 -Matrix3x1f16 :: distinct matrix[3, 1]f16 -Matrix3x2f16 :: distinct matrix[3, 2]f16 -Matrix3x3f16 :: distinct matrix[3, 3]f16 -Matrix3x4f16 :: distinct matrix[3, 4]f16 +Matrix3x1f16 :: matrix[3, 1]f16 +Matrix3x2f16 :: matrix[3, 2]f16 +Matrix3x3f16 :: matrix[3, 3]f16 +Matrix3x4f16 :: matrix[3, 4]f16 -Matrix4x1f16 :: distinct matrix[4, 1]f16 -Matrix4x2f16 :: distinct matrix[4, 2]f16 -Matrix4x3f16 :: distinct matrix[4, 3]f16 -Matrix4x4f16 :: distinct matrix[4, 4]f16 +Matrix4x1f16 :: matrix[4, 1]f16 +Matrix4x2f16 :: matrix[4, 2]f16 +Matrix4x3f16 :: matrix[4, 3]f16 +Matrix4x4f16 :: matrix[4, 4]f16 Matrix1f16 :: Matrix1x1f16 Matrix2f16 :: Matrix2x2f16 Matrix3f16 :: Matrix3x3f16 Matrix4f16 :: Matrix4x4f16 -Vector2f32 :: distinct [2]f32 -Vector3f32 :: distinct [3]f32 -Vector4f32 :: distinct [4]f32 +Vector2f32 :: [2]f32 +Vector3f32 :: [3]f32 +Vector4f32 :: [4]f32 -Matrix1x1f32 :: distinct matrix[1, 1]f32 -Matrix1x2f32 :: distinct matrix[1, 2]f32 -Matrix1x3f32 :: distinct matrix[1, 3]f32 -Matrix1x4f32 :: distinct matrix[1, 4]f32 +Matrix1x1f32 :: matrix[1, 1]f32 +Matrix1x2f32 :: matrix[1, 2]f32 +Matrix1x3f32 :: matrix[1, 3]f32 +Matrix1x4f32 :: matrix[1, 4]f32 -Matrix2x1f32 :: distinct matrix[2, 1]f32 -Matrix2x2f32 :: distinct matrix[2, 2]f32 -Matrix2x3f32 :: distinct matrix[2, 3]f32 -Matrix2x4f32 :: distinct matrix[2, 4]f32 +Matrix2x1f32 :: matrix[2, 1]f32 +Matrix2x2f32 :: matrix[2, 2]f32 +Matrix2x3f32 :: matrix[2, 3]f32 +Matrix2x4f32 :: matrix[2, 4]f32 -Matrix3x1f32 :: distinct matrix[3, 1]f32 -Matrix3x2f32 :: distinct matrix[3, 2]f32 -Matrix3x3f32 :: distinct matrix[3, 3]f32 -Matrix3x4f32 :: distinct matrix[3, 4]f32 +Matrix3x1f32 :: matrix[3, 1]f32 +Matrix3x2f32 :: matrix[3, 2]f32 +Matrix3x3f32 :: matrix[3, 3]f32 +Matrix3x4f32 :: matrix[3, 4]f32 -Matrix4x1f32 :: distinct matrix[4, 1]f32 -Matrix4x2f32 :: distinct matrix[4, 2]f32 -Matrix4x3f32 :: distinct matrix[4, 3]f32 -Matrix4x4f32 :: distinct matrix[4, 4]f32 +Matrix4x1f32 :: matrix[4, 1]f32 +Matrix4x2f32 :: matrix[4, 2]f32 +Matrix4x3f32 :: matrix[4, 3]f32 +Matrix4x4f32 :: matrix[4, 4]f32 Matrix1f32 :: Matrix1x1f32 Matrix2f32 :: Matrix2x2f32 Matrix3f32 :: Matrix3x3f32 Matrix4f32 :: Matrix4x4f32 -Vector2f64 :: distinct [2]f64 -Vector3f64 :: distinct [3]f64 -Vector4f64 :: distinct [4]f64 +Vector2f64 :: [2]f64 +Vector3f64 :: [3]f64 +Vector4f64 :: [4]f64 -Matrix1x1f64 :: distinct matrix[1, 1]f64 -Matrix1x2f64 :: distinct matrix[1, 2]f64 -Matrix1x3f64 :: distinct matrix[1, 3]f64 -Matrix1x4f64 :: distinct matrix[1, 4]f64 +Matrix1x1f64 :: matrix[1, 1]f64 +Matrix1x2f64 :: matrix[1, 2]f64 +Matrix1x3f64 :: matrix[1, 3]f64 +Matrix1x4f64 :: matrix[1, 4]f64 -Matrix2x1f64 :: distinct matrix[2, 1]f64 -Matrix2x2f64 :: distinct matrix[2, 2]f64 -Matrix2x3f64 :: distinct matrix[2, 3]f64 -Matrix2x4f64 :: distinct matrix[2, 4]f64 +Matrix2x1f64 :: matrix[2, 1]f64 +Matrix2x2f64 :: matrix[2, 2]f64 +Matrix2x3f64 :: matrix[2, 3]f64 +Matrix2x4f64 :: matrix[2, 4]f64 -Matrix3x1f64 :: distinct matrix[3, 1]f64 -Matrix3x2f64 :: distinct matrix[3, 2]f64 -Matrix3x3f64 :: distinct matrix[3, 3]f64 -Matrix3x4f64 :: distinct matrix[3, 4]f64 +Matrix3x1f64 :: matrix[3, 1]f64 +Matrix3x2f64 :: matrix[3, 2]f64 +Matrix3x3f64 :: matrix[3, 3]f64 +Matrix3x4f64 :: matrix[3, 4]f64 -Matrix4x1f64 :: distinct matrix[4, 1]f64 -Matrix4x2f64 :: distinct matrix[4, 2]f64 -Matrix4x3f64 :: distinct matrix[4, 3]f64 -Matrix4x4f64 :: distinct matrix[4, 4]f64 +Matrix4x1f64 :: matrix[4, 1]f64 +Matrix4x2f64 :: matrix[4, 2]f64 +Matrix4x3f64 :: matrix[4, 3]f64 +Matrix4x4f64 :: matrix[4, 4]f64 Matrix1f64 :: Matrix1x1f64 Matrix2f64 :: Matrix2x2f64 Matrix3f64 :: Matrix3x3f64 Matrix4f64 :: Matrix4x4f64 -Quaternionf16 :: distinct quaternion64 -Quaternionf32 :: distinct quaternion128 -Quaternionf64 :: distinct quaternion256 +Quaternionf16 :: quaternion64 +Quaternionf32 :: quaternion128 +Quaternionf64 :: quaternion256 MATRIX1F16_IDENTITY :: Matrix1f16(1) MATRIX2F16_IDENTITY :: Matrix2f16(1) diff --git a/core/math/math.odin b/core/math/math.odin index dddff4079..696293f70 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -2312,17 +2312,17 @@ F32_NORMALIZE :: 0 F32_RADIX :: 2 F32_ROUNDS :: 1 -F64_DIG :: 15 // # of decimal digits of precision -F64_EPSILON :: 2.2204460492503131e-016 // smallest such that 1.0+F64_EPSILON != 1.0 -F64_MANT_DIG :: 53 // # of bits in mantissa -F64_MAX :: 1.7976931348623158e+308 // max value -F64_MAX_10_EXP :: 308 // max decimal exponent -F64_MAX_EXP :: 1024 // max binary exponent -F64_MIN :: 2.2250738585072014e-308 // min positive value -F64_MIN_10_EXP :: -307 // min decimal exponent -F64_MIN_EXP :: -1021 // min binary exponent -F64_RADIX :: 2 // exponent radix -F64_ROUNDS :: 1 // addition rounding: near +F64_DIG :: 15 // Number of representable decimal digits. +F64_EPSILON :: 2.2204460492503131e-016 // Smallest number such that `1.0 + F64_EPSILON != 1.0`. +F64_MANT_DIG :: 53 // Number of bits in the mantissa. +F64_MAX :: 1.7976931348623158e+308 // Maximum representable value. +F64_MAX_10_EXP :: 308 // Maximum base-10 exponent yielding normalized value. +F64_MAX_EXP :: 1024 // One greater than the maximum possible base-2 exponent yielding normalized value. +F64_MIN :: 2.2250738585072014e-308 // Minimum positive normalized value. +F64_MIN_10_EXP :: -307 // Minimum base-10 exponent yielding normalized value. +F64_MIN_EXP :: -1021 // One greater than the minimum possible base-2 exponent yielding normalized value. +F64_RADIX :: 2 // Exponent radix. +F64_ROUNDS :: 1 // Addition rounding: near. F16_MASK :: 0x1f diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 57e82a5f8..4cea20f30 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -11,6 +11,8 @@ Allocator_Mode :: enum byte { Free_All, Resize, Query_Features, + Alloc_Non_Zeroed, + Resize_Non_Zeroed, } */ @@ -243,12 +245,26 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: res = raw_data(data) return } + +@(require_results) +default_resize_bytes_align_non_zeroed :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { + return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc) +} @(require_results) default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { + return _default_resize_bytes_align(old_data, new_size, alignment, true, allocator, loc) +} + +@(require_results) +_default_resize_bytes_align :: #force_inline proc(old_data: []byte, new_size, alignment: int, should_zero: bool, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { old_memory := raw_data(old_data) old_size := len(old_data) if old_memory == nil { - return alloc_bytes(new_size, alignment, allocator, loc) + if should_zero { + return alloc_bytes(new_size, alignment, allocator, loc) + } else { + return alloc_bytes_non_zeroed(new_size, alignment, allocator, loc) + } } if new_size == 0 { @@ -260,7 +276,13 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a return old_data, .None } - new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) + new_memory : []byte + err : Allocator_Error + if should_zero { + new_memory, err = alloc_bytes(new_size, alignment, allocator, loc) + } else { + new_memory, err = alloc_bytes_non_zeroed(new_size, alignment, allocator, loc) + } if new_memory == nil || err != nil { return nil, err } diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 4f5dd8eef..76f87a450 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -85,13 +85,16 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case .Free_All: arena.offset = 0 - case .Resize: - return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena)) + case .Resize: + return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena)) + + case .Resize_Non_Zeroed: + return default_resize_bytes_align_non_zeroed(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena)) case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features} } return nil, nil @@ -259,7 +262,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } clear(&s.leaked_allocations) - case .Resize: + case .Resize, .Resize_Non_Zeroed: begin := uintptr(raw_data(s.data)) end := begin + uintptr(len(s.data)) old_ptr := uintptr(old_memory) @@ -278,7 +281,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features} } return nil, nil @@ -406,9 +409,9 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, s.prev_offset = 0 s.curr_offset = 0 - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_memory == nil { - return raw_alloc(s, size, alignment, true) + return raw_alloc(s, size, alignment, mode == .Resize) } if size == 0 { return nil, nil @@ -434,7 +437,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) if old_offset != header.prev_offset { - data, err := raw_alloc(s, size, alignment, true) + data, err := raw_alloc(s, size, alignment, mode == .Resize) if err == nil { runtime.copy(data, byte_slice(old_memory, old_size)) } @@ -455,7 +458,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features} } return nil, nil case .Query_Info: @@ -565,9 +568,9 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case .Free_All: s.offset = 0 - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_memory == nil { - return raw_alloc(s, size, align, true) + return raw_alloc(s, size, align, mode == .Resize) } if size == 0 { return nil, nil @@ -590,7 +593,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return byte_slice(old_memory, size), nil } - data, err := raw_alloc(s, size, align, true) + data, err := raw_alloc(s, size, align, mode == .Resize) if err == nil { runtime.copy(data, byte_slice(old_memory, old_size)) } @@ -599,7 +602,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features} } return nil, nil @@ -649,7 +652,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode case .Free_All: dynamic_pool_free_all(pool) return nil, nil - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_size >= size { return byte_slice(old_memory, size), nil } @@ -662,7 +665,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features, .Query_Info} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features, .Query_Info} } return nil, nil @@ -826,6 +829,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if size > 0 { panic("mem: panic allocator, .Resize called", loc=loc) } + case .Resize_Non_Zeroed: + if size > 0 { + panic("mem: panic allocator, .Resize_Non_Zeroed called", loc=loc) + } case .Free: if old_memory != nil { panic("mem: panic allocator, .Free called", loc=loc) @@ -958,7 +965,7 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if data.clear_on_free_all { clear_map(&data.allocation_map) } - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_memory != result_ptr { delete_key(&data.allocation_map, old_memory) } diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index d15df46ad..cdac3c32f 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -51,7 +51,7 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING // Initialization of an `Arena` to be a `.Static` variant. // A static arena contains a single `Memory_Block` allocated with virtual memory. @(require_results) -arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) { +arena_init_static :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_STATIC_RESERVE_SIZE, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) { arena.kind = .Static arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return arena.total_used = 0 @@ -98,15 +98,15 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l switch arena.kind { case .Growing: - if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved { - size = mem.align_forward_uint(size, alignment) + needed := mem.align_forward_uint(size, alignment) + if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.reserved { if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE } - block_size := max(size, arena.minimum_block_size) + block_size := max(needed, arena.minimum_block_size) - new_block := memory_block_alloc(size, block_size, {}) or_return + new_block := memory_block_alloc(needed, block_size, alignment, {}) or_return new_block.prev = arena.curr_block arena.curr_block = new_block arena.total_reserved += new_block.reserved @@ -288,7 +288,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, err = .Mode_Not_Implemented case .Free_All: arena_free_all(arena, location) - case .Resize: + case .Resize, .Resize_Non_Zeroed: old_data := ([^]byte)(old_memory) switch { diff --git a/core/mem/virtual/file.odin b/core/mem/virtual/file.odin new file mode 100644 index 000000000..5d7180588 --- /dev/null +++ b/core/mem/virtual/file.odin @@ -0,0 +1,47 @@ +package mem_virtual + +import "core:os" + +Map_File_Error :: enum { + None, + Open_Failure, + Stat_Failure, + Negative_Size, + Too_Large_Size, + Map_Failure, +} + +Map_File_Flag :: enum u32 { + Read, + Write, +} +Map_File_Flags :: distinct bit_set[Map_File_Flag; u32] + +map_file :: proc{ + map_file_from_path, + map_file_from_file_descriptor, +} + +map_file_from_path :: proc(filename: string, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + fd, err := os.open(filename, os.O_RDWR) + if err != 0 { + return nil, .Open_Failure + } + defer os.close(fd) + + return map_file_from_file_descriptor(uintptr(fd), flags) +} + +map_file_from_file_descriptor :: proc(fd: uintptr, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + size, os_err := os.file_size(os.Handle(fd)) + if os_err != 0 { + return nil, .Stat_Failure + } + if size < 0 { + return nil, .Negative_Size + } + if size != i64(int(size)) { + return nil, .Too_Large_Size + } + return _map_file(fd, size, flags) +} diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 1624fae9d..00a9e6a5d 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -68,7 +68,7 @@ align_formula :: #force_inline proc "contextless" (size, align: uint) -> uint { } @(require_results) -memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) -> (block: ^Memory_Block, err: Allocator_Error) { +memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags: Memory_Block_Flags = {}) -> (block: ^Memory_Block, err: Allocator_Error) { page_size := DEFAULT_PAGE_SIZE assert(mem.is_power_of_two(uintptr(page_size))) @@ -79,8 +79,8 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) reserved = align_formula(reserved, page_size) committed = clamp(committed, 0, reserved) - total_size := uint(reserved + size_of(Platform_Memory_Block)) - base_offset := uintptr(size_of(Platform_Memory_Block)) + total_size := uint(reserved + max(alignment, size_of(Platform_Memory_Block))) + base_offset := uintptr(max(alignment, size_of(Platform_Memory_Block))) protect_offset := uintptr(0) do_protection := false @@ -183,4 +183,4 @@ memory_block_dealloc :: proc(block_to_free: ^Memory_Block) { safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) { z, did_overflow := intrinsics.overflow_add(x, y) return z, !did_overflow -} \ No newline at end of file +} diff --git a/core/mem/virtual/virtual_bsd.odin b/core/mem/virtual/virtual_bsd.odin index 103e48074..7568084c0 100644 --- a/core/mem/virtual/virtual_bsd.odin +++ b/core/mem/virtual/virtual_bsd.odin @@ -22,3 +22,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) _platform_memory_init :: proc() { } + +_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + return nil, .Map_Failure +} diff --git a/core/mem/virtual/virtual_darwin.odin b/core/mem/virtual/virtual_darwin.odin index 5505149b0..5be17c0f9 100644 --- a/core/mem/virtual/virtual_darwin.odin +++ b/core/mem/virtual/virtual_darwin.odin @@ -136,7 +136,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) if .Write in flags { pflags |= PROT_WRITE } if .Execute in flags { pflags |= PROT_EXEC } err := _mprotect(data, size, pflags) - return err != 0 + return err == 0 } @@ -146,3 +146,20 @@ _platform_memory_init :: proc() { // is power of two assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } + + +_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + prot, mflags: c.int + if .Read in flags { + prot |= PROT_READ + } + if .Write in flags { + prot |= PROT_WRITE + } + mflags |= MAP_SHARED + addr := _mmap(nil, c.size_t(size), prot, mflags, i32(fd), 0) + if addr == nil { + return nil, .Map_Failure + } + return ([^]byte)(addr)[:size], nil +} diff --git a/core/mem/virtual/virtual_linux.odin b/core/mem/virtual/virtual_linux.odin index 7ffc7643e..816a8bb84 100644 --- a/core/mem/virtual/virtual_linux.odin +++ b/core/mem/virtual/virtual_linux.odin @@ -40,7 +40,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) if .Write in flags { pflags |= {.WRITE} } if .Execute in flags { pflags |= {.EXEC} } errno := linux.mprotect(data, size, pflags) - return errno != .NONE + return errno == .NONE } _platform_memory_init :: proc() { @@ -48,3 +48,21 @@ _platform_memory_init :: proc() { // is power of two assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } + + +_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + prot: linux.Mem_Protection + if .Read in flags { + prot += {.READ} + } + if .Write in flags { + prot += {.WRITE} + } + + flags := linux.Map_Flags{.SHARED} + addr, errno := linux.mmap(0, uint(size), prot, flags, linux.Fd(fd), offset=0) + if addr == nil || errno != nil { + return nil, .Map_Failure + } + return ([^]byte)(addr)[:size], nil +} diff --git a/core/mem/virtual/virtual_windows.odin b/core/mem/virtual/virtual_windows.odin index bbd74a925..ee47a01a8 100644 --- a/core/mem/virtual/virtual_windows.odin +++ b/core/mem/virtual/virtual_windows.odin @@ -50,19 +50,39 @@ PAGE_WRITECOPY :: 0x08 PAGE_TARGETS_INVALID :: 0x40000000 PAGE_TARGETS_NO_UPDATE :: 0x40000000 +SECTION_MAP_WRITE :: 0x0002 +SECTION_MAP_READ :: 0x0004 +FILE_MAP_WRITE :: SECTION_MAP_WRITE +FILE_MAP_READ :: SECTION_MAP_READ + ERROR_INVALID_ADDRESS :: 487 ERROR_COMMITMENT_LIMIT :: 1455 -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Kernel32 { GetSystemInfo :: proc(lpSystemInfo: LPSYSTEM_INFO) --- VirtualAlloc :: proc(lpAddress: rawptr, dwSize: uint, flAllocationType: u32, flProtect: u32) -> rawptr --- VirtualFree :: proc(lpAddress: rawptr, dwSize: uint, dwFreeType: u32) -> b32 --- VirtualProtect :: proc(lpAddress: rawptr, dwSize: uint, flNewProtect: u32, lpflOldProtect: ^u32) -> b32 --- GetLastError :: proc() -> u32 --- + + CreateFileMappingW :: proc( + hFile: rawptr, + lpFileMappingAttributes: rawptr, + flProtect: u32, + dwMaximumSizeHigh: u32, + dwMaximumSizeLow: u32, + lpName: [^]u16, + ) -> rawptr --- + + MapViewOfFile :: proc( + hFileMappingObject: rawptr, + dwDesiredAccess: u32, + dwFileOffsetHigh: u32, + dwFileOffsetLow: u32, + dwNumberOfBytesToMap: uint, + ) -> rawptr --- } - - _reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { result := VirtualAlloc(nil, size, MEM_RESERVE, PAGE_READWRITE) if result == nil { @@ -125,3 +145,33 @@ _platform_memory_init :: proc() { // is power of two assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } + + +_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + page_flags: u32 + if flags == {.Read} { + page_flags = PAGE_READONLY + } else if flags == {.Write} { + page_flags = PAGE_READWRITE + } else if flags == {.Read, .Write} { + page_flags = PAGE_READWRITE + } else { + page_flags = PAGE_NOACCESS + } + maximum_size := transmute([2]u32)size + handle := CreateFileMappingW(rawptr(fd), nil, page_flags, maximum_size[1], maximum_size[0], nil) + if handle == nil { + return nil, .Map_Failure + } + + desired_access: u32 + if .Read in flags { + desired_access |= FILE_MAP_READ + } + if .Write in flags { + desired_access |= FILE_MAP_WRITE + } + + file_data := MapViewOfFile(handle, desired_access, 0, 0, uint(size)) + return ([^]byte)(file_data)[:size], nil +} diff --git a/core/net/socket.odin b/core/net/socket.odin index 40fa6ab56..1bfa52257 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -148,7 +148,29 @@ recv_udp :: proc(socket: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_en return _recv_udp(socket, buf) } -recv :: proc{recv_tcp, recv_udp} +/* + Receive data from into a buffer from any socket. + + Note: `remote_endpoint` parameter is non-nil only if the socket type is UDP. On TCP sockets it + will always return `nil`. +*/ +recv_any :: proc(socket: Any_Socket, buf: []byte) -> ( + bytes_read: int, + remote_endpoint: Maybe(Endpoint), + err: Network_Error, +) { + switch socktype in socket { + case TCP_Socket: + bytes_read, err := recv_tcp(socktype, buf) + return bytes_read, nil, err + case UDP_Socket: + bytes_read, endpoint, err := recv_udp(socktype, buf) + return bytes_read, endpoint, err + case: panic("Not supported") + } +} + +recv :: proc{recv_tcp, recv_udp, recv_any} /* Repeatedly sends data until the entire buffer is sent. @@ -168,7 +190,20 @@ send_udp :: proc(socket: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_writte return _send_udp(socket, buf, to) } -send :: proc{send_tcp, send_udp} +send_any :: proc(socket: Any_Socket, buf: []byte, to: Maybe(Endpoint) = nil) -> ( + bytes_written: int, + err: Network_Error, +) { + switch socktype in socket { + case TCP_Socket: + return send_tcp(socktype, buf) + case UDP_Socket: + return send_udp(socktype, buf, to.(Endpoint)) + case: panic("Not supported") + } +} + +send :: proc{send_tcp, send_udp, send_any} shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) { return _shutdown(socket, manner) @@ -180,4 +215,4 @@ set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc := set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { return _set_blocking(socket, should_block) -} \ No newline at end of file +} diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index 6d3f111d1..ba48959fb 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -125,7 +125,7 @@ _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (An } @(private) -_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (tcp_sock: TCP_Socket, err: Network_Error) { +_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (TCP_Socket, Network_Error) { errno: linux.Errno if endpoint.port == 0 { return 0, .Port_Required diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index 2d85029e8..f1d3e08b8 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -7,7 +7,7 @@ import "core:reflect" import "core:odin/tokenizer" _ :: intrinsics -new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T { +new_from_positions :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T { n, _ := mem.new(T) n.pos = pos n.end = end @@ -23,6 +23,15 @@ new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T { return n } +new_from_pos_and_end_node :: proc($T: typeid, pos: tokenizer.Pos, end: ^Node) -> ^T { + return new(T, pos, end != nil ? end.end : pos) +} + +new :: proc { + new_from_positions, + new_from_pos_and_end_node, +} + clone :: proc{ clone_node, clone_expr, diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index bbfaf9114..3383f3514 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -436,6 +436,24 @@ expect_closing_brace_of_field_list :: proc(p: ^Parser) -> tokenizer.Token { return expect_brace } +expect_closing_parentheses_of_field_list :: proc(p: ^Parser) -> tokenizer.Token { + token := p.curr_tok + if allow_token(p, .Close_Paren) { + return token + } + + if allow_token(p, .Semicolon) && !tokenizer.is_newline(token) { + str := tokenizer.token_to_string(token) + error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", str) + } + + for p.curr_tok.kind != .Close_Paren && p.curr_tok.kind != .EOF && !is_non_inserted_semicolon(p.curr_tok) { + advance_token(p) + } + + return expect_token(p, .Close_Paren) +} + is_non_inserted_semicolon :: proc(tok: tokenizer.Token) -> bool { return tok.kind == .Semicolon && tok.text != "\n" } @@ -786,8 +804,11 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt { else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok)) } } - - end := body.end + + end: tokenizer.Pos + if body != nil { + end = body.end + } if else_stmt != nil { end = else_stmt.end } @@ -850,7 +871,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { body = parse_body(p) } - range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end) + range_stmt := ast.new(ast.Range_Stmt, tok.pos, body) range_stmt.for_pos = tok.pos range_stmt.in_pos = in_tok.pos range_stmt.expr = rhs @@ -910,7 +931,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { rhs = assign_stmt.rhs[0] } - range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end) + range_stmt := ast.new(ast.Range_Stmt, tok.pos, body) range_stmt.for_pos = tok.pos range_stmt.vals = vals range_stmt.in_pos = assign_stmt.op.pos @@ -920,7 +941,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { } cond_expr := convert_stmt_to_expr(p, cond, "boolean expression") - for_stmt := ast.new(ast.For_Stmt, tok.pos, body.end) + for_stmt := ast.new(ast.For_Stmt, tok.pos, body) for_stmt.for_pos = tok.pos for_stmt.init = init for_stmt.cond = cond_expr @@ -976,7 +997,7 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { lhs[0] = new_blank_ident(p, tok.pos) rhs[0] = parse_expr(p, true) - as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0].end) + as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0]) as.lhs = lhs as.op = in_tok as.rhs = rhs @@ -1010,14 +1031,14 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { body.stmts = clauses[:] if is_type_switch { - ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end) + ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body) ts.tag = tag ts.body = body ts.switch_pos = tok.pos return ts } else { cond := convert_stmt_to_expr(p, tag, "switch expression") - ts := ast.new(ast.Switch_Stmt, tok.pos, body.end) + ts := ast.new(ast.Switch_Stmt, tok.pos, body) ts.init = init ts.cond = cond ts.body = body @@ -1044,7 +1065,7 @@ parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind: if p.curr_tok.kind == .Eq { eq := expect_token(p, .Eq) value := parse_value(p) - fv := ast.new(ast.Field_Value, elem.pos, value.end) + fv := ast.new(ast.Field_Value, elem.pos, value) fv.field = elem fv.sep = eq.pos fv.value = value @@ -1137,7 +1158,7 @@ parse_foreign_block :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Foreign_Bl body.stmts = decls[:] body.close = close.pos - decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body.end) + decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body) decl.docs = docs decl.tok = tok decl.foreign_library = foreign_library @@ -1248,7 +1269,7 @@ parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok)) } - range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body.end) + range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body) range_stmt.inline_pos = inline_tok.pos range_stmt.for_pos = for_tok.pos range_stmt.val0 = val0 @@ -1304,7 +1325,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { case ^ast.Return_Stmt: error(p, s.pos, "you cannot defer a return statement") } - ds := ast.new(ast.Defer_Stmt, tok.pos, stmt.end) + ds := ast.new(ast.Defer_Stmt, tok.pos, stmt) ds.stmt = stmt return ds @@ -1341,8 +1362,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { if tok.kind != .Fallthrough && p.curr_tok.kind == .Ident { label = parse_ident(p) } - end := label.end if label != nil else end_pos(tok) - s := ast.new(ast.Branch_Stmt, tok.pos, end) + s := ast.new(ast.Branch_Stmt, tok.pos, label) s.tok = tok s.label = label expect_semicolon(p, s) @@ -1366,7 +1386,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { if p.curr_tok.kind != .Colon { end := list[len(list)-1] expect_semicolon(p, end) - us := ast.new(ast.Using_Stmt, tok.pos, end.end) + us := ast.new(ast.Using_Stmt, tok.pos, end) us.list = list return us } @@ -1416,13 +1436,13 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { bd.tok = tok bd.name = name ce := parse_call_expr(p, bd) - es := ast.new(ast.Expr_Stmt, ce.pos, ce.end) + es := ast.new(ast.Expr_Stmt, ce.pos, ce) es.expr = ce return es case "force_inline", "force_no_inline": expr := parse_inlining_operand(p, true, tag) - es := ast.new(ast.Expr_Stmt, expr.pos, expr.end) + es := ast.new(ast.Expr_Stmt, expr.pos, expr) es.expr = expr return es case "unroll": @@ -1436,7 +1456,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { } range.reverse = true } else { - error(p, range.pos, "#reverse can only be applied to a 'for in' statement") + error(p, stmt.pos, "#reverse can only be applied to a 'for in' statement") } return stmt case "include": @@ -1444,7 +1464,8 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag)) case: stmt := parse_stmt(p) - te := ast.new(ast.Tag_Stmt, tok.pos, stmt.pos) + end := stmt.pos if stmt != nil else end_pos(tok) + te := ast.new(ast.Tag_Stmt, tok.pos, end) te.op = tok te.name = name te.stmt = stmt @@ -1572,7 +1593,7 @@ convert_stmt_to_body :: proc(p: ^Parser, stmt: ^ast.Stmt) -> ^ast.Stmt { error(p, stmt.pos, "expected a non-empty statement") } - bs := ast.new(ast.Block_Stmt, stmt.pos, stmt.end) + bs := ast.new(ast.Block_Stmt, stmt.pos, stmt) bs.open = stmt.pos bs.stmts = make([]^ast.Stmt, 1) bs.stmts[0] = stmt @@ -1741,7 +1762,7 @@ parse_var_type :: proc(p: ^Parser, flags: ast.Field_Flags) -> ^ast.Expr { error(p, tok.pos, "variadic field missing type after '..'") type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok)) } - e := ast.new(ast.Ellipsis, type.pos, type.end) + e := ast.new(ast.Ellipsis, type.pos, type) e.expr = type return e } @@ -1808,7 +1829,7 @@ parse_ident_list :: proc(p: ^Parser, allow_poly_names: bool) -> []^ast.Expr { if is_blank_ident(ident) { error(p, ident.pos, "invalid polymorphic type definition with a blank identifier") } - poly_name := ast.new(ast.Poly_Type, tok.pos, ident.end) + poly_name := ast.new(ast.Poly_Type, tok.pos, ident) poly_name.type = ident append(&list, poly_name) } else { @@ -2092,7 +2113,7 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type { expect_token(p, .Open_Paren) params, _ := parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Params) - expect_token(p, .Close_Paren) + expect_closing_parentheses_of_field_list(p) results, diverging := parse_results(p) is_generic := false @@ -2154,7 +2175,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ e.inlining = pi case: error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text) - return ast.new(ast.Bad_Expr, tok.pos, expr.end) + return ast.new(ast.Bad_Expr, tok.pos, expr) } return expr } @@ -2204,7 +2225,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Distinct: tok := advance_token(p) type := parse_type(p) - dt := ast.new(ast.Distinct_Type, tok.pos, type.end) + dt := ast.new(ast.Distinct_Type, tok.pos, type) dt.tok = tok.kind dt.type = type return dt @@ -2215,7 +2236,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { switch name.text { case "type": type := parse_type(p) - hp := ast.new(ast.Helper_Type, tok.pos, type.end) + hp := ast.new(ast.Helper_Type, tok.pos, type) hp.tok = tok.kind hp.type = type return hp @@ -2319,7 +2340,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { tag_call := parse_call_expr(p, tag) type := parse_type(p) - rt := ast.new(ast.Relative_Type, tok.pos, type.end) + rt := ast.new(ast.Relative_Type, tok.pos, type) rt.tag = tag_call rt.type = type return rt @@ -2328,7 +2349,8 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { return parse_inlining_operand(p, lhs, name) case: expr := parse_expr(p, lhs) - te := ast.new(ast.Tag_Expr, tok.pos, expr.pos) + end := expr.pos if expr != nil else end_pos(tok) + te := ast.new(ast.Tag_Expr, tok.pos, end) te.op = tok te.name = name.text te.expr = expr @@ -2456,7 +2478,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Pointer: tok := expect_token(p, .Pointer) elem := parse_type(p) - ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end) + ptr := ast.new(ast.Pointer_Type, tok.pos, elem) ptr.pointer = tok.pos ptr.elem = elem return ptr @@ -2470,7 +2492,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { tok := expect_token(p, .Pointer) close := expect_token(p, .Close_Bracket) elem := parse_type(p) - t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end) + t := ast.new(ast.Multi_Pointer_Type, open.pos, elem) t.open = open.pos t.pointer = tok.pos t.close = close.pos @@ -2480,7 +2502,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { tok := expect_token(p, .Dynamic) close := expect_token(p, .Close_Bracket) elem := parse_type(p) - da := ast.new(ast.Dynamic_Array_Type, open.pos, elem.end) + da := ast.new(ast.Dynamic_Array_Type, open.pos, elem) da.open = open.pos da.dynamic_pos = tok.pos da.close = close.pos @@ -2500,7 +2522,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { } close := expect_token(p, .Close_Bracket) elem := parse_type(p) - at := ast.new(ast.Array_Type, open.pos, elem.end) + at := ast.new(ast.Array_Type, open.pos, elem) at.open = open.pos at.len = count at.close = close.pos @@ -2514,7 +2536,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { expect_token(p, .Close_Bracket) value := parse_type(p) - mt := ast.new(ast.Map_Type, tok.pos, value.end) + mt := ast.new(ast.Map_Type, tok.pos, value) mt.tok_pos = tok.pos mt.key = key mt.value = value @@ -2755,7 +2777,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { expect_token(p, .Close_Bracket) elem := parse_type(p) - mt := ast.new(ast.Matrix_Type, tok.pos, elem.end) + mt := ast.new(ast.Matrix_Type, tok.pos, elem) mt.tok_pos = tok.pos mt.row_count = row_count mt.column_count = column_count @@ -2893,7 +2915,7 @@ parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr { eq := expect_token(p, .Eq) value := parse_value(p) - fv := ast.new(ast.Field_Value, elem.pos, value.end) + fv := ast.new(ast.Field_Value, elem.pos, value) fv.field = elem fv.sep = eq.pos fv.value = value @@ -2962,7 +2984,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { } value := parse_value(p) - fv := ast.new(ast.Field_Value, arg.pos, value.end) + fv := ast.new(ast.Field_Value, arg.pos, value) fv.field = arg fv.sep = eq.pos fv.value = value @@ -2993,7 +3015,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { o := ast.unparen_expr(operand) if se, ok := o.derived.(^ast.Selector_Expr); ok && se.op.kind == .Arrow_Right { - sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end) + sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce) sce.expr = o sce.call = ce return sce @@ -3101,7 +3123,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a case .Ident: field := parse_ident(p) - sel := ast.new(ast.Selector_Expr, operand.pos, field.end) + sel := ast.new(ast.Selector_Expr, operand.pos, field) sel.expr = operand sel.op = tok sel.field = field @@ -3127,7 +3149,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a type.op = question type.expr = nil - ta := ast.new(ast.Type_Assertion, operand.pos, type.end) + ta := ast.new(ast.Type_Assertion, operand.pos, type) ta.expr = operand ta.type = type @@ -3145,7 +3167,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a case .Ident: field := parse_ident(p) - sel := ast.new(ast.Selector_Expr, operand.pos, field.end) + sel := ast.new(ast.Selector_Expr, operand.pos, field) sel.expr = operand sel.op = tok sel.field = field @@ -3225,7 +3247,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { close := expect_token(p, .Close_Paren) expr := parse_unary_expr(p, lhs) - tc := ast.new(ast.Type_Cast, tok.pos, expr.end) + tc := ast.new(ast.Type_Cast, tok.pos, expr) tc.tok = tok tc.open = open.pos tc.type = type @@ -3237,7 +3259,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { op := advance_token(p) expr := parse_unary_expr(p, lhs) - ac := ast.new(ast.Auto_Cast, op.pos, expr.end) + ac := ast.new(ast.Auto_Cast, op.pos, expr) ac.op = op ac.expr = expr return ac @@ -3247,8 +3269,8 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { .And: op := advance_token(p) expr := parse_unary_expr(p, lhs) - - ue := ast.new(ast.Unary_Expr, op.pos, expr.end) + + ue := ast.new(ast.Unary_Expr, op.pos, expr) ue.op = op ue.expr = expr return ue @@ -3258,7 +3280,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { error(p, op.pos, "unary '%s' operator is not supported", op.text) expr := parse_unary_expr(p, lhs) - ue := ast.new(ast.Unary_Expr, op.pos, expr.end) + ue := ast.new(ast.Unary_Expr, op.pos, expr) ue.op = op ue.expr = expr return ue @@ -3266,7 +3288,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Period: op := advance_token(p) field := parse_ident(p) - ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end) + ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field) ise.field = field return ise @@ -3407,7 +3429,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt { error(p, p.curr_tok.pos, "no right-hand side in assignment statement") return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok)) } - stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end) + stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1]) stmt.lhs = lhs stmt.op = op stmt.rhs = rhs @@ -3424,7 +3446,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt { rhs := make([]^ast.Expr, 1) rhs[0] = expr - stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end) + stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1]) stmt.lhs = lhs stmt.op = op stmt.rhs = rhs @@ -3466,7 +3488,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt { error(p, op.pos, "postfix '%s' statement is not supported", op.text) } - es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0].end) + es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0]) es.expr = lhs[0] return es } diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin index 9d62014af..0b0baeea3 100644 --- a/core/os/file_windows.odin +++ b/core/os/file_windows.odin @@ -149,7 +149,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) { return } -read :: proc(fd: Handle, data: []byte) -> (int, Errno) { +read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Errno) { if len(data) == 0 { return 0, ERROR_NONE } @@ -158,32 +158,32 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) { m: u32 is_console := win32.GetConsoleMode(handle, &m) - - single_read_length: win32.DWORD - total_read: int length := len(data) // NOTE(Jeroen): `length` can't be casted to win32.DWORD here because it'll overflow if > 4 GiB and return 0 if exactly that. to_read := min(i64(length), MAX_RW) - e: win32.BOOL if is_console { - n, err := read_console(handle, data[total_read:][:to_read]) - total_read += n + total_read, err = read_console(handle, data[total_read:][:to_read]) if err != 0 { - return int(total_read), err + return total_read, err } } else { // NOTE(Jeroen): So we cast it here *after* we've ensured that `to_read` is at most MAX_RW (1 GiB) - e = win32.ReadFile(handle, &data[total_read], win32.DWORD(to_read), &single_read_length, nil) + bytes_read: win32.DWORD + if e := win32.ReadFile(handle, &data[total_read], win32.DWORD(to_read), &bytes_read, nil); e { + // Successful read can mean two things, including EOF, see: + // https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file + if bytes_read == 0 { + return 0, ERROR_HANDLE_EOF + } else { + return int(bytes_read), ERROR_NONE + } + } else { + return 0, Errno(win32.GetLastError()) + } } - if single_read_length <= 0 || !e { - err := Errno(win32.GetLastError()) - return int(total_read), err - } - total_read += int(single_read_length) - - return int(total_read), ERROR_NONE + return total_read, ERROR_NONE } seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { diff --git a/core/os/os.odin b/core/os/os.odin index 15864e47e..3210a39d0 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -210,15 +210,15 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, } } - aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> (new_memory: []byte, err: mem.Allocator_Error) { + aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: mem.Allocator_Error) { if p == nil { return nil, nil } - new_memory = aligned_alloc(new_size, new_alignment, p) or_return + new_memory = aligned_alloc(new_size, new_alignment, p, zero_memory) or_return // NOTE: heap_resize does not zero the new memory, so we do it - if new_size > old_size { + if zero_memory && new_size > old_size { new_region := mem.raw_data(new_memory[old_size:]) mem.zero(new_region, new_size - old_size) } @@ -235,16 +235,16 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case .Free_All: return nil, .Mode_Not_Implemented - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_memory == nil { - return aligned_alloc(size, alignment) + return aligned_alloc(size, alignment, nil, mode == .Resize) } - return aligned_resize(old_memory, old_size, size, alignment) + return aligned_resize(old_memory, old_size, size, alignment, mode == .Resize) case .Query_Features: set := (^mem.Allocator_Mode_Set)(old_memory) if set != nil { - set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Query_Features} + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features} } return nil, nil diff --git a/core/os/os2/heap_windows.odin b/core/os/os2/heap_windows.odin index eba403c1d..4afc016a0 100644 --- a/core/os/os2/heap_windows.odin +++ b/core/os/os2/heap_windows.odin @@ -85,7 +85,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case .Free_All: return nil, .Mode_Not_Implemented - case .Resize: + case .Resize, .Resize_Non_Zeroed: if old_memory == nil { return aligned_alloc(size, alignment, true) } diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index aabf42574..298335ac9 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -263,26 +263,48 @@ Unix_File_Time :: struct { nanoseconds: i64, } -OS_Stat :: struct { - device_id: u64, // ID of device containing file - serial: u64, // File serial number - nlink: u64, // Number of hard links - mode: u32, // Mode of the file - uid: u32, // User ID of the file's owner - gid: u32, // Group ID of the file's group - _padding: i32, // 32 bits of padding - rdev: u64, // Device ID, if device - size: i64, // Size of the file, in bytes - block_size: i64, // Optimal bllocksize for I/O - blocks: i64, // Number of 512-byte blocks allocated +when ODIN_ARCH == .arm64 { + OS_Stat :: struct { + device_id: u64, // ID of device containing file + serial: u64, // File serial number + mode: u32, // Mode of the file + nlink: u32, // Number of hard links + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + rdev: u64, // Device ID, if device + _: u64, // Padding + size: i64, // Size of the file, in bytes + block_size: i32, // Optimal blocksize for I/O + _: i32, // Padding + blocks: i64, // Number of 512-byte blocks allocated - last_access: Unix_File_Time, // Time of last access - modified: Unix_File_Time, // Time of last modification - status_change: Unix_File_Time, // Time of last status change + last_access: Unix_File_Time, // Time of last access + modified: Unix_File_Time, // Time of last modification + status_change: Unix_File_Time, // Time of last status change - _reserve1, - _reserve2, - _reserve3: i64, + _reserved: [2]i32, + } + #assert(size_of(OS_Stat) == 128) +} else { + OS_Stat :: struct { + device_id: u64, // ID of device containing file + serial: u64, // File serial number + nlink: u64, // Number of hard links + mode: u32, // Mode of the file + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + _: i32, // 32 bits of padding + rdev: u64, // Device ID, if device + size: i64, // Size of the file, in bytes + block_size: i64, // Optimal bllocksize for I/O + blocks: i64, // Number of 512-byte blocks allocated + + last_access: Unix_File_Time, // Time of last access + modified: Unix_File_Time, // Time of last modification + status_change: Unix_File_Time, // Time of last status change + + _reserved: [3]i64, + } } // NOTE(laleksic, 2021-01-21): Comment and rename these to match OS_Stat above diff --git a/core/os/stream.odin b/core/os/stream.odin index 2b4c83663..a5132239f 100644 --- a/core/os/stream.odin +++ b/core/os/stream.odin @@ -27,9 +27,7 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, case .Read: n_int, os_err = read(fd, p) n = i64(n_int) - if os_err != 0 { - err = .Unknown - } + case .Read_At: when !(ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD) { n_int, os_err = read_at(fd, p, offset) @@ -57,6 +55,11 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, } } if err == nil && os_err != 0 { + when ODIN_OS == .Windows { + if os_err == ERROR_HANDLE_EOF { + return n, .EOF + } + } err = .Unknown } return diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 2d176f909..740482493 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -18,6 +18,7 @@ // This could change at a later date if the all these data structures are // implemented within the compiler rather than in this "preload" file // +//+no-instrumentation package runtime import "core:intrinsics" @@ -306,6 +307,7 @@ Allocator_Mode :: enum byte { Query_Features, Query_Info, Alloc_Non_Zeroed, + Resize_Non_Zeroed, } Allocator_Mode_Set :: distinct bit_set[Allocator_Mode] diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index a73a3d712..3f4ebbc74 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -109,7 +109,7 @@ remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_locatio // `pop` will remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. // -// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic. +// Note: If the dynamic array has no elements (`len(array) == 0`), this procedure will panic. @builtin pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { assert(len(array) > 0, loc=loc) @@ -169,10 +169,16 @@ clear :: proc{clear_dynamic_array, clear_map} @builtin reserve :: proc{reserve_dynamic_array, reserve_map} -// `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). +@builtin +non_zero_reserve :: proc{non_zero_reserve_dynamic_array} + +// `resize` will try to resize memory of a passed dynamic array to the requested element count (setting the `len`, and possibly `cap`). @builtin resize :: proc{resize_dynamic_array} +@builtin +non_zero_resize :: proc{non_zero_resize_dynamic_array} + // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity. @builtin shrink :: proc{shrink_dynamic_array, shrink_map} @@ -234,6 +240,8 @@ delete :: proc{ delete_dynamic_array, delete_slice, delete_map, + delete_soa_slice, + delete_soa_dynamic_array, } @@ -346,7 +354,7 @@ make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := con // // Similar to `new`, the first argument is a type, not a value. Unlike new, make's return type is the same as the // type of its argument, not a pointer to it. -// Make uses the specified allocator, default is context.allocator, default is context.allocator +// Make uses the specified allocator, default is context.allocator. @builtin make :: proc{ make_slice, @@ -404,10 +412,7 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: return } - - -@builtin -append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +_append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return 0, nil } @@ -418,7 +423,13 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> } else { if cap(array) < len(array)+1 { cap := 2 * cap(array) + max(8, 1) - err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success + + // do not 'or_return' here as it could be a partial success + if should_zero { + err = reserve(array, cap, loc) + } else { + err = non_zero_reserve(array, cap, loc) + } } if cap(array)-len(array) > 0 { a := (^Raw_Dynamic_Array)(array) @@ -435,7 +446,16 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> } @builtin -append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + return _append_elem(array, arg, true, loc=loc) +} + +@builtin +non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + return _append_elem(array, arg, false, loc=loc) +} + +_append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, loc := #caller_location, args: ..E) -> (n: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return 0, nil } @@ -452,7 +472,13 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) } else { if cap(array) < len(array)+arg_len { cap := 2 * cap(array) + max(8, arg_len) - err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success + + // do not 'or_return' here as it could be a partial success + if should_zero { + err = reserve(array, cap, loc) + } else { + err = non_zero_reserve(array, cap, loc) + } } arg_len = min(cap(array)-len(array), arg_len) if arg_len > 0 { @@ -468,11 +494,33 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) } } +@builtin +append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + return _append_elems(array, true, loc, ..args) +} + +@builtin +non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + return _append_elems(array, false, loc, ..args) +} + // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type +_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + args := transmute([]E)arg + if should_zero { + return append_elems(array, ..args, loc=loc) + } else { + return non_zero_append_elems(array, ..args, loc=loc) + } +} + @builtin append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { - args := transmute([]E)arg - return append_elems(array, ..args, loc=loc) + return _append_elem_string(array, arg, true, loc) +} +@builtin +non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { + return _append_elem_string(array, arg, false, loc) } @@ -492,6 +540,7 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_ // The append built-in procedure appends elements to the end of a dynamic array @builtin append :: proc{append_elem, append_elems, append_elem_string} +@builtin non_zero_append :: proc{non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string} @builtin @@ -587,11 +636,14 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle @builtin assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { - if index+len(args) < len(array) { + new_size := index + len(args) + if len(args) == 0 { + ok = true + } else if new_size < len(array) { copy(array[index:], args) ok = true } else { - resize(array, index+1+len(args), loc) or_return + resize(array, new_size, loc) or_return copy(array[index:], args) ok = true } @@ -633,8 +685,7 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) { // `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). // // Note: Prefer the procedure group `reserve`. -@builtin -reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { +_reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { if array == nil { return nil } @@ -653,7 +704,12 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal new_size := capacity * size_of(E) allocator := a.allocator - new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + new_data: []byte + if should_zero { + new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + } else { + new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + } if new_data == nil && new_size > 0 { return .Out_Of_Memory } @@ -663,11 +719,20 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal return nil } +@builtin +reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { + return _reserve_dynamic_array(array, capacity, true, loc) +} + +@builtin +non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { + return _reserve_dynamic_array(array, capacity, false, loc) +} + // `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). // // Note: Prefer the procedure group `resize` -@builtin -resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { +_resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { if array == nil { return nil } @@ -687,7 +752,12 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller new_size := length * size_of(E) allocator := a.allocator - new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + new_data : []byte + if should_zero { + new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + } else { + new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return + } if new_data == nil && new_size > 0 { return .Out_Of_Memory } @@ -698,6 +768,16 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller return nil } +@builtin +resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { + return _resize_dynamic_array(array, length, true, loc=loc) +} + +@builtin +non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { + return _resize_dynamic_array(array, length, false, loc=loc) +} + /* Shrinks the capacity of a dynamic array down to the current length, or the given capacity. diff --git a/core/runtime/core_builtin_soa.odin b/core/runtime/core_builtin_soa.odin index f3882a9a8..6313a28f5 100644 --- a/core/runtime/core_builtin_soa.odin +++ b/core/runtime/core_builtin_soa.odin @@ -287,7 +287,7 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat footer := raw_soa_footer(array) if size_of(E) > 0 && cap(array)-len(array) > 0 { - ti := type_info_of(typeid_of(T)) + ti := type_info_of(T) ti = type_info_base(ti) si := &ti.variant.(Type_Info_Struct) field_count: uintptr diff --git a/core/runtime/default_allocators_arena.odin b/core/runtime/default_allocators_arena.odin index 1c36c4f7c..1fe3c6cfc 100644 --- a/core/runtime/default_allocators_arena.odin +++ b/core/runtime/default_allocators_arena.odin @@ -28,11 +28,11 @@ safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) { } @(require_results) -memory_block_alloc :: proc(allocator: Allocator, capacity: uint, loc := #caller_location) -> (block: ^Memory_Block, err: Allocator_Error) { - total_size := uint(capacity + size_of(Memory_Block)) - base_offset := uintptr(size_of(Memory_Block)) +memory_block_alloc :: proc(allocator: Allocator, capacity: uint, alignment: uint, loc := #caller_location) -> (block: ^Memory_Block, err: Allocator_Error) { + total_size := uint(capacity + max(alignment, size_of(Memory_Block))) + base_offset := uintptr(max(alignment, size_of(Memory_Block))) - min_alignment: int = max(16, align_of(Memory_Block)) + min_alignment: int = max(16, align_of(Memory_Block), int(alignment)) data := mem_alloc(int(total_size), min_alignment, allocator, loc) or_return block = (^Memory_Block)(raw_data(data)) end := uintptr(raw_data(data)[len(data):]) @@ -102,20 +102,20 @@ arena_alloc :: proc(arena: ^Arena, size, alignment: uint, loc := #caller_locatio if size == 0 { return } - - if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.capacity { - size = align_forward_uint(size, alignment) + + needed := align_forward_uint(size, alignment) + if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.capacity { if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE } - block_size := max(size, arena.minimum_block_size) + block_size := max(needed, arena.minimum_block_size) if arena.backing_allocator.procedure == nil { arena.backing_allocator = default_allocator() } - new_block := memory_block_alloc(arena.backing_allocator, block_size, loc) or_return + new_block := memory_block_alloc(arena.backing_allocator, block_size, alignment, loc) or_return new_block.prev = arena.curr_block arena.curr_block = new_block arena.total_capacity += new_block.capacity @@ -134,7 +134,7 @@ arena_init :: proc(arena: ^Arena, size: uint, backing_allocator: Allocator, loc arena^ = {} arena.backing_allocator = backing_allocator arena.minimum_block_size = max(size, 1<<12) // minimum block size of 4 KiB - new_block := memory_block_alloc(arena.backing_allocator, arena.minimum_block_size, loc) or_return + new_block := memory_block_alloc(arena.backing_allocator, arena.minimum_block_size, 0, loc) or_return arena.curr_block = new_block arena.total_capacity += new_block.capacity return nil @@ -195,7 +195,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, err = .Mode_Not_Implemented case .Free_All: arena_free_all(arena, location) - case .Resize: + case .Resize, .Resize_Non_Zeroed: old_data := ([^]byte)(old_memory) switch { diff --git a/core/runtime/default_allocators_nil.odin b/core/runtime/default_allocators_nil.odin index a340050eb..c882f5196 100644 --- a/core/runtime/default_allocators_nil.odin +++ b/core/runtime/default_allocators_nil.odin @@ -10,7 +10,7 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, .None case .Free_All: return nil, .Mode_Not_Implemented - case .Resize: + case .Resize, .Resize_Non_Zeroed: if size == 0 { return nil, .None } @@ -35,7 +35,7 @@ nil_allocator :: proc() -> Allocator { when ODIN_OS == .Freestanding { default_allocator_proc :: nil_allocator_proc default_allocator :: nil_allocator -} +} @@ -55,6 +55,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if size > 0 { panic("panic allocator, .Resize called", loc=loc) } + case .Resize_Non_Zeroed: + if size > 0 { + panic("panic allocator, .Alloc_Non_Zeroed called", loc=loc) + } case .Free: if old_memory != nil { panic("panic allocator, .Free called", loc=loc) @@ -78,9 +82,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, panic_allocator :: proc() -> Allocator { return Allocator{ - procedure = nil_allocator_proc, + procedure = panic_allocator_proc, data = nil, } } - - diff --git a/core/runtime/default_allocators_windows.odin b/core/runtime/default_allocators_windows.odin index a78a4d04e..1b0f78428 100644 --- a/core/runtime/default_allocators_windows.odin +++ b/core/runtime/default_allocators_windows.odin @@ -19,7 +19,7 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR { case .Free_All: return nil, .Mode_Not_Implemented - case .Resize: + case .Resize, .Resize_Non_Zeroed: data, err = _windows_default_resize(old_memory, old_size, size, alignment) case .Query_Features: @@ -41,4 +41,4 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR { data = nil, } } -} \ No newline at end of file +} diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index bdf0979cb..491a7974d 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -44,7 +44,7 @@ _ :: intrinsics MAP_LOAD_FACTOR :: 75 // Minimum log2 capacity. -MAP_MIN_LOG2_CAPACITY :: 6 // 64 elements +MAP_MIN_LOG2_CAPACITY :: 3 // 8 elements // Has to be less than 100% though. #assert(MAP_LOAD_FACTOR < 100) diff --git a/core/runtime/entry_unix.odin b/core/runtime/entry_unix.odin index 0c718445a..f494a509e 100644 --- a/core/runtime/entry_unix.odin +++ b/core/runtime/entry_unix.odin @@ -1,5 +1,6 @@ //+private //+build linux, darwin, freebsd, openbsd +//+no-instrumentation package runtime import "core:intrinsics" @@ -26,8 +27,13 @@ when ODIN_BUILD_MODE == .Dynamic { // to retrieve argc and argv from the stack when ODIN_ARCH == .amd64 { @require foreign import entry "entry_unix_no_crt_amd64.asm" + SYS_exit :: 60 } else when ODIN_ARCH == .i386 { @require foreign import entry "entry_unix_no_crt_i386.asm" + SYS_exit :: 1 + } else when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 { + @require foreign import entry "entry_unix_no_crt_darwin_arm64.asm" + SYS_exit :: 1 } @(link_name="_start_odin", linkage="strong", require) _start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! { @@ -36,11 +42,7 @@ when ODIN_BUILD_MODE == .Dynamic { #force_no_inline _startup_runtime() intrinsics.__entry_point() #force_no_inline _cleanup_runtime() - when ODIN_ARCH == .amd64 { - intrinsics.syscall(/*SYS_exit = */60) - } else when ODIN_ARCH == .i386 { - intrinsics.syscall(/*SYS_exit = */1) - } + intrinsics.syscall(SYS_exit, 0) unreachable() } } else { diff --git a/core/runtime/entry_unix_no_crt_darwin_arm64.asm b/core/runtime/entry_unix_no_crt_darwin_arm64.asm new file mode 100644 index 000000000..0f71fbdf8 --- /dev/null +++ b/core/runtime/entry_unix_no_crt_darwin_arm64.asm @@ -0,0 +1,20 @@ + .section __TEXT,__text + + ; NOTE(laytan): this should ideally be the -minimum-os-version flag but there is no nice way of preprocessing assembly in Odin. + ; 10 seems to be the lowest it goes and I don't see it mess with any targeted os version so this seems fine. + .build_version macos, 10, 0 + + .extern __start_odin + + .global _main + .align 2 +_main: + mov x5, sp ; use x5 as the stack pointer + + str x0, [x5] ; get argc into x0 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment) + str x1, [x5, #8] ; get argv into x1 + + and sp, x5, #~15 ; force 16-byte alignment of the stack + + bl __start_odin ; call into Odin entry point + ret ; should never get here diff --git a/core/runtime/entry_wasm.odin b/core/runtime/entry_wasm.odin index 235d5611b..e7f3f156f 100644 --- a/core/runtime/entry_wasm.odin +++ b/core/runtime/entry_wasm.odin @@ -1,5 +1,6 @@ //+private //+build wasm32, wasm64p32 +//+no-instrumentation package runtime import "core:intrinsics" diff --git a/core/runtime/entry_windows.odin b/core/runtime/entry_windows.odin index a315c1209..b6fbe1dcc 100644 --- a/core/runtime/entry_windows.odin +++ b/core/runtime/entry_windows.odin @@ -1,12 +1,13 @@ //+private //+build windows +//+no-instrumentation package runtime import "core:intrinsics" when ODIN_BUILD_MODE == .Dynamic { @(link_name="DllMain", linkage="strong", require) - DllMain :: proc "stdcall" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 { + DllMain :: proc "system" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 { context = default_context() // Populate Windows DLL-specific global @@ -28,7 +29,7 @@ when ODIN_BUILD_MODE == .Dynamic { } else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT { when ODIN_ARCH == .i386 || ODIN_NO_CRT { @(link_name="mainCRTStartup", linkage="strong", require) - mainCRTStartup :: proc "stdcall" () -> i32 { + mainCRTStartup :: proc "system" () -> i32 { context = default_context() #force_no_inline _startup_runtime() intrinsics.__entry_point() diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index 9d484979a..ea6333c29 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -1,5 +1,6 @@ package runtime +@(no_instrumentation) bounds_trap :: proc "contextless" () -> ! { when ODIN_OS == .Windows { windows_trap_array_bounds() @@ -8,6 +9,7 @@ bounds_trap :: proc "contextless" () -> ! { } } +@(no_instrumentation) type_assertion_trap :: proc "contextless" () -> ! { when ODIN_OS == .Windows { windows_trap_type_assertion() @@ -21,7 +23,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index if uint(index) < uint(count) { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Index ") @@ -34,6 +36,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index handle_error(file, line, column, index, count) } +@(no_instrumentation) slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid slice indices ") @@ -46,6 +49,7 @@ slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, h bounds_trap() } +@(no_instrumentation) multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid slice indices ") @@ -82,7 +86,7 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, if 0 <= low && low <= high && high <= max { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid dynamic array indices ") @@ -103,7 +107,7 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32 uint(column_index) < uint(column_count) { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Matrix indices [") @@ -127,7 +131,7 @@ when ODIN_NO_RTTI { if ok { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion\n") @@ -140,7 +144,7 @@ when ODIN_NO_RTTI { if ok { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion\n") @@ -153,7 +157,7 @@ when ODIN_NO_RTTI { if ok { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion from ") @@ -198,7 +202,7 @@ when ODIN_NO_RTTI { return id } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! { actual := variant_type(from, from_data) @@ -224,7 +228,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio if 0 <= len { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) -> ! { print_caller_location(loc) print_string(" Invalid slice length for make: ") @@ -239,7 +243,7 @@ make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller if 0 <= len && len <= cap { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) -> ! { print_caller_location(loc) print_string(" Invalid dynamic array parameters for make: ") @@ -256,7 +260,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca if 0 <= cap { return } - @(cold) + @(cold, no_instrumentation) handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) -> ! { print_caller_location(loc) print_string(" Invalid map capacity for make: ") diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index d0e550743..d4c43ed7e 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -187,7 +187,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle return } -mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { +_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { if allocator.procedure == nil { return nil, nil } @@ -198,15 +198,27 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL } return } else if ptr == nil { - return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + if should_zero { + return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + } else { + return allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc) + } } else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 { data = ([^]byte)(ptr)[:old_size] return } - data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc) + if should_zero { + data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc) + } else { + data, err = allocator.procedure(allocator.data, .Resize_Non_Zeroed, new_size, alignment, ptr, old_size, loc) + } if err == .Mode_Not_Implemented { - data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + if should_zero { + data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + } else { + data, err = allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc) + } if err != nil { return } @@ -216,6 +228,13 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL return } +mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { + return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc) +} +non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { + return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc) +} + memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { switch { case n == 0: return true @@ -730,7 +749,7 @@ mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 { t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { @@ -742,7 +761,7 @@ mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { @@ -754,7 +773,7 @@ mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1 t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 { @@ -768,7 +787,7 @@ quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 { t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { @@ -782,7 +801,7 @@ quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 { t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { @@ -796,7 +815,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2 t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2 - return quaternion(t0, t1, t2, t3) + return quaternion(w=t0, x=t1, y=t2, z=t3) } @(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) diff --git a/core/runtime/os_specific_any.odin b/core/runtime/os_specific_any.odin index afa106138..6a96655c4 100644 --- a/core/runtime/os_specific_any.odin +++ b/core/runtime/os_specific_any.odin @@ -1,4 +1,8 @@ -//+build !freestanding !wasi !windows !js +//+build !darwin +//+build !freestanding +//+build !js +//+build !wasi +//+build !windows package runtime import "core:os" diff --git a/core/runtime/os_specific_darwin.odin b/core/runtime/os_specific_darwin.odin new file mode 100644 index 000000000..5de9a7d57 --- /dev/null +++ b/core/runtime/os_specific_darwin.odin @@ -0,0 +1,12 @@ +//+build darwin +package runtime + +import "core:intrinsics" + +_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { + ret := intrinsics.syscall(0x2000004, 1, uintptr(raw_data(data)), uintptr(len(data))) + if ret < 0 { + return 0, _OS_Errno(-ret) + } + return int(ret), 0 +} diff --git a/core/runtime/os_specific_windows.odin b/core/runtime/os_specific_windows.odin index 9f001fa5a..4a5907466 100644 --- a/core/runtime/os_specific_windows.odin +++ b/core/runtime/os_specific_windows.odin @@ -4,7 +4,7 @@ package runtime foreign import kernel32 "system:Kernel32.lib" @(private="file") -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { // NOTE(bill): The types are not using the standard names (e.g. DWORD and LPVOID) to just minimizing the dependency diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index 1592c608b..454574c35 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -4,7 +4,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { foreign import lib "system:NtDll.lib" @(private="file") - @(default_calling_convention="stdcall") + @(default_calling_convention="system") foreign lib { RtlMoveMemory :: proc(dst, s: rawptr, length: int) --- RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- @@ -37,7 +37,18 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { } return ptr } - + + @(link_name="bzero", linkage="strong", require) + bzero :: proc "c" (ptr: rawptr, len: int) -> rawptr { + if ptr != nil && len != 0 { + p := ([^]byte)(ptr) + for i := 0; i < len; i += 1 { + p[i] = 0 + } + } + return ptr + } + @(link_name="memmove", linkage="strong", require) memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { d, s := ([^]byte)(dst), ([^]byte)(src) diff --git a/core/runtime/procs_windows_amd64.odin b/core/runtime/procs_windows_amd64.odin index e430357be..ea495f5fa 100644 --- a/core/runtime/procs_windows_amd64.odin +++ b/core/runtime/procs_windows_amd64.odin @@ -1,11 +1,12 @@ //+private +//+no-instrumentation package runtime foreign import kernel32 "system:Kernel32.lib" @(private) foreign kernel32 { - RaiseException :: proc "stdcall" (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: u32, lpArguments: ^uint) -> ! --- + RaiseException :: proc "system" (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: u32, lpArguments: ^uint) -> ! --- } windows_trap_array_bounds :: proc "contextless" () -> ! { diff --git a/core/runtime/procs_windows_i386.odin b/core/runtime/procs_windows_i386.odin index f810197f1..10422cf07 100644 --- a/core/runtime/procs_windows_i386.odin +++ b/core/runtime/procs_windows_i386.odin @@ -1,4 +1,5 @@ //+private +//+no-instrumentation package runtime @require foreign import "system:int64.lib" @@ -12,7 +13,7 @@ windows_trap_array_bounds :: proc "contextless" () -> ! { EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C foreign kernel32 { - RaiseException :: proc "stdcall" (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! --- + RaiseException :: proc "system" (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! --- } RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, nil) diff --git a/core/simd/x86/adx.odin b/core/simd/x86/adx.odin index d03cffcff..5750ae627 100644 --- a/core/simd/x86/adx.odin +++ b/core/simd/x86/adx.odin @@ -37,7 +37,7 @@ when ODIN_ARCH == .amd64 { } } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.addcarry.32") llvm_addcarry_u32 :: proc(a: u8, b: u32, c: u32) -> (u8, u32) --- diff --git a/core/simd/x86/fxsr.odin b/core/simd/x86/fxsr.odin index cd78de7d4..a9213fed2 100644 --- a/core/simd/x86/fxsr.odin +++ b/core/simd/x86/fxsr.odin @@ -21,7 +21,7 @@ when ODIN_ARCH == .amd64 { } } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.fxsave") fxsave :: proc(p: rawptr) --- diff --git a/core/simd/x86/pclmulqdq.odin b/core/simd/x86/pclmulqdq.odin index 692fb7ce1..e827bf6b9 100644 --- a/core/simd/x86/pclmulqdq.odin +++ b/core/simd/x86/pclmulqdq.odin @@ -1,12 +1,12 @@ //+build i386, amd64 package simd_x86 -@(require_results, enable_target_feature="pclmulqdq") +@(require_results, enable_target_feature="pclmul") _mm_clmulepi64_si128 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i { return pclmulqdq(a, b, u8(IMM8)) } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.pclmulqdq") pclmulqdq :: proc(a, round_key: __m128i, #const imm8: u8) -> __m128i --- diff --git a/core/simd/x86/rdtsc.odin b/core/simd/x86/rdtsc.odin index 54024c3f2..8a8b13c4b 100644 --- a/core/simd/x86/rdtsc.odin +++ b/core/simd/x86/rdtsc.odin @@ -11,7 +11,7 @@ __rdtscp :: #force_inline proc "c" (aux: ^u32) -> u64 { return rdtscp(aux) } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.rdtsc") rdtsc :: proc() -> u64 --- diff --git a/core/simd/x86/sha.odin b/core/simd/x86/sha.odin index f015f4b8a..bc58e8504 100644 --- a/core/simd/x86/sha.odin +++ b/core/simd/x86/sha.odin @@ -30,7 +30,7 @@ _mm_sha256rnds2_epu32 :: #force_inline proc "c" (a, b, k: __m128i) -> __m128i { return transmute(__m128i)sha256rnds2(transmute(i32x4)a, transmute(i32x4)b, transmute(i32x4)k) } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.sha1msg1") sha1msg1 :: proc(a, b: i32x4) -> i32x4 --- diff --git a/core/simd/x86/sse.odin b/core/simd/x86/sse.odin index 2b70e954f..903a43dfd 100644 --- a/core/simd/x86/sse.odin +++ b/core/simd/x86/sse.odin @@ -532,7 +532,7 @@ when ODIN_ARCH == .amd64 { } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.sse.add.ss") addss :: proc(a, b: __m128) -> __m128 --- diff --git a/core/simd/x86/sse2.odin b/core/simd/x86/sse2.odin index dd292712f..a597122f1 100644 --- a/core/simd/x86/sse2.odin +++ b/core/simd/x86/sse2.odin @@ -1040,7 +1040,7 @@ when ODIN_ARCH == .amd64 { } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name="llvm.x86.sse2.pause") pause :: proc() --- diff --git a/core/simd/x86/sse3.odin b/core/simd/x86/sse3.odin index 7a3073c18..cf5f3b2fa 100644 --- a/core/simd/x86/sse3.odin +++ b/core/simd/x86/sse3.odin @@ -49,7 +49,7 @@ _mm_moveldup_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return simd.shuffle(a, a, 0, 0, 2, 2) } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name = "llvm.x86.sse3.addsub.ps") addsubps :: proc(a, b: __m128) -> __m128 --- diff --git a/core/simd/x86/sse41.odin b/core/simd/x86/sse41.odin index b35be33f2..8c306ba4c 100644 --- a/core/simd/x86/sse41.odin +++ b/core/simd/x86/sse41.odin @@ -291,7 +291,7 @@ when ODIN_ARCH == .amd64 { } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name = "llvm.x86.sse41.pblendvb") pblendvb :: proc(a, b: i8x16, mask: i8x16) -> i8x16 --- diff --git a/core/simd/x86/sse42.odin b/core/simd/x86/sse42.odin index 62b4f0478..621346342 100644 --- a/core/simd/x86/sse42.odin +++ b/core/simd/x86/sse42.odin @@ -104,7 +104,7 @@ when ODIN_ARCH == .amd64 { } } -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { // SSE 4.2 string and text comparison ops @(link_name="llvm.x86.sse42.pcmpestrm128") diff --git a/core/simd/x86/ssse3.odin b/core/simd/x86/ssse3.odin index f11ef6774..0264a1c93 100644 --- a/core/simd/x86/ssse3.odin +++ b/core/simd/x86/ssse3.odin @@ -105,7 +105,7 @@ _mm_sign_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { -@(private, default_calling_convention="c") +@(private, default_calling_convention="none") foreign _ { @(link_name = "llvm.x86.ssse3.pabs.b.128") pabsb128 :: proc(a: i8x16) -> u8x16 --- diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 107f48fb2..2a9e29d01 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -49,7 +49,7 @@ to_bytes :: proc "contextless" (s: []$T) -> []byte { ``` ``` small_items := []byte{1, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0} + 2, 0, 0, 0} large_items := slice.reinterpret([]i64, small_items) assert(len(large_items) == 1) // only enough bytes to make 1 x i64; two would need at least 8 bytes. ``` @@ -78,7 +78,7 @@ swap_between :: proc(a, b: $T/[]$E) { n := builtin.min(len(a), len(b)) if n >= 0 { ptr_swap_overlapping(&a[0], &b[0], size_of(E)*n) - } + } } @@ -117,46 +117,67 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f return -1, false } +/* + Binary search searches the given slice for the given element. + If the slice is not sorted, the returned index is unspecified and meaningless. + + If the value is found then the returned int is the index of the matching element. + If there are multiple matches, then any one of the matches could be returned. + + If the value is not found then the returned int is the index where a matching + element could be inserted while maintaining sorted order. + + # Examples + + Looks up a series of four elements. The first is found, with a + uniquely determined position; the second and third are not + found; the fourth could match any position in `[1, 4]`. + + ``` + index: int + found: bool + + s := []i32{0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55} + + index, found = slice.binary_search(s, 13) + assert(index == 9 && found == true) + + index, found = slice.binary_search(s, 4) + assert(index == 7 && found == false) + + index, found = slice.binary_search(s, 100) + assert(index == 13 && found == false) + + index, found = slice.binary_search(s, 1) + assert(index >= 1 && index <= 4 && found == true) + ``` + + For slices of more complex types see: binary_search_by +*/ @(require_results) binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) - where intrinsics.type_is_ordered(T) #no_bounds_check { - - n := len(array) - switch n { - case 0: - return -1, false - case 1: - if array[0] == key { - return 0, true - } - return -1, false - } - - lo, hi := 0, n-1 - - for array[hi] != array[lo] && key >= array[lo] && key <= array[hi] { - when intrinsics.type_is_ordered_numeric(T) { - // NOTE(bill): This is technically interpolation search - m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo])) - } else { - m := lo + (hi - lo)/2 - } - switch { - case array[m] < key: - lo = m + 1 - case key < array[m]: - hi = m - 1 - case: - return m, true - } - } - - if key == array[lo] { - return lo, true - } - return -1, false + where intrinsics.type_is_ordered(T) #no_bounds_check +{ + return binary_search_by(array, key, cmp_proc(T)) } +@(require_results) +binary_search_by :: proc(array: $A/[]$T, key: T, f: proc(T, T) -> Ordering) -> (index: int, found: bool) #no_bounds_check { + n := len(array) + left, right := 0, n + for left < right { + mid := int(uint(left+right) >> 1) + if f(array[mid], key) == .Less { + left = mid+1 + } else { + // .Equal or .Greater + right = mid + } + } + // left == right + // f(array[left-1], key) == .Less (if left > 0) + return left, left < n && f(array[left], key) == .Equal +} @(require_results) equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) { @@ -397,14 +418,35 @@ reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V { } @(require_results) -filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> S { - r := make([dynamic]U, 0, 0, allocator) +reduce_reverse :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V { + r := initializer + for i := len(s)-1; i >= 0; i -= 1 { + #no_bounds_check r = f(r, s[i]) + } + return r +} + +@(require_results) +filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { + r := make([dynamic]U, 0, 0, allocator) or_return for v in s { if f(v) { append(&r, v) } } - return r[:] + return r[:], nil +} + +@(require_results) +filter_reverse :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { + r := make([dynamic]U, 0, 0, allocator) or_return + for i := len(s)-1; i >= 0; i -= 1 { + #no_bounds_check v := s[i] + if f(v) { + append(&r, v) + } + } + return r[:], nil } @(require_results) @@ -427,6 +469,60 @@ scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := c } +@(require_results) +repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator) -> (b: S, err: runtime.Allocator_Error) #optional_allocator_error { + if count < 0 { + panic("slice: negative repeat count") + } else if count > 0 && (len(s)*count)/count != len(s) { + panic("slice: repeat count will cause an overflow") + } + + b = make(S, len(s)*count, allocator) or_return + i := copy(b, s) + for i < len(b) { // 2^N trick to reduce the need to copy + copy(b[i:], b[:i]) + i *= 2 + } + return +} + +// 'unique' replaces consecutive runs of equal elements with a single copy. +// The procedures modifies the slice in-place and returns the modified slice. +@(require_results) +unique :: proc(s: $S/[]$T) -> S where intrinsics.type_is_comparable(T) #no_bounds_check { + if len(s) < 2 { + return s + } + i := 1 + for j in 1.. bool) -> S #no_bounds_check { + if len(s) < 2 { + return s + } + i := 1 + for j in 1.. (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) != 0 { @@ -463,6 +559,40 @@ min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ return } +// Find the index of the (first) minimum element in a slice. +@(require_results) +min_index :: proc(s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { + if len(s) == 0 { + return -1, false + } + min_index = 0 + min_value := s[0] + for v, i in s[1:] { + if v < min_value { + min_value = v + min_index = i+1 + } + } + return min_index, true +} + +// Find the index of the (first) maximum element in a slice. +@(require_results) +max_index :: proc(s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { + if len(s) == 0 { + return -1, false + } + max_index = 0 + max_value := s[0] + for v, i in s[1:] { + if v > max_value { + max_value = v + max_index = i+1 + } + } + return max_index, true +} + @(require_results) any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { for v in s { diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 515eddcc3..3b4119afa 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -62,7 +62,7 @@ _sort_by_indices :: proc(data, sorted: $T/[]$E, indices: []int) { sort_by_indices_overwrite :: proc(data: $T/[]$E, indices: []int) { assert(len(data) == len(indices)) - temp := make([]int, len(data), context.allocator) + temp := make([]E, len(data), context.allocator) defer delete(temp) for v, i in indices { temp[i] = data[v] diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index 70febf832..4ad42a647 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -103,8 +103,11 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) } } else { switch fmt { - case 'e', 'E': decimal.round(d, prec+1) - case 'f', 'F': decimal.round(d, d.decimal_point+prec) + case 'e', 'E': + prec += 1 + decimal.round(d, prec) + case 'f', 'F': + decimal.round(d, d.decimal_point+prec) case 'g', 'G': if prec == 0 { prec = 1 diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 2f36eddbe..5cee25a66 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -885,6 +885,7 @@ Splits a string into parts based on a separator. If n < count of seperators, the Inputs: - s: The string to split. - sep: The separator string used to split the input string. +- n: The maximum amount of parts to split the string into. - allocator: (default is context.allocator) Returns: @@ -1791,7 +1792,8 @@ last_index_any :: proc(s, chars: string) -> (res: int) { if r >= utf8.RUNE_SELF { r = utf8.RUNE_ERROR } - return index_rune(chars, r) + i := index_rune(chars, r) + return i if i < 0 else 0 } if len(s) > 8 { diff --git a/core/sync/futex_windows.odin b/core/sync/futex_windows.odin index 8ddbef3ed..6a26baf5b 100644 --- a/core/sync/futex_windows.odin +++ b/core/sync/futex_windows.odin @@ -5,14 +5,14 @@ package sync import "core:time" foreign import Synchronization "system:Synchronization.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Synchronization { WakeByAddressSingle :: proc(Address: rawptr) --- WakeByAddressAll :: proc(Address: rawptr) --- } foreign import Ntdll "system:Ntdll.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Ntdll { RtlWaitOnAddress :: proc(Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> i32 --- RtlNtStatusToDosError :: proc(status: i32) -> u32 --- @@ -30,7 +30,7 @@ foreign Ntdll { GODDAMN MICROSOFT! */ -CustomWaitOnAddress :: proc "stdcall" (Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> bool { +CustomWaitOnAddress :: proc "system" (Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> bool { status := RtlWaitOnAddress(Address, CompareAddress, AddressSize, Timeout) if status != 0 { SetLastError(RtlNtStatusToDosError(status)) diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin index 5a11863d4..1344c3d2a 100644 --- a/core/sys/info/cpu_intel.odin +++ b/core/sys/info/cpu_intel.odin @@ -37,11 +37,11 @@ cpu_name: Maybe(string) @(init, private) init_cpu_features :: proc "c" () { - is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool { - return hwc&(1 << value) != 0 + is_set :: #force_inline proc "c" (bit: u32, value: u32) -> bool { + return (value>>bit) & 0x1 != 0 } - try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) { - if is_set(hwc, value) { + try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, bit: u32, value: u32) { + if is_set(bit, value) { set^ += {feature} } } diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin index 7a56f1e23..4ca542b7a 100644 --- a/core/sys/info/platform_darwin.odin +++ b/core/sys/info/platform_darwin.odin @@ -138,338 +138,388 @@ Darwin_To_Release :: struct { @(private) macos_release_map: map[string]Darwin_To_Release = { // MacOS Tiger - "8A428" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, - "8A432" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, - "8B15" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, - "8B17" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, - "8C46" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, - "8C47" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, - "8E102" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, - "8E45" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, - "8E90" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, - "8F46" = {{8, 3, 0}, "macOS", {"Tiger", {10, 4, 3}}}, - "8G32" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, - "8G1165" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, - "8H14" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, - "8G1454" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, - "8I127" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, - "8I1119" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, - "8J135" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, - "8J2135a" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, - "8K1079" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, - "8N5107" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, - "8L127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, - "8L2127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, - "8P135" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, - "8P2137" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, - "8R218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, - "8R2218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, - "8R2232" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, - "8S165" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, - "8S2167" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, + "8A428" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, + "8A432" = {{8, 0, 0}, "macOS", {"Tiger", {10, 4, 0}}}, + "8B15" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, + "8B17" = {{8, 1, 0}, "macOS", {"Tiger", {10, 4, 1}}}, + "8C46" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8C47" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E102" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E45" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8E90" = {{8, 2, 0}, "macOS", {"Tiger", {10, 4, 2}}}, + "8F46" = {{8, 3, 0}, "macOS", {"Tiger", {10, 4, 3}}}, + "8G32" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, + "8G1165" = {{8, 4, 0}, "macOS", {"Tiger", {10, 4, 4}}}, + "8H14" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, + "8G1454" = {{8, 5, 0}, "macOS", {"Tiger", {10, 4, 5}}}, + "8I127" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, + "8I1119" = {{8, 6, 0}, "macOS", {"Tiger", {10, 4, 6}}}, + "8J135" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8J2135a" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8K1079" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8N5107" = {{8, 7, 0}, "macOS", {"Tiger", {10, 4, 7}}}, + "8L127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, + "8L2127" = {{8, 8, 0}, "macOS", {"Tiger", {10, 4, 8}}}, + "8P135" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, + "8P2137" = {{8, 9, 0}, "macOS", {"Tiger", {10, 4, 9}}}, + "8R218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8R2218" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8R2232" = {{8, 10, 0}, "macOS", {"Tiger", {10, 4, 10}}}, + "8S165" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, + "8S2167" = {{8, 11, 0}, "macOS", {"Tiger", {10, 4, 11}}}, // MacOS Leopard - "9A581" = {{9, 0, 0}, "macOS", {"Leopard", {10, 5, 0}}}, - "9B18" = {{9, 1, 0}, "macOS", {"Leopard", {10, 5, 1}}}, - "9B2117" = {{9, 1, 1}, "macOS", {"Leopard", {10, 5, 1}}}, - "9C31" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, - "9C7010" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, - "9D34" = {{9, 3, 0}, "macOS", {"Leopard", {10, 5, 3}}}, - "9E17" = {{9, 4, 0}, "macOS", {"Leopard", {10, 5, 4}}}, - "9F33" = {{9, 5, 0}, "macOS", {"Leopard", {10, 5, 5}}}, - "9G55" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, - "9G66" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, - "9G71" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, - "9J61" = {{9, 7, 0}, "macOS", {"Leopard", {10, 5, 7}}}, - "9L30" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, - "9L34" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, + "9A581" = {{9, 0, 0}, "macOS", {"Leopard", {10, 5, 0}}}, + "9B18" = {{9, 1, 0}, "macOS", {"Leopard", {10, 5, 1}}}, + "9B2117" = {{9, 1, 1}, "macOS", {"Leopard", {10, 5, 1}}}, + "9C31" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, + "9C7010" = {{9, 2, 0}, "macOS", {"Leopard", {10, 5, 2}}}, + "9D34" = {{9, 3, 0}, "macOS", {"Leopard", {10, 5, 3}}}, + "9E17" = {{9, 4, 0}, "macOS", {"Leopard", {10, 5, 4}}}, + "9F33" = {{9, 5, 0}, "macOS", {"Leopard", {10, 5, 5}}}, + "9G55" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9G66" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9G71" = {{9, 6, 0}, "macOS", {"Leopard", {10, 5, 6}}}, + "9J61" = {{9, 7, 0}, "macOS", {"Leopard", {10, 5, 7}}}, + "9L30" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, + "9L34" = {{9, 8, 0}, "macOS", {"Leopard", {10, 5, 8}}}, // MacOS Snow Leopard - "10A432" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, - "10A433" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, - "10B504" = {{10, 1, 0}, "macOS", {"Snow Leopard", {10, 6, 1}}}, - "10C540" = {{10, 2, 0}, "macOS", {"Snow Leopard", {10, 6, 2}}}, - "10D573" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, - "10D575" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, - "10D578" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, - "10F569" = {{10, 4, 0}, "macOS", {"Snow Leopard", {10, 6, 4}}}, - "10H574" = {{10, 5, 0}, "macOS", {"Snow Leopard", {10, 6, 5}}}, - "10J567" = {{10, 6, 0}, "macOS", {"Snow Leopard", {10, 6, 6}}}, - "10J869" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, - "10J3250" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, - "10J4138" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, - "10K540" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, - "10K549" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, + "10A432" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, + "10A433" = {{10, 0, 0}, "macOS", {"Snow Leopard", {10, 6, 0}}}, + "10B504" = {{10, 1, 0}, "macOS", {"Snow Leopard", {10, 6, 1}}}, + "10C540" = {{10, 2, 0}, "macOS", {"Snow Leopard", {10, 6, 2}}}, + "10D573" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10D575" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10D578" = {{10, 3, 0}, "macOS", {"Snow Leopard", {10, 6, 3}}}, + "10F569" = {{10, 4, 0}, "macOS", {"Snow Leopard", {10, 6, 4}}}, + "10H574" = {{10, 5, 0}, "macOS", {"Snow Leopard", {10, 6, 5}}}, + "10J567" = {{10, 6, 0}, "macOS", {"Snow Leopard", {10, 6, 6}}}, + "10J869" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10J3250" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10J4138" = {{10, 7, 0}, "macOS", {"Snow Leopard", {10, 6, 7}}}, + "10K540" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, + "10K549" = {{10, 8, 0}, "macOS", {"Snow Leopard", {10, 6, 8}}}, // MacOS Lion - "11A511" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, - "11A511s" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, - "11A2061" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, - "11A2063" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, - "11B26" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, - "11B2118" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, - "11C74" = {{11, 2, 0}, "macOS", {"Lion", {10, 7, 2}}}, - "11D50" = {{11, 3, 0}, "macOS", {"Lion", {10, 7, 3}}}, - "11E53" = {{11, 4, 0}, "macOS", {"Lion", {10, 7, 4}}}, - "11G56" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, - "11G63" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, + "11A511" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, + "11A511s" = {{11, 0, 0}, "macOS", {"Lion", {10, 7, 0}}}, + "11A2061" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, + "11A2063" = {{11, 0, 2}, "macOS", {"Lion", {10, 7, 0}}}, + "11B26" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, + "11B2118" = {{11, 1, 0}, "macOS", {"Lion", {10, 7, 1}}}, + "11C74" = {{11, 2, 0}, "macOS", {"Lion", {10, 7, 2}}}, + "11D50" = {{11, 3, 0}, "macOS", {"Lion", {10, 7, 3}}}, + "11E53" = {{11, 4, 0}, "macOS", {"Lion", {10, 7, 4}}}, + "11G56" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, + "11G63" = {{11, 4, 2}, "macOS", {"Lion", {10, 7, 5}}}, // MacOS Mountain Lion - "12A269" = {{12, 0, 0}, "macOS", {"Mountain Lion", {10, 8, 0}}}, - "12B19" = {{12, 1, 0}, "macOS", {"Mountain Lion", {10, 8, 1}}}, - "12C54" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, - "12C60" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, - "12C2034" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, - "12C3104" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, - "12D78" = {{12, 3, 0}, "macOS", {"Mountain Lion", {10, 8, 3}}}, - "12E55" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, - "12E3067" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, - "12E4022" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, - "12F37" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, - "12F45" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, - "12F2501" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, - "12F2518" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, - "12F2542" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, - "12F2560" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12A269" = {{12, 0, 0}, "macOS", {"Mountain Lion", {10, 8, 0}}}, + "12B19" = {{12, 1, 0}, "macOS", {"Mountain Lion", {10, 8, 1}}}, + "12C54" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C60" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C2034" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12C3104" = {{12, 2, 0}, "macOS", {"Mountain Lion", {10, 8, 2}}}, + "12D78" = {{12, 3, 0}, "macOS", {"Mountain Lion", {10, 8, 3}}}, + "12E55" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12E3067" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12E4022" = {{12, 4, 0}, "macOS", {"Mountain Lion", {10, 8, 4}}}, + "12F37" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F45" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2501" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2518" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2542" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, + "12F2560" = {{12, 5, 0}, "macOS", {"Mountain Lion", {10, 8, 5}}}, // MacOS Mavericks - "13A603" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 0}}}, - "13B42" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 1}}}, - "13C64" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, - "13C1021" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, - "13D65" = {{13, 2, 0}, "macOS", {"Mavericks", {10, 9, 3}}}, - "13E28" = {{13, 3, 0}, "macOS", {"Mavericks", {10, 9, 4}}}, - "13F34" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1066" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1077" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1096" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1112" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1134" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1507" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1603" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1712" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1808" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, - "13F1911" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13A603" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 0}}}, + "13B42" = {{13, 0, 0}, "macOS", {"Mavericks", {10, 9, 1}}}, + "13C64" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, + "13C1021" = {{13, 1, 0}, "macOS", {"Mavericks", {10, 9, 2}}}, + "13D65" = {{13, 2, 0}, "macOS", {"Mavericks", {10, 9, 3}}}, + "13E28" = {{13, 3, 0}, "macOS", {"Mavericks", {10, 9, 4}}}, + "13F34" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1066" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1077" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1096" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1112" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1134" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1507" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1603" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1712" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1808" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, + "13F1911" = {{13, 4, 0}, "macOS", {"Mavericks", {10, 9, 5}}}, // MacOS Yosemite - "14A389" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 0}}}, - "14B25" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 1}}}, - "14C109" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, - "14C1510" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, - "14C2043" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, - "14C1514" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, - "14C2513" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, - "14D131" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, - "14D136" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, - "14E46" = {{14, 4, 0}, "macOS", {"Yosemite", {10, 10, 4}}}, - "14F27" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1021" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1505" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1509" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1605" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1713" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1808" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1909" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F1912" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F2009" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F2109" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F2315" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F2411" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, - "14F2511" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14A389" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 0}}}, + "14B25" = {{14, 0, 0}, "macOS", {"Yosemite", {10, 10, 1}}}, + "14C109" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C1510" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C2043" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C1514" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14C2513" = {{14, 1, 0}, "macOS", {"Yosemite", {10, 10, 2}}}, + "14D131" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, + "14D136" = {{14, 3, 0}, "macOS", {"Yosemite", {10, 10, 3}}}, + "14E46" = {{14, 4, 0}, "macOS", {"Yosemite", {10, 10, 4}}}, + "14F27" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1021" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1505" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1509" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1605" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1713" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1808" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1909" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F1912" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2009" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2109" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2315" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2411" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, + "14F2511" = {{14, 5, 0}, "macOS", {"Yosemite", {10, 10, 5}}}, // MacOS El Capitan - "15A284" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 0}}}, - "15B42" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 1}}}, - "15C50" = {{15, 2, 0}, "macOS", {"El Capitan", {10, 11, 2}}}, - "15D21" = {{15, 3, 0}, "macOS", {"El Capitan", {10, 11, 3}}}, - "15E65" = {{15, 4, 0}, "macOS", {"El Capitan", {10, 11, 4}}}, - "15F34" = {{15, 5, 0}, "macOS", {"El Capitan", {10, 11, 5}}}, - "15G31" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1004" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1011" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1108" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1212" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1217" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1421" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1510" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G1611" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G17023" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G18013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G19009" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G20015" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G21013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, - "15G22010" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15A284" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 0}}}, + "15B42" = {{15, 0, 0}, "macOS", {"El Capitan", {10, 11, 1}}}, + "15C50" = {{15, 2, 0}, "macOS", {"El Capitan", {10, 11, 2}}}, + "15D21" = {{15, 3, 0}, "macOS", {"El Capitan", {10, 11, 3}}}, + "15E65" = {{15, 4, 0}, "macOS", {"El Capitan", {10, 11, 4}}}, + "15F34" = {{15, 5, 0}, "macOS", {"El Capitan", {10, 11, 5}}}, + "15G31" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1004" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1011" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1108" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1212" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1217" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1421" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1510" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G1611" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G17023" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G18013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G19009" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G20015" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G21013" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, + "15G22010" = {{15, 6, 0}, "macOS", {"El Capitan", {10, 11, 6}}}, // MacOS Sierra - "16A323" = {{16, 0, 0}, "macOS", {"Sierra", {10, 12, 0}}}, - "16B2555" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, - "16B2657" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, - "16C67" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, - "16C68" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, - "16D32" = {{16, 4, 0}, "macOS", {"Sierra", {10, 12, 3}}}, - "16E195" = {{16, 5, 0}, "macOS", {"Sierra", {10, 12, 4}}}, - "16F73" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, - "16F2073" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, - "16G29" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1036" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1114" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1212" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1314" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1408" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1510" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1618" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1710" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1815" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1917" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G1918" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G2016" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G2127" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G2128" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, - "16G2136" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16A323" = {{16, 0, 0}, "macOS", {"Sierra", {10, 12, 0}}}, + "16B2555" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, + "16B2657" = {{16, 1, 0}, "macOS", {"Sierra", {10, 12, 1}}}, + "16C67" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, + "16C68" = {{16, 3, 0}, "macOS", {"Sierra", {10, 12, 2}}}, + "16D32" = {{16, 4, 0}, "macOS", {"Sierra", {10, 12, 3}}}, + "16E195" = {{16, 5, 0}, "macOS", {"Sierra", {10, 12, 4}}}, + "16F73" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, + "16F2073" = {{16, 6, 0}, "macOS", {"Sierra", {10, 12, 5}}}, + "16G29" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1036" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1114" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1212" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1314" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1408" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1510" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1618" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1710" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1815" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1917" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G1918" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2016" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2127" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2128" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, + "16G2136" = {{16, 7, 0}, "macOS", {"Sierra", {10, 12, 6}}}, // MacOS High Sierra - "17A365" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, - "17A405" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, - "17B48" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, - "17B1002" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, - "17B1003" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, - "17C88" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, - "17C89" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, - "17C205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, - "17C2205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, - "17D47" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, - "17D2047" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, - "17D102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, - "17D2102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, - "17E199" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, - "17E202" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, - "17F77" = {{17, 6, 0}, "macOS", {"High Sierra", {10, 13, 5}}}, - "17G65" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G2208" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G2307" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G3025" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G4015" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G5019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G6029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G6030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G7024" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G8029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G8030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G8037" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G9016" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G10021" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G11023" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G12034" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G13033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G13035" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G14019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G14033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, - "17G14042" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17A365" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, + "17A405" = {{17, 0, 0}, "macOS", {"High Sierra", {10, 13, 0}}}, + "17B48" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17B1002" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17B1003" = {{17, 2, 0}, "macOS", {"High Sierra", {10, 13, 1}}}, + "17C88" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C89" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17C2205" = {{17, 3, 0}, "macOS", {"High Sierra", {10, 13, 2}}}, + "17D47" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D2047" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17D2102" = {{17, 4, 0}, "macOS", {"High Sierra", {10, 13, 3}}}, + "17E199" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, + "17E202" = {{17, 5, 0}, "macOS", {"High Sierra", {10, 13, 4}}}, + "17F77" = {{17, 6, 0}, "macOS", {"High Sierra", {10, 13, 5}}}, + "17G65" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G2208" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G2307" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G3025" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G4015" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G5019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G6029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G6030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G7024" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8029" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8030" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G8037" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G9016" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G10021" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G11023" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G12034" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G13033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G13035" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14019" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14033" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, + "17G14042" = {{17, 7, 0}, "macOS", {"High Sierra", {10, 13, 6}}}, // MacOS Mojave - "18A391" = {{18, 0, 0}, "macOS", {"Mojave", {10, 14, 0}}}, - "18B75" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, - "18B2107" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, - "18B3094" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, - "18C54" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 2}}}, - "18D42" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, - "18D43" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, - "18D109" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, - "18E226" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, - "18E227" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, - "18F132" = {{18, 6, 0}, "macOS", {"Mojave", {10, 14, 5}}}, - "18G84" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G87" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G95" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G103" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G1012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G2022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G3020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G4032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G5033" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G6020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G6032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G6042" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G7016" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G8012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G8022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G9028" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G9216" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, - "18G9323" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18A391" = {{18, 0, 0}, "macOS", {"Mojave", {10, 14, 0}}}, + "18B75" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18B2107" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18B3094" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 1}}}, + "18C54" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 2}}}, + "18D42" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18D43" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18D109" = {{18, 2, 0}, "macOS", {"Mojave", {10, 14, 3}}}, + "18E226" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, + "18E227" = {{18, 5, 0}, "macOS", {"Mojave", {10, 14, 4}}}, + "18F132" = {{18, 6, 0}, "macOS", {"Mojave", {10, 14, 5}}}, + "18G84" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G87" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G95" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G103" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G1012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G2022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G3020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G4032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G5033" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6020" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6032" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G6042" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G7016" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G8012" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G8022" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9028" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9216" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, + "18G9323" = {{18, 7, 0}, "macOS", {"Mojave", {10, 14, 6}}}, // MacOS Catalina - "19A583" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, - "19A602" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, - "19A603" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, - "19B88" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 1}}}, - "19C57" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, - "19C58" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, - "19D76" = {{19, 3, 0}, "macOS", {"Catalina", {10, 15, 3}}}, - "19E266" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, - "19E287" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, - "19F96" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, - "19F101" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, - "19G73" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, - "19G2021" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, - "19H2" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H4" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H15" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H114" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H512" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H524" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1030" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1217" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1323" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1417" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1419" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1519" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1615" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1713" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1715" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1824" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H1922" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, - "19H2026" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19A583" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19A602" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19A603" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 0}}}, + "19B88" = {{19, 0, 0}, "macOS", {"Catalina", {10, 15, 1}}}, + "19C57" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, + "19C58" = {{19, 2, 0}, "macOS", {"Catalina", {10, 15, 2}}}, + "19D76" = {{19, 3, 0}, "macOS", {"Catalina", {10, 15, 3}}}, + "19E266" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, + "19E287" = {{19, 4, 0}, "macOS", {"Catalina", {10, 15, 4}}}, + "19F96" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, + "19F101" = {{19, 5, 0}, "macOS", {"Catalina", {10, 15, 5}}}, + "19G73" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, + "19G2021" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 6}}}, + "19H2" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H4" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H15" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H114" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H512" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H524" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1030" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1217" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1323" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1417" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1419" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1519" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1615" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1713" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1715" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1824" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H1922" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, + "19H2026" = {{19, 6, 0}, "macOS", {"Catalina", {10, 15, 7}}}, // MacOS Big Sur - "20A2411" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 0}}}, - "20B29" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, - "20B50" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, - "20C69" = {{20, 2, 0}, "macOS", {"Big Sur", {11, 1, 0}}}, - "20D64" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 0}}}, - "20D74" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, - "20D75" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, - "20D80" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 2}}}, - "20D91" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 3}}}, - "20E232" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 0}}}, - "20E241" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 1}}}, - "20F71" = {{20, 5, 0}, "macOS", {"Big Sur", {11, 4, 0}}}, - "20G71" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 0}}}, - "20G80" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 1}}}, - "20G95" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 2}}}, - "20G165" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 0}}}, - "20G224" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 1}}}, - "20G314" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 2}}}, - "20G415" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 3}}}, - "20G417" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 4}}}, - "20G527" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 5}}}, - "20G624" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 6}}}, - "20G630" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 7}}}, - "20G730" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 8}}}, + "20A2411" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 0}}}, + "20B29" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, + "20B50" = {{20, 1, 0}, "macOS", {"Big Sur", {11, 0, 1}}}, + "20C69" = {{20, 2, 0}, "macOS", {"Big Sur", {11, 1, 0}}}, + "20D64" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 0}}}, + "20D74" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, + "20D75" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 1}}}, + "20D80" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 2}}}, + "20D91" = {{20, 3, 0}, "macOS", {"Big Sur", {11, 2, 3}}}, + "20E232" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 0}}}, + "20E241" = {{20, 4, 0}, "macOS", {"Big Sur", {11, 3, 1}}}, + "20F71" = {{20, 5, 0}, "macOS", {"Big Sur", {11, 4, 0}}}, + "20G71" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 0}}}, + "20G80" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 1}}}, + "20G95" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 5, 2}}}, + "20G165" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 0}}}, + "20G224" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 1}}}, + "20G314" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 2}}}, + "20G415" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 3}}}, + "20G417" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 4}}}, + "20G527" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 5}}}, + "20G624" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 6}}}, + "20G630" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 7}}}, + "20G730" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 6, 8}}}, + "20G817" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 0}}}, + "20G918" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 1}}}, + "20G1020" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 2}}}, + "20G1116" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 3}}}, + "20G1120" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 4}}}, + "20G1225" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 5}}}, + "20G1231" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 6}}}, + "20G1345" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 7}}}, + "20G1351" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 8}}}, + "20G1426" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 9}}}, + "20G1427" = {{20, 6, 0}, "macOS", {"Big Sur", {11, 7, 10}}}, // MacOS Monterey - "21A344" = {{21, 0, 1}, "macOS", {"Monterey", {12, 0, 0}}}, - "21A559" = {{21, 1, 0}, "macOS", {"Monterey", {12, 0, 1}}}, - "21C52" = {{21, 2, 0}, "macOS", {"Monterey", {12, 1, 0}}}, - "21D49" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 0}}}, - "21D62" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 1}}}, - "21E230" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 0}}}, - "21E258" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 1}}}, - "21F79" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, - "21F2081" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, - "21F2092" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, - "21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}}, - "21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}}, - "21G115" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 0}}}, + "21A344" = {{21, 0, 1}, "macOS", {"Monterey", {12, 0, 0}}}, + "21A559" = {{21, 1, 0}, "macOS", {"Monterey", {12, 0, 1}}}, + "21C52" = {{21, 2, 0}, "macOS", {"Monterey", {12, 1, 0}}}, + "21D49" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 0}}}, + "21D62" = {{21, 3, 0}, "macOS", {"Monterey", {12, 2, 1}}}, + "21E230" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 0}}}, + "21E258" = {{21, 4, 0}, "macOS", {"Monterey", {12, 3, 1}}}, + "21F79" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21F2081" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21F2092" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, + "21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}}, + "21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}}, + "21G115" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 0}}}, + "21G217" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 1}}}, + "21G320" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 2}}}, + "21G419" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 3}}}, + "21G526" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 4}}}, + "21G531" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 5}}}, + "21G646" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 6}}}, + "21G651" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 7}}}, + "21G725" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 8}}}, + "21G726" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 9}}}, + "21G816" = {{21, 6, 0}, "macOS", {"Monterey", {12, 7, 0}}}, + "21G920" = {{21, 6, 0}, "macOS", {"Monterey", {12, 7, 1}}}, + "21G1974" = {{21, 6, 0}, "macOS", {"Monterey", {12, 7, 2}}}, + + // MacOS Ventura + "22A380" = {{22, 1, 0}, "macOS", {"Ventura", {13, 0, 0}}}, + "22A400" = {{22, 1, 0}, "macOS", {"Ventura", {13, 0, 1}}}, + "22C65" = {{22, 2, 0}, "macOS", {"Ventura", {13, 1, 0}}}, + "22D49" = {{22, 3, 0}, "macOS", {"Ventura", {13, 2, 0}}}, + "22D68" = {{22, 3, 0}, "macOS", {"Ventura", {13, 2, 1}}}, + "22E252" = {{22, 4, 0}, "macOS", {"Ventura", {13, 3, 0}}}, + "22E261" = {{22, 4, 0}, "macOS", {"Ventura", {13, 3, 1}}}, + "22F66" = {{22, 5, 0}, "macOS", {"Ventura", {13, 4, 0}}}, + "22F82" = {{22, 5, 0}, "macOS", {"Ventura", {13, 4, 1}}}, + "22E772610a" = {{22, 5, 0}, "macOS", {"Ventura", {13, 4, 1}}}, + "22F770820d" = {{22, 5, 0}, "macOS", {"Ventura", {13, 4, 1}}}, + "22G74" = {{22, 6, 0}, "macOS", {"Ventura", {13, 5, 0}}}, + "22G90" = {{22, 6, 0}, "macOS", {"Ventura", {13, 5, 1}}}, + "22G91" = {{22, 6, 0}, "macOS", {"Ventura", {13, 5, 2}}}, + "22G120" = {{22, 6, 0}, "macOS", {"Ventura", {13, 6, 0}}}, + "22G313" = {{22, 6, 0}, "macOS", {"Ventura", {13, 6, 1}}}, + "22G320" = {{22, 6, 0}, "macOS", {"Ventura", {13, 6, 2}}}, + + // MacOS Sonoma + "23A344" = {{23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, + "23B74" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, + "23B81" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, + "23B92" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, + "23C64" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}}, + "23C71" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, } @(private) diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 0cf90ed3b..8b7de5d5e 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -1,7 +1,9 @@ package linux -/// Represents an error returned by most of syscalls +/* + Represents an error returned by most of syscalls +*/ Errno :: enum i32 { NONE = 0, // Errno-base @@ -142,8 +144,9 @@ Errno :: enum i32 { EDEADLOCK = EDEADLK, } - -/// Bits for Open_Flags +/* + Bits for Open_Flags +*/ Open_Flags_Bits :: enum { RDONLY = 0, WRONLY = 1, @@ -164,7 +167,9 @@ Open_Flags_Bits :: enum { PATH = 21, } -/// Bits for FD_Flags bitset +/* + Bits for FD_Flags bitset +*/ FD_Flags_Bits :: enum { SYMLINK_NOFOLLOW = 8, REMOVEDIR = 9, @@ -177,7 +182,9 @@ FD_Flags_Bits :: enum { RECURSIVE = 15, } -/// The bits for the Mode bitset. +/* + The bits for the Mode bitset. +*/ Mode_Bits :: enum { IXOTH = 0, // 0o0000001 IWOTH = 1, // 0o0000002 @@ -197,7 +204,9 @@ Mode_Bits :: enum { IFREG = 15, // 0o0100000 } -/// The bits used by the Statx_Mask bitset +/* + The bits used by the Statx_Mask bitset +*/ Statx_Mask_Bits :: enum { TYPE = 0, MODE = 1, @@ -215,8 +224,10 @@ Statx_Mask_Bits :: enum { DIOALIGN = 13, } -/// Bits found in Statx_Attr bitset -/// You should not use these directly +/* + Bits found in Statx_Attr bitset + You should not use these directly +*/ Statx_Attr_Bits :: enum { COMPRESSED = 2, // 0x00000004 IMMUTABLE = 4, // 0x00000010 @@ -229,7 +240,9 @@ Statx_Attr_Bits :: enum { DAX = 21, // 0x00200000 } -/// Magic bits for filesystems returned by Stat_FS +/* + Magic bits for filesystems returned by Stat_FS +*/ FS_Magic :: enum u32 { ADFS_SUPER_MAGIC = 0xadf5, AFFS_SUPER_MAGIC = 0xadff, @@ -317,7 +330,9 @@ FS_Magic :: enum u32 { _XIAFS_SUPER_MAGIC = 0x012fd16d, } -/// Bits for FS_Flags bitset +/* + Bits for FS_Flags bitset +*/ FS_Flags_Bits :: enum { RDONLY = 0, NOSUID = 1, @@ -340,20 +355,26 @@ Seek_Whence :: enum i16 { HOLE = 4, } -/// Bits for Close_Range_Flags +/* + Bits for Close_Range_Flags +*/ Close_Range_Flags_Bits :: enum { CLOEXEC = 2, UNSHARE = 1, } -/// Bits for Rename_Flags +/* + Bits for Rename_Flags +*/ Rename_Flags_Bits :: enum { EXCHANGE = 1, NOREPLACE = 0, WHITEOUT = 2, } -/// Type of the file in a directory entry +/* + Type of the file in a directory entry +*/ Dirent_Type :: enum u8 { UNKNOWN = 0, FIFO = 1, @@ -366,14 +387,18 @@ Dirent_Type :: enum u8 { WHT = 14, } -/// Type of a lock for fcntl.2 +/* + Type of a lock for fcntl(2) +*/ FLock_Type :: enum i16 { RDLCK = 0, WRLCK = 1, UNLCK = 2, } -/// Bits for FD_Notifications +/* + Bits for FD_Notifications +*/ FD_Notifications_Bits :: enum { ACCESS = 0, MODIFY = 1, @@ -384,7 +409,9 @@ FD_Notifications_Bits :: enum { MULTISHOT = 31, } -/// Bits for seal +/* + Bits for seal +*/ Seal_Bits :: enum { SEAL = 0, SHRINK = 1, @@ -408,14 +435,18 @@ FD_Lease :: enum { UNLCK = 2, } -/// Kind of owner for FD_Owner +/* + Kind of owner for FD_Owner +*/ F_Owner_Type :: enum i32 { OWNER_TID = 0, OWNER_PID = 1, OWNER_PGRP = 2, } -/// Command for fcntl.2 +/* + Command for fcntl(2) +*/ FCntl_Command :: enum { DUPFD = 0, GETFD = 1, @@ -465,7 +496,9 @@ Fd_Poll_Events_Bits :: enum { RDHUP = 13, } -/// Bits for Mem_Protection bitfield +/* + Bits for Mem_Protection bitfield +*/ Mem_Protection_Bits :: enum{ READ = 0, WRITE = 1, @@ -479,7 +512,9 @@ Mem_Protection_Bits :: enum{ GROWSUP = 25, } -/// Bits for Map_Flags +/* + Bits for Map_Flags +*/ Map_Flags_Bits :: enum { SHARED = 0, PRIVATE = 1, @@ -504,19 +539,25 @@ Map_Flags_Bits :: enum { UNINITIALIZED = 26, } -/// Bits for MLock_Flags +/* + Bits for MLock_Flags +*/ MLock_Flags_Bits :: enum { ONFAULT = 0, } -/// Bits for MSync_Flags +/* + Bits for MSync_Flags +*/ MSync_Flags_Bits :: enum { ASYNC = 0, INVALIDATE = 1, SYNC = 2, } -/// Argument for madvice.2 +/* + Argument for madvice(2) +*/ MAdvice :: enum { NORMAL = 0, RANDOM = 1, @@ -545,27 +586,35 @@ MAdvice :: enum { SOFT_OFFLINE = 101, } -/// Bits for PKey_Access_Rights +/* + Bits for PKey_Access_Rights +*/ PKey_Access_Bits :: enum { DISABLE_ACCESS = 0, DISABLE_WRITE = 2, } -/// Bits for MRemap_Flags +/* + Bits for MRemap_Flags +*/ MRemap_Flags_Bits :: enum { MAYMOVE = 0, FIXED = 1, DONTUNMAP = 2, } -/// Bits for Get_Random_Flags +/* + Bits for Get_Random_Flags +*/ Get_Random_Flags_Bits :: enum { RANDOM = 0, NONBLOCK = 1, INSECURE = 2, } -/// Bits for Perf_Flags +/* + Bits for Perf_Flags +*/ Perf_Flags_Bits :: enum { FD_NO_GROUP = 0, FD_OUTPUT = 1, @@ -573,7 +622,9 @@ Perf_Flags_Bits :: enum { FD_CLOEXEC = 3, } -/// Union tag for Perf_Event_Attr struct +/* + Union tag for Perf_Event_Attr struct +*/ Perf_Event_Type :: enum u32 { HARDWARE = 0, SOFTWARE = 1, @@ -633,7 +684,9 @@ Perf_Cap_Flags_Bits :: enum u64 { User_Time_Short = 5, } -/// Specifies the type of the hardware event that you want to get info about +/* + Specifies the type of the hardware event that you want to get info about +*/ Perf_Hardware_Id :: enum u64 { CPU_CYCLES = 0, INSTRUCTIONS = 1, @@ -647,7 +700,9 @@ Perf_Hardware_Id :: enum u64 { REF_CPU_CYCLES = 9, } -/// Specifies the cache for the particular cache event that you want to get info about +/* + Specifies the cache for the particular cache event that you want to get info about +*/ Perf_Hardware_Cache_Id :: enum u64 { L1D = 0, L1I = 1, @@ -658,20 +713,26 @@ Perf_Hardware_Cache_Id :: enum u64 { NODE = 6, } -/// Specifies the cache op that you want to get info about +/* + Specifies the cache op that you want to get info about +*/ Perf_Hardware_Cache_Op_Id :: enum u64 { READ = 0, WRITE = 1, PREFETCH = 2, } -/// Specifies the cache operation result that you want to get info about +/* + Specifies the cache operation result that you want to get info about +*/ Perf_Hardware_Cache_Result_Id :: enum u64 { ACCESS = 0, MISS = 1, } -/// Specifies the particular software event that you want to get info about +/* + Specifies the particular software event that you want to get info about +*/ Perf_Software_Id :: enum u64 { CPU_CLOCK = 0, TASK_CLOCK = 1, @@ -688,7 +749,9 @@ Perf_Software_Id :: enum u64 { } -/// Specifies which values to include in the sample +/* + Specifies which values to include in the sample +*/ Perf_Event_Sample_Type_Bits :: enum { IP = 0, TID = 1, @@ -718,7 +781,7 @@ Perf_Event_Sample_Type_Bits :: enum { } /// Describes field sets to include in mmaped page -Perf_Read_Format :: enum { +Perf_Read_Format_Bits :: enum { TOTAL_TIME_ENABLED = 0, TOTAL_TIME_RUNNING = 1, ID = 2, @@ -726,7 +789,9 @@ Perf_Read_Format :: enum { LOST = 4, } -/// Chooses the breakpoint type +/* + Chooses the breakpoint type +*/ Hardware_Breakpoint_Type :: enum u32 { EMPTY = 0, R = 1, @@ -736,7 +801,9 @@ Hardware_Breakpoint_Type :: enum u32 { INVALID = RW | X, } -/// Bits for Branch_Sample_Type +/* + Bits for Branch_Sample_Type +*/ Branch_Sample_Type_Bits :: enum { USER = 0, KERNEL = 1, @@ -759,7 +826,9 @@ Branch_Sample_Type_Bits :: enum { PRIV_SAVE = 18, } -/// Represent the type of Id +/* + Represent the type of Id +*/ Id_Type :: enum uint { ALL = 0, PID = 1, @@ -767,7 +836,9 @@ Id_Type :: enum uint { PIDFD = 3, } -/// Options for wait syscalls +/* + Options for wait syscalls +*/ Wait_Option :: enum { WNOHANG = 0, WUNTRACED = 1, @@ -781,12 +852,16 @@ Wait_Option :: enum { __WCLONE = 31, } -/// Bits for flags for pidfd +/* + Bits for flags for pidfd +*/ Pid_FD_Flags_Bits :: enum { NONBLOCK = 11, } -/// Priority for process, process group, user +/* + Priority for process, process group, user +*/ Priority_Which :: enum i32 { PROCESS = 0, PGRP = 1, @@ -849,10 +924,12 @@ Sig_Stack_Flag :: enum i32 { AUTODISARM = 31, } -/// Type of socket to create -/// For TCP you want to use SOCK_STREAM -/// For UDP you want to use SOCK_DGRAM -/// Also see Protocol +/* + Type of socket to create + - For TCP you want to use SOCK_STREAM + - For UDP you want to use SOCK_DGRAM + Also see `Protocol` +*/ Socket_Type :: enum { STREAM = 1, DGRAM = 2, @@ -863,13 +940,17 @@ Socket_Type :: enum { PACKET = 10, } -/// Bits for Socket_FD_Flags +/* + Bits for Socket_FD_Flags +*/ Socket_FD_Flags_Bits :: enum { NONBLOCK = 14, CLOEXEC = 25, } -/// Protocol family +/* + Protocol family +*/ Protocol_Family :: enum u16 { UNSPEC = 0, LOCAL = 1, @@ -922,11 +1003,13 @@ Protocol_Family :: enum u16 { MCTP = 45, } -/// The protocol number according to IANA protocol number list -/// Full list of protocol numbers: -/// https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml -/// Supported by the OS protocols can be queried by reading: -/// /etc/protocols +/* + The protocol number according to IANA protocol number list + Full list of protocol numbers: + https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + Supported by the OS protocols can be queried by reading: + /etc/protocols +*/ Protocol :: enum { HOPOPT = 0, ICMP = 1, @@ -1066,7 +1149,9 @@ Protocol :: enum { Reserved = 255, } -/// API Level for get/setsockopt.2 +/* + API Level for getsockopt(2)/setsockopt(2) +*/ Socket_API_Level :: enum { // Comes from SOCKET = 1, @@ -1103,8 +1188,10 @@ Socket_API_Level :: enum { SMC = 286, } -/// If Socket_API_Level == .SOCKET, these are the options -/// you can specify in get/setsockopt.2 +/* + If Socket_API_Level == .SOCKET, these are the options + you can specify in getsockopt(2)/setsockopt(2) +*/ Socket_Option :: enum { DEBUG = 1, REUSEADDR = 2, @@ -1249,7 +1336,9 @@ Socket_TCP_Option :: enum { TX_DELAY = 37, } -/// Bits for Socket_Msg +/* + Bits for Socket_Msg +*/ Socket_Msg_Bits :: enum { OOB = 0, PEEK = 1, @@ -1275,14 +1364,18 @@ Socket_Msg_Bits :: enum { CMSG_CLOEXEC = 30, } -/// Argument to shutdown.2 +/* + Argument to shutdown(2) +*/ Shutdown_How :: enum i32 { RD = 0, WR = 1, RDWR = 2, } -/// Second argument to futex.2 syscall +/* + Second argument to futex(2) syscall +*/ Futex_Op :: enum u32 { WAIT = 0, WAKE = 1, @@ -1300,13 +1393,17 @@ Futex_Op :: enum u32 { LOCK_PI2 = 13, } -/// Bits for Futex_Flags +/* + Bits for Futex_Flags +*/ Futex_Flags_Bits :: enum { PRIVATE = 7, REALTIME = 8, } -/// Kind of operation on futex, see FUTEX_WAKE_OP +/* + Kind of operation on futex, see FUTEX_WAKE_OP +*/ Futex_Arg_Op :: enum { SET = 0, /* uaddr2 = oparg; */ ADD = 1, /* uaddr2 += oparg; */ @@ -1320,7 +1417,9 @@ Futex_Arg_Op :: enum { PO2_XOR = 4, /* uaddr2 ^= 1<= cmparg) wake */ } -/// The kind of resource limits +/* + The kind of resource limits +*/ RLimit_Kind :: enum i32 { CPU = 0, FSIZE = 1, @@ -1351,7 +1452,9 @@ RLimit_Kind :: enum i32 { NLIMITS = 16, } -/// Represents the user of resources +/* + Represents the user of resources +*/ RUsage_Who :: enum i32 { CHILDREN = -1, SELF = 0, @@ -1359,7 +1462,9 @@ RUsage_Who :: enum i32 { LWP = THREAD, } -/// Bits for Personality_Flags +/* + Bits for Personality_Flags +*/ UNAME26 :: 17 ADDR_NO_RANDOMIZE :: 18 FDPIC_FUNCPTRS :: 19 @@ -1372,8 +1477,10 @@ WHOLE_SECONDS :: 25 STICKY_TIMEOUTS :: 26 ADDR_LIMIT_3GB :: 27 -/// Personality type -/// These go into the bottom 8 bits of the personality value +/* + Personality type + These go into the bottom 8 bits of the personality value +*/ PER_LINUX :: 0x0000 PER_LINUX_32BIT :: 0x0000 | ADDR_LIMIT_32BIT PER_LINUX_FDPIC :: 0x0000 | FDPIC_FUNCPTRS @@ -1398,3 +1505,254 @@ PER_OSF4 :: 0x000f PER_HPUX :: 0x0010 PER_MASK :: 0x00ff +/* + Bits for access modes for shared memory +*/ +IPC_Mode_Bits :: enum { + WROTH = 1, + RDOTH = 2, + WRGRP = 4, + RDGRP = 5, + WRUSR = 7, + RDUSR = 8, + DEST = 9, + LOCKED = 10, +} + +/* + Shared memory flags bits +*/ +IPC_Flags_Bits :: enum { + IPC_CREAT = 9, + IPC_EXCL = 10, + IPC_NOWAIT = 11, + // Semaphore + SEM_UNDO = 9, + // Shared memory + SHM_HUGETLB = 11, + SHM_NORESERVE = 12, + SHM_RDONLY = 12, + SHM_RND = 13, + SHM_REMAP = 14, + SHM_EXEC = 15, + // Message queue + MSG_NOERROR = 12, + MSG_EXCEPT = 13, + MSG_COPY = 14, +} + +/* + IPC memory commands +*/ +IPC_Cmd :: enum i16 { + // IPC common + IPC_RMID = 0, + IPC_SET = 1, + IPC_STAT = 2, + // Shared memory + SHM_LOCK = 11, + SHM_UNLOCK = 12, + SHM_STAT = 13, + SHM_INFO = 14, + SHM_STAT_ANY = 15, + // Semaphore + GETPID = 11, + GETVAL = 12, + GETALL = 13, + GETNCNT = 14, + GETZCNT = 15, + SETVAL = 16, + SETALL = 17, + SEM_STAT = 18, + SEM_INFO = 19, + SEM_STAT_ANY = 20, + // Message queue + MSG_STAT = 11, + MSG_INFO = 12, + MSG_STAT_ANY = 13, +} + +/* + File locking operation bits +*/ +FLock_Op_Bits :: enum { + SH = 1, + EX = 2, + NB = 4, + UN = 8, +} + +/* + ptrace requests +*/ +PTrace_Request :: enum { + TRACEME = 0, + PEEKTEXT = 1, + PEEKDATA = 2, + PEEKUSER = 3, + POKETEXT = 4, + POKEDATA = 5, + POKEUSER = 6, + CONT = 7, + KILL = 8, + SINGLESTEP = 9, + GETREGS = 12, + SETREGS = 13, + GETFPREGS = 14, + SETFPREGS = 15, + ATTACH = 16, + DETACH = 17, + GETFPXREGS = 18, + SETFPXREGS = 19, + SYSCALL = 24, + GET_THREAD_AREA = 25, + SET_THREAD_AREA = 26, + ARCH_PRCTL = 30, + SYSEMU = 31, + SYSEMU_SINGLESTEP = 32, + SINGLEBLOCK = 33, + SETOPTIONS = 0x4200, + GETEVENTMSG = 0x4201, + GETSIGINFO = 0x4202, + SETSIGINFO = 0x4203, + GETREGSET = 0x4204, + SETREGSET = 0x4205, + SEIZE = 0x4206, + INTERRUPT = 0x4207, + LISTEN = 0x4208, + PEEKSIGINFO = 0x4209, + GETSIGMASK = 0x420a, + SETSIGMASK = 0x420b, + SECCOMP_GET_FILTER = 0x420c, + SECCOMP_GET_METADATA = 0x420d, + GET_SYSCALL_INFO = 0x420e, + GET_RSEQ_CONFIGURATION = 0x420f, +} + +/* + ptrace options +*/ +PTrace_Options_Bits :: enum { + TRACESYSGOOD = 0, + TRACEFORK = 1, + TRACEVFORK = 2, + TRACECLONE = 3, + TRACEEXEC = 4, + TRACEVFORKDONE = 5, + TRACEEXIT = 6, + TRACESECCOMP = 7, + EXITKILL = 20, + SUSPEND_SECCOMP = 21, +} + +/* + ptrace event codes. +*/ +PTrace_Event_Code :: enum { + EVENT_FORK = 1, + EVENT_VFORK = 2, + EVENT_CLONE = 3, + EVENT_EXEC = 4, + EVENT_VFORK_DONE = 5, + EVENT_EXIT = 6, + EVENT_SECCOMP = 7, + EVENT_STOP = 128, +} + +/* + ptrace's get syscall info operation. +*/ +PTrace_Get_Syscall_Info_Op :: enum u8 { + NONE = 0, + ENTRY = 1, + EXIT = 2, + SECCOMP = 3, +} + +/* + ptrace's PEEKSIGINFO flags bits +*/ +PTrace_Peek_Sig_Info_Flags_Bits :: enum { + SHARED = 0, +} + +/* + Syslog actions. +*/ +Syslog_Action :: enum i32 { + CLOSE = 0, + OPEN = 1, + READ = 2, + READ_ALL = 3, + READ_CLEAR = 4, + CLEAR = 5, + CONSOLE_OFF = 6, + CONSOLE_ON = 7, + CONSOLE_LEVEL = 8, + SIZE_UNREAD = 9, + SIZE_BUFFER = 10, +} + +/* + Bits for splice flags. +*/ +Splice_Flags_Bits :: enum { + MOVE = 0x01, + NONBLOCK = 0x02, + MORE = 0x04, + GIFT = 0x08, +} + +/* + Clock IDs for various system clocks. +*/ +Clock_Id :: enum { + REALTIME = 0, + MONOTONIC = 1, + PROCESS_CPUTIME_ID = 2, + THREAD_CPUTIME_ID = 3, + MONOTONIC_RAW = 4, + REALTIME_COARSE = 5, + MONOTONIC_COARSE = 6, + BOOTTIME = 7, + REALTIME_ALARM = 8, + BOOTTIME_ALARM = 9, +} + +/* + Bits for POSIX interval timer flags. +*/ +ITimer_Flags_Bits :: enum { + ABSTIME = 1, +} + +/* + Bits for epoll_create(2) flags. +*/ +EPoll_Flags_Bits :: enum { + FDCLOEXEC = 19, +} + +EPoll_Event_Kind :: enum u32 { + IN = 0x001, + PRI = 0x002, + OUT = 0x004, + RDNORM = 0x040, + RDBAND = 0x080, + WRNORM = 0x100, + WRBAND = 0x200, + MSG = 0x400, + ERR = 0x008, + HUP = 0x010, + RDHUP = 0x2000, + EXCLUSIVE = 1<<28, + WAKEUP = 1<<29, + ONESHOT = 1<<30, + ET = 1<<31, +} + +EPoll_Ctl_Opcode :: enum i32 { + ADD = 1, + DEL = 2, + MOD = 3, +} diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index e725ed2fd..6294602e9 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -1,26 +1,40 @@ package linux -/// Special file descriptor to pass to `*at` functions to specify -/// that relative paths are relative to current directory +/* + Special file descriptor to pass to `*at` functions to specify + that relative paths are relative to current directory. +*/ AT_FDCWD :: Fd(-100) -/// Special value to put into timespec for utimensat() to set timestamp to the current time +/* + Special value to put into timespec for utimensat() to set timestamp to the current time. +*/ UTIME_NOW :: uint((1 << 30) - 1) -/// Special value to put into the timespec for utimensat() to leave the corresponding field of the timestamp unchanged +/* + Special value to put into the timespec for utimensat() to leave the corresponding field of the timestamp unchanged. +*/ UTIME_OMIT :: uint((1 << 30) - 2) -/// For wait4: Pass this pid to wait for any process +/* + For wait4: Pass this pid to wait for any process. +*/ WAIT_ANY :: Pid(-1) -/// For wait4: Pass this pid to wait for any process in current process group +/* + For wait4: Pass this pid to wait for any process in current process group. +*/ WAIT_MYPGRP :: Pid(0) -/// Maximum priority (aka nice value) for the process +/* + Maximum priority (aka nice value) for the process. +*/ PRIO_MAX :: 20 -/// Minimum priority (aka nice value) for the process +/* + Minimum priority (aka nice value) for the process. +*/ PRIO_MIN :: -20 SIGRTMIN :: Signal(32) @@ -35,40 +49,64 @@ S_IFCHR :: Mode{.IFCHR} S_IFDIR :: Mode{.IFDIR} S_IFREG :: Mode{.IFREG} -/// Checks the Mode bits to see if the file is a named pipe (FIFO) +/* + Checks the Mode bits to see if the file is a named pipe (FIFO). +*/ S_ISFIFO :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFFIFO == (m & S_IFMT))} -/// Check the Mode bits to see if the file is a character device +/* + Check the Mode bits to see if the file is a character device. +*/ S_ISCHR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFCHR == (m & S_IFMT))} - -/// Check the Mode bits to see if the file is a directory + +/* + Check the Mode bits to see if the file is a directory. +*/ S_ISDIR :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFDIR == (m & S_IFMT))} -/// Check the Mode bits to see if the file is a register +/* + Check the Mode bits to see if the file is a register. +*/ S_ISREG :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFREG == (m & S_IFMT))} -/// Check the Mode bits to see if the file is a socket +/* + Check the Mode bits to see if the file is a socket. +*/ S_ISSOCK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFSOCK == (m & S_IFMT))} -/// Check the Mode bits to see if the file is a symlink +/* + Check the Mode bits to see if the file is a symlink. +*/ S_ISLNK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFLNK == (m & S_IFMT))} -/// Check the Mode bits to see if the file is a block device +/* + Check the Mode bits to see if the file is a block device. +*/ S_ISBLK :: #force_inline proc "contextless" (m: Mode) -> bool {return (S_IFBLK == (m & S_IFMT))} -/// For access.2 syscall family: instruct to check if the file exists +/* + For access.2 syscall family: instruct to check if the file exists. +*/ F_OK :: Mode{} -/// For access.2 syscall family: instruct to check if the file is executable +/* + For access.2 syscall family: instruct to check if the file is executable. +*/ X_OK :: Mode{.IXOTH} -/// For access.2 syscall family: instruct to check if the file is writeable +/* + For access.2 syscall family: instruct to check if the file is writeable. +*/ W_OK :: Mode{.IWOTH} -/// For access.2 syscall family: instruct to check if the file is readable +/* + For access.2 syscall family: instruct to check if the file is readable. +*/ R_OK :: Mode{.IROTH} -/// The stats you get by calling `stat` +/* + The stats you get by calling `stat`. +*/ STATX_BASIC_STATS :: Statx_Mask { .TYPE, .MODE, @@ -83,6 +121,10 @@ STATX_BASIC_STATS :: Statx_Mask { .BLOCKS, } +/* + Tell `shmget` to create a new key +*/ +IPC_PRIVATE :: Key(0) FCntl_Command_DUPFD :: distinct FCntl_Command FCntl_Command_GETFD :: distinct FCntl_Command @@ -165,28 +207,44 @@ Futex_Wait_requeue_Pi_Type :: distinct Futex_Op Futex_Cmp_requeue_Pi_Type :: distinct Futex_Op Futex_Lock_Pi2_Type :: distinct Futex_Op -/// Wait on futex wakeup signal +/* + Wait on futex wakeup signal. +*/ FUTEX_WAIT :: Futex_Wait_Type(.WAIT) -/// Wake up other processes waiting on the futex +/* + Wake up other processes waiting on the futex. +*/ FUTEX_WAKE :: Futex_Wake_Type(.WAKE) -/// Not implemented. Basically, since +/* + Not implemented. Basically, since. +*/ FUTEX_FD :: Futex_Fd_Type(.FD) -/// Requeue waiters from one futex to another +/* + Requeue waiters from one futex to another. +*/ FUTEX_REQUEUE :: Futex_Requeue_Type(.REQUEUE) -/// Requeue waiters from one futex to another if the value at mutex matches +/* + Requeue waiters from one futex to another if the value at mutex matches. +*/ FUTEX_CMP_REQUEUE :: Futex_Cmp_Requeue_Type(.CMP_REQUEUE) -/// See man pages, I'm not describing it here +/* + See man pages, I'm not describing it here. +*/ FUTEX_WAKE_OP :: Futex_Wake_Op_Type(.WAKE_OP) -/// Wait on a futex, but the value is a bitset +/* + Wait on a futex, but the value is a bitset. +*/ FUTEX_WAIT_BITSET :: Futex_Wait_Bitset_Type(.WAIT_BITSET) -/// Wait on a futex, but the value is a bitset +/* + Wait on a futex, but the value is a bitset. +*/ FUTEX_WAKE_BITSET :: Futex_Wake_Bitset_Type(.WAKE_BITSET) // TODO(flysand): Priority inversion futexes @@ -197,3 +255,82 @@ FUTEX_WAIT_REQUEUE_PI :: Futex_Wait_requeue_Pi_Type(.WAIT_REQUEUE_PI) FUTEX_CMP_REQUEUE_PI :: Futex_Cmp_requeue_Pi_Type(.CMP_REQUEUE_PI) FUTEX_LOCK_PI2 :: Futex_Lock_Pi2_Type(.LOCK_PI2) +PTrace_Traceme_Type :: distinct PTrace_Request +PTrace_Peek_Type :: distinct PTrace_Request +PTrace_Poke_Type :: distinct PTrace_Request +PTrace_Cont_Type :: distinct PTrace_Request +PTrace_Kill_Type :: distinct PTrace_Request +PTrace_Singlestep_Type :: distinct PTrace_Request +PTrace_Getregs_Type :: distinct PTrace_Request +PTrace_Setregs_Type :: distinct PTrace_Request +PTrace_Getfpregs_Type :: distinct PTrace_Request +PTrace_Setfpregs_Type :: distinct PTrace_Request +PTrace_Attach_Type :: distinct PTrace_Request +PTrace_Detach_Type :: distinct PTrace_Request +PTrace_Getfpxregs_Type :: distinct PTrace_Request +PTrace_Setfpxregs_Type :: distinct PTrace_Request +PTrace_Syscall_Type :: distinct PTrace_Request +PTrace_Get_Thread_Area_Type :: distinct PTrace_Request +PTrace_Set_Thread_Area_Type :: distinct PTrace_Request +PTrace_Arch_Prctl_Type :: distinct PTrace_Request +PTrace_Sysemu_Type :: distinct PTrace_Request +PTrace_Sysemu_Singlestep_Type :: distinct PTrace_Request +PTrace_Singleblock_Type :: distinct PTrace_Request +PTrace_Setoptions_Type :: distinct PTrace_Request +PTrace_Geteventmsg_Type :: distinct PTrace_Request +PTrace_Getsiginfo_Type :: distinct PTrace_Request +PTrace_Setsiginfo_Type :: distinct PTrace_Request +PTrace_Getregset_Type :: distinct PTrace_Request +PTrace_Setregset_Type :: distinct PTrace_Request +PTrace_Seize_Type :: distinct PTrace_Request +PTrace_Interrupt_Type :: distinct PTrace_Request +PTrace_Listen_Type :: distinct PTrace_Request +PTrace_Peeksiginfo_Type :: distinct PTrace_Request +PTrace_Getsigmask_Type :: distinct PTrace_Request +PTrace_Setsigmask_Type :: distinct PTrace_Request +PTrace_Seccomp_Get_Filter_Type :: distinct PTrace_Request +PTrace_Seccomp_Get_Metadata_Type :: distinct PTrace_Request +PTrace_Get_Syscall_Info_Type :: distinct PTrace_Request +PTrace_Get_RSeq_Configuration_Type :: distinct PTrace_Request + +PTRACE_TRACEME :: PTrace_Traceme_Type(.TRACEME) +PTRACE_PEEKTEXT :: PTrace_Peek_Type(.PEEKTEXT) +PTRACE_PEEKDATA :: PTrace_Peek_Type(.PEEKDATA) +PTRACE_PEEKUSER :: PTrace_Peek_Type(.PEEKUSER) +PTRACE_POKETEXT :: PTrace_Poke_Type(.POKETEXT) +PTRACE_POKEDATA :: PTrace_Poke_Type(.POKEDATA) +PTRACE_POKEUSER :: PTrace_Poke_Type(.POKEUSER) +PTRACE_CONT :: PTrace_Cont_Type(.CONT) +PTRACE_KILL :: PTrace_Kill_Type(.KILL) +PTRACE_SINGLESTEP :: PTrace_Singlestep_Type(.SINGLESTEP) +PTRACE_GETREGS :: PTrace_Getregs_Type(.GETREGS) +PTRACE_SETREGS :: PTrace_Setregs_Type(.SETREGS) +PTRACE_GETFPREGS :: PTrace_Getfpregs_Type(.GETFPREGS) +PTRACE_SETFPREGS :: PTrace_Setfpregs_Type(.SETFPREGS) +PTRACE_ATTACH :: PTrace_Attach_Type(.ATTACH) +PTRACE_DETACH :: PTrace_Detach_Type(.DETACH) +PTRACE_GETFPXREGS :: PTrace_Getfpxregs_Type(.GETFPXREGS) +PTRACE_SETFPXREGS :: PTrace_Setfpxregs_Type(.SETFPXREGS) +PTRACE_SYSCALL :: PTrace_Syscall_Type(.SYSCALL) +PTRACE_GET_THREAD_AREA :: PTrace_Get_Thread_Area_Type(.GET_THREAD_AREA) +PTRACE_SET_THREAD_AREA :: PTrace_Set_Thread_Area_Type(.SET_THREAD_AREA) +PTRACE_ARCH_PRCTL :: PTrace_Arch_Prctl_Type(.ARCH_PRCTL) +PTRACE_SYSEMU :: PTrace_Sysemu_Type(.SYSEMU) +PTRACE_SYSEMU_SINGLESTEP :: PTrace_Sysemu_Singlestep_Type(.SYSEMU_SINGLESTEP) +PTRACE_SINGLEBLOCK :: PTrace_Singleblock_Type(.SINGLEBLOCK) +PTRACE_SETOPTIONS :: PTrace_Setoptions_Type(.SETOPTIONS) +PTRACE_GETEVENTMSG :: PTrace_Geteventmsg_Type(.GETEVENTMSG) +PTRACE_GETSIGINFO :: PTrace_Getsiginfo_Type(.GETSIGINFO) +PTRACE_SETSIGINFO :: PTrace_Setsiginfo_Type(.SETSIGINFO) +PTRACE_GETREGSET :: PTrace_Getregset_Type(.GETREGSET) +PTRACE_SETREGSET :: PTrace_Setregset_Type(.SETREGSET) +PTRACE_SEIZE :: PTrace_Seize_Type(.SEIZE) +PTRACE_INTERRUPT :: PTrace_Interrupt_Type(.INTERRUPT) +PTRACE_LISTEN :: PTrace_Listen_Type(.LISTEN) +PTRACE_PEEKSIGINFO :: PTrace_Peeksiginfo_Type(.PEEKSIGINFO) +PTRACE_GETSIGMASK :: PTrace_Getsigmask_Type(.GETSIGMASK) +PTRACE_SETSIGMASK :: PTrace_Setsigmask_Type(.SETSIGMASK) +PTRACE_SECCOMP_GET_FILTER :: PTrace_Seccomp_Get_Filter_Type(.SECCOMP_GET_FILTER) +PTRACE_SECCOMP_GET_METADATA :: PTrace_Seccomp_Get_Metadata_Type(.SECCOMP_GET_METADATA) +PTRACE_GET_SYSCALL_INFO :: PTrace_Get_Syscall_Info_Type(.GET_SYSCALL_INFO) +PTRACE_GET_RSEQ_CONFIGURATION :: PTrace_Get_RSeq_Configuration_Type(.GET_RSEQ_CONFIGURATION) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index e0e19056a..9a0f18e9f 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -1,38 +1,42 @@ -//+build linux package linux import "core:intrinsics" -/// Read data from file into the buffer -/// Returns the number of bytes successfully read, which may be less than the size -/// of the buffer even if the termination is successfull -/// -/// Available since Linux 1.0 -/// Before Linux 3.14, this operation is not atomic (i.e. not thread safe). -read :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) { - ret := syscall(SYS_read, fd, raw_data(buf), len(buf) * size_of(T)) +/* + Read data from file into the buffer + Returns the number of bytes successfully read, which may be less than the size + of the buffer even if the termination is successfull. + Available since Linux 1.0. + Before Linux 3.14, this operation is not atomic (i.e. not thread safe). +*/ +read :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) { + ret := syscall(SYS_read, fd, raw_data(buf), len(buf)) return errno_unwrap(ret, int) } -/// Write the data from a buffer into the file -/// Returns the number of bytes successfully written, which may be less than the size -/// of the buffer, even if the termination is successfull -/// When using direct I/O, error doesn't mean the write has failed. Partial data may -/// have been written. -/// If .Eintr is returned, the write operation has failed due to interrupt. You'll probably -/// need to restart this syscall -/// -/// Available since Linux 1.0 -/// Before Linux 3.14 this operation is not atomic (i.e. not thread safe) -write :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) { - ret := syscall(SYS_write, fd, raw_data(buf), len(buf)*size_of(T)) +/* + Write the data from a buffer into the file + Returns the number of bytes successfully written, which may be less than the size + of the buffer, even if the termination is successfull + When using direct I/O, error doesn't mean the write has failed. Partial data may + have been written. + If .Eintr is returned, the write operation has failed due to interrupt. You'll probably + need to restart this syscall + + Available since Linux 1.0 + Before Linux 3.14 this operation is not atomic (i.e. not thread safe) +*/ +write :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) { + ret := syscall(SYS_write, fd, raw_data(buf), len(buf)) return errno_unwrap(ret, int) } -/// Open file, get the file descriptor -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Open file, get the file descriptor + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ open :: proc "contextless" (name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_openat, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode) @@ -43,20 +47,24 @@ open :: proc "contextless" (name: cstring, flags: Open_Flags, mode: Mode = {}) - } } -/// Close the file -/// Available since Linux 1.0 +/* + Close the file. + Available since Linux 1.0. +*/ close :: proc "contextless" (fd: Fd) -> (Errno) { ret := syscall(SYS_close, fd) return Errno(-ret) } -/// Get file status -/// -/// Returns information about the file in struct pointed to by `stat` parameter. -/// -/// Available since Linux 1.0 -/// For 32-bit systems a different syscall is used that became available since 2.4 -/// Not available on arm64 +/* + Get file status. + + Returns information about the file in struct pointed to by `stat` parameter. + + Available since Linux 1.0 + For 32-bit systems a different syscall is used that became available since 2.4. + Not available on ARM64. +*/ stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { when size_of(int) == 8 { when ODIN_ARCH == .arm64 { @@ -72,12 +80,14 @@ stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { } } -/// Get file status from file descriptor -/// -/// Returns information about the file in struct pointed to by `stat` parameter. -/// -/// Available since Linux 1.0 -/// For 32-bit systems a different syscall is used that became available since 2.4 +/* + Get file status from file descriptor. + + Returns information about the file in struct pointed to by `stat` parameter. + + Available since Linux 1.0. + For 32-bit systems a different syscall is used that became available since 2.4. +*/ fstat :: proc "contextless" (fd: Fd, stat: ^Stat) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_fstat, stat) @@ -88,14 +98,16 @@ fstat :: proc "contextless" (fd: Fd, stat: ^Stat) -> (Errno) { } } -/// Get information about the file that's potentially a symbolic link -/// The information is returned in a struct pointed to by `stat` parameter. -/// The difference with stat, fstat is that if the file is a symbolic link, -/// stat and fstat will dereference the link. lstat doesn't dereference symlinks -/// -/// Available since Linux 1.0 -/// For 32-bit systems a different syscall is used that became available since 2.4 -/// Not available on arm64 +/* + Get information about the file that's potentially a symbolic link + The information is returned in a struct pointed to by `stat` parameter. + The difference with stat, fstat is that if the file is a symbolic link, + stat and fstat will dereference the link. lstat doesn't dereference symlinks. + + Available since Linux 1.0. + For 32-bit systems a different syscall is used that became available since 2.4. + Not available on arm64. +*/ lstat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { when size_of(int) == 8 { when ODIN_ARCH == .arm64 { @@ -110,8 +122,10 @@ lstat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) { } } -/// Wait on event on a file descriptor -/// Available since Linux 2.2 +/* + Wait on event on a file descriptor. + Available since Linux 2.2. +*/ poll :: proc "contextless" (fds: []Poll_Fd, timeout: i32) -> (i32, Errno) { when ODIN_ARCH == .arm64 { seconds := cast(uint) timeout / 1000 @@ -125,23 +139,27 @@ poll :: proc "contextless" (fds: []Poll_Fd, timeout: i32) -> (i32, Errno) { } } - -/// Seek the file stream to specified offset -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 1.2 -lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (Errno) { +/* + Seek the file stream to specified offset. + Available since Linux 1.0. + On 32-bit platforms available since Linux 1.2. +*/ +lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (i64, Errno) { when size_of(int) == 8 { ret := syscall(SYS_lseek, fd, off, whence) - return Errno(-ret) + return errno_unwrap(ret, i64) } else { - ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), whence) - return Errno(-ret) + result: i64 = --- + ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), &result, whence) + return result, Errno(-ret) } } -/// Map files into memory -/// Available since Linux 1.0 -/// On 32-bit platforms since Linux 1.0 +/* + Map files into memory. + Available since Linux 1.0. + On 32-bit platforms since Linux 1.0. +*/ mmap :: proc "contextless" (addr: uintptr, size: uint, prot: Mem_Protection, flags: Map_Flags, fd: Fd = Fd(-1), offset: i64 = 0) -> (rawptr, Errno) { when size_of(int) == 8 { ret := syscall(SYS_mmap, addr, size, transmute(i32) prot, transmute(i32) flags, fd, offset) @@ -152,63 +170,99 @@ mmap :: proc "contextless" (addr: uintptr, size: uint, prot: Mem_Protection, fla } } -/// Protect memory region +/* + Protect memory region. + Available since Linux 1.0. +*/ mprotect :: proc "contextless" (addr: rawptr, size: uint, prot: Mem_Protection) -> (Errno) { ret := syscall(SYS_mprotect, addr, size, transmute(i32) prot) return Errno(-ret) } -/// Unmap memory -/// Available since Linux 1.0 +/* + Unmap memory. + Available since Linux 1.0. +*/ munmap :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) { ret := syscall(SYS_munmap, addr, size) return Errno(-ret) } -// TODO(flysand): brk +/* + Extend the data segment size until the address `addr`. Note: you may be + familiar with sbrk(), which is not actually a syscall, so is not + implemented here. + Available since Linux 1.0. +*/ +brk :: proc "contextless" (addr: uintptr) -> (Errno) { + ret := syscall(SYS_brk, addr) + return Errno(-ret) +} -/// Alter an action taken by a process +/* + Alter an action taken by a process. +*/ rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno { ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set)) return Errno(-ret) } -/// Examime and alter blocked signals -/// Available since Linux 2.2 +/* + Examime and alter blocked signals. + Available since Linux 2.2. +*/ rt_sigprocmask :: proc "contextless" (mask_kind: Sig_Mask_Kind, new_set: ^Sig_Set, old_set: ^Sig_Set) -> Errno { ret := syscall(SYS_rt_sigprocmask, mask_kind, new_set, old_set, size_of(Sig_Set)) return Errno(-ret) } -// TODO(flysand): rt_sigreturn - // TODO(flysand): ioctl -/// Read the file at a specified offset -/// Note, it is not an error to return less bytes than requested -/// Available since Linux 2.2 -pread :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) { - ret := syscall(SYS_pread64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T))) +/* + Read the file at a specified offset. + Note, it is not an error to return less bytes than requested. + Available since Linux 2.2. +*/ +pread :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) { + ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset)) return errno_unwrap(ret, int) } -/// Read the file at a specified offset -/// Note, it is not an error to return less bytes than requested -/// Available since Linux 2.2 -pwrite :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) { - ret := syscall(SYS_pwrite64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T))) +/* + Read the file at a specified offset. + Note, it is not an error to return less bytes than requested. + Available since Linux 2.2. +*/ +pwrite :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) { + ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset)) return errno_unwrap(ret, int) } -// TODO(flysand): readv +/* + Read the data from file into multiple buffers. + Available since Linux 2.0. +*/ +readv :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) { + ret := syscall(SYS_readv, fd, raw_data(iov), len(iov)) + return errno_unwrap(ret, int) +} -// TODO(flysand): writev +/* + Write the data from multiple buffers into a file. + Available since Linux 2.0. +*/ +writev :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) { + ret := syscall(SYS_writev, fd, raw_data(iov), len(iov)) + return errno_unwrap(ret, int) +} -/// Check user permissions for a file -/// If Mode is F_OK, checks whether the file exists -/// Similarly, X_OK, W_OK, R_OK check if the file is executable, writeable, readable respectively -/// Available since Linux 1.0 -/// For ARM64 available since Linux 2.6.16 +/* + Check user permissions for a file. + If Mode is F_OK, checks whether the file exists. + Similarly, X_OK, W_OK, R_OK check if the file is executable, writeable, readable respectively. + Available since Linux 1.0. + For ARM64 available since Linux 2.6.16. +*/ access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (bool, Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_faccessat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode) @@ -219,18 +273,27 @@ access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (bool, Errno) } } -/// Create a pipe -/// Available since Linux 2.6.27 +/* + Create a pipe + Available since Linux 2.6.27 +*/ pipe2 :: proc "contextless" (pipes: ^[2]Fd, flags: Open_Flags) -> (Errno) { ret := syscall(SYS_pipe2, pipes, transmute(u32) flags) return Errno(-ret) } -// TODO(flysand): select +/* + Yield the processor. + Available since Linux 2.0. +*/ +sched_yield :: proc "contextless" () { + syscall(SYS_sched_yield) +} -// TODO(flysand): sched_yield - -// TODO(flysand): add docs here +/* + Remap a virtual memory address. + Available since Linux 2.0. +*/ mremap :: proc "contextless" (old_addr: rawptr, old_size: uint, new_size: uint, flags: MRemap_Flags, new_addr: uintptr = 0) -> (rawptr, Errno) { if .FIXED in flags { ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags, new_addr) @@ -241,38 +304,81 @@ mremap :: proc "contextless" (old_addr: rawptr, old_size: uint, new_size: uint, } } -/// Sync file with memory map -/// Available since Linux 2.0 +/* + Sync file with memory map. + Available since Linux 2.0. +*/ msync :: proc "contextless" (addr: rawptr, size: uint, flags: MSync_Flags) -> (Errno) { ret := syscall(SYS_msync, addr, size, transmute(i32) flags) return Errno(-ret) } -// TODO(flysand): mincore +/* + Determine if pages are resident in memory. + Available since Linux 2.4. +*/ +mincore :: proc "contextless" (addr: rawptr, size: uint, vec: []b8) -> (Errno) { + ret := syscall(SYS_mincore, addr, size, raw_data(vec)) + return Errno(-ret) +} -/// Give advice about use of memory -/// Available since Linux 2.4 +/* + Give advice about use of memory. + Available since Linux 2.4. +*/ madvise :: proc "contextless" (addr: rawptr, size: uint, advice: MAdvice) -> (Errno) { ret := syscall(SYS_madvise, addr, size, advice) return Errno(-ret) } -// TODO(flysand): shmget +/* + Allocate a SystemV shared memory segment. + Available since Linux 2.0. +*/ +shmget :: proc "contextless" (key: Key, size: uint, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_shmget, key, size, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): shmat +/* + SystemV shared memory segment operations. + Available since Linux 2.0. +*/ +shmat :: proc "contextless" (key: Key, addr: rawptr, flags: IPC_Flags) -> (rawptr, Errno) { + ret := syscall(SYS_shmat, key, addr, transmute(i16) flags) + return errno_unwrap(ret, rawptr, uintptr) +} -// TODO(flysand): shmctl +shmctl_ds :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shmid_DS) -> (Errno) { + ret := syscall(SYS_shmctl, key, cmd, buf) + return Errno(-ret) +} -/// Allocate a new file descriptor that refers to the same file as the one provided -/// Available since Linux 1.0 +shmctl_info :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Shm_Info) -> (int, Errno) { + ret := syscall(SYS_shmctl, key, cmd, buf) + return errno_unwrap(ret, int) +} + +/* + SystemV shared memory control. + Available since Linux 2.0. +*/ +shmctl :: proc {shmctl_ds, shmctl_info} + +/* + Allocate a new file descriptor that refers to the same file as the one provided. + Available since Linux 1.0. +*/ dup :: proc "contextless" (fd: Fd) -> (Fd, Errno) { ret := syscall(SYS_dup, fd) return errno_unwrap(ret, Fd) } -/// Adjust an existing file descriptor to point to the same file as `old` -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.27 +/* + Adjust an existing file descriptor to point to the same file as `old`. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.27. +*/ dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_dup3, old, new, 0) @@ -283,35 +389,99 @@ dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) { } } -// TODO(flysand): pause +/* + Wait until the next signal is delivered. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ +pause :: proc "contextless" () { + when ODIN_ARCH == .arm64 { + syscall(SYS_ppoll, 0, 0, 0, 0) + } else { + syscall(SYS_pause) + } +} -// TODO(flysand): nanosleep +/* + High-resolution sleep. + Available since Linux 2.0. +*/ +nanosleep :: proc "contextless" (req: ^Time_Spec, rem: ^Time_Spec) -> (Errno) { + ret := syscall(SYS_nanosleep, req, rem) + return Errno(-ret) +} -// TODO(flysand): getitimer +/* + Get the value of an internal timer. + Available since Linux 1.0. +*/ +getitimer :: proc "contextless" (which: ITimer_Which, cur: ^ITimer_Val) -> (Errno) { + ret := syscall(SYS_getitimer, cur) + return Errno(-ret) +} -// TODO(flysand): alarm +/* + Set an alarm clock for delivery of a signal. + Available since Linux 1.0. +*/ +alarm :: proc "contextless" (seconds: u32) -> u32 { + when ODIN_ARCH == .arm64 { + new := ITimer_Val { value = { seconds = cast(int) seconds } } + old := ITimer_Val {} + syscall(SYS_setitimer, ITimer_Which.REAL, &new, &old) + return u32(old.value.seconds) + u32(new.value.microseconds) + } else { + return cast(u32) syscall(SYS_alarm, seconds) + } +} -// TODO(flysand): setitimer +/* + Set the value of an internal timer. + Available since Linux 1.0. +*/ +setitimer :: proc "contextless" (which: ITimer_Which, new: ^ITimer_Val, old: ^ITimer_Val) -> (Errno) { + ret := syscall(SYS_getitimer, new, old) + return Errno(-ret) +} -/// Returns the thread group ID of the current process -/// Note that it doesn't return the pid, despite it's name. -/// Available since Linux 1.0 +/* + Returns the thread group ID of the current process. + Note that it doesn't return the pid, despite it's name. + Available since Linux 1.0. +*/ getpid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_getpid) } -// TODO(flysand): sendfile +/* + Transfer the data between file descriptors. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.6. +*/ +sendfile :: proc "contextless" (out_fd: Fd, in_fd: Fd, offset: ^i64, count: uint) -> (int, Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_sendfile, out_fd, in_fd, offset, count) + return errno_unwrap(ret, int) + } else { + ret := syscall(SYS_sendfile64, out_fd, in_fd, offset, count) + return errno_unwrap(ret, int) + } +} -/// Create a socket file descriptor -/// Available since Linux 2.0 +/* + Create a socket file descriptor. + Available since Linux 2.0. +*/ socket :: proc "contextless" (domain: Address_Family, socktype: Socket_Type, sockflags: Socket_FD_Flags, protocol: Protocol) -> (Fd, Errno) { sock_type_flags: int = cast(int) socktype | transmute(int) sockflags ret := syscall(SYS_socket, domain, sock_type_flags, protocol) return errno_unwrap(ret, Fd) } -/// Connect the socket to the address -/// Available since Linux 2.0 +/* + Connect the socket to the address. + Available since Linux 2.0. +*/ connect :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno) where T == Sock_Addr_In || @@ -322,9 +492,11 @@ where return Errno(-ret) } -/// Accept a pending connection or block until new connection appears -/// Depends on Sock_FD_Flags of the `sock` parameter. -/// Available since Linux 2.0 +/* + Accept a pending connection or block until new connection appears. + Depends on Sock_FD_Flags of the `sock` parameter. + Available since Linux 2.0. +*/ accept :: proc "contextless" (sock: Fd, addr: ^$T, sockflags: Socket_FD_Flags = {}) -> (Fd, Errno) where T == Sock_Addr_In || @@ -370,25 +542,49 @@ send_noaddr :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg) -> (i return errno_unwrap(ret, int) } -/// Receive a message from a socket -/// Available since Linux 2.0 +/* + Receive a message from a socket. + Available since Linux 2.0. +*/ recv :: proc {recvfrom, recv_noaddr} -/// Send a message through a socket -/// Available since Linux 2.0 +/* + Send a message through a socket. + Available since Linux 2.0. +*/ send :: proc {sendto, send_noaddr} -// TODO(flysand): sendmsg +/* + Send a message on a socket. + Available since Linux 2.0. +*/ +sendmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_sendmsg, sock, msghdr, transmute(i32) flags) + return errno_unwrap(ret, int) +} -// TODO(flysand): recvmsg +/* + Receive a message on a socket. + Available since Linux 2.0. +*/ +recvmsg :: proc "contextless" (sock: Fd, msghdr: ^Msg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_recvmsg, sock, msghdr, transmute(i32) flags) + return errno_unwrap(ret, int) +} +/* + Shutdown a socket. + Available since Linux 2.0. +*/ shutdown :: proc "contextless" (sock: Fd, how: Shutdown_How) -> (Errno) { ret := syscall(SYS_shutdown, sock, how) return Errno(-ret) } -/// Bind a socket to the given local address -/// Available since Linux 2.0 +/* + Bind a socket to the given local address. + Available since Linux 2.0. +*/ bind :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno) where T == Sock_Addr_In || @@ -399,18 +595,43 @@ where return Errno(-ret) } -/// Marks the socket as a socket that listen to connections using accept.2 -/// Available since Linux 2.0 +/* + Marks the socket as a socket that listen to connections using accept(2). + Available since Linux 2.0. +*/ listen :: proc "contextless" (sock: Fd, queue_len: i32) -> (Errno) { ret := syscall(SYS_listen, sock, queue_len) return Errno(-ret) } -// TODO(flysand): getsockname +/* + Get socket name (aka it's bound address). + Available since Linux 2.0. +*/ +getsockname :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) { + addr_len := size_of(Sock_Addr_Any) + ret := syscall(SYS_getsockname, sock, addr, &addr_len) + return Errno(-ret) +} -// TODO(flysand): getpeername +/* + Get the name of the connected peer socket. + Available since Linux 2.0. +*/ +getpeername :: proc "contextless" (sock: Fd, addr: ^Sock_Addr_Any) -> (Errno) { + addr_len := size_of(Sock_Addr_Any) + ret := syscall(SYS_getpeername, sock, addr, &addr_len) + return Errno(-ret) +} -// TODO(flysand): socketpair +/* + Create a pair of connected sockets. + Available since Linux 2.0. +*/ +socketpair :: proc "contextless" (domain: Protocol_Family, type: Socket_Type, proto: Protocol, pair: ^[2]Fd) -> (Errno) { + ret := syscall(SYS_socketpair, domain, type, proto, pair) + return Errno(-ret) +} // TODO(flysand): the parameters are the same, maybe there's a way to make it into a single proc, sacrificing type // safety slightly @@ -450,8 +671,10 @@ where return setsockopt_base(sock, cast(int) level, cast(int) opt, val) } -/// Set socket option for a given socket API level -/// Available since Linux 2.0 +/* + Set socket option for a given socket API level. + Available since Linux 2.0. +*/ setsockopt :: proc { setsockopt_sock, setsockopt_tcp, @@ -494,8 +717,10 @@ where return getsockopt_base(sock, cast(int) level, cast(int) opt, val) } -/// Get socket option for a given socket API level -/// Available since Linux 2.0 +/* + Get socket option for a given socket API level. + Available since Linux 2.0. +*/ getsockopt :: proc { getsockopt_sock, getsockopt_tcp, @@ -505,8 +730,10 @@ getsockopt :: proc { // TODO(flysand): clone (probably not in this PR, maybe not ever) -/// Creates a copy of the running process -/// Available since Linux 1.0 +/* + Creates a copy of the running process. + Available since Linux 1.0. +*/ fork :: proc "contextless" () -> (Pid, Errno) { when ODIN_ARCH == .arm64 { // Note(flysand): this syscall is not documented, but the bottom 8 bits of flags @@ -519,51 +746,162 @@ fork :: proc "contextless" () -> (Pid, Errno) { } } -// TODO(flysand): vfork +/* + Create a child process and block parent. + Available since Linux 2.2. +*/ +vfork :: proc "contextless" () -> Pid { + when ODIN_ARCH != .arm64 { + return Pid(syscall(SYS_vfork)) + } else { + return Pid(syscall(SYS_clone, Signal.SIGCHLD)) + } +} -// TODO(flysand): execve +/* + Replace the current process with another program. + Available since Linux 1.0. + On ARM64 available since Linux 3.19. +*/ +execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { + when ODIN_ARCH != .arm64 { + ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) + return Errno(-ret) + } else { + ret := syscall(SYS_execveat, AT_FDCWD, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) + return Errno(-ret) + } +} -/// Exit the thread with a given exit code -/// Available since Linux 1.0 +/* + Exit the thread with a given exit code. + Available since Linux 1.0. +*/ exit :: proc "contextless" (code: i32) -> ! { syscall(SYS_exit, code) unreachable() } -/// Wait for the process to change state -/// Available since Linux 1.0 +/* + Wait for the process to change state. + Available since Linux 1.0. +*/ wait4 :: proc "contextless" (pid: Pid, status: ^u32, options: Wait_Options) -> (Pid, Errno) { ret := syscall(SYS_wait4, pid, status, transmute(u32) options) return errno_unwrap(ret, Pid) } -/// See wait4 +/* + See `wait4` for documentation. +*/ waitpid :: wait4 -// TODO(flysand): kill +/* + Send signal to a process. + Available since Linux 1.0. +*/ +kill :: proc "contextless" (pid: Pid, signal: Signal) -> (Errno) { + ret := syscall(SYS_kill, pid, signal) + return Errno(-ret) +} -/// Get system information -/// Available since Linux 1.0 +/* + Get system information. + Available since Linux 1.0. +*/ uname :: proc "contextless" (uts_name: ^UTS_Name) -> (Errno) { ret := syscall(SYS_uname, uts_name) return Errno(-ret) } -// TODO(flysand): semget +/* + Get a SystemV semaphore set identifier. + Available since Linux 2.0. +*/ +semget :: proc "contextless" (key: Key, n: i32, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_semget, key, n, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): semop +/* + SystemV semaphore operations. + Available since Linux 2.0. +*/ +semop :: proc "contextless" (key: Key, ops: []Sem_Buf) -> (Errno) { + when ODIN_ARCH != .i386 { + ret := syscall(SYS_semop, key, raw_data(ops), len(ops)) + return Errno(-ret) + } else { + // Note(flysand): Max time limit, let's not worry about nanoseconds... + max_timespec := Time_Spec { + time_sec = max(uint), + time_nsec = 0, + } + ret := syscall(SYS_semtimedop_time64, key, raw_data(ops), len(ops), &max_timespec) + return Errno(-ret) + } +} -// TODO(flysand): semctl +semctl3 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd) -> (int, Errno) { + ret := syscall(SYS_semctl, key, semnum, cmd) + return errno_unwrap(ret, int) +} -// TODO(flysand): shmdt +semctl4 :: proc "contextless" (key: Key, semnum: i32, cmd: IPC_Cmd, semun: ^Sem_Un) -> (int, Errno) { + ret := syscall(SYS_semctl, key, semnum, cmd, semun) + return errno_unwrap(ret, int) +} -// TODO(flysand): msgget +/* + SystemV semaphore control operations. + Available since Linux 2.0. +*/ +semctl :: proc {semctl3, semctl4} -// TODO(flysand): msgsnd +/* + SystemV shared memory operations. + Available since Linux 2.0. +*/ +shmdt :: proc "contextless" (shmaddr: rawptr) -> (Errno) { + ret := syscall(SYS_shmdt, shmaddr) + return Errno(-ret) +} -// TODO(flysand): msgrcv +/* + Get SystemV message queue identifier. + Available since Linux 2.0. +*/ +msgget :: proc "contextless" (key: Key, flags: IPC_Flags) -> (Key, Errno) { + ret := syscall(SYS_msgget, key, transmute(i16) flags) + return errno_unwrap(ret, Key) +} -// TODO(flysand): msgctl +/* + Send message to a SystemV message queue. + Available since Linux 2.0. +*/ +msgsnd :: proc "contextless" (key: Key, buf: rawptr, size: int, flags: IPC_Flags) -> (Errno) { + ret := syscall(SYS_msgsnd, key, buf, size, transmute(i16) flags) + return Errno(-ret) +} + +/* + Receive a message from a SystemV message queue. + Available since Linux 2.0. +*/ +msgrcv :: proc "contextless" (key: Key, buf: rawptr, size: int, type: uint, flags: IPC_Flags) -> (int, Errno) { + ret := syscall(SYS_msgrcv, key, buf, size, type, transmute(i16) flags) + return errno_unwrap(ret, int) +} + +/* + SystemV message control operations. + Available since Linux 2.0. +*/ +msgctl :: proc "contextless" (key: Key, cmd: IPC_Cmd, buf: ^Msqid_DS) -> (int, Errno) { + ret := syscall(SYS_msgctl, key, cmd, buf) + return errno_unwrap(ret, int) +} fcntl_dupfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD, newfd: Fd) -> (Fd, Errno) { ret := syscall(SYS_fcntl, fd, cmd, newfd) @@ -727,18 +1065,39 @@ fcntl :: proc { fcntl_set_file_rw_hint, } -// TODO(flysand): flock +/* + Apply or remove advisory lock on an open file. + Available since Linux 2.0. +*/ +flock :: proc "contextless" (fd: Fd, operation: FLock_Op) -> (Errno) { + ret := syscall(SYS_flock, fd, transmute(i32) operation) + return Errno(-ret) +} -/// Sync state of the file with the storage device +/* + Sync state of the file with the storage device. + Available since Linux 1.0. +*/ fsync :: proc "contextless" (fd: Fd) -> (Errno) { ret := syscall(SYS_fsync, fd) return Errno(-ret) } -// TODO(flysand): fdatasync +/* + Synchronize the state of the file with the storage device. Similar to `fsync`, + except does not flush the metadata. + Available since Linux 2.0. +*/ +fdatasync :: proc "contextless" (fd: Fd) -> (Errno) { + ret := syscall(SYS_fdatasync, fd) + return Errno(-ret) +} -/// Truncate a file to specified length -/// On 32-bit architectures available since Linux 2.4 +/* + Truncate a file to specified length. + Available since Linux 1.0. + On 32-bit architectures available since Linux 2.4. +*/ truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_truncate64, cast(rawptr) name, compat64_arg_pair(length)) @@ -749,8 +1108,10 @@ truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) { } } -/// Truncate a file specified by file descriptor to specified length -/// On 32-bit architectures available since 2.4 +/* + Truncate a file specified by file descriptor to specified length. + On 32-bit architectures available since 2.4. +*/ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length)) @@ -761,38 +1122,48 @@ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) { } } -/// Retrieve the contents of the directory specified by dirfd -/// Returns the number of bytes written -/// Available since Linux 2.4 +/* + Retrieve the contents of the directory specified by dirfd. + Returns the number of bytes written. + Available since Linux 2.4. +*/ getdents :: proc "contextless" (dirfd: Fd, buf: []u8) -> (int, Errno) { ret := syscall(SYS_getdents64, dirfd, raw_data(buf), len(buf)) return errno_unwrap(ret, int) } -/// Get current working directory -/// Available since Linux 1.0 +/* + Get current working directory. + Available since Linux 1.0. +*/ getcwd :: proc "contextless" (buf: []u8) -> (int, Errno) { ret := syscall(SYS_getcwd, raw_data(buf), len(buf)) return errno_unwrap(ret, int) } -/// Change working directory to the directory specified by path -/// Available since Linux 1.0 +/* + Change working directory to the directory specified by path. + Available since Linux 1.0. +*/ chdir :: proc "contextless" (path: cstring) -> (Errno) { ret := syscall(SYS_chdir, cast(rawptr) path) return Errno(-ret) } -/// Change working directory to the directory specified by dirfd -/// Available since Linux 1.0 +/* + Change working directory to the directory specified by dirfd. + Available since Linux 1.0. +*/ fchdir :: proc "contextless" (fd: Fd) -> (Errno) { ret := syscall(SYS_fchdir, fd) return Errno(-ret) } -/// Rename (move) the file -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Rename (move) the file. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ rename :: proc "contextless" (old: cstring, new: cstring) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_renameat, AT_FDCWD, cast(rawptr) old, AT_FDCWD, cast(rawptr) new) @@ -803,9 +1174,11 @@ rename :: proc "contextless" (old: cstring, new: cstring) -> (Errno) { } } -/// Creates a directory -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Creates a directory. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ mkdir :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_mkdirat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode) @@ -816,9 +1189,11 @@ mkdir :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { } } -/// Remove a directory specified by name -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Remove a directory specified by name. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ rmdir :: proc "contextless" (name: cstring) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, transmute(i32) FD_Flags{.REMOVEDIR}) @@ -829,11 +1204,25 @@ rmdir :: proc "contextless" (name: cstring) -> (Errno) { } } -// TODO(flysand): creat +/* + Create a file. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ +creat :: proc "contextless" (name: cstring, mode: Mode) -> (Fd, Errno) { + when ODIN_ARCH == .arm64 { + return openat(AT_FDCWD, name, {.CREAT, .WRONLY,.TRUNC}, mode) + } else { + ret := syscall(SYS_creat, cast(rawptr) name, transmute(u32) mode) + return errno_unwrap(ret, Fd) + } +} -/// Create a hard link on a file -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Create a hard link on a file. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath) @@ -844,9 +1233,11 @@ link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { } } -/// Delete a name, and possible a file it refers to -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Delete a name, and possible a file it refers to. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ unlink :: proc "contextless" (name: cstring) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, 0) @@ -857,9 +1248,11 @@ unlink :: proc "contextless" (name: cstring) -> (Errno) { } } -/// Create a symbolic link -/// Available since Linux 1.0 -/// On arm64 available since Linux 2.6.16 +/* + Create a symbolic link. + Available since Linux 1.0. + On arm64 available since Linux 2.6.16. +*/ symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath) @@ -870,9 +1263,11 @@ symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) { } } -/// Read the value of a symbolic link -/// Available since Linux 1.0 -/// On arm64 available since Linux 2.6.16 +/* + Read the value of a symbolic link. + Available since Linux 1.0. + On arm64 available since Linux 2.6.16. +*/ readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_readlinkat, AT_FDCWD, cast(rawptr) name, raw_data(buf), len(buf)) @@ -883,9 +1278,11 @@ readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) { } } -/// Change file permissions -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Change file permissions. + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0) @@ -896,17 +1293,21 @@ chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) { } } -/// Change file permissions through a file descriptor -/// Available since Linux 1.0 +/* + Change file permissions through a file descriptor. + Available since Linux 1.0. +*/ fchmod :: proc "contextless" (fd: Fd, mode: Mode) -> (Errno) { ret := syscall(SYS_fchmod, fd, transmute(u32) mode) return Errno(-ret) } -/// Change ownership of a file -/// Available since Linux 2.2 -/// On 32-bit architectures available since Linux 2.4 -/// On ARM64 available since Linux 2.6.16 +/* + Change ownership of a file. + Available since Linux 2.2. + On 32-bit architectures available since Linux 2.4. + On ARM64 available since Linux 2.6.16. +*/ chown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_chown32, cast(rawptr) name, uid, gid) @@ -920,9 +1321,11 @@ chown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { } } -/// Change ownership of a file by file descriptor -/// Available since Linux 1.0 -/// On 32-bit architecvtures available since Linux 2.4 +/* + Change ownership of a file by file descriptor. + Available since Linux 1.0. + On 32-bit architecvtures available since Linux 2.4. +*/ fchown :: proc "contextless" (fd: Fd, uid: Uid, gid: Gid) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_fchown32, fd, uid, gid) @@ -933,10 +1336,12 @@ fchown :: proc "contextless" (fd: Fd, uid: Uid, gid: Gid) -> (Errno) { } } -/// Change ownership of a file. Unlike chown, if a file is a symlink dooesn't dereference it -/// Available since Linux 1.0 -/// On 32-bit architectures available since Linux 2.4 -/// On ARM64 available since Linux 2.6.16 +/* + Change ownership of a file. Unlike chown, if a file is a symlink dooesn't dereference it. + Available since Linux 1.0. + On 32-bit architectures available since Linux 2.4. + On ARM64 available since Linux 2.6.16. +*/ lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_lchown32, cast(rawptr) name, uid, gid) @@ -950,42 +1355,239 @@ lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) { } } -// TODO(flysand): umask +/* + Set file mode creation mask. + Available since Linux 1.0. +*/ +umask :: proc "contextless" (mask: Mode) -> Mode { + ret := syscall(SYS_umask, transmute(u32) mask) + return transmute(Mode) cast(u32) ret +} -// TODO(flysand): gettimeofday +/* + Get current time. + Available since Linux 1.0. +*/ +gettimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) { + ret := syscall(SYS_gettimeofday, tv) + return Errno(-ret) +} -/// Get limits on resources -/// Available since Linux 1.0 +/* + Get limits on resources. + Available since Linux 1.0. +*/ getrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) { ret := syscall(SYS_getrlimit, kind, resource) return Errno(-ret) } -/// Get resource usage -/// Available since Linux 1.0 +/* + Get resource usage. + Available since Linux 1.0. +*/ getrusage :: proc "contextless" (who: RUsage_Who, rusage: ^RUsage) -> (Errno) { ret := syscall(SYS_getrusage, who, rusage) return Errno(-ret) } -/// Get information about the system +/* + Get information about the system. + Available since Linux 1.0. +*/ sysinfo :: proc "contextless" (sysinfo: ^Sys_Info) -> (Errno) { ret := syscall(SYS_sysinfo, sysinfo) return Errno(-ret) } -/// Get current process times -/// Available since Linux 1.0 +/* + Get current process times. + Available since Linux 1.0. +*/ times :: proc "contextless" (tms: ^Tms) -> (Errno) { ret := syscall(SYS_times, cast(rawptr) tms) return Errno(-ret) } -// TODO(flysand): ptrace +ptrace_traceme :: proc "contextless" (rq: PTrace_Traceme_Type) -> (Errno) { + ret := syscall(SYS_ptrace, rq) + return Errno(-ret) +} -/// Get real user ID -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +ptrace_peek :: proc "contextless" (rq: PTrace_Peek_Type, pid: Pid, addr: uintptr) -> (uint, Errno) { + ret := syscall(SYS_ptrace, rq, pid, addr) + return errno_unwrap(ret, uint) +} + +ptrace_poke :: proc "contextless" (rq: PTrace_Poke_Type, pid: Pid, addr: uintptr, data: uint) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, addr, data) + return Errno(-ret) +} + +ptrace_getregs :: proc "contextless" (rq: PTrace_Getregs_Type, pid: Pid, buf: ^User_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_getfpregs :: proc "contextless" (rq: PTrace_Getfpregs_Type, pid: Pid, buf: ^User_FP_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_getfpxregs :: proc "contextless" (rq: PTrace_Getfpxregs_Type, pid: Pid, buf: ^User_FPX_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_setregs :: proc "contextless" (rq: PTrace_Setregs_Type, pid: Pid, buf: ^User_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_setfpregs :: proc "contextless" (rq: PTrace_Setfpregs_Type, pid: Pid, buf: ^User_FP_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_setfpxregs :: proc "contextless" (rq: PTrace_Setfpxregs_Type, pid: Pid, buf: ^User_FPX_Regs) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, buf) + return Errno(-ret) +} + +ptrace_getregset :: proc "contextless" (rq: PTrace_Getregset_Type, pid: Pid, note: PTrace_Note_Type, buf: ^IO_Vec) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, note, buf) + return Errno(-ret) +} + +ptrace_setregset :: proc "contextless" (rq: PTrace_Setregset_Type, pid: Pid, note: PTrace_Note_Type, buf: ^IO_Vec) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, note, buf) + return Errno(-ret) +} + +ptrace_getsiginfo :: proc "contextless" (rq: PTrace_Getsiginfo_Type, pid: Pid, si: ^Sig_Info) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, si) + return Errno(-ret) +} + +ptrace_peeksiginfo :: proc "contextless" (rq: PTrace_Peeksiginfo_Type, pid: Pid, si: ^Sig_Info) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, si) + return Errno(-ret) +} + +ptrace_getsigmask :: proc "contextless" (rq: PTrace_Getsigmask_Type, pid: Pid, sigmask: ^Sig_Set) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, size_of(Sig_Set), sigmask) + return Errno(-ret) +} + +ptrace_setsigmask :: proc "contextless" (rq: PTrace_Setsigmask_Type, pid: Pid, sigmask: ^Sig_Set) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, size_of(Sig_Set), sigmask) + return Errno(-ret) +} + +ptrace_setoptions :: proc "contextless" (rq: PTrace_Setoptions_Type, pid: Pid, options: PTrace_Options) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, transmute(u32) options) + return Errno(-ret) +} + +ptrace_geteventmsg :: proc "contextless" (rq: PTrace_Geteventmsg_Type, pid: Pid, msg: ^uint) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, msg) + return Errno(-ret) +} + +ptrace_cont :: proc "contextless" (rq: PTrace_Cont_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, sig) + return Errno(-ret) +} + +ptrace_singlestep :: proc "contextless" (rq: PTrace_Singlestep_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, sig) + return Errno(-ret) +} + +ptrace_syscall :: proc "contextless" (rq: PTrace_Syscall_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, sig) + return Errno(-ret) +} + +ptrace_sysemu :: proc "contextless" (rq: PTrace_Sysemu_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, sig) + return Errno(-ret) +} + +ptrace_sysemu_singlestep :: proc "contextless" (rq: PTrace_Sysemu_Singlestep_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, sig) + return Errno(-ret) +} + +ptrace_listen :: proc "contextless" (rq: PTrace_Listen_Type, pid: Pid) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid) + return Errno(-ret) +} + +ptrace_interrupt :: proc "contextless" (rq: PTrace_Interrupt_Type, pid: Pid) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid) + return Errno(-ret) +} + +ptrace_attach :: proc "contextless" (rq: PTrace_Attach_Type, pid: Pid) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid) + return Errno(-ret) +} + +ptrace_seize :: proc "contextless" (rq: PTrace_Seize_Type, pid: Pid, opt: PTrace_Options) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, transmute(u32) opt) + return Errno(-ret) +} + +// TODO(flysand): ptrace_seccomp_get_filter + +ptrace_detach :: proc "contextless" (rq: PTrace_Detach_Type, pid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_ptrace, rq, pid, 0, sig) + return Errno(-ret) +} + +// TODO(flysand): ptrace_get_thread_area +// TODO(flysand): ptrace_set_thread_area +// TODO(flysand): ptrace_get_syscall_info + +/* + Trace process. +*/ +ptrace :: proc { + ptrace_traceme, + ptrace_peek, + ptrace_poke, + ptrace_getregs, + ptrace_getfpregs, + ptrace_getfpxregs, + ptrace_setregs, + ptrace_setfpregs, + ptrace_setfpxregs, + ptrace_getregset, + ptrace_setregset, + ptrace_getsiginfo, + ptrace_peeksiginfo, + ptrace_getsigmask, + ptrace_setsigmask, + ptrace_setoptions, + ptrace_geteventmsg, + ptrace_cont, + ptrace_singlestep, + ptrace_syscall, + ptrace_sysemu, + ptrace_sysemu_singlestep, + ptrace_listen, + ptrace_interrupt, + ptrace_attach, + ptrace_seize, + ptrace_detach, +} + +/* + Get real user ID. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ getuid :: proc "contextless" () -> Uid { when size_of(int) == 8 { return cast(Uid) syscall(SYS_getuid) @@ -994,11 +1596,20 @@ getuid :: proc "contextless" () -> Uid { } } -// TODO(flysand): syslog +/* + Read or clear kernel message ring buffer. + Available since Linux 1.0. +*/ +syslog :: proc "contextless" (act: Syslog_Action, buf: []u8) -> (int, Errno) { + ret := syscall(SYS_syslog, act, raw_data(buf), len(buf)) + return errno_unwrap(ret, int) +} -/// Get real group ID -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Get real group ID. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ getgid :: proc "contextless" () -> Gid { when size_of(int) == 8 { return cast(Gid) syscall(SYS_getgid) @@ -1007,9 +1618,11 @@ getgid :: proc "contextless" () -> Gid { } } -/// Set effective user id -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Set effective User ID. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setuid :: proc "contextless" (uid: Uid) -> (Errno) { when size_of(int) == 8 { @@ -1021,10 +1634,12 @@ setuid :: proc "contextless" (uid: Uid) -> (Errno) { } } -/// Set effective group id -/// If the process is privileged also sets real group id -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Set effective group id. + If the process is privileged also sets real group id. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setgid :: proc "contextless" (gid: Gid) -> (Errno) { when size_of(int) == 8 { @@ -1036,9 +1651,11 @@ setgid :: proc "contextless" (gid: Gid) -> (Errno) { } } -/// Get effective user ID -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Get effective user ID. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ geteuid :: proc "contextless" () -> Uid { when size_of(int) == 8 { return cast(Uid) syscall(SYS_geteuid) @@ -1047,9 +1664,11 @@ geteuid :: proc "contextless" () -> Uid { } } -/// Get effective group ID -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Get effective group ID. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ getegid :: proc "contextless" () -> Gid { when size_of(int) == 8 { return cast(Gid) syscall(SYS_getegid) @@ -1058,21 +1677,27 @@ getegid :: proc "contextless" () -> Gid { } } -/// Set process group -/// Available since Linux 1.0 +/* + Set process group. + Available since Linux 1.0. +*/ setpgid :: proc "contextless" (pid: Pid, pgid: Pid) -> (Errno) { ret := syscall(SYS_setpgid, pid, pgid) return Errno(-ret) } -/// Get the parent process ID -/// Available since Linux 1.0 +/* + Get the parent process ID. + Available since Linux 1.0. +*/ getppid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_getppid) } -/// Get process group -/// Available since Linux 1.0 +/* + Get process group. + Available since Linux 1.0. +*/ getpgrp :: proc "contextless" () -> (Pid, Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_getpgid, 0) @@ -1083,17 +1708,21 @@ getpgrp :: proc "contextless" () -> (Pid, Errno) { } } -/// Create a session and set the process group ID -/// Available since Linux 2.0 +/* + Create a session and set the process group ID. + Available since Linux 2.0. +*/ setsid :: proc "contextless" () -> (Errno) { ret := syscall(SYS_setsid) return Errno(-ret) } -/// Set real and/or effective user id -/// If any of the arguments is -1, the corresponding id is not changed -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Set real and/or effective user id. + If any of the arguments is -1, the corresponding id is not changed. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setreuid :: proc "contextless" (real: Uid, effective: Uid) -> (Errno) { when size_of(int) == 8 { @@ -1105,10 +1734,12 @@ setreuid :: proc "contextless" (real: Uid, effective: Uid) -> (Errno) { } } -/// Set real and/or effective group id -/// If any of the arguments is -1, the corresponding id is not changed -/// Available since Linux 1.0 -/// On 32-bit platforms available since Linux 2.4 +/* + Set real and/or effective group id. + If any of the arguments is -1, the corresponding id is not changed. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setregid :: proc "contextless" (real: Gid, effective: Gid) -> (Errno) { when size_of(int) == 8 { @@ -1120,14 +1751,42 @@ setregid :: proc "contextless" (real: Gid, effective: Gid) -> (Errno) { } } -// TODO(flysand): getgroups +/* + Get supplementary group IDs. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ +getgroups :: proc "contextless" (gids: []Gid) -> (int, Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_getgroups, len(gids), raw_data(gids)) + return errno_unwrap(ret, int) + } else { + ret := syscall(SYS_getgroups32, len(gids), raw_data(gids)) + return errno_unwrap(ret, int) + } +} -// TODO(flysand): setgroups +/* + Set supplementary group IDs. + Available since Linux 1.0. + On 32-bit platforms available since Linux 2.4. +*/ +setgroups :: proc "contextless" (gids: []Gid) -> (Errno) { + when size_of(int) == 8 { + ret := syscall(SYS_setgroups, len(gids), raw_data(gids)) + return Errno(-ret) + } else { + ret := syscall(SYS_setgroups32, len(gids), raw_data(gids)) + return Errno(-ret) + } +} -/// Set real, effective and/or saved user id -/// If any of the arguments is -1, the corresponding id is not changed -/// Available since Linux 2.2 -/// On 32-bit platforms available since Linux 2.4 +/* + Set real, effective and/or saved user id. + If any of the arguments is -1, the corresponding id is not changed. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setresuid :: proc "contextless" (real: Uid, effective: Uid, saved: Uid) -> (Errno) { when size_of(int) == 8 { @@ -1139,9 +1798,11 @@ setresuid :: proc "contextless" (real: Uid, effective: Uid, saved: Uid) -> (Errn } } -/// Get real, effective and saved user id -/// Available since Linux 2.2 -/// On 32-bit platforms available since Linux 2.4 +/* + Get real, effective and saved user id. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.4. +*/ getresuid :: proc "contextless" (real: ^Uid, effective: ^Uid, saved: ^Uid) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_getresuid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) @@ -1152,10 +1813,12 @@ getresuid :: proc "contextless" (real: ^Uid, effective: ^Uid, saved: ^Uid) -> (E } } -/// Set real, effective and/or saved group id -/// If any of the arguments is -1, the corresponding id is not changed -/// Available since Linux 2.2 -/// On 32-bit platforms available since Linux 2.4 +/* + Set real, effective and/or saved group id. + If any of the arguments is -1, the corresponding id is not changed. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.4. +*/ @(require_results) setresgid :: proc "contextless" (real: Gid, effective: Gid, saved: Uid) -> (Errno) { when size_of(int) == 8 { @@ -1167,9 +1830,11 @@ setresgid :: proc "contextless" (real: Gid, effective: Gid, saved: Uid) -> (Errn } } -/// Get real, effective and saved group id -/// Available since Linux 2.2 -/// On 32-bit platforms available since Linux 2.4 +/* + Get real, effective and saved group id. + Available since Linux 2.2. + On 32-bit platforms available since Linux 2.4. +*/ getresgid :: proc "contextless" (real: ^Gid, effective: ^Gid, saved: ^Gid) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_getresgid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved) @@ -1180,17 +1845,19 @@ getresgid :: proc "contextless" (real: ^Gid, effective: ^Gid, saved: ^Gid) -> (E } } -/// Get process group -/// Available since Linux 1.0 +/* + Get process group. + Available since Linux 1.0. +*/ getpgid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { ret := syscall(SYS_getpgid, pid) return errno_unwrap(ret, Pid) } -// NOTE(flysand): setfsuid and setfsgid are deprecated - -/// Get session ID of the calling process -/// Available since Linux 2.0 +/* + Get session ID of the calling process. + Available since Linux 2.0. +*/ getsid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { ret := syscall(SYS_getsid, pid) return errno_unwrap(ret, Pid) @@ -1200,48 +1867,60 @@ getsid :: proc "contextless" (pid: Pid) -> (Pid, Errno) { // TODO(flysand): capset -/// Examine pending signals -/// Available since Linux 2.2 +/* + Examine pending signals. + Available since Linux 2.2. +*/ rt_sigpending :: proc "contextless" (sigs: ^Sig_Set) -> Errno { ret := syscall(SYS_rt_sigpending, sigs, size_of(Sig_Set)) return Errno(-ret) } -/// Synchronously wait for queued signals -/// Available since Linux 2.2 +/* + Synchronously wait for queued signals. + Available since Linux 2.2. +*/ rt_sigtimedwait :: proc "contextless" (sigs: ^Sig_Set, info: ^Sig_Info, time_sus: ^Time_Spec) -> (Signal, Errno) { ret := syscall(SYS_rt_sigtimedwait, sigs, info, time_sus, size_of(Sig_Set)) return errno_unwrap(ret, Signal) } -/// Send signal information to a process -/// Available since Linux 2.2 +/* + Send signal information to a process. + Available since Linux 2.2. +*/ rt_sigqueueinfo :: proc "contextless" (pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) { ret := syscall(SYS_rt_sigqueueinfo, pid, sig, si) return Errno(-ret) } -/// Replace the signal mask for a value with the new mask until a signal is received -/// Available since Linux 2.2 +/* + Replace the signal mask for a value with the new mask until a signal is received. + Available since Linux 2.2. +*/ rt_sigsuspend :: proc "contextless" (sigset: ^Sig_Set) -> Errno { ret := syscall(SYS_rt_sigsuspend, sigset, size_of(Sig_Set)) return Errno(-ret) } -/// Set or get signal stack context -/// Available since Linux 2.2 +/* + Set or get signal stack context. + Available since Linux 2.2. +*/ sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) -> (Errno) { ret := syscall(SYS_sigaltstack, stack, old_stack) return Errno(-ret) } -// TODO(flysand): utime - -/// Create a special or ordinary file -/// `mode` parameter contains both the the file mode and the type of the node to create -/// -> Add one of S_IFSOCK, S_IFBLK, S_IFFIFO, S_IFCHR to mode -/// Available since Linux 1.0 -/// On ARM64 available since Linux 2.6.16 +/* + Create a special or ordinary file. + + `mode` parameter contains both the the file mode and the type of the node to create. + -> Add one of S_IFSOCK, S_IFBLK, S_IFFIFO, S_IFCHR to mode. + + Available since Linux 1.0. + On ARM64 available since Linux 2.6.16. +*/ mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) { when ODIN_ARCH == .arm64 { ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, dev) @@ -1252,10 +1931,10 @@ mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) { } } -// TODO(flysand): uselib - -/// Set the process execution domain -/// Available since Linux 1.2 +/* + Set the process execution domain. + Available since Linux 1.2. +*/ personality :: proc "contextless" (personality: uint) -> (uint, Errno) { ret := syscall(SYS_personality, personality) return errno_unwrap(ret, uint) @@ -1263,10 +1942,12 @@ personality :: proc "contextless" (personality: uint) -> (uint, Errno) { // TODO(flysand): ustat -/// Query information about filesystem -/// -/// Available since Linux 1.0 -/// For 32-bit systems a different syscall is used that became available since 2.6 +/* + Query information about filesystem. + + Available since Linux 1.0. + For 32-bit systems a different syscall is used that became available since 2.6. +*/ statfs :: proc "contextless" (path: cstring, statfs: ^Stat_FS) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_statfs, transmute(uintptr) path, statfs) @@ -1277,10 +1958,12 @@ statfs :: proc "contextless" (path: cstring, statfs: ^Stat_FS) -> (Errno) { } } -/// Query information about filesystem by file descriptor -/// -/// Available since Linux 1.0 -/// For 32-bit systems a different syscall is used that became available since 2.6 +/* + Query information about filesystem by file descriptor. + + Available since Linux 1.0. + For 32-bit systems a different syscall is used that became available since 2.6. +*/ fstatfs :: proc "contextless" (fd: Fd, statfs: ^Stat_FS) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_statfs, fd, statfs) @@ -1293,8 +1976,10 @@ fstatfs :: proc "contextless" (fd: Fd, statfs: ^Stat_FS) -> (Errno) { // TODO(flysand): sysfs -/// Get priority on user, process group or process -/// Available since Linux 1.0 +/* + Get priority on user, process group or process. + Available since Linux 1.0. +*/ getpriority :: proc "contextless" (which: Priority_Which, who: i32) -> (i32, Errno) { ret := syscall(SYS_getpriority, which, who) prio, err := errno_unwrap(ret, i32) @@ -1304,8 +1989,10 @@ getpriority :: proc "contextless" (which: Priority_Which, who: i32) -> (i32, Err return prio, err } -/// Set priority on user, process group or process -/// Available since Linux 1.0 +/* + Set priority on user, process group or process. + Available since Linux 1.0. +*/ setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) -> (Errno) { ret := syscall(SYS_setpriority, which, who, prio) return Errno(-ret) @@ -1325,9 +2012,11 @@ setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) - // TODO(flysand): sched_rr_get_interval -/// Lock and memory -/// Available since Linux 2.0 -/// If flags specified, available since Linux 4.4 +/* + Lock and memory. + Available since Linux 2.0. + If flags specified, available since Linux 4.4. +*/ mlock :: proc "contextless" (addr: rawptr, size: uint, flags: MLock_Flags = {}) -> (Errno) { // Pretty darn recent syscall, better call simpler version if we can if flags > {} { @@ -1339,20 +2028,28 @@ mlock :: proc "contextless" (addr: rawptr, size: uint, flags: MLock_Flags = {}) } } -/// Unlock memory -/// Available since Linux 2.0 +/* + Unlock memory. + Available since Linux 2.0. +*/ munlock :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) { ret := syscall(SYS_munlock, addr, size) return Errno(-ret) } -/// Lock all memory +/* + Lock all memory. + Available since Linux 2.0. +*/ mlockall :: proc "contextless" (flags: MLock_Flags = {}) -> (Errno) { ret := syscall(SYS_mlockall, transmute(i32) flags) return Errno(-ret) } -/// Unlock all memory +/* + Unlock all memory. + Available since Linux 2.0. +*/ munlockall :: proc "contextless" () -> (Errno) { ret := syscall(SYS_munlockall) return Errno(-ret) @@ -1372,8 +2069,10 @@ munlockall :: proc "contextless" () -> (Errno) { // TODO(flysand): adj_timex -/// Set limits on resources -/// Available since Linux 1.0 +/* + Set limits on resources. + Available since Linux 1.0. +*/ setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) { ret := syscall(SYS_setrlimit, kind, resource) return Errno(-ret) @@ -1395,17 +2094,21 @@ setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno // TODO(flysand): reboot -/// Set hostname -/// Note: to get the host name, use `uname` syscall -/// Available since Linux 1.0 +/* + Set hostname. + Note: to get the host name, use `uname` syscall. + Available since Linux 1.0. +*/ sethostname :: proc "contextless" (hostname: string) -> (Errno) { ret := syscall(SYS_sethostname, raw_data(hostname), len(hostname)) return Errno(-ret) } -/// Set domain name -/// Note: to get the domain name, use `uname` syscall -/// Available since Linux 2.2 +/* + Set domain name. + Note: to get the domain name, use `uname` syscall. + Available since Linux 2.2. +*/ setdomainname :: proc "contextless" (name: string) -> (Errno) { ret := syscall(SYS_setdomainname, raw_data(name), len(name)) return Errno(-ret) @@ -1415,16 +2118,10 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) { // TODO(flysand): ioperm -// TODO(flysand): create_module - // TODO(flysand): init_module // TODO(flysand): delete_module -// TODO(flysand): get_kernel_syms - -// TODO(flysand): query_module - // TODO(flysand): quotactl // TODO(flysand): nfsservctl @@ -1439,12 +2136,14 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) { // TODO(flysand): security -/// Returns the thread ID of the current process -/// This is what the kernel calls "pid" -/// Let me insert a tiny rant here, this terminology is confusing: -/// sometimes pid refers to a thread, and other times it refers -/// to a thread group (process group?) -/// Anyway, this syscall is available since Linux 1.0 +/* + Returns the thread ID of the current process + This is what the kernel calls "pid". + Let me insert a tiny rant here, this terminology is confusing: + sometimes pid refers to a thread, and other times it refers + to a thread group (process group?) + Anyway, this syscall is available since Linux 1.0 +*/ gettid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_gettid) } @@ -1475,19 +2174,35 @@ gettid :: proc "contextless" () -> Pid { // TODO(flysand): fremovexattr -// TODO(flysand): tkill +/* + Get current time in seconds. + Available since Linux 1.0. +*/ +time :: proc "contextless" (tloc: ^uint) -> (Errno) { + when ODIN_ARCH != .arm64 { + ret := syscall(SYS_time, tloc) + return Errno(-ret) + } else { + ts: Time_Spec + ret := syscall(SYS_clock_gettime, Clock_Id.REALTIME, &ts) + tloc^ = ts.time_sec + return Errno(-ret) + } +} -// TODO(flysand): time - -/// Wait on a futex until it's signaled +/* + Wait on a futex until it's signaled. +*/ futex_wait :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Type, flags: Futex_Flags, val: u32, timeout: ^Time_Spec = nil) -> (Errno) { futex_flags := cast(u32) op + transmute(u32) flags ret := syscall(SYS_futex, futex, futex_flags, val, timeout) return Errno(-ret) } -/// Wake up other threads on a futex -/// n_wakeup specifies the number of processes to wakeup. Specify max(i32) to wake up all processes waiting +/* + Wake up other threads on a futex + n_wakeup specifies the number of processes to wakeup. Specify max(i32) to wake up all processes waiting +*/ futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Futex_Flags, n_wakeup: i32) -> (int, Errno) { futex_flags := cast(u32) op + transmute(u32) flags ret := syscall(SYS_futex, futex, futex_flags, n_wakeup) @@ -1496,12 +2211,14 @@ futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Fut // NOTE(flysand): futex_fd is racy, so not implemented -/// Requeues processes waiting on futex `futex` to wait on futex `requeue_futex` -/// `requeue_threshold` specifies the maximum amount of waiters to wake up, the rest of the waiters will be requeued -/// `requeue_max` specifies the maximum amount of waiters that are required at `requeue_futex` -/// The operation blocks until the `requeue_max` requirement is satisfied -/// If the value of the mutex is not equal to `val`, fails with EAGAIN before any further checks -/// Returns the total number of waiters that have been woken up plus the number of waiters requeued +/* + Requeues processes waiting on futex `futex` to wait on futex `requeue_futex` + `requeue_threshold` specifies the maximum amount of waiters to wake up, the rest of the waiters will be requeued + `requeue_max` specifies the maximum amount of waiters that are required at `requeue_futex` + The operation blocks until the `requeue_max` requirement is satisfied + If the value of the mutex is not equal to `val`, fails with EAGAIN before any further checks + Returns the total number of waiters that have been woken up plus the number of waiters requeued. +*/ futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32, requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno) { @@ -1510,8 +2227,10 @@ futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Ty return errno_unwrap(ret, int) } -/// See `futex_cmp_requeue`, this function does the same thing but doesn't check the value of the futex -/// Returns the total number of waiters that have been woken up +/* + See `futex_cmp_requeue`, this function does the same thing but doesn't check the value of the futex. + Returns the total number of waiters that have been woken up. +*/ futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32, requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno) { @@ -1520,8 +2239,10 @@ futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flag return errno_unwrap(ret, int) } -/// Okay, for this one, see the man pages, the description for it is pretty long and very specific. It's sole -/// purpose is to allow implementing conditional values sync primitive, it seems like +/* + Okay, for this one, see the man pages, the description for it is pretty long and very specific. It's sole. + purpose is to allow implementing conditional values sync primitive, it seems like. +*/ futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flags: Futex_Flags, wakeup: i32, dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno) { @@ -1530,7 +2251,9 @@ futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flag return errno_unwrap(ret, int) } -/// Same as wait, but mask specifies bits that must be equal for the mutex to wake up +/* + Same as wait, but mask specifies bits that must be equal for the mutex to wake up. +*/ futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Type, flags: Futex_Flags, val: u32, timeout: ^Time_Spec, mask: u32) -> (int, Errno) { @@ -1539,7 +2262,9 @@ futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Ty return errno_unwrap(ret, int) } -/// Wake up on bitset +/* + Wake up on bitset. +*/ futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno) { futex_flags := cast(u32) op + transmute(u32) flags @@ -1579,36 +2304,82 @@ futex :: proc { // TODO(flysand): lookup_dcookie -// TODO(flysand): epoll_create - -// TODO(flysand): epoll_ctl_old - -// TODO(flysand): epoll_wait_old +/* + Open an epoll file descriptor. + + The `size` argument is ignored but must be greater than zero. + + Available since Linux 2.6. +*/ +epoll_create :: proc(size: i32 = 1) -> (Fd, Errno) { + when ODIN_ARCH != .arm64 { + ret := syscall(SYS_epoll_create) + return errno_unwrap(ret, Fd) + } else { + ret := syscall(SYS_epoll_create1, i32(0)) + return errno_unwrap(ret, Fd) + } +} // TODO(flysand): remap_file_pages -/// Set the address of the futex that's gonna be waken when -/// current thread terminates -/// Available since Linux 2.6 +/* + Set the address of the futex that's gonna be waken when. + current thread terminates. + Available since Linux 2.6. +*/ set_tid_address :: proc "contextless" (tidptr: ^u32) { syscall(SYS_set_tid_address, tidptr) } -// TODO(flysand): restart_syscall - // TODO(flysand): semtimedop // TODO(flysand): fadvise64 -// TODO(flysand): timer_create +/* + Create POSIX per-process timer. + Available since Linux 2.6. +*/ +timer_create :: proc "contextless" (clock_id: Clock_Id, sigevent: ^Sig_Event, timer: ^Timer) -> (Errno) { + ret := syscall(SYS_timer_create, clock_id, sigevent, timer) + return Errno(-ret) +} -// TODO(flysand): timer_settime +/* + Get the state of the POSIX per-process timer. + Available since Linux 2.6. +*/ +timer_gettime :: proc "contextless" (timer: Timer, curr_value: ^ITimer_Spec) -> (Errno) { + ret := syscall(SYS_timer_gettime, timer, curr_value) + return Errno(-ret) +} -// TODO(flysand): timer_gettime +/* + Arm/disarm the state of the POSIX per-process timer. + Available since Linux 2.6. +*/ +timer_settime :: proc "contextless" (timer: Timer, flags: ITimer_Flags, #no_alias new_value, old_value: ^ITimer_Spec) -> (Errno) { + ret := syscall(SYS_timer_settime, timer, transmute(u32) flags, new_value, old_value) + return Errno(-ret) +} -// TODO(flysand): timer_getoverrun +/* + Get overrun count of the POSIX per-process timer. + Available since Linux 2.6. +*/ +timer_getoverrun :: proc "contextless" (timer: Timer) -> (int, Errno) { + ret := syscall(SYS_timer_getoverrun, timer) + return errno_unwrap(ret, int) +} -// TODO(flysand): timer_delete +/* + Delete a POSIX per-process timer. + Available since Linux 2.6. +*/ +timer_delete :: proc "contextless" (timer: Timer) -> (Errno) { + ret := syscall(SYS_timer_delete, timer) + return Errno(-ret) +} // TODO(flysand): clock_settime @@ -1618,18 +2389,54 @@ set_tid_address :: proc "contextless" (tidptr: ^u32) { // TODO(flysand): clock_nanosleep -/// Exit the thread group -/// Available since Linux 2.6 +/* + Exit the thread group. + Available since Linux 2.6. +*/ exit_group :: proc "contextless" (code: i32) -> ! { syscall(SYS_exit_group, code) unreachable() } -// TODO(flysand): epoll_wait +/* + Wait for an I/O event on an epoll file descriptor. + + `timeout` is specified in milliseconds. + + Available since Linux 2.6. +*/ +epoll_wait :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: i32) -> (i32, Errno) { + when ODIN_ARCH != .arm64 { + ret := syscall(SYS_epoll_wait, epfd, events, count, timeout) + return errno_unwrap(ret, i32) + } else { + // Convert milliseconds to nanosecond timespec + timeout_ns := Time_Spec { + time_sec = uint(timeout * 1000), + time_nsec = 0, + } + ret := syscall(SYS_epoll_pwait, epfd, events, count, &timeout_ns, rawptr(nil)) + return errno_unwrap(ret, i32) + } +} -// TODO(flysand): epoll_ctl +/* + Control interface for an epoll file descriptor. + Available since Linux 2.6. +*/ +epoll_ctl :: proc(epfd: Fd, op: EPoll_Ctl_Opcode, fd: Fd, event: ^EPoll_Event) -> (Errno) { + ret := syscall(SYS_epoll_ctl, epfd, op, fd, event) + return Errno(-ret) +} -// TODO(flysand): tgkill +/* + Send a signal to a specific thread in a thread group. + Available since Linux 2.6. +*/ +tgkill :: proc "contextless" (tgid, tid: Pid, sig: Signal) -> (Errno) { + ret := syscall(SYS_tgkill, tgid, tid, sig) + return Errno(-ret) +} // TODO(flysand): utimes @@ -1655,9 +2462,10 @@ exit_group :: proc "contextless" (code: i32) -> ! { // TODO(flysand): kexec_load - -/// Wait on process, process group or pid file descriptor -/// Available since Linux 2.6.10 +/* + Wait on process, process group or pid file descriptor. + Available since Linux 2.6.10. +*/ waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) { ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options) return Errno(-ret) @@ -1681,38 +2489,46 @@ waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, opt // TODO(flysand): migrate_pages -/// Open file at the specified file descriptor -/// Available since Linux 2.6.16 +/* + Open file at the specified file descriptor. + Available since Linux 2.6.16. +*/ openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) { ret := syscall(SYS_openat, fd, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode) return errno_unwrap(ret, Fd) } -/// Create a directory relative to specified dirfd -/// Available since Linux 2.6.16 +/* + Create a directory relative to specified dirfd. + Available since Linux 2.6.16. +*/ mkdirat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode) -> (Errno) { ret := syscall(SYS_mkdirat, dirfd, cast(rawptr) name, transmute(u32) mode) return Errno(-ret) } -/// Create a special or ordinary file wrt given directory specified by dirfd -/// Available since Linux 2.6.16 +/* + Create a special or ordinary file wrt given directory specified by dirfd. + Available since Linux 2.6.16. +*/ mknodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, dev: Dev) -> (Errno) { ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, dev) return Errno(-ret) } -/// Change the ownership of the file specified relative to directory -/// Available since Linux 2.6.16 +/* + Change the ownership of the file specified relative to directory. + Available since Linux 2.6.16. +*/ fchownat :: proc "contextless" (dirfd: Fd, name: cstring, uid: Uid, gid: Gid) -> (Errno) { ret := syscall(SYS_fchownat, dirfd, cast(rawptr) name, uid, gid) return Errno(-ret) } -// TODO(flysand): futimesat - -/// Get information about a file at a specific directory -/// Available since Linux 2.6.16 +/* + Get information about a file at a specific directory. + Available since Linux 2.6.16. +*/ fstatat :: proc "contextless" (dirfd: Fd, name: cstring, stat: ^Stat, flags: FD_Flags) -> (Errno) { when size_of(int) == 4 { ret := syscall(SYS_fstatat64, dirfd, cast(rawptr) name, stat, transmute(i32) flags) @@ -1726,59 +2542,73 @@ fstatat :: proc "contextless" (dirfd: Fd, name: cstring, stat: ^Stat, flags: FD_ } } -/// Remove a directory entry relative to a directory file descriptor -/// Available since Linux 2.6.16 +/* + Remove a directory entry relative to a directory file descriptor. + Available since Linux 2.6.16. +*/ unlinkat :: proc "contextless" (dirfd: Fd, name: cstring, flags: FD_Flags) -> (Errno) { ret := syscall(SYS_unlinkat, dirfd, cast(rawptr) name, transmute(i32) flags) return Errno(-ret) } -/// Rename the file with names relative to the specified dirfd's -/// Available since Linux 2.6.16 +/* + Rename the file with names relative to the specified dirfd's. + Available since Linux 2.6.16. +*/ renameat :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring) -> (Errno) { ret := syscall(SYS_renameat, oldfd, cast(rawptr) old, newfd, cast(rawptr) new) return Errno(-ret) } -/// Creates a hard link on a file relative to specified dirfd -/// Available since Linux 2.6.16 +/* + Creates a hard link on a file relative to specified dirfd. + Available since Linux 2.6.16. +*/ linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd, link: cstring, flags: FD_Flags) -> (Errno) { ret := syscall(SYS_linkat, target_dirfd, cast(rawptr) oldpath, link_dirfd, cast(rawptr) link, transmute(i32) flags) return Errno(-ret) } -/// Create a symbolic link at specified dirfd -/// Available since Linux 2.6.16 +/* + Create a symbolic link at specified dirfd. + Available since Linux 2.6.16. +*/ symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) { ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath) return Errno(-ret) } -/// Read the value of a symbolic link at given dirfd -/// Available since Linux 2.6.16 +/* + Read the value of a symbolic link at given dirfd. + Available since Linux 2.6.16. +*/ readlinkat :: proc "contextless" (dirfd: Fd, name: cstring, buf: []u8) -> (int, Errno) { ret := syscall(SYS_readlinkat, dirfd, cast(rawptr) name, raw_data(buf), len(buf)) return errno_unwrap(ret, int) } -/// Change the file mode at a specified file descriptor -/// Available since Linux 2.6.16 +/* + Change the file mode at a specified file descriptor. + Available since Linux 2.6.16. +*/ fchmodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, flags: FD_Flags) -> (Errno) { ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags) return Errno(-ret) } -/// Checks the user permissions for a file at specified dirfd -/// Available since Linux 2.6.16 +/* + Checks the user permissions for a file at specified dirfd. + Available since Linux 2.6.16. +*/ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) -> (bool, Errno) { ret := syscall(SYS_faccessat, dirfd, cast(rawptr) name, transmute(u32) mode) return errno_unwrap(ret, bool) } -// TODO(flysand): pselect6 - -/// Wait for events on a file descriptor -/// Available since Linux 2.6.16 +/* + Wait for events on a file descriptor. + Available since Linux 2.6.16. +*/ ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (Errno) { when size_of(int) == 8 { ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set)) @@ -1795,9 +2625,23 @@ ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_ // TODO(flysand): get_robust_list -// TODO(flysand): splice +/* + Transfer the data between file descriptors. + Available since Linux 2.6.17. +*/ +splice :: proc "contextless" (fd_in: Fd, off_in: ^i64, fd_out: Fd, off_out: ^i64, len: uint, flags: Splice_Flags) -> (int, Errno) { + ret := syscall(SYS_splice, fd_in, off_in, fd_out, off_out, len, transmute(u32) flags) + return errno_unwrap(ret, int) +} -// TODO(flysand): tee +/* + Transfer the data between file descriptors. + Available since Linux 2.6.16. +*/ +tee :: proc "contextless" (fd_in: Fd, fd_out: Fd, len: uint, flags: Splice_Flags) -> (int, Errno) { + ret := syscall(SYS_tee, fd_in, fd_out, len, transmute(u32) flags) + return errno_unwrap(ret, int) +} // TODO(flysand): sync_file_range @@ -1805,14 +2649,25 @@ ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_ // TODO(flysand): move_pages -/// Change file timestamps with nanosecond precision -/// Available since Linux 2.6.22 -utimensat :: proc "contextless" (dirfd: Fd, name: cstring, timespec: ^Time_Spec, flags: FD_Flags) -> (Errno) { - ret := syscall(SYS_utimensat, dirfd, cast(rawptr) name, timespec, transmute(i32) flags) +/* + Change file timestamps with nanosecond precision. + **utimes** must point to an array of two `Time_Spec`'s. The "utime" is the + last access time, the second is last modification time. + Available since Linux 2.6.22. +*/ +utimensat :: proc "contextless" (dirfd: Fd, name: cstring, utimes: [^]Time_Spec, flags: FD_Flags) -> (Errno) { + ret := syscall(SYS_utimensat, dirfd, cast(rawptr) name, utimes, transmute(i32) flags) return Errno(-ret) } -// TODO(flysand): epoll_pwait +/* + Wait for an I/O event on an epoll file descriptor. + Available since Linux 2.6. +*/ +epoll_pwait :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: i32, sigmask: ^Sig_Set) -> (i32, Errno) { + ret := syscall(SYS_epoll_pwait, epfd, events, count, timeout, sigmask) + return errno_unwrap(ret, i32) +} // TODO(flysand): signalfd @@ -1832,11 +2687,16 @@ utimensat :: proc "contextless" (dirfd: Fd, name: cstring, timespec: ^Time_Spec, // TODO(flysand): eventfd2 -// TODO(flysand): epoll_create1 +epoll_create1 :: proc(flags: EPoll_Flags) -> (Fd, Errno) { + ret := syscall(SYS_epoll_create1, transmute(i32) flags) + return errno_unwrap(ret, Fd) +} -/// Adjust an existing file descriptor to point to the same file as `old` -/// In addition to dup2 allows to pass O_CLOEXEC flag -/// Available since Linux 2.6.27 +/* + Adjust an existing file descriptor to point to the same file as `old`. + In addition to dup2 allows to pass O_CLOEXEC flag. + Available since Linux 2.6.27. +*/ dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno) { ret := syscall(SYS_dup3, old, new, transmute(i32) flags) return errno_unwrap(ret, Fd) @@ -1848,7 +2708,6 @@ dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno) // TODO(flysand): pwritev - /// Send signal information to a thread /// Available since Linux 2.2 rt_tgsigqueueinfo :: proc "contextless" (tgid: Pid, pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) { @@ -1856,14 +2715,23 @@ rt_tgsigqueueinfo :: proc "contextless" (tgid: Pid, pid: Pid, sig: Signal, si: ^ return Errno(-ret) } -/// Set up performance monitoring -/// Available since Linux 2.6.31 +/* + Set up performance monitoring. + Available since Linux 2.6.31. +*/ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: int, group_fd: Fd, flags: Perf_Flags = {}) -> (Fd, Errno) { ret := syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, transmute(uint) flags) return errno_unwrap(ret, Fd) } -// TODO(flysand): recvmmsg +/* + Receive multiple messages from a socket. + Available since Linux 2.6.33. +*/ +recvmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_recvmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags) + return errno_unwrap(ret, int) +} // TODO(flysand): fanotify_init @@ -1879,7 +2747,14 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in // TODO(flysand): syncfs -// TODO(flysand): sendmmsg +/* + Send multiple messages on a socket. + Available since Linux 3.0. +*/ +sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg) -> (int, Errno) { + ret := syscall(SYS_sendmmsg, sock, raw_data(msg_vec), len(msg_vec), transmute(i32) flags) + return errno_unwrap(ret, int) +} // TODO(flysand): setns @@ -1897,8 +2772,10 @@ perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: in // TODO(flysand): sched_getattr -/// Rename the file with names relative to the specified dirfd's with other options -/// Available since Linux 3.15 +/* + Rename the file with names relative to the specified dirfd's with other options. + Available since Linux 3.15. +*/ renameat2 :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring, flags: Rename_Flags) -> (Errno) { ret := syscall(SYS_renameat2, oldfd, cast(rawptr) old, newfd, cast(rawptr) new, transmute(u32) flags) return Errno(-ret) @@ -1917,7 +2794,14 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er // TODO(flysand): bpf -// TODO(flysand): execveat +/* + Execute program relative to a directory file descriptor. + Available since Linux 3.19. +*/ +execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { + ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) + return Errno(-ret) +} // TODO(flysand): userfaultfd @@ -1937,14 +2821,16 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er // TODO(flysand): pkey_free -/// Query extended information about the file -/// -/// The file can be specified as: -/// absolute pathname: `dir` parameter is ignored -/// relatvie pathname: `dir` parameter specifies the base directory's fd -/// file descriptor: `AT_EMPTY_PATH` is passed in flags, pathname is empty, `dir` specifies the file descriptor -/// -/// Available since Linux 4.11 +/* + Query extended information about the file + + The file can be specified as: + - absolute pathname: `dir` parameter is ignored + - relatvie pathname: `dir` parameter specifies the base directory's fd + - file descriptor: `AT_EMPTY_PATH` is passed in flags, pathname is empty, `dir` specifies the file descriptor + + Available since Linux 4.11 +*/ statx :: proc "contextless" (dir: Fd, pathname: cstring, flags: FD_Flags, mask: Statx_Mask, statx: ^Statx) -> (Errno) { ret := syscall(SYS_statx, dir, transmute(uintptr) pathname, transmute(i32) flags, transmute(u32) mask, statx) return Errno(-ret) @@ -1974,10 +2860,12 @@ statx :: proc "contextless" (dir: Fd, pathname: cstring, flags: FD_Flags, mask: // TODO(flysand): fspick -/// Creates a new PID file descriptor -/// The process identified by `pid` must be a pid group leader -/// The returned `pidfd` has `CLOEXEC` semantics -/// Available since Linux 5.3 +/* + Creates a new PID file descriptor. + The process identified by `pid` must be a pid group leader. + The returned `pidfd` has `CLOEXEC` semantics. + Available since Linux 5.3. +*/ pidfd_open :: proc "contextless" (pid: Pid, flags: Pid_FD_Flags) -> (Pid_FD, Errno) { ret := syscall(SYS_pidfd_open, pid, transmute(i32) flags) return errno_unwrap(ret, Pid_FD) @@ -1985,9 +2873,11 @@ pidfd_open :: proc "contextless" (pid: Pid, flags: Pid_FD_Flags) -> (Pid_FD, Err // TODO(flysand): clone3 (probably not this PR) -/// Close the range of files as an atomic operation -/// The range of file descriptors is inclusive, and may contain invalid file descriptors -/// Available since Linux 5.9 +/* + Close the range of files as an atomic operation. + The range of file descriptors is inclusive, and may contain invalid file descriptors. + Available since Linux 5.9. +*/ close_range :: proc "contextless" (lo: Fd, hi: Fd, flags: Close_Range_Flags) -> (Errno) { ret := syscall(SYS_close_range, lo, hi, transmute(u32) flags) return Errno(-ret) @@ -1995,17 +2885,21 @@ close_range :: proc "contextless" (lo: Fd, hi: Fd, flags: Close_Range_Flags) -> // TODO(flysand): openat2 -/// Get a file descriptor from another process -/// `fd` refers to a file descriptor number to get -/// `flags` must be zero -/// Available since Linux 5.3 +/* + Get a file descriptor from another process. + - `fd` refers to a file descriptor number to get. + - `flags` must be zero. + Available since Linux 5.3. +*/ pidfd_getfd :: proc "contextless" (pidfd: Pid_FD, fd: Fd, flags: i32 = 0) -> (Fd, Errno) { ret := syscall(SYS_pidfd_getfd, pidfd, fd, flags) return errno_unwrap(ret, Fd) } -/// Checks the user permissions for a file at specified dirfd (with flags) -/// Available since Linux 5.8 +/* + Checks the user permissions for a file at specified dirfd (with flags). + Available since Linux 5.8. +*/ faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, flags: FD_Flags = FD_Flags{}) -> (bool, Errno) { ret := syscall(SYS_faccessat2, dirfd, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags) return errno_unwrap(ret, bool) @@ -2013,7 +2907,14 @@ faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, f // TODO(flysand): process_madvise -// TODO(flysand): epoll_pwait2 +/* + Wait for an I/O event on an epoll file descriptor. + Available since Linux 2.6. +*/ +epoll_pwait2 :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) { + ret := syscall(SYS_epoll_pwait2, epfd, events, count, timeout, sigmask) + return errno_unwrap(ret, i32) +} // TODO(flysand): mount_setattr diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 8789ca2d1..677bac7e0 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -1,56 +1,103 @@ -//+build linux package linux -/// Represents storage device handle +/* + Type for storage device handle. +*/ Dev :: distinct int -/// Represents 32-bit user id +/* + Type for 32-bit User IDs. +*/ Uid :: distinct u32 -/// Represents 32-bit group id +/* + Type for 32-bit Group IDs. +*/ Gid :: distinct u32 -/// Process id's +/* + Type for Process IDs, Thread IDs, Thread group ID. +*/ Pid :: distinct int -/// Represents pid, pifd, pgid values in general +/* + Type for any of: pid, pidfd, pgid. +*/ Id :: distinct uint -/// Represents a file descriptor +/* + Represents a file descriptor. +*/ Fd :: distinct i32 -/// Represents a PID file descriptor +/* + Type for PID file descriptors. +*/ Pid_FD :: distinct i32 -/// Represents 64-bit inode number for files -/// Used pretty much only in struct Stat64 for 32-bit platforms +/* + Type for 64-bit inode number for files. + Used pretty much only in struct Stat64 for 32-bit platforms. +*/ Inode :: distinct u64 -/// Represents time with nanosecond precision +/* + Shared memory identifiers used by shmget(2) and other calls. +*/ +Key :: distinct i32 + +/* + Represents timer IDs. +*/ +Timer :: distinct i32 + +/* + Represents time with nanosecond precision. +*/ Time_Spec :: struct { time_sec: uint, time_nsec: uint, } -/// Represents time with millisecond precision +/* + Represents time with millisecond precision. +*/ Time_Val :: struct { seconds: int, microseconds: int, } -/// open.2 flags +/* + Access and modification times for files +*/ +UTim_Buf :: struct { + actime: uint, + modtime: uint, +} + +/* + Flags for open(2). +*/ Open_Flags :: bit_set[Open_Flags_Bits; u32] -/// Flags for the file descriptor to be passed in some syscalls +/* + Flags for the file descriptors. +*/ FD_Flags :: bit_set[FD_Flags_Bits; i32] -/// Represents file's permission and status bits -/// Example: -/// When you're passing a value of this type the recommended usage is -/// sys.Mode{.S_IXOTH, .S_IROTH} | sys.S_IRWXU | sys.S_IRWXG -/// This would generate a mode that has full permissions for the -/// file's owner and group, and only "read" and "execute" bits -/// for others. +/* + Represents file's permission and status bits +**Example:** + When you're passing a value of this type the recommended usage is: + + ``` + linux.Mode{.S_IXOTH, .S_IROTH} | linux.S_IRWXU | linux.S_IRWXG + ``` + + This would generate a mode that has full permissions for the + file's owner and group, and only "read" and "execute" bits + for others. +*/ Mode :: bit_set[Mode_Bits; u32] when ODIN_ARCH == .amd64 { @@ -111,29 +158,38 @@ when ODIN_ARCH == .amd64 { } } -/// Represents the file state. -/// Mirrors struct stat in glibc/linux kernel. -/// If you're on 32-bit platform, consider using Stat64 instead +/* + Represents the file state. + If you're on 32-bit platform, consider using Stat64 instead. +*/ Stat :: struct { using _impl_stat: _Arch_Stat, } -/// Timestamp type used for Statx struct +/* + Timestamp type used for Statx struct +*/ Statx_Timestamp :: struct { sec: i64, nsec: u32, _: i32, } -/// Query params/results for `statx()` +/* + Query params/results for `statx()`. +*/ Statx_Mask :: bit_set[Statx_Mask_Bits; u32] -/// File attributes, returned by statx. This bitset is also -/// used to specify which attributes are present, not just -/// their value. +/* + File attributes, returned by statx. This bitset is also + used to specify which attributes are present, not just + their value. +*/ Statx_Attr :: bit_set[Statx_Attr_Bits; u64] -/// The extended Stat struct +/* + The extended Stat struct, the argument to statx(2) syscall. +*/ Statx :: struct { mask: Statx_Mask, blksize: u32, @@ -165,7 +221,9 @@ Statx :: struct { _: [12]u64, } -/// Mount flags for filesystem +/* + Mount flags for filesystem. +*/ FS_Flags :: bit_set[FS_Flags_Bits; u32] when size_of(int) == 8 { @@ -205,19 +263,28 @@ when size_of(int) == 8 { } } +/* + Struct for statfs(2). +*/ Stat_FS :: struct { using _impl_stat_fs: _Arch_Stat_FS, } -/// Flags for close_range.2 +/* + Flags for close_range(2). +*/ Close_Range_Flags :: bit_set[Close_Range_Flags_Bits; u32] -/// Flags for rename.2 +/* + Flags for rename(2). +*/ Rename_Flags :: bit_set[Rename_Flags_Bits; u32] -/// Directory entry -/// Recommended to use this with dirent_iterator() -/// and dirent_name() +/* + Directory entry record. + Recommended iterate these with `dirent_iterator()`, + and obtain the name via `dirent_name()`. +*/ Dirent :: struct { ino: Inode, off: i64, @@ -226,7 +293,9 @@ Dirent :: struct { name: [0]u8, // See dirent_name } -/// Lock record for fcntl.2 +/* + Lock record for fcntl(2). +*/ FLock :: struct { type: FLock_Type, whence: Seek_Whence, @@ -235,62 +304,101 @@ FLock :: struct { pid: Pid, } -/// Flags for fcntl_notify +/* + File locking operations. + Use one of `EX`, `RW` or `UN` to specify the operation, and add `UN` if + you need a non-blocking operation. +*/ +FLock_Op :: bit_set[FLock_Op_Bits; i32] + +/* + Flags for `fcntl_notify()`. +*/ FD_Notifications :: bit_set[FD_Notifications_Bits; i32] -/// Seals for fcntl_add_seals +/* + Seals for `fcntl_add_seals()`. +*/ Seal :: bit_set[Seal_Bits; i32] -/// Represents owner that receives events on file updates +/* + Represents owner that receives events on file updates. +*/ F_Owner :: struct { type: F_Owner_Type, pid: Pid, } -/// Events for ppoll +/* + Events for ppoll(2). +*/ Fd_Poll_Events :: bit_set[Fd_Poll_Events_Bits; u16] -/// Struct for ppoll +/* + Struct for ppoll(2). +*/ Poll_Fd :: struct { fd: Fd, events: Fd_Poll_Events, revents: Fd_Poll_Events, } -/// Specifies protection for memory pages +/* + Specifies protection for memory pages. +*/ Mem_Protection :: bit_set[Mem_Protection_Bits; i32] -/// Flags for mmap +/* + Flags for mmap. +*/ Map_Flags :: bit_set[Map_Flags_Bits; i32] -/// Flags for mlock.2 +/* + Flags for mlock(2). +*/ MLock_Flags :: bit_set[MLock_Flags_Bits; u32] -/// Flags for msync.2 +/* + Flags for msync(2). +*/ MSync_Flags :: bit_set[MSync_Flags_Bits; i32] -/// Access rights for pkey_alloc.2 +/* + Access rights for pkey_alloc(2). +*/ PKey_Access_Rights :: bit_set[PKey_Access_Bits; u32] -/// Flags for mremap.2 +/* + Flags for mremap(2). +*/ MRemap_Flags :: bit_set[MRemap_Flags_Bits; i32] -/// Flags for getrandom syscall +/* + Flags for getrandom(2) syscall. +*/ Get_Random_Flags :: bit_set[Get_Random_Flags_Bits; i32] -/// Flags for perf_event_open syscall +/* + Flags for perf_event_open(2) syscall. +*/ Perf_Flags :: bit_set[Perf_Flags_Bits; uint] Perf_Event_Flags :: distinct bit_set[Perf_Event_Flags_Bits; u64] +Perf_Read_Format :: distinct bit_set[Perf_Read_Format_Bits; u64] + Perf_Cap_Flags :: distinct bit_set[Perf_Cap_Flags_Bits; u64] Perf_Event_Sample_Type :: bit_set[Perf_Event_Sample_Type_Bits; u64] -/// Specifies which branches to include in branch record +/* + Specifies which branches to include in branch record. +*/ Branch_Sample_Type :: bit_set[Branch_Sample_Type_Bits; u64] -/// The struct for perf_event_open +/* + The struct for perf_event_open. +*/ Perf_Event_Attr :: struct #packed { type: Perf_Event_Type, size: u32, @@ -334,7 +442,9 @@ Perf_Event_Attr :: struct #packed { _: u16, } -/// The ring buffer structure when mmaping Perf_Event_Attr +/* + The ring buffer structure when mmaping Perf_Event_Attr. +*/ Perf_Event_Mmap_Page :: struct #packed { version: u32, compat_version: u32, @@ -369,10 +479,14 @@ Perf_Event_Mmap_Page :: struct #packed { // TODO(flysand): Its taking too much effort to bind the other data structures related to perf_event_open -/// Options for wait4() and waitpid() +/* + Options for wait4(2) and waitpid(2). +*/ Wait_Options :: bit_set[Wait_Option; i32] -/// Flags for pidfd_open.2 +/* + Flags for pidfd_open(2). +*/ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32] // Note(flysand): these could, in principle be implemented with bitfields, @@ -439,6 +553,28 @@ Sig_Info :: struct #packed { }, } +SIGEV_MAX_SIZE :: 64 +SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32)) + +Sig_Val :: struct #raw_union { + sival_int: i32, + sival_ptr: rawptr, +} + +Sig_Event :: struct { + value: Sig_Val, + signo: i32, + notify: i32, + using _: struct #raw_union { + _: [SIGEV_PAD_SIZE]u32, + thread_id: Pid, + using _: struct { + notify_function: #type proc "c" (val: Sig_Val), + notify_attribute: rawptr, + }, + }, +} + Sig_Stack_Flags :: bit_set[Sig_Stack_Flag; i32] Sig_Stack :: struct { @@ -457,27 +593,36 @@ Sig_Action :: struct($T: typeid) { mask: Sig_Set, } - -/// Flags for the socket file descriptor -/// Note, on linux these are technically passed by OR'ing together -/// with Socket_Type, our wrapper does this under the hood. +/* + Flags for the socket file descriptor. + Note, on linux these are technically passed by OR'ing together + with Socket_Type, our wrapper does this under the hood. +*/ Socket_FD_Flags :: bit_set[Socket_FD_Flags_Bits; int] -/// Address family for the socket -/// Typically there's one address family for every protocol family +/* + Address family for the socket. + Typically there's one address family for every protocol family. +*/ Address_Family :: distinct Protocol_Family -/// Flags for the socket for send/recv calls +/* + Flags for the socket for send/recv calls. +*/ Socket_Msg :: bit_set[Socket_Msg_Bits; i32] -/// Struct representing IPv4 socket address +/* + Struct representing IPv4 socket address. +*/ Sock_Addr_In :: struct #packed { sin_family: Address_Family, sin_port: u16be, sin_addr: [4]u8, } -/// Struct representing IPv6 socket address +/* + Struct representing IPv6 socket address. +*/ Sock_Addr_In6 :: struct #packed { sin6_family: Address_Family, sin6_port: u16be, @@ -486,7 +631,9 @@ Sock_Addr_In6 :: struct #packed { sin6_scope_id: u32, } -/// Struct representing an arbitrary socket address +/* + Struct representing an arbitrary socket address. +*/ Sock_Addr_Any :: struct #raw_union { using _: struct { family: Address_Family, @@ -496,13 +643,38 @@ Sock_Addr_Any :: struct #raw_union { using ipv6: Sock_Addr_In6, } -/// Just an alias to make futex-values more visible +/* + Message header for sendmsg/recvmsg +*/ +Msg_Hdr :: struct { + name: rawptr, + namelen: i32, + iov: []IO_Vec, // ptr followed by length, abi matches + control: []u8, + flags: Socket_Msg, +} + +/* + Multiple message header for sendmmsg/recvmmsg +*/ +MMsg_Hdr :: struct { + hdr: Msg_Hdr, + len: u32, +} + +/* + Just an alias to make futex-values more visible +*/ Futex :: u32 -/// Flags for the futex (they are kept separately) +/* + Flags for the futex (they are kept separately) +*/ Futex_Flags :: bit_set[Futex_Flags_Bits; u32] -/// Times +/* + Times +*/ Tms :: struct { tms_utime: int, tms_stime: int, @@ -510,8 +682,10 @@ Tms :: struct { tms_cstime: int, } -/// "Unix time-sharing system name", allegedly -/// Basically system info +/* + "Unix time-sharing system name", allegedly. + Basically system info. +*/ UTS_Name :: struct { sysname: [65]u8 `fmt:"s,0"`, nodename: [65]u8 `fmt:"s,0"`, @@ -521,7 +695,9 @@ UTS_Name :: struct { domainname: [65]u8 `fmt:"s,0"`, } -/// Return buffer for the sysinfo syscall +/* + Return buffer for the sysinfo syscall +*/ Sys_Info :: struct { uptime: int, loads: [3]int, @@ -538,14 +714,17 @@ Sys_Info :: struct { _padding: [20 - (2 * size_of(int)) - size_of(i32)]u8, } -/// Resource limit +/* + Resource limit +*/ RLimit :: struct { cur: uint, max: uint, } -/// Structure representing how much of each resource -/// got used. +/* + Structure representing how much of each resource got used. +*/ RUsage :: struct { utime: Time_Val, stime: Time_Val, @@ -564,3 +743,498 @@ RUsage :: struct { nvcsw_word: int, nivcsw_word: int, } + +/* + Struct used for IO operations +*/ +IO_Vec :: struct { + base: rawptr, + len: uint, +} + +/* + Access mode for shared memory +*/ +IPC_Mode :: bit_set[IPC_Mode_Bits; u32] + +/* + Flags used by IPC objects +*/ +IPC_Flags :: bit_set[IPC_Flags_Bits; i16] + +/* + Permissions for IPC objects +*/ +IPC_Perm :: struct { + key: Key, + uid: u32, + gid: u32, + cuid: u32, + cgid: u32, + mode: IPC_Mode, + seq: u16, + _: [2 + 2*size_of(int)]u8, +} + +when size_of(int) == 8 || ODIN_ARCH == .i386 { + // 32-bit and 64-bit x86, 64-bit arm + _Arch_Shmid_DS :: struct { + perm: IPC_Perm, + segsz: uint, + atime: int, + dtime: int, + ctime: int, + cpid: Pid, + lpid: Pid, + nattch: uint, + _: [2]uint, + } +} else { + // Other 32-bit platforms + // NOTE(flysand): I'm not risking assuming it's little endian... + _Arch_Shmid_DS :: struct { + perm: IPC_Perm, + segsz: uint, + atime: uint, + atime_high: uint, + dtime: uint, + dtime_high: uint, + ctime: uint, + ctime_high: uint, + cpid: Pid, + lpid: Pid, + nattach: uint, + _: [2]uint, + } +} + +/* + SystemV shared memory data. +*/ +Shmid_DS :: _Arch_Shmid_DS + +/* + SystemV shared memory info. +*/ +Shm_Info :: struct { + used_ids: i32, + shm_tot: uint, + shm_rss: uint, + shm_swp: uint, + swap_attempts: uint, + swap_successes: uint, +} + +/* + SystemV semaphore operation. +*/ +Sem_Buf :: struct { + num: u16, + op: IPC_Cmd, + flg: IPC_Flags, +} + +when ODIN_ARCH == .i386 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: uint, + otime_high: uint, + ctime: uint, + ctime_high: uint, + nsems: uint, + _: [2]uint, + } +} else when ODIN_ARCH == .amd64 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: int, + ctime: int, + nsems: uint, + _: [2]uint, + } +} else when ODIN_ARCH == .arm32 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: uint, + otime_high: uint, + ctime: uint, + ctime_high: uint, + nsems: uint, + _: [2]uint, + } +} else when ODIN_ARCH == .arm64 { + _Arch_Semid_DS :: struct { + perm: IPC_Perm, + otime: int, + ctime: int, + sem_nsems: uint, + __unused3: uint, + __unused4: uint, + } +} + +/* + Architecture-specific semaphore data. +*/ +Semid_DS :: _Arch_Semid_DS + +/* + Argument for semctl functions +*/ +Sem_Un :: struct #raw_union { + val: i32, + buf: rawptr, + array: u16, + __buf: Sem_Info, + _: uintptr, +} + +/* + SystenV semaphore info. +*/ +Sem_Info :: struct { + semmap: i32, + mni: i32, + mns: i32, + mnu: i32, + msl: i32, + opm: i32, + ume: i32, + usz: i32, + vmx: i32, + aem: i32, +} + +/* + Template for the struct used for sending and receiving messages +*/ +Msg_Buf :: struct { + type: int, + text: [0]u8, +} + +/* + SystemV message queue data. +*/ +Msqid_DS :: struct { + perm: IPC_Perm, + stime: uint, + rtime: uint, + ctime: uint, + cbytes: uint, + qnum: uint, + qbytes: uint, + lspid: Pid, + lrpid: Pid, + _: [2]uint, +} + +/* + Interval timer types +*/ +ITimer_Which :: enum { + REAL = 0, + VIRTUAL = 1, + PROF = 2, +} + +/* + Interval timer value +*/ +ITimer_Val :: struct { + interval: Time_Val, + value: Time_Val, +} + +ITimer_Spec :: struct { + interval: Time_Spec, + value: Time_Spec, +} + +/* + Flags for POSIX interval timers. +*/ +ITimer_Flags :: bit_set[ITimer_Flags_Bits; u32] + +when ODIN_ARCH == .arm32 { + _Arch_User_Regs :: struct { + cpsr: uint, + pc: uint, + lr: uint, + sp: uint, + ip: uint, + fp: uint, + r10: uint, + r9: uint, + r8: uint, + r7: uint, + r6: uint, + r5: uint, + r4: uint, + r3: uint, + r2: uint, + r1: uint, + r0: uint, + ORIG_r0: uint, + } + // TODO(flysand): Idk what to do about these, couldn't find their + // definitions + _Arch_User_FP_Regs :: struct {} + _Arch_User_FPX_Regs :: struct {} +} else when ODIN_ARCH == .arm64 { + _Arch_User_Regs :: struct { + regs: [31]uint, + sp: uint, + pc: uint, + pstate: uint, + } + _Arch_User_FP_Regs :: struct { + vregs: [32]u128, + fpsr: u32, + fpcr: u32, + _: [2]u32, + } + _Arch_User_FPX_Regs :: struct {} +} else when ODIN_ARCH == .i386 { + _Arch_User_Regs :: struct { + ebx: uint, + ecx: uint, + edx: uint, + esi: uint, + edi: uint, + ebp: uint, + eax: uint, + xds: uint, + xes: uint, + xfs: uint, + xgs: uint, + orig_eax: uint, + eip: uint, + xcs: uint, + eflags: uint, + esp: uint, + xss: uint, + } + // x87 FPU state + _Arch_User_FP_Regs :: struct { + cwd: uint, + swd: uint, + twd: uint, + fip: uint, + fcs: uint, + foo: uint, + fos: uint, + st_space: [20]uint, + } + // FXSR instruction set state + _Arch_User_FPX_Regs :: struct { + cwd: u16, + swd: u16, + twd: u16, + fop: u16, + fip: uint, + fcs: uint, + foo: uint, + fos: uint, + mxcsr: uint, + _: uint, + st_space: [32]uint, + xmm_space: [32]uint, + padding: [56]uint, + } +} else when ODIN_ARCH == .amd64 { + _Arch_User_Regs :: struct { + // Callee-preserved, may not be correct if the syscall doesn't need + // these registers + r15: uint, + r14: uint, + r13: uint, + r12: uint, + rbp: uint, + rbx: uint, + // Always saved + r11: uint, + r10: uint, + r9: uint, + r8: uint, + rax: uint, + rcx: uint, + rdx: uint, + rsi: uint, + rdi: uint, + // On syscall entry this is the syscall number, on CPU exception this + // is the error code, on hardware interrupt this is its IRQ number + orig_rax: uint, + // Return frame for iretq + rip: uint, + cs: uint, + eflags: uint, + rsp: uint, + ss: uint, + } + // All floating point state + _Arch_User_FP_Regs :: struct { + cwd: u16, + swd: u16, + twd: u16, + fop: u16, + rip: uint, + rdp: uint, + mxcsr: u32, + mxcsr_mask: u32, + st_space: [32]u32, + xmm_space: [64]u32, + _: [24]u32, + } + // FXSR instruction set state + _Arch_User_FPX_Regs :: struct { + cwd: u16, + swd: u16, + twd: u16, + fop: u16, + fip: uint, + fcs: uint, + foo: uint, + fos: uint, + mxcsr: uint, + _: uint, + st_space: [32]uint, + xmm_space: [32]uint, + padding: [56]uint, + } +} + +/* + Architecture-specific registers struct. +*/ +User_Regs :: _Arch_User_Regs + +/* + Architecture-specific floating-point registers +*/ +User_FP_Regs :: _Arch_User_FP_Regs + +/* + Architecture-specific extended floating-point registers. + Currently only used for x86 CPU's. +*/ +User_FPX_Regs :: _Arch_User_FPX_Regs + +/* + ptrace options. +*/ +PTrace_Options :: bit_set[PTrace_Options_Bits; u32] + +/* + ptrace's PEEKSIGINFO argument. +*/ +PTrace_Peek_Sig_Info_Args :: struct { + off: u64, + flags: PTrace_Peek_Sig_Info_Flags, + nr: i32, +} + +/* + ptrace's PEEKSIGINFO flags. +*/ +PTrace_Peek_Sig_Info_Flags :: bit_set[PTrace_Peek_Sig_Info_Flags_Bits; u32] + +/* + ptrace's SECCOMP metadata. +*/ +PTrace_Seccomp_Metadata :: struct { + filter_off: u64, + flags: u64, +} + +/* + ptrace's results of GET_SYSCALL_INFO. +*/ +PTrace_Syscall_Info :: struct { + op: PTrace_Get_Syscall_Info_Op, + arch: u32, // TODO: AUDIT_ARCH* + instruction_pointer: u64, + stack_pointer: u64, + using _: struct #raw_union { + entry: struct { + nr: u64, + args: [6]u64, + }, + exit: struct { + rval: i64, + is_error: b8, + }, + seccomp: struct { + nr: u64, + args: [6]u64, + ret_data: u32, + }, + }, +} + +/* + ptrace's results of GET_RSEQ_CONFIGURATION. +*/ +PTrace_RSeq_Configuration :: struct { + rseq_abi_pointer: u64, + rseq_abi_size: u32, + signature: u32, + flags: u32, + _: u32, +} + +/* + Note types for PTRACE_GETREGSET. Mirrors constants in `elf` definition, + files though this enum only contains the constants defined for architectures + Odin can compile to. +*/ +PTrace_Note_Type :: enum { + NT_PRSTATUS = 1, + NT_PRFPREG = 2, + NT_PRPSINFO = 3, + NT_TASKSTRUCT = 4, + NT_AUXV = 6, + NT_SIGINFO = 0x53494749, + NT_FILE = 0x46494c45, + NT_PRXFPREG = 0x46e62b7f, + NT_386_TLS = 0x200, + NT_386_IOPERM = 0x201, + NT_X86_XSTATE = 0x202, + NT_X86_SHSTK = 0x204, + NT_ARM_VFP = 0x400, + NT_ARM_TLS = 0x401, + NT_ARM_HW_BREAK = 0x402, + NT_ARM_HW_WATCH = 0x403, + NT_ARM_SYSTEM_CALL = 0x404, + NT_ARM_SVE = 0x405, + NT_ARM_PAC_MASK = 0x406, + NT_ARM_PACA_KEYS = 0x407, + NT_ARM_PACG_KEYS = 0x408, + NT_ARM_TAGGED_ADDR_CTRL = 0x409, + NT_ARM_PAC_ENABLED_KEYS = 0x40a, + NT_ARM_SSVE = 0x40b, + NT_ARM_ZA = 0x40c, + NT_ARM_ZT = 0x40d, +} + +/* + Flags for splice(2) and tee(2) syscalls. +*/ +Splice_Flags :: bit_set[Splice_Flags_Bits; u32] + +/* + Flags for epoll_create(2) syscall. +*/ +EPoll_Flags :: bit_set[EPoll_Flags_Bits; i32] + +EPoll_Data :: struct #raw_union { + ptr: rawptr, + fd: Fd, + u32: u32, + u64: u64, +} + +EPoll_Event :: struct #packed { + events: EPoll_Event_Kind, + data: EPoll_Data, +} diff --git a/core/sys/windows/advapi32.odin b/core/sys/windows/advapi32.odin index dc7ec1e08..163bf2a5e 100644 --- a/core/sys/windows/advapi32.odin +++ b/core/sys/windows/advapi32.odin @@ -5,7 +5,7 @@ foreign import advapi32 "system:Advapi32.lib" HCRYPTPROV :: distinct HANDLE -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign advapi32 { @(link_name = "SystemFunction036") RtlGenRandom :: proc(RandomBuffer: ^u8, RandomBufferLength: ULONG) -> BOOLEAN --- @@ -13,13 +13,18 @@ foreign advapi32 { DesiredAccess: DWORD, TokenHandle: ^HANDLE) -> BOOL --- + OpenThreadToken :: proc(ThreadHandle: HANDLE, + DesiredAccess: DWORD, + OpenAsSelf: BOOL, + TokenHandle: ^HANDLE) -> BOOL --- + CryptAcquireContextW :: proc(hProv: ^HCRYPTPROV, szContainer, szProvider: wstring, dwProvType, dwFlags: DWORD) -> DWORD --- CryptGenRandom :: proc(hProv: HCRYPTPROV, dwLen: DWORD, buf: LPVOID) -> DWORD --- CryptReleaseContext :: proc(hProv: HCRYPTPROV, dwFlags: DWORD) -> DWORD --- } // Necessary to create a token to impersonate a user with for CreateProcessAsUser -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign advapi32 { LogonUserW :: proc( lpszUsername: LPCWSTR, diff --git a/core/sys/windows/bcrypt.odin b/core/sys/windows/bcrypt.odin index 52eb4b1b6..d891aa92b 100644 --- a/core/sys/windows/bcrypt.odin +++ b/core/sys/windows/bcrypt.odin @@ -5,7 +5,7 @@ foreign import bcrypt "system:Bcrypt.lib" BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD : 0x00000002 -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign bcrypt { BCryptGenRandom :: proc(hAlgorithm: LPVOID, pBuffer: [^]u8, cbBuffer: ULONG, dwFlags: ULONG) -> LONG --- } diff --git a/core/sys/windows/bluetooth.odin b/core/sys/windows/bluetooth.odin index c2534896b..7bfb7ea96 100644 --- a/core/sys/windows/bluetooth.odin +++ b/core/sys/windows/bluetooth.odin @@ -51,7 +51,7 @@ BLUETOOTH_DEVICE_INFO :: struct { name: [BLUETOOTH_MAX_NAME_SIZE]u16, // Name of the device } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign bthprops { /* Version diff --git a/core/sys/windows/comctl32.odin b/core/sys/windows/comctl32.odin index 983c45d36..9c4404a9d 100644 --- a/core/sys/windows/comctl32.odin +++ b/core/sys/windows/comctl32.odin @@ -3,7 +3,7 @@ package sys_windows foreign import "system:Comctl32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Comctl32 { LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT --- } diff --git a/core/sys/windows/comdlg32.odin b/core/sys/windows/comdlg32.odin index 8284050f1..30d9b169c 100644 --- a/core/sys/windows/comdlg32.odin +++ b/core/sys/windows/comdlg32.odin @@ -3,7 +3,7 @@ package sys_windows foreign import "system:Comdlg32.lib" -LPOFNHOOKPROC :: #type proc "stdcall" (hdlg: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> UINT_PTR +LPOFNHOOKPROC :: #type proc "system" (hdlg: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> UINT_PTR OPENFILENAMEW :: struct { lStructSize: DWORD, @@ -31,7 +31,7 @@ OPENFILENAMEW :: struct { FlagsEx: DWORD, } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Comdlg32 { GetOpenFileNameW :: proc(arg1: ^OPENFILENAMEW) -> BOOL --- GetSaveFileNameW :: proc(arg1: ^OPENFILENAMEW) -> BOOL --- diff --git a/core/sys/windows/dbghelp.odin b/core/sys/windows/dbghelp.odin new file mode 100644 index 000000000..c2e506748 --- /dev/null +++ b/core/sys/windows/dbghelp.odin @@ -0,0 +1,250 @@ +// +build windows +package sys_windows + +foreign import "system:Dbghelp.lib" + +RVA :: DWORD + +MINIDUMP_LOCATION_DESCRIPTOR :: struct { + DataSize: ULONG32, + Rva: RVA, +} + +MINIDUMP_DIRECTORY :: struct { + StreamType: ULONG32, + Location: MINIDUMP_LOCATION_DESCRIPTOR, +} + +MINIDUMP_EXCEPTION_INFORMATION :: struct { + ThreadId: DWORD, + ExceptionPointers: ^EXCEPTION_POINTERS, + ClientPointers: BOOL, +} + +MINIDUMP_MEMORY_INFO :: struct { + BaseAddress: ULONG64, + AllocationBase: ULONG64, + AllocationProtect: ULONG32, + __alignment1: ULONG32, + RegionSize: ULONG64, + State: ULONG32, + Protect: ULONG32, + Type: ULONG32, + __alignment2: ULONG32, +} + +MINIDUMP_USER_STREAM :: struct { + Type: ULONG32, + BufferSize: ULONG, + Buffer: PVOID, +} + +MINIDUMP_USER_STREAM_INFORMATION :: struct { + UserStreamCount: ULONG, + UserStreamArray: ^MINIDUMP_USER_STREAM, +} + +MINIDUMP_CALLBACK_ROUTINE :: #type proc "system" ( + CallbackParam: PVOID, + CallbackInput: ^MINIDUMP_CALLBACK_INPUT, + CallbackOutpu: ^MINIDUMP_CALLBACK_OUTPUT, +) -> BOOL + +MINIDUMP_CALLBACK_INFORMATION :: struct { + CallbackRoutine: MINIDUMP_CALLBACK_ROUTINE, + CallbackParam: PVOID, +} + +MINIDUMP_CALLBACK_INPUT :: struct { + ProcessId: ULONG, + ProcessHandle: HANDLE, + CallbackType: ULONG, + using _: struct #raw_union { + Status: HRESULT, + Thread: MINIDUMP_THREAD_CALLBACK, + ThreadEx: MINIDUMP_THREAD_EX_CALLBACK, + Module: MINIDUMP_MODULE_CALLBACK, + IncludeThread: MINIDUMP_INCLUDE_THREAD_CALLBACK, + IncludeModule: MINIDUMP_INCLUDE_MODULE_CALLBACK, + Io: MINIDUMP_IO_CALLBACK, + ReadMemoryFailure: MINIDUMP_READ_MEMORY_FAILURE_CALLBACK, + SecondaryFlags: ULONG, + VmQuery: MINIDUMP_VM_QUERY_CALLBACK, + VmPreRead: MINIDUMP_VM_PRE_READ_CALLBACK, + VmPostRead: MINIDUMP_VM_POST_READ_CALLBACK, + }, +} + +_MINIDUMP_ARM64_PAD :: ULONG when ODIN_ARCH == .arm64 else struct {} + +MINIDUMP_THREAD_CALLBACK :: struct { + ThreadId: ULONG, + ThreadHandle: HANDLE, + Pad: _MINIDUMP_ARM64_PAD, + Context: CONTEXT, + SizeOfContext: ULONG, + StackBase: ULONG64, + StackEnd: ULONG64, +} + +MINIDUMP_THREAD_EX_CALLBACK :: struct { + ThreadId: ULONG, + ThreadHandle: HANDLE, + Pad: _MINIDUMP_ARM64_PAD, + Context: CONTEXT, + SizeOfContext: ULONG, + StackBase: ULONG64, + StackEnd: ULONG64, + BackingStoreBase: ULONG64, + BackingStoreEnd: ULONG64, +} + +MINIDUMP_INCLUDE_THREAD_CALLBACK :: struct { + ThreadId: ULONG, +} + +// NOTE(jakubtomsu): From verrsrc.h +VS_FIXEDFILEINFO :: struct { + dwSignature: DWORD, /* e.g. 0xfeef04bd */ + dwStrucVersion: DWORD, /* e.g. 0x00000042 = "0.42" */ + dwFileVersionMS: DWORD, /* e.g. 0x00030075 = "3.75" */ + dwFileVersionLS: DWORD, /* e.g. 0x00000031 = "0.31" */ + dwProductVersionMS: DWORD, /* e.g. 0x00030010 = "3.10" */ + dwProductVersionLS: DWORD, /* e.g. 0x00000031 = "0.31" */ + dwFileFlagsMask: DWORD, /* = 0x3F for version "0.42" */ + dwFileFlags: DWORD, /* e.g. VFF_DEBUG | VFF_PRERELEASE */ + dwFileOS: DWORD, /* e.g. VOS_DOS_WINDOWS16 */ + dwFileType: DWORD, /* e.g. VFT_DRIVER */ + dwFileSubtype: DWORD, /* e.g. VFT2_DRV_KEYBOARD */ + dwFileDateMS: DWORD, /* e.g. 0 */ + dwFileDateLS: DWORD, /* e.g. 0 */ +} + +MINIDUMP_MODULE_CALLBACK :: struct { + FullPath: ^WCHAR, + BaseOfImage: ULONG64, + SizeOfImage: ULONG, + CheckSum: ULONG, + TimeDateStamp: ULONG, + VersionInfo: VS_FIXEDFILEINFO, + CvRecord: PVOID, + SizeOfCvRecord: ULONG, + MiscRecord: PVOID, + SizeOfMiscRecord: ULONG, +} + +MINIDUMP_INCLUDE_MODULE_CALLBACK :: struct { + BaseOfImage: u64, +} + +MINIDUMP_IO_CALLBACK :: struct { + Handle: HANDLE, + Offset: ULONG64, + Buffer: PVOID, + BufferBytes: ULONG, +} + +MINIDUMP_READ_MEMORY_FAILURE_CALLBACK :: struct { + Offset: ULONG64, + Bytes: ULONG, + FailureStatus: HRESULT, +} + +MINIDUMP_VM_QUERY_CALLBACK :: struct { + Offset: ULONG64, +} + +MINIDUMP_VM_PRE_READ_CALLBACK :: struct { + Offset: ULONG64, + Buffer: PVOID, + Size: ULONG, +} + +MINIDUMP_VM_POST_READ_CALLBACK :: struct { + Offset: ULONG64, + Buffer: PVOID, + Size: ULONG, + Completed: ULONG, + Status: HRESULT, +} + +MINIDUMP_CALLBACK_OUTPUT :: struct { + using _: struct #raw_union { + ModuleWriteFlags: ULONG, + ThreadWriteFlags: ULONG, + SecondaryFlags: ULONG, + using _: struct { + MemoryBase: ULONG64, + MemorySize: ULONG, + }, + using _: struct { + CheckCancel: BOOL, + Cancel: BOOL, + }, + Handle: HANDLE, + using _: struct { + VmRegion: MINIDUMP_MEMORY_INFO, + Continue: BOOL, + }, + using _: struct { + VmQueryStatus: HRESULT, + VmQueryResult: MINIDUMP_MEMORY_INFO, + }, + using _: struct { + VmReadStatus: HRESULT, + VmReadBytesCompleted: ULONG, + }, + Status: HRESULT, + }, +} + +MINIDUMP_TYPE :: enum u32 { + Normal = 0x00000000, + WithDataSegs = 0x00000001, + WithFullMemory = 0x00000002, + WithHandleData = 0x00000004, + FilterMemory = 0x00000008, + ScanMemory = 0x00000010, + WithUnloadedModules = 0x00000020, + WithIndirectlyReferencedMemory = 0x00000040, + FilterModulePaths = 0x00000080, + WithProcessThreadData = 0x00000100, + WithPrivateReadWriteMemory = 0x00000200, + WithoutOptionalData = 0x00000400, + WithFullMemoryInfo = 0x00000800, + WithThreadInfo = 0x00001000, + WithCodeSegs = 0x00002000, + WithoutAuxiliaryState = 0x00004000, + WithFullAuxiliaryState = 0x00008000, + WithPrivateWriteCopyMemory = 0x00010000, + IgnoreInaccessibleMemory = 0x00020000, + WithTokenInformation = 0x00040000, + WithModuleHeaders = 0x00080000, + FilterTriage = 0x00100000, + WithAvxXStateContext = 0x00200000, + WithIptTrace = 0x00400000, + ScanInaccessiblePartialPages = 0x00800000, + FilterWriteCombinedMemory = 0x01000000, + ValidTypeFlags = 0x01ffffff, +} + +@(default_calling_convention = "system") +foreign Dbghelp { + MiniDumpWriteDump :: proc( + hProcess: HANDLE, + ProcessId: DWORD, + hFile: HANDLE, + DumpType: MINIDUMP_TYPE, + ExceptionParam: ^MINIDUMP_EXCEPTION_INFORMATION, + UserStreamParam: ^MINIDUMP_USER_STREAM_INFORMATION, + CallbackPara: ^MINIDUMP_CALLBACK_INFORMATION, + ) -> BOOL --- + + MiniDumpReadDumpStream :: proc( + BaseOfDump: PVOID, + StreamNumber: ULONG, + Dir: ^^MINIDUMP_DIRECTORY, + StreamPointer: ^PVOID, + StreamSize: ^ULONG, + ) -> BOOL --- +} diff --git a/core/sys/windows/dnsapi.odin b/core/sys/windows/dnsapi.odin index 623fa2889..dd2d1acee 100644 --- a/core/sys/windows/dnsapi.odin +++ b/core/sys/windows/dnsapi.odin @@ -3,7 +3,7 @@ package sys_windows foreign import "system:Dnsapi.lib" -@(default_calling_convention="std") +@(default_calling_convention="system") foreign Dnsapi { DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DWORD, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) --- diff --git a/core/sys/windows/dwmapi.odin b/core/sys/windows/dwmapi.odin index 9b5916ab1..91911baae 100644 --- a/core/sys/windows/dwmapi.odin +++ b/core/sys/windows/dwmapi.odin @@ -38,10 +38,11 @@ DWMNCRENDERINGPOLICY :: enum { DWMNCRP_LAST, } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign dwmapi { DwmFlush :: proc() -> HRESULT --- DwmIsCompositionEnabled :: proc(pfEnabled: ^BOOL) -> HRESULT --- DwmExtendFrameIntoClientArea :: proc(hWnd: HWND, pMarInset: PMARGINS) -> HRESULT --- + DwmGetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: PVOID, cbAttribute: DWORD) -> HRESULT --- DwmSetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: LPCVOID, cbAttribute: DWORD) -> HRESULT --- } diff --git a/core/sys/windows/gdi32.odin b/core/sys/windows/gdi32.odin index 9e2294c71..1d2be6dab 100644 --- a/core/sys/windows/gdi32.odin +++ b/core/sys/windows/gdi32.odin @@ -3,13 +3,15 @@ package sys_windows foreign import gdi32 "system:Gdi32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign gdi32 { GetStockObject :: proc(i: c_int) -> HGDIOBJ --- SelectObject :: proc(hdc: HDC, h: HGDIOBJ) -> HGDIOBJ --- DeleteObject :: proc(ho: HGDIOBJ) -> BOOL --- SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- + CreateCompatibleDC :: proc(hdc: HDC) -> HDC --- + CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH --- CreateDIBitmap :: proc( @@ -81,6 +83,11 @@ foreign gdi32 { GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL --- CreateSolidBrush :: proc(color: COLORREF) -> HBRUSH --- + + GetObjectW :: proc(h: HANDLE, c: c_int, pv: LPVOID) -> int --- + CreateCompatibleBitmap :: proc(hdc: HDC, cx, cy: c_int) -> HBITMAP --- + BitBlt :: proc(hdc: HDC, x, y, cx, cy: c_int, hdcSrc: HDC, x1, y1: c_int, rop: DWORD) -> BOOL --- + GetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start, cLines: UINT, lpvBits: LPVOID, lpbmi: ^BITMAPINFO, usage: UINT) -> int --- } RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF { diff --git a/core/sys/windows/hidpi.odin b/core/sys/windows/hidpi.odin new file mode 100644 index 000000000..f862971f4 --- /dev/null +++ b/core/sys/windows/hidpi.odin @@ -0,0 +1,134 @@ +// +build windows +package sys_windows +import "core:c" + +USAGE :: distinct USHORT +PUSAGE :: ^USAGE + +HIDP_CAPS :: struct { + Usage: USAGE, + UsagePage: USAGE, + InputReportByteLength: USHORT, + OutputReportByteLength: USHORT, + FeatureReportByteLength: USHORT, + Reserved: [17]USHORT, + NumberLinkCollectionNodes: USHORT, + NumberInputButtonCaps: USHORT, + NumberInputValueCaps: USHORT, + NumberInputDataIndices: USHORT, + NumberOutputButtonCaps: USHORT, + NumberOutputValueCaps: USHORT, + NumberOutputDataIndices: USHORT, + NumberFeatureButtonCaps: USHORT, + NumberFeatureValueCaps: USHORT, + NumberFeatureDataIndices: USHORT, +} +PHIDP_CAPS :: ^HIDP_CAPS + +HIDP_BUTTON_CAPS :: struct { + UsagePage: USAGE, + ReportID: UCHAR, + IsAlias: BOOLEAN, + BitField: USHORT, + LinkCollection: USHORT, + LinkUsage: USAGE, + LinkUsagePage: USAGE, + IsRange: BOOLEAN, + IsStringRange: BOOLEAN, + IsDesignatorRange: BOOLEAN, + IsAbsolute: BOOLEAN, + ReportCount: USHORT, + Reserved2: USHORT, + Reserved: [9]ULONG, + using _: struct #raw_union { + Range: struct { + UsageMin: USAGE, + UsageMax: USAGE, + StringMin: USHORT, + StringMax: USHORT, + DesignatorMin: USHORT, + DesignatorMax: USHORT, + DataIndexMin: USHORT, + DataIndexMax: USHORT, + }, + NotRange: struct { + Usage: USAGE, + Reserved1: USAGE, + StringIndex: USHORT, + Reserved2: USHORT, + DesignatorIndex: USHORT, + Reserved3: USHORT, + DataIndex: USHORT, + Reserved4: USHORT, + }, + }, +} +PHIDP_BUTTON_CAPS :: ^HIDP_BUTTON_CAPS + +HIDP_VALUE_CAPS :: struct { + UsagePage: USAGE, + ReportID: UCHAR, + IsAlias: BOOLEAN, + BitField: USHORT, + LinkCollection: USHORT, + LinkUsage: USAGE, + LinkUsagePage: USAGE, + IsRange: BOOLEAN, + IsStringRange: BOOLEAN, + IsDesignatorRange: BOOLEAN, + IsAbsolute: BOOLEAN, + HasNull: BOOLEAN, + Reserved: UCHAR, + BitSize: USHORT, + ReportCount: USHORT, + Reserved2: [5]USHORT, + UnitsExp: ULONG, + Units: ULONG, + LogicalMin: LONG, + LogicalMax: LONG, + PhysicalMin: LONG, + PhysicalMax: LONG, + using _: struct #raw_union { + Range: struct { + UsageMin: USAGE, + UsageMax: USAGE, + StringMin: USHORT, + StringMax: USHORT, + DesignatorMin: USHORT, + DesignatorMax: USHORT, + DataIndexMin: USHORT, + DataIndexMax: USHORT, + }, + NotRange: struct { + Usage: USAGE, + Reserved1: USAGE, + StringIndex: USHORT, + Reserved2: USHORT, + DesignatorIndex: USHORT, + Reserved3: USHORT, + DataIndex: USHORT, + Reserved4: USHORT, + }, + }, +} +PHIDP_VALUE_CAPS :: ^HIDP_VALUE_CAPS + +PHIDP_PREPARSED_DATA :: rawptr + +HIDP_REPORT_TYPE :: enum c.int { + Input, + Output, + Feature, +} + +HIDP_STATUS_SUCCESS : NTSTATUS : 0x110000 + +foreign import hid "system:hid.lib" +@(default_calling_convention="system") +foreign hid { + HidP_GetCaps :: proc(PreparsedData: PHIDP_PREPARSED_DATA, Capabilities: PHIDP_CAPS) -> NTSTATUS --- + HidP_GetButtonCaps :: proc(ReportType: HIDP_REPORT_TYPE, ButtonCaps: PHIDP_BUTTON_CAPS, ButtonCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- + HidP_GetValueCaps :: proc(ReportType: HIDP_REPORT_TYPE, ValueCaps: PHIDP_VALUE_CAPS, ValueCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- + HidP_GetUsages :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, UsageList: PUSAGE, UsageLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- + HidP_GetUsageValue :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, Usage: USAGE, UsageValue: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- +} diff --git a/core/sys/windows/ip_helper.odin b/core/sys/windows/ip_helper.odin index d8f93f533..4c2534c10 100644 --- a/core/sys/windows/ip_helper.odin +++ b/core/sys/windows/ip_helper.odin @@ -217,7 +217,7 @@ NL_DAD_STATE :: enum i32 { IpDadStatePreferred = 4, } -@(default_calling_convention = "std") +@(default_calling_convention = "system") foreign iphlpapi { /* The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer. diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 0c612a974..390af3ab8 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -21,7 +21,7 @@ COMMON_LVB_REVERSE_VIDEO :: WORD(0x4000) COMMON_LVB_UNDERSCORE :: WORD(0x8000) COMMON_LVB_SBCSDBCS :: WORD(0x0300) -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { OutputDebugStringA :: proc(lpOutputString: LPCSTR) --- // The only A thing that is allowed OutputDebugStringW :: proc(lpOutputString: LPCWSTR) --- @@ -112,7 +112,7 @@ foreign kernel32 { CreateThread :: proc( lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, - lpStartAddress: proc "stdcall" (rawptr) -> DWORD, + lpStartAddress: proc "system" (rawptr) -> DWORD, lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD, @@ -121,7 +121,7 @@ foreign kernel32 { hProcess: HANDLE, lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, - lpStartAddress: proc "stdcall" (rawptr) -> DWORD, + lpStartAddress: proc "system" (rawptr) -> DWORD, lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD, @@ -172,6 +172,7 @@ foreign kernel32 { TolerableDelay: ULONG, ) -> BOOL --- WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- + WaitForSingleObjectEx :: proc(hHandle: HANDLE, dwMilliseconds: DWORD, bAlterable: BOOL) -> DWORD --- Sleep :: proc(dwMilliseconds: DWORD) --- GetProcessId :: proc(handle: HANDLE) -> DWORD --- CopyFileW :: proc( @@ -290,6 +291,14 @@ foreign kernel32 { hTemplateFile: HANDLE, ) -> HANDLE --- + GetFileTime :: proc( + hFile: HANDLE, + lpCreationTime: LPFILETIME, + lpLastAccessTime: LPFILETIME, + lpLastWriteTime: LPFILETIME, + ) -> BOOL --- + CompareFileTime :: proc(lpFileTime1: LPFILETIME, lpFileTime2: LPFILETIME) -> LONG --- + FindFirstFileW :: proc(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE --- FindNextFileW :: proc(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL --- FindClose :: proc(findFile: HANDLE) -> BOOL --- @@ -320,6 +329,13 @@ foreign kernel32 { bWaitAll: BOOL, dwMilliseconds: DWORD, ) -> DWORD --- + WaitForMultipleObjectsEx :: proc( + nCount: DWORD, + lpHandles: ^HANDLE, + bWaitAll: BOOL, + dwMilliseconds: DWORD, + bAlterable: BOOL, + ) -> DWORD --- CreateNamedPipeW :: proc( lpName: LPCWSTR, dwOpenMode: DWORD, @@ -346,6 +362,9 @@ foreign kernel32 { LocalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID --- LocalFree :: proc(mem: LPVOID) -> LPVOID --- + GlobalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID --- + GlobalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID --- + GlobalFree :: proc(mem: LPVOID) -> LPVOID --- ReadDirectoryChangesW :: proc( hDirectory: HANDLE, @@ -414,7 +433,7 @@ foreign kernel32 { GetConsoleWindow :: proc() -> HWND --- GetConsoleScreenBufferInfo :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO) -> BOOL --- SetConsoleScreenBufferSize :: proc(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL --- - SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute : BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL --- + SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL --- GetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- SetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- @@ -562,7 +581,7 @@ MEM_TOP_DOWN :: 0x100000 MEM_LARGE_PAGES :: 0x20000000 MEM_4MB_PAGES :: 0x80000000 -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { VirtualAlloc :: proc( lpAddress: LPVOID, @@ -705,7 +724,7 @@ LowMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.LowMemoryRes HighMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.HighMemoryResourceNotification -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { CreateMemoryResourceNotification :: proc( NotificationType: MEMORY_RESOURCE_NOTIFICATION_TYPE, @@ -721,7 +740,7 @@ FILE_CACHE_MAX_HARD_DISABLE :: DWORD(0x00000002) FILE_CACHE_MIN_HARD_ENABLE :: DWORD(0x00000004) FILE_CACHE_MIN_HARD_DISABLE :: DWORD(0x00000008) -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { GetSystemFileCacheSize :: proc( lpMinimumFileCacheSize: PSIZE_T, @@ -751,7 +770,7 @@ WIN32_MEMORY_RANGE_ENTRY :: struct { PWIN32_MEMORY_RANGE_ENTRY :: ^WIN32_MEMORY_RANGE_ENTRY -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { PrefetchVirtualMemory :: proc( hProcess: HANDLE, @@ -809,23 +828,23 @@ foreign kernel32 { MEHC_PATROL_SCRUBBER_PRESENT :: ULONG(0x1) -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { GetMemoryErrorHandlingCapabilities :: proc( Capabilities: PULONG, ) -> BOOL --- } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { GlobalMemoryStatusEx :: proc( lpBuffer: ^MEMORYSTATUSEX, ) -> BOOL --- } -PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "stdcall" () +PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "system" () -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { RegisterBadMemoryNotification :: proc( Callback: PBAD_MEMORY_CALLBACK_ROUTINE, @@ -846,7 +865,7 @@ VmOfferPriorityLow :: OFFER_PRIORITY.VmOfferPriorityLow VmOfferPriorityBelowNormal :: OFFER_PRIORITY.VmOfferPriorityBelowNormal VmOfferPriorityNormal :: OFFER_PRIORITY.VmOfferPriorityNormal -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { OfferVirtualMemory :: proc( VirtualAddress: PVOID, @@ -911,7 +930,7 @@ WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG Reserved : 32-6, }*/ -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign one_core { QueryVirtualMemoryInformation :: proc( Process: HANDLE, @@ -936,7 +955,7 @@ foreign one_core { NUMA_NO_PREFERRED_NODE :: 0xffffffff -MapViewOfFile2 :: #force_inline proc "stdcall" ( +MapViewOfFile2 :: #force_inline proc "system" ( FileMappingHandle: HANDLE, ProcessHandle: HANDLE, Offset: ULONG64, @@ -957,7 +976,7 @@ MapViewOfFile2 :: #force_inline proc "stdcall" ( ) } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { UnmapViewOfFile2 :: proc( ProcessHandle: HANDLE, @@ -966,7 +985,7 @@ foreign kernel32 { ) -> BOOL --- } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { GetProductInfo :: proc( OSMajorVersion: DWORD, @@ -977,7 +996,7 @@ foreign kernel32 { ) -> BOOL --- } -HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL +HandlerRoutine :: proc "system" (dwCtrlType: DWORD) -> BOOL PHANDLER_ROUTINE :: HandlerRoutine @@ -1118,16 +1137,16 @@ DCB :: struct { wReserved1: WORD, } -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign kernel32 { GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- } -LPFIBER_START_ROUTINE :: #type proc "stdcall" (lpFiberParameter: LPVOID) +LPFIBER_START_ROUTINE :: #type proc "system" (lpFiberParameter: LPVOID) -@(default_calling_convention = "stdcall") +@(default_calling_convention = "system") foreign kernel32 { CreateFiber :: proc(dwStackSize: SIZE_T, lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID) -> LPVOID --- DeleteFiber :: proc(lpFiber: LPVOID) --- diff --git a/core/sys/windows/known_folders.odin b/core/sys/windows/known_folders.odin new file mode 100644 index 000000000..439d65faf --- /dev/null +++ b/core/sys/windows/known_folders.odin @@ -0,0 +1,145 @@ +// +build windows +package sys_windows + +FOLDERID_NetworkFolder :: GUID {0xD20BEEC4, 0x5CA8, 0x4905, {0xAE, 0x3B, 0xBF, 0x25, 0x1E, 0xA0, 0x9B, 0x53}} +FOLDERID_ComputerFolder :: GUID {0x0AC0837C, 0xBBF8, 0x452A, {0x85, 0x0D, 0x79, 0xD0, 0x8E, 0x66, 0x7C, 0xA7}} +FOLDERID_InternetFolder :: GUID {0x4D9F7874, 0x4E0C, 0x4904, {0x96, 0x7B, 0x40, 0xB0, 0xD2, 0x0C, 0x3E, 0x4B}} +FOLDERID_ControlPanelFolder :: GUID {0x82A74AEB, 0xAEB4, 0x465C, {0xA0, 0x14, 0xD0, 0x97, 0xEE, 0x34, 0x6D, 0x63}} +FOLDERID_PrintersFolder :: GUID {0x76FC4E2D, 0xD6AD, 0x4519, {0xA6, 0x63, 0x37, 0xBD, 0x56, 0x06, 0x81, 0x85}} +FOLDERID_SyncManagerFolder :: GUID {0x43668BF8, 0xC14E, 0x49B2, {0x97, 0xC9, 0x74, 0x77, 0x84, 0xD7, 0x84, 0xB7}} +FOLDERID_SyncSetupFolder :: GUID {0xf214138 , 0xb1d3, 0x4a90, {0xbb, 0xa9, 0x27, 0xcb, 0xc0, 0xc5, 0x38, 0x9a}} +FOLDERID_ConflictFolder :: GUID {0x4bfefb45, 0x347d, 0x4006, {0xa5, 0xbe, 0xac, 0x0c, 0xb0, 0x56, 0x71, 0x92}} +FOLDERID_SyncResultsFolder :: GUID {0x289a9a43, 0xbe44, 0x4057, {0xa4, 0x1b, 0x58, 0x7a, 0x76, 0xd7, 0xe7, 0xf9}} +FOLDERID_RecycleBinFolder :: GUID {0xB7534046, 0x3ECB, 0x4C18, {0xBE, 0x4E, 0x64, 0xCD, 0x4C, 0xB7, 0xD6, 0xAC}} +FOLDERID_ConnectionsFolder :: GUID {0x6F0CD92B, 0x2E97, 0x45D1, {0x88, 0xFF, 0xB0, 0xD1, 0x86, 0xB8, 0xDE, 0xDD}} +FOLDERID_Fonts :: GUID {0xFD228CB7, 0xAE11, 0x4AE3, {0x86, 0x4C, 0x16, 0xF3, 0x91, 0x0A, 0xB8, 0xFE}} +FOLDERID_Desktop :: GUID {0xB4BFCC3A, 0xDB2C, 0x424C, {0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41}} +FOLDERID_Startup :: GUID {0xB97D20BB, 0xF46A, 0x4C97, {0xBA, 0x10, 0x5E, 0x36, 0x08, 0x43, 0x08, 0x54}} +FOLDERID_Programs :: GUID {0xA77F5D77, 0x2E2B, 0x44C3, {0xA6, 0xA2, 0xAB, 0xA6, 0x01, 0x05, 0x4A, 0x51}} +FOLDERID_StartMenu :: GUID {0x625B53C3, 0xAB48, 0x4EC1, {0xBA, 0x1F, 0xA1, 0xEF, 0x41, 0x46, 0xFC, 0x19}} +FOLDERID_Recent :: GUID {0xAE50C081, 0xEBD2, 0x438A, {0x86, 0x55, 0x8A, 0x09, 0x2E, 0x34, 0x98, 0x7A}} +FOLDERID_SendTo :: GUID {0x8983036C, 0x27C0, 0x404B, {0x8F, 0x08, 0x10, 0x2D, 0x10, 0xDC, 0xFD, 0x74}} +FOLDERID_Documents :: GUID {0xFDD39AD0, 0x238F, 0x46AF, {0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7}} +FOLDERID_Favorites :: GUID {0x1777F761, 0x68AD, 0x4D8A, {0x87, 0xBD, 0x30, 0xB7, 0x59, 0xFA, 0x33, 0xDD}} +FOLDERID_NetHood :: GUID {0xC5ABBF53, 0xE17F, 0x4121, {0x89, 0x00, 0x86, 0x62, 0x6F, 0xC2, 0xC9, 0x73}} +FOLDERID_PrintHood :: GUID {0x9274BD8D, 0xCFD1, 0x41C3, {0xB3, 0x5E, 0xB1, 0x3F, 0x55, 0xA7, 0x58, 0xF4}} +FOLDERID_Templates :: GUID {0xA63293E8, 0x664E, 0x48DB, {0xA0, 0x79, 0xDF, 0x75, 0x9E, 0x05, 0x09, 0xF7}} +FOLDERID_CommonStartup :: GUID {0x82A5EA35, 0xD9CD, 0x47C5, {0x96, 0x29, 0xE1, 0x5D, 0x2F, 0x71, 0x4E, 0x6E}} +FOLDERID_CommonPrograms :: GUID {0x0139D44E, 0x6AFE, 0x49F2, {0x86, 0x90, 0x3D, 0xAF, 0xCA, 0xE6, 0xFF, 0xB8}} +FOLDERID_CommonStartMenu :: GUID {0xA4115719, 0xD62E, 0x491D, {0xAA, 0x7C, 0xE7, 0x4B, 0x8B, 0xE3, 0xB0, 0x67}} +FOLDERID_PublicDesktop :: GUID {0xC4AA340D, 0xF20F, 0x4863, {0xAF, 0xEF, 0xF8, 0x7E, 0xF2, 0xE6, 0xBA, 0x25}} +FOLDERID_ProgramData :: GUID {0x62AB5D82, 0xFDC1, 0x4DC3, {0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97}} +FOLDERID_CommonTemplates :: GUID {0xB94237E7, 0x57AC, 0x4347, {0x91, 0x51, 0xB0, 0x8C, 0x6C, 0x32, 0xD1, 0xF7}} +FOLDERID_PublicDocuments :: GUID {0xED4824AF, 0xDCE4, 0x45A8, {0x81, 0xE2, 0xFC, 0x79, 0x65, 0x08, 0x36, 0x34}} +FOLDERID_RoamingAppData :: GUID {0x3EB685DB, 0x65F9, 0x4CF6, {0xA0, 0x3A, 0xE3, 0xEF, 0x65, 0x72, 0x9F, 0x3D}} +FOLDERID_LocalAppData :: GUID {0xF1B32785, 0x6FBA, 0x4FCF, {0x9D, 0x55, 0x7B, 0x8E, 0x7F, 0x15, 0x70, 0x91}} +FOLDERID_LocalAppDataLow :: GUID {0xA520A1A4, 0x1780, 0x4FF6, {0xBD, 0x18, 0x16, 0x73, 0x43, 0xC5, 0xAF, 0x16}} +FOLDERID_InternetCache :: GUID {0x352481E8, 0x33BE, 0x4251, {0xBA, 0x85, 0x60, 0x07, 0xCA, 0xED, 0xCF, 0x9D}} +FOLDERID_Cookies :: GUID {0x2B0F765D, 0xC0E9, 0x4171, {0x90, 0x8E, 0x08, 0xA6, 0x11, 0xB8, 0x4F, 0xF6}} +FOLDERID_History :: GUID {0xD9DC8A3B, 0xB784, 0x432E, {0xA7, 0x81, 0x5A, 0x11, 0x30, 0xA7, 0x59, 0x63}} +FOLDERID_System :: GUID {0x1AC14E77, 0x02E7, 0x4E5D, {0xB7, 0x44, 0x2E, 0xB1, 0xAE, 0x51, 0x98, 0xB7}} +FOLDERID_SystemX86 :: GUID {0xD65231B0, 0xB2F1, 0x4857, {0xA4, 0xCE, 0xA8, 0xE7, 0xC6, 0xEA, 0x7D, 0x27}} +FOLDERID_Windows :: GUID {0xF38BF404, 0x1D43, 0x42F2, {0x93, 0x05, 0x67, 0xDE, 0x0B, 0x28, 0xFC, 0x23}} +FOLDERID_Profile :: GUID {0x5E6C858F, 0x0E22, 0x4760, {0x9A, 0xFE, 0xEA, 0x33, 0x17, 0xB6, 0x71, 0x73}} +FOLDERID_Pictures :: GUID {0x33E28130, 0x4E1E, 0x4676, {0x83, 0x5A, 0x98, 0x39, 0x5C, 0x3B, 0xC3, 0xBB}} +FOLDERID_ProgramFilesX86 :: GUID {0x7C5A40EF, 0xA0FB, 0x4BFC, {0x87, 0x4A, 0xC0, 0xF2, 0xE0, 0xB9, 0xFA, 0x8E}} +FOLDERID_ProgramFilesCommonX86 :: GUID {0xDE974D24, 0xD9C6, 0x4D3E, {0xBF, 0x91, 0xF4, 0x45, 0x51, 0x20, 0xB9, 0x17}} +FOLDERID_ProgramFilesX64 :: GUID {0x6d809377, 0x6af0, 0x444b, {0x89, 0x57, 0xa3, 0x77, 0x3f, 0x02, 0x20, 0x0e}} +FOLDERID_ProgramFilesCommonX64 :: GUID {0x6365d5a7, 0xf0d , 0x45e5, {0x87, 0xf6, 0xd, 0xa5, 0x6b, 0x6a, 0x4f, 0x7d }} +FOLDERID_ProgramFiles :: GUID {0x905e63b6, 0xc1bf, 0x494e, {0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a}} +FOLDERID_ProgramFilesCommon :: GUID {0xF7F1ED05, 0x9F6D, 0x47A2, {0xAA, 0xAE, 0x29, 0xD3, 0x17, 0xC6, 0xF0, 0x66}} +FOLDERID_UserProgramFiles :: GUID {0x5cd7aee2, 0x2219, 0x4a67, {0xb8, 0x5d, 0x6c, 0x9c, 0xe1, 0x56, 0x60, 0xcb}} +FOLDERID_UserProgramFilesCommon :: GUID {0xbcbd3057, 0xca5c, 0x4622, {0xb4, 0x2d, 0xbc, 0x56, 0xdb, 0x0a, 0xe5, 0x16}} +FOLDERID_AdminTools :: GUID {0x724EF170, 0xA42D, 0x4FEF, {0x9F, 0x26, 0xB6, 0x0E, 0x84, 0x6F, 0xBA, 0x4F}} +FOLDERID_CommonAdminTools :: GUID {0xD0384E7D, 0xBAC3, 0x4797, {0x8F, 0x14, 0xCB, 0xA2, 0x29, 0xB3, 0x92, 0xB5}} +FOLDERID_Music :: GUID {0x4BD8D571, 0x6D19, 0x48D3, {0xBE, 0x97, 0x42, 0x22, 0x20, 0x08, 0x0E, 0x43}} +FOLDERID_Videos :: GUID {0x18989B1D, 0x99B5, 0x455B, {0x84, 0x1C, 0xAB, 0x7C, 0x74, 0xE4, 0xDD, 0xFC}} +FOLDERID_Ringtones :: GUID {0xC870044B, 0xF49E, 0x4126, {0xA9, 0xC3, 0xB5, 0x2A, 0x1F, 0xF4, 0x11, 0xE8}} +FOLDERID_PublicPictures :: GUID {0xB6EBFB86, 0x6907, 0x413C, {0x9A, 0xF7, 0x4F, 0xC2, 0xAB, 0xF0, 0x7C, 0xC5}} +FOLDERID_PublicMusic :: GUID {0x3214FAB5, 0x9757, 0x4298, {0xBB, 0x61, 0x92, 0xA9, 0xDE, 0xAA, 0x44, 0xFF}} +FOLDERID_PublicVideos :: GUID {0x2400183A, 0x6185, 0x49FB, {0xA2, 0xD8, 0x4A, 0x39, 0x2A, 0x60, 0x2B, 0xA3}} +FOLDERID_PublicRingtones :: GUID {0xE555AB60, 0x153B, 0x4D17, {0x9F, 0x04, 0xA5, 0xFE, 0x99, 0xFC, 0x15, 0xEC}} +FOLDERID_ResourceDir :: GUID {0x8AD10C31, 0x2ADB, 0x4296, {0xA8, 0xF7, 0xE4, 0x70, 0x12, 0x32, 0xC9, 0x72}} +FOLDERID_LocalizedResourcesDir :: GUID {0x2A00375E, 0x224C, 0x49DE, {0xB8, 0xD1, 0x44, 0x0D, 0xF7, 0xEF, 0x3D, 0xDC}} +FOLDERID_CommonOEMLinks :: GUID {0xC1BAE2D0, 0x10DF, 0x4334, {0xBE, 0xDD, 0x7A, 0xA2, 0x0B, 0x22, 0x7A, 0x9D}} +FOLDERID_CDBurning :: GUID {0x9E52AB10, 0xF80D, 0x49DF, {0xAC, 0xB8, 0x43, 0x30, 0xF5, 0x68, 0x78, 0x55}} +FOLDERID_UserProfiles :: GUID {0x0762D272, 0xC50A, 0x4BB0, {0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80}} +FOLDERID_Playlists :: GUID {0xDE92C1C7, 0x837F, 0x4F69, {0xA3, 0xBB, 0x86, 0xE6, 0x31, 0x20, 0x4A, 0x23}} +FOLDERID_SamplePlaylists :: GUID {0x15CA69B3, 0x30EE, 0x49C1, {0xAC, 0xE1, 0x6B, 0x5E, 0xC3, 0x72, 0xAF, 0xB5}} +FOLDERID_SampleMusic :: GUID {0xB250C668, 0xF57D, 0x4EE1, {0xA6, 0x3C, 0x29, 0x0E, 0xE7, 0xD1, 0xAA, 0x1F}} +FOLDERID_SamplePictures :: GUID {0xC4900540, 0x2379, 0x4C75, {0x84, 0x4B, 0x64, 0xE6, 0xFA, 0xF8, 0x71, 0x6B}} +FOLDERID_SampleVideos :: GUID {0x859EAD94, 0x2E85, 0x48AD, {0xA7, 0x1A, 0x09, 0x69, 0xCB, 0x56, 0xA6, 0xCD}} +FOLDERID_PhotoAlbums :: GUID {0x69D2CF90, 0xFC33, 0x4FB7, {0x9A, 0x0C, 0xEB, 0xB0, 0xF0, 0xFC, 0xB4, 0x3C}} +FOLDERID_Public :: GUID {0xDFDF76A2, 0xC82A, 0x4D63, {0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85}} +FOLDERID_ChangeRemovePrograms :: GUID {0xdf7266ac, 0x9274, 0x4867, {0x8d, 0x55, 0x3b, 0xd6, 0x61, 0xde, 0x87, 0x2d}} +FOLDERID_AppUpdates :: GUID {0xa305ce99, 0xf527, 0x492b, {0x8b, 0x1a, 0x7e, 0x76, 0xfa, 0x98, 0xd6, 0xe4}} +FOLDERID_AddNewPrograms :: GUID {0xde61d971, 0x5ebc, 0x4f02, {0xa3, 0xa9, 0x6c, 0x82, 0x89, 0x5e, 0x5c, 0x04}} +FOLDERID_Downloads :: GUID {0x374de290, 0x123f, 0x4565, {0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}} +FOLDERID_PublicDownloads :: GUID {0x3d644c9b, 0x1fb8, 0x4f30, {0x9b, 0x45, 0xf6, 0x70, 0x23, 0x5f, 0x79, 0xc0}} +FOLDERID_SavedSearches :: GUID {0x7d1d3a04, 0xdebb, 0x4115, {0x95, 0xcf, 0x2f, 0x29, 0xda, 0x29, 0x20, 0xda}} +FOLDERID_QuickLaunch :: GUID {0x52a4f021, 0x7b75, 0x48a9, {0x9f, 0x6b, 0x4b, 0x87, 0xa2, 0x10, 0xbc, 0x8f}} +FOLDERID_Contacts :: GUID {0x56784854, 0xc6cb, 0x462b, {0x81, 0x69, 0x88, 0xe3, 0x50, 0xac, 0xb8, 0x82}} +FOLDERID_SidebarParts :: GUID {0xa75d362e, 0x50fc, 0x4fb7, {0xac, 0x2c, 0xa8, 0xbe, 0xaa, 0x31, 0x44, 0x93}} +FOLDERID_SidebarDefaultParts :: GUID {0x7b396e54, 0x9ec5, 0x4300, {0xbe, 0xa , 0x24, 0x82, 0xeb, 0xae, 0x1a, 0x26}} +FOLDERID_PublicGameTasks :: GUID {0xdebf2536, 0xe1a8, 0x4c59, {0xb6, 0xa2, 0x41, 0x45, 0x86, 0x47, 0x6a, 0xea}} +FOLDERID_GameTasks :: GUID {0x54fae61 , 0x4dd8, 0x4787, {0x80, 0xb6, 0x9 , 0x2 , 0x20, 0xc4, 0xb7, 0x0 }} +FOLDERID_SavedGames :: GUID {0x4c5c32ff, 0xbb9d, 0x43b0, {0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4}} +FOLDERID_Games :: GUID {0xcac52c1a, 0xb53d, 0x4edc, {0x92, 0xd7, 0x6b, 0x2e, 0x8a, 0xc1, 0x94, 0x34}} +FOLDERID_SEARCH_MAPI :: GUID {0x98ec0e18, 0x2098, 0x4d44, {0x86, 0x44, 0x66, 0x97, 0x93, 0x15, 0xa2, 0x81}} +FOLDERID_SEARCH_CSC :: GUID {0xee32e446, 0x31ca, 0x4aba, {0x81, 0x4f, 0xa5, 0xeb, 0xd2, 0xfd, 0x6d, 0x5e}} +FOLDERID_Links :: GUID {0xbfb9d5e0, 0xc6a9, 0x404c, {0xb2, 0xb2, 0xae, 0x6d, 0xb6, 0xaf, 0x49, 0x68}} +FOLDERID_UsersFiles :: GUID {0xf3ce0f7c, 0x4901, 0x4acc, {0x86, 0x48, 0xd5, 0xd4, 0x4b, 0x04, 0xef, 0x8f}} +FOLDERID_UsersLibraries :: GUID {0xa302545d, 0xdeff, 0x464b, {0xab, 0xe8, 0x61, 0xc8, 0x64, 0x8d, 0x93, 0x9b}} +FOLDERID_SearchHome :: GUID {0x190337d1, 0xb8ca, 0x4121, {0xa6, 0x39, 0x6d, 0x47, 0x2d, 0x16, 0x97, 0x2a}} +FOLDERID_OriginalImages :: GUID {0x2C36C0AA, 0x5812, 0x4b87, {0xbf, 0xd0, 0x4c, 0xd0, 0xdf, 0xb1, 0x9b, 0x39}} +FOLDERID_DocumentsLibrary :: GUID {0x7b0db17d, 0x9cd2, 0x4a93, {0x97, 0x33, 0x46, 0xcc, 0x89, 0x02, 0x2e, 0x7c}} +FOLDERID_MusicLibrary :: GUID {0x2112ab0a, 0xc86a, 0x4ffe, {0xa3, 0x68, 0xd , 0xe9, 0x6e, 0x47, 0x1 , 0x2e}} +FOLDERID_PicturesLibrary :: GUID {0xa990ae9f, 0xa03b, 0x4e80, {0x94, 0xbc, 0x99, 0x12, 0xd7, 0x50, 0x41, 0x4 }} +FOLDERID_VideosLibrary :: GUID {0x491e922f, 0x5643, 0x4af4, {0xa7, 0xeb, 0x4e, 0x7a, 0x13, 0x8d, 0x81, 0x74}} +FOLDERID_RecordedTVLibrary :: GUID {0x1a6fdba2, 0xf42d, 0x4358, {0xa7, 0x98, 0xb7, 0x4d, 0x74, 0x59, 0x26, 0xc5}} +FOLDERID_HomeGroup :: GUID {0x52528a6b, 0xb9e3, 0x4add, {0xb6, 0xd , 0x58, 0x8c, 0x2d, 0xba, 0x84, 0x2d}} +FOLDERID_HomeGroupCurrentUser :: GUID {0x9b74b6a3, 0xdfd , 0x4f11, {0x9e, 0x78, 0x5f, 0x78, 0x0 , 0xf2, 0xe7, 0x72}} +FOLDERID_DeviceMetadataStore :: GUID {0x5ce4a5e9, 0xe4eb, 0x479d, {0xb8, 0x9f, 0x13, 0x0c, 0x02, 0x88, 0x61, 0x55}} +FOLDERID_Libraries :: GUID {0x1b3ea5dc, 0xb587, 0x4786, {0xb4, 0xef, 0xbd, 0x1d, 0xc3, 0x32, 0xae, 0xae}} +FOLDERID_PublicLibraries :: GUID {0x48daf80b, 0xe6cf, 0x4f4e, {0xb8, 0x00, 0x0e, 0x69, 0xd8, 0x4e, 0xe3, 0x84}} +FOLDERID_UserPinned :: GUID {0x9e3995ab, 0x1f9c, 0x4f13, {0xb8, 0x27, 0x48, 0xb2, 0x4b, 0x6c, 0x71, 0x74}} +FOLDERID_ImplicitAppShortcuts :: GUID {0xbcb5256f, 0x79f6, 0x4cee, {0xb7, 0x25, 0xdc, 0x34, 0xe4, 0x2 , 0xfd, 0x46}} +FOLDERID_AccountPictures :: GUID {0x008ca0b1, 0x55b4, 0x4c56, {0xb8, 0xa8, 0x4d, 0xe4, 0xb2, 0x99, 0xd3, 0xbe}} +FOLDERID_PublicUserTiles :: GUID {0x0482af6c, 0x08f1, 0x4c34, {0x8c, 0x90, 0xe1, 0x7e, 0xc9, 0x8b, 0x1e, 0x17}} +FOLDERID_AppsFolder :: GUID {0x1e87508d, 0x89c2, 0x42f0, {0x8a, 0x7e, 0x64, 0x5a, 0x0f, 0x50, 0xca, 0x58}} +FOLDERID_StartMenuAllPrograms :: GUID {0xf26305ef, 0x6948, 0x40b9, {0xb2, 0x55, 0x81, 0x45, 0x3d, 0x9 , 0xc7, 0x85}} +FOLDERID_CommonStartMenuPlaces :: GUID {0xa440879f, 0x87a0, 0x4f7d, {0xb7, 0x0 , 0x2 , 0x7 , 0xb9, 0x66, 0x19, 0x4a}} +FOLDERID_ApplicationShortcuts :: GUID {0xa3918781, 0xe5f2, 0x4890, {0xb3, 0xd9, 0xa7, 0xe5, 0x43, 0x32, 0x32, 0x8c}} +FOLDERID_RoamingTiles :: GUID {0xbcfc5a , 0xed94, 0x4e48, {0x96, 0xa1, 0x3f, 0x62, 0x17, 0xf2, 0x19, 0x90}} +FOLDERID_RoamedTileImages :: GUID {0xaaa8d5a5, 0xf1d6, 0x4259, {0xba, 0xa8, 0x78, 0xe7, 0xef, 0x60, 0x83, 0x5e}} +FOLDERID_Screenshots :: GUID {0xb7bede81, 0xdf94, 0x4682, {0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f}} +FOLDERID_CameraRoll :: GUID {0xab5fb87b, 0x7ce2, 0x4f83, {0x91, 0x5d, 0x55, 0x8 , 0x46, 0xc9, 0x53, 0x7b}} +FOLDERID_SkyDrive :: GUID {0xa52bba46, 0xe9e1, 0x435f, {0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}} +FOLDERID_OneDrive :: GUID {0xa52bba46, 0xe9e1, 0x435f, {0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}} +FOLDERID_SkyDriveDocuments :: GUID {0x24d89e24, 0x2f19, 0x4534, {0x9d, 0xde, 0x6a, 0x66, 0x71, 0xfb, 0xb8, 0xfe}} +FOLDERID_SkyDrivePictures :: GUID {0x339719b5, 0x8c47, 0x4894, {0x94, 0xc2, 0xd8, 0xf7, 0x7a, 0xdd, 0x44, 0xa6}} +FOLDERID_SkyDriveMusic :: GUID {0xc3f2459e, 0x80d6, 0x45dc, {0xbf, 0xef, 0x1f, 0x76, 0x9f, 0x2b, 0xe7, 0x30}} +FOLDERID_SkyDriveCameraRoll :: GUID {0x767e6811, 0x49cb, 0x4273, {0x87, 0xc2, 0x20, 0xf3, 0x55, 0xe1, 0x08, 0x5b}} +FOLDERID_SearchHistory :: GUID {0x0d4c3db6, 0x03a3, 0x462f, {0xa0, 0xe6, 0x08, 0x92, 0x4c, 0x41, 0xb5, 0xd4}} +FOLDERID_SearchTemplates :: GUID {0x7e636bfe, 0xdfa9, 0x4d5e, {0xb4, 0x56, 0xd7, 0xb3, 0x98, 0x51, 0xd8, 0xa9}} +FOLDERID_CameraRollLibrary :: GUID {0x2b20df75, 0x1eda, 0x4039, {0x80, 0x97, 0x38, 0x79, 0x82, 0x27, 0xd5, 0xb7}} +FOLDERID_SavedPictures :: GUID {0x3b193882, 0xd3ad, 0x4eab, {0x96, 0x5a, 0x69, 0x82, 0x9d, 0x1f, 0xb5, 0x9f}} +FOLDERID_SavedPicturesLibrary :: GUID {0xe25b5812, 0xbe88, 0x4bd9, {0x94, 0xb0, 0x29, 0x23, 0x34, 0x77, 0xb6, 0xc3}} +FOLDERID_RetailDemo :: GUID {0x12d4c69e, 0x24ad, 0x4923, {0xbe, 0x19, 0x31, 0x32, 0x1c, 0x43, 0xa7, 0x67}} +FOLDERID_Device :: GUID {0x1C2AC1DC, 0x4358, 0x4B6C, {0x97, 0x33, 0xAF, 0x21, 0x15, 0x65, 0x76, 0xF0}} +FOLDERID_DevelopmentFiles :: GUID {0xdbe8e08e, 0x3053, 0x4bbc, {0xb1, 0x83, 0x2a, 0x7b, 0x2b, 0x19, 0x1e, 0x59}} +FOLDERID_Objects3D :: GUID {0x31c0dd25, 0x9439, 0x4f12, {0xbf, 0x41, 0x7f, 0xf4, 0xed, 0xa3, 0x87, 0x22}} +FOLDERID_AppCaptures :: GUID {0xedc0fe71, 0x98d8, 0x4f4a, {0xb9, 0x20, 0xc8, 0xdc, 0x13, 0x3c, 0xb1, 0x65}} +FOLDERID_LocalDocuments :: GUID {0xf42ee2d3, 0x909f, 0x4907, {0x88, 0x71, 0x4c, 0x22, 0xfc, 0x0b, 0xf7, 0x56}} +FOLDERID_LocalPictures :: GUID {0x0ddd015d, 0xb06c, 0x45d5, {0x8c, 0x4c, 0xf5, 0x97, 0x13, 0x85, 0x46, 0x39}} +FOLDERID_LocalVideos :: GUID {0x35286a68, 0x3c57, 0x41a1, {0xbb, 0xb1, 0x0e, 0xae, 0x73, 0xd7, 0x6c, 0x95}} +FOLDERID_LocalMusic :: GUID {0xa0c69a99, 0x21c8, 0x4671, {0x87, 0x03, 0x79, 0x34, 0x16, 0x2f, 0xcf, 0x1d}} +FOLDERID_LocalDownloads :: GUID {0x7d83ee9b, 0x2244, 0x4e70, {0xb1, 0xf5, 0x53, 0x93, 0x04, 0x2a, 0xf1, 0xe4}} +FOLDERID_RecordedCalls :: GUID {0x2f8b40c2, 0x83ed, 0x48ee, {0xb3, 0x83, 0xa1, 0xf1, 0x57, 0xec, 0x6f, 0x9a}} +FOLDERID_AllAppMods :: GUID {0x7ad67899, 0x66af, 0x43ba, {0x91, 0x56, 0x6a, 0xad, 0x42, 0xe6, 0xc5, 0x96}} +FOLDERID_CurrentAppMods :: GUID {0x3db40b20, 0x2a30, 0x4dbe, {0x91, 0x7e, 0x77, 0x1d, 0xd2, 0x1d, 0xd0, 0x99}} +FOLDERID_AppDataDesktop :: GUID {0xb2c5e279, 0x7add, 0x439f, {0xb2, 0x8c, 0xc4, 0x1f, 0xe1, 0xbb, 0xf6, 0x72}} +FOLDERID_AppDataDocuments :: GUID {0x7be16610, 0x1f7f, 0x44ac, {0xbf, 0xf0, 0x83, 0xe1, 0x5f, 0x2f, 0xfc, 0xa1}} +FOLDERID_AppDataFavorites :: GUID {0x7cfbefbc, 0xde1f, 0x45aa, {0xb8, 0x43, 0xa5, 0x42, 0xac, 0x53, 0x6c, 0xc9}} +FOLDERID_AppDataProgramData :: GUID {0x559d40a3, 0xa036, 0x40fa, {0xaf, 0x61, 0x84, 0xcb, 0x43, 0xa , 0x4d, 0x34}} +FOLDERID_LocalStorage :: GUID {0xB3EB08D3, 0xA1F3, 0x496B, {0x86, 0x5A, 0x42, 0xB5, 0x36, 0xCD, 0xA0, 0xEC}} diff --git a/core/sys/windows/netapi32.odin b/core/sys/windows/netapi32.odin index 0df277181..d9f75c623 100644 --- a/core/sys/windows/netapi32.odin +++ b/core/sys/windows/netapi32.odin @@ -3,7 +3,7 @@ package sys_windows foreign import netapi32 "system:Netapi32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign netapi32 { NetUserAdd :: proc( servername: wstring, diff --git a/core/sys/windows/ntdll.odin b/core/sys/windows/ntdll.odin index dda5b9711..56c24f1a2 100644 --- a/core/sys/windows/ntdll.odin +++ b/core/sys/windows/ntdll.odin @@ -3,7 +3,7 @@ package sys_windows foreign import ntdll_lib "system:ntdll.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign ntdll_lib { RtlGetVersion :: proc(lpVersionInformation: ^OSVERSIONINFOEXW) -> NTSTATUS --- } \ No newline at end of file diff --git a/core/sys/windows/ole32.odin b/core/sys/windows/ole32.odin index 4a4b470ea..6fa398d46 100644 --- a/core/sys/windows/ole32.odin +++ b/core/sys/windows/ole32.odin @@ -1,4 +1,3 @@ -// +build windows package sys_windows foreign import "system:Ole32.lib" @@ -15,14 +14,14 @@ IUnknown :: struct { using Vtbl: ^IUnknownVtbl, } IUnknownVtbl :: struct { - QueryInterface: proc "stdcall" (This: ^IUnknown, riid: REFIID, ppvObject: ^rawptr) -> HRESULT, - AddRef: proc "stdcall" (This: ^IUnknown) -> ULONG, - Release: proc "stdcall" (This: ^IUnknown) -> ULONG, + QueryInterface: proc "system" (This: ^IUnknown, riid: REFIID, ppvObject: ^rawptr) -> HRESULT, + AddRef: proc "system" (This: ^IUnknown) -> ULONG, + Release: proc "system" (This: ^IUnknown) -> ULONG, } LPUNKNOWN :: ^IUnknown -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Ole32 { CoInitializeEx :: proc(reserved: rawptr, co_init: COINIT) -> HRESULT --- CoUninitialize :: proc() --- diff --git a/core/sys/windows/shell32.odin b/core/sys/windows/shell32.odin index 0a6f90a44..358b8482f 100644 --- a/core/sys/windows/shell32.odin +++ b/core/sys/windows/shell32.odin @@ -3,7 +3,7 @@ package sys_windows foreign import shell32 "system:Shell32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign shell32 { CommandLineToArgvW :: proc(cmd_list: wstring, num_args: ^c_int) -> ^wstring --- ShellExecuteW :: proc( @@ -22,9 +22,13 @@ foreign shell32 { ) -> c_int --- SHFileOperationW :: proc(lpFileOp: LPSHFILEOPSTRUCTW) -> c_int --- SHGetFolderPathW :: proc(hwnd: HWND, csidl: c_int, hToken: HANDLE, dwFlags: DWORD, pszPath: LPWSTR) -> HRESULT --- - SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR --- + SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR --- Shell_NotifyIconW :: proc(dwMessage: DWORD, lpData: ^NOTIFYICONDATAW) -> BOOL --- + + SHGetKnownFolderIDList :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppidl: rawptr) -> HRESULT --- + SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT --- + SHGetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppszPath: ^LPWSTR) -> HRESULT --- } APPBARDATA :: struct { @@ -36,16 +40,16 @@ APPBARDATA :: struct { lParam: LPARAM, } PAPPBARDATA :: ^APPBARDATA - + ABM_NEW :: 0x00000000 ABM_REMOVE :: 0x00000001 ABM_QUERYPOS :: 0x00000002 ABM_SETPOS :: 0x00000003 ABM_GETSTATE :: 0x00000004 ABM_GETTASKBARPOS :: 0x00000005 -ABM_ACTIVATE :: 0x00000006 +ABM_ACTIVATE :: 0x00000006 ABM_GETAUTOHIDEBAR :: 0x00000007 -ABM_SETAUTOHIDEBAR :: 0x00000008 +ABM_SETAUTOHIDEBAR :: 0x00000008 ABM_WINDOWPOSCHANGED :: 0x0000009 ABM_SETSTATE :: 0x0000000a ABN_STATECHANGE :: 0x0000000 @@ -58,3 +62,32 @@ ABE_LEFT :: 0 ABE_TOP :: 1 ABE_RIGHT :: 2 ABE_BOTTOM :: 3 + +KNOWNFOLDERID :: GUID +REFKNOWNFOLDERID :: ^KNOWNFOLDERID + +KNOWN_FOLDER_FLAG :: enum u32 { + DEFAULT = 0x00000000, + + // if NTDDI_VERSION >= NTDDI_WIN10_RS3 + FORCE_APP_DATA_REDIRECTION = 0x00080000, + + // if NTDDI_VERSION >= NTDDI_WIN10_RS2 + RETURN_FILTER_REDIRECTION_TARGET = 0x00040000, + FORCE_PACKAGE_REDIRECTION = 0x00020000, + NO_PACKAGE_REDIRECTION = 0x00010000, + FORCE_APPCONTAINER_REDIRECTION = 0x00020000, + + // if NTDDI_VERSION >= NTDDI_WIN7 + NO_APPCONTAINER_REDIRECTION = 0x00010000, + + CREATE = 0x00008000, + DONT_VERIFY = 0x00004000, + DONT_UNEXPAND = 0x00002000, + NO_ALIAS = 0x00001000, + INIT = 0x00000800, + DEFAULT_PATH = 0x00000400, + NOT_PARENT_RELATIVE = 0x00000200, + SIMPLE_IDLIST = 0x00000100, + ALIAS_ONLY = 0x80000000, +} diff --git a/core/sys/windows/shlwapi.odin b/core/sys/windows/shlwapi.odin index 241ade8f6..bf9d2d1e8 100644 --- a/core/sys/windows/shlwapi.odin +++ b/core/sys/windows/shlwapi.odin @@ -3,7 +3,7 @@ package sys_windows foreign import shlwapi "system:shlwapi.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign shlwapi { PathFileExistsW :: proc(pszPath: wstring) -> BOOL --- PathFindExtensionW :: proc(pszPath: wstring) -> wstring --- diff --git a/core/sys/windows/synchronization.odin b/core/sys/windows/synchronization.odin index c98730aa0..79efaab34 100644 --- a/core/sys/windows/synchronization.odin +++ b/core/sys/windows/synchronization.odin @@ -3,7 +3,7 @@ package sys_windows foreign import Synchronization "system:Synchronization.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Synchronization { WaitOnAddress :: proc(Address: PVOID, CompareAddress: PVOID, AddressSize: SIZE_T, dwMilliseconds: DWORD) -> BOOL --- WakeByAddressSingle :: proc(Address: PVOID) --- diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index d5377eb2f..6dbf6d523 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -1,4 +1,3 @@ -// +build windows package sys_windows import "core:c" @@ -7,9 +6,9 @@ c_char :: c.char c_uchar :: c.uchar c_int :: c.int c_uint :: c.uint -c_long :: c.long +c_long :: i32 c_longlong :: c.longlong -c_ulong :: c.ulong +c_ulong :: u32 c_ulonglong :: c.ulonglong c_short :: c.short c_ushort :: c.ushort @@ -75,6 +74,8 @@ LPRECT :: ^RECT LPPOINT :: ^POINT LSTATUS :: LONG PHKEY :: ^HKEY +PUSHORT :: ^USHORT +PCHAR :: ^CHAR UINT8 :: u8 UINT16 :: u16 @@ -86,6 +87,8 @@ INT16 :: i16 INT32 :: i32 INT64 :: i64 +ULONG32 :: u32 +LONG32 :: i32 ULONG64 :: u64 LONG64 :: i64 @@ -688,13 +691,13 @@ FW_DEMIBOLD :: FW_SEMIBOLD FW_ULTRABOLD :: FW_EXTRABOLD FW_BLACK :: FW_HEAVY -PTIMERAPCROUTINE :: #type proc "stdcall" (lpArgToCompletionRoutine: LPVOID, dwTimerLowValue, dwTimerHighValue: DWORD) +PTIMERAPCROUTINE :: #type proc "system" (lpArgToCompletionRoutine: LPVOID, dwTimerLowValue, dwTimerHighValue: DWORD) -TIMERPROC :: #type proc "stdcall" (HWND, UINT, UINT_PTR, DWORD) +TIMERPROC :: #type proc "system" (HWND, UINT, UINT_PTR, DWORD) -WNDPROC :: #type proc "stdcall" (HWND, UINT, WPARAM, LPARAM) -> LRESULT +WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT -HOOKPROC :: #type proc "stdcall" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT +HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT CWPRETSTRUCT :: struct { lResult: LRESULT, @@ -1969,6 +1972,16 @@ BITMAPINFO :: struct { bmiColors: [1]RGBQUAD, } +BITMAP :: struct { + bmType: LONG, + bmWidth: LONG, + bmHeight: LONG, + bmWidthBytes: LONG, + bmPlanes: WORD, + bmBitsPixel: WORD, + bmBits: LPVOID, +} + // pixel types PFD_TYPE_RGBA :: 0 PFD_TYPE_COLORINDEX :: 1 @@ -2311,7 +2324,7 @@ MOUNT_POINT_REPARSE_BUFFER :: struct { PathBuffer: WCHAR, } -LPPROGRESS_ROUTINE :: #type proc "stdcall" ( +LPPROGRESS_ROUTINE :: #type proc "system" ( TotalFileSize: LARGE_INTEGER, TotalBytesTransferred: LARGE_INTEGER, StreamSize: LARGE_INTEGER, @@ -2481,7 +2494,7 @@ OVERLAPPED_ENTRY :: struct { dwNumberOfBytesTransferred: DWORD, } -LPOVERLAPPED_COMPLETION_ROUTINE :: #type proc "stdcall" ( +LPOVERLAPPED_COMPLETION_ROUTINE :: #type proc "system" ( dwErrorCode: DWORD, dwNumberOfBytesTransfered: DWORD, lpOverlapped: LPOVERLAPPED, @@ -2545,7 +2558,7 @@ EXCEPTION_POINTERS :: struct { ContextRecord: ^CONTEXT, } -PVECTORED_EXCEPTION_HANDLER :: #type proc "stdcall" (ExceptionInfo: ^EXCEPTION_POINTERS) -> LONG +PVECTORED_EXCEPTION_HANDLER :: #type proc "system" (ExceptionInfo: ^EXCEPTION_POINTERS) -> LONG CONSOLE_READCONSOLE_CONTROL :: struct { nLength: ULONG, @@ -2600,7 +2613,7 @@ ADDRINFOEXW :: struct { ai_next: ^ADDRINFOEXW, } -LPLOOKUPSERVICE_COMPLETION_ROUTINE :: #type proc "stdcall" ( +LPLOOKUPSERVICE_COMPLETION_ROUTINE :: #type proc "system" ( dwErrorCode: DWORD, dwNumberOfBytesTransfered: DWORD, lpOverlapped: LPOVERLAPPED, @@ -2706,16 +2719,17 @@ SECURITY_MAX_SID_SIZE :: 68 // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid SID :: struct #packed { - Revision: byte, - SubAuthorityCount: byte, + Revision: byte, + SubAuthorityCount: byte, IdentifierAuthority: SID_IDENTIFIER_AUTHORITY, - SubAuthority: [15]DWORD, // Array of DWORDs + SubAuthority: [15]DWORD, // Array of DWORDs } #assert(size_of(SID) == SECURITY_MAX_SID_SIZE) SID_IDENTIFIER_AUTHORITY :: struct #packed { Value: [6]u8, } +#assert(size_of(SID_IDENTIFIER_AUTHORITY) == 6) // For NetAPI32 // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/shared/lmerr.h @@ -3413,7 +3427,7 @@ IModalWindow :: struct #raw_union { } IModalWindowVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Show: proc "stdcall" (this: ^IModalWindow, hwndOwner: HWND) -> HRESULT, + Show: proc "system" (this: ^IModalWindow, hwndOwner: HWND) -> HRESULT, } ISequentialStream :: struct #raw_union { @@ -3422,8 +3436,8 @@ ISequentialStream :: struct #raw_union { } ISequentialStreamVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Read: proc "stdcall" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbRead: ^ULONG) -> HRESULT, - Write: proc "stdcall" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbWritten: ^ULONG) -> HRESULT, + Read: proc "system" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbRead: ^ULONG) -> HRESULT, + Write: proc "system" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbWritten: ^ULONG) -> HRESULT, } IStream :: struct #raw_union { @@ -3432,15 +3446,15 @@ IStream :: struct #raw_union { } IStreamVtbl :: struct { using ISequentialStreamVtbl: ISequentialStreamVtbl, - Seek: proc "stdcall" (this: ^IStream, dlibMove: LARGE_INTEGER, dwOrigin: DWORD, plibNewPosition: ^ULARGE_INTEGER) -> HRESULT, - SetSize: proc "stdcall" (this: ^IStream, libNewSize: ULARGE_INTEGER) -> HRESULT, - CopyTo: proc "stdcall" (this: ^IStream, pstm: ^IStream, cb: ULARGE_INTEGER, pcbRead: ^ULARGE_INTEGER, pcbWritten: ^ULARGE_INTEGER) -> HRESULT, - Commit: proc "stdcall" (this: ^IStream, grfCommitFlags: DWORD) -> HRESULT, - Revert: proc "stdcall" (this: ^IStream) -> HRESULT, - LockRegion: proc "stdcall" (this: ^IStream, libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD) -> HRESULT, - UnlockRegion: proc "stdcall" (this: ^IStream, libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD) -> HRESULT, - Stat: proc "stdcall" (this: ^IStream, pstatstg: ^STATSTG, grfStatFlag: DWORD) -> HRESULT, - Clone: proc "stdcall" (this: ^IStream, ppstm: ^^IStream) -> HRESULT, + Seek: proc "system" (this: ^IStream, dlibMove: LARGE_INTEGER, dwOrigin: DWORD, plibNewPosition: ^ULARGE_INTEGER) -> HRESULT, + SetSize: proc "system" (this: ^IStream, libNewSize: ULARGE_INTEGER) -> HRESULT, + CopyTo: proc "system" (this: ^IStream, pstm: ^IStream, cb: ULARGE_INTEGER, pcbRead: ^ULARGE_INTEGER, pcbWritten: ^ULARGE_INTEGER) -> HRESULT, + Commit: proc "system" (this: ^IStream, grfCommitFlags: DWORD) -> HRESULT, + Revert: proc "system" (this: ^IStream) -> HRESULT, + LockRegion: proc "system" (this: ^IStream, libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD) -> HRESULT, + UnlockRegion: proc "system" (this: ^IStream, libOffset: ULARGE_INTEGER, cb: ULARGE_INTEGER, dwLockType: DWORD) -> HRESULT, + Stat: proc "system" (this: ^IStream, pstatstg: ^STATSTG, grfStatFlag: DWORD) -> HRESULT, + Clone: proc "system" (this: ^IStream, ppstm: ^^IStream) -> HRESULT, } IPersist :: struct #raw_union { @@ -3449,7 +3463,7 @@ IPersist :: struct #raw_union { } IPersistVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - GetClassID: proc "stdcall" (this: ^IPersist, pClassID: ^CLSID) -> HRESULT, + GetClassID: proc "system" (this: ^IPersist, pClassID: ^CLSID) -> HRESULT, } IPersistStream :: struct #raw_union { @@ -3458,10 +3472,10 @@ IPersistStream :: struct #raw_union { } IPersistStreamVtbl :: struct { using IPersistVtbl: IPersistVtbl, - IsDirty: proc "stdcall" (this: ^IPersistStream) -> HRESULT, - Load: proc "stdcall" (this: ^IPersistStream, pStm: ^IStream) -> HRESULT, - Save: proc "stdcall" (this: ^IPersistStream, pStm: ^IStream, fClearDirty: BOOL) -> HRESULT, - GetSizeMax: proc "stdcall" (this: ^IPersistStream, pcbSize: ^ULARGE_INTEGER) -> HRESULT, + IsDirty: proc "system" (this: ^IPersistStream) -> HRESULT, + Load: proc "system" (this: ^IPersistStream, pStm: ^IStream) -> HRESULT, + Save: proc "system" (this: ^IPersistStream, pStm: ^IStream, fClearDirty: BOOL) -> HRESULT, + GetSizeMax: proc "system" (this: ^IPersistStream, pcbSize: ^ULARGE_INTEGER) -> HRESULT, } IMoniker :: struct #raw_union { @@ -3470,21 +3484,21 @@ IMoniker :: struct #raw_union { } IMonikerVtbl :: struct { using IPersistStreamVtbl: IPersistStreamVtbl, - BindToObject: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, riidResult: REFIID, ppvResult: ^rawptr) -> HRESULT, - BindToStorage: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, riid: REFIID, ppvObj: ^rawptr) -> HRESULT, - Reduce: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, dwReduceHowFar: DWORD, ppmkToLeft: ^^IMoniker, ppmkReduced: ^^IMoniker) -> HRESULT, - ComposeWith: proc "stdcall" (this: ^IMoniker, pmkRight: ^IMoniker, fOnlyIfNotGeneric: BOOL, ppmkComposite: ^^IMoniker) -> HRESULT, - Enum: proc "stdcall" (this: ^IMoniker, fForward: BOOL, ppenumMoniker: ^^IEnumMoniker) -> HRESULT, - IsEqual: proc "stdcall" (this: ^IMoniker, pmkOtherMoniker: ^IMoniker) -> HRESULT, - Hash: proc "stdcall" (this: ^IMoniker, pdwHash: ^DWORD) -> HRESULT, - IsRunning: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pmkNewlyRunning: ^IMoniker) -> HRESULT, - GetTimeOfLastChange: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pFileTime: ^FILETIME) -> HRESULT, - Inverse: proc "stdcall" (this: ^IMoniker, ppmk: ^^IMoniker) -> HRESULT, - CommonPrefixWith: proc "stdcall" (this: ^IMoniker, pmkOther: ^IMoniker, ppmkPrefix: ^^IMoniker) -> HRESULT, - RelativePathTo: proc "stdcall" (this: ^IMoniker, pmkOther: ^IMoniker, ppmkRelPath: ^^IMoniker) -> HRESULT, - GetDisplayName: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, ppszDisplayName: ^LPOLESTR) -> HRESULT, - ParseDisplayName: proc "stdcall" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pszDisplayName: LPOLESTR, pchEaten: ^ULONG, ppmkOut: ^^IMoniker) -> HRESULT, - IsSystemMoniker: proc "stdcall" (this: ^IMoniker, pdwMksys: ^DWORD) -> HRESULT, + BindToObject: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, riidResult: REFIID, ppvResult: ^rawptr) -> HRESULT, + BindToStorage: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, riid: REFIID, ppvObj: ^rawptr) -> HRESULT, + Reduce: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, dwReduceHowFar: DWORD, ppmkToLeft: ^^IMoniker, ppmkReduced: ^^IMoniker) -> HRESULT, + ComposeWith: proc "system" (this: ^IMoniker, pmkRight: ^IMoniker, fOnlyIfNotGeneric: BOOL, ppmkComposite: ^^IMoniker) -> HRESULT, + Enum: proc "system" (this: ^IMoniker, fForward: BOOL, ppenumMoniker: ^^IEnumMoniker) -> HRESULT, + IsEqual: proc "system" (this: ^IMoniker, pmkOtherMoniker: ^IMoniker) -> HRESULT, + Hash: proc "system" (this: ^IMoniker, pdwHash: ^DWORD) -> HRESULT, + IsRunning: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pmkNewlyRunning: ^IMoniker) -> HRESULT, + GetTimeOfLastChange: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pFileTime: ^FILETIME) -> HRESULT, + Inverse: proc "system" (this: ^IMoniker, ppmk: ^^IMoniker) -> HRESULT, + CommonPrefixWith: proc "system" (this: ^IMoniker, pmkOther: ^IMoniker, ppmkPrefix: ^^IMoniker) -> HRESULT, + RelativePathTo: proc "system" (this: ^IMoniker, pmkOther: ^IMoniker, ppmkRelPath: ^^IMoniker) -> HRESULT, + GetDisplayName: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, ppszDisplayName: ^LPOLESTR) -> HRESULT, + ParseDisplayName: proc "system" (this: ^IMoniker, pbc: ^IBindCtx, pmkToLeft: ^IMoniker, pszDisplayName: LPOLESTR, pchEaten: ^ULONG, ppmkOut: ^^IMoniker) -> HRESULT, + IsSystemMoniker: proc "system" (this: ^IMoniker, pdwMksys: ^DWORD) -> HRESULT, } IEnumMoniker :: struct #raw_union { @@ -3493,10 +3507,10 @@ IEnumMoniker :: struct #raw_union { } IEnumMonikerVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Next: proc "stdcall" (this: ^IEnumMoniker, celt: ULONG, rgelt: ^^IMoniker, pceltFetched: ^ULONG) -> HRESULT, - Skip: proc "stdcall" (this: ^IEnumMoniker, celt: ULONG) -> HRESULT, - Reset: proc "stdcall" (this: ^IEnumMoniker) -> HRESULT, - Clone: proc "stdcall" (this: ^IEnumMoniker, ppenum: ^^IEnumMoniker) -> HRESULT, + Next: proc "system" (this: ^IEnumMoniker, celt: ULONG, rgelt: ^^IMoniker, pceltFetched: ^ULONG) -> HRESULT, + Skip: proc "system" (this: ^IEnumMoniker, celt: ULONG) -> HRESULT, + Reset: proc "system" (this: ^IEnumMoniker) -> HRESULT, + Clone: proc "system" (this: ^IEnumMoniker, ppenum: ^^IEnumMoniker) -> HRESULT, } IRunningObjectTable :: struct #raw_union { @@ -3505,13 +3519,13 @@ IRunningObjectTable :: struct #raw_union { } IRunningObjectTableVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Register: proc "stdcall" (this: ^IRunningObjectTable, grfFlags: DWORD, punkObject: ^IUnknown, pmkObjectName: ^IMoniker, pdwRegister: ^DWORD) -> HRESULT, - Revoke: proc "stdcall" (this: ^IRunningObjectTable, dwRegister: DWORD) -> HRESULT, - IsRunning: proc "stdcall" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker) -> HRESULT, - GetObject: proc "stdcall" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker, ppunkObject: ^^IUnknown) -> HRESULT, - NoteChangeTime: proc "stdcall" (this: ^IRunningObjectTable, dwRegister: DWORD, pfiletime: ^FILETIME) -> HRESULT, - GetTimeOfLastChange: proc "stdcall" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker, pfiletime: ^FILETIME) -> HRESULT, - EnumRunning: proc "stdcall" (this: ^IRunningObjectTable, ppenumMoniker: ^^IEnumMoniker) -> HRESULT, + Register: proc "system" (this: ^IRunningObjectTable, grfFlags: DWORD, punkObject: ^IUnknown, pmkObjectName: ^IMoniker, pdwRegister: ^DWORD) -> HRESULT, + Revoke: proc "system" (this: ^IRunningObjectTable, dwRegister: DWORD) -> HRESULT, + IsRunning: proc "system" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker) -> HRESULT, + GetObject: proc "system" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker, ppunkObject: ^^IUnknown) -> HRESULT, + NoteChangeTime: proc "system" (this: ^IRunningObjectTable, dwRegister: DWORD, pfiletime: ^FILETIME) -> HRESULT, + GetTimeOfLastChange: proc "system" (this: ^IRunningObjectTable, pmkObjectName: ^IMoniker, pfiletime: ^FILETIME) -> HRESULT, + EnumRunning: proc "system" (this: ^IRunningObjectTable, ppenumMoniker: ^^IEnumMoniker) -> HRESULT, } IEnumString :: struct #raw_union { @@ -3520,10 +3534,10 @@ IEnumString :: struct #raw_union { } IEnumStringVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Next: proc "stdcall" (this: ^IEnumString, celt: ULONG, rgelt: ^LPOLESTR, pceltFetched: ^ULONG) -> HRESULT, - Skip: proc "stdcall" (this: ^IEnumString, celt: ULONG) -> HRESULT, - Reset: proc "stdcall" (this: ^IEnumString) -> HRESULT, - Clone: proc "stdcall" (this: ^IEnumString, ppenum: ^^IEnumString) -> HRESULT, + Next: proc "system" (this: ^IEnumString, celt: ULONG, rgelt: ^LPOLESTR, pceltFetched: ^ULONG) -> HRESULT, + Skip: proc "system" (this: ^IEnumString, celt: ULONG) -> HRESULT, + Reset: proc "system" (this: ^IEnumString) -> HRESULT, + Clone: proc "system" (this: ^IEnumString, ppenum: ^^IEnumString) -> HRESULT, } IBindCtx :: struct #raw_union { @@ -3532,16 +3546,16 @@ IBindCtx :: struct #raw_union { } IBindCtxVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - RegisterObjectBound: proc "stdcall" (this: ^IBindCtx, punk: ^IUnknown) -> HRESULT, - RevokeObjectBound: proc "stdcall" (this: ^IBindCtx, punk: ^IUnknown) -> HRESULT, - ReleaseBoundObjects: proc "stdcall" (this: ^IBindCtx) -> HRESULT, - SetBindOptions: proc "stdcall" (this: ^IBindCtx, pbindopts: ^BIND_OPTS) -> HRESULT, - GetBindOptions: proc "stdcall" (this: ^IBindCtx, pbindopts: ^BIND_OPTS) -> HRESULT, - GetRunningObjectTable: proc "stdcall" (this: ^IBindCtx, pprot: ^^IRunningObjectTable) -> HRESULT, - RegisterObjectParam: proc "stdcall" (this: ^IBindCtx, pszKey: LPOLESTR, punk: ^IUnknown) -> HRESULT, - GetObjectParam: proc "stdcall" (this: ^IBindCtx, pszKey: LPOLESTR, ppunk: ^^IUnknown) -> HRESULT, - EnumObjectParam: proc "stdcall" (this: ^IBindCtx, ppenum: ^^IEnumString) -> HRESULT, - RevokeObjectParam: proc "stdcall" (this: ^IBindCtx, pszKey: LPOLESTR) -> HRESULT, + RegisterObjectBound: proc "system" (this: ^IBindCtx, punk: ^IUnknown) -> HRESULT, + RevokeObjectBound: proc "system" (this: ^IBindCtx, punk: ^IUnknown) -> HRESULT, + ReleaseBoundObjects: proc "system" (this: ^IBindCtx) -> HRESULT, + SetBindOptions: proc "system" (this: ^IBindCtx, pbindopts: ^BIND_OPTS) -> HRESULT, + GetBindOptions: proc "system" (this: ^IBindCtx, pbindopts: ^BIND_OPTS) -> HRESULT, + GetRunningObjectTable: proc "system" (this: ^IBindCtx, pprot: ^^IRunningObjectTable) -> HRESULT, + RegisterObjectParam: proc "system" (this: ^IBindCtx, pszKey: LPOLESTR, punk: ^IUnknown) -> HRESULT, + GetObjectParam: proc "system" (this: ^IBindCtx, pszKey: LPOLESTR, ppunk: ^^IUnknown) -> HRESULT, + EnumObjectParam: proc "system" (this: ^IBindCtx, ppenum: ^^IEnumString) -> HRESULT, + RevokeObjectParam: proc "system" (this: ^IBindCtx, pszKey: LPOLESTR) -> HRESULT, } IEnumShellItems :: struct #raw_union { @@ -3550,10 +3564,10 @@ IEnumShellItems :: struct #raw_union { } IEnumShellItemsVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - Next: proc "stdcall" (this: ^IEnumShellItems, celt: ULONG, rgelt: ^^IShellItem, pceltFetched: ^ULONG) -> HRESULT, - Skip: proc "stdcall" (this: ^IEnumShellItems, celt: ULONG) -> HRESULT, - Reset: proc "stdcall" (this: ^IEnumShellItems) -> HRESULT, - Clone: proc "stdcall" (this: ^IEnumShellItems, ppenum: ^^IEnumShellItems) -> HRESULT, + Next: proc "system" (this: ^IEnumShellItems, celt: ULONG, rgelt: ^^IShellItem, pceltFetched: ^ULONG) -> HRESULT, + Skip: proc "system" (this: ^IEnumShellItems, celt: ULONG) -> HRESULT, + Reset: proc "system" (this: ^IEnumShellItems) -> HRESULT, + Clone: proc "system" (this: ^IEnumShellItems, ppenum: ^^IEnumShellItems) -> HRESULT, } IShellItem :: struct #raw_union { @@ -3562,11 +3576,11 @@ IShellItem :: struct #raw_union { } IShellItemVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - BindToHandler: proc "stdcall" (this: ^IShellItem, pbc: ^IBindCtx, bhid: REFGUID, riid: REFIID, ppv: ^rawptr) -> HRESULT, - GetParent: proc "stdcall" (this: ^IShellItem, ppsiFolder: ^^IShellItem) -> HRESULT, - GetDisplayName: proc "stdcall" (this: ^IShellItem, sigdnName: SIGDN, ppszName: ^LPWSTR) -> HRESULT, - GetAttributes: proc "stdcall" (this: ^IShellItem, sfgaoMask: SFGAOF, psfgaoAttribs: ^SFGAOF) -> HRESULT, - Compare: proc "stdcall" (this: ^IShellItem, psi: ^IShellItem, hint: SICHINTF, piOrder: ^c_int) -> HRESULT, + BindToHandler: proc "system" (this: ^IShellItem, pbc: ^IBindCtx, bhid: REFGUID, riid: REFIID, ppv: ^rawptr) -> HRESULT, + GetParent: proc "system" (this: ^IShellItem, ppsiFolder: ^^IShellItem) -> HRESULT, + GetDisplayName: proc "system" (this: ^IShellItem, sigdnName: SIGDN, ppszName: ^LPWSTR) -> HRESULT, + GetAttributes: proc "system" (this: ^IShellItem, sfgaoMask: SFGAOF, psfgaoAttribs: ^SFGAOF) -> HRESULT, + Compare: proc "system" (this: ^IShellItem, psi: ^IShellItem, hint: SICHINTF, piOrder: ^c_int) -> HRESULT, } IShellItemArray :: struct #raw_union { @@ -3575,13 +3589,13 @@ IShellItemArray :: struct #raw_union { } IShellItemArrayVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - BindToHandler: proc "stdcall" (this: ^IShellItemArray, pbc: ^IBindCtx, bhid: REFGUID, riid: REFIID, ppvOut: ^rawptr) -> HRESULT, - GetPropertyStore: proc "stdcall" (this: ^IShellItemArray, flags: GETPROPERTYSTOREFLAGS, riid: REFIID, ppv: ^rawptr) -> HRESULT, - GetPropertyDescriptionList: proc "stdcall" (this: ^IShellItemArray, keyType: REFPROPERTYKEY, riid: REFIID, ppv: ^rawptr) -> HRESULT, - GetAttributes: proc "stdcall" (this: ^IShellItemArray, AttribFlags: SIATTRIBFLAGS, sfgaoMask: SFGAOF, psfgaoAttribs: ^SFGAOF) -> HRESULT, - GetCount: proc "stdcall" (this: ^IShellItemArray, pdwNumItems: ^DWORD) -> HRESULT, - GetItemAt: proc "stdcall" (this: ^IShellItemArray, dwIndex: DWORD, ppsi: ^^IShellItem) -> HRESULT, - EnumItems: proc "stdcall" (this: ^IShellItemArray, ppenumShellItems: ^^IEnumShellItems) -> HRESULT, + BindToHandler: proc "system" (this: ^IShellItemArray, pbc: ^IBindCtx, bhid: REFGUID, riid: REFIID, ppvOut: ^rawptr) -> HRESULT, + GetPropertyStore: proc "system" (this: ^IShellItemArray, flags: GETPROPERTYSTOREFLAGS, riid: REFIID, ppv: ^rawptr) -> HRESULT, + GetPropertyDescriptionList: proc "system" (this: ^IShellItemArray, keyType: REFPROPERTYKEY, riid: REFIID, ppv: ^rawptr) -> HRESULT, + GetAttributes: proc "system" (this: ^IShellItemArray, AttribFlags: SIATTRIBFLAGS, sfgaoMask: SFGAOF, psfgaoAttribs: ^SFGAOF) -> HRESULT, + GetCount: proc "system" (this: ^IShellItemArray, pdwNumItems: ^DWORD) -> HRESULT, + GetItemAt: proc "system" (this: ^IShellItemArray, dwIndex: DWORD, ppsi: ^^IShellItem) -> HRESULT, + EnumItems: proc "system" (this: ^IShellItemArray, ppenumShellItems: ^^IEnumShellItems) -> HRESULT, } IFileDialogEvents :: struct #raw_union { @@ -3590,13 +3604,13 @@ IFileDialogEvents :: struct #raw_union { } IFileDialogEventsVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - OnFileOk: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, - OnFolderChanging: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psiFolder: ^IShellItem) -> HRESULT, - OnFolderChange: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, - OnSelectionChange: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, - OnShareViolation: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psi: ^IShellItem, pResponse: ^FDE_SHAREVIOLATION_RESPONSE) -> HRESULT, - OnTypeChange: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, - OnOverwrite: proc "stdcall" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psi: ^IShellItem, pResponse: ^FDE_SHAREVIOLATION_RESPONSE) -> HRESULT, + OnFileOk: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, + OnFolderChanging: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psiFolder: ^IShellItem) -> HRESULT, + OnFolderChange: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, + OnSelectionChange: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, + OnShareViolation: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psi: ^IShellItem, pResponse: ^FDE_SHAREVIOLATION_RESPONSE) -> HRESULT, + OnTypeChange: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog) -> HRESULT, + OnOverwrite: proc "system" (this: ^IFileDialogEvents, pfd: ^IFileDialog, psi: ^IShellItem, pResponse: ^FDE_SHAREVIOLATION_RESPONSE) -> HRESULT, } IShellItemFilter :: struct #raw_union { @@ -3605,8 +3619,8 @@ IShellItemFilter :: struct #raw_union { } IShellItemFilterVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - IncludeItem: proc "stdcall" (this: ^IShellItemFilter, psi: ^IShellItem) -> HRESULT, - GetEnumFlagsForItem: proc "stdcall" (this: ^IShellItemFilter, psi: ^IShellItem, pgrfFlags: ^SHCONTF) -> HRESULT, + IncludeItem: proc "system" (this: ^IShellItemFilter, psi: ^IShellItem) -> HRESULT, + GetEnumFlagsForItem: proc "system" (this: ^IShellItemFilter, psi: ^IShellItem, pgrfFlags: ^SHCONTF) -> HRESULT, } IFileDialog :: struct #raw_union { @@ -3615,29 +3629,29 @@ IFileDialog :: struct #raw_union { } IFileDialogVtbl :: struct { using IModalWindowVtbl: IModalWindowVtbl, - SetFileTypes: proc "stdcall" (this: ^IFileDialog, cFileTypes: UINT, rgFilterSpec: ^COMDLG_FILTERSPEC) -> HRESULT, - SetFileTypeIndex: proc "stdcall" (this: ^IFileDialog, iFileType: UINT) -> HRESULT, - GetFileTypeIndex: proc "stdcall" (this: ^IFileDialog, piFileType: ^UINT) -> HRESULT, - Advise: proc "stdcall" (this: ^IFileDialog, pfde: ^IFileDialogEvents, pdwCookie: ^DWORD) -> HRESULT, - Unadvise: proc "stdcall" (this: ^IFileDialog, dwCookie: DWORD) -> HRESULT, - SetOptions: proc "stdcall" (this: ^IFileDialog, fos: FILEOPENDIALOGOPTIONS) -> HRESULT, - GetOptions: proc "stdcall" (this: ^IFileDialog, pfos: ^FILEOPENDIALOGOPTIONS) -> HRESULT, - SetDefaultFolder: proc "stdcall" (this: ^IFileDialog, psi: ^IShellItem) -> HRESULT, - SetFolder: proc "stdcall" (this: ^IFileDialog, psi: ^IShellItem) -> HRESULT, - GetFolder: proc "stdcall" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, - GetCurrentSelection: proc "stdcall" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, - SetFileName: proc "stdcall" (this: ^IFileDialog, pszName: LPCWSTR) -> HRESULT, - GetFileName: proc "stdcall" (this: ^IFileDialog, pszName: ^LPCWSTR) -> HRESULT, - SetTitle: proc "stdcall" (this: ^IFileDialog, pszTitle: LPCWSTR) -> HRESULT, - SetOkButtonLabel: proc "stdcall" (this: ^IFileDialog, pszText: LPCWSTR) -> HRESULT, - SetFileNameLabel: proc "stdcall" (this: ^IFileDialog, pszLabel: LPCWSTR) -> HRESULT, - GetResult: proc "stdcall" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, - AddPlace: proc "stdcall" (this: ^IFileDialog, psi: ^IShellItem, fdap: FDAP) -> HRESULT, - SetDefaultExtension: proc "stdcall" (this: ^IFileDialog, pszDefaultExtension: LPCWSTR) -> HRESULT, - Close: proc "stdcall" (this: ^IFileDialog, hr: HRESULT) -> HRESULT, - SetClientGuid: proc "stdcall" (this: ^IFileDialog, guid: REFGUID) -> HRESULT, - ClearClientData: proc "stdcall" (this: ^IFileDialog) -> HRESULT, - SetFilter: proc "stdcall" (this: ^IFileDialog, pFilter: ^IShellItemFilter) -> HRESULT, + SetFileTypes: proc "system" (this: ^IFileDialog, cFileTypes: UINT, rgFilterSpec: ^COMDLG_FILTERSPEC) -> HRESULT, + SetFileTypeIndex: proc "system" (this: ^IFileDialog, iFileType: UINT) -> HRESULT, + GetFileTypeIndex: proc "system" (this: ^IFileDialog, piFileType: ^UINT) -> HRESULT, + Advise: proc "system" (this: ^IFileDialog, pfde: ^IFileDialogEvents, pdwCookie: ^DWORD) -> HRESULT, + Unadvise: proc "system" (this: ^IFileDialog, dwCookie: DWORD) -> HRESULT, + SetOptions: proc "system" (this: ^IFileDialog, fos: FILEOPENDIALOGOPTIONS) -> HRESULT, + GetOptions: proc "system" (this: ^IFileDialog, pfos: ^FILEOPENDIALOGOPTIONS) -> HRESULT, + SetDefaultFolder: proc "system" (this: ^IFileDialog, psi: ^IShellItem) -> HRESULT, + SetFolder: proc "system" (this: ^IFileDialog, psi: ^IShellItem) -> HRESULT, + GetFolder: proc "system" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, + GetCurrentSelection: proc "system" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, + SetFileName: proc "system" (this: ^IFileDialog, pszName: LPCWSTR) -> HRESULT, + GetFileName: proc "system" (this: ^IFileDialog, pszName: ^LPCWSTR) -> HRESULT, + SetTitle: proc "system" (this: ^IFileDialog, pszTitle: LPCWSTR) -> HRESULT, + SetOkButtonLabel: proc "system" (this: ^IFileDialog, pszText: LPCWSTR) -> HRESULT, + SetFileNameLabel: proc "system" (this: ^IFileDialog, pszLabel: LPCWSTR) -> HRESULT, + GetResult: proc "system" (this: ^IFileDialog, ppsi: ^^IShellItem) -> HRESULT, + AddPlace: proc "system" (this: ^IFileDialog, psi: ^IShellItem, fdap: FDAP) -> HRESULT, + SetDefaultExtension: proc "system" (this: ^IFileDialog, pszDefaultExtension: LPCWSTR) -> HRESULT, + Close: proc "system" (this: ^IFileDialog, hr: HRESULT) -> HRESULT, + SetClientGuid: proc "system" (this: ^IFileDialog, guid: REFGUID) -> HRESULT, + ClearClientData: proc "system" (this: ^IFileDialog) -> HRESULT, + SetFilter: proc "system" (this: ^IFileDialog, pFilter: ^IShellItemFilter) -> HRESULT, } IFileOpenDialog :: struct #raw_union { @@ -3646,8 +3660,8 @@ IFileOpenDialog :: struct #raw_union { } IFileOpenDialogVtbl :: struct { using IFileDialogVtbl: IFileDialogVtbl, - GetResults: proc "stdcall" (this: ^IFileOpenDialog, ppenum: ^^IShellItemArray) -> HRESULT, - GetSelectedItems: proc "stdcall" (this: ^IFileOpenDialog, ppsai: ^^IShellItemArray) -> HRESULT, + GetResults: proc "system" (this: ^IFileOpenDialog, ppenum: ^^IShellItemArray) -> HRESULT, + GetSelectedItems: proc "system" (this: ^IFileOpenDialog, ppsai: ^^IShellItemArray) -> HRESULT, } IPropertyStore :: struct #raw_union { @@ -3656,11 +3670,11 @@ IPropertyStore :: struct #raw_union { } IPropertyStoreVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - GetCount: proc "stdcall" (this: ^IPropertyStore, cProps: ^DWORD) -> HRESULT, - GetAt: proc "stdcall" (this: ^IPropertyStore, iProp: DWORD, pkey: ^PROPERTYKEY) -> HRESULT, - GetValue: proc "stdcall" (this: ^IPropertyStore, key: REFPROPERTYKEY, pv: ^PROPVARIANT) -> HRESULT, - SetValue: proc "stdcall" (this: ^IPropertyStore, key: REFPROPERTYKEY, propvar: REFPROPVARIANT) -> HRESULT, - Commit: proc "stdcall" (this: ^IPropertyStore) -> HRESULT, + GetCount: proc "system" (this: ^IPropertyStore, cProps: ^DWORD) -> HRESULT, + GetAt: proc "system" (this: ^IPropertyStore, iProp: DWORD, pkey: ^PROPERTYKEY) -> HRESULT, + GetValue: proc "system" (this: ^IPropertyStore, key: REFPROPERTYKEY, pv: ^PROPVARIANT) -> HRESULT, + SetValue: proc "system" (this: ^IPropertyStore, key: REFPROPERTYKEY, propvar: REFPROPVARIANT) -> HRESULT, + Commit: proc "system" (this: ^IPropertyStore) -> HRESULT, } IPropertyDescriptionList :: struct #raw_union { @@ -3669,8 +3683,8 @@ IPropertyDescriptionList :: struct #raw_union { } IPropertyDescriptionListVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - GetCount: proc "stdcall" (this: ^IPropertyDescriptionList, pcElem: ^UINT) -> HRESULT, - GetAt: proc "stdcall" (this: ^IPropertyDescriptionList, iElem: UINT, riid: REFIID, ppv: ^rawptr) -> HRESULT, + GetCount: proc "system" (this: ^IPropertyDescriptionList, pcElem: ^UINT) -> HRESULT, + GetAt: proc "system" (this: ^IPropertyDescriptionList, iElem: UINT, riid: REFIID, ppv: ^rawptr) -> HRESULT, } IFileOperationProgressSink :: struct #raw_union { @@ -3679,22 +3693,22 @@ IFileOperationProgressSink :: struct #raw_union { } IFileOperationProgressSinkVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - StartOperations: proc "stdcall" (this: ^IFileOperationProgressSink) -> HRESULT, - FinishOperations: proc "stdcall" (this: ^IFileOperationProgressSink, hrResult: HRESULT) -> HRESULT, - PreRenameItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, - PostRenameItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, pszNewName: LPCWSTR, hrRename: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, - PreMoveItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, - PostMoveItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, hrMove: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, - PreCopyItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, - PostCopyItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, hrMove: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, - PreDeleteItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem) -> HRESULT, - PostDeleteItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, hrDelete: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, - PreNewItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, - PostNewItem: proc "stdcall" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, pszTemplateName: LPCWSTR, dwFileAttributes: DWORD, hrNew: HRESULT, psiNewItem: ^IShellItem) -> HRESULT, - UpdateProgress: proc "stdcall" (this: ^IFileOperationProgressSink, iWorkTotal: UINT, iWorkSoFar: UINT) -> HRESULT, - ResetTimer: proc "stdcall" (this: ^IFileOperationProgressSink) -> HRESULT, - PauseTimer: proc "stdcall" (this: ^IFileOperationProgressSink) -> HRESULT, - ResumeTimer: proc "stdcall" (this: ^IFileOperationProgressSink) -> HRESULT, + StartOperations: proc "system" (this: ^IFileOperationProgressSink) -> HRESULT, + FinishOperations: proc "system" (this: ^IFileOperationProgressSink, hrResult: HRESULT) -> HRESULT, + PreRenameItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, + PostRenameItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, pszNewName: LPCWSTR, hrRename: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, + PreMoveItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, + PostMoveItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, hrMove: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, + PreCopyItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, + PostCopyItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, hrMove: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, + PreDeleteItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem) -> HRESULT, + PostDeleteItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiItem: ^IShellItem, hrDelete: HRESULT, psiNewlyCreated: ^IShellItem) -> HRESULT, + PreNewItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR) -> HRESULT, + PostNewItem: proc "system" (this: ^IFileOperationProgressSink, dwFlags: DWORD, psiDestinationFolder: ^IShellItem, pszNewName: LPCWSTR, pszTemplateName: LPCWSTR, dwFileAttributes: DWORD, hrNew: HRESULT, psiNewItem: ^IShellItem) -> HRESULT, + UpdateProgress: proc "system" (this: ^IFileOperationProgressSink, iWorkTotal: UINT, iWorkSoFar: UINT) -> HRESULT, + ResetTimer: proc "system" (this: ^IFileOperationProgressSink) -> HRESULT, + PauseTimer: proc "system" (this: ^IFileOperationProgressSink) -> HRESULT, + ResumeTimer: proc "system" (this: ^IFileOperationProgressSink) -> HRESULT, } IFileSaveDialog :: struct #raw_union { @@ -3703,11 +3717,11 @@ IFileSaveDialog :: struct #raw_union { } IFileSaveDialogVtbl :: struct { using IFileDialogVtbl: IFileDialogVtbl, - SetSaveAsItem: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem) -> HRESULT, - SetProperties: proc "stdcall" (this: ^IFileSaveDialog, pStore: ^IPropertyStore) -> HRESULT, - SetCollectedProperties: proc "stdcall" (this: ^IFileSaveDialog, pList: ^IPropertyDescriptionList, fAppendDefault: BOOL) -> HRESULT, - GetProperties: proc "stdcall" (this: ^IFileSaveDialog, ppStore: ^^IPropertyStore) -> HRESULT, - ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, + SetSaveAsItem: proc "system" (this: ^IFileSaveDialog, psi: ^IShellItem) -> HRESULT, + SetProperties: proc "system" (this: ^IFileSaveDialog, pStore: ^IPropertyStore) -> HRESULT, + SetCollectedProperties: proc "system" (this: ^IFileSaveDialog, pList: ^IPropertyDescriptionList, fAppendDefault: BOOL) -> HRESULT, + GetProperties: proc "system" (this: ^IFileSaveDialog, ppStore: ^^IPropertyStore) -> HRESULT, + ApplyProperties: proc "system" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, } ITaskbarList :: struct #raw_union { @@ -3716,11 +3730,11 @@ ITaskbarList :: struct #raw_union { } ITaskbarListVtbl :: struct { using IUnknownVtbl: IUnknownVtbl, - HrInit: proc "stdcall" (this: ^ITaskbarList) -> HRESULT, - AddTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, - DeleteTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, - ActivateTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, - SetActiveAlt: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + HrInit: proc "system" (this: ^ITaskbarList) -> HRESULT, + AddTab: proc "system" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + DeleteTab: proc "system" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + ActivateTab: proc "system" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + SetActiveAlt: proc "system" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, } ITaskbarList2 :: struct #raw_union { @@ -3729,7 +3743,7 @@ ITaskbarList2 :: struct #raw_union { } ITaskbarList2Vtbl :: struct { using ITaskbarListVtbl: ITaskbarListVtbl, - MarkFullscreenWindow: proc "stdcall" (this: ^ITaskbarList2, hwnd: HWND, fFullscreen: BOOL) -> HRESULT, + MarkFullscreenWindow: proc "system" (this: ^ITaskbarList2, hwnd: HWND, fFullscreen: BOOL) -> HRESULT, } TBPFLAG :: enum c_int { @@ -3774,18 +3788,18 @@ ITaskbarList3 :: struct #raw_union { } ITaskbarList3Vtbl :: struct { using ITaskbarList2Vtbl: ITaskbarList2Vtbl, - SetProgressValue: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, ullCompleted: ULONGLONG, ullTotal: ULONGLONG) -> HRESULT, - SetProgressState: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, tbpFlags: TBPFLAG) -> HRESULT, - RegisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND) -> HRESULT, - UnregisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND) -> HRESULT, - SetTabOrder: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndInsertBefore: HWND) -> HRESULT, - SetTabActive: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND, dwReserved: DWORD) -> HRESULT, - ThumbBarAddButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, - ThumbBarUpdateButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, - ThumbBarSetImageList: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, himl: HIMAGELIST) -> HRESULT, - SetOverlayIcon: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, hIcon: HICON, pszDescription: LPCWSTR) -> HRESULT, - SetThumbnailTooltip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, pszTip: LPCWSTR) -> HRESULT, - SetThumbnailClip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, prcClip: ^RECT) -> HRESULT, + SetProgressValue: proc "system" (this: ^ITaskbarList3, hwnd: HWND, ullCompleted: ULONGLONG, ullTotal: ULONGLONG) -> HRESULT, + SetProgressState: proc "system" (this: ^ITaskbarList3, hwnd: HWND, tbpFlags: TBPFLAG) -> HRESULT, + RegisterTab: proc "system" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND) -> HRESULT, + UnregisterTab: proc "system" (this: ^ITaskbarList3, hwndTab: HWND) -> HRESULT, + SetTabOrder: proc "system" (this: ^ITaskbarList3, hwndTab: HWND, hwndInsertBefore: HWND) -> HRESULT, + SetTabActive: proc "system" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND, dwReserved: DWORD) -> HRESULT, + ThumbBarAddButtons: proc "system" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, + ThumbBarUpdateButtons: proc "system" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, + ThumbBarSetImageList: proc "system" (this: ^ITaskbarList3, hwnd: HWND, himl: HIMAGELIST) -> HRESULT, + SetOverlayIcon: proc "system" (this: ^ITaskbarList3, hwnd: HWND, hIcon: HICON, pszDescription: LPCWSTR) -> HRESULT, + SetThumbnailTooltip: proc "system" (this: ^ITaskbarList3, hwnd: HWND, pszTip: LPCWSTR) -> HRESULT, + SetThumbnailClip: proc "system" (this: ^ITaskbarList3, hwnd: HWND, prcClip: ^RECT) -> HRESULT, } MEMORYSTATUSEX :: struct { diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index ee536e0a8..0c92adca4 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -3,7 +3,7 @@ package sys_windows foreign import user32 "system:User32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign user32 { GetClassInfoW :: proc(hInstance: HINSTANCE, lpClassNAme: LPCWSTR, lpWndClass: ^WNDCLASSW) -> BOOL --- GetClassInfoExW :: proc(hInsatnce: HINSTANCE, lpszClass: LPCWSTR, lpwcx: ^WNDCLASSEXW) -> BOOL --- @@ -136,6 +136,7 @@ foreign user32 { GetKeyboardState :: proc(lpKeyState: PBYTE) -> BOOL --- MapVirtualKeyW :: proc(uCode: UINT, uMapType: UINT) -> UINT --- + ToUnicode :: proc(nVirtKey: UINT, wScanCode: UINT, lpKeyState: ^BYTE, pwszBuff: LPWSTR, cchBuff: c_int, wFlags: UINT) -> c_int --- SetWindowsHookExW :: proc(idHook: c_int, lpfn: HOOKPROC, hmod: HINSTANCE, dwThreadId: DWORD) -> HHOOK --- UnhookWindowsHookEx :: proc(hhk: HHOOK) -> BOOL --- @@ -160,6 +161,8 @@ foreign user32 { MonitorFromRect :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR --- MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR --- EnumDisplayMonitors :: proc(hdc: HDC, lprcClip: LPRECT, lpfnEnum: Monitor_Enum_Proc, dwData: LPARAM) -> BOOL --- + + EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL --- SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT --- GetThreadDpiAwarenessContext :: proc() -> DPI_AWARENESS_CONTEXT --- @@ -233,7 +236,7 @@ foreign user32 { EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL --- } -CreateWindowW :: #force_inline proc "stdcall" ( +CreateWindowW :: #force_inline proc "system" ( lpClassName: LPCTSTR, lpWindowName: LPCTSTR, dwStyle: DWORD, @@ -263,7 +266,7 @@ CreateWindowW :: #force_inline proc "stdcall" ( } when ODIN_ARCH == .amd64 { - @(default_calling_convention="stdcall") + @(default_calling_convention="system") foreign user32 { GetClassLongPtrW :: proc(hWnd: HWND, nIndex: c_int) -> ULONG_PTR --- SetClassLongPtrW :: proc(hWnd: HWND, nIndex: c_int, dwNewLong: LONG_PTR) -> ULONG_PTR --- @@ -309,7 +312,8 @@ Monitor_From_Flags :: enum DWORD { MONITOR_DEFAULTTONEAREST = 0x00000002, // Returns a handle to the display monitor that is nearest to the window } -Monitor_Enum_Proc :: #type proc "stdcall" (HMONITOR, HDC, LPRECT, LPARAM) -> BOOL +Monitor_Enum_Proc :: #type proc "system" (HMONITOR, HDC, LPRECT, LPARAM) -> BOOL +Window_Enum_Proc :: #type proc "system" (HWND, LPARAM) -> BOOL USER_DEFAULT_SCREEN_DPI :: 96 DPI_AWARENESS_CONTEXT :: distinct HANDLE diff --git a/core/sys/windows/userenv.odin b/core/sys/windows/userenv.odin index 92bc09a7e..a31e363e1 100644 --- a/core/sys/windows/userenv.odin +++ b/core/sys/windows/userenv.odin @@ -3,7 +3,7 @@ package sys_windows foreign import userenv "system:Userenv.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign userenv { GetUserProfileDirectoryW :: proc(hToken: HANDLE, lpProfileDir: LPWSTR, diff --git a/core/sys/windows/ux_theme.odin b/core/sys/windows/ux_theme.odin index 39b489bc0..7af399361 100644 --- a/core/sys/windows/ux_theme.odin +++ b/core/sys/windows/ux_theme.odin @@ -6,7 +6,7 @@ foreign import uxtheme "system:UxTheme.lib" MARGINS :: distinct [4]int PMARGINS :: ^MARGINS -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign uxtheme { IsThemeActive :: proc() -> BOOL --- } diff --git a/core/sys/windows/wgl.odin b/core/sys/windows/wgl.odin index 77cff2fa9..d0d96d90b 100644 --- a/core/sys/windows/wgl.odin +++ b/core/sys/windows/wgl.odin @@ -66,7 +66,7 @@ GetExtensionsStringARBType :: #type proc "c" (HDC) -> cstring wglGetExtensionsStringARB: GetExtensionsStringARBType -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign Opengl32 { wglCreateContext :: proc(hdc: HDC) -> HGLRC --- wglMakeCurrent :: proc(hdc: HDC, HGLRC: HGLRC) -> BOOL --- diff --git a/core/sys/windows/winerror.odin b/core/sys/windows/winerror.odin index f552b9a53..118327ffa 100644 --- a/core/sys/windows/winerror.odin +++ b/core/sys/windows/winerror.odin @@ -48,3 +48,5485 @@ ERROR_PIPE_BUSY : DWORD : 231 E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001 SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool { return result >= 0 } + + +System_Error :: enum DWORD { + // The operation completed successfully. + SUCCESS = 0x0, + // Incorrect function. + INVALID_FUNCTION = 0x1, + // The system cannot find the file specified. + FILE_NOT_FOUND = 0x2, + // The system cannot find the path specified. + PATH_NOT_FOUND = 0x3, + // The system cannot open the file. + TOO_MANY_OPEN_FILES = 0x4, + // Access is denied. + ACCESS_DENIED = 0x5, + // The handle is invalid. + INVALID_HANDLE = 0x6, + // The storage control blocks were destroyed. + ARENA_TRASHED = 0x7, + // Not enough memory resources are available to process this command. + NOT_ENOUGH_MEMORY = 0x8, + // The storage control block address is invalid. + INVALID_BLOCK = 0x9, + // The environment is incorrect. + BAD_ENVIRONMENT = 0xA, + // An attempt was made to load a program with an incorrect format. + BAD_FORMAT = 0xB, + // The access code is invalid. + INVALID_ACCESS = 0xC, + // The data is invalid. + INVALID_DATA = 0xD, + // Not enough storage is available to complete this operation. + OUTOFMEMORY = 0xE, + // The system cannot find the drive specified. + INVALID_DRIVE = 0xF, + // The directory cannot be removed. + CURRENT_DIRECTORY = 0x10, + // The system cannot move the file to a different disk drive. + NOT_SAME_DEVICE = 0x11, + // There are no more files. + NO_MORE_FILES = 0x12, + // The media is write protected. + WRITE_PROTECT = 0x13, + // The system cannot find the device specified. + BAD_UNIT = 0x14, + // The device is not ready. + NOT_READY = 0x15, + // The device does not recognize the command. + BAD_COMMAND = 0x16, + // Data error cyclic redundancy check. + CRC = 0x17, + // The program issued a command but the command length is incorrect. + BAD_LENGTH = 0x18, + // The drive cannot locate a specific area or track on the disk. + SEEK = 0x19, + // The specified disk or diskette cannot be accessed. + NOT_DOS_DISK = 0x1A, + // The drive cannot find the sector requested. + SECTOR_NOT_FOUND = 0x1B, + // The printer is out of paper. + OUT_OF_PAPER = 0x1C, + // The system cannot write to the specified device. + WRITE_FAULT = 0x1D, + // The system cannot read from the specified device. + READ_FAULT = 0x1E, + // A device attached to the system is not functioning. + GEN_FAILURE = 0x1F, + // The process cannot access the file because it is being used by another process. + SHARING_VIOLATION = 0x20, + // The process cannot access the file because another process has locked a portion of the file. + LOCK_VIOLATION = 0x21, + // The wrong diskette is in the drive. Insert %2 Volume Serial Number: %3 into drive %1. + WRONG_DISK = 0x22, + // Too many files opened for sharing. + SHARING_BUFFER_EXCEEDED = 0x24, + // Reached the end of the file. + HANDLE_EOF = 0x26, + // The disk is full. + HANDLE_DISK_FULL = 0x27, + // The request is not supported. + NOT_SUPPORTED = 0x32, + // Windows cannot find the network path. Verify that the network path is correct and the destination computer is not busy or turned off. If Windows still cannot find the network path, contact your network administrator. + REM_NOT_LIST = 0x33, + // You were not connected because a duplicate name exists on the network. If joining a domain, go to System in Control Panel to change the computer name and try again. If joining a workgroup, choose another workgroup name. + DUP_NAME = 0x34, + // The network path was not found. + BAD_NETPATH = 0x35, + // The network is busy. + NETWORK_BUSY = 0x36, + // The specified network resource or device is no longer available. + DEV_NOT_EXIST = 0x37, + // The network BIOS command limit has been reached. + TOO_MANY_CMDS = 0x38, + // A network adapter hardware error occurred. + ADAP_HDW_ERR = 0x39, + // The specified server cannot perform the requested operation. + BAD_NET_RESP = 0x3A, + // An unexpected network error occurred. + UNEXP_NET_ERR = 0x3B, + // The remote adapter is not compatible. + BAD_REM_ADAP = 0x3C, + // The printer queue is full. + PRINTQ_FULL = 0x3D, + // Space to store the file waiting to be printed is not available on the server. + NO_SPOOL_SPACE = 0x3E, + // Your file waiting to be printed was deleted. + PRINT_CANCELLED = 0x3F, + // The specified network name is no longer available. + NETNAME_DELETED = 0x40, + // Network access is denied. + NETWORK_ACCESS_DENIED = 0x41, + // The network resource type is not correct. + BAD_DEV_TYPE = 0x42, + // The network name cannot be found. + BAD_NET_NAME = 0x43, + // The name limit for the local computer network adapter card was exceeded. + TOO_MANY_NAMES = 0x44, + // The network BIOS session limit was exceeded. + TOO_MANY_SESS = 0x45, + // The remote server has been paused or is in the process of being started. + SHARING_PAUSED = 0x46, + // No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept. + REQ_NOT_ACCEP = 0x47, + // The specified printer or disk device has been paused. + REDIR_PAUSED = 0x48, + // The file exists. + FILE_EXISTS = 0x50, + // The directory or file cannot be created. + CANNOT_MAKE = 0x52, + // Fail on INT 24. + FAIL_I24 = 0x53, + // Storage to process this request is not available. + OUT_OF_STRUCTURES = 0x54, + // The local device name is already in use. + ALREADY_ASSIGNED = 0x55, + // The specified network password is not correct. + INVALID_PASSWORD = 0x56, + // The parameter is incorrect. + INVALID_PARAMETER = 0x57, + // A write fault occurred on the network. + NET_WRITE_FAULT = 0x58, + // The system cannot start another process at this time. + NO_PROC_SLOTS = 0x59, + // Cannot create another system semaphore. + TOO_MANY_SEMAPHORES = 0x64, + // The exclusive semaphore is owned by another process. + EXCL_SEM_ALREADY_OWNED = 0x65, + // The semaphore is set and cannot be closed. + SEM_IS_SET = 0x66, + // The semaphore cannot be set again. + TOO_MANY_SEM_REQUESTS = 0x67, + // Cannot request exclusive semaphores at interrupt time. + INVALID_AT_INTERRUPT_TIME = 0x68, + // The previous ownership of this semaphore has ended. + SEM_OWNER_DIED = 0x69, + // Insert the diskette for drive %1. + SEM_USER_LIMIT = 0x6A, + // The program stopped because an alternate diskette was not inserted. + DISK_CHANGE = 0x6B, + // The disk is in use or locked by another process. + DRIVE_LOCKED = 0x6C, + // The pipe has been ended. + BROKEN_PIPE = 0x6D, + // The system cannot open the device or file specified. + OPEN_FAILED = 0x6E, + // The file name is too long. + BUFFER_OVERFLOW = 0x6F, + // There is not enough space on the disk. + DISK_FULL = 0x70, + // No more internal file identifiers available. + NO_MORE_SEARCH_HANDLES = 0x71, + // The target internal file identifier is incorrect. + INVALID_TARGET_HANDLE = 0x72, + // The IOCTL call made by the application program is not correct. + INVALID_CATEGORY = 0x75, + // The verify-on-write switch parameter value is not correct. + INVALID_VERIFY_SWITCH = 0x76, + // The system does not support the command requested. + BAD_DRIVER_LEVEL = 0x77, + // This function is not supported on this system. + CALL_NOT_IMPLEMENTED = 0x78, + // The semaphore timeout period has expired. + SEM_TIMEOUT = 0x79, + // The data area passed to a system call is too small. + INSUFFICIENT_BUFFER = 0x7A, + // The filename, directory name, or volume label syntax is incorrect. + INVALID_NAME = 0x7B, + // The system call level is not correct. + INVALID_LEVEL = 0x7C, + // The disk has no volume label. + NO_VOLUME_LABEL = 0x7D, + // The specified module could not be found. + MOD_NOT_FOUND = 0x7E, + // The specified procedure could not be found. + PROC_NOT_FOUND = 0x7F, + // There are no child processes to wait for. + WAIT_NO_CHILDREN = 0x80, + // The %1 application cannot be run in Win32 mode. + CHILD_NOT_COMPLETE = 0x81, + // Attempt to use a file handle to an open disk partition for an operation other than raw disk I/O. + DIRECT_ACCESS_HANDLE = 0x82, + // An attempt was made to move the file pointer before the beginning of the file. + NEGATIVE_SEEK = 0x83, + // The file pointer cannot be set on the specified device or file. + SEEK_ON_DEVICE = 0x84, + // A JOIN or SUBST command cannot be used for a drive that contains previously joined drives. + IS_JOIN_TARGET = 0x85, + // An attempt was made to use a JOIN or SUBST command on a drive that has already been joined. + IS_JOINED = 0x86, + // An attempt was made to use a JOIN or SUBST command on a drive that has already been substituted. + IS_SUBSTED = 0x87, + // The system tried to delete the JOIN of a drive that is not joined. + NOT_JOINED = 0x88, + // The system tried to delete the substitution of a drive that is not substituted. + NOT_SUBSTED = 0x89, + // The system tried to join a drive to a directory on a joined drive. + JOIN_TO_JOIN = 0x8A, + // The system tried to substitute a drive to a directory on a substituted drive. + SUBST_TO_SUBST = 0x8B, + // The system tried to join a drive to a directory on a substituted drive. + JOIN_TO_SUBST = 0x8C, + // The system tried to SUBST a drive to a directory on a joined drive. + SUBST_TO_JOIN = 0x8D, + // The system cannot perform a JOIN or SUBST at this time. + BUSY_DRIVE = 0x8E, + // The system cannot join or substitute a drive to or for a directory on the same drive. + SAME_DRIVE = 0x8F, + // The directory is not a subdirectory of the root directory. + DIR_NOT_ROOT = 0x90, + // The directory is not empty. + DIR_NOT_EMPTY = 0x91, + // The path specified is being used in a substitute. + IS_SUBST_PATH = 0x92, + // Not enough resources are available to process this command. + IS_JOIN_PATH = 0x93, + // The path specified cannot be used at this time. + PATH_BUSY = 0x94, + // An attempt was made to join or substitute a drive for which a directory on the drive is the target of a previous substitute. + IS_SUBST_TARGET = 0x95, + // System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. + SYSTEM_TRACE = 0x96, + // The number of specified semaphore events for DosMuxSemWait is not correct. + INVALID_EVENT_COUNT = 0x97, + // DosMuxSemWait did not execute; too many semaphores are already set. + TOO_MANY_MUXWAITERS = 0x98, + // The DosMuxSemWait list is not correct. + INVALID_LIST_FORMAT = 0x99, + // The volume label you entered exceeds the label character limit of the target file system. + LABEL_TOO_LONG = 0x9A, + // Cannot create another thread. + TOO_MANY_TCBS = 0x9B, + // The recipient process has refused the signal. + SIGNAL_REFUSED = 0x9C, + // The segment is already discarded and cannot be locked. + DISCARDED = 0x9D, + // The segment is already unlocked. + NOT_LOCKED = 0x9E, + // The address for the thread ID is not correct. + BAD_THREADID_ADDR = 0x9F, + // One or more arguments are not correct. + BAD_ARGUMENTS = 0xA0, + // The specified path is invalid. + BAD_PATHNAME = 0xA1, + // A signal is already pending. + SIGNAL_PENDING = 0xA2, + // No more threads can be created in the system. + MAX_THRDS_REACHED = 0xA4, + // Unable to lock a region of a file. + LOCK_FAILED = 0xA7, + // The requested resource is in use. + BUSY = 0xAA, + // Device's command support detection is in progress. + DEVICE_SUPPORT_IN_PROGRESS = 0xAB, + // A lock request was not outstanding for the supplied cancel region. + CANCEL_VIOLATION = 0xAD, + // The file system does not support atomic changes to the lock type. + ATOMIC_LOCKS_NOT_SUPPORTED = 0xAE, + // The system detected a segment number that was not correct. + INVALID_SEGMENT_NUMBER = 0xB4, + // The operating system cannot run %1. + INVALID_ORDINAL = 0xB6, + // Cannot create a file when that file already exists. + ALREADY_EXISTS = 0xB7, + // The flag passed is not correct. + INVALID_FLAG_NUMBER = 0xBA, + // The specified system semaphore name was not found. + SEM_NOT_FOUND = 0xBB, + // The operating system cannot run %1. + INVALID_STARTING_CODESEG = 0xBC, + // The operating system cannot run %1. + INVALID_STACKSEG = 0xBD, + // The operating system cannot run %1. + INVALID_MODULETYPE = 0xBE, + // Cannot run %1 in Win32 mode. + INVALID_EXE_SIGNATURE = 0xBF, + // The operating system cannot run %1. + EXE_MARKED_INVALID = 0xC0, + // %1 is not a valid Win32 application. + BAD_EXE_FORMAT = 0xC1, + // The operating system cannot run %1. + ITERATED_DATA_EXCEEDS_64k = 0xC2, + // The operating system cannot run %1. + INVALID_MINALLOCSIZE = 0xC3, + // The operating system cannot run this application program. + DYNLINK_FROM_INVALID_RING = 0xC4, + // The operating system is not presently configured to run this application. + IOPL_NOT_ENABLED = 0xC5, + // The operating system cannot run %1. + INVALID_SEGDPL = 0xC6, + // The operating system cannot run this application program. + AUTODATASEG_EXCEEDS_64k = 0xC7, + // The code segment cannot be greater than or equal to 64K. + RING2SEG_MUST_BE_MOVABLE = 0xC8, + // The operating system cannot run %1. + RELOC_CHAIN_XEEDS_SEGLIM = 0xC9, + // The operating system cannot run %1. + INFLOOP_IN_RELOC_CHAIN = 0xCA, + // The system could not find the environment option that was entered. + ENVVAR_NOT_FOUND = 0xCB, + // No process in the command subtree has a signal handler. + NO_SIGNAL_SENT = 0xCD, + // The filename or extension is too long. + FILENAME_EXCED_RANGE = 0xCE, + // The ring 2 stack is in use. + RING2_STACK_IN_USE = 0xCF, + // The global filename characters, * or ?, are entered incorrectly or too many global filename characters are specified. + META_EXPANSION_TOO_LONG = 0xD0, + // The signal being posted is not correct. + INVALID_SIGNAL_NUMBER = 0xD1, + // The signal handler cannot be set. + THREAD_1_INACTIVE = 0xD2, + // The segment is locked and cannot be reallocated. + LOCKED = 0xD4, + // Too many dynamic-link modules are attached to this program or dynamic-link module. + TOO_MANY_MODULES = 0xD6, + // Cannot nest calls to LoadModule. + NESTING_NOT_ALLOWED = 0xD7, + // This version of %1 is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher. + EXE_MACHINE_TYPE_MISMATCH = 0xD8, + // The image file %1 is signed, unable to modify. + EXE_CANNOT_MODIFY_SIGNED_BINARY = 0xD9, + // The image file %1 is strong signed, unable to modify. + EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY = 0xDA, + // This file is checked out or locked for editing by another user. + FILE_CHECKED_OUT = 0xDC, + // The file must be checked out before saving changes. + CHECKOUT_REQUIRED = 0xDD, + // The file type being saved or retrieved has been blocked. + BAD_FILE_TYPE = 0xDE, + // The file size exceeds the limit allowed and cannot be saved. + FILE_TOO_LARGE = 0xDF, + // Access Denied. Before opening files in this location, you must first add the web site to your trusted sites list, browse to the web site, and select the option to login automatically. + FORMS_AUTH_REQUIRED = 0xE0, + // Operation did not complete successfully because the file contains a virus or potentially unwanted software. + VIRUS_INFECTED = 0xE1, + // This file contains a virus or potentially unwanted software and cannot be opened. Due to the nature of this virus or potentially unwanted software, the file has been removed from this location. + VIRUS_DELETED = 0xE2, + // The pipe is local. + PIPE_LOCAL = 0xE5, + // The pipe state is invalid. + BAD_PIPE = 0xE6, + // All pipe instances are busy. + PIPE_BUSY = 0xE7, + // The pipe is being closed. + NO_DATA = 0xE8, + // No process is on the other end of the pipe. + PIPE_NOT_CONNECTED = 0xE9, + // More data is available. + MORE_DATA = 0xEA, + // The session was canceled. + VC_DISCONNECTED = 0xF0, + // The specified extended attribute name was invalid. + INVALID_EA_NAME = 0xFE, + // The extended attributes are inconsistent. + EA_LIST_INCONSISTENT = 0xFF, + // The wait operation timed out. + WAIT_TIMEOUT = 0x102, + // No more data is available. + NO_MORE_ITEMS = 0x103, + // The copy functions cannot be used. + CANNOT_COPY = 0x10A, + // The directory name is invalid. + DIRECTORY = 0x10B, + // The extended attributes did not fit in the buffer. + EAS_DIDNT_FIT = 0x113, + // The extended attribute file on the mounted file system is corrupt. + EA_FILE_CORRUPT = 0x114, + // The extended attribute table file is full. + EA_TABLE_FULL = 0x115, + // The specified extended attribute handle is invalid. + INVALID_EA_HANDLE = 0x116, + // The mounted file system does not support extended attributes. + EAS_NOT_SUPPORTED = 0x11A, + // Attempt to release mutex not owned by caller. + NOT_OWNER = 0x120, + // Too many posts were made to a semaphore. + TOO_MANY_POSTS = 0x12A, + // Only part of a ReadProcessMemory or WriteProcessMemory request was completed. + PARTIAL_COPY = 0x12B, + // The oplock request is denied. + OPLOCK_NOT_GRANTED = 0x12C, + // An invalid oplock acknowledgment was received by the system. + INVALID_OPLOCK_PROTOCOL = 0x12D, + // The volume is too fragmented to complete this operation. + DISK_TOO_FRAGMENTED = 0x12E, + // The file cannot be opened because it is in the process of being deleted. + DELETE_PENDING = 0x12F, + // Short name settings may not be changed on this volume due to the global registry setting. + INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 0x130, + // Short names are not enabled on this volume. + SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 0x131, + // The security stream for the given volume is in an inconsistent state. Please run CHKDSK on the volume. + SECURITY_STREAM_IS_INCONSISTENT = 0x132, + // A requested file lock operation cannot be processed due to an invalid byte range. + INVALID_LOCK_RANGE = 0x133, + // The subsystem needed to support the image type is not present. + IMAGE_SUBSYSTEM_NOT_PRESENT = 0x134, + // The specified file already has a notification GUID associated with it. + NOTIFICATION_GUID_ALREADY_DEFINED = 0x135, + // An invalid exception handler routine has been detected. + INVALID_EXCEPTION_HANDLER = 0x136, + // Duplicate privileges were specified for the token. + DUPLICATE_PRIVILEGES = 0x137, + // No ranges for the specified operation were able to be processed. + NO_RANGES_PROCESSED = 0x138, + // Operation is not allowed on a file system internal file. + NOT_ALLOWED_ON_SYSTEM_FILE = 0x139, + // The physical resources of this disk have been exhausted. + DISK_RESOURCES_EXHAUSTED = 0x13A, + // The token representing the data is invalid. + INVALID_TOKEN = 0x13B, + // The device does not support the command feature. + DEVICE_FEATURE_NOT_SUPPORTED = 0x13C, + // The system cannot find message text for message number 0x%1 in the message file for %2. + MR_MID_NOT_FOUND = 0x13D, + // The scope specified was not found. + SCOPE_NOT_FOUND = 0x13E, + // The Central Access Policy specified is not defined on the target machine. + UNDEFINED_SCOPE = 0x13F, + // The Central Access Policy obtained from Active Directory is invalid. + INVALID_CAP = 0x140, + // The device is unreachable. + DEVICE_UNREACHABLE = 0x141, + // The target device has insufficient resources to complete the operation. + DEVICE_NO_RESOURCES = 0x142, + // A data integrity checksum error occurred. Data in the file stream is corrupt. + DATA_CHECKSUM_ERROR = 0x143, + // An attempt was made to modify both a KERNEL and normal Extended Attribute EA in the same operation. + INTERMIXED_KERNEL_EA_OPERATION = 0x144, + // Device does not support file-level TRIM. + FILE_LEVEL_TRIM_NOT_SUPPORTED = 0x146, + // The command specified a data offset that does not align to the device's granularity/alignment. + OFFSET_ALIGNMENT_VIOLATION = 0x147, + // The command specified an invalid field in its parameter list. + INVALID_FIELD_IN_PARAMETER_LIST = 0x148, + // An operation is currently in progress with the device. + OPERATION_IN_PROGRESS = 0x149, + // An attempt was made to send down the command via an invalid path to the target device. + BAD_DEVICE_PATH = 0x14A, + // The command specified a number of descriptors that exceeded the maximum supported by the device. + TOO_MANY_DESCRIPTORS = 0x14B, + // Scrub is disabled on the specified file. + SCRUB_DATA_DISABLED = 0x14C, + // The storage device does not provide redundancy. + NOT_REDUNDANT_STORAGE = 0x14D, + // An operation is not supported on a resident file. + RESIDENT_FILE_NOT_SUPPORTED = 0x14E, + // An operation is not supported on a compressed file. + COMPRESSED_FILE_NOT_SUPPORTED = 0x14F, + // An operation is not supported on a directory. + DIRECTORY_NOT_SUPPORTED = 0x150, + // The specified copy of the requested data could not be read. + NOT_READ_FROM_COPY = 0x151, + // No action was taken as a system reboot is required. + FAIL_NOACTION_REBOOT = 0x15E, + // The shutdown operation failed. + FAIL_SHUTDOWN = 0x15F, + // The restart operation failed. + FAIL_RESTART = 0x160, + // The maximum number of sessions has been reached. + MAX_SESSIONS_REACHED = 0x161, + // The thread is already in background processing mode. + THREAD_MODE_ALREADY_BACKGROUND = 0x190, + // The thread is not in background processing mode. + THREAD_MODE_NOT_BACKGROUND = 0x191, + // The process is already in background processing mode. + PROCESS_MODE_ALREADY_BACKGROUND = 0x192, + // The process is not in background processing mode. + PROCESS_MODE_NOT_BACKGROUND = 0x193, + // Attempt to access invalid address. + INVALID_ADDRESS = 0x1E7, + + // User profile cannot be loaded. + USER_PROFILE_LOAD = 0x1F4, + // Arithmetic result exceeded 32 bits. + ARITHMETIC_OVERFLOW = 0x216, + // There is a process on other end of the pipe. + PIPE_CONNECTED = 0x217, + // Waiting for a process to open the other end of the pipe. + PIPE_LISTENING = 0x218, + // Application verifier has found an error in the current process. + VERIFIER_STOP = 0x219, + // An error occurred in the ABIOS subsystem. + ABIOS_ERROR = 0x21A, + // A warning occurred in the WX86 subsystem. + WX86_WARNING = 0x21B, + // An error occurred in the WX86 subsystem. + WX86_ERROR = 0x21C, + // An attempt was made to cancel or set a timer that has an associated APC and the subject thread is not the thread that originally set the timer with an associated APC routine. + TIMER_NOT_CANCELED = 0x21D, + // Unwind exception code. + UNWIND = 0x21E, + // An invalid or unaligned stack was encountered during an unwind operation. + BAD_STACK = 0x21F, + // An invalid unwind target was encountered during an unwind operation. + INVALID_UNWIND_TARGET = 0x220, + // Invalid Object Attributes specified to NtCreatePort or invalid Port Attributes specified to NtConnectPort + INVALID_PORT_ATTRIBUTES = 0x221, + // Length of message passed to NtRequestPort or NtRequestWaitReplyPort was longer than the maximum message allowed by the port. + PORT_MESSAGE_TOO_LONG = 0x222, + // An attempt was made to lower a quota limit below the current usage. + INVALID_QUOTA_LOWER = 0x223, + // An attempt was made to attach to a device that was already attached to another device. + DEVICE_ALREADY_ATTACHED = 0x224, + // An attempt was made to execute an instruction at an unaligned address and the host system does not support unaligned instruction references. + INSTRUCTION_MISALIGNMENT = 0x225, + // Profiling not started. + PROFILING_NOT_STARTED = 0x226, + // Profiling not stopped. + PROFILING_NOT_STOPPED = 0x227, + // The passed ACL did not contain the minimum required information. + COULD_NOT_INTERPRET = 0x228, + // The number of active profiling objects is at the maximum and no more may be started. + PROFILING_AT_LIMIT = 0x229, + // Used to indicate that an operation cannot continue without blocking for I/O. + CANT_WAIT = 0x22A, + // Indicates that a thread attempted to terminate itself by default (called NtTerminateThread with NULL) and it was the last thread in the current process. + CANT_TERMINATE_SELF = 0x22B, + // If an MM error is returned which is not defined in the standard FsRtl filter, it is converted to one of the following errors which is guaranteed to be in the filter. In this case information is lost, however, the filter correctly handles the exception. + UNEXPECTED_MM_CREATE_ERR = 0x22C, + // If an MM error is returned which is not defined in the standard FsRtl filter, it is converted to one of the following errors which is guaranteed to be in the filter. In this case information is lost, however, the filter correctly handles the exception. + UNEXPECTED_MM_MAP_ERROR = 0x22D, + // If an MM error is returned which is not defined in the standard FsRtl filter, it is converted to one of the following errors which is guaranteed to be in the filter. In this case information is lost, however, the filter correctly handles the exception. + UNEXPECTED_MM_EXTEND_ERR = 0x22E, + // A malformed function table was encountered during an unwind operation. + BAD_FUNCTION_TABLE = 0x22F, + // Indicates that an attempt was made to assign protection to a file system file or directory and one of the SIDs in the security descriptor could not be translated into a GUID that could be stored by the file system. This causes the protection attempt to fail, which may cause a file creation attempt to fail. + NO_GUID_TRANSLATION = 0x230, + // Indicates that an attempt was made to grow an LDT by setting its size, or that the size was not an even number of selectors. + INVALID_LDT_SIZE = 0x231, + // Indicates that the starting value for the LDT information was not an integral multiple of the selector size. + INVALID_LDT_OFFSET = 0x233, + // Indicates that the user supplied an invalid descriptor when trying to set up Ldt descriptors. + INVALID_LDT_DESCRIPTOR = 0x234, + // Indicates a process has too many threads to perform the requested action. For example, assignment of a primary token may only be performed when a process has zero or one threads. + TOO_MANY_THREADS = 0x235, + // An attempt was made to operate on a thread within a specific process, but the thread specified is not in the process specified. + THREAD_NOT_IN_PROCESS = 0x236, + // Page file quota was exceeded. + PAGEFILE_QUOTA_EXCEEDED = 0x237, + // The Netlogon service cannot start because another Netlogon service running in the domain conflicts with the specified role. + LOGON_SERVER_CONFLICT = 0x238, + // The SAM database on a Windows Server is significantly out of synchronization with the copy on the Domain Controller. A complete synchronization is required. + SYNCHRONIZATION_REQUIRED = 0x239, + // The NtCreateFile API failed. This error should never be returned to an application, it is a place holder for the Windows Lan Manager Redirector to use in its internal error mapping routines. + NET_OPEN_FAILED = 0x23A, + // {Privilege Failed} The I/O permissions for the process could not be changed. + IO_PRIVILEGE_FAILED = 0x23B, + // {Application Exit by CTRL+C} The application terminated as a result of a CTRL+C. + CONTROL_C_EXIT = 0x23C, + // {Missing System File} The required system file %hs is bad or missing. + MISSING_SYSTEMFILE = 0x23D, + // {Application Error} The exception %s (0x%08lx) occurred in the application at location 0x%08lx. + UNHANDLED_EXCEPTION = 0x23E, + // {Application Error} The application was unable to start correctly (0x%lx). Click OK to close the application. + APP_INIT_FAILURE = 0x23F, + // {Unable to Create Paging File} The creation of the paging file %hs failed (%lx). The requested size was %ld. + PAGEFILE_CREATE_FAILED = 0x240, + // Windows cannot verify the digital signature for this file. A recent hardware or software change might have installed a file that is signed incorrectly or damaged, or that might be malicious software from an unknown source. + INVALID_IMAGE_HASH = 0x241, + // {No Paging File Specified} No paging file was specified in the system configuration. + NO_PAGEFILE = 0x242, + // {EXCEPTION} A real-mode application issued a floating-point instruction and floating-point hardware is not present. + ILLEGAL_FLOAT_CONTEXT = 0x243, + // An event pair synchronization operation was performed using the thread specific client/server event pair object, but no event pair object was associated with the thread. + NO_EVENT_PAIR = 0x244, + // A Windows Server has an incorrect configuration. + DOMAIN_CTRLR_CONFIG_ERROR = 0x245, + // An illegal character was encountered. For a multi-byte character set this includes a lead byte without a succeeding trail byte. For the Unicode character set this includes the characters 0xFFFF and 0xFFFE. + ILLEGAL_CHARACTER = 0x246, + // The Unicode character is not defined in the Unicode character set installed on the system. + UNDEFINED_CHARACTER = 0x247, + // The paging file cannot be created on a floppy diskette. + FLOPPY_VOLUME = 0x248, + // The system BIOS failed to connect a system interrupt to the device or bus for which the device is connected. + BIOS_FAILED_TO_CONNECT_INTERRUPT = 0x249, + // This operation is only allowed for the Primary Domain Controller of the domain. + BACKUP_CONTROLLER = 0x24A, + // An attempt was made to acquire a mutant such that its maximum count would have been exceeded. + MUTANT_LIMIT_EXCEEDED = 0x24B, + // A volume has been accessed for which a file system driver is required that has not yet been loaded. + FS_DRIVER_REQUIRED = 0x24C, + // {Registry File Failure} The registry cannot load the hive (file): %hs or its log or alternate. It is corrupt, absent, or not writable. + CANNOT_LOAD_REGISTRY_FILE = 0x24D, + // {Unexpected Failure in DebugActiveProcess} An unexpected failure occurred while processing a DebugActiveProcess API request. You may choose OK to terminate the process, or Cancel to ignore the error. + DEBUG_ATTACH_FAILED = 0x24E, + // {Fatal System Error} The %hs system process terminated unexpectedly with a status of 0x%08x (0x%08x 0x%08x). The system has been shut down. + SYSTEM_PROCESS_TERMINATED = 0x24F, + // {Data Not Accepted} The TDI client could not handle the data received during an indication. + DATA_NOT_ACCEPTED = 0x250, + // NTVDM encountered a hard error. + VDM_HARD_ERROR = 0x251, + // {Cancel Timeout} The driver %hs failed to complete a cancelled I/O request in the allotted time. + DRIVER_CANCEL_TIMEOUT = 0x252, + // {Reply Message Mismatch} An attempt was made to reply to an LPC message, but the thread specified by the client ID in the message was not waiting on that message. + REPLY_MESSAGE_MISMATCH = 0x253, + // {Delayed Write Failed} Windows was unable to save all the data for the file %hs. The data has been lost. This error may be caused by a failure of your computer hardware or network connection. Please try to save this file elsewhere. + LOST_WRITEBEHIND_DATA = 0x254, + // The parameter(s) passed to the server in the client/server shared memory window were invalid. Too much data may have been put in the shared memory window. + CLIENT_SERVER_PARAMETERS_INVALID = 0x255, + // The stream is not a tiny stream. + NOT_TINY_STREAM = 0x256, + // The request must be handled by the stack overflow code. + STACK_OVERFLOW_READ = 0x257, + // Internal OFS status codes indicating how an allocation operation is handled. Either it is retried after the containing onode is moved or the extent stream is converted to a large stream. + CONVERT_TO_LARGE = 0x258, + // The attempt to find the object found an object matching by ID on the volume but it is out of the scope of the handle used for the operation. + FOUND_OUT_OF_SCOPE = 0x259, + // The bucket array must be grown. Retry transaction after doing so. + ALLOCATE_BUCKET = 0x25A, + // The user/kernel marshalling buffer has overflowed. + MARSHALL_OVERFLOW = 0x25B, + // The supplied variant structure contains invalid data. + INVALID_VARIANT = 0x25C, + // The specified buffer contains ill-formed data. + BAD_COMPRESSION_BUFFER = 0x25D, + // {Audit Failed} An attempt to generate a security audit failed. + AUDIT_FAILED = 0x25E, + // The timer resolution was not previously set by the current process. + TIMER_RESOLUTION_NOT_SET = 0x25F, + // There is insufficient account information to log you on. + INSUFFICIENT_LOGON_INFO = 0x260, + // {Invalid DLL Entrypoint} The dynamic link library %hs is not written correctly. The stack pointer has been left in an inconsistent state. The entrypoint should be declared as WINAPI or STDCALL. Select YES to fail the DLL load. Select NO to continue execution. Selecting NO may cause the application to operate incorrectly. + BAD_DLL_ENTRYPOINT = 0x261, + // {Invalid Service Callback Entrypoint} The %hs service is not written correctly. The stack pointer has been left in an inconsistent state. The callback entrypoint should be declared as WINAPI or STDCALL. Selecting OK will cause the service to continue operation. However, the service process may operate incorrectly. + BAD_SERVICE_ENTRYPOINT = 0x262, + // There is an IP address conflict with another system on the network. + IP_ADDRESS_CONFLICT1 = 0x263, + // There is an IP address conflict with another system on the network. + IP_ADDRESS_CONFLICT2 = 0x264, + // {Low On Registry Space} The system has reached the maximum size allowed for the system part of the registry. Additional storage requests will be ignored. + REGISTRY_QUOTA_LIMIT = 0x265, + // A callback return system service cannot be executed when no callback is active. + NO_CALLBACK_ACTIVE = 0x266, + // The password provided is too short to meet the policy of your user account. Please choose a longer password. + PWD_TOO_SHORT = 0x267, + // The policy of your user account does not allow you to change passwords too frequently. This is done to prevent users from changing back to a familiar, but potentially discovered, password. If you feel your password has been compromised then please contact your administrator immediately to have a new one assigned. + PWD_TOO_RECENT = 0x268, + // You have attempted to change your password to one that you have used in the past. The policy of your user account does not allow this. Please select a password that you have not previously used. + PWD_HISTORY_CONFLICT = 0x269, + // The specified compression format is unsupported. + UNSUPPORTED_COMPRESSION = 0x26A, + // The specified hardware profile configuration is invalid. + INVALID_HW_PROFILE = 0x26B, + // The specified Plug and Play registry device path is invalid. + INVALID_PLUGPLAY_DEVICE_PATH = 0x26C, + // The specified quota list is internally inconsistent with its descriptor. + QUOTA_LIST_INCONSISTENT = 0x26D, + // {Windows Evaluation Notification} The evaluation period for this installation of Windows has expired. This system will shutdown in 1 hour. To restore access to this installation of Windows, please upgrade this installation using a licensed distribution of this product. + EVALUATION_EXPIRATION = 0x26E, + // {Illegal System DLL Relocation} The system DLL %hs was relocated in memory. The application will not run properly. The relocation occurred because the DLL %hs occupied an address range reserved for Windows system DLLs. The vendor supplying the DLL should be contacted for a new DLL. + ILLEGAL_DLL_RELOCATION = 0x26F, + // {DLL Initialization Failed} The application failed to initialize because the window station is shutting down. + DLL_INIT_FAILED_LOGOFF = 0x270, + // The validation process needs to continue on to the next step. + VALIDATE_CONTINUE = 0x271, + // There are no more matches for the current index enumeration. + NO_MORE_MATCHES = 0x272, + // The range could not be added to the range list because of a conflict. + RANGE_LIST_CONFLICT = 0x273, + // The server process is running under a SID different than that required by client. + SERVER_SID_MISMATCH = 0x274, + // A group marked use for deny only cannot be enabled. + CANT_ENABLE_DENY_ONLY = 0x275, + // {EXCEPTION} Multiple floating point faults. + FLOAT_MULTIPLE_FAULTS = 0x276, + // {EXCEPTION} Multiple floating point traps. + FLOAT_MULTIPLE_TRAPS = 0x277, + // The requested interface is not supported. + NOINTERFACE = 0x278, + // {System Standby Failed} The driver %hs does not support standby mode. Updating this driver may allow the system to go to standby mode. + DRIVER_FAILED_SLEEP = 0x279, + // The system file %1 has become corrupt and has been replaced. + CORRUPT_SYSTEM_FILE = 0x27A, + // {Virtual Memory Minimum Too Low} Your system is low on virtual memory. Windows is increasing the size of your virtual memory paging file. During this process, memory requests for some applications may be denied. For more information, see Help. + COMMITMENT_MINIMUM = 0x27B, + // A device was removed so enumeration must be restarted. + PNP_RESTART_ENUMERATION = 0x27C, + // {Fatal System Error} The system image %s is not properly signed. The file has been replaced with the signed file. The system has been shut down. + SYSTEM_IMAGE_BAD_SIGNATURE = 0x27D, + // Device will not start without a reboot. + PNP_REBOOT_REQUIRED = 0x27E, + // There is not enough power to complete the requested operation. + INSUFFICIENT_POWER = 0x27F, + // MULTIPLE_FAULT_VIOLATION = , = 0x281, + MULTIPLE_FAULT_VIOLATION = 0x280, // The system is in the process of shutting down. + // An attempt to remove a processes DebugPort was made, but a port was not already associated with the process. + PORT_NOT_SET = 0x282, + // This version of Windows is not compatible with the behavior version of directory forest, domain or domain controller. + DS_VERSION_CHECK_FAILURE = 0x283, + // The specified range could not be found in the range list. + RANGE_NOT_FOUND = 0x284, + // The driver was not loaded because the system is booting into safe mode. + NOT_SAFE_MODE_DRIVER = 0x286, + // The driver was not loaded because it failed its initialization call. + FAILED_DRIVER_ENTRY = 0x287, + // The "%hs" encountered an error while applying power or reading the device configuration. This may be caused by a failure of your hardware or by a poor connection. + DEVICE_ENUMERATION_ERROR = 0x288, + // The create operation failed because the name contained at least one mount point which resolves to a volume to which the specified device object is not attached. + MOUNT_POINT_NOT_RESOLVED = 0x289, + // The device object parameter is either not a valid device object or is not attached to the volume specified by the file name. + INVALID_DEVICE_OBJECT_PARAMETER = 0x28A, + // A Machine Check Error has occurred. Please check the system eventlog for additional information. + MCA_OCCURED = 0x28B, + // There was error [%2] processing the driver database. + DRIVER_DATABASE_ERROR = 0x28C, + // System hive size has exceeded its limit. + SYSTEM_HIVE_TOO_LARGE = 0x28D, + // The driver could not be loaded because a previous version of the driver is still in memory. + DRIVER_FAILED_PRIOR_UNLOAD = 0x28E, + // {Volume Shadow Copy Service} Please wait while the Volume Shadow Copy Service prepares volume %hs for hibernation. + VOLSNAP_PREPARE_HIBERNATE = 0x28F, + // The system has failed to hibernate (The error code is %hs). Hibernation will be disabled until the system is restarted. + HIBERNATION_FAILURE = 0x290, + // The password provided is too long to meet the policy of your user account. Please choose a shorter password. + PWD_TOO_LONG = 0x291, + // The requested operation could not be completed due to a file system limitation. + FILE_SYSTEM_LIMITATION = 0x299, + // An assertion failure has occurred. + ASSERTION_FAILURE = 0x29C, + // An error occurred in the ACPI subsystem. + ACPI_ERROR = 0x29D, + // WOW Assertion Error. + WOW_ASSERTION = 0x29E, + // A device is missing in the system BIOS MPS table. This device will not be used. Please contact your system vendor for system BIOS update. + PNP_BAD_MPS_TABLE = 0x29F, + // A translator failed to translate resources. + PNP_TRANSLATION_FAILED = 0x2A0, + // A IRQ translator failed to translate resources. + PNP_IRQ_TRANSLATION_FAILED = 0x2A1, + // Driver %2 returned invalid ID for a child device (%3). + PNP_INVALID_ID = 0x2A2, + // {Kernel Debugger Awakened} the system debugger was awakened by an interrupt. + WAKE_SYSTEM_DEBUGGER = 0x2A3, + // {Handles Closed} Handles to objects have been automatically closed as a result of the requested operation. + HANDLES_CLOSED = 0x2A4, + // {Too Much Information} The specified access control list (ACL) contained more information than was expected. + EXTRANEOUS_INFORMATION = 0x2A5, + // This warning level status indicates that the transaction state already exists for the registry sub-tree, but that a transaction commit was previously aborted. The commit has NOT been completed, but has not been rolled back either (so it may still be committed if desired). + RXACT_COMMIT_NECESSARY = 0x2A6, + // {Media Changed} The media may have changed. + MEDIA_CHECK = 0x2A7, + // {GUID Substitution} During the translation of a global identifier (GUID) to a Windows security ID SID, no administratively-defined GUID prefix was found. A substitute prefix was used, which will not compromise system security. However, this may provide a more restrictive access than intended. + GUID_SUBSTITUTION_MADE = 0x2A8, + // The create operation stopped after reaching a symbolic link. + STOPPED_ON_SYMLINK = 0x2A9, + // A long jump has been executed. + LONGJUMP = 0x2AA, + // The Plug and Play query operation was not successful. + PLUGPLAY_QUERY_VETOED = 0x2AB, + // A frame consolidation has been executed. + UNWIND_CONSOLIDATE = 0x2AC, + // {Registry Hive Recovered} Registry hive (file): %hs was corrupted and it has been recovered. Some data might have been lost. + REGISTRY_HIVE_RECOVERED = 0x2AD, + // The application is attempting to run executable code from the module %hs. This may be insecure. An alternative, %hs, is available. Should the application use the secure module %hs? + DLL_MIGHT_BE_INSECURE = 0x2AE, + // The application is loading executable code from the module %hs. This is secure, but may be incompatible with previous releases of the operating system. An alternative, %hs, is available. Should the application use the secure module %hs? + DLL_MIGHT_BE_INCOMPATIBLE = 0x2AF, + // Debugger did not handle the exception. + DBG_EXCEPTION_NOT_HANDLED = 0x2B0, + // Debugger will reply later. + DBG_REPLY_LATER = 0x2B1, + // Debugger cannot provide handle. + DBG_UNABLE_TO_PROVIDE_HANDLE = 0x2B2, + // Debugger terminated thread. + DBG_TERMINATE_THREAD = 0x2B3, + // Debugger terminated process. + DBG_TERMINATE_PROCESS = 0x2B4, + // Debugger got control C. + DBG_CONTROL_C = 0x2B5, + // Debugger printed exception on control C. + DBG_PRINTEXCEPTION_C = 0x2B6, + // Debugger received RIP exception. + DBG_RIPEXCEPTION = 0x2B7, + // Debugger received control break. + DBG_CONTROL_BREAK = 0x2B8, + // Debugger command communication exception. + DBG_COMMAND_EXCEPTION = 0x2B9, + // {Object Exists} An attempt was made to create an object and the object name already existed. + OBJECT_NAME_EXISTS = 0x2BA, + // {Thread Suspended} A thread termination occurred while the thread was suspended. The thread was resumed, and termination proceeded. + THREAD_WAS_SUSPENDED = 0x2BB, + // {Image Relocated} An image file could not be mapped at the address specified in the image file. Local fixups must be performed on this image. + IMAGE_NOT_AT_BASE = 0x2BC, + // This informational level status indicates that a specified registry sub-tree transaction state did not yet exist and had to be created. + RXACT_STATE_CREATED = 0x2BD, + // {Segment Load} A virtual DOS machine (VDM) is loading, unloading, or moving an MS-DOS or Win16 program segment image. An exception is raised so a debugger can load, unload or track symbols and breakpoints within these 16-bit segments. + SEGMENT_NOTIFICATION = 0x2BE, + // {Invalid Current Directory} The process cannot switch to the startup current directory %hs. Select OK to set current directory to %hs, or select CANCEL to exit. + BAD_CURRENT_DIRECTORY = 0x2BF, + // {Redundant Read} To satisfy a read request, the NT fault-tolerant file system successfully read the requested data from a redundant copy. This was done because the file system encountered a failure on a member of the fault-tolerant volume, but was unable to reassign the failing area of the device. + FT_READ_RECOVERY_FROM_BACKUP = 0x2C0, + // {Redundant Write} To satisfy a write request, the NT fault-tolerant file system successfully wrote a redundant copy of the information. This was done because the file system encountered a failure on a member of the fault-tolerant volume, but was not able to reassign the failing area of the device. + FT_WRITE_RECOVERY = 0x2C1, + // {Machine Type Mismatch} The image file %hs is valid, but is for a machine type other than the current machine. Select OK to continue, or CANCEL to fail the DLL load. + IMAGE_MACHINE_TYPE_MISMATCH = 0x2C2, + // {Partial Data Received} The network transport returned partial data to its client. The remaining data will be sent later. + RECEIVE_PARTIAL = 0x2C3, + // {Expedited Data Received} The network transport returned data to its client that was marked as expedited by the remote system. + RECEIVE_EXPEDITED = 0x2C4, + // {Partial Expedited Data Received} The network transport returned partial data to its client and this data was marked as expedited by the remote system. The remaining data will be sent later. + RECEIVE_PARTIAL_EXPEDITED = 0x2C5, + // {TDI Event Done} The TDI indication has completed successfully. + EVENT_DONE = 0x2C6, + // {TDI Event Pending} The TDI indication has entered the pending state. + EVENT_PENDING = 0x2C7, + // Checking file system on %wZ. + CHECKING_FILE_SYSTEM = 0x2C8, + // {Fatal Application Exit} %hs. + FATAL_APP_EXIT = 0x2C9, + // The specified registry key is referenced by a predefined handle. + PREDEFINED_HANDLE = 0x2CA, + // {Page Unlocked} The page protection of a locked page was changed to 'No Access' and the page was unlocked from memory and from the process. + WAS_UNLOCKED = 0x2CB, + // %hs + SERVICE_NOTIFICATION = 0x2CC, + // {Page Locked} One of the pages to lock was already locked. + WAS_LOCKED = 0x2CD, + // Application popup: %1 : %2 + LOG_HARD_ERROR = 0x2CE, + // ALREADY_WIN32 = , = 0x2D0, + ALREADY_WIN32 = 0x2CF, // {Machine Type Mismatch} The image file %hs is valid, but is for a machine type other than the current machine. + // A yield execution was performed and no thread was available to run. + NO_YIELD_PERFORMED = 0x2D1, + // The resumable flag to a timer API was ignored. + TIMER_RESUME_IGNORED = 0x2D2, + // The arbiter has deferred arbitration of these resources to its parent. + ARBITRATION_UNHANDLED = 0x2D3, + // The inserted CardBus device cannot be started because of a configuration error on "%hs". + CARDBUS_NOT_SUPPORTED = 0x2D4, + // The CPUs in this multiprocessor system are not all the same revision level. To use all processors the operating system restricts itself to the features of the least capable processor in the system. Should problems occur with this system, contact the CPU manufacturer to see if this mix of processors is supported. + MP_PROCESSOR_MISMATCH = 0x2D5, + // The system was put into hibernation. + HIBERNATED = 0x2D6, + // The system was resumed from hibernation. + RESUME_HIBERNATION = 0x2D7, + // Windows has detected that the system firmware (BIOS) was updated [previous firmware date = %2, current firmware date %3]. + FIRMWARE_UPDATED = 0x2D8, + // A device driver is leaking locked I/O pages causing system degradation. The system has automatically enabled tracking code in order to try and catch the culprit. + DRIVERS_LEAKING_LOCKED_PAGES = 0x2D9, + // The system has awoken. + WAKE_SYSTEM = 0x2DA, + // WAIT_1 = , = 0x2DC, + WAIT_1 = 0x2DB, // WAIT_2 = , = 0x2DD, // WAIT_3 = , = 0x2DE, // WAIT_63 = , = 0x2DF, // ABANDONED_WAIT_0 = , = 0x2E0, // ABANDONED_WAIT_63 = , = 0x2E1, // USER_APC = , = 0x2E2, // KERNEL_APC = , = 0x2E3, // ALERTED = , = 0x2E4, // The requested operation requires elevation. + // A reparse should be performed by the Object Manager since the name of the file resulted in a symbolic link. + REPARSE = 0x2E5, + // An open/create operation completed while an oplock break is underway. + OPLOCK_BREAK_IN_PROGRESS = 0x2E6, + // A new volume has been mounted by a file system. + VOLUME_MOUNTED = 0x2E7, + // This success level status indicates that the transaction state already exists for the registry sub-tree, but that a transaction commit was previously aborted. The commit has now been completed. + RXACT_COMMITTED = 0x2E8, + // This indicates that a notify change request has been completed due to closing the handle which made the notify change request. + NOTIFY_CLEANUP = 0x2E9, + // {Connect Failure on Primary Transport} An attempt was made to connect to the remote server %hs on the primary transport, but the connection failed. The computer WAS able to connect on a secondary transport. + PRIMARY_TRANSPORT_CONNECT_FAILED = 0x2EA, + // Page fault was a transition fault. + PAGE_FAULT_TRANSITION = 0x2EB, + // Page fault was a demand zero fault. + PAGE_FAULT_DEMAND_ZERO = 0x2EC, + // Page fault was a demand zero fault. + PAGE_FAULT_COPY_ON_WRITE = 0x2ED, + // Page fault was a demand zero fault. + PAGE_FAULT_GUARD_PAGE = 0x2EE, + // Page fault was satisfied by reading from a secondary storage device. + PAGE_FAULT_PAGING_FILE = 0x2EF, + // Cached page was locked during operation. + CACHE_PAGE_LOCKED = 0x2F0, + // Crash dump exists in paging file. + CRASH_DUMP = 0x2F1, + // Specified buffer contains all zeros. + BUFFER_ALL_ZEROS = 0x2F2, + // A reparse should be performed by the Object Manager since the name of the file resulted in a symbolic link. + REPARSE_OBJECT = 0x2F3, + // The device has succeeded a query-stop and its resource requirements have changed. + RESOURCE_REQUIREMENTS_CHANGED = 0x2F4, + // The translator has translated these resources into the global space and no further translations should be performed. + TRANSLATION_COMPLETE = 0x2F5, + // A process being terminated has no threads to terminate. + NOTHING_TO_TERMINATE = 0x2F6, + // The specified process is not part of a job. + PROCESS_NOT_IN_JOB = 0x2F7, + // The specified process is part of a job. + PROCESS_IN_JOB = 0x2F8, + // {Volume Shadow Copy Service} The system is now ready for hibernation. + VOLSNAP_HIBERNATE_READY = 0x2F9, + // A file system or file system filter driver has successfully completed an FsFilter operation. + FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x2FA, + // The specified interrupt vector was already connected. + INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x2FB, + // The specified interrupt vector is still connected. + INTERRUPT_STILL_CONNECTED = 0x2FC, + // An operation is blocked waiting for an oplock. + WAIT_FOR_OPLOCK = 0x2FD, + // Debugger handled exception. + DBG_EXCEPTION_HANDLED = 0x2FE, + // Debugger continued. + DBG_CONTINUE = 0x2FF, + // An exception occurred in a user mode callback and the kernel callback frame should be removed. + CALLBACK_POP_STACK = 0x300, + // Compression is disabled for this volume. + COMPRESSION_DISABLED = 0x301, + // The data provider cannot fetch backwards through a result set. + CANTFETCHBACKWARDS = 0x302, + // The data provider cannot scroll backwards through a result set. + CANTSCROLLBACKWARDS = 0x303, + // The data provider requires that previously fetched data is released before asking for more data. + ROWSNOTRELEASED = 0x304, + // The data provider was not able to interpret the flags set for a column binding in an accessor. + BAD_ACCESSOR_FLAGS = 0x305, + // One or more errors occurred while processing the request. + ERRORS_ENCOUNTERED = 0x306, + // The implementation is not capable of performing the request. + NOT_CAPABLE = 0x307, + // The client of a component requested an operation which is not valid given the state of the component instance. + REQUEST_OUT_OF_SEQUENCE = 0x308, + // A version number could not be parsed. + VERSION_PARSE_ERROR = 0x309, + // The iterator's start position is invalid. + BADSTARTPOSITION = 0x30A, + // The hardware has reported an uncorrectable memory error. + MEMORY_HARDWARE = 0x30B, + // The attempted operation required self healing to be enabled. + DISK_REPAIR_DISABLED = 0x30C, + // The Desktop heap encountered an error while allocating session memory. There is more information in the system event log. + INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 0x30D, + // The system power state is transitioning from %2 to %3. + SYSTEM_POWERSTATE_TRANSITION = 0x30E, + // The system power state is transitioning from %2 to %3 but could enter %4. + SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x30F, + // A thread is getting dispatched with MCA EXCEPTION because of MCA. + MCA_EXCEPTION = 0x310, + // Access to %1 is monitored by policy rule %2. + ACCESS_AUDIT_BY_POLICY = 0x311, + // Access to %1 has been restricted by your Administrator by policy rule %2. + ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 0x312, + // A valid hibernation file has been invalidated and should be abandoned. + ABANDON_HIBERFILE = 0x313, + // {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost. This error may be caused by network connectivity issues. Please try to save this file elsewhere. + LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0x314, + // {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost. This error was returned by the server on which the file exists. Please try to save this file elsewhere. + LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0x315, + // {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost. This error may be caused if the device has been removed or the media is write-protected. + LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0x316, + // The resources required for this device conflict with the MCFG table. + BAD_MCFG_TABLE = 0x317, + // The volume repair could not be performed while it is online. Please schedule to take the volume offline so that it can be repaired. + DISK_REPAIR_REDIRECTED = 0x318, + // The volume repair was not successful. + DISK_REPAIR_UNSUCCESSFUL = 0x319, + // One of the volume corruption logs is full. Further corruptions that may be detected won't be logged. + CORRUPT_LOG_OVERFULL = 0x31A, + // One of the volume corruption logs is internally corrupted and needs to be recreated. The volume may contain undetected corruptions and must be scanned. + CORRUPT_LOG_CORRUPTED = 0x31B, + // One of the volume corruption logs is unavailable for being operated on. + CORRUPT_LOG_UNAVAILABLE = 0x31C, + // One of the volume corruption logs was deleted while still having corruption records in them. The volume contains detected corruptions and must be scanned. + CORRUPT_LOG_DELETED_FULL = 0x31D, + // One of the volume corruption logs was cleared by chkdsk and no longer contains real corruptions. + CORRUPT_LOG_CLEARED = 0x31E, + // Orphaned files exist on the volume but could not be recovered because no more new names could be created in the recovery directory. Files must be moved from the recovery directory. + ORPHAN_NAME_EXHAUSTED = 0x31F, + // The oplock that was associated with this handle is now associated with a different handle. + OPLOCK_SWITCHED_TO_NEW_HANDLE = 0x320, + // An oplock of the requested level cannot be granted. An oplock of a lower level may be available. + CANNOT_GRANT_REQUESTED_OPLOCK = 0x321, + // The operation did not complete successfully because it would cause an oplock to be broken. The caller has requested that existing oplocks not be broken. + CANNOT_BREAK_OPLOCK = 0x322, + // The handle with which this oplock was associated has been closed. The oplock is now broken. + OPLOCK_HANDLE_CLOSED = 0x323, + // The specified access control entry (ACE) does not contain a condition. + NO_ACE_CONDITION = 0x324, + // The specified access control entry (ACE) contains an invalid condition. + INVALID_ACE_CONDITION = 0x325, + // Access to the specified file handle has been revoked. + FILE_HANDLE_REVOKED = 0x326, + // An image file was mapped at a different address from the one specified in the image file but fixups will still be automatically performed on the image. + IMAGE_AT_DIFFERENT_BASE = 0x327, + // Access to the extended attribute was denied. + EA_ACCESS_DENIED = 0x3E2, + // The I/O operation has been aborted because of either a thread exit or an application request. + OPERATION_ABORTED = 0x3E3, + // Overlapped I/O event is not in a signaled state. + IO_INCOMPLETE = 0x3E4, + // Overlapped I/O operation is in progress. + IO_PENDING = 0x3E5, + // Invalid access to memory location. + NOACCESS = 0x3E6, + // Error performing inpage operation. + SWAPERROR = 0x3E7, + + // Recursion too deep; the stack overflowed. + STACK_OVERFLOW = 0x3E9, + // The window cannot act on the sent message. + INVALID_MESSAGE = 0x3EA, + // Cannot complete this function. + CAN_NOT_COMPLETE = 0x3EB, + // Invalid flags. + INVALID_FLAGS = 0x3EC, + // The volume does not contain a recognized file system. Please make sure that all required file system drivers are loaded and that the volume is not corrupted. + UNRECOGNIZED_VOLUME = 0x3ED, + // The volume for a file has been externally altered so that the opened file is no longer valid. + FILE_INVALID = 0x3EE, + // The requested operation cannot be performed in full-screen mode. + FULLSCREEN_MODE = 0x3EF, + // An attempt was made to reference a token that does not exist. + NO_TOKEN = 0x3F0, + // The configuration registry database is corrupt. + BADDB = 0x3F1, + // The configuration registry key is invalid. + BADKEY = 0x3F2, + // The configuration registry key could not be opened. + CANTOPEN = 0x3F3, + // The configuration registry key could not be read. + CANTREAD = 0x3F4, + // The configuration registry key could not be written. + CANTWRITE = 0x3F5, + // One of the files in the registry database had to be recovered by use of a log or alternate copy. The recovery was successful. + REGISTRY_RECOVERED = 0x3F6, + // The registry is corrupted. The structure of one of the files containing registry data is corrupted, or the system's memory image of the file is corrupted, or the file could not be recovered because the alternate copy or log was absent or corrupted. + REGISTRY_CORRUPT = 0x3F7, + // An I/O operation initiated by the registry failed unrecoverably. The registry could not read in, or write out, or flush, one of the files that contain the system's image of the registry. + REGISTRY_IO_FAILED = 0x3F8, + // The system has attempted to load or restore a file into the registry, but the specified file is not in a registry file format. + NOT_REGISTRY_FILE = 0x3F9, + // Illegal operation attempted on a registry key that has been marked for deletion. + KEY_DELETED = 0x3FA, + // System could not allocate the required space in a registry log. + NO_LOG_SPACE = 0x3FB, + // Cannot create a symbolic link in a registry key that already has subkeys or values. + KEY_HAS_CHILDREN = 0x3FC, + // Cannot create a stable subkey under a volatile parent key. + CHILD_MUST_BE_VOLATILE = 0x3FD, + // A notify change request is being completed and the information is not being returned in the caller's buffer. The caller now needs to enumerate the files to find the changes. + NOTIFY_ENUM_DIR = 0x3FE, + // A stop control has been sent to a service that other running services are dependent on. + DEPENDENT_SERVICES_RUNNING = 0x41B, + // The requested control is not valid for this service. + INVALID_SERVICE_CONTROL = 0x41C, + // The service did not respond to the start or control request in a timely fashion. + SERVICE_REQUEST_TIMEOUT = 0x41D, + // A thread could not be created for the service. + SERVICE_NO_THREAD = 0x41E, + // The service database is locked. + SERVICE_DATABASE_LOCKED = 0x41F, + // An instance of the service is already running. + SERVICE_ALREADY_RUNNING = 0x420, + // The account name is invalid or does not exist, or the password is invalid for the account name specified. + INVALID_SERVICE_ACCOUNT = 0x421, + // The service cannot be started, either because it is disabled or because it has no enabled devices associated with it. + SERVICE_DISABLED = 0x422, + // Circular service dependency was specified. + CIRCULAR_DEPENDENCY = 0x423, + // The specified service does not exist as an installed service. + SERVICE_DOES_NOT_EXIST = 0x424, + // The service cannot accept control messages at this time. + SERVICE_CANNOT_ACCEPT_CTRL = 0x425, + // The service has not been started. + SERVICE_NOT_ACTIVE = 0x426, + // The service process could not connect to the service controller. + FAILED_SERVICE_CONTROLLER_CONNECT = 0x427, + // An exception occurred in the service when handling the control request. + EXCEPTION_IN_SERVICE = 0x428, + // The database specified does not exist. + DATABASE_DOES_NOT_EXIST = 0x429, + // The service has returned a service-specific error code. + SERVICE_SPECIFIC_ERROR = 0x42A, + // The process terminated unexpectedly. + PROCESS_ABORTED = 0x42B, + // The dependency service or group failed to start. + SERVICE_DEPENDENCY_FAIL = 0x42C, + // The service did not start due to a logon failure. + SERVICE_LOGON_FAILED = 0x42D, + // After starting, the service hung in a start-pending state. + SERVICE_START_HANG = 0x42E, + // The specified service database lock is invalid. + INVALID_SERVICE_LOCK = 0x42F, + // The specified service has been marked for deletion. + SERVICE_MARKED_FOR_DELETE = 0x430, + // The specified service already exists. + SERVICE_EXISTS = 0x431, + // The system is currently running with the last-known-good configuration. + ALREADY_RUNNING_LKG = 0x432, + // The dependency service does not exist or has been marked for deletion. + SERVICE_DEPENDENCY_DELETED = 0x433, + // The current boot has already been accepted for use as the last-known-good control set. + BOOT_ALREADY_ACCEPTED = 0x434, + // No attempts to start the service have been made since the last boot. + SERVICE_NEVER_STARTED = 0x435, + // The name is already in use as either a service name or a service display name. + DUPLICATE_SERVICE_NAME = 0x436, + // The account specified for this service is different from the account specified for other services running in the same process. + DIFFERENT_SERVICE_ACCOUNT = 0x437, + // Failure actions can only be set for Win32 services, not for drivers. + CANNOT_DETECT_DRIVER_FAILURE = 0x438, + // This service runs in the same process as the service control manager. Therefore, the service control manager cannot take action if this service's process terminates unexpectedly. + CANNOT_DETECT_PROCESS_ABORT = 0x439, + // No recovery program has been configured for this service. + NO_RECOVERY_PROGRAM = 0x43A, + // The executable program that this service is configured to run in does not implement the service. + SERVICE_NOT_IN_EXE = 0x43B, + // This service cannot be started in Safe Mode. + NOT_SAFEBOOT_SERVICE = 0x43C, + // The physical end of the tape has been reached. + END_OF_MEDIA = 0x44C, + // A tape access reached a filemark. + FILEMARK_DETECTED = 0x44D, + // The beginning of the tape or a partition was encountered. + BEGINNING_OF_MEDIA = 0x44E, + // A tape access reached the end of a set of files. + SETMARK_DETECTED = 0x44F, + // No more data is on the tape. + NO_DATA_DETECTED = 0x450, + // Tape could not be partitioned. + PARTITION_FAILURE = 0x451, + // When accessing a new tape of a multivolume partition, the current block size is incorrect. + INVALID_BLOCK_LENGTH = 0x452, + // Tape partition information could not be found when loading a tape. + DEVICE_NOT_PARTITIONED = 0x453, + // Unable to lock the media eject mechanism. + UNABLE_TO_LOCK_MEDIA = 0x454, + // Unable to unload the media. + UNABLE_TO_UNLOAD_MEDIA = 0x455, + // The media in the drive may have changed. + MEDIA_CHANGED = 0x456, + // The I/O bus was reset. + BUS_RESET = 0x457, + // No media in drive. + NO_MEDIA_IN_DRIVE = 0x458, + // No mapping for the Unicode character exists in the target multi-byte code page. + NO_UNICODE_TRANSLATION = 0x459, + // A dynamic link library (DLL) initialization routine failed. + DLL_INIT_FAILED = 0x45A, + // A system shutdown is in progress. + SHUTDOWN_IN_PROGRESS = 0x45B, + // Unable to abort the system shutdown because no shutdown was in progress. + NO_SHUTDOWN_IN_PROGRESS = 0x45C, + // The request could not be performed because of an I/O device error. + IO_DEVICE = 0x45D, + // No serial device was successfully initialized. The serial driver will unload. + SERIAL_NO_DEVICE = 0x45E, + // Unable to open a device that was sharing an interrupt request (IRQ) with other devices. At least one other device that uses that IRQ was already opened. + IRQ_BUSY = 0x45F, + // A serial I/O operation was completed by another write to the serial port. The IOCTL_SERIAL_XOFF_COUNTER reached zero.) + MORE_WRITES = 0x460, + // A serial I/O operation completed because the timeout period expired. The IOCTL_SERIAL_XOFF_COUNTER did not reach zero.) + COUNTER_TIMEOUT = 0x461, + // No ID address mark was found on the floppy disk. + FLOPPY_ID_MARK_NOT_FOUND = 0x462, + // Mismatch between the floppy disk sector ID field and the floppy disk controller track address. + FLOPPY_WRONG_CYLINDER = 0x463, + // The floppy disk controller reported an error that is not recognized by the floppy disk driver. + FLOPPY_UNKNOWN_ERROR = 0x464, + // The floppy disk controller returned inconsistent results in its registers. + FLOPPY_BAD_REGISTERS = 0x465, + // While accessing the hard disk, a recalibrate operation failed, even after retries. + DISK_RECALIBRATE_FAILED = 0x466, + // While accessing the hard disk, a disk operation failed even after retries. + DISK_OPERATION_FAILED = 0x467, + // While accessing the hard disk, a disk controller reset was needed, but even that failed. + DISK_RESET_FAILED = 0x468, + // Physical end of tape encountered. + EOM_OVERFLOW = 0x469, + // Not enough server storage is available to process this command. + NOT_ENOUGH_SERVER_MEMORY = 0x46A, + // A potential deadlock condition has been detected. + POSSIBLE_DEADLOCK = 0x46B, + // The base address or the file offset specified does not have the proper alignment. + MAPPED_ALIGNMENT = 0x46C, + // An attempt to change the system power state was vetoed by another application or driver. + SET_POWER_STATE_VETOED = 0x474, + // The system BIOS failed an attempt to change the system power state. + SET_POWER_STATE_FAILED = 0x475, + // An attempt was made to create more links on a file than the file system supports. + TOO_MANY_LINKS = 0x476, + // The specified program requires a newer version of Windows. + OLD_WIN_VERSION = 0x47E, + // The specified program is not a Windows or MS-DOS program. + APP_WRONG_OS = 0x47F, + // Cannot start more than one instance of the specified program. + SINGLE_INSTANCE_APP = 0x480, + // The specified program was written for an earlier version of Windows. + RMODE_APP = 0x481, + // One of the library files needed to run this application is damaged. + INVALID_DLL = 0x482, + // No application is associated with the specified file for this operation. + NO_ASSOCIATION = 0x483, + // An error occurred in sending the command to the application. + DDE_FAIL = 0x484, + // One of the library files needed to run this application cannot be found. + DLL_NOT_FOUND = 0x485, + // The current process has used all of its system allowance of handles for Window Manager objects. + NO_MORE_USER_HANDLES = 0x486, + // The message can be used only with synchronous operations. + MESSAGE_SYNC_ONLY = 0x487, + // The indicated source element has no media. + SOURCE_ELEMENT_EMPTY = 0x488, + // The indicated destination element already contains media. + DESTINATION_ELEMENT_FULL = 0x489, + // The indicated element does not exist. + ILLEGAL_ELEMENT_ADDRESS = 0x48A, + // The indicated element is part of a magazine that is not present. + MAGAZINE_NOT_PRESENT = 0x48B, + // The indicated device requires reinitialization due to hardware errors. + DEVICE_REINITIALIZATION_NEEDED = 0x48C, + // The device has indicated that cleaning is required before further operations are attempted. + DEVICE_REQUIRES_CLEANING = 0x48D, + // The device has indicated that its door is open. + DEVICE_DOOR_OPEN = 0x48E, + // The device is not connected. + DEVICE_NOT_CONNECTED = 0x48F, + // Element not found. + NOT_FOUND = 0x490, + // There was no match for the specified key in the index. + NO_MATCH = 0x491, + // The property set specified does not exist on the object. + SET_NOT_FOUND = 0x492, + // The point passed to GetMouseMovePoints is not in the buffer. + POINT_NOT_FOUND = 0x493, + // The tracking (workstation) service is not running. + NO_TRACKING_SERVICE = 0x494, + // The Volume ID could not be found. + NO_VOLUME_ID = 0x495, + // Unable to remove the file to be replaced. + UNABLE_TO_REMOVE_REPLACED = 0x497, + // Unable to move the replacement file to the file to be replaced. The file to be replaced has retained its original name. + UNABLE_TO_MOVE_REPLACEMENT = 0x498, + // Unable to move the replacement file to the file to be replaced. The file to be replaced has been renamed using the backup name. + UNABLE_TO_MOVE_REPLACEMENT_2 = 0x499, + // The volume change journal is being deleted. + JOURNAL_DELETE_IN_PROGRESS = 0x49A, + // The volume change journal is not active. + JOURNAL_NOT_ACTIVE = 0x49B, + // A file was found, but it may not be the correct file. + POTENTIAL_FILE_FOUND = 0x49C, + // The journal entry has been deleted from the journal. + JOURNAL_ENTRY_DELETED = 0x49D, + // A system shutdown has already been scheduled. + SHUTDOWN_IS_SCHEDULED = 0x4A6, + // The system shutdown cannot be initiated because there are other users logged on to the computer. + SHUTDOWN_USERS_LOGGED_ON = 0x4A7, + // The specified device name is invalid. + BAD_DEVICE = 0x4B0, + // The device is not currently connected but it is a remembered connection. + CONNECTION_UNAVAIL = 0x4B1, + // The local device name has a remembered connection to another network resource. + DEVICE_ALREADY_REMEMBERED = 0x4B2, + // The network path was either typed incorrectly, does not exist, or the network provider is not currently available. Please try retyping the path or contact your network administrator. + NO_NET_OR_BAD_PATH = 0x4B3, + // The specified network provider name is invalid. + BAD_PROVIDER = 0x4B4, + // Unable to open the network connection profile. + CANNOT_OPEN_PROFILE = 0x4B5, + // The network connection profile is corrupted. + BAD_PROFILE = 0x4B6, + // Cannot enumerate a noncontainer. + NOT_CONTAINER = 0x4B7, + // An extended error has occurred. + EXTENDED_ERROR = 0x4B8, + // The format of the specified group name is invalid. + INVALID_GROUPNAME = 0x4B9, + // The format of the specified computer name is invalid. + INVALID_COMPUTERNAME = 0x4BA, + // The format of the specified event name is invalid. + INVALID_EVENTNAME = 0x4BB, + // The format of the specified domain name is invalid. + INVALID_DOMAINNAME = 0x4BC, + // The format of the specified service name is invalid. + INVALID_SERVICENAME = 0x4BD, + // The format of the specified network name is invalid. + INVALID_NETNAME = 0x4BE, + // The format of the specified share name is invalid. + INVALID_SHARENAME = 0x4BF, + // The format of the specified password is invalid. + INVALID_PASSWORDNAME = 0x4C0, + // The format of the specified message name is invalid. + INVALID_MESSAGENAME = 0x4C1, + // The format of the specified message destination is invalid. + INVALID_MESSAGEDEST = 0x4C2, + // Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again. + SESSION_CREDENTIAL_CONFLICT = 0x4C3, + // An attempt was made to establish a session to a network server, but there are already too many sessions established to that server. + REMOTE_SESSION_LIMIT_EXCEEDED = 0x4C4, + // The workgroup or domain name is already in use by another computer on the network. + DUP_DOMAINNAME = 0x4C5, + // The network is not present or not started. + NO_NETWORK = 0x4C6, + // The operation was canceled by the user. + CANCELLED = 0x4C7, + // The requested operation cannot be performed on a file with a user-mapped section open. + USER_MAPPED_FILE = 0x4C8, + // The remote computer refused the network connection. + CONNECTION_REFUSED = 0x4C9, + // The network connection was gracefully closed. + GRACEFUL_DISCONNECT = 0x4CA, + // The network transport endpoint already has an address associated with it. + ADDRESS_ALREADY_ASSOCIATED = 0x4CB, + // An address has not yet been associated with the network endpoint. + ADDRESS_NOT_ASSOCIATED = 0x4CC, + // An operation was attempted on a nonexistent network connection. + CONNECTION_INVALID = 0x4CD, + // An invalid operation was attempted on an active network connection. + CONNECTION_ACTIVE = 0x4CE, + // The network location cannot be reached. For information about network troubleshooting, see Windows Help. + NETWORK_UNREACHABLE = 0x4CF, + // The network location cannot be reached. For information about network troubleshooting, see Windows Help. + HOST_UNREACHABLE = 0x4D0, + // The network location cannot be reached. For information about network troubleshooting, see Windows Help. + PROTOCOL_UNREACHABLE = 0x4D1, + // No service is operating at the destination network endpoint on the remote system. + PORT_UNREACHABLE = 0x4D2, + // The request was aborted. + REQUEST_ABORTED = 0x4D3, + // The network connection was aborted by the local system. + CONNECTION_ABORTED = 0x4D4, + // The operation could not be completed. A retry should be performed. + RETRY = 0x4D5, + // A connection to the server could not be made because the limit on the number of concurrent connections for this account has been reached. + CONNECTION_COUNT_LIMIT = 0x4D6, + // Attempting to log in during an unauthorized time of day for this account. + LOGIN_TIME_RESTRICTION = 0x4D7, + // The account is not authorized to log in from this station. + LOGIN_WKSTA_RESTRICTION = 0x4D8, + // The network address could not be used for the operation requested. + INCORRECT_ADDRESS = 0x4D9, + // The service is already registered. + ALREADY_REGISTERED = 0x4DA, + // The specified service does not exist. + SERVICE_NOT_FOUND = 0x4DB, + // The operation being requested was not performed because the user has not been authenticated. + NOT_AUTHENTICATED = 0x4DC, + // The operation being requested was not performed because the user has not logged on to the network. The specified service does not exist. + NOT_LOGGED_ON = 0x4DD, + // Continue with work in progress. + CONTINUE = 0x4DE, + // An attempt was made to perform an initialization operation when initialization has already been completed. + ALREADY_INITIALIZED = 0x4DF, + // No more local devices. + NO_MORE_DEVICES = 0x4E0, + // The specified site does not exist. + NO_SUCH_SITE = 0x4E1, + // A domain controller with the specified name already exists. + DOMAIN_CONTROLLER_EXISTS = 0x4E2, + // This operation is supported only when you are connected to the server. + ONLY_IF_CONNECTED = 0x4E3, + // The group policy framework should call the extension even if there are no changes. + OVERRIDE_NOCHANGES = 0x4E4, + // The specified user does not have a valid profile. + BAD_USER_PROFILE = 0x4E5, + // This operation is not supported on a computer running Windows Server 2003 for Small Business Server. + NOT_SUPPORTED_ON_SBS = 0x4E6, + // The server machine is shutting down. + SERVER_SHUTDOWN_IN_PROGRESS = 0x4E7, + // The remote system is not available. For information about network troubleshooting, see Windows Help. + HOST_DOWN = 0x4E8, + // The security identifier provided is not from an account domain. + NON_ACCOUNT_SID = 0x4E9, + // The security identifier provided does not have a domain component. + NON_DOMAIN_SID = 0x4EA, + // AppHelp dialog canceled thus preventing the application from starting. + APPHELP_BLOCK = 0x4EB, + // This program is blocked by group policy. For more information, contact your system administrator. + ACCESS_DISABLED_BY_POLICY = 0x4EC, + // A program attempt to use an invalid register value. Normally caused by an uninitialized register. This error is Itanium specific. + REG_NAT_CONSUMPTION = 0x4ED, + // The share is currently offline or does not exist. + CSCSHARE_OFFLINE = 0x4EE, + // The Kerberos protocol encountered an error while validating the KDC certificate during smartcard logon. There is more information in the system event log. + PKINIT_FAILURE = 0x4EF, + // The Kerberos protocol encountered an error while attempting to utilize the smartcard subsystem. + SMARTCARD_SUBSYSTEM_FAILURE = 0x4F0, + // The system cannot contact a domain controller to service the authentication request. Please try again later. + DOWNGRADE_DETECTED = 0x4F1, + // The machine is locked and cannot be shut down without the force option. + MACHINE_LOCKED = 0x4F7, + // An application-defined callback gave invalid data when called. + CALLBACK_SUPPLIED_INVALID_DATA = 0x4F9, + // The group policy framework should call the extension in the synchronous foreground policy refresh. + SYNC_FOREGROUND_REFRESH_REQUIRED = 0x4FA, + // This driver has been blocked from loading. + DRIVER_BLOCKED = 0x4FB, + // A dynamic link library (DLL) referenced a module that was neither a DLL nor the process's executable image. + INVALID_IMPORT_OF_NON_DLL = 0x4FC, + // Windows cannot open this program since it has been disabled. + ACCESS_DISABLED_WEBBLADE = 0x4FD, + // Windows cannot open this program because the license enforcement system has been tampered with or become corrupted. + ACCESS_DISABLED_WEBBLADE_TAMPER = 0x4FE, + // A transaction recover failed. + RECOVERY_FAILURE = 0x4FF, + // The current thread has already been converted to a fiber. + ALREADY_FIBER = 0x500, + // The current thread has already been converted from a fiber. + ALREADY_THREAD = 0x501, + // The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application. + STACK_BUFFER_OVERRUN = 0x502, + // Data present in one of the parameters is more than the function can operate on. + PARAMETER_QUOTA_EXCEEDED = 0x503, + // An attempt to do an operation on a debug object failed because the object is in the process of being deleted. + DEBUGGER_INACTIVE = 0x504, + // An attempt to delay-load a .dll or get a function address in a delay-loaded .dll failed. + DELAY_LOAD_FAILED = 0x505, + // %1 is a 16-bit application. You do not have permissions to execute 16-bit applications. Check your permissions with your system administrator. + VDM_DISALLOWED = 0x506, + // Insufficient information exists to identify the cause of failure. + UNIDENTIFIED_ERROR = 0x507, + // The parameter passed to a C runtime function is incorrect. + INVALID_CRUNTIME_PARAMETER = 0x508, + // The operation occurred beyond the valid data length of the file. + BEYOND_VDL = 0x509, + // The service start failed since one or more services in the same process have an incompatible service SID type setting. A service with restricted service SID type can only coexist in the same process with other services with a restricted SID type. If the service SID type for this service was just configured, the hosting process must be restarted in order to start this service. + // On Windows Server 2003 and Windows XP, an unrestricted service cannot coexist in the same process with other services. The service with the unrestricted service SID type must be moved to an owned process in order to start this service. + INCOMPATIBLE_SERVICE_SID_TYPE = 0x50A, + // The process hosting the driver for this device has been terminated. + DRIVER_PROCESS_TERMINATED = 0x50B, + // An operation attempted to exceed an implementation-defined limit. + IMPLEMENTATION_LIMIT = 0x50C, + // Either the target process, or the target thread's containing process, is a protected process. + PROCESS_IS_PROTECTED = 0x50D, + // The service notification client is lagging too far behind the current state of services in the machine. + SERVICE_NOTIFY_CLIENT_LAGGING = 0x50E, + // The requested file operation failed because the storage quota was exceeded. To free up disk space, move files to a different location or delete unnecessary files. For more information, contact your system administrator. + DISK_QUOTA_EXCEEDED = 0x50F, + // The requested file operation failed because the storage policy blocks that type of file. For more information, contact your system administrator. + CONTENT_BLOCKED = 0x510, + // A privilege that the service requires to function properly does not exist in the service account configuration. You may use the Services Microsoft Management Console (MMC) snap-in (services.msc) and the Local Security Settings MMC snap-in (secpol.msc) to view the service configuration and the account configuration. + INCOMPATIBLE_SERVICE_PRIVILEGE = 0x511, + // A thread involved in this operation appears to be unresponsive. + APP_HANG = 0x512, + // Indicates a particular Security ID may not be assigned as the label of an object. + INVALID_LABEL = 0x513, + + // Not all privileges or groups referenced are assigned to the caller. + NOT_ALL_ASSIGNED = 0x514, + // Some mapping between account names and security IDs was not done. + SOME_NOT_MAPPED = 0x515, + // No system quota limits are specifically set for this account. + NO_QUOTAS_FOR_ACCOUNT = 0x516, + // No encryption key is available. A well-known encryption key was returned. + LOCAL_USER_SESSION_KEY = 0x517, + // The password is too complex to be converted to a LAN Manager password. The LAN Manager password returned is a NULL string. + NULL_LM_PASSWORD = 0x518, + // The revision level is unknown. + UNKNOWN_REVISION = 0x519, + // Indicates two revision levels are incompatible. + REVISION_MISMATCH = 0x51A, + // This security ID may not be assigned as the owner of this object. + INVALID_OWNER = 0x51B, + // This security ID may not be assigned as the primary group of an object. + INVALID_PRIMARY_GROUP = 0x51C, + // An attempt has been made to operate on an impersonation token by a thread that is not currently impersonating a client. + NO_IMPERSONATION_TOKEN = 0x51D, + // The group may not be disabled. + CANT_DISABLE_MANDATORY = 0x51E, + // There are currently no logon servers available to service the logon request. + NO_LOGON_SERVERS = 0x51F, + // A specified logon session does not exist. It may already have been terminated. + NO_SUCH_LOGON_SESSION = 0x520, + // A specified privilege does not exist. + NO_SUCH_PRIVILEGE = 0x521, + // A required privilege is not held by the client. + PRIVILEGE_NOT_HELD = 0x522, + // The name provided is not a properly formed account name. + INVALID_ACCOUNT_NAME = 0x523, + // The specified account already exists. + USER_EXISTS = 0x524, + // The specified account does not exist. + NO_SUCH_USER = 0x525, + // The specified group already exists. + GROUP_EXISTS = 0x526, + // The specified group does not exist. + NO_SUCH_GROUP = 0x527, + // Either the specified user account is already a member of the specified group, or the specified group cannot be deleted because it contains a member. + MEMBER_IN_GROUP = 0x528, + // The specified user account is not a member of the specified group account. + MEMBER_NOT_IN_GROUP = 0x529, + // This operation is disallowed as it could result in an administration account being disabled, deleted or unable to log on. + LAST_ADMIN = 0x52A, + // Unable to update the password. The value provided as the current password is incorrect. + WRONG_PASSWORD = 0x52B, + // Unable to update the password. The value provided for the new password contains values that are not allowed in passwords. + ILL_FORMED_PASSWORD = 0x52C, + // Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirements of the domain. + PASSWORD_RESTRICTION = 0x52D, + // The user name or password is incorrect. + LOGON_FAILURE = 0x52E, + // Account restrictions are preventing this user from signing in. For example: blank passwords aren't allowed, sign-in times are limited, or a policy restriction has been enforced. + ACCOUNT_RESTRICTION = 0x52F, + // Your account has time restrictions that keep you from signing in right now. + INVALID_LOGON_HOURS = 0x530, + // This user isn't allowed to sign in to this computer. + INVALID_WORKSTATION = 0x531, + // The password for this account has expired. + PASSWORD_EXPIRED = 0x532, + // This user can't sign in because this account is currently disabled. + ACCOUNT_DISABLED = 0x533, + // No mapping between account names and security IDs was done. + NONE_MAPPED = 0x534, + // Too many local user identifiers (LUIDs) were requested at one time. + TOO_MANY_LUIDS_REQUESTED = 0x535, + // No more local user identifiers (LUIDs) are available. + LUIDS_EXHAUSTED = 0x536, + // The subauthority part of a security ID is invalid for this particular use. + INVALID_SUB_AUTHORITY = 0x537, + // The access control list (ACL) structure is invalid. + INVALID_ACL = 0x538, + // The security ID structure is invalid. + INVALID_SID = 0x539, + // The security descriptor structure is invalid. + INVALID_SECURITY_DESCR = 0x53A, + // The inherited access control list (ACL) or access control entry (ACE) could not be built. + BAD_INHERITANCE_ACL = 0x53C, + // The server is currently disabled. + SERVER_DISABLED = 0x53D, + // The server is currently enabled. + SERVER_NOT_DISABLED = 0x53E, + // The value provided was an invalid value for an identifier authority. + INVALID_ID_AUTHORITY = 0x53F, + // No more memory is available for security information updates. + ALLOTTED_SPACE_EXCEEDED = 0x540, + // The specified attributes are invalid, or incompatible with the attributes for the group as a whole. + INVALID_GROUP_ATTRIBUTES = 0x541, + // Either a required impersonation level was not provided, or the provided impersonation level is invalid. + BAD_IMPERSONATION_LEVEL = 0x542, + // Cannot open an anonymous level security token. + CANT_OPEN_ANONYMOUS = 0x543, + // The validation information class requested was invalid. + BAD_VALIDATION_CLASS = 0x544, + // The type of the token is inappropriate for its attempted use. + BAD_TOKEN_TYPE = 0x545, + // Unable to perform a security operation on an object that has no associated security. + NO_SECURITY_ON_OBJECT = 0x546, + // Configuration information could not be read from the domain controller, either because the machine is unavailable, or access has been denied. + CANT_ACCESS_DOMAIN_INFO = 0x547, + // The security account manager (SAM) or local security authority (LSA) server was in the wrong state to perform the security operation. + INVALID_SERVER_STATE = 0x548, + // The domain was in the wrong state to perform the security operation. + INVALID_DOMAIN_STATE = 0x549, + // This operation is only allowed for the Primary Domain Controller of the domain. + INVALID_DOMAIN_ROLE = 0x54A, + // The specified domain either does not exist or could not be contacted. + NO_SUCH_DOMAIN = 0x54B, + // The specified domain already exists. + DOMAIN_EXISTS = 0x54C, + // An attempt was made to exceed the limit on the number of domains per server. + DOMAIN_LIMIT_EXCEEDED = 0x54D, + // Unable to complete the requested operation because of either a catastrophic media failure or a data structure corruption on the disk. + INTERNAL_DB_CORRUPTION = 0x54E, + // An internal error occurred. + INTERNAL_ERROR = 0x54F, + // Generic access types were contained in an access mask which should already be mapped to nongeneric types. + GENERIC_NOT_MAPPED = 0x550, + // A security descriptor is not in the right format (absolute or self-relative). + BAD_DESCRIPTOR_FORMAT = 0x551, + // The requested action is restricted for use by logon processes only. The calling process has not registered as a logon process. + NOT_LOGON_PROCESS = 0x552, + // Cannot start a new logon session with an ID that is already in use. + LOGON_SESSION_EXISTS = 0x553, + // A specified authentication package is unknown. + NO_SUCH_PACKAGE = 0x554, + // The logon session is not in a state that is consistent with the requested operation. + BAD_LOGON_SESSION_STATE = 0x555, + // The logon session ID is already in use. + LOGON_SESSION_COLLISION = 0x556, + // A logon request contained an invalid logon type value. + INVALID_LOGON_TYPE = 0x557, + // Unable to impersonate using a named pipe until data has been read from that pipe. + CANNOT_IMPERSONATE = 0x558, + // The transaction state of a registry subtree is incompatible with the requested operation. + RXACT_INVALID_STATE = 0x559, + // An internal security database corruption has been encountered. + RXACT_COMMIT_FAILURE = 0x55A, + // Cannot perform this operation on built-in accounts. + SPECIAL_ACCOUNT = 0x55B, + // Cannot perform this operation on this built-in special group. + SPECIAL_GROUP = 0x55C, + // Cannot perform this operation on this built-in special user. + SPECIAL_USER = 0x55D, + // The user cannot be removed from a group because the group is currently the user's primary group. + MEMBERS_PRIMARY_GROUP = 0x55E, + // The token is already in use as a primary token. + TOKEN_ALREADY_IN_USE = 0x55F, + // The specified local group does not exist. + NO_SUCH_ALIAS = 0x560, + // The specified account name is not a member of the group. + MEMBER_NOT_IN_ALIAS = 0x561, + // The specified account name is already a member of the group. + MEMBER_IN_ALIAS = 0x562, + // The specified local group already exists. + ALIAS_EXISTS = 0x563, + // Logon failure: the user has not been granted the requested logon type at this computer. + LOGON_NOT_GRANTED = 0x564, + // The maximum number of secrets that may be stored in a single system has been exceeded. + TOO_MANY_SECRETS = 0x565, + // The length of a secret exceeds the maximum length allowed. + SECRET_TOO_LONG = 0x566, + // The local security authority database contains an internal inconsistency. + INTERNAL_DB_ERROR = 0x567, + // During a logon attempt, the user's security context accumulated too many security IDs. + TOO_MANY_CONTEXT_IDS = 0x568, + // Logon failure: the user has not been granted the requested logon type at this computer. + LOGON_TYPE_NOT_GRANTED = 0x569, + // A cross-encrypted password is necessary to change a user password. + NT_CROSS_ENCRYPTION_REQUIRED = 0x56A, + // A member could not be added to or removed from the local group because the member does not exist. + NO_SUCH_MEMBER = 0x56B, + // A new member could not be added to a local group because the member has the wrong account type. + INVALID_MEMBER = 0x56C, + // Too many security IDs have been specified. + TOO_MANY_SIDS = 0x56D, + // A cross-encrypted password is necessary to change this user password. + LM_CROSS_ENCRYPTION_REQUIRED = 0x56E, + // Indicates an ACL contains no inheritable components. + NO_INHERITANCE = 0x56F, + // The file or directory is corrupted and unreadable. + FILE_CORRUPT = 0x570, + // The disk structure is corrupted and unreadable. + DISK_CORRUPT = 0x571, + // There is no user session key for the specified logon session. + NO_USER_SESSION_KEY = 0x572, + // The service being accessed is licensed for a particular number of connections. No more connections can be made to the service at this time because there are already as many connections as the service can accept. + LICENSE_QUOTA_EXCEEDED = 0x573, + // The target account name is incorrect. + WRONG_TARGET_NAME = 0x574, + // Mutual Authentication failed. The server's password is out of date at the domain controller. + MUTUAL_AUTH_FAILED = 0x575, + // There is a time and/or date difference between the client and server. + TIME_SKEW = 0x576, + // This operation cannot be performed on the current domain. + CURRENT_DOMAIN_NOT_ALLOWED = 0x577, + // Invalid window handle. + INVALID_WINDOW_HANDLE = 0x578, + // Invalid menu handle. + INVALID_MENU_HANDLE = 0x579, + // Invalid cursor handle. + INVALID_CURSOR_HANDLE = 0x57A, + // Invalid accelerator table handle. + INVALID_ACCEL_HANDLE = 0x57B, + // Invalid hook handle. + INVALID_HOOK_HANDLE = 0x57C, + // Invalid handle to a multiple-window position structure. + INVALID_DWP_HANDLE = 0x57D, + // Cannot create a top-level child window. + TLW_WITH_WSCHILD = 0x57E, + // Cannot find window class. + CANNOT_FIND_WND_CLASS = 0x57F, + // Invalid window; it belongs to other thread. + WINDOW_OF_OTHER_THREAD = 0x580, + // Hot key is already registered. + HOTKEY_ALREADY_REGISTERED = 0x581, + // Class already exists. + CLASS_ALREADY_EXISTS = 0x582, + // Class does not exist. + CLASS_DOES_NOT_EXIST = 0x583, + // Class still has open windows. + CLASS_HAS_WINDOWS = 0x584, + // Invalid index. + INVALID_INDEX = 0x585, + // Invalid icon handle. + INVALID_ICON_HANDLE = 0x586, + // Using private DIALOG window words. + PRIVATE_DIALOG_INDEX = 0x587, + // The list box identifier was not found. + LISTBOX_ID_NOT_FOUND = 0x588, + // No wildcards were found. + NO_WILDCARD_CHARACTERS = 0x589, + // Thread does not have a clipboard open. + CLIPBOARD_NOT_OPEN = 0x58A, + // Hot key is not registered. + HOTKEY_NOT_REGISTERED = 0x58B, + // The window is not a valid dialog window. + WINDOW_NOT_DIALOG = 0x58C, + // Control ID not found. + CONTROL_ID_NOT_FOUND = 0x58D, + // Invalid message for a combo box because it does not have an edit control. + INVALID_COMBOBOX_MESSAGE = 0x58E, + // The window is not a combo box. + WINDOW_NOT_COMBOBOX = 0x58F, + // Height must be less than 256. + INVALID_EDIT_HEIGHT = 0x590, + // Invalid device context (DC) handle. + DC_NOT_FOUND = 0x591, + // Invalid hook procedure type. + INVALID_HOOK_FILTER = 0x592, + // Invalid hook procedure. + INVALID_FILTER_PROC = 0x593, + // Cannot set nonlocal hook without a module handle. + HOOK_NEEDS_HMOD = 0x594, + // This hook procedure can only be set globally. + GLOBAL_ONLY_HOOK = 0x595, + // The journal hook procedure is already installed. + JOURNAL_HOOK_SET = 0x596, + // The hook procedure is not installed. + HOOK_NOT_INSTALLED = 0x597, + // Invalid message for single-selection list box. + INVALID_LB_MESSAGE = 0x598, + // LB_SETCOUNT sent to non-lazy list box. + SETCOUNT_ON_BAD_LB = 0x599, + // This list box does not support tab stops. + LB_WITHOUT_TABSTOPS = 0x59A, + // Cannot destroy object created by another thread. + DESTROY_OBJECT_OF_OTHER_THREAD = 0x59B, + // Child windows cannot have menus. + CHILD_WINDOW_MENU = 0x59C, + // The window does not have a system menu. + NO_SYSTEM_MENU = 0x59D, + // Invalid message box style. + INVALID_MSGBOX_STYLE = 0x59E, + // Invalid system-wide (SPI_*) parameter. + INVALID_SPI_VALUE = 0x59F, + // Screen already locked. + SCREEN_ALREADY_LOCKED = 0x5A0, + // All handles to windows in a multiple-window position structure must have the same parent. + HWNDS_HAVE_DIFF_PARENT = 0x5A1, + // The window is not a child window. + NOT_CHILD_WINDOW = 0x5A2, + // Invalid GW_* command. + INVALID_GW_COMMAND = 0x5A3, + // Invalid thread identifier. + INVALID_THREAD_ID = 0x5A4, + // Cannot process a message from a window that is not a multiple document interface (MDI) window. + NON_MDICHILD_WINDOW = 0x5A5, + // Popup menu already active. + POPUP_ALREADY_ACTIVE = 0x5A6, + // The window does not have scroll bars. + NO_SCROLLBARS = 0x5A7, + // Scroll bar range cannot be greater than MAXLONG. + INVALID_SCROLLBAR_RANGE = 0x5A8, + // Cannot show or remove the window in the way specified. + INVALID_SHOWWIN_COMMAND = 0x5A9, + // Insufficient system resources exist to complete the requested service. + NO_SYSTEM_RESOURCES = 0x5AA, + // Insufficient system resources exist to complete the requested service. + NONPAGED_SYSTEM_RESOURCES = 0x5AB, + // Insufficient system resources exist to complete the requested service. + PAGED_SYSTEM_RESOURCES = 0x5AC, + // Insufficient quota to complete the requested service. + WORKING_SET_QUOTA = 0x5AD, + // Insufficient quota to complete the requested service. + PAGEFILE_QUOTA = 0x5AE, + // The paging file is too small for this operation to complete. + COMMITMENT_LIMIT = 0x5AF, + // A menu item was not found. + MENU_ITEM_NOT_FOUND = 0x5B0, + // Invalid keyboard layout handle. + INVALID_KEYBOARD_HANDLE = 0x5B1, + // Hook type not allowed. + HOOK_TYPE_NOT_ALLOWED = 0x5B2, + // This operation requires an interactive window station. + REQUIRES_INTERACTIVE_WINDOWSTATION = 0x5B3, + // This operation returned because the timeout period expired. + TIMEOUT = 0x5B4, + // Invalid monitor handle. + INVALID_MONITOR_HANDLE = 0x5B5, + // Incorrect size argument. + INCORRECT_SIZE = 0x5B6, + // The symbolic link cannot be followed because its type is disabled. + SYMLINK_CLASS_DISABLED = 0x5B7, + // This application does not support the current operation on symbolic links. + SYMLINK_NOT_SUPPORTED = 0x5B8, + // Windows was unable to parse the requested XML data. + XML_PARSE_ERROR = 0x5B9, + // An error was encountered while processing an XML digital signature. + XMLDSIG_ERROR = 0x5BA, + // This application must be restarted. + RESTART_APPLICATION = 0x5BB, + // The caller made the connection request in the wrong routing compartment. + WRONG_COMPARTMENT = 0x5BC, + // There was an AuthIP failure when attempting to connect to the remote host. + AUTHIP_FAILURE = 0x5BD, + // Insufficient NVRAM resources exist to complete the requested service. A reboot might be required. + NO_NVRAM_RESOURCES = 0x5BE, + // Unable to finish the requested operation because the specified process is not a GUI process. + NOT_GUI_PROCESS = 0x5BF, + // The event log file is corrupted. + EVENTLOG_FILE_CORRUPT = 0x5DC, + // No event log file could be opened, so the event logging service did not start. + EVENTLOG_CANT_START = 0x5DD, + // The event log file is full. + LOG_FILE_FULL = 0x5DE, + // The event log file has changed between read operations. + EVENTLOG_FILE_CHANGED = 0x5DF, + // The specified task name is invalid. + INVALID_TASK_NAME = 0x60E, + // The specified task index is invalid. + INVALID_TASK_INDEX = 0x60F, + // The specified thread is already joining a task. + THREAD_ALREADY_IN_TASK = 0x610, + // The Windows Installer Service could not be accessed. This can occur if the Windows Installer is not correctly installed. Contact your support personnel for assistance. + INSTALL_SERVICE_FAILURE = 0x641, + // User cancelled installation. + INSTALL_USEREXIT = 0x642, + // Fatal error during installation. + INSTALL_FAILURE = 0x643, + // Installation suspended, incomplete. + INSTALL_SUSPEND = 0x644, + // This action is only valid for products that are currently installed. + UNKNOWN_PRODUCT = 0x645, + // Feature ID not registered. + UNKNOWN_FEATURE = 0x646, + // Component ID not registered. + UNKNOWN_COMPONENT = 0x647, + // Unknown property. + UNKNOWN_PROPERTY = 0x648, + // Handle is in an invalid state. + INVALID_HANDLE_STATE = 0x649, + // The configuration data for this product is corrupt. Contact your support personnel. + BAD_CONFIGURATION = 0x64A, + // Component qualifier not present. + INDEX_ABSENT = 0x64B, + // The installation source for this product is not available. Verify that the source exists and that you can access it. + INSTALL_SOURCE_ABSENT = 0x64C, + // This installation package cannot be installed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service. + INSTALL_PACKAGE_VERSION = 0x64D, + // Product is uninstalled. + PRODUCT_UNINSTALLED = 0x64E, + // SQL query syntax invalid or unsupported. + BAD_QUERY_SYNTAX = 0x64F, + // Record field does not exist. + INVALID_FIELD = 0x650, + // The device has been removed. + DEVICE_REMOVED = 0x651, + // Another installation is already in progress. Complete that installation before proceeding with this install. + INSTALL_ALREADY_RUNNING = 0x652, + // This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package. + INSTALL_PACKAGE_OPEN_FAILED = 0x653, + // This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package. + INSTALL_PACKAGE_INVALID = 0x654, + // There was an error starting the Windows Installer service user interface. Contact your support personnel. + INSTALL_UI_FAILURE = 0x655, + // Error opening installation log file. Verify that the specified log file location exists and that you can write to it. + INSTALL_LOG_FAILURE = 0x656, + // The language of this installation package is not supported by your system. + INSTALL_LANGUAGE_UNSUPPORTED = 0x657, + // Error applying transforms. Verify that the specified transform paths are valid. + INSTALL_TRANSFORM_FAILURE = 0x658, + // This installation is forbidden by system policy. Contact your system administrator. + INSTALL_PACKAGE_REJECTED = 0x659, + // Function could not be executed. + FUNCTION_NOT_CALLED = 0x65A, + // Function failed during execution. + FUNCTION_FAILED = 0x65B, + // Invalid or unknown table specified. + INVALID_TABLE = 0x65C, + // Data supplied is of wrong type. + DATATYPE_MISMATCH = 0x65D, + // Data of this type is not supported. + UNSUPPORTED_TYPE = 0x65E, + // The Windows Installer service failed to start. Contact your support personnel. + CREATE_FAILED = 0x65F, + // The Temp folder is on a drive that is full or is inaccessible. Free up space on the drive or verify that you have write permission on the Temp folder. + INSTALL_TEMP_UNWRITABLE = 0x660, + // This installation package is not supported by this processor type. Contact your product vendor. + INSTALL_PLATFORM_UNSUPPORTED = 0x661, + // Component not used on this computer. + INSTALL_NOTUSED = 0x662, + // This update package could not be opened. Verify that the update package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer update package. + PATCH_PACKAGE_OPEN_FAILED = 0x663, + // This update package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer update package. + PATCH_PACKAGE_INVALID = 0x664, + // This update package cannot be processed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service. + PATCH_PACKAGE_UNSUPPORTED = 0x665, + // Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. + PRODUCT_VERSION = 0x666, + // Invalid command line argument. Consult the Windows Installer SDK for detailed command line help. + INVALID_COMMAND_LINE = 0x667, + // Only administrators have permission to add, remove, or configure server software during a Terminal services remote session. If you want to install or configure software on the server, contact your network administrator. + INSTALL_REMOTE_DISALLOWED = 0x668, + // The requested operation completed successfully. The system will be restarted so the changes can take effect. + SUCCESS_REBOOT_INITIATED = 0x669, + // The upgrade cannot be installed by the Windows Installer service because the program to be upgraded may be missing, or the upgrade may update a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade. + PATCH_TARGET_NOT_FOUND = 0x66A, + // The update package is not permitted by software restriction policy. + PATCH_PACKAGE_REJECTED = 0x66B, + // One or more customizations are not permitted by software restriction policy. + INSTALL_TRANSFORM_REJECTED = 0x66C, + // The Windows Installer does not permit installation from a Remote Desktop Connection. + INSTALL_REMOTE_PROHIBITED = 0x66D, + // Uninstallation of the update package is not supported. + PATCH_REMOVAL_UNSUPPORTED = 0x66E, + // The update is not applied to this product. + UNKNOWN_PATCH = 0x66F, + // No valid sequence could be found for the set of updates. + PATCH_NO_SEQUENCE = 0x670, + // Update removal was disallowed by policy. + PATCH_REMOVAL_DISALLOWED = 0x671, + // The XML update data is invalid. + INVALID_PATCH_XML = 0x672, + // Windows Installer does not permit updating of managed advertised products. At least one feature of the product must be installed before applying the update. + PATCH_MANAGED_ADVERTISED_PRODUCT = 0x673, + // The Windows Installer service is not accessible in Safe Mode. Please try again when your computer is not in Safe Mode or you can use System Restore to return your machine to a previous good state. + INSTALL_SERVICE_SAFEBOOT = 0x674, + // A fail fast exception occurred. Exception handlers will not be invoked and the process will be terminated immediately. + FAIL_FAST_EXCEPTION = 0x675, + // The app that you are trying to run is not supported on this version of Windows. + INSTALL_REJECTED = 0x676, + + // The string binding is invalid. + RPC_S_INVALID_STRING_BINDING = 0x6A4, + // The binding handle is not the correct type. + RPC_S_WRONG_KIND_OF_BINDING = 0x6A5, + // The binding handle is invalid. + RPC_S_INVALID_BINDING = 0x6A6, + // The RPC protocol sequence is not supported. + RPC_S_PROTSEQ_NOT_SUPPORTED = 0x6A7, + // The RPC protocol sequence is invalid. + RPC_S_INVALID_RPC_PROTSEQ = 0x6A8, + // The string universal unique identifier (UUID) is invalid. + RPC_S_INVALID_STRING_UUID = 0x6A9, + // The endpoint format is invalid. + RPC_S_INVALID_ENDPOINT_FORMAT = 0x6AA, + // The network address is invalid. + RPC_S_INVALID_NET_ADDR = 0x6AB, + // No endpoint was found. + RPC_S_NO_ENDPOINT_FOUND = 0x6AC, + // The timeout value is invalid. + RPC_S_INVALID_TIMEOUT = 0x6AD, + // The object universal unique identifier (UUID) was not found. + RPC_S_OBJECT_NOT_FOUND = 0x6AE, + // The object universal unique identifier (UUID) has already been registered. + RPC_S_ALREADY_REGISTERED = 0x6AF, + // The type universal unique identifier (UUID) has already been registered. + RPC_S_TYPE_ALREADY_REGISTERED = 0x6B0, + // The RPC server is already listening. + RPC_S_ALREADY_LISTENING = 0x6B1, + // No protocol sequences have been registered. + RPC_S_NO_PROTSEQS_REGISTERED = 0x6B2, + // The RPC server is not listening. + RPC_S_NOT_LISTENING = 0x6B3, + // The manager type is unknown. + RPC_S_UNKNOWN_MGR_TYPE = 0x6B4, + // The interface is unknown. + RPC_S_UNKNOWN_IF = 0x6B5, + // There are no bindings. + RPC_S_NO_BINDINGS = 0x6B6, + // There are no protocol sequences. + RPC_S_NO_PROTSEQS = 0x6B7, + // The endpoint cannot be created. + RPC_S_CANT_CREATE_ENDPOINT = 0x6B8, + // Not enough resources are available to complete this operation. + RPC_S_OUT_OF_RESOURCES = 0x6B9, + // The RPC server is unavailable. + RPC_S_SERVER_UNAVAILABLE = 0x6BA, + // The RPC server is too busy to complete this operation. + RPC_S_SERVER_TOO_BUSY = 0x6BB, + // The network options are invalid. + RPC_S_INVALID_NETWORK_OPTIONS = 0x6BC, + // There are no remote procedure calls active on this thread. + RPC_S_NO_CALL_ACTIVE = 0x6BD, + // The remote procedure call failed. + RPC_S_CALL_FAILED = 0x6BE, + // The remote procedure call failed and did not execute. + RPC_S_CALL_FAILED_DNE = 0x6BF, + // A remote procedure call (RPC) protocol error occurred. + RPC_S_PROTOCOL_ERROR = 0x6C0, + // Access to the HTTP proxy is denied. + RPC_S_PROXY_ACCESS_DENIED = 0x6C1, + // The transfer syntax is not supported by the RPC server. + RPC_S_UNSUPPORTED_TRANS_SYN = 0x6C2, + // The universal unique identifier (UUID) type is not supported. + RPC_S_UNSUPPORTED_TYPE = 0x6C4, + // The tag is invalid. + RPC_S_INVALID_TAG = 0x6C5, + // The array bounds are invalid. + RPC_S_INVALID_BOUND = 0x6C6, + // The binding does not contain an entry name. + RPC_S_NO_ENTRY_NAME = 0x6C7, + // The name syntax is invalid. + RPC_S_INVALID_NAME_SYNTAX = 0x6C8, + // The name syntax is not supported. + RPC_S_UNSUPPORTED_NAME_SYNTAX = 0x6C9, + // No network address is available to use to construct a universal unique identifier (UUID). + RPC_S_UUID_NO_ADDRESS = 0x6CB, + // The endpoint is a duplicate. + RPC_S_DUPLICATE_ENDPOINT = 0x6CC, + // The authentication type is unknown. + RPC_S_UNKNOWN_AUTHN_TYPE = 0x6CD, + // The maximum number of calls is too small. + RPC_S_MAX_CALLS_TOO_SMALL = 0x6CE, + // The string is too long. + RPC_S_STRING_TOO_LONG = 0x6CF, + // The RPC protocol sequence was not found. + RPC_S_PROTSEQ_NOT_FOUND = 0x6D0, + // The procedure number is out of range. + RPC_S_PROCNUM_OUT_OF_RANGE = 0x6D1, + // The binding does not contain any authentication information. + RPC_S_BINDING_HAS_NO_AUTH = 0x6D2, + // The authentication service is unknown. + RPC_S_UNKNOWN_AUTHN_SERVICE = 0x6D3, + // The authentication level is unknown. + RPC_S_UNKNOWN_AUTHN_LEVEL = 0x6D4, + // The security context is invalid. + RPC_S_INVALID_AUTH_IDENTITY = 0x6D5, + // The authorization service is unknown. + RPC_S_UNKNOWN_AUTHZ_SERVICE = 0x6D6, + // The entry is invalid. + EPT_S_INVALID_ENTRY = 0x6D7, + // The server endpoint cannot perform the operation. + EPT_S_CANT_PERFORM_OP = 0x6D8, + // There are no more endpoints available from the endpoint mapper. + EPT_S_NOT_REGISTERED = 0x6D9, + // No interfaces have been exported. + RPC_S_NOTHING_TO_EXPORT = 0x6DA, + // The entry name is incomplete. + RPC_S_INCOMPLETE_NAME = 0x6DB, + // The version option is invalid. + RPC_S_INVALID_VERS_OPTION = 0x6DC, + // There are no more members. + RPC_S_NO_MORE_MEMBERS = 0x6DD, + // There is nothing to unexport. + RPC_S_NOT_ALL_OBJS_UNEXPORTED = 0x6DE, + // The interface was not found. + RPC_S_INTERFACE_NOT_FOUND = 0x6DF, + // The entry already exists. + RPC_S_ENTRY_ALREADY_EXISTS = 0x6E0, + // The entry is not found. + RPC_S_ENTRY_NOT_FOUND = 0x6E1, + // The name service is unavailable. + RPC_S_NAME_SERVICE_UNAVAILABLE = 0x6E2, + // The network address family is invalid. + RPC_S_INVALID_NAF_ID = 0x6E3, + // The requested operation is not supported. + RPC_S_CANNOT_SUPPORT = 0x6E4, + // No security context is available to allow impersonation. + RPC_S_NO_CONTEXT_AVAILABLE = 0x6E5, + // An internal error occurred in a remote procedure call (RPC). + RPC_S_INTERNAL_ERROR = 0x6E6, + // The RPC server attempted an integer division by zero. + RPC_S_ZERO_DIVIDE = 0x6E7, + // An addressing error occurred in the RPC server. + RPC_S_ADDRESS_ERROR = 0x6E8, + // A floating-point operation at the RPC server caused a division by zero. + RPC_S_FP_DIV_ZERO = 0x6E9, + // A floating-point underflow occurred at the RPC server. + RPC_S_FP_UNDERFLOW = 0x6EA, + // A floating-point overflow occurred at the RPC server. + RPC_S_FP_OVERFLOW = 0x6EB, + // The list of RPC servers available for the binding of auto handles has been exhausted. + RPC_X_NO_MORE_ENTRIES = 0x6EC, + // Unable to open the character translation table file. + RPC_X_SS_CHAR_TRANS_OPEN_FAIL = 0x6ED, + // The file containing the character translation table has fewer than 512 bytes. + RPC_X_SS_CHAR_TRANS_SHORT_FILE = 0x6EE, + // A null context handle was passed from the client to the host during a remote procedure call. + RPC_X_SS_IN_NULL_CONTEXT = 0x6EF, + // The context handle changed during a remote procedure call. + RPC_X_SS_CONTEXT_DAMAGED = 0x6F1, + // The binding handles passed to a remote procedure call do not match. + RPC_X_SS_HANDLES_MISMATCH = 0x6F2, + // The stub is unable to get the remote procedure call handle. + RPC_X_SS_CANNOT_GET_CALL_HANDLE = 0x6F3, + // A null reference pointer was passed to the stub. + RPC_X_NULL_REF_POINTER = 0x6F4, + // The enumeration value is out of range. + RPC_X_ENUM_VALUE_OUT_OF_RANGE = 0x6F5, + // The byte count is too small. + RPC_X_BYTE_COUNT_TOO_SMALL = 0x6F6, + // The stub received bad data. + RPC_X_BAD_STUB_DATA = 0x6F7, + // The supplied user buffer is not valid for the requested operation. + INVALID_USER_BUFFER = 0x6F8, + // The disk media is not recognized. It may not be formatted. + UNRECOGNIZED_MEDIA = 0x6F9, + // The workstation does not have a trust secret. + NO_TRUST_LSA_SECRET = 0x6FA, + // The security database on the server does not have a computer account for this workstation trust relationship. + NO_TRUST_SAM_ACCOUNT = 0x6FB, + // The trust relationship between the primary domain and the trusted domain failed. + TRUSTED_DOMAIN_FAILURE = 0x6FC, + // The trust relationship between this workstation and the primary domain failed. + TRUSTED_RELATIONSHIP_FAILURE = 0x6FD, + // The network logon failed. + TRUST_FAILURE = 0x6FE, + // A remote procedure call is already in progress for this thread. + RPC_S_CALL_IN_PROGRESS = 0x6FF, + // An attempt was made to logon, but the network logon service was not started. + NETLOGON_NOT_STARTED = 0x700, + // The user's account has expired. + ACCOUNT_EXPIRED = 0x701, + // The redirector is in use and cannot be unloaded. + REDIRECTOR_HAS_OPEN_HANDLES = 0x702, + // The specified printer driver is already installed. + PRINTER_DRIVER_ALREADY_INSTALLED = 0x703, + // The specified port is unknown. + UNKNOWN_PORT = 0x704, + // The printer driver is unknown. + UNKNOWN_PRINTER_DRIVER = 0x705, + // The print processor is unknown. + UNKNOWN_PRINTPROCESSOR = 0x706, + // The specified separator file is invalid. + INVALID_SEPARATOR_FILE = 0x707, + // The specified priority is invalid. + INVALID_PRIORITY = 0x708, + // The printer name is invalid. + INVALID_PRINTER_NAME = 0x709, + // The printer already exists. + PRINTER_ALREADY_EXISTS = 0x70A, + // The printer command is invalid. + INVALID_PRINTER_COMMAND = 0x70B, + // The specified datatype is invalid. + INVALID_DATATYPE = 0x70C, + // The environment specified is invalid. + INVALID_ENVIRONMENT = 0x70D, + // There are no more bindings. + RPC_S_NO_MORE_BINDINGS = 0x70E, + // The account used is an interdomain trust account. Use your global user account or local user account to access this server. + NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0x70F, + // The account used is a computer account. Use your global user account or local user account to access this server. + NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0x710, + // The account used is a server trust account. Use your global user account or local user account to access this server. + NOLOGON_SERVER_TRUST_ACCOUNT = 0x711, + // The name or security ID (SID) of the domain specified is inconsistent with the trust information for that domain. + DOMAIN_TRUST_INCONSISTENT = 0x712, + // The server is in use and cannot be unloaded. + SERVER_HAS_OPEN_HANDLES = 0x713, + // The specified image file did not contain a resource section. + RESOURCE_DATA_NOT_FOUND = 0x714, + // The specified resource type cannot be found in the image file. + RESOURCE_TYPE_NOT_FOUND = 0x715, + // The specified resource name cannot be found in the image file. + RESOURCE_NAME_NOT_FOUND = 0x716, + // The specified resource language ID cannot be found in the image file. + RESOURCE_LANG_NOT_FOUND = 0x717, + // Not enough quota is available to process this command. + NOT_ENOUGH_QUOTA = 0x718, + // No interfaces have been registered. + RPC_S_NO_INTERFACES = 0x719, + // The remote procedure call was cancelled. + RPC_S_CALL_CANCELLED = 0x71A, + // The binding handle does not contain all required information. + RPC_S_BINDING_INCOMPLETE = 0x71B, + // A communications failure occurred during a remote procedure call. + RPC_S_COMM_FAILURE = 0x71C, + // The requested authentication level is not supported. + RPC_S_UNSUPPORTED_AUTHN_LEVEL = 0x71D, + // No principal name registered. + RPC_S_NO_PRINC_NAME = 0x71E, + // The error specified is not a valid Windows RPC error code. + RPC_S_NOT_RPC_ERROR = 0x71F, + // A UUID that is valid only on this computer has been allocated. + RPC_S_UUID_LOCAL_ONLY = 0x720, + // A security package specific error occurred. + RPC_S_SEC_PKG_ERROR = 0x721, + // Thread is not canceled. + RPC_S_NOT_CANCELLED = 0x722, + // Invalid operation on the encoding/decoding handle. + RPC_X_INVALID_ES_ACTION = 0x723, + // Incompatible version of the serializing package. + RPC_X_WRONG_ES_VERSION = 0x724, + // Incompatible version of the RPC stub. + RPC_X_WRONG_STUB_VERSION = 0x725, + // The RPC pipe object is invalid or corrupted. + RPC_X_INVALID_PIPE_OBJECT = 0x726, + // An invalid operation was attempted on an RPC pipe object. + RPC_X_WRONG_PIPE_ORDER = 0x727, + // Unsupported RPC pipe version. + RPC_X_WRONG_PIPE_VERSION = 0x728, + // HTTP proxy server rejected the connection because the cookie authentication failed. + RPC_S_COOKIE_AUTH_FAILED = 0x729, + // The group member was not found. + RPC_S_GROUP_MEMBER_NOT_FOUND = 0x76A, + // The endpoint mapper database entry could not be created. + EPT_S_CANT_CREATE = 0x76B, + // The object universal unique identifier (UUID) is the nil UUID. + RPC_S_INVALID_OBJECT = 0x76C, + // The specified time is invalid. + INVALID_TIME = 0x76D, + // The specified form name is invalid. + INVALID_FORM_NAME = 0x76E, + // The specified form size is invalid. + INVALID_FORM_SIZE = 0x76F, + // The specified printer handle is already being waited on. + ALREADY_WAITING = 0x770, + // The specified printer has been deleted. + PRINTER_DELETED = 0x771, + // The state of the printer is invalid. + INVALID_PRINTER_STATE = 0x772, + // The user's password must be changed before signing in. + PASSWORD_MUST_CHANGE = 0x773, + // Could not find the domain controller for this domain. + DOMAIN_CONTROLLER_NOT_FOUND = 0x774, + // The referenced account is currently locked out and may not be logged on to. + ACCOUNT_LOCKED_OUT = 0x775, + // The object exporter specified was not found. + OR_INVALID_OXID = 0x776, + // The object specified was not found. + OR_INVALID_OID = 0x777, + // The object resolver set specified was not found. + OR_INVALID_SET = 0x778, + // Some data remains to be sent in the request buffer. + RPC_S_SEND_INCOMPLETE = 0x779, + // Invalid asynchronous remote procedure call handle. + RPC_S_INVALID_ASYNC_HANDLE = 0x77A, + // Invalid asynchronous RPC call handle for this operation. + RPC_S_INVALID_ASYNC_CALL = 0x77B, + // The RPC pipe object has already been closed. + RPC_X_PIPE_CLOSED = 0x77C, + // The RPC call completed before all pipes were processed. + RPC_X_PIPE_DISCIPLINE_ERROR = 0x77D, + // No more data is available from the RPC pipe. + RPC_X_PIPE_EMPTY = 0x77E, + // No site name is available for this machine. + NO_SITENAME = 0x77F, + // The file cannot be accessed by the system. + CANT_ACCESS_FILE = 0x780, + // The name of the file cannot be resolved by the system. + CANT_RESOLVE_FILENAME = 0x781, + // The entry is not of the expected type. + RPC_S_ENTRY_TYPE_MISMATCH = 0x782, + // Not all object UUIDs could be exported to the specified entry. + RPC_S_NOT_ALL_OBJS_EXPORTED = 0x783, + // Interface could not be exported to the specified entry. + RPC_S_INTERFACE_NOT_EXPORTED = 0x784, + // The specified profile entry could not be added. + RPC_S_PROFILE_NOT_ADDED = 0x785, + // The specified profile element could not be added. + RPC_S_PRF_ELT_NOT_ADDED = 0x786, + // The specified profile element could not be removed. + RPC_S_PRF_ELT_NOT_REMOVED = 0x787, + // The group element could not be added. + RPC_S_GRP_ELT_NOT_ADDED = 0x788, + // The group element could not be removed. + RPC_S_GRP_ELT_NOT_REMOVED = 0x789, + // The printer driver is not compatible with a policy enabled on your computer that blocks NT 4.0 drivers. + KM_DRIVER_BLOCKED = 0x78A, + // The context has expired and can no longer be used. + CONTEXT_EXPIRED = 0x78B, + // The current user's delegated trust creation quota has been exceeded. + PER_USER_TRUST_QUOTA_EXCEEDED = 0x78C, + // The total delegated trust creation quota has been exceeded. + ALL_USER_TRUST_QUOTA_EXCEEDED = 0x78D, + // The current user's delegated trust deletion quota has been exceeded. + USER_DELETE_TRUST_QUOTA_EXCEEDED = 0x78E, + // The computer you are signing into is protected by an authentication firewall. The specified account is not allowed to authenticate to the computer. + AUTHENTICATION_FIREWALL_FAILED = 0x78F, + // Remote connections to the Print Spooler are blocked by a policy set on your machine. + REMOTE_PRINT_CONNECTIONS_BLOCKED = 0x790, + // Authentication failed because NTLM authentication has been disabled. + NTLM_BLOCKED = 0x791, + // Logon Failure: EAS policy requires that the user change their password before this operation can be performed. + PASSWORD_CHANGE_REQUIRED = 0x792, + // The pixel format is invalid. + INVALID_PIXEL_FORMAT = 0x7D0, + // The specified driver is invalid. + BAD_DRIVER = 0x7D1, + // The window style or class attribute is invalid for this operation. + INVALID_WINDOW_STYLE = 0x7D2, + // The requested metafile operation is not supported. + METAFILE_NOT_SUPPORTED = 0x7D3, + // The requested transformation operation is not supported. + TRANSFORM_NOT_SUPPORTED = 0x7D4, + // The requested clipping operation is not supported. + CLIPPING_NOT_SUPPORTED = 0x7D5, + // The specified color management module is invalid. + INVALID_CMM = 0x7DA, + // The specified color profile is invalid. + INVALID_PROFILE = 0x7DB, + // The specified tag was not found. + TAG_NOT_FOUND = 0x7DC, + // A required tag is not present. + TAG_NOT_PRESENT = 0x7DD, + // The specified tag is already present. + DUPLICATE_TAG = 0x7DE, + // The specified color profile is not associated with the specified device. + PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 0x7DF, + // The specified color profile was not found. + PROFILE_NOT_FOUND = 0x7E0, + // The specified color space is invalid. + INVALID_COLORSPACE = 0x7E1, + // Image Color Management is not enabled. + ICM_NOT_ENABLED = 0x7E2, + // There was an error while deleting the color transform. + DELETING_ICM_XFORM = 0x7E3, + // The specified color transform is invalid. + INVALID_TRANSFORM = 0x7E4, + // The specified transform does not match the bitmap's color space. + COLORSPACE_MISMATCH = 0x7E5, + // The specified named color index is not present in the profile. + INVALID_COLORINDEX = 0x7E6, + // The specified profile is intended for a device of a different type than the specified device. + PROFILE_DOES_NOT_MATCH_DEVICE = 0x7E7, + // The network connection was made successfully, but the user had to be prompted for a password other than the one originally specified. + CONNECTED_OTHER_PASSWORD = 0x83C, + // The network connection was made successfully using default credentials. + CONNECTED_OTHER_PASSWORD_DEFAULT = 0x83D, + // The specified username is invalid. + BAD_USERNAME = 0x89A, + // This network connection does not exist. + NOT_CONNECTED = 0x8CA, + // This network connection has files open or requests pending. + OPEN_FILES = 0x961, + // Active connections still exist. + ACTIVE_CONNECTIONS = 0x962, + // The device is in use by an active process and cannot be disconnected. + DEVICE_IN_USE = 0x964, + // The specified print monitor is unknown. + UNKNOWN_PRINT_MONITOR = 0xBB8, + // The specified printer driver is currently in use. + PRINTER_DRIVER_IN_USE = 0xBB9, + // The spool file was not found. + SPOOL_FILE_NOT_FOUND = 0xBBA, + // A StartDocPrinter call was not issued. + SPL_NO_STARTDOC = 0xBBB, + // An AddJob call was not issued. + SPL_NO_ADDJOB = 0xBBC, + // The specified print processor has already been installed. + PRINT_PROCESSOR_ALREADY_INSTALLED = 0xBBD, + // The specified print monitor has already been installed. + PRINT_MONITOR_ALREADY_INSTALLED = 0xBBE, + // The specified print monitor does not have the required functions. + INVALID_PRINT_MONITOR = 0xBBF, + // The specified print monitor is currently in use. + PRINT_MONITOR_IN_USE = 0xBC0, + // The requested operation is not allowed when there are jobs queued to the printer. + PRINTER_HAS_JOBS_QUEUED = 0xBC1, + // The requested operation is successful. Changes will not be effective until the system is rebooted. + SUCCESS_REBOOT_REQUIRED = 0xBC2, + // The requested operation is successful. Changes will not be effective until the service is restarted. + SUCCESS_RESTART_REQUIRED = 0xBC3, + // No printers were found. + PRINTER_NOT_FOUND = 0xBC4, + // The printer driver is known to be unreliable. + PRINTER_DRIVER_WARNED = 0xBC5, + // The printer driver is known to harm the system. + PRINTER_DRIVER_BLOCKED = 0xBC6, + // The specified printer driver package is currently in use. + PRINTER_DRIVER_PACKAGE_IN_USE = 0xBC7, + // Unable to find a core driver package that is required by the printer driver package. + CORE_DRIVER_PACKAGE_NOT_FOUND = 0xBC8, + // The requested operation failed. A system reboot is required to roll back changes made. + FAIL_REBOOT_REQUIRED = 0xBC9, + // The requested operation failed. A system reboot has been initiated to roll back changes made. + FAIL_REBOOT_INITIATED = 0xBCA, + // The specified printer driver was not found on the system and needs to be downloaded. + PRINTER_DRIVER_DOWNLOAD_NEEDED = 0xBCB, + // The requested print job has failed to print. A print system update requires the job to be resubmitted. + PRINT_JOB_RESTART_REQUIRED = 0xBCC, + // The printer driver does not contain a valid manifest, or contains too many manifests. + INVALID_PRINTER_DRIVER_MANIFEST = 0xBCD, + // The specified printer cannot be shared. + PRINTER_NOT_SHAREABLE = 0xBCE, + // The operation was paused. + REQUEST_PAUSED = 0xBEA, + // Reissue the given operation as a cached IO operation. + IO_REISSUE_AS_CACHED = 0xF6E, + + // WINS encountered an error while processing the command. + WINS_INTERNAL = 0xFA0, + // The local WINS cannot be deleted. + CAN_NOT_DEL_LOCAL_WINS = 0xFA1, + // The importation from the file failed. + STATIC_INIT = 0xFA2, + // The backup failed. Was a full backup done before? + INC_BACKUP = 0xFA3, + // The backup failed. Check the directory to which you are backing the database. + FULL_BACKUP = 0xFA4, + // The name does not exist in the WINS database. + REC_NON_EXISTENT = 0xFA5, + // Replication with a nonconfigured partner is not allowed. + RPL_NOT_ALLOWED = 0xFA6, + // The version of the supplied content information is not supported. + PEERDIST_ERROR_CONTENTINFO_VERSION_UNSUPPORTED = 0xFD2, + // The supplied content information is malformed. + PEERDIST_ERROR_CANNOT_PARSE_CONTENTINFO = 0xFD3, + // The requested data cannot be found in local or peer caches. + PEERDIST_ERROR_MISSING_DATA = 0xFD4, + // No more data is available or required. + PEERDIST_ERROR_NO_MORE = 0xFD5, + // The supplied object has not been initialized. + PEERDIST_ERROR_NOT_INITIALIZED = 0xFD6, + // The supplied object has already been initialized. + PEERDIST_ERROR_ALREADY_INITIALIZED = 0xFD7, + // A shutdown operation is already in progress. + PEERDIST_ERROR_SHUTDOWN_IN_PROGRESS = 0xFD8, + // The supplied object has already been invalidated. + PEERDIST_ERROR_INVALIDATED = 0xFD9, + // An element already exists and was not replaced. + PEERDIST_ERROR_ALREADY_EXISTS = 0xFDA, + // Cannot cancel the requested operation as it has already been completed. + PEERDIST_ERROR_OPERATION_NOTFOUND = 0xFDB, + // Can not perform the reqested operation because it has already been carried out. + PEERDIST_ERROR_ALREADY_COMPLETED = 0xFDC, + // An operation accessed data beyond the bounds of valid data. + PEERDIST_ERROR_OUT_OF_BOUNDS = 0xFDD, + // The requested version is not supported. + PEERDIST_ERROR_VERSION_UNSUPPORTED = 0xFDE, + // A configuration value is invalid. + PEERDIST_ERROR_INVALID_CONFIGURATION = 0xFDF, + // The SKU is not licensed. + PEERDIST_ERROR_NOT_LICENSED = 0xFE0, + // PeerDist Service is still initializing and will be available shortly. + PEERDIST_ERROR_SERVICE_UNAVAILABLE = 0xFE1, + // Communication with one or more computers will be temporarily blocked due to recent errors. + PEERDIST_ERROR_TRUST_FAILURE = 0xFE2, + // The DHCP client has obtained an IP address that is already in use on the network. The local interface will be disabled until the DHCP client can obtain a new address. + DHCP_ADDRESS_CONFLICT = 0x1004, + // The GUID passed was not recognized as valid by a WMI data provider. + WMI_GUID_NOT_FOUND = 0x1068, + // The instance name passed was not recognized as valid by a WMI data provider. + WMI_INSTANCE_NOT_FOUND = 0x1069, + // The data item ID passed was not recognized as valid by a WMI data provider. + WMI_ITEMID_NOT_FOUND = 0x106A, + // The WMI request could not be completed and should be retried. + WMI_TRY_AGAIN = 0x106B, + // The WMI data provider could not be located. + WMI_DP_NOT_FOUND = 0x106C, + // The WMI data provider references an instance set that has not been registered. + WMI_UNRESOLVED_INSTANCE_REF = 0x106D, + // The WMI data block or event notification has already been enabled. + WMI_ALREADY_ENABLED = 0x106E, + // The WMI data block is no longer available. + WMI_GUID_DISCONNECTED = 0x106F, + // The WMI data service is not available. + WMI_SERVER_UNAVAILABLE = 0x1070, + // The WMI data provider failed to carry out the request. + WMI_DP_FAILED = 0x1071, + // The WMI MOF information is not valid. + WMI_INVALID_MOF = 0x1072, + // The WMI registration information is not valid. + WMI_INVALID_REGINFO = 0x1073, + // The WMI data block or event notification has already been disabled. + WMI_ALREADY_DISABLED = 0x1074, + // The WMI data item or data block is read only. + WMI_READ_ONLY = 0x1075, + // The WMI data item or data block could not be changed. + WMI_SET_FAILURE = 0x1076, + // This operation is only valid in the context of an app container. + NOT_APPCONTAINER = 0x109A, + // This application can only run in the context of an app container. + APPCONTAINER_REQUIRED = 0x109B, + // This functionality is not supported in the context of an app container. + NOT_SUPPORTED_IN_APPCONTAINER = 0x109C, + // The length of the SID supplied is not a valid length for app container SIDs. + INVALID_PACKAGE_SID_LENGTH = 0x109D, + // The media identifier does not represent a valid medium. + INVALID_MEDIA = 0x10CC, + // The library identifier does not represent a valid library. + INVALID_LIBRARY = 0x10CD, + // The media pool identifier does not represent a valid media pool. + INVALID_MEDIA_POOL = 0x10CE, + // The drive and medium are not compatible or exist in different libraries. + DRIVE_MEDIA_MISMATCH = 0x10CF, + // The medium currently exists in an offline library and must be online to perform this operation. + MEDIA_OFFLINE = 0x10D0, + // The operation cannot be performed on an offline library. + LIBRARY_OFFLINE = 0x10D1, + // The library, drive, or media pool is empty. + EMPTY = 0x10D2, + // The library, drive, or media pool must be empty to perform this operation. + NOT_EMPTY = 0x10D3, + // No media is currently available in this media pool or library. + MEDIA_UNAVAILABLE = 0x10D4, + // A resource required for this operation is disabled. + RESOURCE_DISABLED = 0x10D5, + // The media identifier does not represent a valid cleaner. + INVALID_CLEANER = 0x10D6, + // The drive cannot be cleaned or does not support cleaning. + UNABLE_TO_CLEAN = 0x10D7, + // The object identifier does not represent a valid object. + OBJECT_NOT_FOUND = 0x10D8, + // Unable to read from or write to the database. + DATABASE_FAILURE = 0x10D9, + // The database is full. + DATABASE_FULL = 0x10DA, + // The medium is not compatible with the device or media pool. + MEDIA_INCOMPATIBLE = 0x10DB, + // The resource required for this operation does not exist. + RESOURCE_NOT_PRESENT = 0x10DC, + // The operation identifier is not valid. + INVALID_OPERATION = 0x10DD, + // The media is not mounted or ready for use. + MEDIA_NOT_AVAILABLE = 0x10DE, + // The device is not ready for use. + DEVICE_NOT_AVAILABLE = 0x10DF, + // The operator or administrator has refused the request. + REQUEST_REFUSED = 0x10E0, + // The drive identifier does not represent a valid drive. + INVALID_DRIVE_OBJECT = 0x10E1, + // Library is full. No slot is available for use. + LIBRARY_FULL = 0x10E2, + // The transport cannot access the medium. + MEDIUM_NOT_ACCESSIBLE = 0x10E3, + // Unable to load the medium into the drive. + UNABLE_TO_LOAD_MEDIUM = 0x10E4, + // Unable to retrieve the drive status. + UNABLE_TO_INVENTORY_DRIVE = 0x10E5, + // Unable to retrieve the slot status. + UNABLE_TO_INVENTORY_SLOT = 0x10E6, + // Unable to retrieve status about the transport. + UNABLE_TO_INVENTORY_TRANSPORT = 0x10E7, + // Cannot use the transport because it is already in use. + TRANSPORT_FULL = 0x10E8, + // Unable to open or close the inject/eject port. + CONTROLLING_IEPORT = 0x10E9, + // Unable to eject the medium because it is in a drive. + UNABLE_TO_EJECT_MOUNTED_MEDIA = 0x10EA, + // A cleaner slot is already reserved. + CLEANER_SLOT_SET = 0x10EB, + // A cleaner slot is not reserved. + CLEANER_SLOT_NOT_SET = 0x10EC, + // The cleaner cartridge has performed the maximum number of drive cleanings. + CLEANER_CARTRIDGE_SPENT = 0x10ED, + // Unexpected on-medium identifier. + UNEXPECTED_OMID = 0x10EE, + // The last remaining item in this group or resource cannot be deleted. + CANT_DELETE_LAST_ITEM = 0x10EF, + // The message provided exceeds the maximum size allowed for this parameter. + MESSAGE_EXCEEDS_MAX_SIZE = 0x10F0, + // The volume contains system or paging files. + VOLUME_CONTAINS_SYS_FILES = 0x10F1, + // The media type cannot be removed from this library since at least one drive in the library reports it can support this media type. + INDIGENOUS_TYPE = 0x10F2, + // This offline media cannot be mounted on this system since no enabled drives are present which can be used. + NO_SUPPORTING_DRIVES = 0x10F3, + // A cleaner cartridge is present in the tape library. + CLEANER_CARTRIDGE_INSTALLED = 0x10F4, + // Cannot use the inject/eject port because it is not empty. + IEPORT_FULL = 0x10F5, + // This file is currently not available for use on this computer. + FILE_OFFLINE = 0x10FE, + // The remote storage service is not operational at this time. + REMOTE_STORAGE_NOT_ACTIVE = 0x10FF, + // The remote storage service encountered a media error. + REMOTE_STORAGE_MEDIA_ERROR = 0x1100, + // The file or directory is not a reparse point. + NOT_A_REPARSE_POINT = 0x1126, + // The reparse point attribute cannot be set because it conflicts with an existing attribute. + REPARSE_ATTRIBUTE_CONFLICT = 0x1127, + // The data present in the reparse point buffer is invalid. + INVALID_REPARSE_DATA = 0x1128, + // The tag present in the reparse point buffer is invalid. + REPARSE_TAG_INVALID = 0x1129, + // There is a mismatch between the tag specified in the request and the tag present in the reparse point. + REPARSE_TAG_MISMATCH = 0x112A, + // Fast Cache data not found. + APP_DATA_NOT_FOUND = 0x1130, + // Fast Cache data expired. + APP_DATA_EXPIRED = 0x1131, + // Fast Cache data corrupt. + APP_DATA_CORRUPT = 0x1132, + // Fast Cache data has exceeded its max size and cannot be updated. + APP_DATA_LIMIT_EXCEEDED = 0x1133, + // Fast Cache has been ReArmed and requires a reboot until it can be updated. + APP_DATA_REBOOT_REQUIRED = 0x1134, + // Secure Boot detected that rollback of protected data has been attempted. + SECUREBOOT_ROLLBACK_DETECTED = 0x1144, + // The value is protected by Secure Boot policy and cannot be modified or deleted. + SECUREBOOT_POLICY_VIOLATION = 0x1145, + // The Secure Boot policy is invalid. + SECUREBOOT_INVALID_POLICY = 0x1146, + // A new Secure Boot policy did not contain the current publisher on its update list. + SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = 0x1147, + // The Secure Boot policy is either not signed or is signed by a non-trusted signer. + SECUREBOOT_POLICY_NOT_SIGNED = 0x1148, + // Secure Boot is not enabled on this machine. + SECUREBOOT_NOT_ENABLED = 0x1149, + // Secure Boot requires that certain files and drivers are not replaced by other files or drivers. + SECUREBOOT_FILE_REPLACED = 0x114A, + // The copy offload read operation is not supported by a filter. + OFFLOAD_READ_FLT_NOT_SUPPORTED = 0x1158, + // The copy offload write operation is not supported by a filter. + OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 0x1159, + // The copy offload read operation is not supported for the file. + OFFLOAD_READ_FILE_NOT_SUPPORTED = 0x115A, + // The copy offload write operation is not supported for the file. + OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 0x115B, + // Single Instance Storage is not available on this volume. + VOLUME_NOT_SIS_ENABLED = 0x1194, + // The operation cannot be completed because other resources are dependent on this resource. + DEPENDENT_RESOURCE_EXISTS = 0x1389, + // The cluster resource dependency cannot be found. + DEPENDENCY_NOT_FOUND = 0x138A, + // The cluster resource cannot be made dependent on the specified resource because it is already dependent. + DEPENDENCY_ALREADY_EXISTS = 0x138B, + // The cluster resource is not online. + RESOURCE_NOT_ONLINE = 0x138C, + // A cluster node is not available for this operation. + HOST_NODE_NOT_AVAILABLE = 0x138D, + // The cluster resource is not available. + RESOURCE_NOT_AVAILABLE = 0x138E, + // The cluster resource could not be found. + RESOURCE_NOT_FOUND = 0x138F, + // The cluster is being shut down. + SHUTDOWN_CLUSTER = 0x1390, + // A cluster node cannot be evicted from the cluster unless the node is down or it is the last node. + CANT_EVICT_ACTIVE_NODE = 0x1391, + // The object already exists. + OBJECT_ALREADY_EXISTS = 0x1392, + // The object is already in the list. + OBJECT_IN_LIST = 0x1393, + // The cluster group is not available for any new requests. + GROUP_NOT_AVAILABLE = 0x1394, + // The cluster group could not be found. + GROUP_NOT_FOUND = 0x1395, + // The operation could not be completed because the cluster group is not online. + GROUP_NOT_ONLINE = 0x1396, + // The operation failed because either the specified cluster node is not the owner of the resource, or the node is not a possible owner of the resource. + HOST_NODE_NOT_RESOURCE_OWNER = 0x1397, + // The operation failed because either the specified cluster node is not the owner of the group, or the node is not a possible owner of the group. + HOST_NODE_NOT_GROUP_OWNER = 0x1398, + // The cluster resource could not be created in the specified resource monitor. + RESMON_CREATE_FAILED = 0x1399, + // The cluster resource could not be brought online by the resource monitor. + RESMON_ONLINE_FAILED = 0x139A, + // The operation could not be completed because the cluster resource is online. + RESOURCE_ONLINE = 0x139B, + // The cluster resource could not be deleted or brought offline because it is the quorum resource. + QUORUM_RESOURCE = 0x139C, + // The cluster could not make the specified resource a quorum resource because it is not capable of being a quorum resource. + NOT_QUORUM_CAPABLE = 0x139D, + // The cluster software is shutting down. + CLUSTER_SHUTTING_DOWN = 0x139E, + // The group or resource is not in the correct state to perform the requested operation. + INVALID_STATE = 0x139F, + // The properties were stored but not all changes will take effect until the next time the resource is brought online. + RESOURCE_PROPERTIES_STORED = 0x13A0, + // The cluster could not make the specified resource a quorum resource because it does not belong to a shared storage class. + NOT_QUORUM_CLASS = 0x13A1, + // The cluster resource could not be deleted since it is a core resource. + CORE_RESOURCE = 0x13A2, + // The quorum resource failed to come online. + QUORUM_RESOURCE_ONLINE_FAILED = 0x13A3, + // The quorum log could not be created or mounted successfully. + QUORUMLOG_OPEN_FAILED = 0x13A4, + // The cluster log is corrupt. + CLUSTERLOG_CORRUPT = 0x13A5, + // The record could not be written to the cluster log since it exceeds the maximum size. + CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE = 0x13A6, + // The cluster log exceeds its maximum size. + CLUSTERLOG_EXCEEDS_MAXSIZE = 0x13A7, + // No checkpoint record was found in the cluster log. + CLUSTERLOG_CHKPOINT_NOT_FOUND = 0x13A8, + // The minimum required disk space needed for logging is not available. + CLUSTERLOG_NOT_ENOUGH_SPACE = 0x13A9, + // The cluster node failed to take control of the quorum resource because the resource is owned by another active node. + QUORUM_OWNER_ALIVE = 0x13AA, + // A cluster network is not available for this operation. + NETWORK_NOT_AVAILABLE = 0x13AB, + // A cluster node is not available for this operation. + NODE_NOT_AVAILABLE = 0x13AC, + // All cluster nodes must be running to perform this operation. + ALL_NODES_NOT_AVAILABLE = 0x13AD, + // A cluster resource failed. + RESOURCE_FAILED = 0x13AE, + // The cluster node is not valid. + CLUSTER_INVALID_NODE = 0x13AF, + // The cluster node already exists. + CLUSTER_NODE_EXISTS = 0x13B0, + // A node is in the process of joining the cluster. + CLUSTER_JOIN_IN_PROGRESS = 0x13B1, + // The cluster node was not found. + CLUSTER_NODE_NOT_FOUND = 0x13B2, + // The cluster local node information was not found. + CLUSTER_LOCAL_NODE_NOT_FOUND = 0x13B3, + // The cluster network already exists. + CLUSTER_NETWORK_EXISTS = 0x13B4, + // The cluster network was not found. + CLUSTER_NETWORK_NOT_FOUND = 0x13B5, + // The cluster network interface already exists. + CLUSTER_NETINTERFACE_EXISTS = 0x13B6, + // The cluster network interface was not found. + CLUSTER_NETINTERFACE_NOT_FOUND = 0x13B7, + // The cluster request is not valid for this object. + CLUSTER_INVALID_REQUEST = 0x13B8, + // The cluster network provider is not valid. + CLUSTER_INVALID_NETWORK_PROVIDER = 0x13B9, + // The cluster node is down. + CLUSTER_NODE_DOWN = 0x13BA, + // The cluster node is not reachable. + CLUSTER_NODE_UNREACHABLE = 0x13BB, + // The cluster node is not a member of the cluster. + CLUSTER_NODE_NOT_MEMBER = 0x13BC, + // A cluster join operation is not in progress. + CLUSTER_JOIN_NOT_IN_PROGRESS = 0x13BD, + // The cluster network is not valid. + CLUSTER_INVALID_NETWORK = 0x13BE, + // The cluster node is up. + CLUSTER_NODE_UP = 0x13C0, + // The cluster IP address is already in use. + CLUSTER_IPADDR_IN_USE = 0x13C1, + // The cluster node is not paused. + CLUSTER_NODE_NOT_PAUSED = 0x13C2, + // No cluster security context is available. + CLUSTER_NO_SECURITY_CONTEXT = 0x13C3, + // The cluster network is not configured for internal cluster communication. + CLUSTER_NETWORK_NOT_INTERNAL = 0x13C4, + // The cluster node is already up. + CLUSTER_NODE_ALREADY_UP = 0x13C5, + // The cluster node is already down. + CLUSTER_NODE_ALREADY_DOWN = 0x13C6, + // The cluster network is already online. + CLUSTER_NETWORK_ALREADY_ONLINE = 0x13C7, + // The cluster network is already offline. + CLUSTER_NETWORK_ALREADY_OFFLINE = 0x13C8, + // The cluster node is already a member of the cluster. + CLUSTER_NODE_ALREADY_MEMBER = 0x13C9, + // The cluster network is the only one configured for internal cluster communication between two or more active cluster nodes. The internal communication capability cannot be removed from the network. + CLUSTER_LAST_INTERNAL_NETWORK = 0x13CA, + // One or more cluster resources depend on the network to provide service to clients. The client access capability cannot be removed from the network. + CLUSTER_NETWORK_HAS_DEPENDENTS = 0x13CB, + // This operation cannot be performed on the cluster resource as it the quorum resource. You may not bring the quorum resource offline or modify its possible owners list. + INVALID_OPERATION_ON_QUORUM = 0x13CC, + // The cluster quorum resource is not allowed to have any dependencies. + DEPENDENCY_NOT_ALLOWED = 0x13CD, + // The cluster node is paused. + CLUSTER_NODE_PAUSED = 0x13CE, + // The cluster resource cannot be brought online. The owner node cannot run this resource. + NODE_CANT_HOST_RESOURCE = 0x13CF, + // The cluster node is not ready to perform the requested operation. + CLUSTER_NODE_NOT_READY = 0x13D0, + // The cluster node is shutting down. + CLUSTER_NODE_SHUTTING_DOWN = 0x13D1, + // The cluster join operation was aborted. + CLUSTER_JOIN_ABORTED = 0x13D2, + // The cluster join operation failed due to incompatible software versions between the joining node and its sponsor. + CLUSTER_INCOMPATIBLE_VERSIONS = 0x13D3, + // This resource cannot be created because the cluster has reached the limit on the number of resources it can monitor. + CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED = 0x13D4, + // The system configuration changed during the cluster join or form operation. The join or form operation was aborted. + CLUSTER_SYSTEM_CONFIG_CHANGED = 0x13D5, + // The specified resource type was not found. + CLUSTER_RESOURCE_TYPE_NOT_FOUND = 0x13D6, + // The specified node does not support a resource of this type. This may be due to version inconsistencies or due to the absence of the resource DLL on this node. + CLUSTER_RESTYPE_NOT_SUPPORTED = 0x13D7, + // The specified resource name is not supported by this resource DLL. This may be due to a bad (or changed) name supplied to the resource DLL. + CLUSTER_RESNAME_NOT_FOUND = 0x13D8, + // No authentication package could be registered with the RPC server. + CLUSTER_NO_RPC_PACKAGES_REGISTERED = 0x13D9, + // You cannot bring the group online because the owner of the group is not in the preferred list for the group. To change the owner node for the group, move the group. + CLUSTER_OWNER_NOT_IN_PREFLIST = 0x13DA, + // The join operation failed because the cluster database sequence number has changed or is incompatible with the locker node. This may happen during a join operation if the cluster database was changing during the join. + CLUSTER_DATABASE_SEQMISMATCH = 0x13DB, + // The resource monitor will not allow the fail operation to be performed while the resource is in its current state. This may happen if the resource is in a pending state. + RESMON_INVALID_STATE = 0x13DC, + // A non locker code got a request to reserve the lock for making global updates. + CLUSTER_GUM_NOT_LOCKER = 0x13DD, + // The quorum disk could not be located by the cluster service. + QUORUM_DISK_NOT_FOUND = 0x13DE, + // The backed up cluster database is possibly corrupt. + DATABASE_BACKUP_CORRUPT = 0x13DF, + // A DFS root already exists in this cluster node. + CLUSTER_NODE_ALREADY_HAS_DFS_ROOT = 0x13E0, + // An attempt to modify a resource property failed because it conflicts with another existing property. + RESOURCE_PROPERTY_UNCHANGEABLE = 0x13E1, + // An operation was attempted that is incompatible with the current membership state of the node. + CLUSTER_MEMBERSHIP_INVALID_STATE = 0x1702, + // The quorum resource does not contain the quorum log. + CLUSTER_QUORUMLOG_NOT_FOUND = 0x1703, + // The membership engine requested shutdown of the cluster service on this node. + CLUSTER_MEMBERSHIP_HALT = 0x1704, + // The join operation failed because the cluster instance ID of the joining node does not match the cluster instance ID of the sponsor node. + CLUSTER_INSTANCE_ID_MISMATCH = 0x1705, + // A matching cluster network for the specified IP address could not be found. + CLUSTER_NETWORK_NOT_FOUND_FOR_IP = 0x1706, + // The actual data type of the property did not match the expected data type of the property. + CLUSTER_PROPERTY_DATA_TYPE_MISMATCH = 0x1707, + // The cluster node was evicted from the cluster successfully, but the node was not cleaned up. To determine what cleanup steps failed and how to recover, see the Failover Clustering application event log using Event Viewer. + CLUSTER_EVICT_WITHOUT_CLEANUP = 0x1708, + // Two or more parameter values specified for a resource's properties are in conflict. + CLUSTER_PARAMETER_MISMATCH = 0x1709, + // This computer cannot be made a member of a cluster. + NODE_CANNOT_BE_CLUSTERED = 0x170A, + // This computer cannot be made a member of a cluster because it does not have the correct version of Windows installed. + CLUSTER_WRONG_OS_VERSION = 0x170B, + // A cluster cannot be created with the specified cluster name because that cluster name is already in use. Specify a different name for the cluster. + CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME = 0x170C, + // The cluster configuration action has already been committed. + CLUSCFG_ALREADY_COMMITTED = 0x170D, + // The cluster configuration action could not be rolled back. + CLUSCFG_ROLLBACK_FAILED = 0x170E, + // The drive letter assigned to a system disk on one node conflicted with the drive letter assigned to a disk on another node. + CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT = 0x170F, + // One or more nodes in the cluster are running a version of Windows that does not support this operation. + CLUSTER_OLD_VERSION = 0x1710, + // The name of the corresponding computer account doesn't match the Network Name for this resource. + CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME = 0x1711, + // No network adapters are available. + CLUSTER_NO_NET_ADAPTERS = 0x1712, + // The cluster node has been poisoned. + CLUSTER_POISONED = 0x1713, + // The group is unable to accept the request since it is moving to another node. + CLUSTER_GROUP_MOVING = 0x1714, + // The resource type cannot accept the request since is too busy performing another operation. + CLUSTER_RESOURCE_TYPE_BUSY = 0x1715, + // The call to the cluster resource DLL timed out. + RESOURCE_CALL_TIMED_OUT = 0x1716, + // The address is not valid for an IPv6 Address resource. A global IPv6 address is required, and it must match a cluster network. Compatibility addresses are not permitted. + INVALID_CLUSTER_IPV6_ADDRESS = 0x1717, + // An internal cluster error occurred. A call to an invalid function was attempted. + CLUSTER_INTERNAL_INVALID_FUNCTION = 0x1718, + // A parameter value is out of acceptable range. + CLUSTER_PARAMETER_OUT_OF_BOUNDS = 0x1719, + // A network error occurred while sending data to another node in the cluster. The number of bytes transmitted was less than required. + CLUSTER_PARTIAL_SEND = 0x171A, + // An invalid cluster registry operation was attempted. + CLUSTER_REGISTRY_INVALID_FUNCTION = 0x171B, + // An input string of characters is not properly terminated. + CLUSTER_INVALID_STRING_TERMINATION = 0x171C, + // An input string of characters is not in a valid format for the data it represents. + CLUSTER_INVALID_STRING_FORMAT = 0x171D, + // An internal cluster error occurred. A cluster database transaction was attempted while a transaction was already in progress. + CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS = 0x171E, + // An internal cluster error occurred. There was an attempt to commit a cluster database transaction while no transaction was in progress. + CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS = 0x171F, + // An internal cluster error occurred. Data was not properly initialized. + CLUSTER_NULL_DATA = 0x1720, + // An error occurred while reading from a stream of data. An unexpected number of bytes was returned. + CLUSTER_PARTIAL_READ = 0x1721, + // An error occurred while writing to a stream of data. The required number of bytes could not be written. + CLUSTER_PARTIAL_WRITE = 0x1722, + // An error occurred while deserializing a stream of cluster data. + CLUSTER_CANT_DESERIALIZE_DATA = 0x1723, + // One or more property values for this resource are in conflict with one or more property values associated with its dependent resource(s). + DEPENDENT_RESOURCE_PROPERTY_CONFLICT = 0x1724, + // A quorum of cluster nodes was not present to form a cluster. + CLUSTER_NO_QUORUM = 0x1725, + // The cluster network is not valid for an IPv6 Address resource, or it does not match the configured address. + CLUSTER_INVALID_IPV6_NETWORK = 0x1726, + // The cluster network is not valid for an IPv6 Tunnel resource. Check the configuration of the IP Address resource on which the IPv6 Tunnel resource depends. + CLUSTER_INVALID_IPV6_TUNNEL_NETWORK = 0x1727, + // Quorum resource cannot reside in the Available Storage group. + QUORUM_NOT_ALLOWED_IN_THIS_GROUP = 0x1728, + // The dependencies for this resource are nested too deeply. + DEPENDENCY_TREE_TOO_COMPLEX = 0x1729, + // The call into the resource DLL raised an unhandled exception. + EXCEPTION_IN_RESOURCE_CALL = 0x172A, + // The RHS process failed to initialize. + CLUSTER_RHS_FAILED_INITIALIZATION = 0x172B, + // The Failover Clustering feature is not installed on this node. + CLUSTER_NOT_INSTALLED = 0x172C, + // The resources must be online on the same node for this operation. + CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE = 0x172D, + // A new node can not be added since this cluster is already at its maximum number of nodes. + CLUSTER_MAX_NODES_IN_CLUSTER = 0x172E, + // This cluster can not be created since the specified number of nodes exceeds the maximum allowed limit. + CLUSTER_TOO_MANY_NODES = 0x172F, + // An attempt to use the specified cluster name failed because an enabled computer object with the given name already exists in the domain. + CLUSTER_OBJECT_ALREADY_USED = 0x1730, + // This cluster cannot be destroyed. It has non-core application groups which must be deleted before the cluster can be destroyed. + NONCORE_GROUPS_FOUND = 0x1731, + // File share associated with file share witness resource cannot be hosted by this cluster or any of its nodes. + FILE_SHARE_RESOURCE_CONFLICT = 0x1732, + // Eviction of this node is invalid at this time. Due to quorum requirements node eviction will result in cluster shutdown. If it is the last node in the cluster, destroy cluster command should be used. + CLUSTER_EVICT_INVALID_REQUEST = 0x1733, + // Only one instance of this resource type is allowed in the cluster. + CLUSTER_SINGLETON_RESOURCE = 0x1734, + // Only one instance of this resource type is allowed per resource group. + CLUSTER_GROUP_SINGLETON_RESOURCE = 0x1735, + // The resource failed to come online due to the failure of one or more provider resources. + CLUSTER_RESOURCE_PROVIDER_FAILED = 0x1736, + // The resource has indicated that it cannot come online on any node. + CLUSTER_RESOURCE_CONFIGURATION_ERROR = 0x1737, + // The current operation cannot be performed on this group at this time. + CLUSTER_GROUP_BUSY = 0x1738, + // The directory or file is not located on a cluster shared volume. + CLUSTER_NOT_SHARED_VOLUME = 0x1739, + // The Security Descriptor does not meet the requirements for a cluster. + CLUSTER_INVALID_SECURITY_DESCRIPTOR = 0x173A, + // There is one or more shared volumes resources configured in the cluster. Those resources must be moved to available storage in order for operation to succeed. + CLUSTER_SHARED_VOLUMES_IN_USE = 0x173B, + // This group or resource cannot be directly manipulated. Use shared volume APIs to perform desired operation. + CLUSTER_USE_SHARED_VOLUMES_API = 0x173C, + // Back up is in progress. Please wait for backup completion before trying this operation again. + CLUSTER_BACKUP_IN_PROGRESS = 0x173D, + // The path does not belong to a cluster shared volume. + NON_CSV_PATH = 0x173E, + // The cluster shared volume is not locally mounted on this node. + CSV_VOLUME_NOT_LOCAL = 0x173F, + // The cluster watchdog is terminating. + CLUSTER_WATCHDOG_TERMINATING = 0x1740, + // A resource vetoed a move between two nodes because they are incompatible. + CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES = 0x1741, + // The request is invalid either because node weight cannot be changed while the cluster is in disk-only quorum mode, or because changing the node weight would violate the minimum cluster quorum requirements. + CLUSTER_INVALID_NODE_WEIGHT = 0x1742, + // The resource vetoed the call. + CLUSTER_RESOURCE_VETOED_CALL = 0x1743, + // Resource could not start or run because it could not reserve sufficient system resources. + RESMON_SYSTEM_RESOURCES_LACKING = 0x1744, + // A resource vetoed a move between two nodes because the destination currently does not have enough resources to complete the operation. + CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION = 0x1745, + // A resource vetoed a move between two nodes because the source currently does not have enough resources to complete the operation. + CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE = 0x1746, + // The requested operation can not be completed because the group is queued for an operation. + CLUSTER_GROUP_QUEUED = 0x1747, + // The requested operation can not be completed because a resource has locked status. + CLUSTER_RESOURCE_LOCKED_STATUS = 0x1748, + // The resource cannot move to another node because a cluster shared volume vetoed the operation. + CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED = 0x1749, + // A node drain is already in progress. + // This value was also named ERROR_CLUSTER_NODE_EVACUATION_IN_PROGRESS + CLUSTER_NODE_DRAIN_IN_PROGRESS = 0x174A, + // Clustered storage is not connected to the node. + CLUSTER_DISK_NOT_CONNECTED = 0x174B, + // The disk is not configured in a way to be used with CSV. CSV disks must have at least one partition that is formatted with NTFS. + DISK_NOT_CSV_CAPABLE = 0x174C, + // The resource must be part of the Available Storage group to complete this action. + RESOURCE_NOT_IN_AVAILABLE_STORAGE = 0x174D, + // CSVFS failed operation as volume is in redirected mode. + CLUSTER_SHARED_VOLUME_REDIRECTED = 0x174E, + // CSVFS failed operation as volume is not in redirected mode. + CLUSTER_SHARED_VOLUME_NOT_REDIRECTED = 0x174F, + // Cluster properties cannot be returned at this time. + CLUSTER_CANNOT_RETURN_PROPERTIES = 0x1750, + // The clustered disk resource contains software snapshot diff area that are not supported for Cluster Shared Volumes. + CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES = 0x1751, + // The operation cannot be completed because the resource is in maintenance mode. + CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE = 0x1752, + // The operation cannot be completed because of cluster affinity conflicts. + CLUSTER_AFFINITY_CONFLICT = 0x1753, + // The operation cannot be completed because the resource is a replica virtual machine. + CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE = 0x1754, + + // The specified file could not be encrypted. + ENCRYPTION_FAILED = 0x1770, + // The specified file could not be decrypted. + DECRYPTION_FAILED = 0x1771, + // The specified file is encrypted and the user does not have the ability to decrypt it. + FILE_ENCRYPTED = 0x1772, + // There is no valid encryption recovery policy configured for this system. + NO_RECOVERY_POLICY = 0x1773, + // The required encryption driver is not loaded for this system. + NO_EFS = 0x1774, + // The file was encrypted with a different encryption driver than is currently loaded. + WRONG_EFS = 0x1775, + // There are no EFS keys defined for the user. + NO_USER_KEYS = 0x1776, + // The specified file is not encrypted. + FILE_NOT_ENCRYPTED = 0x1777, + // The specified file is not in the defined EFS export format. + NOT_EXPORT_FORMAT = 0x1778, + // The specified file is read only. + FILE_READ_ONLY = 0x1779, + // The directory has been disabled for encryption. + DIR_EFS_DISALLOWED = 0x177A, + // The server is not trusted for remote encryption operation. + EFS_SERVER_NOT_TRUSTED = 0x177B, + // Recovery policy configured for this system contains invalid recovery certificate. + BAD_RECOVERY_POLICY = 0x177C, + // The encryption algorithm used on the source file needs a bigger key buffer than the one on the destination file. + EFS_ALG_BLOB_TOO_BIG = 0x177D, + // The disk partition does not support file encryption. + VOLUME_NOT_SUPPORT_EFS = 0x177E, + // This machine is disabled for file encryption. + EFS_DISABLED = 0x177F, + // A newer system is required to decrypt this encrypted file. + EFS_VERSION_NOT_SUPPORT = 0x1780, + // The remote server sent an invalid response for a file being opened with Client Side Encryption. + CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 0x1781, + // Client Side Encryption is not supported by the remote server even though it claims to support it. + CS_ENCRYPTION_UNSUPPORTED_SERVER = 0x1782, + // File is encrypted and should be opened in Client Side Encryption mode. + CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 0x1783, + // A new encrypted file is being created and a $EFS needs to be provided. + CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 0x1784, + // The SMB client requested a CSE FSCTL on a non-CSE file. + CS_ENCRYPTION_FILE_NOT_CSE = 0x1785, + // The requested operation was blocked by policy. For more information, contact your system administrator. + ENCRYPTION_POLICY_DENIES_OPERATION = 0x1786, + // The list of servers for this workgroup is not currently available. + NO_BROWSER_SERVERS_FOUND = 0x17E6, + // The Task Scheduler service must be configured to run in the System account to function properly. Individual tasks may be configured to run in other accounts. + SCHED_E_SERVICE_NOT_LOCALSYSTEM = 0x1838, + // Log service encountered an invalid log sector. + LOG_SECTOR_INVALID = 0x19C8, + // Log service encountered a log sector with invalid block parity. + LOG_SECTOR_PARITY_INVALID = 0x19C9, + // Log service encountered a remapped log sector. + LOG_SECTOR_REMAPPED = 0x19CA, + // Log service encountered a partial or incomplete log block. + LOG_BLOCK_INCOMPLETE = 0x19CB, + // Log service encountered an attempt access data outside the active log range. + LOG_INVALID_RANGE = 0x19CC, + // Log service user marshalling buffers are exhausted. + LOG_BLOCKS_EXHAUSTED = 0x19CD, + // Log service encountered an attempt read from a marshalling area with an invalid read context. + LOG_READ_CONTEXT_INVALID = 0x19CE, + // Log service encountered an invalid log restart area. + LOG_RESTART_INVALID = 0x19CF, + // Log service encountered an invalid log block version. + LOG_BLOCK_VERSION = 0x19D0, + // Log service encountered an invalid log block. + LOG_BLOCK_INVALID = 0x19D1, + // Log service encountered an attempt to read the log with an invalid read mode. + LOG_READ_MODE_INVALID = 0x19D2, + // Log service encountered a log stream with no restart area. + LOG_NO_RESTART = 0x19D3, + // Log service encountered a corrupted metadata file. + LOG_METADATA_CORRUPT = 0x19D4, + // Log service encountered a metadata file that could not be created by the log file system. + LOG_METADATA_INVALID = 0x19D5, + // Log service encountered a metadata file with inconsistent data. + LOG_METADATA_INCONSISTENT = 0x19D6, + // Log service encountered an attempt to erroneous allocate or dispose reservation space. + LOG_RESERVATION_INVALID = 0x19D7, + // Log service cannot delete log file or file system container. + LOG_CANT_DELETE = 0x19D8, + // Log service has reached the maximum allowable containers allocated to a log file. + LOG_CONTAINER_LIMIT_EXCEEDED = 0x19D9, + // Log service has attempted to read or write backward past the start of the log. + LOG_START_OF_LOG = 0x19DA, + // Log policy could not be installed because a policy of the same type is already present. + LOG_POLICY_ALREADY_INSTALLED = 0x19DB, + // Log policy in question was not installed at the time of the request. + LOG_POLICY_NOT_INSTALLED = 0x19DC, + // The installed set of policies on the log is invalid. + LOG_POLICY_INVALID = 0x19DD, + // A policy on the log in question prevented the operation from completing. + LOG_POLICY_CONFLICT = 0x19DE, + // Log space cannot be reclaimed because the log is pinned by the archive tail. + LOG_PINNED_ARCHIVE_TAIL = 0x19DF, + // Log record is not a record in the log file. + LOG_RECORD_NONEXISTENT = 0x19E0, + // Number of reserved log records or the adjustment of the number of reserved log records is invalid. + LOG_RECORDS_RESERVED_INVALID = 0x19E1, + // Reserved log space or the adjustment of the log space is invalid. + LOG_SPACE_RESERVED_INVALID = 0x19E2, + // An new or existing archive tail or base of the active log is invalid. + LOG_TAIL_INVALID = 0x19E3, + // Log space is exhausted. + LOG_FULL = 0x19E4, + // The log could not be set to the requested size. + COULD_NOT_RESIZE_LOG = 0x19E5, + // Log is multiplexed, no direct writes to the physical log is allowed. + LOG_MULTIPLEXED = 0x19E6, + // The operation failed because the log is a dedicated log. + LOG_DEDICATED = 0x19E7, + // The operation requires an archive context. + LOG_ARCHIVE_NOT_IN_PROGRESS = 0x19E8, + // Log archival is in progress. + LOG_ARCHIVE_IN_PROGRESS = 0x19E9, + // The operation requires a non-ephemeral log, but the log is ephemeral. + LOG_EPHEMERAL = 0x19EA, + // The log must have at least two containers before it can be read from or written to. + LOG_NOT_ENOUGH_CONTAINERS = 0x19EB, + // A log client has already registered on the stream. + LOG_CLIENT_ALREADY_REGISTERED = 0x19EC, + // A log client has not been registered on the stream. + LOG_CLIENT_NOT_REGISTERED = 0x19ED, + // A request has already been made to handle the log full condition. + LOG_FULL_HANDLER_IN_PROGRESS = 0x19EE, + // Log service encountered an error when attempting to read from a log container. + LOG_CONTAINER_READ_FAILED = 0x19EF, + // Log service encountered an error when attempting to write to a log container. + LOG_CONTAINER_WRITE_FAILED = 0x19F0, + // Log service encountered an error when attempting open a log container. + LOG_CONTAINER_OPEN_FAILED = 0x19F1, + // Log service encountered an invalid container state when attempting a requested action. + LOG_CONTAINER_STATE_INVALID = 0x19F2, + // Log service is not in the correct state to perform a requested action. + LOG_STATE_INVALID = 0x19F3, + // Log space cannot be reclaimed because the log is pinned. + LOG_PINNED = 0x19F4, + // Log metadata flush failed. + LOG_METADATA_FLUSH_FAILED = 0x19F5, + // Security on the log and its containers is inconsistent. + LOG_INCONSISTENT_SECURITY = 0x19F6, + // Records were appended to the log or reservation changes were made, but the log could not be flushed. + LOG_APPENDED_FLUSH_FAILED = 0x19F7, + // The log is pinned due to reservation consuming most of the log space. Free some reserved records to make space available. + LOG_PINNED_RESERVATION = 0x19F8, + // The transaction handle associated with this operation is not valid. + INVALID_TRANSACTION = 0x1A2C, + // The requested operation was made in the context of a transaction that is no longer active. + TRANSACTION_NOT_ACTIVE = 0x1A2D, + // The requested operation is not valid on the Transaction object in its current state. + TRANSACTION_REQUEST_NOT_VALID = 0x1A2E, + // The caller has called a response API, but the response is not expected because the TM did not issue the corresponding request to the caller. + TRANSACTION_NOT_REQUESTED = 0x1A2F, + // It is too late to perform the requested operation, since the Transaction has already been aborted. + TRANSACTION_ALREADY_ABORTED = 0x1A30, + // It is too late to perform the requested operation, since the Transaction has already been committed. + TRANSACTION_ALREADY_COMMITTED = 0x1A31, + // The Transaction Manager was unable to be successfully initialized. Transacted operations are not supported. + TM_INITIALIZATION_FAILED = 0x1A32, + // The specified ResourceManager made no changes or updates to the resource under this transaction. + RESOURCEMANAGER_READ_ONLY = 0x1A33, + // The resource manager has attempted to prepare a transaction that it has not successfully joined. + TRANSACTION_NOT_JOINED = 0x1A34, + // The Transaction object already has a superior enlistment, and the caller attempted an operation that would have created a new superior. Only a single superior enlistment is allow. + TRANSACTION_SUPERIOR_EXISTS = 0x1A35, + // The RM tried to register a protocol that already exists. + CRM_PROTOCOL_ALREADY_EXISTS = 0x1A36, + // The attempt to propagate the Transaction failed. + TRANSACTION_PROPAGATION_FAILED = 0x1A37, + // The requested propagation protocol was not registered as a CRM. + CRM_PROTOCOL_NOT_FOUND = 0x1A38, + // The buffer passed in to PushTransaction or PullTransaction is not in a valid format. + TRANSACTION_INVALID_MARSHALL_BUFFER = 0x1A39, + // The current transaction context associated with the thread is not a valid handle to a transaction object. + CURRENT_TRANSACTION_NOT_VALID = 0x1A3A, + // The specified Transaction object could not be opened, because it was not found. + TRANSACTION_NOT_FOUND = 0x1A3B, + // The specified ResourceManager object could not be opened, because it was not found. + RESOURCEMANAGER_NOT_FOUND = 0x1A3C, + // The specified Enlistment object could not be opened, because it was not found. + ENLISTMENT_NOT_FOUND = 0x1A3D, + // The specified TransactionManager object could not be opened, because it was not found. + TRANSACTIONMANAGER_NOT_FOUND = 0x1A3E, + // The object specified could not be created or opened, because its associated TransactionManager is not online. The TransactionManager must be brought fully Online by calling RecoverTransactionManager to recover to the end of its LogFile before objects in its Transaction or ResourceManager namespaces can be opened. In addition, errors in writing records to its LogFile can cause a TransactionManager to go offline. + TRANSACTIONMANAGER_NOT_ONLINE = 0x1A3F, + // The specified TransactionManager was unable to create the objects contained in its logfile in the Ob namespace. Therefore, the TransactionManager was unable to recover. + TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 0x1A40, + // The call to create a superior Enlistment on this Transaction object could not be completed, because the Transaction object specified for the enlistment is a subordinate branch of the Transaction. Only the root of the Transaction can be enlisted on as a superior. + TRANSACTION_NOT_ROOT = 0x1A41, + // Because the associated transaction manager or resource manager has been closed, the handle is no longer valid. + TRANSACTION_OBJECT_EXPIRED = 0x1A42, + // The specified operation could not be performed on this Superior enlistment, because the enlistment was not created with the corresponding completion response in the NotificationMask. + TRANSACTION_RESPONSE_NOT_ENLISTED = 0x1A43, + // The specified operation could not be performed, because the record that would be logged was too long. This can occur because of two conditions: either there are too many Enlistments on this Transaction, or the combined RecoveryInformation being logged on behalf of those Enlistments is too long. + TRANSACTION_RECORD_TOO_LONG = 0x1A44, + // Implicit transaction are not supported. + IMPLICIT_TRANSACTION_NOT_SUPPORTED = 0x1A45, + // The kernel transaction manager had to abort or forget the transaction because it blocked forward progress. + TRANSACTION_INTEGRITY_VIOLATED = 0x1A46, + // The TransactionManager identity that was supplied did not match the one recorded in the TransactionManager's log file. + TRANSACTIONMANAGER_IDENTITY_MISMATCH = 0x1A47, + // This snapshot operation cannot continue because a transactional resource manager cannot be frozen in its current state. Please try again. + RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT = 0x1A48, + // The transaction cannot be enlisted on with the specified EnlistmentMask, because the transaction has already completed the PrePrepare phase. In order to ensure correctness, the ResourceManager must switch to a write- through mode and cease caching data within this transaction. Enlisting for only subsequent transaction phases may still succeed. + TRANSACTION_MUST_WRITETHROUGH = 0x1A49, + // The transaction does not have a superior enlistment. + TRANSACTION_NO_SUPERIOR = 0x1A4A, + // The attempt to commit the Transaction completed, but it is possible that some portion of the transaction tree did not commit successfully due to heuristics. Therefore it is possible that some data modified in the transaction may not have committed, resulting in transactional inconsistency. If possible, check the consistency of the associated data. + HEURISTIC_DAMAGE_POSSIBLE = 0x1A4B, + // The function attempted to use a name that is reserved for use by another transaction. + TRANSACTIONAL_CONFLICT = 0x1A90, + // Transaction support within the specified resource manager is not started or was shut down due to an error. + RM_NOT_ACTIVE = 0x1A91, + // The metadata of the RM has been corrupted. The RM will not function. + RM_METADATA_CORRUPT = 0x1A92, + // The specified directory does not contain a resource manager. + DIRECTORY_NOT_RM = 0x1A93, + // The remote server or share does not support transacted file operations. + TRANSACTIONS_UNSUPPORTED_REMOTE = 0x1A95, + // The requested log size is invalid. + LOG_RESIZE_INVALID_SIZE = 0x1A96, + // The object (file, stream, link) corresponding to the handle has been deleted by a Transaction Savepoint Rollback. + OBJECT_NO_LONGER_EXISTS = 0x1A97, + // The specified file miniversion was not found for this transacted file open. + STREAM_MINIVERSION_NOT_FOUND = 0x1A98, + // The specified file miniversion was found but has been invalidated. Most likely cause is a transaction savepoint rollback. + STREAM_MINIVERSION_NOT_VALID = 0x1A99, + // A miniversion may only be opened in the context of the transaction that created it. + MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 0x1A9A, + // It is not possible to open a miniversion with modify access. + CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 0x1A9B, + // It is not possible to create any more miniversions for this stream. + CANT_CREATE_MORE_STREAM_MINIVERSIONS = 0x1A9C, + // The remote server sent mismatching version number or Fid for a file opened with transactions. + REMOTE_FILE_VERSION_MISMATCH = 0x1A9E, + // The handle has been invalidated by a transaction. The most likely cause is the presence of memory mapping on a file or an open handle when the transaction ended or rolled back to savepoint. + HANDLE_NO_LONGER_VALID = 0x1A9F, + // There is no transaction metadata on the file. + NO_TXF_METADATA = 0x1AA0, + // The log data is corrupt. + LOG_CORRUPTION_DETECTED = 0x1AA1, + // The file can't be recovered because there is a handle still open on it. + CANT_RECOVER_WITH_HANDLE_OPEN = 0x1AA2, + // The transaction outcome is unavailable because the resource manager responsible for it has disconnected. + RM_DISCONNECTED = 0x1AA3, + // The request was rejected because the enlistment in question is not a superior enlistment. + ENLISTMENT_NOT_SUPERIOR = 0x1AA4, + // The transactional resource manager is already consistent. Recovery is not needed. + RECOVERY_NOT_NEEDED = 0x1AA5, + // The transactional resource manager has already been started. + RM_ALREADY_STARTED = 0x1AA6, + // The file cannot be opened transactionally, because its identity depends on the outcome of an unresolved transaction. + FILE_IDENTITY_NOT_PERSISTENT = 0x1AA7, + // The operation cannot be performed because another transaction is depending on the fact that this property will not change. + CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 0x1AA8, + // The operation would involve a single file with two transactional resource managers and is therefore not allowed. + CANT_CROSS_RM_BOUNDARY = 0x1AA9, + // The $Txf directory must be empty for this operation to succeed. + TXF_DIR_NOT_EMPTY = 0x1AAA, + // The operation would leave a transactional resource manager in an inconsistent state and is therefore not allowed. + INDOUBT_TRANSACTIONS_EXIST = 0x1AAB, + // The operation could not be completed because the transaction manager does not have a log. + TM_VOLATILE = 0x1AAC, + // A rollback could not be scheduled because a previously scheduled rollback has already executed or been queued for execution. + ROLLBACK_TIMER_EXPIRED = 0x1AAD, + // The transactional metadata attribute on the file or directory is corrupt and unreadable. + TXF_ATTRIBUTE_CORRUPT = 0x1AAE, + // The encryption operation could not be completed because a transaction is active. + EFS_NOT_ALLOWED_IN_TRANSACTION = 0x1AAF, + // This object is not allowed to be opened in a transaction. + TRANSACTIONAL_OPEN_NOT_ALLOWED = 0x1AB0, + // An attempt to create space in the transactional resource manager's log failed. The failure status has been recorded in the event log. + LOG_GROWTH_FAILED = 0x1AB1, + // Memory mapping (creating a mapped section) a remote file under a transaction is not supported. + TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 0x1AB2, + // Transaction metadata is already present on this file and cannot be superseded. + TXF_METADATA_ALREADY_PRESENT = 0x1AB3, + // A transaction scope could not be entered because the scope handler has not been initialized. + TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x1AB4, + // Promotion was required in order to allow the resource manager to enlist, but the transaction was set to disallow it. + TRANSACTION_REQUIRED_PROMOTION = 0x1AB5, + // This file is open for modification in an unresolved transaction and may be opened for execute only by a transacted reader. + CANNOT_EXECUTE_FILE_IN_TRANSACTION = 0x1AB6, + // The request to thaw frozen transactions was ignored because transactions had not previously been frozen. + TRANSACTIONS_NOT_FROZEN = 0x1AB7, + // Transactions cannot be frozen because a freeze is already in progress. + TRANSACTION_FREEZE_IN_PROGRESS = 0x1AB8, + // The target volume is not a snapshot volume. This operation is only valid on a volume mounted as a snapshot. + NOT_SNAPSHOT_VOLUME = 0x1AB9, + // The savepoint operation failed because files are open on the transaction. This is not permitted. + NO_SAVEPOINT_WITH_OPEN_FILES = 0x1ABA, + // Windows has discovered corruption in a file, and that file has since been repaired. Data loss may have occurred. + DATA_LOST_REPAIR = 0x1ABB, + // The sparse operation could not be completed because a transaction is active on the file. + SPARSE_NOT_ALLOWED_IN_TRANSACTION = 0x1ABC, + // The call to create a TransactionManager object failed because the Tm Identity stored in the logfile does not match the Tm Identity that was passed in as an argument. + TM_IDENTITY_MISMATCH = 0x1ABD, + // I/O was attempted on a section object that has been floated as a result of a transaction ending. There is no valid data. + FLOATED_SECTION = 0x1ABE, + // The transactional resource manager cannot currently accept transacted work due to a transient condition such as low resources. + CANNOT_ACCEPT_TRANSACTED_WORK = 0x1ABF, + // The transactional resource manager had too many tranactions outstanding that could not be aborted. The transactional resource manger has been shut down. + CANNOT_ABORT_TRANSACTIONS = 0x1AC0, + // The operation could not be completed due to bad clusters on disk. + BAD_CLUSTERS = 0x1AC1, + // The compression operation could not be completed because a transaction is active on the file. + COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 0x1AC2, + // The operation could not be completed because the volume is dirty. Please run chkdsk and try again. + VOLUME_DIRTY = 0x1AC3, + // The link tracking operation could not be completed because a transaction is active. + NO_LINK_TRACKING_IN_TRANSACTION = 0x1AC4, + // This operation cannot be performed in a transaction. + OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 0x1AC5, + // The handle is no longer properly associated with its transaction. It may have been opened in a transactional resource manager that was subsequently forced to restart. Please close the handle and open a new one. + EXPIRED_HANDLE = 0x1AC6, + // The specified operation could not be performed because the resource manager is not enlisted in the transaction. + TRANSACTION_NOT_ENLISTED = 0x1AC7, + // The specified session name is invalid. + CTX_WINSTATION_NAME_INVALID = 0x1B59, + // The specified protocol driver is invalid. + CTX_INVALID_PD = 0x1B5A, + // The specified protocol driver was not found in the system path. + CTX_PD_NOT_FOUND = 0x1B5B, + // The specified terminal connection driver was not found in the system path. + CTX_WD_NOT_FOUND = 0x1B5C, + // A registry key for event logging could not be created for this session. + CTX_CANNOT_MAKE_EVENTLOG_ENTRY = 0x1B5D, + // A service with the same name already exists on the system. + CTX_SERVICE_NAME_COLLISION = 0x1B5E, + // A close operation is pending on the session. + CTX_CLOSE_PENDING = 0x1B5F, + // There are no free output buffers available. + CTX_NO_OUTBUF = 0x1B60, + // The MODEM.INF file was not found. + CTX_MODEM_INF_NOT_FOUND = 0x1B61, + // The modem name was not found in MODEM.INF. + CTX_INVALID_MODEMNAME = 0x1B62, + // The modem did not accept the command sent to it. Verify that the configured modem name matches the attached modem. + CTX_MODEM_RESPONSE_ERROR = 0x1B63, + // The modem did not respond to the command sent to it. Verify that the modem is properly cabled and powered on. + CTX_MODEM_RESPONSE_TIMEOUT = 0x1B64, + // Carrier detect has failed or carrier has been dropped due to disconnect. + CTX_MODEM_RESPONSE_NO_CARRIER = 0x1B65, + // Dial tone not detected within the required time. Verify that the phone cable is properly attached and functional. + CTX_MODEM_RESPONSE_NO_DIALTONE = 0x1B66, + // Busy signal detected at remote site on callback. + CTX_MODEM_RESPONSE_BUSY = 0x1B67, + // Voice detected at remote site on callback. + CTX_MODEM_RESPONSE_VOICE = 0x1B68, + // Transport driver error. + CTX_TD_ERROR = 0x1B69, + // The specified session cannot be found. + CTX_WINSTATION_NOT_FOUND = 0x1B6E, + // The specified session name is already in use. + CTX_WINSTATION_ALREADY_EXISTS = 0x1B6F, + // The task you are trying to do can't be completed because Remote Desktop Services is currently busy. Please try again in a few minutes. Other users should still be able to log on. + CTX_WINSTATION_BUSY = 0x1B70, + // An attempt has been made to connect to a session whose video mode is not supported by the current client. + CTX_BAD_VIDEO_MODE = 0x1B71, + // The application attempted to enable DOS graphics mode. DOS graphics mode is not supported. + CTX_GRAPHICS_INVALID = 0x1B7B, + // Your interactive logon privilege has been disabled. Please contact your administrator. + CTX_LOGON_DISABLED = 0x1B7D, + // The requested operation can be performed only on the system console. This is most often the result of a driver or system DLL requiring direct console access. + CTX_NOT_CONSOLE = 0x1B7E, + // The client failed to respond to the server connect message. + CTX_CLIENT_QUERY_TIMEOUT = 0x1B80, + // Disconnecting the console session is not supported. + CTX_CONSOLE_DISCONNECT = 0x1B81, + // Reconnecting a disconnected session to the console is not supported. + CTX_CONSOLE_CONNECT = 0x1B82, + // The request to control another session remotely was denied. + CTX_SHADOW_DENIED = 0x1B84, + // The requested session access is denied. + CTX_WINSTATION_ACCESS_DENIED = 0x1B85, + // The specified terminal connection driver is invalid. + CTX_INVALID_WD = 0x1B89, + // The requested session cannot be controlled remotely. This may be because the session is disconnected or does not currently have a user logged on. + CTX_SHADOW_INVALID = 0x1B8A, + // The requested session is not configured to allow remote control. + CTX_SHADOW_DISABLED = 0x1B8B, + // Your request to connect to this Terminal Server has been rejected. Your Terminal Server client license number is currently being used by another user. Please call your system administrator to obtain a unique license number. + CTX_CLIENT_LICENSE_IN_USE = 0x1B8C, + // Your request to connect to this Terminal Server has been rejected. Your Terminal Server client license number has not been entered for this copy of the Terminal Server client. Please contact your system administrator. + CTX_CLIENT_LICENSE_NOT_SET = 0x1B8D, + // The number of connections to this computer is limited and all connections are in use right now. Try connecting later or contact your system administrator. + CTX_LICENSE_NOT_AVAILABLE = 0x1B8E, + // The client you are using is not licensed to use this system. Your logon request is denied. + CTX_LICENSE_CLIENT_INVALID = 0x1B8F, + // The system license has expired. Your logon request is denied. + CTX_LICENSE_EXPIRED = 0x1B90, + // Remote control could not be terminated because the specified session is not currently being remotely controlled. + CTX_SHADOW_NOT_RUNNING = 0x1B91, + // The remote control of the console was terminated because the display mode was changed. Changing the display mode in a remote control session is not supported. + CTX_SHADOW_ENDED_BY_MODE_CHANGE = 0x1B92, + // Activation has already been reset the maximum number of times for this installation. Your activation timer will not be cleared. + ACTIVATION_COUNT_EXCEEDED = 0x1B93, + // Remote logins are currently disabled. + CTX_WINSTATIONS_DISABLED = 0x1B94, + // You do not have the proper encryption level to access this Session. + CTX_ENCRYPTION_LEVEL_REQUIRED = 0x1B95, + // The user %s\\%s is currently logged on to this computer. Only the current user or an administrator can log on to this computer. + CTX_SESSION_IN_USE = 0x1B96, + // The user %s\\%s is already logged on to the console of this computer. You do not have permission to log in at this time. To resolve this issue, contact %s\\%s and have them log off. + CTX_NO_FORCE_LOGOFF = 0x1B97, + // Unable to log you on because of an account restriction. + CTX_ACCOUNT_RESTRICTION = 0x1B98, + // The RDP protocol component %2 detected an error in the protocol stream and has disconnected the client. + RDP_PROTOCOL_ERROR = 0x1B99, + // The Client Drive Mapping Service Has Connected on Terminal Connection. + CTX_CDM_CONNECT = 0x1B9A, + // The Client Drive Mapping Service Has Disconnected on Terminal Connection. + CTX_CDM_DISCONNECT = 0x1B9B, + // The Terminal Server security layer detected an error in the protocol stream and has disconnected the client. + CTX_SECURITY_LAYER_ERROR = 0x1B9C, + // The target session is incompatible with the current session. + TS_INCOMPATIBLE_SESSIONS = 0x1B9D, + // Windows can't connect to your session because a problem occurred in the Windows video subsystem. Try connecting again later, or contact the server administrator for assistance. + TS_VIDEO_SUBSYSTEM_ERROR = 0x1B9E, + // The file replication service API was called incorrectly. + FRS_ERR_INVALID_API_SEQUENCE = 0x1F41, + // The file replication service cannot be started. + FRS_ERR_STARTING_SERVICE = 0x1F42, + // The file replication service cannot be stopped. + FRS_ERR_STOPPING_SERVICE = 0x1F43, + // The file replication service API terminated the request. The event log may have more information. + FRS_ERR_INTERNAL_API = 0x1F44, + // The file replication service terminated the request. The event log may have more information. + FRS_ERR_INTERNAL = 0x1F45, + // The file replication service cannot be contacted. The event log may have more information. + FRS_ERR_SERVICE_COMM = 0x1F46, + // The file replication service cannot satisfy the request because the user has insufficient privileges. The event log may have more information. + FRS_ERR_INSUFFICIENT_PRIV = 0x1F47, + // The file replication service cannot satisfy the request because authenticated RPC is not available. The event log may have more information. + FRS_ERR_AUTHENTICATION = 0x1F48, + // The file replication service cannot satisfy the request because the user has insufficient privileges on the domain controller. The event log may have more information. + FRS_ERR_PARENT_INSUFFICIENT_PRIV = 0x1F49, + // The file replication service cannot satisfy the request because authenticated RPC is not available on the domain controller. The event log may have more information. + FRS_ERR_PARENT_AUTHENTICATION = 0x1F4A, + // The file replication service cannot communicate with the file replication service on the domain controller. The event log may have more information. + FRS_ERR_CHILD_TO_PARENT_COMM = 0x1F4B, + // The file replication service on the domain controller cannot communicate with the file replication service on this computer. The event log may have more information. + FRS_ERR_PARENT_TO_CHILD_COMM = 0x1F4C, + // The file replication service cannot populate the system volume because of an internal error. The event log may have more information. + FRS_ERR_SYSVOL_POPULATE = 0x1F4D, + // The file replication service cannot populate the system volume because of an internal timeout. The event log may have more information. + FRS_ERR_SYSVOL_POPULATE_TIMEOUT = 0x1F4E, + // The file replication service cannot process the request. The system volume is busy with a previous request. + FRS_ERR_SYSVOL_IS_BUSY = 0x1F4F, + // The file replication service cannot stop replicating the system volume because of an internal error. The event log may have more information. + FRS_ERR_SYSVOL_DEMOTE = 0x1F50, + // The file replication service detected an invalid parameter. + FRS_ERR_INVALID_SERVICE_PARAMETER = 0x1F51, + + + // An error occurred while installing the directory service. For more information, see the event log. + DS_NOT_INSTALLED = 0x2008, + // The directory service evaluated group memberships locally. + DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x2009, + // The specified directory service attribute or value does not exist. + DS_NO_ATTRIBUTE_OR_VALUE = 0x200A, + // The attribute syntax specified to the directory service is invalid. + DS_INVALID_ATTRIBUTE_SYNTAX = 0x200B, + // The attribute type specified to the directory service is not defined. + DS_ATTRIBUTE_TYPE_UNDEFINED = 0x200C, + // The specified directory service attribute or value already exists. + DS_ATTRIBUTE_OR_VALUE_EXISTS = 0x200D, + // The directory service is busy. + DS_BUSY = 0x200E, + // The directory service is unavailable. + DS_UNAVAILABLE = 0x200F, + // The directory service was unable to allocate a relative identifier. + DS_NO_RIDS_ALLOCATED = 0x2010, + // The directory service has exhausted the pool of relative identifiers. + DS_NO_MORE_RIDS = 0x2011, + // The requested operation could not be performed because the directory service is not the master for that type of operation. + DS_INCORRECT_ROLE_OWNER = 0x2012, + // The directory service was unable to initialize the subsystem that allocates relative identifiers. + DS_RIDMGR_INIT_ERROR = 0x2013, + // The requested operation did not satisfy one or more constraints associated with the class of the object. + DS_OBJ_CLASS_VIOLATION = 0x2014, + // The directory service can perform the requested operation only on a leaf object. + DS_CANT_ON_NON_LEAF = 0x2015, + // The directory service cannot perform the requested operation on the RDN attribute of an object. + DS_CANT_ON_RDN = 0x2016, + // The directory service detected an attempt to modify the object class of an object. + DS_CANT_MOD_OBJ_CLASS = 0x2017, + // The requested cross-domain move operation could not be performed. + DS_CROSS_DOM_MOVE_ERROR = 0x2018, + // Unable to contact the global catalog server. + DS_GC_NOT_AVAILABLE = 0x2019, + // The policy object is shared and can only be modified at the root. + SHARED_POLICY = 0x201A, + // The policy object does not exist. + POLICY_OBJECT_NOT_FOUND = 0x201B, + // The requested policy information is only in the directory service. + POLICY_ONLY_IN_DS = 0x201C, + // A domain controller promotion is currently active. + PROMOTION_ACTIVE = 0x201D, + // A domain controller promotion is not currently active. + NO_PROMOTION_ACTIVE = 0x201E, + // An operations error occurred. + DS_OPERATIONS_ERROR = 0x2020, + // A protocol error occurred. + DS_PROTOCOL_ERROR = 0x2021, + // The time limit for this request was exceeded. + DS_TIMELIMIT_EXCEEDED = 0x2022, + // The size limit for this request was exceeded. + DS_SIZELIMIT_EXCEEDED = 0x2023, + // The administrative limit for this request was exceeded. + DS_ADMIN_LIMIT_EXCEEDED = 0x2024, + // The compare response was false. + DS_COMPARE_FALSE = 0x2025, + // The compare response was true. + DS_COMPARE_TRUE = 0x2026, + // The requested authentication method is not supported by the server. + DS_AUTH_METHOD_NOT_SUPPORTED = 0x2027, + // A more secure authentication method is required for this server. + DS_STRONG_AUTH_REQUIRED = 0x2028, + // Inappropriate authentication. + DS_INAPPROPRIATE_AUTH = 0x2029, + // The authentication mechanism is unknown. + DS_AUTH_UNKNOWN = 0x202A, + // A referral was returned from the server. + DS_REFERRAL = 0x202B, + // The server does not support the requested critical extension. + DS_UNAVAILABLE_CRIT_EXTENSION = 0x202C, + // This request requires a secure connection. + DS_CONFIDENTIALITY_REQUIRED = 0x202D, + // Inappropriate matching. + DS_INAPPROPRIATE_MATCHING = 0x202E, + // A constraint violation occurred. + DS_CONSTRAINT_VIOLATION = 0x202F, + // There is no such object on the server. + DS_NO_SUCH_OBJECT = 0x2030, + // There is an alias problem. + DS_ALIAS_PROBLEM = 0x2031, + // An invalid dn syntax has been specified. + DS_INVALID_DN_SYNTAX = 0x2032, + // The object is a leaf object. + DS_IS_LEAF = 0x2033, + // There is an alias dereferencing problem. + DS_ALIAS_DEREF_PROBLEM = 0x2034, + // The server is unwilling to process the request. + DS_UNWILLING_TO_PERFORM = 0x2035, + // A loop has been detected. + DS_LOOP_DETECT = 0x2036, + // There is a naming violation. + DS_NAMING_VIOLATION = 0x2037, + // The result set is too large. + DS_OBJECT_RESULTS_TOO_LARGE = 0x2038, + // The operation affects multiple DSAs. + DS_AFFECTS_MULTIPLE_DSAS = 0x2039, + // The server is not operational. + DS_SERVER_DOWN = 0x203A, + // A local error has occurred. + DS_LOCAL_ERROR = 0x203B, + // An encoding error has occurred. + DS_ENCODING_ERROR = 0x203C, + // A decoding error has occurred. + DS_DECODING_ERROR = 0x203D, + // The search filter cannot be recognized. + DS_FILTER_UNKNOWN = 0x203E, + // One or more parameters are illegal. + DS_PARAM_ERROR = 0x203F, + // The specified method is not supported. + DS_NOT_SUPPORTED = 0x2040, + // No results were returned. + DS_NO_RESULTS_RETURNED = 0x2041, + // The specified control is not supported by the server. + DS_CONTROL_NOT_FOUND = 0x2042, + // A referral loop was detected by the client. + DS_CLIENT_LOOP = 0x2043, + // The preset referral limit was exceeded. + DS_REFERRAL_LIMIT_EXCEEDED = 0x2044, + // The search requires a SORT control. + DS_SORT_CONTROL_MISSING = 0x2045, + // The search results exceed the offset range specified. + DS_OFFSET_RANGE_ERROR = 0x2046, + // The directory service detected the subsystem that allocates relative identifiers is disabled. This can occur as a protective mechanism when the system determines a significant portion of relative identifiers (RIDs) have been exhausted. Please see https://go.microsoft.com/fwlink/p/?linkid=228610 for recommended diagnostic steps and the procedure to re-enable account creation. + DS_RIDMGR_DISABLED = 0x2047, + // The root object must be the head of a naming context. The root object cannot have an instantiated parent. + DS_ROOT_MUST_BE_NC = 0x206D, + // The add replica operation cannot be performed. The naming context must be writeable in order to create the replica. + DS_ADD_REPLICA_INHIBITED = 0x206E, + // A reference to an attribute that is not defined in the schema occurred. + DS_ATT_NOT_DEF_IN_SCHEMA = 0x206F, + // The maximum size of an object has been exceeded. + DS_MAX_OBJ_SIZE_EXCEEDED = 0x2070, + // An attempt was made to add an object to the directory with a name that is already in use. + DS_OBJ_STRING_NAME_EXISTS = 0x2071, + // An attempt was made to add an object of a class that does not have an RDN defined in the schema. + DS_NO_RDN_DEFINED_IN_SCHEMA = 0x2072, + // An attempt was made to add an object using an RDN that is not the RDN defined in the schema. + DS_RDN_DOESNT_MATCH_SCHEMA = 0x2073, + // None of the requested attributes were found on the objects. + DS_NO_REQUESTED_ATTS_FOUND = 0x2074, + // The user buffer is too small. + DS_USER_BUFFER_TO_SMALL = 0x2075, + // The attribute specified in the operation is not present on the object. + DS_ATT_IS_NOT_ON_OBJ = 0x2076, + // Illegal modify operation. Some aspect of the modification is not permitted. + DS_ILLEGAL_MOD_OPERATION = 0x2077, + // The specified object is too large. + DS_OBJ_TOO_LARGE = 0x2078, + // The specified instance type is not valid. + DS_BAD_INSTANCE_TYPE = 0x2079, + // The operation must be performed at a master DSA. + DS_MASTERDSA_REQUIRED = 0x207A, + // The object class attribute must be specified. + DS_OBJECT_CLASS_REQUIRED = 0x207B, + // A required attribute is missing. + DS_MISSING_REQUIRED_ATT = 0x207C, + // An attempt was made to modify an object to include an attribute that is not legal for its class. + DS_ATT_NOT_DEF_FOR_CLASS = 0x207D, + // The specified attribute is already present on the object. + DS_ATT_ALREADY_EXISTS = 0x207E, + // The specified attribute is not present, or has no values. + DS_CANT_ADD_ATT_VALUES = 0x2080, + // Multiple values were specified for an attribute that can have only one value. + DS_SINGLE_VALUE_CONSTRAINT = 0x2081, + // A value for the attribute was not in the acceptable range of values. + DS_RANGE_CONSTRAINT = 0x2082, + // The specified value already exists. + DS_ATT_VAL_ALREADY_EXISTS = 0x2083, + // The attribute cannot be removed because it is not present on the object. + DS_CANT_REM_MISSING_ATT = 0x2084, + // The attribute value cannot be removed because it is not present on the object. + DS_CANT_REM_MISSING_ATT_VAL = 0x2085, + // The specified root object cannot be a subref. + DS_ROOT_CANT_BE_SUBREF = 0x2086, + // Chaining is not permitted. + DS_NO_CHAINING = 0x2087, + // Chained evaluation is not permitted. + DS_NO_CHAINED_EVAL = 0x2088, + // The operation could not be performed because the object's parent is either uninstantiated or deleted. + DS_NO_PARENT_OBJECT = 0x2089, + // Having a parent that is an alias is not permitted. Aliases are leaf objects. + DS_PARENT_IS_AN_ALIAS = 0x208A, + // The object and parent must be of the same type, either both masters or both replicas. + DS_CANT_MIX_MASTER_AND_REPS = 0x208B, + // The operation cannot be performed because child objects exist. This operation can only be performed on a leaf object. + DS_CHILDREN_EXIST = 0x208C, + // Directory object not found. + DS_OBJ_NOT_FOUND = 0x208D, + // The aliased object is missing. + DS_ALIASED_OBJ_MISSING = 0x208E, + // The object name has bad syntax. + DS_BAD_NAME_SYNTAX = 0x208F, + // It is not permitted for an alias to refer to another alias. + DS_ALIAS_POINTS_TO_ALIAS = 0x2090, + // The alias cannot be dereferenced. + DS_CANT_DEREF_ALIAS = 0x2091, + // The operation is out of scope. + DS_OUT_OF_SCOPE = 0x2092, + // The operation cannot continue because the object is in the process of being removed. + DS_OBJECT_BEING_REMOVED = 0x2093, + // The DSA object cannot be deleted. + DS_CANT_DELETE_DSA_OBJ = 0x2094, + // A directory service error has occurred. + DS_GENERIC_ERROR = 0x2095, + // The operation can only be performed on an internal master DSA object. + DS_DSA_MUST_BE_INT_MASTER = 0x2096, + // The object must be of class DSA. + DS_CLASS_NOT_DSA = 0x2097, + // Insufficient access rights to perform the operation. + DS_INSUFF_ACCESS_RIGHTS = 0x2098, + // The object cannot be added because the parent is not on the list of possible superiors. + DS_ILLEGAL_SUPERIOR = 0x2099, + // Access to the attribute is not permitted because the attribute is owned by the Security Accounts Manager (SAM). + DS_ATTRIBUTE_OWNED_BY_SAM = 0x209A, + // The name has too many parts. + DS_NAME_TOO_MANY_PARTS = 0x209B, + // The name is too long. + DS_NAME_TOO_LONG = 0x209C, + // The name value is too long. + DS_NAME_VALUE_TOO_LONG = 0x209D, + // The directory service encountered an error parsing a name. + DS_NAME_UNPARSEABLE = 0x209E, + // The directory service cannot get the attribute type for a name. + DS_NAME_TYPE_UNKNOWN = 0x209F, + // The name does not identify an object; the name identifies a phantom. + DS_NOT_AN_OBJECT = 0x20A0, + // The security descriptor is too short. + DS_SEC_DESC_TOO_SHORT = 0x20A1, + // The security descriptor is invalid. + DS_SEC_DESC_INVALID = 0x20A2, + // Failed to create name for deleted object. + DS_NO_DELETED_NAME = 0x20A3, + // The parent of a new subref must exist. + DS_SUBREF_MUST_HAVE_PARENT = 0x20A4, + // The object must be a naming context. + DS_NCNAME_MUST_BE_NC = 0x20A5, + // It is not permitted to add an attribute which is owned by the system. + DS_CANT_ADD_SYSTEM_ONLY = 0x20A6, + // The class of the object must be structural; you cannot instantiate an abstract class. + DS_CLASS_MUST_BE_CONCRETE = 0x20A7, + // The schema object could not be found. + DS_INVALID_DMD = 0x20A8, + // A local object with this GUID (dead or alive) already exists. + DS_OBJ_GUID_EXISTS = 0x20A9, + // The operation cannot be performed on a back link. + DS_NOT_ON_BACKLINK = 0x20AA, + // The cross reference for the specified naming context could not be found. + DS_NO_CROSSREF_FOR_NC = 0x20AB, + // The operation could not be performed because the directory service is shutting down. + DS_SHUTTING_DOWN = 0x20AC, + // The directory service request is invalid. + DS_UNKNOWN_OPERATION = 0x20AD, + // The role owner attribute could not be read. + DS_INVALID_ROLE_OWNER = 0x20AE, + // The requested FSMO operation failed. The current FSMO holder could not be contacted. + DS_COULDNT_CONTACT_FSMO = 0x20AF, + // Modification of a DN across a naming context is not permitted. + DS_CROSS_NC_DN_RENAME = 0x20B0, + // The attribute cannot be modified because it is owned by the system. + DS_CANT_MOD_SYSTEM_ONLY = 0x20B1, + // Only the replicator can perform this function. + DS_REPLICATOR_ONLY = 0x20B2, + // The specified class is not defined. + DS_OBJ_CLASS_NOT_DEFINED = 0x20B3, + // The specified class is not a subclass. + DS_OBJ_CLASS_NOT_SUBCLASS = 0x20B4, + // The name reference is invalid. + DS_NAME_REFERENCE_INVALID = 0x20B5, + // A cross reference already exists. + DS_CROSS_REF_EXISTS = 0x20B6, + // It is not permitted to delete a master cross reference. + DS_CANT_DEL_MASTER_CROSSREF = 0x20B7, + // Subtree notifications are only supported on NC heads. + DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 0x20B8, + // Notification filter is too complex. + DS_NOTIFY_FILTER_TOO_COMPLEX = 0x20B9, + // Schema update failed: duplicate RDN. + DS_DUP_RDN = 0x20BA, + // Schema update failed: duplicate OID. + DS_DUP_OID = 0x20BB, + // Schema update failed: duplicate MAPI identifier. + DS_DUP_MAPI_ID = 0x20BC, + // Schema update failed: duplicate schema-id GUID. + DS_DUP_SCHEMA_ID_GUID = 0x20BD, + // Schema update failed: duplicate LDAP display name. + DS_DUP_LDAP_DISPLAY_NAME = 0x20BE, + // Schema update failed: range-lower less than range upper. + DS_SEMANTIC_ATT_TEST = 0x20BF, + // Schema update failed: syntax mismatch. + DS_SYNTAX_MISMATCH = 0x20C0, + // Schema deletion failed: attribute is used in must-contain. + DS_EXISTS_IN_MUST_HAVE = 0x20C1, + // Schema deletion failed: attribute is used in may-contain. + DS_EXISTS_IN_MAY_HAVE = 0x20C2, + // Schema update failed: attribute in may-contain does not exist. + DS_NONEXISTENT_MAY_HAVE = 0x20C3, + // Schema update failed: attribute in must-contain does not exist. + DS_NONEXISTENT_MUST_HAVE = 0x20C4, + // Schema update failed: class in aux-class list does not exist or is not an auxiliary class. + DS_AUX_CLS_TEST_FAIL = 0x20C5, + // Schema update failed: class in poss-superiors does not exist. + DS_NONEXISTENT_POSS_SUP = 0x20C6, + // Schema update failed: class in subclassof list does not exist or does not satisfy hierarchy rules. + DS_SUB_CLS_TEST_FAIL = 0x20C7, + // Schema update failed: Rdn-Att-Id has wrong syntax. + DS_BAD_RDN_ATT_ID_SYNTAX = 0x20C8, + // Schema deletion failed: class is used as auxiliary class. + DS_EXISTS_IN_AUX_CLS = 0x20C9, + // Schema deletion failed: class is used as sub class. + DS_EXISTS_IN_SUB_CLS = 0x20CA, + // Schema deletion failed: class is used as poss superior. + DS_EXISTS_IN_POSS_SUP = 0x20CB, + // Schema update failed in recalculating validation cache. + DS_RECALCSCHEMA_FAILED = 0x20CC, + // The tree deletion is not finished. The request must be made again to continue deleting the tree. + DS_TREE_DELETE_NOT_FINISHED = 0x20CD, + // The requested delete operation could not be performed. + DS_CANT_DELETE = 0x20CE, + // Cannot read the governs class identifier for the schema record. + DS_ATT_SCHEMA_REQ_ID = 0x20CF, + // The attribute schema has bad syntax. + DS_BAD_ATT_SCHEMA_SYNTAX = 0x20D0, + // The attribute could not be cached. + DS_CANT_CACHE_ATT = 0x20D1, + // The class could not be cached. + DS_CANT_CACHE_CLASS = 0x20D2, + // The attribute could not be removed from the cache. + DS_CANT_REMOVE_ATT_CACHE = 0x20D3, + // The class could not be removed from the cache. + DS_CANT_REMOVE_CLASS_CACHE = 0x20D4, + // The distinguished name attribute could not be read. + DS_CANT_RETRIEVE_DN = 0x20D5, + // No superior reference has been configured for the directory service. The directory service is therefore unable to issue referrals to objects outside this forest. + DS_MISSING_SUPREF = 0x20D6, + // The instance type attribute could not be retrieved. + DS_CANT_RETRIEVE_INSTANCE = 0x20D7, + // An internal error has occurred. + DS_CODE_INCONSISTENCY = 0x20D8, + // A database error has occurred. + DS_DATABASE_ERROR = 0x20D9, + // The attribute GOVERNSID is missing. + DS_GOVERNSID_MISSING = 0x20DA, + // An expected attribute is missing. + DS_MISSING_EXPECTED_ATT = 0x20DB, + // The specified naming context is missing a cross reference. + DS_NCNAME_MISSING_CR_REF = 0x20DC, + // A security checking error has occurred. + DS_SECURITY_CHECKING_ERROR = 0x20DD, + // The schema is not loaded. + DS_SCHEMA_NOT_LOADED = 0x20DE, + // Schema allocation failed. Please check if the machine is running low on memory. + DS_SCHEMA_ALLOC_FAILED = 0x20DF, + // Failed to obtain the required syntax for the attribute schema. + DS_ATT_SCHEMA_REQ_SYNTAX = 0x20E0, + // The global catalog verification failed. The global catalog is not available or does not support the operation. Some part of the directory is currently not available. + DS_GCVERIFY_ERROR = 0x20E1, + // The replication operation failed because of a schema mismatch between the servers involved. + DS_DRA_SCHEMA_MISMATCH = 0x20E2, + // The DSA object could not be found. + DS_CANT_FIND_DSA_OBJ = 0x20E3, + // The naming context could not be found. + DS_CANT_FIND_EXPECTED_NC = 0x20E4, + // The naming context could not be found in the cache. + DS_CANT_FIND_NC_IN_CACHE = 0x20E5, + // The child object could not be retrieved. + DS_CANT_RETRIEVE_CHILD = 0x20E6, + // The modification was not permitted for security reasons. + DS_SECURITY_ILLEGAL_MODIFY = 0x20E7, + // The operation cannot replace the hidden record. + DS_CANT_REPLACE_HIDDEN_REC = 0x20E8, + // The hierarchy file is invalid. + DS_BAD_HIERARCHY_FILE = 0x20E9, + // The attempt to build the hierarchy table failed. + DS_BUILD_HIERARCHY_TABLE_FAILED = 0x20EA, + // The directory configuration parameter is missing from the registry. + DS_CONFIG_PARAM_MISSING = 0x20EB, + // The attempt to count the address book indices failed. + DS_COUNTING_AB_INDICES_FAILED = 0x20EC, + // The allocation of the hierarchy table failed. + DS_HIERARCHY_TABLE_MALLOC_FAILED = 0x20ED, + // The directory service encountered an internal failure. + DS_INTERNAL_FAILURE = 0x20EE, + // The directory service encountered an unknown failure. + DS_UNKNOWN_ERROR = 0x20EF, + // A root object requires a class of 'top'. + DS_ROOT_REQUIRES_CLASS_TOP = 0x20F0, + // This directory server is shutting down, and cannot take ownership of new floating single-master operation roles. + DS_REFUSING_FSMO_ROLES = 0x20F1, + // The directory service is missing mandatory configuration information, and is unable to determine the ownership of floating single-master operation roles. + DS_MISSING_FSMO_SETTINGS = 0x20F2, + // The directory service was unable to transfer ownership of one or more floating single-master operation roles to other servers. + DS_UNABLE_TO_SURRENDER_ROLES = 0x20F3, + // The replication operation failed. + DS_DRA_GENERIC = 0x20F4, + // An invalid parameter was specified for this replication operation. + DS_DRA_INVALID_PARAMETER = 0x20F5, + // The directory service is too busy to complete the replication operation at this time. + DS_DRA_BUSY = 0x20F6, + // The distinguished name specified for this replication operation is invalid. + DS_DRA_BAD_DN = 0x20F7, + // The naming context specified for this replication operation is invalid. + DS_DRA_BAD_NC = 0x20F8, + // The distinguished name specified for this replication operation already exists. + DS_DRA_DN_EXISTS = 0x20F9, + // The replication system encountered an internal error. + DS_DRA_INTERNAL_ERROR = 0x20FA, + // The replication operation encountered a database inconsistency. + DS_DRA_INCONSISTENT_DIT = 0x20FB, + // The server specified for this replication operation could not be contacted. + DS_DRA_CONNECTION_FAILED = 0x20FC, + // The replication operation encountered an object with an invalid instance type. + DS_DRA_BAD_INSTANCE_TYPE = 0x20FD, + // The replication operation failed to allocate memory. + DS_DRA_OUT_OF_MEM = 0x20FE, + // The replication operation encountered an error with the mail system. + DS_DRA_MAIL_PROBLEM = 0x20FF, + // The replication reference information for the target server already exists. + DS_DRA_REF_ALREADY_EXISTS = 0x2100, + // The replication reference information for the target server does not exist. + DS_DRA_REF_NOT_FOUND = 0x2101, + // The naming context cannot be removed because it is replicated to another server. + DS_DRA_OBJ_IS_REP_SOURCE = 0x2102, + // The replication operation encountered a database error. + DS_DRA_DB_ERROR = 0x2103, + // The naming context is in the process of being removed or is not replicated from the specified server. + DS_DRA_NO_REPLICA = 0x2104, + // Replication access was denied. + DS_DRA_ACCESS_DENIED = 0x2105, + // The requested operation is not supported by this version of the directory service. + DS_DRA_NOT_SUPPORTED = 0x2106, + // The replication remote procedure call was cancelled. + DS_DRA_RPC_CANCELLED = 0x2107, + // The source server is currently rejecting replication requests. + DS_DRA_SOURCE_DISABLED = 0x2108, + // The destination server is currently rejecting replication requests. + DS_DRA_SINK_DISABLED = 0x2109, + // The replication operation failed due to a collision of object names. + DS_DRA_NAME_COLLISION = 0x210A, + // The replication source has been reinstalled. + DS_DRA_SOURCE_REINSTALLED = 0x210B, + // The replication operation failed because a required parent object is missing. + DS_DRA_MISSING_PARENT = 0x210C, + // The replication operation was preempted. + DS_DRA_PREEMPTED = 0x210D, + // The replication synchronization attempt was abandoned because of a lack of updates. + DS_DRA_ABANDON_SYNC = 0x210E, + // The replication operation was terminated because the system is shutting down. + DS_DRA_SHUTDOWN = 0x210F, + // Synchronization attempt failed because the destination DC is currently waiting to synchronize new partial attributes from source. This condition is normal if a recent schema change modified the partial attribute set. The destination partial attribute set is not a subset of source partial attribute set. + DS_DRA_INCOMPATIBLE_PARTIAL_SET = 0x2110, + // The replication synchronization attempt failed because a master replica attempted to sync from a partial replica. + DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 0x2111, + // The server specified for this replication operation was contacted, but that server was unable to contact an additional server needed to complete the operation. + DS_DRA_EXTN_CONNECTION_FAILED = 0x2112, + // The version of the directory service schema of the source forest is not compatible with the version of directory service on this computer. + DS_INSTALL_SCHEMA_MISMATCH = 0x2113, + // Schema update failed: An attribute with the same link identifier already exists. + DS_DUP_LINK_ID = 0x2114, + // Name translation: Generic processing error. + DS_NAME_ERROR_RESOLVING = 0x2115, + // Name translation: Could not find the name or insufficient right to see name. + DS_NAME_ERROR_NOT_FOUND = 0x2116, + // Name translation: Input name mapped to more than one output name. + DS_NAME_ERROR_NOT_UNIQUE = 0x2117, + // Name translation: Input name found, but not the associated output format. + DS_NAME_ERROR_NO_MAPPING = 0x2118, + // Name translation: Unable to resolve completely, only the domain was found. + DS_NAME_ERROR_DOMAIN_ONLY = 0x2119, + // Name translation: Unable to perform purely syntactical mapping at the client without going out to the wire. + DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 0x211A, + // Modification of a constructed attribute is not allowed. + DS_CONSTRUCTED_ATT_MOD = 0x211B, + // The OM-Object-Class specified is incorrect for an attribute with the specified syntax. + DS_WRONG_OM_OBJ_CLASS = 0x211C, + // The replication request has been posted; waiting for reply. + DS_DRA_REPL_PENDING = 0x211D, + // The requested operation requires a directory service, and none was available. + DS_DS_REQUIRED = 0x211E, + // The LDAP display name of the class or attribute contains non-ASCII characters. + DS_INVALID_LDAP_DISPLAY_NAME = 0x211F, + // The requested search operation is only supported for base searches. + DS_NON_BASE_SEARCH = 0x2120, + // The search failed to retrieve attributes from the database. + DS_CANT_RETRIEVE_ATTS = 0x2121, + // The schema update operation tried to add a backward link attribute that has no corresponding forward link. + DS_BACKLINK_WITHOUT_LINK = 0x2122, + // Source and destination of a cross-domain move do not agree on the object's epoch number. Either source or destination does not have the latest version of the object. + DS_EPOCH_MISMATCH = 0x2123, + // Source and destination of a cross-domain move do not agree on the object's current name. Either source or destination does not have the latest version of the object. + DS_SRC_NAME_MISMATCH = 0x2124, + // Source and destination for the cross-domain move operation are identical. Caller should use local move operation instead of cross-domain move operation. + DS_SRC_AND_DST_NC_IDENTICAL = 0x2125, + // Source and destination for a cross-domain move are not in agreement on the naming contexts in the forest. Either source or destination does not have the latest version of the Partitions container. + DS_DST_NC_MISMATCH = 0x2126, + // Destination of a cross-domain move is not authoritative for the destination naming context. + DS_NOT_AUTHORITIVE_FOR_DST_NC = 0x2127, + // Source and destination of a cross-domain move do not agree on the identity of the source object. Either source or destination does not have the latest version of the source object. + DS_SRC_GUID_MISMATCH = 0x2128, + // Object being moved across-domains is already known to be deleted by the destination server. The source server does not have the latest version of the source object. + DS_CANT_MOVE_DELETED_OBJECT = 0x2129, + // Another operation which requires exclusive access to the PDC FSMO is already in progress. + DS_PDC_OPERATION_IN_PROGRESS = 0x212A, + // A cross-domain move operation failed such that two versions of the moved object exist - one each in the source and destination domains. The destination object needs to be removed to restore the system to a consistent state. + DS_CROSS_DOMAIN_CLEANUP_REQD = 0x212B, + // This object may not be moved across domain boundaries either because cross-domain moves for this class are disallowed, or the object has some special characteristics, e.g.: trust account or restricted RID, which prevent its move. + DS_ILLEGAL_XDOM_MOVE_OPERATION = 0x212C, + // Can't move objects with memberships across domain boundaries as once moved, this would violate the membership conditions of the account group. Remove the object from any account group memberships and retry. + DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 0x212D, + // A naming context head must be the immediate child of another naming context head, not of an interior node. + DS_NC_MUST_HAVE_NC_PARENT = 0x212E, + // The directory cannot validate the proposed naming context name because it does not hold a replica of the naming context above the proposed naming context. Please ensure that the domain naming master role is held by a server that is configured as a global catalog server, and that the server is up to date with its replication partners. (Applies only to Windows 2000 Domain Naming masters.) + DS_CR_IMPOSSIBLE_TO_VALIDATE = 0x212F, + // Destination domain must be in native mode. + DS_DST_DOMAIN_NOT_NATIVE = 0x2130, + // The operation cannot be performed because the server does not have an infrastructure container in the domain of interest. + DS_MISSING_INFRASTRUCTURE_CONTAINER = 0x2131, + // Cross-domain move of non-empty account groups is not allowed. + DS_CANT_MOVE_ACCOUNT_GROUP = 0x2132, + // Cross-domain move of non-empty resource groups is not allowed. + DS_CANT_MOVE_RESOURCE_GROUP = 0x2133, + // The search flags for the attribute are invalid. The ANR bit is valid only on attributes of Unicode or Teletex strings. + DS_INVALID_SEARCH_FLAG = 0x2134, + // Tree deletions starting at an object which has an NC head as a descendant are not allowed. + DS_NO_TREE_DELETE_ABOVE_NC = 0x2135, + // The directory service failed to lock a tree in preparation for a tree deletion because the tree was in use. + DS_COULDNT_LOCK_TREE_FOR_DELETE = 0x2136, + // The directory service failed to identify the list of objects to delete while attempting a tree deletion. + DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 0x2137, + // Security Accounts Manager initialization failed because of the following error: %1. Error Status: 0x%2. Please shutdown this system and reboot into Directory Services Restore Mode, check the event log for more detailed information. + DS_SAM_INIT_FAILURE = 0x2138, + // Only an administrator can modify the membership list of an administrative group. + DS_SENSITIVE_GROUP_VIOLATION = 0x2139, + // Cannot change the primary group ID of a domain controller account. + DS_CANT_MOD_PRIMARYGROUPID = 0x213A, + // An attempt is made to modify the base schema. + DS_ILLEGAL_BASE_SCHEMA_MOD = 0x213B, + // Adding a new mandatory attribute to an existing class, deleting a mandatory attribute from an existing class, or adding an optional attribute to the special class Top that is not a backlink attribute (directly or through inheritance, for example, by adding or deleting an auxiliary class) is not allowed. + DS_NONSAFE_SCHEMA_CHANGE = 0x213C, + // Schema update is not allowed on this DC because the DC is not the schema FSMO Role Owner. + DS_SCHEMA_UPDATE_DISALLOWED = 0x213D, + // An object of this class cannot be created under the schema container. You can only create attribute-schema and class-schema objects under the schema container. + DS_CANT_CREATE_UNDER_SCHEMA = 0x213E, + // The replica/child install failed to get the objectVersion attribute on the schema container on the source DC. Either the attribute is missing on the schema container or the credentials supplied do not have permission to read it. + DS_INSTALL_NO_SRC_SCH_VERSION = 0x213F, + // The replica/child install failed to read the objectVersion attribute in the SCHEMA section of the file schema.ini in the system32 directory. + DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 0x2140, + // The specified group type is invalid. + DS_INVALID_GROUP_TYPE = 0x2141, + // You cannot nest global groups in a mixed domain if the group is security-enabled. + DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 0x2142, + // You cannot nest local groups in a mixed domain if the group is security-enabled. + DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 0x2143, + // A global group cannot have a local group as a member. + DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 0x2144, + // A global group cannot have a universal group as a member. + DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 0x2145, + // A universal group cannot have a local group as a member. + DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 0x2146, + // A global group cannot have a cross-domain member. + DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 0x2147, + // A local group cannot have another cross domain local group as a member. + DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 0x2148, + // A group with primary members cannot change to a security-disabled group. + DS_HAVE_PRIMARY_MEMBERS = 0x2149, + // The schema cache load failed to convert the string default SD on a class-schema object. + DS_STRING_SD_CONVERSION_FAILED = 0x214A, + // Only DSAs configured to be Global Catalog servers should be allowed to hold the Domain Naming Master FSMO role. (Applies only to Windows 2000 servers.) + DS_NAMING_MASTER_GC = 0x214B, + // The DSA operation is unable to proceed because of a DNS lookup failure. + DS_DNS_LOOKUP_FAILURE = 0x214C, + // While processing a change to the DNS Host Name for an object, the Service Principal Name values could not be kept in sync. + DS_COULDNT_UPDATE_SPNS = 0x214D, + // The Security Descriptor attribute could not be read. + DS_CANT_RETRIEVE_SD = 0x214E, + // The object requested was not found, but an object with that key was found. + DS_KEY_NOT_UNIQUE = 0x214F, + // The syntax of the linked attribute being added is incorrect. Forward links can only have syntax 2.5.5.1, 2.5.5.7, and 2.5.5.14, and backlinks can only have syntax 2.5.5.1. + DS_WRONG_LINKED_ATT_SYNTAX = 0x2150, + // Security Account Manager needs to get the boot password. + DS_SAM_NEED_BOOTKEY_PASSWORD = 0x2151, + // Security Account Manager needs to get the boot key from floppy disk. + DS_SAM_NEED_BOOTKEY_FLOPPY = 0x2152, + // Directory Service cannot start. + DS_CANT_START = 0x2153, + // Directory Services could not start. + DS_INIT_FAILURE = 0x2154, + // The connection between client and server requires packet privacy or better. + DS_NO_PKT_PRIVACY_ON_CONNECTION = 0x2155, + // The source domain may not be in the same forest as destination. + DS_SOURCE_DOMAIN_IN_FOREST = 0x2156, + // The destination domain must be in the forest. + DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 0x2157, + // The operation requires that destination domain auditing be enabled. + DS_DESTINATION_AUDITING_NOT_ENABLED = 0x2158, + // The operation couldn't locate a DC for the source domain. + DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 0x2159, + // The source object must be a group or user. + DS_SRC_OBJ_NOT_GROUP_OR_USER = 0x215A, + // The source object's SID already exists in destination forest. + DS_SRC_SID_EXISTS_IN_FOREST = 0x215B, + // The source and destination object must be of the same type. + DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 0x215C, + // Security Accounts Manager initialization failed because of the following error: %1. Error Status: 0x%2. Click OK to shut down the system and reboot into Safe Mode. Check the event log for detailed information. + SAM_INIT_FAILURE = 0x215D, + // Schema information could not be included in the replication request. + DS_DRA_SCHEMA_INFO_SHIP = 0x215E, + // The replication operation could not be completed due to a schema incompatibility. + DS_DRA_SCHEMA_CONFLICT = 0x215F, + // The replication operation could not be completed due to a previous schema incompatibility. + DS_DRA_EARLIER_SCHEMA_CONFLICT = 0x2160, + // The replication update could not be applied because either the source or the destination has not yet received information regarding a recent cross-domain move operation. + DS_DRA_OBJ_NC_MISMATCH = 0x2161, + // The requested domain could not be deleted because there exist domain controllers that still host this domain. + DS_NC_STILL_HAS_DSAS = 0x2162, + // The requested operation can be performed only on a global catalog server. + DS_GC_REQUIRED = 0x2163, + // A local group can only be a member of other local groups in the same domain. + DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 0x2164, + // Foreign security principals cannot be members of universal groups. + DS_NO_FPO_IN_UNIVERSAL_GROUPS = 0x2165, + // The attribute is not allowed to be replicated to the GC because of security reasons. + DS_CANT_ADD_TO_GC = 0x2166, + // The checkpoint with the PDC could not be taken because there too many modifications being processed currently. + DS_NO_CHECKPOINT_WITH_PDC = 0x2167, + // The operation requires that source domain auditing be enabled. + DS_SOURCE_AUDITING_NOT_ENABLED = 0x2168, + // Security principal objects can only be created inside domain naming contexts. + DS_CANT_CREATE_IN_NONDOMAIN_NC = 0x2169, + // A Service Principal Name (SPN) could not be constructed because the provided hostname is not in the necessary format. + DS_INVALID_NAME_FOR_SPN = 0x216A, + // A Filter was passed that uses constructed attributes. + DS_FILTER_USES_CONTRUCTED_ATTRS = 0x216B, + // The unicodePwd attribute value must be enclosed in double quotes. + DS_UNICODEPWD_NOT_IN_QUOTES = 0x216C, + // Your computer could not be joined to the domain. You have exceeded the maximum number of computer accounts you are allowed to create in this domain. Contact your system administrator to have this limit reset or increased. + DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 0x216D, + // For security reasons, the operation must be run on the destination DC. + DS_MUST_BE_RUN_ON_DST_DC = 0x216E, + // For security reasons, the source DC must be NT4SP4 or greater. + DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 0x216F, + // Critical Directory Service System objects cannot be deleted during tree delete operations. The tree delete may have been partially performed. + DS_CANT_TREE_DELETE_CRITICAL_OBJ = 0x2170, + // Directory Services could not start because of the following error: %1. Error Status: 0x%2. Please click OK to shutdown the system. You can use the recovery console to diagnose the system further. + DS_INIT_FAILURE_CONSOLE = 0x2171, + // Security Accounts Manager initialization failed because of the following error: %1. Error Status: 0x%2. Please click OK to shutdown the system. You can use the recovery console to diagnose the system further. + DS_SAM_INIT_FAILURE_CONSOLE = 0x2172, + // The version of the operating system is incompatible with the current AD DS forest functional level or AD LDS Configuration Set functional level. You must upgrade to a new version of the operating system before this server can become an AD DS Domain Controller or add an AD LDS Instance in this AD DS Forest or AD LDS Configuration Set. + DS_FOREST_VERSION_TOO_HIGH = 0x2173, + // The version of the operating system installed is incompatible with the current domain functional level. You must upgrade to a new version of the operating system before this server can become a domain controller in this domain. + DS_DOMAIN_VERSION_TOO_HIGH = 0x2174, + // The version of the operating system installed on this server no longer supports the current AD DS Forest functional level or AD LDS Configuration Set functional level. You must raise the AD DS Forest functional level or AD LDS Configuration Set functional level before this server can become an AD DS Domain Controller or an AD LDS Instance in this Forest or Configuration Set. + DS_FOREST_VERSION_TOO_LOW = 0x2175, + // The version of the operating system installed on this server no longer supports the current domain functional level. You must raise the domain functional level before this server can become a domain controller in this domain. + DS_DOMAIN_VERSION_TOO_LOW = 0x2176, + // The version of the operating system installed on this server is incompatible with the functional level of the domain or forest. + DS_INCOMPATIBLE_VERSION = 0x2177, + // The functional level of the domain (or forest) cannot be raised to the requested value, because there exist one or more domain controllers in the domain (or forest) that are at a lower incompatible functional level. + DS_LOW_DSA_VERSION = 0x2178, + // The forest functional level cannot be raised to the requested value since one or more domains are still in mixed domain mode. All domains in the forest must be in native mode, for you to raise the forest functional level. + DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 0x2179, + // The sort order requested is not supported. + DS_NOT_SUPPORTED_SORT_ORDER = 0x217A, + // The requested name already exists as a unique identifier. + DS_NAME_NOT_UNIQUE = 0x217B, + // The machine account was created pre-NT4. The account needs to be recreated. + DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 0x217C, + // The database is out of version store. + DS_OUT_OF_VERSION_STORE = 0x217D, + // Unable to continue operation because multiple conflicting controls were used. + DS_INCOMPATIBLE_CONTROLS_USED = 0x217E, + // Unable to find a valid security descriptor reference domain for this partition. + DS_NO_REF_DOMAIN = 0x217F, + // Schema update failed: The link identifier is reserved. + DS_RESERVED_LINK_ID = 0x2180, + // Schema update failed: There are no link identifiers available. + DS_LINK_ID_NOT_AVAILABLE = 0x2181, + // An account group cannot have a universal group as a member. + DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 0x2182, + // Rename or move operations on naming context heads or read-only objects are not allowed. + DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 0x2183, + // Move operations on objects in the schema naming context are not allowed. + DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 0x2184, + // A system flag has been set on the object and does not allow the object to be moved or renamed. + DS_MODIFYDN_DISALLOWED_BY_FLAG = 0x2185, + // This object is not allowed to change its grandparent container. Moves are not forbidden on this object, but are restricted to sibling containers. + DS_MODIFYDN_WRONG_GRANDPARENT = 0x2186, + // Unable to resolve completely, a referral to another forest is generated. + DS_NAME_ERROR_TRUST_REFERRAL = 0x2187, + // The requested action is not supported on standard server. + NOT_SUPPORTED_ON_STANDARD_SERVER = 0x2188, + // Could not access a partition of the directory service located on a remote server. Make sure at least one server is running for the partition in question. + DS_CANT_ACCESS_REMOTE_PART_OF_AD = 0x2189, + // The directory cannot validate the proposed naming context (or partition) name because it does not hold a replica nor can it contact a replica of the naming context above the proposed naming context. Please ensure that the parent naming context is properly registered in DNS, and at least one replica of this naming context is reachable by the Domain Naming master. + DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 0x218A, + // The thread limit for this request was exceeded. + DS_THREAD_LIMIT_EXCEEDED = 0x218B, + // The Global catalog server is not in the closest site. + DS_NOT_CLOSEST = 0x218C, + // The DS cannot derive a service principal name (SPN) with which to mutually authenticate the target server because the corresponding server object in the local DS database has no serverReference attribute. + DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 0x218D, + // The Directory Service failed to enter single user mode. + DS_SINGLE_USER_MODE_FAILED = 0x218E, + // The Directory Service cannot parse the script because of a syntax error. + DS_NTDSCRIPT_SYNTAX_ERROR = 0x218F, + // The Directory Service cannot process the script because of an error. + DS_NTDSCRIPT_PROCESS_ERROR = 0x2190, + // The directory service cannot perform the requested operation because the servers involved are of different replication epochs (which is usually related to a domain rename that is in progress). + DS_DIFFERENT_REPL_EPOCHS = 0x2191, + // The directory service binding must be renegotiated due to a change in the server extensions information. + DS_DRS_EXTENSIONS_CHANGED = 0x2192, + // Operation not allowed on a disabled cross ref. + DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 0x2193, + // Schema update failed: No values for msDS-IntId are available. + DS_NO_MSDS_INTID = 0x2194, + // Schema update failed: Duplicate msDS-INtId. Retry the operation. + DS_DUP_MSDS_INTID = 0x2195, + // Schema deletion failed: attribute is used in rDNAttID. + DS_EXISTS_IN_RDNATTID = 0x2196, + // The directory service failed to authorize the request. + DS_AUTHORIZATION_FAILED = 0x2197, + // The Directory Service cannot process the script because it is invalid. + DS_INVALID_SCRIPT = 0x2198, + // The remote create cross reference operation failed on the Domain Naming Master FSMO. The operation's error is in the extended data. + DS_REMOTE_CROSSREF_OP_FAILED = 0x2199, + // A cross reference is in use locally with the same name. + DS_CROSS_REF_BUSY = 0x219A, + // The DS cannot derive a service principal name (SPN) with which to mutually authenticate the target server because the server's domain has been deleted from the forest. + DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 0x219B, + // Writeable NCs prevent this DC from demoting. + DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 0x219C, + // The requested object has a non-unique identifier and cannot be retrieved. + DS_DUPLICATE_ID_FOUND = 0x219D, + // Insufficient attributes were given to create an object. This object may not exist because it may have been deleted and already garbage collected. + DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 0x219E, + // The group cannot be converted due to attribute restrictions on the requested group type. + DS_GROUP_CONVERSION_ERROR = 0x219F, + // Cross-domain move of non-empty basic application groups is not allowed. + DS_CANT_MOVE_APP_BASIC_GROUP = 0x21A0, + // Cross-domain move of non-empty query based application groups is not allowed. + DS_CANT_MOVE_APP_QUERY_GROUP = 0x21A1, + // The FSMO role ownership could not be verified because its directory partition has not replicated successfully with at least one replication partner. + DS_ROLE_NOT_VERIFIED = 0x21A2, + // The target container for a redirection of a well known object container cannot already be a special container. + DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 0x21A3, + // The Directory Service cannot perform the requested operation because a domain rename operation is in progress. + DS_DOMAIN_RENAME_IN_PROGRESS = 0x21A4, + // The directory service detected a child partition below the requested partition name. The partition hierarchy must be created in a top down method. + DS_EXISTING_AD_CHILD_NC = 0x21A5, + // The directory service cannot replicate with this server because the time since the last replication with this server has exceeded the tombstone lifetime. + DS_REPL_LIFETIME_EXCEEDED = 0x21A6, + // The requested operation is not allowed on an object under the system container. + DS_DISALLOWED_IN_SYSTEM_CONTAINER = 0x21A7, + // The LDAP servers network send queue has filled up because the client is not processing the results of its requests fast enough. No more requests will be processed until the client catches up. If the client does not catch up then it will be disconnected. + DS_LDAP_SEND_QUEUE_FULL = 0x21A8, + // The scheduled replication did not take place because the system was too busy to execute the request within the schedule window. The replication queue is overloaded. Consider reducing the number of partners or decreasing the scheduled replication frequency. + DS_DRA_OUT_SCHEDULE_WINDOW = 0x21A9, + // At this time, it cannot be determined if the branch replication policy is available on the hub domain controller. Please retry at a later time to account for replication latencies. + DS_POLICY_NOT_KNOWN = 0x21AA, + // The site settings object for the specified site does not exist. + NO_SITE_SETTINGS_OBJECT = 0x21AB, + // The local account store does not contain secret material for the specified account. + NO_SECRETS = 0x21AC, + // Could not find a writable domain controller in the domain. + NO_WRITABLE_DC_FOUND = 0x21AD, + // The server object for the domain controller does not exist. + DS_NO_SERVER_OBJECT = 0x21AE, + // The NTDS Settings object for the domain controller does not exist. + DS_NO_NTDSA_OBJECT = 0x21AF, + // The requested search operation is not supported for ASQ searches. + DS_NON_ASQ_SEARCH = 0x21B0, + // A required audit event could not be generated for the operation. + DS_AUDIT_FAILURE = 0x21B1, + // The search flags for the attribute are invalid. The subtree index bit is valid only on single valued attributes. + DS_INVALID_SEARCH_FLAG_SUBTREE = 0x21B2, + // The search flags for the attribute are invalid. The tuple index bit is valid only on attributes of Unicode strings. + DS_INVALID_SEARCH_FLAG_TUPLE = 0x21B3, + // The address books are nested too deeply. Failed to build the hierarchy table. + DS_HIERARCHY_TABLE_TOO_DEEP = 0x21B4, + // The specified up-to-date-ness vector is corrupt. + DS_DRA_CORRUPT_UTD_VECTOR = 0x21B5, + // The request to replicate secrets is denied. + DS_DRA_SECRETS_DENIED = 0x21B6, + // Schema update failed: The MAPI identifier is reserved. + DS_RESERVED_MAPI_ID = 0x21B7, + // Schema update failed: There are no MAPI identifiers available. + DS_MAPI_ID_NOT_AVAILABLE = 0x21B8, + // The replication operation failed because the required attributes of the local krbtgt object are missing. + DS_DRA_MISSING_KRBTGT_SECRET = 0x21B9, + // The domain name of the trusted domain already exists in the forest. + DS_DOMAIN_NAME_EXISTS_IN_FOREST = 0x21BA, + // The flat name of the trusted domain already exists in the forest. + DS_FLAT_NAME_EXISTS_IN_FOREST = 0x21BB, + // The User Principal Name (UPN) is invalid. + INVALID_USER_PRINCIPAL_NAME = 0x21BC, + // OID mapped groups cannot have members. + DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 0x21BD, + // The specified OID cannot be found. + DS_OID_NOT_FOUND = 0x21BE, + // The replication operation failed because the target object referred by a link value is recycled. + DS_DRA_RECYCLED_TARGET = 0x21BF, + // The redirect operation failed because the target object is in a NC different from the domain NC of the current domain controller. + DS_DISALLOWED_NC_REDIRECT = 0x21C0, + // The functional level of the AD LDS configuration set cannot be lowered to the requested value. + DS_HIGH_ADLDS_FFL = 0x21C1, + // The functional level of the domain (or forest) cannot be lowered to the requested value. + DS_HIGH_DSA_VERSION = 0x21C2, + // The functional level of the AD LDS configuration set cannot be raised to the requested value, because there exist one or more ADLDS instances that are at a lower incompatible functional level. + DS_LOW_ADLDS_FFL = 0x21C3, + // The domain join cannot be completed because the SID of the domain you attempted to join was identical to the SID of this machine. This is a symptom of an improperly cloned operating system install. You should run sysprep on this machine in order to generate a new machine SID. Please see https://go.microsoft.com/fwlink/p/?linkid=168895 for more information. + DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION = 0x21C4, + // The undelete operation failed because the Sam Account Name or Additional Sam Account Name of the object being undeleted conflicts with an existing live object. + DS_UNDELETE_SAM_VALIDATION_FAILED = 0x21C5, + // The system is not authoritative for the specified account and therefore cannot complete the operation. Please retry the operation using the provider associated with this account. If this is an online provider please use the provider's online site. + INCORRECT_ACCOUNT_TYPE = 0x21C6, + + + // DNS server unable to interpret format. + DNS_ERROR_RCODE_FORMAT_ERROR = 0x2329, + // DNS server failure. + DNS_ERROR_RCODE_SERVER_FAILURE = 0x232A, + // DNS name does not exist. + DNS_ERROR_RCODE_NAME_ERROR = 0x232B, + // DNS request not supported by name server. + DNS_ERROR_RCODE_NOT_IMPLEMENTED = 0x232C, + // DNS operation refused. + DNS_ERROR_RCODE_REFUSED = 0x232D, + // DNS name that ought not exist, does exist. + DNS_ERROR_RCODE_YXDOMAIN = 0x232E, + // DNS RR set that ought not exist, does exist. + DNS_ERROR_RCODE_YXRRSET = 0x232F, + // DNS RR set that ought to exist, does not exist. + DNS_ERROR_RCODE_NXRRSET = 0x2330, + // DNS server not authoritative for zone. + DNS_ERROR_RCODE_NOTAUTH = 0x2331, + // DNS name in update or prereq is not in zone. + DNS_ERROR_RCODE_NOTZONE = 0x2332, + // DNS signature failed to verify. + DNS_ERROR_RCODE_BADSIG = 0x2338, + // DNS bad key. + DNS_ERROR_RCODE_BADKEY = 0x2339, + // DNS signature validity expired. + DNS_ERROR_RCODE_BADTIME = 0x233A, + // Only the DNS server acting as the key master for the zone may perform this operation. + DNS_ERROR_KEYMASTER_REQUIRED = 0x238D, + // This operation is not allowed on a zone that is signed or has signing keys. + DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE = 0x238E, + // NSEC3 is not compatible with the RSA-SHA-1 algorithm. Choose a different algorithm or use NSEC. + // This value was also named DNS_ERROR_INVALID_NSEC3_PARAMETERS + DNS_ERROR_NSEC3_INCOMPATIBLE_WITH_RSA_SHA1 = 0x238F, + // The zone does not have enough signing keys. There must be at least one key signing key (KSK) and at least one zone signing key (ZSK). + DNS_ERROR_NOT_ENOUGH_SIGNING_KEY_DESCRIPTORS = 0x2390, + // The specified algorithm is not supported. + DNS_ERROR_UNSUPPORTED_ALGORITHM = 0x2391, + // The specified key size is not supported. + DNS_ERROR_INVALID_KEY_SIZE = 0x2392, + // One or more of the signing keys for a zone are not accessible to the DNS server. Zone signing will not be operational until this error is resolved. + DNS_ERROR_SIGNING_KEY_NOT_ACCESSIBLE = 0x2393, + // The specified key storage provider does not support DPAPI++ data protection. Zone signing will not be operational until this error is resolved. + DNS_ERROR_KSP_DOES_NOT_SUPPORT_PROTECTION = 0x2394, + // An unexpected DPAPI++ error was encountered. Zone signing will not be operational until this error is resolved. + DNS_ERROR_UNEXPECTED_DATA_PROTECTION_ERROR = 0x2395, + // An unexpected crypto error was encountered. Zone signing may not be operational until this error is resolved. + DNS_ERROR_UNEXPECTED_CNG_ERROR = 0x2396, + // The DNS server encountered a signing key with an unknown version. Zone signing will not be operational until this error is resolved. + DNS_ERROR_UNKNOWN_SIGNING_PARAMETER_VERSION = 0x2397, + // The specified key service provider cannot be opened by the DNS server. + DNS_ERROR_KSP_NOT_ACCESSIBLE = 0x2398, + // The DNS server cannot accept any more signing keys with the specified algorithm and KSK flag value for this zone. + DNS_ERROR_TOO_MANY_SKDS = 0x2399, + // The specified rollover period is invalid. + DNS_ERROR_INVALID_ROLLOVER_PERIOD = 0x239A, + // The specified initial rollover offset is invalid. + DNS_ERROR_INVALID_INITIAL_ROLLOVER_OFFSET = 0x239B, + // The specified signing key is already in process of rolling over keys. + DNS_ERROR_ROLLOVER_IN_PROGRESS = 0x239C, + // The specified signing key does not have a standby key to revoke. + DNS_ERROR_STANDBY_KEY_NOT_PRESENT = 0x239D, + // This operation is not allowed on a zone signing key (ZSK). + DNS_ERROR_NOT_ALLOWED_ON_ZSK = 0x239E, + // This operation is not allowed on an active signing key. + DNS_ERROR_NOT_ALLOWED_ON_ACTIVE_SKD = 0x239F, + // The specified signing key is already queued for rollover. + DNS_ERROR_ROLLOVER_ALREADY_QUEUED = 0x23A0, + // This operation is not allowed on an unsigned zone. + DNS_ERROR_NOT_ALLOWED_ON_UNSIGNED_ZONE = 0x23A1, + // This operation could not be completed because the DNS server listed as the current key master for this zone is down or misconfigured. Resolve the problem on the current key master for this zone or use another DNS server to seize the key master role. + DNS_ERROR_BAD_KEYMASTER = 0x23A2, + // The specified signature validity period is invalid. + DNS_ERROR_INVALID_SIGNATURE_VALIDITY_PERIOD = 0x23A3, + // The specified NSEC3 iteration count is higher than allowed by the minimum key length used in the zone. + DNS_ERROR_INVALID_NSEC3_ITERATION_COUNT = 0x23A4, + // This operation could not be completed because the DNS server has been configured with DNSSEC features disabled. Enable DNSSEC on the DNS server. + DNS_ERROR_DNSSEC_IS_DISABLED = 0x23A5, + // This operation could not be completed because the XML stream received is empty or syntactically invalid. + DNS_ERROR_INVALID_XML = 0x23A6, + // This operation completed, but no trust anchors were added because all of the trust anchors received were either invalid, unsupported, expired, or would not become valid in less than 30 days. + DNS_ERROR_NO_VALID_TRUST_ANCHORS = 0x23A7, + // The specified signing key is not waiting for parental DS update. + DNS_ERROR_ROLLOVER_NOT_POKEABLE = 0x23A8, + // Hash collision detected during NSEC3 signing. Specify a different user-provided salt, or use a randomly generated salt, and attempt to sign the zone again. + DNS_ERROR_NSEC3_NAME_COLLISION = 0x23A9, + // NSEC is not compatible with the NSEC3-RSA-SHA-1 algorithm. Choose a different algorithm or use NSEC3. + DNS_ERROR_NSEC_INCOMPATIBLE_WITH_NSEC3_RSA_SHA1 = 0x23AA, + // No records found for given DNS query. + DNS_INFO_NO_RECORDS = 0x251D, + // Bad DNS packet. + DNS_ERROR_BAD_PACKET = 0x251E, + // No DNS packet. + DNS_ERROR_NO_PACKET = 0x251F, + // DNS error, check rcode. + DNS_ERROR_RCODE = 0x2520, + // Unsecured DNS packet. + DNS_ERROR_UNSECURE_PACKET = 0x2521, + // DNS query request is pending. + DNS_REQUEST_PENDING = 0x2522, + // Invalid DNS type. + DNS_ERROR_INVALID_TYPE = 0x254F, + // Invalid IP address. + DNS_ERROR_INVALID_IP_ADDRESS = 0x2550, + // Invalid property. + DNS_ERROR_INVALID_PROPERTY = 0x2551, + // Try DNS operation again later. + DNS_ERROR_TRY_AGAIN_LATER = 0x2552, + // Record for given name and type is not unique. + DNS_ERROR_NOT_UNIQUE = 0x2553, + // DNS name does not comply with RFC specifications. + DNS_ERROR_NON_RFC_NAME = 0x2554, + // DNS name is a fully-qualified DNS name. + DNS_STATUS_FQDN = 0x2555, + // DNS name is dotted (multi-label). + DNS_STATUS_DOTTED_NAME = 0x2556, + // DNS name is a single-part name. + DNS_STATUS_SINGLE_PART_NAME = 0x2557, + // DNS name contains an invalid character. + DNS_ERROR_INVALID_NAME_CHAR = 0x2558, + // DNS name is entirely numeric. + DNS_ERROR_NUMERIC_NAME = 0x2559, + // The operation requested is not permitted on a DNS root server. + DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER = 0x255A, + // The record could not be created because this part of the DNS namespace has been delegated to another server. + DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION = 0x255B, + // The DNS server could not find a set of root hints. + DNS_ERROR_CANNOT_FIND_ROOT_HINTS = 0x255C, + // The DNS server found root hints but they were not consistent across all adapters. + DNS_ERROR_INCONSISTENT_ROOT_HINTS = 0x255D, + // The specified value is too small for this parameter. + DNS_ERROR_DWORD_VALUE_TOO_SMALL = 0x255E, + // The specified value is too large for this parameter. + DNS_ERROR_DWORD_VALUE_TOO_LARGE = 0x255F, + // This operation is not allowed while the DNS server is loading zones in the background. Please try again later. + DNS_ERROR_BACKGROUND_LOADING = 0x2560, + // The operation requested is not permitted on against a DNS server running on a read-only DC. + DNS_ERROR_NOT_ALLOWED_ON_RODC = 0x2561, + // No data is allowed to exist underneath a DNAME record. + DNS_ERROR_NOT_ALLOWED_UNDER_DNAME = 0x2562, + // This operation requires credentials delegation. + DNS_ERROR_DELEGATION_REQUIRED = 0x2563, + // Name resolution policy table has been corrupted. DNS resolution will fail until it is fixed. Contact your network administrator. + DNS_ERROR_INVALID_POLICY_TABLE = 0x2564, + // DNS zone does not exist. + DNS_ERROR_ZONE_DOES_NOT_EXIST = 0x2581, + // DNS zone information not available. + DNS_ERROR_NO_ZONE_INFO = 0x2582, + // Invalid operation for DNS zone. + DNS_ERROR_INVALID_ZONE_OPERATION = 0x2583, + // Invalid DNS zone configuration. + DNS_ERROR_ZONE_CONFIGURATION_ERROR = 0x2584, + // DNS zone has no start of authority (SOA) record. + DNS_ERROR_ZONE_HAS_NO_SOA_RECORD = 0x2585, + // DNS zone has no Name Server (NS) record. + DNS_ERROR_ZONE_HAS_NO_NS_RECORDS = 0x2586, + // DNS zone is locked. + DNS_ERROR_ZONE_LOCKED = 0x2587, + // DNS zone creation failed. + DNS_ERROR_ZONE_CREATION_FAILED = 0x2588, + // DNS zone already exists. + DNS_ERROR_ZONE_ALREADY_EXISTS = 0x2589, + // DNS automatic zone already exists. + DNS_ERROR_AUTOZONE_ALREADY_EXISTS = 0x258A, + // Invalid DNS zone type. + DNS_ERROR_INVALID_ZONE_TYPE = 0x258B, + // Secondary DNS zone requires master IP address. + DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP = 0x258C, + // DNS zone not secondary. + DNS_ERROR_ZONE_NOT_SECONDARY = 0x258D, + // Need secondary IP address. + DNS_ERROR_NEED_SECONDARY_ADDRESSES = 0x258E, + // WINS initialization failed. + DNS_ERROR_WINS_INIT_FAILED = 0x258F, + // Need WINS servers. + DNS_ERROR_NEED_WINS_SERVERS = 0x2590, + // NBTSTAT initialization call failed. + DNS_ERROR_NBSTAT_INIT_FAILED = 0x2591, + // Invalid delete of start of authority (SOA). + DNS_ERROR_SOA_DELETE_INVALID = 0x2592, + // A conditional forwarding zone already exists for that name. + DNS_ERROR_FORWARDER_ALREADY_EXISTS = 0x2593, + // This zone must be configured with one or more master DNS server IP addresses. + DNS_ERROR_ZONE_REQUIRES_MASTER_IP = 0x2594, + // The operation cannot be performed because this zone is shut down. + DNS_ERROR_ZONE_IS_SHUTDOWN = 0x2595, + // This operation cannot be performed because the zone is currently being signed. Please try again later. + DNS_ERROR_ZONE_LOCKED_FOR_SIGNING = 0x2596, + // Primary DNS zone requires datafile. + DNS_ERROR_PRIMARY_REQUIRES_DATAFILE = 0x25B3, + // Invalid datafile name for DNS zone. + DNS_ERROR_INVALID_DATAFILE_NAME = 0x25B4, + // Failed to open datafile for DNS zone. + DNS_ERROR_DATAFILE_OPEN_FAILURE = 0x25B5, + // Failed to write datafile for DNS zone. + DNS_ERROR_FILE_WRITEBACK_FAILED = 0x25B6, + // Failure while reading datafile for DNS zone. + DNS_ERROR_DATAFILE_PARSING = 0x25B7, + // DNS record does not exist. + DNS_ERROR_RECORD_DOES_NOT_EXIST = 0x25E5, + // DNS record format error. + DNS_ERROR_RECORD_FORMAT = 0x25E6, + // Node creation failure in DNS. + DNS_ERROR_NODE_CREATION_FAILED = 0x25E7, + // Unknown DNS record type. + DNS_ERROR_UNKNOWN_RECORD_TYPE = 0x25E8, + // DNS record timed out. + DNS_ERROR_RECORD_TIMED_OUT = 0x25E9, + // Name not in DNS zone. + DNS_ERROR_NAME_NOT_IN_ZONE = 0x25EA, + // CNAME loop detected. + DNS_ERROR_CNAME_LOOP = 0x25EB, + // Node is a CNAME DNS record. + DNS_ERROR_NODE_IS_CNAME = 0x25EC, + // A CNAME record already exists for given name. + DNS_ERROR_CNAME_COLLISION = 0x25ED, + // Record only at DNS zone root. + DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT = 0x25EE, + // DNS record already exists. + DNS_ERROR_RECORD_ALREADY_EXISTS = 0x25EF, + // Secondary DNS zone data error. + DNS_ERROR_SECONDARY_DATA = 0x25F0, + // Could not create DNS cache data. + DNS_ERROR_NO_CREATE_CACHE_DATA = 0x25F1, + // DNS name does not exist. + DNS_ERROR_NAME_DOES_NOT_EXIST = 0x25F2, + // Could not create pointer (PTR) record. + DNS_WARNING_PTR_CREATE_FAILED = 0x25F3, + // DNS domain was undeleted. + DNS_WARNING_DOMAIN_UNDELETED = 0x25F4, + // The directory service is unavailable. + DNS_ERROR_DS_UNAVAILABLE = 0x25F5, + // DNS zone already exists in the directory service. + DNS_ERROR_DS_ZONE_ALREADY_EXISTS = 0x25F6, + // DNS server not creating or reading the boot file for the directory service integrated DNS zone. + DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE = 0x25F7, + // Node is a DNAME DNS record. + DNS_ERROR_NODE_IS_DNAME = 0x25F8, + // A DNAME record already exists for given name. + DNS_ERROR_DNAME_COLLISION = 0x25F9, + // An alias loop has been detected with either CNAME or DNAME records. + DNS_ERROR_ALIAS_LOOP = 0x25FA, + // DNS AXFR (zone transfer) complete. + DNS_INFO_AXFR_COMPLETE = 0x2617, + // DNS zone transfer failed. + DNS_ERROR_AXFR = 0x2618, + // Added local WINS server. + DNS_INFO_ADDED_LOCAL_WINS = 0x2619, + // Secure update call needs to continue update request. + DNS_STATUS_CONTINUE_NEEDED = 0x2649, + // TCP/IP network protocol not installed. + DNS_ERROR_NO_TCPIP = 0x267B, + // No DNS servers configured for local system. + DNS_ERROR_NO_DNS_SERVERS = 0x267C, + // The specified directory partition does not exist. + DNS_ERROR_DP_DOES_NOT_EXIST = 0x26AD, + // The specified directory partition already exists. + DNS_ERROR_DP_ALREADY_EXISTS = 0x26AE, + // This DNS server is not enlisted in the specified directory partition. + DNS_ERROR_DP_NOT_ENLISTED = 0x26AF, + // This DNS server is already enlisted in the specified directory partition. + DNS_ERROR_DP_ALREADY_ENLISTED = 0x26B0, + // The directory partition is not available at this time. Please wait a few minutes and try again. + DNS_ERROR_DP_NOT_AVAILABLE = 0x26B1, + // The operation failed because the domain naming master FSMO role could not be reached. The domain controller holding the domain naming master FSMO role is down or unable to service the request or is not running Windows Server 2003 or later. + DNS_ERROR_DP_FSMO_ERROR = 0x26B2, + // A blocking operation was interrupted by a call to WSACancelBlockingCall. + WSAEINTR = 0x2714, + // The file handle supplied is not valid. + WSAEBADF = 0x2719, + // An attempt was made to access a socket in a way forbidden by its access permissions. + WSAEACCES = 0x271D, + // The system detected an invalid pointer address in attempting to use a pointer argument in a call. + WSAEFAULT = 0x271E, + // An invalid argument was supplied. + WSAEINVAL = 0x2726, + // Too many open sockets. + WSAEMFILE = 0x2728, + // A non-blocking socket operation could not be completed immediately. + WSAEWOULDBLOCK = 0x2733, + // A blocking operation is currently executing. + WSAEINPROGRESS = 0x2734, + // An operation was attempted on a non-blocking socket that already had an operation in progress. + WSAEALREADY = 0x2735, + // An operation was attempted on something that is not a socket. + WSAENOTSOCK = 0x2736, + // A required address was omitted from an operation on a socket. + WSAEDESTADDRREQ = 0x2737, + // A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself. + WSAEMSGSIZE = 0x2738, + // A protocol was specified in the socket function call that does not support the semantics of the socket type requested. + WSAEPROTOTYPE = 0x2739, + // An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call. + WSAENOPROTOOPT = 0x273A, + // The requested protocol has not been configured into the system, or no implementation for it exists. + WSAEPROTONOSUPPORT = 0x273B, + // The support for the specified socket type does not exist in this address family. + WSAESOCKTNOSUPPORT = 0x273C, + // The attempted operation is not supported for the type of object referenced. + WSAEOPNOTSUPP = 0x273D, + // The protocol family has not been configured into the system or no implementation for it exists. + WSAEPFNOSUPPORT = 0x273E, + // An address incompatible with the requested protocol was used. + WSAEAFNOSUPPORT = 0x273F, + // Only one usage of each socket address (protocol/network address/port) is normally permitted. + WSAEADDRINUSE = 0x2740, + // The requested address is not valid in its context. + WSAEADDRNOTAVAIL = 0x2741, + // A socket operation encountered a dead network. + WSAENETDOWN = 0x2742, + // A socket operation was attempted to an unreachable network. + WSAENETUNREACH = 0x2743, + // The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress. + WSAENETRESET = 0x2744, + // An established connection was aborted by the software in your host machine. + WSAECONNABORTED = 0x2745, + // An existing connection was forcibly closed by the remote host. + WSAECONNRESET = 0x2746, + // An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full. + WSAENOBUFS = 0x2747, + // A connect request was made on an already connected socket. + WSAEISCONN = 0x2748, + // A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied. + WSAENOTCONN = 0x2749, + // A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call. + WSAESHUTDOWN = 0x274A, + // Too many references to some kernel object. + WSAETOOMANYREFS = 0x274B, + // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. + WSAETIMEDOUT = 0x274C, + // No connection could be made because the target machine actively refused it. + WSAECONNREFUSED = 0x274D, + // Cannot translate name. + WSAELOOP = 0x274E, + // Name component or name was too long. + WSAENAMETOOLONG = 0x274F, + // A socket operation failed because the destination host was down. + WSAEHOSTDOWN = 0x2750, + // A socket operation was attempted to an unreachable host. + WSAEHOSTUNREACH = 0x2751, + // Cannot remove a directory that is not empty. + WSAENOTEMPTY = 0x2752, + // A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously. + WSAEPROCLIM = 0x2753, + // Ran out of quota. + WSAEUSERS = 0x2754, + // Ran out of disk quota. + WSAEDQUOT = 0x2755, + // File handle reference is no longer available. + WSAESTALE = 0x2756, + // Item is not available locally. + WSAEREMOTE = 0x2757, + // WSAStartup cannot function at this time because the underlying system it uses to provide network services is currently unavailable. = = 0x276C, + WSASYSNOTREADY = 0x276B, // The Windows Sockets version requested is not supported. + // Either the application has not called WSAStartup, or WSAStartup failed. + WSANOTINITIALISED = 0x276D, + // Returned by WSARecv or WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence. + WSAEDISCON = 0x2775, + // No more results can be returned by WSALookupServiceNext. + WSAENOMORE = 0x2776, + // A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled. + WSAECANCELLED = 0x2777, + // The procedure call table is invalid. + WSAEINVALIDPROCTABLE = 0x2778, + // The requested service provider is invalid. + WSAEINVALIDPROVIDER = 0x2779, + // The requested service provider could not be loaded or initialized. + WSAEPROVIDERFAILEDINIT = 0x277A, + // A system call has failed. + WSASYSCALLFAILURE = 0x277B, + // No such service is known. The service cannot be found in the specified name space. + WSASERVICE_NOT_FOUND = 0x277C, + // The specified class was not found. + WSATYPE_NOT_FOUND = 0x277D, + // No more results can be returned by WSALookupServiceNext. + WSA_E_NO_MORE = 0x277E, + // A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled. + WSA_E_CANCELLED = 0x277F, + // A database query failed because it was actively refused. + WSAEREFUSED = 0x2780, + // No such host is known. + WSAHOST_NOT_FOUND = 0x2AF9, + // This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server. + WSATRY_AGAIN = 0x2AFA, + // A non-recoverable error occurred during a database lookup. + WSANO_RECOVERY = 0x2AFB, + // The requested name is valid, but no data of the requested type was found. + WSANO_DATA = 0x2AFC, + // At least one reserve has arrived. + WSA_QOS_RECEIVERS = 0x2AFD, + // At least one path has arrived. + WSA_QOS_SENDERS = 0x2AFE, + // There are no senders. + WSA_QOS_NO_SENDERS = 0x2AFF, + // There are no receivers. + WSA_QOS_NO_RECEIVERS = 0x2B00, + // Reserve has been confirmed. + WSA_QOS_REQUEST_CONFIRMED = 0x2B01, + // Error due to lack of resources. + WSA_QOS_ADMISSION_FAILURE = 0x2B02, + // Rejected for administrative reasons - bad credentials. + WSA_QOS_POLICY_FAILURE = 0x2B03, + // Unknown or conflicting style. + WSA_QOS_BAD_STYLE = 0x2B04, + // Problem with some part of the filterspec or providerspecific buffer in general. + WSA_QOS_BAD_OBJECT = 0x2B05, + // Problem with some part of the flowspec. + WSA_QOS_TRAFFIC_CTRL_ERROR = 0x2B06, + // General QOS error. + WSA_QOS_GENERIC_ERROR = 0x2B07, + // An invalid or unrecognized service type was found in the flowspec. + WSA_QOS_ESERVICETYPE = 0x2B08, + // An invalid or inconsistent flowspec was found in the QOS structure. + WSA_QOS_EFLOWSPEC = 0x2B09, + // Invalid QOS provider-specific buffer. + WSA_QOS_EPROVSPECBUF = 0x2B0A, + // An invalid QOS filter style was used. + WSA_QOS_EFILTERSTYLE = 0x2B0B, + // An invalid QOS filter type was used. + WSA_QOS_EFILTERTYPE = 0x2B0C, + // An incorrect number of QOS FILTERSPECs were specified in the FLOWDESCRIPTOR. + WSA_QOS_EFILTERCOUNT = 0x2B0D, + // An object with an invalid ObjectLength field was specified in the QOS provider-specific buffer. + WSA_QOS_EOBJLENGTH = 0x2B0E, + // An incorrect number of flow descriptors was specified in the QOS structure. + WSA_QOS_EFLOWCOUNT = 0x2B0F, + // An unrecognized object was found in the QOS provider-specific buffer. + WSA_QOS_EUNKOWNPSOBJ = 0x2B10, + // An invalid policy object was found in the QOS provider-specific buffer. + WSA_QOS_EPOLICYOBJ = 0x2B11, + // An invalid QOS flow descriptor was found in the flow descriptor list. + WSA_QOS_EFLOWDESC = 0x2B12, + // An invalid or inconsistent flowspec was found in the QOS provider specific buffer. + WSA_QOS_EPSFLOWSPEC = 0x2B13, + // An invalid FILTERSPEC was found in the QOS provider-specific buffer. + WSA_QOS_EPSFILTERSPEC = 0x2B14, + // An invalid shape discard mode object was found in the QOS provider specific buffer. + WSA_QOS_ESDMODEOBJ = 0x2B15, + // An invalid shaping rate object was found in the QOS provider-specific buffer. + WSA_QOS_ESHAPERATEOBJ = 0x2B16, + // A reserved policy element was found in the QOS provider-specific buffer. + WSA_QOS_RESERVED_PETYPE = 0x2B17, + // No such host is known securely. + WSA_SECURE_HOST_NOT_FOUND = 0x2B18, + // Name based IPSEC policy could not be added. + WSA_IPSEC_NAME_POLICY_ERROR = 0x2B19, + + // See Internet Error Codes and WinInet.h. + INTERNET_ = 0x2EE0, + // See WinHTTP Error Codes and Winhttp.h. + WINHTTP_ = 0x2EE1, + // The specified quick mode policy already exists. + IPSEC_QM_POLICY_EXISTS = 0x32C8, + // The specified quick mode policy was not found. + IPSEC_QM_POLICY_NOT_FOUND = 0x32C9, + // The specified quick mode policy is being used. + IPSEC_QM_POLICY_IN_USE = 0x32CA, + // The specified main mode policy already exists. + IPSEC_MM_POLICY_EXISTS = 0x32CB, + // The specified main mode policy was not found. + IPSEC_MM_POLICY_NOT_FOUND = 0x32CC, + // The specified main mode policy is being used. + IPSEC_MM_POLICY_IN_USE = 0x32CD, + // The specified main mode filter already exists. + IPSEC_MM_FILTER_EXISTS = 0x32CE, + // The specified main mode filter was not found. + IPSEC_MM_FILTER_NOT_FOUND = 0x32CF, + // The specified transport mode filter already exists. + IPSEC_TRANSPORT_FILTER_EXISTS = 0x32D0, + // The specified transport mode filter does not exist. + IPSEC_TRANSPORT_FILTER_NOT_FOUND = 0x32D1, + // The specified main mode authentication list exists. + IPSEC_MM_AUTH_EXISTS = 0x32D2, + // The specified main mode authentication list was not found. + IPSEC_MM_AUTH_NOT_FOUND = 0x32D3, + // The specified main mode authentication list is being used. + IPSEC_MM_AUTH_IN_USE = 0x32D4, + // The specified default main mode policy was not found. + IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 0x32D5, + // The specified default main mode authentication list was not found. + IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 0x32D6, + // The specified default quick mode policy was not found. + IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 0x32D7, + // The specified tunnel mode filter exists. + IPSEC_TUNNEL_FILTER_EXISTS = 0x32D8, + // The specified tunnel mode filter was not found. + IPSEC_TUNNEL_FILTER_NOT_FOUND = 0x32D9, + // The Main Mode filter is pending deletion. + IPSEC_MM_FILTER_PENDING_DELETION = 0x32DA, + // The transport filter is pending deletion. + IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 0x32DB, + // The tunnel filter is pending deletion. + IPSEC_TUNNEL_FILTER_PENDING_DELETION = 0x32DC, + // The Main Mode policy is pending deletion. + IPSEC_MM_POLICY_PENDING_DELETION = 0x32DD, + // The Main Mode authentication bundle is pending deletion. + IPSEC_MM_AUTH_PENDING_DELETION = 0x32DE, + // The Quick Mode policy is pending deletion. + IPSEC_QM_POLICY_PENDING_DELETION = 0x32DF, + // The Main Mode policy was successfully added, but some of the requested offers are not supported. + WARNING_IPSEC_MM_POLICY_PRUNED = 0x32E0, + // The Quick Mode policy was successfully added, but some of the requested offers are not supported. + WARNING_IPSEC_QM_POLICY_PRUNED = 0x32E1, + // IPSEC_IKE_NEG_STATUS_BEGIN = = 0x35E9, + IPSEC_IKE_NEG_STATUS_BEGIN = 0x35E8, // IKE authentication credentials are unacceptable. + // IKE security attributes are unacceptable. + IPSEC_IKE_ATTRIB_FAIL = 0x35EA, + // IKE Negotiation in progress. + IPSEC_IKE_NEGOTIATION_PENDING = 0x35EB, + // General processing error. + IPSEC_IKE_GENERAL_PROCESSING_ERROR = 0x35EC, + // Negotiation timed out. + IPSEC_IKE_TIMED_OUT = 0x35ED, + // IKE failed to find valid machine certificate. Contact your Network Security Administrator about installing a valid certificate in the appropriate Certificate Store. + IPSEC_IKE_NO_CERT = 0x35EE, + // IKE SA deleted by peer before establishment completed. + IPSEC_IKE_SA_DELETED = 0x35EF, + // IKE SA deleted before establishment completed. + IPSEC_IKE_SA_REAPED = 0x35F0, + // Negotiation request sat in Queue too long. + IPSEC_IKE_MM_ACQUIRE_DROP = 0x35F1, + // Negotiation request sat in Queue too long. + IPSEC_IKE_QM_ACQUIRE_DROP = 0x35F2, + // Negotiation request sat in Queue too long. + IPSEC_IKE_QUEUE_DROP_MM = 0x35F3, + // Negotiation request sat in Queue too long. + IPSEC_IKE_QUEUE_DROP_NO_MM = 0x35F4, + // No response from peer. + IPSEC_IKE_DROP_NO_RESPONSE = 0x35F5, + // Negotiation took too long. + IPSEC_IKE_MM_DELAY_DROP = 0x35F6, + // Negotiation took too long. + IPSEC_IKE_QM_DELAY_DROP = 0x35F7, + // Unknown error occurred. + IPSEC_IKE_ERROR = 0x35F8, + // Certificate Revocation Check failed. + IPSEC_IKE_CRL_FAILED = 0x35F9, + // Invalid certificate key usage. + IPSEC_IKE_INVALID_KEY_USAGE = 0x35FA, + // Invalid certificate type. + IPSEC_IKE_INVALID_CERT_TYPE = 0x35FB, + // IKE negotiation failed because the machine certificate used does not have a private key. IPsec certificates require a private key. Contact your Network Security administrator about replacing with a certificate that has a private key. + IPSEC_IKE_NO_PRIVATE_KEY = 0x35FC, + // Simultaneous rekeys were detected. + IPSEC_IKE_SIMULTANEOUS_REKEY = 0x35FD, + // Failure in Diffie-Hellman computation. + IPSEC_IKE_DH_FAIL = 0x35FE, + // Don't know how to process critical payload. + IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED = 0x35FF, + // Invalid header. + IPSEC_IKE_INVALID_HEADER = 0x3600, + // No policy configured. + IPSEC_IKE_NO_POLICY = 0x3601, + // Failed to verify signature. + IPSEC_IKE_INVALID_SIGNATURE = 0x3602, + // Failed to authenticate using Kerberos. + IPSEC_IKE_KERBEROS_ERROR = 0x3603, + // Peer's certificate did not have a public key. + IPSEC_IKE_NO_PUBLIC_KEY = 0x3604, + // Error processing error payload. + IPSEC_IKE_PROCESS_ERR = 0x3605, + // Error processing SA payload. + IPSEC_IKE_PROCESS_ERR_SA = 0x3606, + // Error processing Proposal payload. + IPSEC_IKE_PROCESS_ERR_PROP = 0x3607, + // Error processing Transform payload. + IPSEC_IKE_PROCESS_ERR_TRANS = 0x3608, + // Error processing KE payload. + IPSEC_IKE_PROCESS_ERR_KE = 0x3609, + // Error processing ID payload. + IPSEC_IKE_PROCESS_ERR_ID = 0x360A, + // Error processing Cert payload. + IPSEC_IKE_PROCESS_ERR_CERT = 0x360B, + // Error processing Certificate Request payload. + IPSEC_IKE_PROCESS_ERR_CERT_REQ = 0x360C, + // Error processing Hash payload. + IPSEC_IKE_PROCESS_ERR_HASH = 0x360D, + // Error processing Signature payload. + IPSEC_IKE_PROCESS_ERR_SIG = 0x360E, + // Error processing Nonce payload. + IPSEC_IKE_PROCESS_ERR_NONCE = 0x360F, + // Error processing Notify payload. + IPSEC_IKE_PROCESS_ERR_NOTIFY = 0x3610, + // Error processing Delete Payload. + IPSEC_IKE_PROCESS_ERR_DELETE = 0x3611, + // Error processing VendorId payload. + IPSEC_IKE_PROCESS_ERR_VENDOR = 0x3612, + // Invalid payload received. + IPSEC_IKE_INVALID_PAYLOAD = 0x3613, + // Soft SA loaded. + IPSEC_IKE_LOAD_SOFT_SA = 0x3614, + // Soft SA torn down. + IPSEC_IKE_SOFT_SA_TORN_DOWN = 0x3615, + // Invalid cookie received. + IPSEC_IKE_INVALID_COOKIE = 0x3616, + // Peer failed to send valid machine certificate. + IPSEC_IKE_NO_PEER_CERT = 0x3617, + // Certification Revocation check of peer's certificate failed. + IPSEC_IKE_PEER_CRL_FAILED = 0x3618, + // New policy invalidated SAs formed with old policy. + IPSEC_IKE_POLICY_CHANGE = 0x3619, + // There is no available Main Mode IKE policy. + IPSEC_IKE_NO_MM_POLICY = 0x361A, + // Failed to enabled TCB privilege. + IPSEC_IKE_NOTCBPRIV = 0x361B, + // Failed to load SECURITY.DLL. + IPSEC_IKE_SECLOADFAIL = 0x361C, + // Failed to obtain security function table dispatch address from SSPI. + IPSEC_IKE_FAILSSPINIT = 0x361D, + // Failed to query Kerberos package to obtain max token size. + IPSEC_IKE_FAILQUERYSSP = 0x361E, + // Failed to obtain Kerberos server credentials for ISAKMP/ERROR_IPSEC_IKE service. Kerberos authentication will not function. The most likely reason for this is lack of domain membership. This is normal if your computer is a member of a workgroup. + IPSEC_IKE_SRVACQFAIL = 0x361F, + // Failed to determine SSPI principal name for ISAKMP/ERROR_IPSEC_IKE service (QueryCredentialsAttributes). + IPSEC_IKE_SRVQUERYCRED = 0x3620, + // Failed to obtain new SPI for the inbound SA from IPsec driver. The most common cause for this is that the driver does not have the correct filter. Check your policy to verify the filters. + IPSEC_IKE_GETSPIFAIL = 0x3621, + // Given filter is invalid. + IPSEC_IKE_INVALID_FILTER = 0x3622, + // Memory allocation failed. + IPSEC_IKE_OUT_OF_MEMORY = 0x3623, + // Failed to add Security Association to IPsec Driver. The most common cause for this is if the IKE negotiation took too long to complete. If the problem persists, reduce the load on the faulting machine. + IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 0x3624, + // Invalid policy. + IPSEC_IKE_INVALID_POLICY = 0x3625, + // Invalid DOI. + IPSEC_IKE_UNKNOWN_DOI = 0x3626, + // Invalid situation. + IPSEC_IKE_INVALID_SITUATION = 0x3627, + // Diffie-Hellman failure. + IPSEC_IKE_DH_FAILURE = 0x3628, + // Invalid Diffie-Hellman group. + IPSEC_IKE_INVALID_GROUP = 0x3629, + // Error encrypting payload. + IPSEC_IKE_ENCRYPT = 0x362A, + // Error decrypting payload. + IPSEC_IKE_DECRYPT = 0x362B, + // Policy match error. + IPSEC_IKE_POLICY_MATCH = 0x362C, + // Unsupported ID. + IPSEC_IKE_UNSUPPORTED_ID = 0x362D, + // Hash verification failed. + IPSEC_IKE_INVALID_HASH = 0x362E, + // Invalid hash algorithm. + IPSEC_IKE_INVALID_HASH_ALG = 0x362F, + // Invalid hash size. + IPSEC_IKE_INVALID_HASH_SIZE = 0x3630, + // Invalid encryption algorithm. + IPSEC_IKE_INVALID_ENCRYPT_ALG = 0x3631, + // Invalid authentication algorithm. + IPSEC_IKE_INVALID_AUTH_ALG = 0x3632, + // Invalid certificate signature. + IPSEC_IKE_INVALID_SIG = 0x3633, + // Load failed. + IPSEC_IKE_LOAD_FAILED = 0x3634, + // Deleted via RPC call. + IPSEC_IKE_RPC_DELETE = 0x3635, + // Temporary state created to perform reinitialization. This is not a real failure. + IPSEC_IKE_BENIGN_REINIT = 0x3636, + // The lifetime value received in the Responder Lifetime Notify is below the Windows 2000 configured minimum value. Please fix the policy on the peer machine. + IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 0x3637, + // The recipient cannot handle version of IKE specified in the header. + IPSEC_IKE_INVALID_MAJOR_VERSION = 0x3638, + // Key length in certificate is too small for configured security requirements. + IPSEC_IKE_INVALID_CERT_KEYLEN = 0x3639, + // Max number of established MM SAs to peer exceeded. + IPSEC_IKE_MM_LIMIT = 0x363A, + // IKE received a policy that disables negotiation. + IPSEC_IKE_NEGOTIATION_DISABLED = 0x363B, + // Reached maximum quick mode limit for the main mode. New main mode will be started. + IPSEC_IKE_QM_LIMIT = 0x363C, + // Main mode SA lifetime expired or peer sent a main mode delete. + IPSEC_IKE_MM_EXPIRED = 0x363D, + // Main mode SA assumed to be invalid because peer stopped responding. + IPSEC_IKE_PEER_MM_ASSUMED_INVALID = 0x363E, + // Certificate doesn't chain to a trusted root in IPsec policy. + IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH = 0x363F, + // Received unexpected message ID. + IPSEC_IKE_UNEXPECTED_MESSAGE_ID = 0x3640, + // Received invalid authentication offers. + IPSEC_IKE_INVALID_AUTH_PAYLOAD = 0x3641, + // Sent DoS cookie notify to initiator. + IPSEC_IKE_DOS_COOKIE_SENT = 0x3642, + // IKE service is shutting down. + IPSEC_IKE_SHUTTING_DOWN = 0x3643, + // Could not verify binding between CGA address and certificate. + IPSEC_IKE_CGA_AUTH_FAILED = 0x3644, + // Error processing NatOA payload. + IPSEC_IKE_PROCESS_ERR_NATOA = 0x3645, + // Parameters of the main mode are invalid for this quick mode. + IPSEC_IKE_INVALID_MM_FOR_QM = 0x3646, + // Quick mode SA was expired by IPsec driver. + IPSEC_IKE_QM_EXPIRED = 0x3647, + // Too many dynamically added IKEEXT filters were detected. + IPSEC_IKE_TOO_MANY_FILTERS = 0x3648, + // IPSEC_IKE_NEG_STATUS_END = = 0x364A, + IPSEC_IKE_NEG_STATUS_END = 0x3649, // NAP reauth succeeded and must delete the dummy NAP IKEv2 tunnel. + // Error in assigning inner IP address to initiator in tunnel mode. + IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE = 0x364B, + // Require configuration payload missing. + IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING = 0x364C, + // A negotiation running as the security principle who issued the connection is in progress. + IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING = 0x364D, + // SA was deleted due to IKEv1/AuthIP co-existence suppress check. + IPSEC_IKE_COEXISTENCE_SUPPRESS = 0x364E, + // Incoming SA request was dropped due to peer IP address rate limiting. + IPSEC_IKE_RATELIMIT_DROP = 0x364F, + // Peer does not support MOBIKE. + IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE = 0x3650, + // SA establishment is not authorized. + IPSEC_IKE_AUTHORIZATION_FAILURE = 0x3651, + // SA establishment is not authorized because there is not a sufficiently strong PKINIT-based credential. + IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE = 0x3652, + // SA establishment is not authorized. You may need to enter updated or different credentials such as a smartcard. + IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY = 0x3653, + // SA establishment is not authorized because there is not a sufficiently strong PKINIT-based credential. This might be related to certificate-to-account mapping failure for the SA. + IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE = 0x3654, + // IPSEC_IKE_NEG_STATUS_EXTENDED_END = = 0x3656, + IPSEC_IKE_NEG_STATUS_EXTENDED_END = 0x3655, // The SPI in the packet does not match a valid IPsec SA. + // Packet was received on an IPsec SA whose lifetime has expired. + IPSEC_SA_LIFETIME_EXPIRED = 0x3657, + // Packet was received on an IPsec SA that does not match the packet characteristics. + IPSEC_WRONG_SA = 0x3658, + // Packet sequence number replay check failed. + IPSEC_REPLAY_CHECK_FAILED = 0x3659, + // IPsec header and/or trailer in the packet is invalid. + IPSEC_INVALID_PACKET = 0x365A, + // IPsec integrity check failed. + IPSEC_INTEGRITY_CHECK_FAILED = 0x365B, + // IPsec dropped a clear text packet. + IPSEC_CLEAR_TEXT_DROP = 0x365C, + // IPsec dropped an incoming ESP packet in authenticated firewall mode. This drop is benign. + IPSEC_AUTH_FIREWALL_DROP = 0x365D, + // IPsec dropped a packet due to DoS throttling. + IPSEC_THROTTLE_DROP = 0x365E, + // IPsec DoS Protection matched an explicit block rule. + IPSEC_DOSP_BLOCK = 0x3665, + // IPsec DoS Protection received an IPsec specific multicast packet which is not allowed. + IPSEC_DOSP_RECEIVED_MULTICAST = 0x3666, + // IPsec DoS Protection received an incorrectly formatted packet. + IPSEC_DOSP_INVALID_PACKET = 0x3667, + // IPsec DoS Protection failed to look up state. + IPSEC_DOSP_STATE_LOOKUP_FAILED = 0x3668, + // IPsec DoS Protection failed to create state because the maximum number of entries allowed by policy has been reached. + IPSEC_DOSP_MAX_ENTRIES = 0x3669, + // IPsec DoS Protection received an IPsec negotiation packet for a keying module which is not allowed by policy. + IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 0x366A, + // IPsec DoS Protection has not been enabled. + IPSEC_DOSP_NOT_INSTALLED = 0x366B, + // IPsec DoS Protection failed to create a per internal IP rate limit queue because the maximum number of queues allowed by policy has been reached. + IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 0x366C, + // The requested section was not present in the activation context. + SXS_SECTION_NOT_FOUND = 0x36B0, + // The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail. + SXS_CANT_GEN_ACTCTX = 0x36B1, + // The application binding data format is invalid. + SXS_INVALID_ACTCTXDATA_FORMAT = 0x36B2, + // The referenced assembly is not installed on your system. + SXS_ASSEMBLY_NOT_FOUND = 0x36B3, + // The manifest file does not begin with the required tag and format information. + SXS_MANIFEST_FORMAT_ERROR = 0x36B4, + // The manifest file contains one or more syntax errors. + SXS_MANIFEST_PARSE_ERROR = 0x36B5, + // The application attempted to activate a disabled activation context. + SXS_ACTIVATION_CONTEXT_DISABLED = 0x36B6, + // The requested lookup key was not found in any active activation context. + SXS_KEY_NOT_FOUND = 0x36B7, + // A component version required by the application conflicts with another component version already active. + SXS_VERSION_CONFLICT = 0x36B8, + // The type requested activation context section does not match the query API used. + SXS_WRONG_SECTION_TYPE = 0x36B9, + // Lack of system resources has required isolated activation to be disabled for the current thread of execution. + SXS_THREAD_QUERIES_DISABLED = 0x36BA, + // An attempt to set the process default activation context failed because the process default activation context was already set. + SXS_PROCESS_DEFAULT_ALREADY_SET = 0x36BB, + // The encoding group identifier specified is not recognized. + SXS_UNKNOWN_ENCODING_GROUP = 0x36BC, + // The encoding requested is not recognized. + SXS_UNKNOWN_ENCODING = 0x36BD, + // The manifest contains a reference to an invalid URI. + SXS_INVALID_XML_NAMESPACE_URI = 0x36BE, + // The application manifest contains a reference to a dependent assembly which is not installed. + SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED = 0x36BF, + // The manifest for an assembly used by the application has a reference to a dependent assembly which is not installed. + SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED = 0x36C0, + // The manifest contains an attribute for the assembly identity which is not valid. + SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE = 0x36C1, + // The manifest is missing the required default namespace specification on the assembly element. + SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE = 0x36C2, + // The manifest has a default namespace specified on the assembly element but its value is not "urn:schemas-microsoft-com:asm.v1". + SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE = 0x36C3, + // The private manifest probed has crossed a path with an unsupported reparse point. + SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT = 0x36C4, + // Two or more components referenced directly or indirectly by the application manifest have files by the same name. + SXS_DUPLICATE_DLL_NAME = 0x36C5, + // Two or more components referenced directly or indirectly by the application manifest have window classes with the same name. + SXS_DUPLICATE_WINDOWCLASS_NAME = 0x36C6, + // Two or more components referenced directly or indirectly by the application manifest have the same COM server CLSIDs. + SXS_DUPLICATE_CLSID = 0x36C7, + // Two or more components referenced directly or indirectly by the application manifest have proxies for the same COM interface IIDs. + SXS_DUPLICATE_IID = 0x36C8, + // Two or more components referenced directly or indirectly by the application manifest have the same COM type library TLBIDs. + SXS_DUPLICATE_TLBID = 0x36C9, + // Two or more components referenced directly or indirectly by the application manifest have the same COM ProgIDs. + SXS_DUPLICATE_PROGID = 0x36CA, + // Two or more components referenced directly or indirectly by the application manifest are different versions of the same component which is not permitted. + SXS_DUPLICATE_ASSEMBLY_NAME = 0x36CB, + // A component's file does not match the verification information present in the component manifest. + SXS_FILE_HASH_MISMATCH = 0x36CC, + // The policy manifest contains one or more syntax errors. + SXS_POLICY_PARSE_ERROR = 0x36CD, + // Manifest Parse Error : A string literal was expected, but no opening quote character was found. + SXS_XML_E_MISSINGQUOTE = 0x36CE, + // Manifest Parse Error : Incorrect syntax was used in a comment. + SXS_XML_E_COMMENTSYNTAX = 0x36CF, + // Manifest Parse Error : A name was started with an invalid character. + SXS_XML_E_BADSTARTNAMECHAR = 0x36D0, + // Manifest Parse Error : A name contained an invalid character. + SXS_XML_E_BADNAMECHAR = 0x36D1, + // Manifest Parse Error : A string literal contained an invalid character. + SXS_XML_E_BADCHARINSTRING = 0x36D2, + // Manifest Parse Error : Invalid syntax for an xml declaration. + SXS_XML_E_XMLDECLSYNTAX = 0x36D3, + // Manifest Parse Error : An Invalid character was found in text content. + SXS_XML_E_BADCHARDATA = 0x36D4, + // Manifest Parse Error : Required white space was missing. + SXS_XML_E_MISSINGWHITESPACE = 0x36D5, + // Manifest Parse Error : The character '>' was expected. + SXS_XML_E_EXPECTINGTAGEND = 0x36D6, + // Manifest Parse Error : A semi colon character was expected. + SXS_XML_E_MISSINGSEMICOLON = 0x36D7, + // Manifest Parse Error : Unbalanced parentheses. + SXS_XML_E_UNBALANCEDPAREN = 0x36D8, + // Manifest Parse Error : Internal error. + SXS_XML_E_INTERNALERROR = 0x36D9, + // Manifest Parse Error : Whitespace is not allowed at this location. + SXS_XML_E_UNEXPECTED_WHITESPACE = 0x36DA, + // Manifest Parse Error : End of file reached in invalid state for current encoding. + SXS_XML_E_INCOMPLETE_ENCODING = 0x36DB, + // Manifest Parse Error : Missing parenthesis. + SXS_XML_E_MISSING_PAREN = 0x36DC, + // Manifest Parse Error : A single or double closing quote character (\' or \") is missing. + SXS_XML_E_EXPECTINGCLOSEQUOTE = 0x36DD, + // Manifest Parse Error : Multiple colons are not allowed in a name. + SXS_XML_E_MULTIPLE_COLONS = 0x36DE, + // Manifest Parse Error : Invalid character for decimal digit. + SXS_XML_E_INVALID_DECIMAL = 0x36DF, + // Manifest Parse Error : Invalid character for hexadecimal digit. + SXS_XML_E_INVALID_HEXIDECIMAL = 0x36E0, + // Manifest Parse Error : Invalid unicode character value for this platform. + SXS_XML_E_INVALID_UNICODE = 0x36E1, + // Manifest Parse Error : Expecting whitespace or '?'. + SXS_XML_E_WHITESPACEORQUESTIONMARK = 0x36E2, + // Manifest Parse Error : End tag was not expected at this location. + SXS_XML_E_UNEXPECTEDENDTAG = 0x36E3, + // Manifest Parse Error : The following tags were not closed: %1. + SXS_XML_E_UNCLOSEDTAG = 0x36E4, + // Manifest Parse Error : Duplicate attribute. + SXS_XML_E_DUPLICATEATTRIBUTE = 0x36E5, + // Manifest Parse Error : Only one top level element is allowed in an XML document. + SXS_XML_E_MULTIPLEROOTS = 0x36E6, + // Manifest Parse Error : Invalid at the top level of the document. + SXS_XML_E_INVALIDATROOTLEVEL = 0x36E7, + // Manifest Parse Error : Invalid xml declaration. + SXS_XML_E_BADXMLDECL = 0x36E8, + // Manifest Parse Error : XML document must have a top level element. + SXS_XML_E_MISSINGROOT = 0x36E9, + // Manifest Parse Error : Unexpected end of file. + SXS_XML_E_UNEXPECTEDEOF = 0x36EA, + // Manifest Parse Error : Parameter entities cannot be used inside markup declarations in an internal subset. + SXS_XML_E_BADPEREFINSUBSET = 0x36EB, + // Manifest Parse Error : Element was not closed. + SXS_XML_E_UNCLOSEDSTARTTAG = 0x36EC, + // Manifest Parse Error : End element was missing the character '>'. + SXS_XML_E_UNCLOSEDENDTAG = 0x36ED, + // Manifest Parse Error : A string literal was not closed. + SXS_XML_E_UNCLOSEDSTRING = 0x36EE, + // Manifest Parse Error : A comment was not closed. + SXS_XML_E_UNCLOSEDCOMMENT = 0x36EF, + // Manifest Parse Error : A declaration was not closed. + SXS_XML_E_UNCLOSEDDECL = 0x36F0, + // Manifest Parse Error : A CDATA section was not closed. + SXS_XML_E_UNCLOSEDCDATA = 0x36F1, + // Manifest Parse Error : The namespace prefix is not allowed to start with the reserved string "xml". + SXS_XML_E_RESERVEDNAMESPACE = 0x36F2, + // Manifest Parse Error : System does not support the specified encoding. + SXS_XML_E_INVALIDENCODING = 0x36F3, + // Manifest Parse Error : Switch from current encoding to specified encoding not supported. + SXS_XML_E_INVALIDSWITCH = 0x36F4, + // Manifest Parse Error : The name 'xml' is reserved and must be lower case. + SXS_XML_E_BADXMLCASE = 0x36F5, + // Manifest Parse Error : The standalone attribute must have the value 'yes' or 'no'. + SXS_XML_E_INVALID_STANDALONE = 0x36F6, + // Manifest Parse Error : The standalone attribute cannot be used in external entities. + SXS_XML_E_UNEXPECTED_STANDALONE = 0x36F7, + // Manifest Parse Error : Invalid version number. + SXS_XML_E_INVALID_VERSION = 0x36F8, + // Manifest Parse Error : Missing equals sign between attribute and attribute value. + SXS_XML_E_MISSINGEQUALS = 0x36F9, + // Assembly Protection Error : Unable to recover the specified assembly. + SXS_PROTECTION_RECOVERY_FAILED = 0x36FA, + // Assembly Protection Error : The public key for an assembly was too short to be allowed. + SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT = 0x36FB, + // Assembly Protection Error : The catalog for an assembly is not valid, or does not match the assembly's manifest. + SXS_PROTECTION_CATALOG_NOT_VALID = 0x36FC, + // An HRESULT could not be translated to a corresponding Win32 error code. + SXS_UNTRANSLATABLE_HRESULT = 0x36FD, + // Assembly Protection Error : The catalog for an assembly is missing. + SXS_PROTECTION_CATALOG_FILE_MISSING = 0x36FE, + // The supplied assembly identity is missing one or more attributes which must be present in this context. + SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE = 0x36FF, + // The supplied assembly identity has one or more attribute names that contain characters not permitted in XML names. + SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME = 0x3700, + // The referenced assembly could not be found. + SXS_ASSEMBLY_MISSING = 0x3701, + // The activation context activation stack for the running thread of execution is corrupt. + SXS_CORRUPT_ACTIVATION_STACK = 0x3702, + // The application isolation metadata for this process or thread has become corrupt. + SXS_CORRUPTION = 0x3703, + // The activation context being deactivated is not the most recently activated one. + SXS_EARLY_DEACTIVATION = 0x3704, + // The activation context being deactivated is not active for the current thread of execution. + SXS_INVALID_DEACTIVATION = 0x3705, + // The activation context being deactivated has already been deactivated. + SXS_MULTIPLE_DEACTIVATION = 0x3706, + // A component used by the isolation facility has requested to terminate the process. + SXS_PROCESS_TERMINATION_REQUESTED = 0x3707, + // A kernel mode component is releasing a reference on an activation context. + SXS_RELEASE_ACTIVATION_CONTEXT = 0x3708, + // The activation context of system default assembly could not be generated. + SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 0x3709, + // The value of an attribute in an identity is not within the legal range. + SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 0x370A, + // The name of an attribute in an identity is not within the legal range. + SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 0x370B, + // An identity contains two definitions for the same attribute. + SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 0x370C, + // The identity string is malformed. This may be due to a trailing comma, more than two unnamed attributes, missing attribute name or missing attribute value. + SXS_IDENTITY_PARSE_ERROR = 0x370D, + // A string containing localized substitutable content was malformed. Either a dollar sign ($) was followed by something other than a left parenthesis or another dollar sign or an substitution's right parenthesis was not found. + MALFORMED_SUBSTITUTION_STRING = 0x370E, + // The public key token does not correspond to the public key specified. + SXS_INCORRECT_PUBLIC_KEY_TOKEN = 0x370F, + // A substitution string had no mapping. + UNMAPPED_SUBSTITUTION_STRING = 0x3710, + // The component must be locked before making the request. + SXS_ASSEMBLY_NOT_LOCKED = 0x3711, + // The component store has been corrupted. + SXS_COMPONENT_STORE_CORRUPT = 0x3712, + // An advanced installer failed during setup or servicing. + ADVANCED_INSTALLER_FAILED = 0x3713, + // The character encoding in the XML declaration did not match the encoding used in the document. + XML_ENCODING_MISMATCH = 0x3714, + // The identities of the manifests are identical but their contents are different. + SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 0x3715, + // The component identities are different. + SXS_IDENTITIES_DIFFERENT = 0x3716, + // The assembly is not a deployment. + SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 0x3717, + // The file is not a part of the assembly. + SXS_FILE_NOT_PART_OF_ASSEMBLY = 0x3718, + // The size of the manifest exceeds the maximum allowed. + SXS_MANIFEST_TOO_BIG = 0x3719, + // The setting is not registered. + SXS_SETTING_NOT_REGISTERED = 0x371A, + // One or more required members of the transaction are not present. + SXS_TRANSACTION_CLOSURE_INCOMPLETE = 0x371B, + // The SMI primitive installer failed during setup or servicing. + SMI_PRIMITIVE_INSTALLER_FAILED = 0x371C, + // A generic command executable returned a result that indicates failure. + GENERIC_COMMAND_FAILED = 0x371D, + // A component is missing file verification information in its manifest. + SXS_FILE_HASH_MISSING = 0x371E, + // The specified channel path is invalid. + EVT_INVALID_CHANNEL_PATH = 0x3A98, + // The specified query is invalid. + EVT_INVALID_QUERY = 0x3A99, + // The publisher metadata cannot be found in the resource. + EVT_PUBLISHER_METADATA_NOT_FOUND = 0x3A9A, + // The template for an event definition cannot be found in the resource (error = %1). + EVT_EVENT_TEMPLATE_NOT_FOUND = 0x3A9B, + // The specified publisher name is invalid. + EVT_INVALID_PUBLISHER_NAME = 0x3A9C, + // The event data raised by the publisher is not compatible with the event template definition in the publisher's manifest. + EVT_INVALID_EVENT_DATA = 0x3A9D, + // The specified channel could not be found. Check channel configuration. + EVT_CHANNEL_NOT_FOUND = 0x3A9F, + // The specified xml text was not well-formed. See Extended Error for more details. + EVT_MALFORMED_XML_TEXT = 0x3AA0, + // The caller is trying to subscribe to a direct channel which is not allowed. The events for a direct channel go directly to a logfile and cannot be subscribed to. + EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL = 0x3AA1, + // Configuration error. + EVT_CONFIGURATION_ERROR = 0x3AA2, + // The query result is stale / invalid. This may be due to the log being cleared or rolling over after the query result was created. Users should handle this code by releasing the query result object and reissuing the query. + EVT_QUERY_RESULT_STALE = 0x3AA3, + // Query result is currently at an invalid position. + EVT_QUERY_RESULT_INVALID_POSITION = 0x3AA4, + // Registered MSXML doesn't support validation. + EVT_NON_VALIDATING_MSXML = 0x3AA5, + // An expression can only be followed by a change of scope operation if it itself evaluates to a node set and is not already part of some other change of scope operation. + EVT_FILTER_ALREADYSCOPED = 0x3AA6, + // Can't perform a step operation from a term that does not represent an element set. + EVT_FILTER_NOTELTSET = 0x3AA7, + // Left hand side arguments to binary operators must be either attributes, nodes or variables and right hand side arguments must be constants. + EVT_FILTER_INVARG = 0x3AA8, + // A step operation must involve either a node test or, in the case of a predicate, an algebraic expression against which to test each node in the node set identified by the preceeding node set can be evaluated. + EVT_FILTER_INVTEST = 0x3AA9, + // This data type is currently unsupported. + EVT_FILTER_INVTYPE = 0x3AAA, + // A syntax error occurred at position %1!d!. + EVT_FILTER_PARSEERR = 0x3AAB, + // This operator is unsupported by this implementation of the filter. + EVT_FILTER_UNSUPPORTEDOP = 0x3AAC, + // The token encountered was unexpected. + EVT_FILTER_UNEXPECTEDTOKEN = 0x3AAD, + // The requested operation cannot be performed over an enabled direct channel. The channel must first be disabled before performing the requested operation. + EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL = 0x3AAE, + // Channel property %1!s! contains invalid value. The value has invalid type, is outside of valid range, can't be updated or is not supported by this type of channel. + EVT_INVALID_CHANNEL_PROPERTY_VALUE = 0x3AAF, + // Publisher property %1!s! contains invalid value. The value has invalid type, is outside of valid range, can't be updated or is not supported by this type of publisher. + EVT_INVALID_PUBLISHER_PROPERTY_VALUE = 0x3AB0, + // The channel fails to activate. + EVT_CHANNEL_CANNOT_ACTIVATE = 0x3AB1, + // The xpath expression exceeded supported complexity. Please symplify it or split it into two or more simple expressions. + EVT_FILTER_TOO_COMPLEX = 0x3AB2, + // the message resource is present but the message is not found in the string/message table. + EVT_MESSAGE_NOT_FOUND = 0x3AB3, + // The message id for the desired message could not be found. + EVT_MESSAGE_ID_NOT_FOUND = 0x3AB4, + // The substitution string for insert index (%1) could not be found. + EVT_UNRESOLVED_VALUE_INSERT = 0x3AB5, + // The description string for parameter reference (%1) could not be found. + EVT_UNRESOLVED_PARAMETER_INSERT = 0x3AB6, + // The maximum number of replacements has been reached. + EVT_MAX_INSERTS_REACHED = 0x3AB7, + // The event definition could not be found for event id (%1). + EVT_EVENT_DEFINITION_NOT_FOUND = 0x3AB8, + // The locale specific resource for the desired message is not present. + EVT_MESSAGE_LOCALE_NOT_FOUND = 0x3AB9, + // The resource is too old to be compatible. + EVT_VERSION_TOO_OLD = 0x3ABA, + // The resource is too new to be compatible. + EVT_VERSION_TOO_NEW = 0x3ABB, + // The channel at index %1!d! of the query can't be opened. + EVT_CANNOT_OPEN_CHANNEL_OF_QUERY = 0x3ABC, + // The publisher has been disabled and its resource is not available. This usually occurs when the publisher is in the process of being uninstalled or upgraded. + EVT_PUBLISHER_DISABLED = 0x3ABD, + // Attempted to create a numeric type that is outside of its valid range. + EVT_FILTER_OUT_OF_RANGE = 0x3ABE, + // The subscription fails to activate. + EC_SUBSCRIPTION_CANNOT_ACTIVATE = 0x3AE8, + // The log of the subscription is in disabled state, and cannot be used to forward events to. The log must first be enabled before the subscription can be activated. + EC_LOG_DISABLED = 0x3AE9, + // When forwarding events from local machine to itself, the query of the subscription can't contain target log of the subscription. + EC_CIRCULAR_FORWARDING = 0x3AEA, + // The credential store that is used to save credentials is full. + EC_CREDSTORE_FULL = 0x3AEB, + // The credential used by this subscription can't be found in credential store. + EC_CRED_NOT_FOUND = 0x3AEC, + // No active channel is found for the query. + EC_NO_ACTIVE_CHANNEL = 0x3AED, + // The resource loader failed to find MUI file. + MUI_FILE_NOT_FOUND = 0x3AFC, + // The resource loader failed to load MUI file because the file fail to pass validation. + MUI_INVALID_FILE = 0x3AFD, + // The RC Manifest is corrupted with garbage data or unsupported version or missing required item. + MUI_INVALID_RC_CONFIG = 0x3AFE, + // The RC Manifest has invalid culture name. + MUI_INVALID_LOCALE_NAME = 0x3AFF, + // The RC Manifest has invalid ultimatefallback name. + MUI_INVALID_ULTIMATEFALLBACK_NAME = 0x3B00, + // The resource loader cache doesn't have loaded MUI entry. + MUI_FILE_NOT_LOADED = 0x3B01, + // User stopped resource enumeration. + RESOURCE_ENUM_USER_STOP = 0x3B02, + // UI language installation failed. + MUI_INTLSETTINGS_UILANG_NOT_INSTALLED = 0x3B03, + // Locale installation failed. + MUI_INTLSETTINGS_INVALID_LOCALE_NAME = 0x3B04, + // A resource does not have default or neutral value. + MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE = 0x3B06, + // Invalid PRI config file. + MRM_INVALID_PRICONFIG = 0x3B07, + // Invalid file type. + MRM_INVALID_FILE_TYPE = 0x3B08, + // Unknown qualifier. + MRM_UNKNOWN_QUALIFIER = 0x3B09, + // Invalid qualifier value. + MRM_INVALID_QUALIFIER_VALUE = 0x3B0A, + // No Candidate found. + MRM_NO_CANDIDATE = 0x3B0B, + // The ResourceMap or NamedResource has an item that does not have default or neutral resource.. + MRM_NO_MATCH_OR_DEFAULT_CANDIDATE = 0x3B0C, + // Invalid ResourceCandidate type. + MRM_RESOURCE_TYPE_MISMATCH = 0x3B0D, + // Duplicate Resource Map. + MRM_DUPLICATE_MAP_NAME = 0x3B0E, + // Duplicate Entry. + MRM_DUPLICATE_ENTRY = 0x3B0F, + // Invalid Resource Identifier. + MRM_INVALID_RESOURCE_IDENTIFIER = 0x3B10, + // Filepath too long. + MRM_FILEPATH_TOO_LONG = 0x3B11, + // Unsupported directory type. + MRM_UNSUPPORTED_DIRECTORY_TYPE = 0x3B12, + // Invalid PRI File. + MRM_INVALID_PRI_FILE = 0x3B16, + // NamedResource Not Found. + MRM_NAMED_RESOURCE_NOT_FOUND = 0x3B17, + // ResourceMap Not Found. + MRM_MAP_NOT_FOUND = 0x3B1F, + // Unsupported MRT profile type. + MRM_UNSUPPORTED_PROFILE_TYPE = 0x3B20, + // Invalid qualifier operator. + MRM_INVALID_QUALIFIER_OPERATOR = 0x3B21, + // Unable to determine qualifier value or qualifier value has not been set. + MRM_INDETERMINATE_QUALIFIER_VALUE = 0x3B22, + // Automerge is enabled in the PRI file. + MRM_AUTOMERGE_ENABLED = 0x3B23, + // Too many resources defined for package. + MRM_TOO_MANY_RESOURCES = 0x3B24, + // The monitor returned a DDC/CI capabilities string that did not comply with the ACCESS.bus 3.0, DDC/CI 1.1 or MCCS 2 Revision 1 specification. + MCA_INVALID_CAPABILITIES_STRING = 0x3B60, + // The monitor's VCP Version (0xDF) VCP code returned an invalid version value. + MCA_INVALID_VCP_VERSION = 0x3B61, + // The monitor does not comply with the MCCS specification it claims to support. + MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION = 0x3B62, + // The MCCS version in a monitor's mccs_ver capability does not match the MCCS version the monitor reports when the VCP Version (0xDF) VCP code is used. + MCA_MCCS_VERSION_MISMATCH = 0x3B63, + // The Monitor Configuration API only works with monitors that support the MCCS 1.0 specification, MCCS 2.0 specification or the MCCS 2.0 Revision 1 specification. + MCA_UNSUPPORTED_MCCS_VERSION = 0x3B64, + // An internal Monitor Configuration API error occurred. + MCA_INTERNAL_ERROR = 0x3B65, + // The monitor returned an invalid monitor technology type. CRT, Plasma and LCD (TFT) are examples of monitor technology types. This error implies that the monitor violated the MCCS 2.0 or MCCS 2.0 Revision 1 specification. + MCA_INVALID_TECHNOLOGY_TYPE_RETURNED = 0x3B66, + // The caller of SetMonitorColorTemperature specified a color temperature that the current monitor did not support. This error implies that the monitor violated the MCCS 2.0 or MCCS 2.0 Revision 1 specification. + MCA_UNSUPPORTED_COLOR_TEMPERATURE = 0x3B67, + // The requested system device cannot be identified due to multiple indistinguishable devices potentially matching the identification criteria. + AMBIGUOUS_SYSTEM_DEVICE = 0x3B92, + // The requested system device cannot be found. + SYSTEM_DEVICE_NOT_FOUND = 0x3BC3, + // Hash generation for the specified hash version and hash type is not enabled on the server. + HASH_NOT_SUPPORTED = 0x3BC4, + // The hash requested from the server is not available or no longer valid. + HASH_NOT_PRESENT = 0x3BC5, + // The secondary interrupt controller instance that manages the specified interrupt is not registered. + SECONDARY_IC_PROVIDER_NOT_REGISTERED = 0x3BD9, + // The information supplied by the GPIO client driver is invalid. + GPIO_CLIENT_INFORMATION_INVALID = 0x3BDA, + // The version specified by the GPIO client driver is not supported. + GPIO_VERSION_NOT_SUPPORTED = 0x3BDB, + // The registration packet supplied by the GPIO client driver is not valid. + GPIO_INVALID_REGISTRATION_PACKET = 0x3BDC, + // The requested operation is not supported for the specified handle. + GPIO_OPERATION_DENIED = 0x3BDD, + // The requested connect mode conflicts with an existing mode on one or more of the specified pins. + GPIO_INCOMPATIBLE_CONNECT_MODE = 0x3BDE, + // The interrupt requested to be unmasked is not masked. + GPIO_INTERRUPT_ALREADY_UNMASKED = 0x3BDF, + // The requested run level switch cannot be completed successfully. + CANNOT_SWITCH_RUNLEVEL = 0x3C28, + // The service has an invalid run level setting. The run level for a service must not be higher than the run level of its dependent services. + INVALID_RUNLEVEL_SETTING = 0x3C29, + // The requested run level switch cannot be completed successfully since one or more services will not stop or restart within the specified timeout. + RUNLEVEL_SWITCH_TIMEOUT = 0x3C2A, + // A run level switch agent did not respond within the specified timeout. + RUNLEVEL_SWITCH_AGENT_TIMEOUT = 0x3C2B, + // A run level switch is currently in progress. + RUNLEVEL_SWITCH_IN_PROGRESS = 0x3C2C, + // One or more services failed to start during the service startup phase of a run level switch. + SERVICES_FAILED_AUTOSTART = 0x3C2D, + // The task stop request cannot be completed immediately since task needs more time to shutdown. + COM_TASK_STOP_PENDING = 0x3C8D, + // Package could not be opened. + INSTALL_OPEN_PACKAGE_FAILED = 0x3CF0, + // Package was not found. + INSTALL_PACKAGE_NOT_FOUND = 0x3CF1, + // Package data is invalid. + INSTALL_INVALID_PACKAGE = 0x3CF2, + // Package failed updates, dependency or conflict validation. + INSTALL_RESOLVE_DEPENDENCY_FAILED = 0x3CF3, + // There is not enough disk space on your computer. Please free up some space and try again. + INSTALL_OUT_OF_DISK_SPACE = 0x3CF4, + // There was a problem downloading your product. + INSTALL_NETWORK_FAILURE = 0x3CF5, + // Package could not be registered. + INSTALL_REGISTRATION_FAILURE = 0x3CF6, + // Package could not be unregistered. + INSTALL_DEREGISTRATION_FAILURE = 0x3CF7, + // User cancelled the install request. + INSTALL_CANCEL = 0x3CF8, + // Install failed. Please contact your software vendor. + INSTALL_FAILED = 0x3CF9, + // Removal failed. Please contact your software vendor. + REMOVE_FAILED = 0x3CFA, + // The provided package is already installed, and reinstallation of the package was blocked. Check the AppXDeployment-Server event log for details. + PACKAGE_ALREADY_EXISTS = 0x3CFB, + // The application cannot be started. Try reinstalling the application to fix the problem. + NEEDS_REMEDIATION = 0x3CFC, + // A Prerequisite for an install could not be satisfied. + INSTALL_PREREQUISITE_FAILED = 0x3CFD, + // The package repository is corrupted. + PACKAGE_REPOSITORY_CORRUPTED = 0x3CFE, + // To install this application you need either a Windows developer license or a sideloading-enabled system. + INSTALL_POLICY_FAILURE = 0x3CFF, + // The application cannot be started because it is currently updating. + PACKAGE_UPDATING = 0x3D00, + // The package deployment operation is blocked by policy. Please contact your system administrator. + DEPLOYMENT_BLOCKED_BY_POLICY = 0x3D01, + // The package could not be installed because resources it modifies are currently in use. + PACKAGES_IN_USE = 0x3D02, + // The package could not be recovered because necessary data for recovery have been corrupted. + RECOVERY_FILE_CORRUPT = 0x3D03, + // The signature is invalid. To register in developer mode, AppxSignature.p7x and AppxBlockMap.xml must be valid or should not be present. + INVALID_STAGED_SIGNATURE = 0x3D04, + // An error occurred while deleting the package's previously existing application data. + DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED = 0x3D05, + // The package could not be installed because a higher version of this package is already installed. + INSTALL_PACKAGE_DOWNGRADE = 0x3D06, + // An error in a system binary was detected. Try refreshing the PC to fix the problem. + SYSTEM_NEEDS_REMEDIATION = 0x3D07, + // A corrupted CLR NGEN binary was detected on the system. + APPX_INTEGRITY_FAILURE_CLR_NGEN = 0x3D08, + // The operation could not be resumed because necessary data for recovery have been corrupted. + RESILIENCY_FILE_CORRUPT = 0x3D09, + // The package could not be installed because the Windows Firewall service is not running. Enable the Windows Firewall service and try again. + INSTALL_FIREWALL_SERVICE_NOT_RUNNING = 0x3D0A, + // The process has no package identity. + APPMODEL_ERROR_NO_PACKAGE = 0x3D54, + // The package runtime information is corrupted. + APPMODEL_ERROR_PACKAGE_RUNTIME_CORRUPT = 0x3D55, + // The package identity is corrupted. + APPMODEL_ERROR_PACKAGE_IDENTITY_CORRUPT = 0x3D56, + // The process has no application identity. + APPMODEL_ERROR_NO_APPLICATION = 0x3D57, + // Loading the state store failed. + STATE_LOAD_STORE_FAILED = 0x3DB8, + // Retrieving the state version for the application failed. + STATE_GET_VERSION_FAILED = 0x3DB9, + // Setting the state version for the application failed. + STATE_SET_VERSION_FAILED = 0x3DBA, + // Resetting the structured state of the application failed. + STATE_STRUCTURED_RESET_FAILED = 0x3DBB, + // State Manager failed to open the container. + STATE_OPEN_CONTAINER_FAILED = 0x3DBC, + // State Manager failed to create the container. + STATE_CREATE_CONTAINER_FAILED = 0x3DBD, + // State Manager failed to delete the container. + STATE_DELETE_CONTAINER_FAILED = 0x3DBE, + // State Manager failed to read the setting. + STATE_READ_SETTING_FAILED = 0x3DBF, + // State Manager failed to write the setting. + STATE_WRITE_SETTING_FAILED = 0x3DC0, + // State Manager failed to delete the setting. + STATE_DELETE_SETTING_FAILED = 0x3DC1, + // State Manager failed to query the setting. + STATE_QUERY_SETTING_FAILED = 0x3DC2, + // State Manager failed to read the composite setting. + STATE_READ_COMPOSITE_SETTING_FAILED = 0x3DC3, + // State Manager failed to write the composite setting. + STATE_WRITE_COMPOSITE_SETTING_FAILED = 0x3DC4, + // State Manager failed to enumerate the containers. + STATE_ENUMERATE_CONTAINER_FAILED = 0x3DC5, + // State Manager failed to enumerate the settings. + STATE_ENUMERATE_SETTINGS_FAILED = 0x3DC6, + // The size of the state manager composite setting value has exceeded the limit. + STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 0x3DC7, + // The size of the state manager setting value has exceeded the limit. + STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 0x3DC8, + // The length of the state manager setting name has exceeded the limit. + STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED = 0x3DC9, + // The length of the state manager container name has exceeded the limit. + STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED = 0x3DCA, + // This API cannot be used in the context of the caller's application type. + API_UNAVAILABLE = 0x3DE1, +} diff --git a/core/sys/windows/winmm.odin b/core/sys/windows/winmm.odin index 445470f6e..0807df8de 100644 --- a/core/sys/windows/winmm.odin +++ b/core/sys/windows/winmm.odin @@ -5,7 +5,7 @@ foreign import winmm "system:Winmm.lib" MMRESULT :: UINT -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign winmm { timeGetDevCaps :: proc(ptc: LPTIMECAPS, cbtc: UINT) -> MMRESULT --- timeBeginPeriod :: proc(uPeriod: UINT) -> MMRESULT --- diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index 1b79be584..c60a21a36 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -56,7 +56,7 @@ Example Load: */ foreign import ws2_32 "system:Ws2_32.lib" -@(default_calling_convention="stdcall") +@(default_calling_convention="system") foreign ws2_32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup) WSAStartup :: proc(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int --- diff --git a/core/testing/runner_windows.odin b/core/testing/runner_windows.odin index 17bcfce26..dbb9ed1c0 100644 --- a/core/testing/runner_windows.odin +++ b/core/testing/runner_windows.odin @@ -90,7 +90,7 @@ Thread_Os_Specific :: struct { } thread_create :: proc(procedure: Thread_Proc) -> ^Thread { - __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { + __windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD { t := (^Thread)(t_) context = t.init_context.? or_else runtime.default_context() @@ -172,7 +172,7 @@ global_current_t: ^T run_internal_test :: proc(t: ^T, it: Internal_Test) { thread := thread_create(proc(thread: ^Thread) { - exception_handler_proc :: proc "stdcall" (ExceptionInfo: ^win32.EXCEPTION_POINTERS) -> win32.LONG { + exception_handler_proc :: proc "system" (ExceptionInfo: ^win32.EXCEPTION_POINTERS) -> win32.LONG { switch ExceptionInfo.ExceptionRecord.ExceptionCode { case win32.EXCEPTION_DATATYPE_MISALIGNMENT, diff --git a/core/text/edit/text_edit.odin b/core/text/edit/text_edit.odin index 8520ba674..3f6565557 100644 --- a/core/text/edit/text_edit.odin +++ b/core/text/edit/text_edit.odin @@ -63,7 +63,9 @@ Translation :: enum u32 { Soft_Line_End, } - +// init the state to some timeout and set the respective allocators +// - undo_state_allocator dictates the dynamic undo|redo arrays allocators +// - undo_text_allocator is the allocator which allocates strings only init :: proc(s: ^State, undo_text_allocator, undo_state_allocator: runtime.Allocator, undo_timeout := DEFAULT_UNDO_TIMEOUT) { s.undo_timeout = undo_timeout @@ -74,6 +76,7 @@ init :: proc(s: ^State, undo_text_allocator, undo_state_allocator: runtime.Alloc s.redo.allocator = undo_state_allocator } +// clear undo|redo strings and delete their stacks destroy :: proc(s: ^State) { undo_clear(s, &s.undo) undo_clear(s, &s.redo) @@ -82,7 +85,6 @@ destroy :: proc(s: ^State) { s.builder = nil } - // Call at the beginning of each frame begin :: proc(s: ^State, id: u64, builder: ^strings.Builder) { assert(builder != nil) @@ -92,11 +94,7 @@ begin :: proc(s: ^State, id: u64, builder: ^strings.Builder) { s.id = id s.selection = {len(builder.buf), 0} s.builder = builder - s.current_time = time.tick_now() - if s.undo_timeout <= 0 { - s.undo_timeout = DEFAULT_UNDO_TIMEOUT - } - set_text(s, string(s.builder.buf[:])) + update_time(s) undo_clear(s, &s.undo) undo_clear(s, &s.redo) } @@ -107,12 +105,37 @@ end :: proc(s: ^State) { s.builder = nil } -set_text :: proc(s: ^State, text: string) { - strings.builder_reset(s.builder) - strings.write_string(s.builder, text) +// update current time so "insert" can check for timeouts +update_time :: proc(s: ^State) { + s.current_time = time.tick_now() + if s.undo_timeout <= 0 { + s.undo_timeout = DEFAULT_UNDO_TIMEOUT + } } +// setup the builder, selection and undo|redo state once allowing to retain selection +setup_once :: proc(s: ^State, builder: ^strings.Builder) { + s.builder = builder + s.selection = { len(builder.buf), 0 } + undo_clear(s, &s.undo) + undo_clear(s, &s.redo) +} +// returns true when the builder had content to be cleared +// clear builder&selection and the undo|redo stacks +clear_all :: proc(s: ^State) -> (cleared: bool) { + if s.builder != nil && len(s.builder.buf) > 0 { + clear(&s.builder.buf) + s.selection = {} + cleared = true + } + + undo_clear(s, &s.undo) + undo_clear(s, &s.redo) + return +} + +// push current text state to the wanted undo|redo stack undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator_Error { text := string(s.builder.buf[:]) item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator) or_return) @@ -125,18 +148,21 @@ undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator return nil } +// pop undo|redo state - push to redo|undo - set selection & text undo :: proc(s: ^State, undo, redo: ^[dynamic]^Undo_State) { if len(undo) > 0 { undo_state_push(s, redo) item := pop(undo) s.selection = item.selection #no_bounds_check { - set_text(s, string(item.text[:item.len])) + strings.builder_reset(s.builder) + strings.write_string(s.builder, string(item.text[:item.len])) } free(item, s.undo_text_allocator) } } +// iteratively clearn the undo|redo stack and free each allocated text state undo_clear :: proc(s: ^State, undo: ^[dynamic]^Undo_State) { for len(undo) > 0 { item := pop(undo) @@ -144,6 +170,7 @@ undo_clear :: proc(s: ^State, undo: ^[dynamic]^Undo_State) { } } +// clear redo stack and check if the undo timeout gets hit undo_check :: proc(s: ^State) { undo_clear(s, &s.redo) if time.tick_diff(s.last_edit_time, s.current_time) > s.undo_timeout { @@ -152,8 +179,7 @@ undo_check :: proc(s: ^State) { s.last_edit_time = s.current_time } - - +// insert text into the edit state - deletes the current selection input_text :: proc(s: ^State, text: string) { if len(text) == 0 { return @@ -166,6 +192,7 @@ input_text :: proc(s: ^State, text: string) { s.selection = {offset, offset} } +// insert slice of runes into the edit state - deletes the current selection input_runes :: proc(s: ^State, text: []rune) { if len(text) == 0 { return @@ -182,43 +209,55 @@ input_runes :: proc(s: ^State, text: []rune) { s.selection = {offset, offset} } +// insert a single rune into the edit state - deletes the current selection +input_rune :: proc(s: ^State, r: rune) { + if has_selection(s) { + selection_delete(s) + } + offset := s.selection[0] + b, w := utf8.encode_rune(r) + insert(s, offset, string(b[:w])) + offset += w + s.selection = {offset, offset} +} +// insert a single rune into the edit state - deletes the current selection insert :: proc(s: ^State, at: int, text: string) { undo_check(s) inject_at(&s.builder.buf, at, text) } +// remove the wanted range withing, usually the selection within byte indices remove :: proc(s: ^State, lo, hi: int) { undo_check(s) remove_range(&s.builder.buf, lo, hi) } - - +// true if selection head and tail dont match and form a selection of multiple characters has_selection :: proc(s: ^State) -> bool { return s.selection[0] != s.selection[1] } +// return the clamped lo/hi of the current selection +// since the selection[0] moves around and could be ahead of selection[1] +// useful when rendering and needing left->right sorted_selection :: proc(s: ^State) -> (lo, hi: int) { lo = min(s.selection[0], s.selection[1]) hi = max(s.selection[0], s.selection[1]) lo = clamp(lo, 0, len(s.builder.buf)) hi = clamp(hi, 0, len(s.builder.buf)) - s.selection[0] = lo - s.selection[1] = hi return } - +// delete the current selection range and set the proper selection afterwards selection_delete :: proc(s: ^State) { lo, hi := sorted_selection(s) remove(s, lo, hi) s.selection = {lo, lo} } - - -translate_position :: proc(s: ^State, pos: int, t: Translation) -> int { +// translates the caret position +translate_position :: proc(s: ^State, t: Translation) -> int { is_continuation_byte :: proc(b: byte) -> bool { return b >= 0x80 && b < 0xc0 } @@ -227,9 +266,7 @@ translate_position :: proc(s: ^State, pos: int, t: Translation) -> int { } buf := s.builder.buf[:] - - pos := pos - pos = clamp(pos, 0, len(buf)) + pos := clamp(s.selection[0], 0, len(buf)) switch t { case .Start: @@ -280,6 +317,7 @@ translate_position :: proc(s: ^State, pos: int, t: Translation) -> int { return clamp(pos, 0, len(buf)) } +// Moves the position of the caret (both sides of the selection) move_to :: proc(s: ^State, t: Translation) { if t == .Left && has_selection(s) { lo, _ := sorted_selection(s) @@ -288,32 +326,36 @@ move_to :: proc(s: ^State, t: Translation) { _, hi := sorted_selection(s) s.selection = {hi, hi} } else { - pos := translate_position(s, s.selection[0], t) + pos := translate_position(s, t) s.selection = {pos, pos} } } + +// Moves only the head of the selection and leaves the tail uneffected select_to :: proc(s: ^State, t: Translation) { - s.selection[0] = translate_position(s, s.selection[0], t) + s.selection[0] = translate_position(s, t) } + +// Deletes everything between the caret and resultant position delete_to :: proc(s: ^State, t: Translation) { if has_selection(s) { selection_delete(s) } else { lo := s.selection[0] - hi := translate_position(s, lo, t) + hi := translate_position(s, t) lo, hi = min(lo, hi), max(lo, hi) remove(s, lo, hi) s.selection = {lo, lo} } } - +// return the currently selected text current_selected_text :: proc(s: ^State) -> string { lo, hi := sorted_selection(s) return string(s.builder.buf[lo:hi]) } - +// copy & delete the current selection when copy() succeeds cut :: proc(s: ^State) -> bool { if copy(s) { selection_delete(s) @@ -322,6 +364,8 @@ cut :: proc(s: ^State) -> bool { return false } +// try and copy the currently selected text to the clipboard +// State.set_clipboard needs to be assigned copy :: proc(s: ^State) -> bool { if s.set_clipboard != nil { return s.set_clipboard(s.clipboard_user_data, current_selected_text(s)) @@ -329,6 +373,8 @@ copy :: proc(s: ^State) -> bool { return s.set_clipboard != nil } +// reinsert whatever the get_clipboard would return +// State.get_clipboard needs to be assigned paste :: proc(s: ^State) -> bool { if s.get_clipboard != nil { input_text(s, s.get_clipboard(s.clipboard_user_data) or_return) diff --git a/core/thread/thread.odin b/core/thread/thread.odin index 9ba03203f..9fcc5b84f 100644 --- a/core/thread/thread.odin +++ b/core/thread/thread.odin @@ -116,26 +116,21 @@ run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe( } run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) - where size_of(T) <= size_of(rawptr) { + where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { create_and_start_with_poly_data(data, fn, init_context, priority, true) } run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { create_and_start_with_poly_data2(arg1, arg2, fn, init_context, priority, true) } run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr), - size_of(T3) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { create_and_start_with_poly_data3(arg1, arg2, arg3, fn, init_context, priority, true) } run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr), - size_of(T3) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS { create_and_start_with_poly_data4(arg1, arg2, arg3, arg4, fn, init_context, priority, true) } @@ -178,7 +173,7 @@ create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_co } create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread - where size_of(T) <= size_of(rawptr) { + where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { thread_proc :: proc(t: ^Thread) { fn := cast(proc(T))t.data assert(t.user_index >= 1) @@ -188,96 +183,118 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex t := create(thread_proc, priority) t.data = rawptr(fn) t.user_index = 1 + data := data - mem.copy(&t.user_args[0], &data, size_of(data)) + + mem.copy(&t.user_args[0], &data, size_of(T)) + if self_cleanup { t.flags += {.Self_Cleanup} } + t.init_context = init_context start(t) return t } create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { thread_proc :: proc(t: ^Thread) { fn := cast(proc(T1, T2))t.data assert(t.user_index >= 2) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ + + user_args := mem.slice_to_bytes(t.user_args[:]) + arg1 := (^T1)(raw_data(user_args))^ + arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^ + fn(arg1, arg2) } t := create(thread_proc, priority) t.data = rawptr(fn) t.user_index = 2 + arg1, arg2 := arg1, arg2 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) + user_args := mem.slice_to_bytes(t.user_args[:]) + + n := copy(user_args, mem.ptr_to_bytes(&arg1)) + _ = copy(user_args[n:], mem.ptr_to_bytes(&arg2)) + if self_cleanup { t.flags += {.Self_Cleanup} } + t.init_context = init_context start(t) return t } create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr), - size_of(T3) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { thread_proc :: proc(t: ^Thread) { fn := cast(proc(T1, T2, T3))t.data assert(t.user_index >= 3) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ - arg3 := (^T3)(&t.user_args[2])^ + + user_args := mem.slice_to_bytes(t.user_args[:]) + arg1 := (^T1)(raw_data(user_args))^ + arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^ + arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^ + fn(arg1, arg2, arg3) } t := create(thread_proc, priority) t.data = rawptr(fn) t.user_index = 3 + arg1, arg2, arg3 := arg1, arg2, arg3 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) - mem.copy(&t.user_args[2], &arg3, size_of(arg3)) + user_args := mem.slice_to_bytes(t.user_args[:]) + + n := copy(user_args, mem.ptr_to_bytes(&arg1)) + n += copy(user_args[n:], mem.ptr_to_bytes(&arg2)) + _ = copy(user_args[n:], mem.ptr_to_bytes(&arg3)) + if self_cleanup { t.flags += {.Self_Cleanup} } + t.init_context = init_context start(t) return t } create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread - where size_of(T1) <= size_of(rawptr), - size_of(T2) <= size_of(rawptr), - size_of(T3) <= size_of(rawptr) { + where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS { thread_proc :: proc(t: ^Thread) { fn := cast(proc(T1, T2, T3, T4))t.data assert(t.user_index >= 4) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ - arg3 := (^T3)(&t.user_args[2])^ - arg4 := (^T4)(&t.user_args[3])^ + + user_args := mem.slice_to_bytes(t.user_args[:]) + arg1 := (^T1)(raw_data(user_args))^ + arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^ + arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^ + arg4 := (^T4)(raw_data(user_args[size_of(T1) + size_of(T2) + size_of(T3):]))^ + fn(arg1, arg2, arg3, arg4) } t := create(thread_proc, priority) t.data = rawptr(fn) t.user_index = 4 + arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) - mem.copy(&t.user_args[2], &arg3, size_of(arg3)) - mem.copy(&t.user_args[3], &arg4, size_of(arg4)) + user_args := mem.slice_to_bytes(t.user_args[:]) + + n := copy(user_args, mem.ptr_to_bytes(&arg1)) + n += copy(user_args[n:], mem.ptr_to_bytes(&arg2)) + n += copy(user_args[n:], mem.ptr_to_bytes(&arg3)) + _ = copy(user_args[n:], mem.ptr_to_bytes(&arg4)) + if self_cleanup { t.flags += {.Self_Cleanup} } + t.init_context = init_context start(t) return t } - _select_context_for_thread :: proc(init_context: Maybe(runtime.Context)) -> runtime.Context { ctx, ok := init_context.? if !ok { diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index 2d6cad1ad..28b2294d1 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -21,7 +21,7 @@ _thread_priority_map := [Thread_Priority]i32{ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { win32_thread_id: win32.DWORD - __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { + __windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD { t := (^Thread)(t_) t.id = sync.current_thread_id() diff --git a/core/unicode/tools/generate_entity_table.odin b/core/unicode/tools/generate_entity_table.odin index e5a4d5513..ec8106cbe 100644 --- a/core/unicode/tools/generate_entity_table.odin +++ b/core/unicode/tools/generate_entity_table.odin @@ -2,7 +2,7 @@ package xml_example import "core:encoding/xml" import "core:os" -import "core:path" +import path "core:path/filepath" import "core:mem" import "core:strings" import "core:strconv" @@ -23,38 +23,38 @@ Entity :: struct { } generate_encoding_entity_table :: proc() { - using fmt - - filename := path.join(ODIN_ROOT, "tests", "core", "assets", "XML", "unicode.xml") + filename := path.join({ODIN_ROOT, "tests", "core", "assets", "XML", "unicode.xml"}) defer delete(filename) - generated_filename := path.join(ODIN_ROOT, "core", "encoding", "entity", "generated.odin") + generated_filename := path.join({ODIN_ROOT, "core", "encoding", "entity", "generated.odin"}) defer delete(generated_filename) - doc, err := xml.parse(filename, OPTIONS, Error_Handler) + doc, err := xml.load_from_file(filename, OPTIONS, Error_Handler) defer xml.destroy(doc) if err != .None { - printf("Load/Parse error: %v\n", err) + fmt.printf("Load/Parse error: %v\n", err) if err == .File_Error { - printf("\"%v\" not found. Did you run \"tests\\download_assets.py\"?", filename) + fmt.printf("\"%v\" not found. Did you run \"tests\\download_assets.py\"?", filename) } os.exit(1) } - printf("\"%v\" loaded and parsed.\n", filename) + fmt.printf("\"%v\" loaded and parsed.\n", filename) generated_buf: strings.Builder defer strings.builder_destroy(&generated_buf) w := strings.to_writer(&generated_buf) - charlist, charlist_ok := xml.find_child_by_ident(doc.root, "charlist") + charlist_id, charlist_ok := xml.find_child_by_ident(doc, 0, "charlist") if !charlist_ok { - eprintln("Could not locate top-level `` tag.") + fmt.eprintln("Could not locate top-level `` tag.") os.exit(1) } - printf("Found `` with %v children.\n", len(charlist.children)) + charlist := doc.elements[charlist_id] + + fmt.printf("Found `` with %v children.\n", len(charlist.value)) entity_map: map[string]Entity names: [dynamic]string @@ -65,20 +65,26 @@ generate_encoding_entity_table :: proc() { longest_name: string count := 0 - for char in charlist.children { + for char_id in charlist.value { + id := char_id.(xml.Element_ID) + char := doc.elements[id] + if char.ident != "character" { - eprintf("Expected ``, got `<%v>`\n", char.ident) + fmt.eprintf("Expected ``, got `<%v>`\n", char.ident) os.exit(1) } - if codepoint_string, ok := xml.find_attribute_val_by_key(char, "dec"); !ok { - eprintln("`` attribute not found.") + if codepoint_string, ok := xml.find_attribute_val_by_key(doc, id, "dec"); !ok { + fmt.eprintln("`` attribute not found.") os.exit(1) } else { codepoint := strconv.atoi(codepoint_string) - desc, desc_ok := xml.find_child_by_ident(char, "description") - description := desc.value if desc_ok else "" + desc, desc_ok := xml.find_child_by_ident(doc, id, "description") + description := "" + if len(doc.elements[desc].value) == 1 { + description = doc.elements[desc].value[0].(string) + } /* For us to be interested in this codepoint, it has to have at least one entity. @@ -86,9 +92,9 @@ generate_encoding_entity_table :: proc() { nth := 0 for { - character_entity := xml.find_child_by_ident(char, "entity", nth) or_break + character_entity := xml.find_child_by_ident(doc, id, "entity", nth) or_break nth += 1 - name := xml.find_attribute_val_by_key(character_entity, "id") or_continue + name := xml.find_attribute_val_by_key(doc, character_entity, "id") or_continue if len(name) == 0 { /* Invalid name. Skip. @@ -97,8 +103,8 @@ generate_encoding_entity_table :: proc() { } if name == "\"\"" { - printf("%#v\n", char) - printf("%#v\n", character_entity) + fmt.printf("%#v\n", char) + fmt.printf("%#v\n", character_entity) } if len(name) > max_name_length { longest_name = name } @@ -129,29 +135,27 @@ generate_encoding_entity_table :: proc() { */ slice.sort(names[:]) - printf("Found %v unique `&name;` -> rune mappings.\n", count) - printf("Shortest name: %v (%v)\n", shortest_name, min_name_length) - printf("Longest name: %v (%v)\n", longest_name, max_name_length) - - // println(rune_to_string(1234)) + fmt.printf("Found %v unique `&name;` -> rune mappings.\n", count) + fmt.printf("Shortest name: %v (%v)\n", shortest_name, min_name_length) + fmt.printf("Longest name: %v (%v)\n", longest_name, max_name_length) /* Generate table. */ - wprintln(w, "package unicode_entity") - wprintln(w, "") - wprintln(w, GENERATED) - wprintln(w, "") - wprintf (w, TABLE_FILE_PROLOG) - wprintln(w, "") + fmt.wprintln(w, "package unicode_entity") + fmt.wprintln(w, "") + fmt.wprintln(w, GENERATED) + fmt.wprintln(w, "") + fmt.wprintf (w, TABLE_FILE_PROLOG) + fmt.wprintln(w, "") - wprintf (w, "// `&%v;`\n", shortest_name) - wprintf (w, "XML_NAME_TO_RUNE_MIN_LENGTH :: %v\n", min_name_length) - wprintf (w, "// `&%v;`\n", longest_name) - wprintf (w, "XML_NAME_TO_RUNE_MAX_LENGTH :: %v\n", max_name_length) - wprintln(w, "") + fmt.wprintf (w, "// `&%v;`\n", shortest_name) + fmt.wprintf (w, "XML_NAME_TO_RUNE_MIN_LENGTH :: %v\n", min_name_length) + fmt.wprintf (w, "// `&%v;`\n", longest_name) + fmt.wprintf (w, "XML_NAME_TO_RUNE_MAX_LENGTH :: %v\n", max_name_length) + fmt.wprintln(w, "") - wprintln(w, + fmt.wprintln(w, ` /* Input: @@ -181,38 +185,41 @@ named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) { for v in names { if rune(v[0]) != prefix { if should_close { - wprintln(w, "\t\t}\n") + fmt.wprintln(w, "\t\t}\n") } prefix = rune(v[0]) - wprintf (w, "\tcase '%v':\n", prefix) - wprintln(w, "\t\tswitch name {") + fmt.wprintf (w, "\tcase '%v':\n", prefix) + fmt.wprintln(w, "\t\tswitch name {") } e := entity_map[v] - wprintf(w, "\t\t\tcase \"%v\": \n", e.name) - wprintf(w, "\t\t\t\t// %v\n", e.description) - wprintf(w, "\t\t\t\treturn %v, true\n", rune_to_string(e.codepoint)) + fmt.wprintf(w, "\t\t\tcase \"%v\":", e.name) + for i := len(e.name); i < max_name_length; i += 1 { + fmt.wprintf(w, " ") + } + fmt.wprintf(w, " // %v\n", e.description) + fmt.wprintf(w, "\t\t\t\treturn %v, true\n", rune_to_string(e.codepoint)) should_close = true } - wprintln(w, "\t\t}") - wprintln(w, "\t}") - wprintln(w, "\treturn -1, false") - wprintln(w, "}\n") - wprintln(w, GENERATED) + fmt.wprintln(w, "\t\t}") + fmt.wprintln(w, "\t}") + fmt.wprintln(w, "\treturn -1, false") + fmt.wprintln(w, "}\n") + fmt.wprintln(w, GENERATED) - println() - println(strings.to_string(generated_buf)) - println() + fmt.println() + fmt.println(strings.to_string(generated_buf)) + fmt.println() written := os.write_entire_file(generated_filename, transmute([]byte)strings.to_string(generated_buf)) if written { - fmt.printf("Successfully written generated \"%v\".", generated_filename) + fmt.printf("Successfully written generated \"%v\".\n", generated_filename) } else { - fmt.printf("Failed to write generated \"%v\".", generated_filename) + fmt.printf("Failed to write generated \"%v\".\n", generated_filename) } delete(entity_map) @@ -227,7 +234,7 @@ GENERATED :: `/* */` TABLE_FILE_PROLOG :: `/* - This file is generated from "https://www.w3.org/2003/entities/2007xml/unicode.xml". + This file is generated from "https://github.com/w3c/xml-entities/blob/gh-pages/unicode.xml". UPDATE: - Ensure the XML file was downloaded using "tests\core\download_assets.py". @@ -235,15 +242,21 @@ TABLE_FILE_PROLOG :: `/* Odin unicode generated tables: https://github.com/odin-lang/Odin/tree/master/core/encoding/entity - Copyright © 2021 World Wide Web Consortium, (Massachusetts Institute of Technology, - European Research Consortium for Informatics and Mathematics, Keio University, Beihang). + Copyright David Carlisle 1999-2023 - All Rights Reserved. + Use and distribution of this code are permitted under the terms of the + W3C Software Notice and License. + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html - This work is distributed under the W3C® Software License [1] in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - [1] http://www.w3.org/Consortium/Legal/copyright-software + + This file is a collection of information about how to map + Unicode entities to LaTeX, and various SGML/XML entity + sets (ISO and MathML/HTML). A Unicode character may be mapped + to several entities. + + Originally designed by Sebastian Rahtz in conjunction with + Barbara Beeton for the STIX project See also: LICENSE_table.md */ @@ -265,8 +278,6 @@ is_dotted_name :: proc(name: string) -> (dotted: bool) { } main :: proc() { - using fmt - track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) context.allocator = mem.tracking_allocator(&track) @@ -274,10 +285,10 @@ main :: proc() { generate_encoding_entity_table() if len(track.allocation_map) > 0 { - println() + fmt.println() for _, v in track.allocation_map { - printf("%v Leaked %v bytes.\n", v.location, v.size) + fmt.printf("%v Leaked %v bytes.\n", v.location, v.size) } } - println("Done and cleaned up!") + fmt.println("Done and cleaned up!") } \ No newline at end of file diff --git a/default.nix b/default.nix deleted file mode 100644 index 64d20f674..000000000 --- a/default.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ pkgs ? import { } }: -let - odin-unwrapped = pkgs.llvmPackages_11.stdenv.mkDerivation (rec { - name = "odin-unwrapped"; - src = ./.; - dontConfigure = true; - nativeBuildInputs = [ pkgs.git ]; - buildPhase = '' - make debug SHELL=${pkgs.llvmPackages_11.stdenv.shell} - ''; - installPhase = '' - mkdir -p $out/bin - cp odin $out/bin/odin - cp -r core $out/bin/core - ''; - }); - path = builtins.map (path: path + "/bin") (with pkgs.llvmPackages_11; [ - bintools - llvm - clang - lld - ]); -in -pkgs.writeScriptBin "odin" '' - #!${pkgs.llvmPackages_11.stdenv.shell} - PATH="${(builtins.concatStringsSep ":" path)}" exec ${odin-unwrapped}/bin/odin $@ -'' diff --git a/examples/all/README.md b/examples/all/README.md new file mode 100644 index 000000000..72398540f --- /dev/null +++ b/examples/all/README.md @@ -0,0 +1,3 @@ +# `examples/all` for Documentation + +**NOTE:** This exists purely for the documentation generator located at \ No newline at end of file diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index c6b727e42..0872e0550 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -23,31 +23,18 @@ import list "core:container/intrusive/list" import topological_sort "core:container/topological_sort" import crypto "core:crypto" -import blake "core:crypto/blake" import blake2b "core:crypto/blake2b" import blake2s "core:crypto/blake2s" import chacha20 "core:crypto/chacha20" import chacha20poly1305 "core:crypto/chacha20poly1305" -import gost "core:crypto/gost" -import groestl "core:crypto/groestl" -import haval "core:crypto/haval" -import jh "core:crypto/jh" -import keccak "core:crypto/keccak" -import md2 "core:crypto/md2" -import md4 "core:crypto/md4" -import md5 "core:crypto/md5" +import keccak "core:crypto/legacy/keccak" +import md5 "core:crypto/legacy/md5" +import sha1 "core:crypto/legacy/sha1" import poly1305 "core:crypto/poly1305" -import ripemd "core:crypto/ripemd" -import sha1 "core:crypto/sha1" import sha2 "core:crypto/sha2" import sha3 "core:crypto/sha3" import shake "core:crypto/shake" import sm3 "core:crypto/sm3" -import streebog "core:crypto/streebog" -import tiger "core:crypto/tiger" -import tiger2 "core:crypto/tiger2" -import crypto_util "core:crypto/util" -import whirlpool "core:crypto/whirlpool" import x25519 "core:crypto/x25519" import pe "core:debug/pe" @@ -150,31 +137,18 @@ _ :: lru _ :: list _ :: topological_sort _ :: crypto -_ :: blake _ :: blake2b _ :: blake2s _ :: chacha20 _ :: chacha20poly1305 -_ :: gost -_ :: groestl -_ :: haval -_ :: jh _ :: keccak -_ :: md2 -_ :: md4 _ :: md5 _ :: poly1305 -_ :: ripemd _ :: sha1 _ :: sha2 _ :: sha3 _ :: shake _ :: sm3 -_ :: streebog -_ :: tiger -_ :: tiger2 -_ :: crypto_util -_ :: whirlpool _ :: x25519 _ :: pe _ :: dynlib diff --git a/examples/all/all_vendor.odin b/examples/all/all_vendor.odin index 6864a7be2..f3c90874c 100644 --- a/examples/all/all_vendor.odin +++ b/examples/all/all_vendor.odin @@ -2,21 +2,14 @@ package all import botan_bindings "vendor:botan/bindings" import botan_blake2b "vendor:botan/blake2b" -import gost "vendor:botan/gost" -import keccak "vendor:botan/keccak" -import md4 "vendor:botan/md4" -import md5 "vendor:botan/md5" -import ripemd "vendor:botan/ripemd" -import sha1 "vendor:botan/sha1" +import keccak "vendor:botan/legacy/keccak" +import md5 "vendor:botan/legacy/md5" +import sha1 "vendor:botan/legacy/sha1" import sha2 "vendor:botan/sha2" import sha3 "vendor:botan/sha3" import shake "vendor:botan/shake" import siphash "vendor:botan/siphash" -import skein512 "vendor:botan/skein512" import sm3 "vendor:botan/sm3" -import streebog "vendor:botan/streebog" -import tiger "vendor:botan/tiger" -import whirlpool "vendor:botan/whirlpool" import cgltf "vendor:cgltf" // import commonmark "vendor:commonmark" @@ -46,23 +39,18 @@ import nvg "vendor:nanovg" import nvg_gl "vendor:nanovg/gl" import fontstash "vendor:fontstash" +import xlib "vendor:x11/xlib" + _ :: botan_bindings _ :: botan_blake2b -_ :: gost _ :: keccak -_ :: md4 _ :: md5 -_ :: ripemd _ :: sha1 _ :: sha2 _ :: sha3 _ :: shake _ :: siphash -_ :: skein512 _ :: sm3 -_ :: streebog -_ :: tiger -_ :: whirlpool _ :: cgltf @@ -90,4 +78,46 @@ _ :: lua_5_4 _ :: nvg _ :: nvg_gl -_ :: fontstash \ No newline at end of file +_ :: fontstash + +_ :: xlib + + +// NOTE: needed for doc generator + +import NS "vendor:darwin/Foundation" +import MTL "vendor:darwin/Metal" +import MTK "vendor:darwin/MetalKit" +import CA "vendor:darwin/QuartzCore" + +_ :: NS +_ :: MTL +_ :: MTK +_ :: CA + + +import D3D11 "vendor:directx/d3d11" +import D3D12 "vendor:directx/d3d12" +import DXGI "vendor:directx/dxgi" + +_ :: D3D11 +_ :: D3D12 +_ :: DXGI + + +import cm "vendor:commonmark" +_ :: cm + + +import stb_easy_font "vendor:stb/easy_font" +import stbi "vendor:stb/image" +import stbrp "vendor:stb/rect_pack" +import stbtt "vendor:stb/truetype" +import stb_vorbis "vendor:stb/vorbis" + +_ :: stb_easy_font +_ :: stbi +_ :: stbrp +_ :: stbtt +_ :: stb_vorbis + diff --git a/examples/all/all_vendor_cmark.odin b/examples/all/all_vendor_cmark.odin deleted file mode 100644 index 5faf47efc..000000000 --- a/examples/all/all_vendor_cmark.odin +++ /dev/null @@ -1,5 +0,0 @@ -//+build windows, linux -package all - -import cm "vendor:commonmark" -_ :: cm diff --git a/examples/all/all_vendor_darwin.odin b/examples/all/all_vendor_darwin.odin deleted file mode 100644 index 9aa41396c..000000000 --- a/examples/all/all_vendor_darwin.odin +++ /dev/null @@ -1,12 +0,0 @@ -//+build darwin -package all - -import NS "vendor:darwin/Foundation" -import MTL "vendor:darwin/Metal" -import MTK "vendor:darwin/MetalKit" -import CA "vendor:darwin/QuartzCore" - -_ :: NS -_ :: MTL -_ :: MTK -_ :: CA diff --git a/examples/all/all_vendor_directx.odin b/examples/all/all_vendor_directx.odin deleted file mode 100644 index 2f10d92f8..000000000 --- a/examples/all/all_vendor_directx.odin +++ /dev/null @@ -1,10 +0,0 @@ -//+build windows -package all - -import D3D11 "vendor:directx/d3d11" -import D3D12 "vendor:directx/d3d12" -import DXGI "vendor:directx/dxgi" - -_ :: D3D11 -_ :: D3D12 -_ :: DXGI diff --git a/examples/all/all_vendor_stl.odin b/examples/all/all_vendor_stl.odin deleted file mode 100644 index 9faf53c63..000000000 --- a/examples/all/all_vendor_stl.odin +++ /dev/null @@ -1,15 +0,0 @@ -//+build windows, linux -package all - -import stb_easy_font "vendor:stb/easy_font" -import stbi "vendor:stb/image" -import stbrp "vendor:stb/rect_pack" -import stbtt "vendor:stb/truetype" -import stb_vorbis "vendor:stb/vorbis" - -_ :: stb_easy_font -_ :: stbi -_ :: stbrp -_ :: stbtt -_ :: stb_vorbis - diff --git a/examples/all/all_vendor_zlib.odin b/examples/all/all_vendor_zlib.odin deleted file mode 100644 index 6004bed50..000000000 --- a/examples/all/all_vendor_zlib.odin +++ /dev/null @@ -1,5 +0,0 @@ -//+build windows, linux -package all - -import zlib "vendor:zlib" -_ :: zlib diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 00dd8a171..bc6a4d9ea 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -44,7 +44,13 @@ the_basics :: proc() { fmt.println("\n# the basics") { // The Basics - fmt.println("Hellope") + + // os.args holds the path to the current executable and any arguments passed to it. + if len(os.args) == 1 { + fmt.printf("Hellope from %v.\n", os.args[0]) + } else { + fmt.printf("%v, %v! from %v.\n", os.args[1], os.args[2], os.args[0]) + } // Lexical elements and literals // A comment @@ -535,7 +541,7 @@ struct_type :: proc() { p.x = 1335 fmt.println(v) - // We could write p^.x, however, it is to nice abstract the ability + // We could write p^.x, however, it is nice to abstract the ability // to not explicitly dereference the pointer. This is very useful when // refactoring code to use a pointer rather than a value, and vice versa. } @@ -1508,7 +1514,7 @@ quaternions :: proc() { { // Quaternion operations q := 1 + 2i + 3j + 4k - r := quaternion(5, 6, 7, 8) + r := quaternion(real=5, imag=6, jmag=7, kmag=8) t := q * r fmt.printf("(%v) * (%v) = %v\n", q, r, t) v := q / r @@ -1521,8 +1527,10 @@ quaternions :: proc() { { // The quaternion types q128: quaternion128 // 4xf32 q256: quaternion256 // 4xf64 - q128 = quaternion(1, 0, 0, 0) - q256 = 1 // quaternion(1, 0, 0, 0) + q128 = quaternion(w=1, x=0, y=0, z=0) + q256 = 1 // quaternion(x=0, y=0, z=0, w=1) + + // NOTE: The internal memory layout of a quaternion is xyzw } { // Built-in procedures q := 1 + 2i + 3j + 4k @@ -2588,4 +2596,4 @@ main :: proc() { arbitrary_precision_mathematics() matrix_type() } -} \ No newline at end of file +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..21301b9d7 --- /dev/null +++ b/shell.nix @@ -0,0 +1,11 @@ +{ pkgs ? import {} }: +pkgs.mkShell { + name = "odin"; + nativeBuildInputs = with pkgs; [ + git + clang_17 + llvmPackages_17.llvm + llvmPackages_17.bintools + ]; + shellHook="CXX=clang++"; +} diff --git a/src/bug_report.cpp b/src/bug_report.cpp index fbf616efb..ac3805919 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -824,6 +824,17 @@ gb_internal void report_os_info() { {"20G624", {20, 6, 0}, "macOS", {"Big Sur", {11, 6, 6}}}, {"20G630", {20, 6, 0}, "macOS", {"Big Sur", {11, 6, 7}}}, {"20G730", {20, 6, 0}, "macOS", {"Big Sur", {11, 6, 8}}}, + {"20G817", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 0}}}, + {"20G918", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 1}}}, + {"20G1020", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 2}}}, + {"20G1116", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 3}}}, + {"20G1120", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 4}}}, + {"20G1225", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 5}}}, + {"20G1231", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 6}}}, + {"20G1345", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 7}}}, + {"20G1351", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 8}}}, + {"20G1426", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 9}}}, + {"20G1427", {20, 6, 0}, "macOS", {"Big Sur", {11, 7, 10}}}, {"21A344", {21, 0, 1}, "macOS", {"Monterey", {12, 0, 0}}}, {"21A559", {21, 1, 0}, "macOS", {"Monterey", {12, 0, 1}}}, {"21C52", {21, 2, 0}, "macOS", {"Monterey", {12, 1, 0}}}, @@ -836,6 +847,42 @@ gb_internal void report_os_info() { {"21F2092", {21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}}, {"21G72", {21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}}, {"21G83", {21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}}, + {"21G115", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 0}}}, + {"21G217", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 1}}}, + {"21G320", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 2}}}, + {"21G419", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 3}}}, + {"21G526", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 4}}}, + {"21G531", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 5}}}, + {"21G646", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 6}}}, + {"21G651", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 7}}}, + {"21G725", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 8}}}, + {"21G726", {21, 6, 0}, "macOS", {"Monterey", {12, 6, 9}}}, + {"21G816", {21, 6, 0}, "macOS", {"Monterey", {12, 7, 0}}}, + {"21G920", {21, 6, 0}, "macOS", {"Monterey", {12, 7, 1}}}, + {"21G1974", {21, 6, 0}, "macOS", {"Monterey", {12, 7, 2}}}, + {"22A380", {13, 0, 0}, "macOS", {"Ventura", {22, 1, 0}}}, + {"22A400", {13, 0, 1}, "macOS", {"Ventura", {22, 1, 0}}}, + {"22C65", {13, 1, 0}, "macOS", {"Ventura", {22, 2, 0}}}, + {"22D49", {13, 2, 0}, "macOS", {"Ventura", {22, 3, 0}}}, + {"22D68", {13, 2, 1}, "macOS", {"Ventura", {22, 3, 0}}}, + {"22E252", {13, 3, 0}, "macOS", {"Ventura", {22, 4, 0}}}, + {"22E261", {13, 3, 1}, "macOS", {"Ventura", {22, 4, 0}}}, + {"22F66", {13, 4, 0}, "macOS", {"Ventura", {22, 5, 0}}}, + {"22F82", {13, 4, 1}, "macOS", {"Ventura", {22, 5, 0}}}, + {"22E772610a", {13, 4, 1}, "macOS", {"Ventura", {22, 5, 0}}}, + {"22F770820d", {13, 4, 1}, "macOS", {"Ventura", {22, 5, 0}}}, + {"22G74", {13, 5, 0}, "macOS", {"Ventura", {22, 6, 0}}}, + {"22G90", {13, 5, 1}, "macOS", {"Ventura", {22, 6, 0}}}, + {"22G91", {13, 5, 2}, "macOS", {"Ventura", {22, 6, 0}}}, + {"22G120", {13, 6, 0}, "macOS", {"Ventura", {22, 6, 0}}}, + {"22G313", {13, 6, 1}, "macOS", {"Ventura", {22, 6, 0}}}, + {"22G320", {13, 6, 2}, "macOS", {"Ventura", {22, 6, 0}}}, + {"23A344", {23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, + {"23B74", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, + {"23B81", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, + {"23B92", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, + {"23C64", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}}, + {"23C71", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, }; @@ -867,37 +914,44 @@ gb_internal void report_os_info() { // Scan table for match on BUILD int macos_release_count = sizeof(macos_release_map) / sizeof(macos_release_map[0]); - Darwin_To_Release match = {}; - + Darwin_To_Release build_match = {}; + Darwin_To_Release kernel_match = {}; + for (int build = 0; build < macos_release_count; build++) { Darwin_To_Release rel = macos_release_map[build]; - + // Do we have an exact match on the BUILD? if (gb_strcmp(rel.build, (const char *)build_buffer) == 0) { - match = rel; + build_match = rel; break; } - + // Do we have an exact Darwin match? if (rel.darwin[0] == major && rel.darwin[1] == minor && rel.darwin[2] == patch) { - match = rel; - break; + kernel_match = rel; } - + // Major kernel version needs to match exactly, if (rel.darwin[0] == major) { // No major version match yet. - if (!match.os_name) { - match = rel; + if (!kernel_match.os_name) { + kernel_match = rel; } if (minor >= rel.darwin[1]) { - match = rel; + kernel_match = rel; if (patch >= rel.darwin[2]) { - match = rel; + kernel_match = rel; } } } } + + Darwin_To_Release match = {}; + if(!build_match.build) { + match = kernel_match; + } else { + match = build_match; + } if (match.os_name) { gb_printf("%s %s %d", match.os_name, match.release.name, match.release.version[0]); diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ffb276d1e..af518bcb4 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -56,6 +56,19 @@ enum TargetABIKind : u16 { TargetABI_COUNT, }; +enum Windows_Subsystem : u8 { + Windows_Subsystem_BOOT_APPLICATION, + Windows_Subsystem_CONSOLE, // Default, + Windows_Subsystem_EFI_APPLICATION, + Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER, + Windows_Subsystem_EFI_ROM, + Windows_Subsystem_EFI_RUNTIME_DRIVER, + Windows_Subsystem_NATIVE, + Windows_Subsystem_POSIX, + Windows_Subsystem_WINDOWS, + Windows_Subsystem_WINDOWSCE, + Windows_Subsystem_COUNT, +}; gb_global String target_os_names[TargetOs_COUNT] = { str_lit(""), @@ -82,6 +95,23 @@ gb_global String target_arch_names[TargetArch_COUNT] = { str_lit("wasm64p32"), }; +gb_global String target_microarch_list[TargetArch_COUNT] = { + // TargetArch_Invalid, + str_lit("Invalid!"), + // TargetArch_amd64, + str_lit("alderlake,amdfam10,athlon-fx,athlon64,athlon64-sse3,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,broadwell,btver1,btver2,cannonlake,cascadelake,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,generic,goldmont,goldmont-plus,goldmont_plus,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k8,k8-sse3,knl,knm,meteorlake,mic_avx512,native,nehalem,nocona,opteron,opteron-sse3,penryn,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,znver1,znver2,znver3,znver4"), + // TargetArch_i386, + str_lit("athlon,athlon-4,athlon-mp,athlon-tbird,athlon-xp,atom,bonnell,c3,c3-2,generic,geode,i386,i486,i586,i686,k6,k6-2,k6-3,lakemont,native,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,winchip-c6,winchip2,yonah"), + // TargetArch_arm32, + str_lit("arm1020e,arm1020t,arm1022e,arm10e,arm10tdmi,arm1136j-s,arm1136jf-s,arm1156t2-s,arm1156t2f-s,arm1176jz-s,arm1176jzf-s,arm710t,arm720t,arm7tdmi,arm7tdmi-s,arm8,arm810,arm9,arm920,arm920t,arm922t,arm926ej-s,arm940t,arm946e-s,arm966e-s,arm968e-s,arm9e,arm9tdmi,cortex-a12,cortex-a15,cortex-a17,cortex-a32,cortex-a35,cortex-a5,cortex-a53,cortex-a55,cortex-a57,cortex-a7,cortex-a710,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78c,cortex-a8,cortex-a9,cortex-m0,cortex-m0plus,cortex-m1,cortex-m23,cortex-m3,cortex-m33,cortex-m35p,cortex-m4,cortex-m55,cortex-m7,cortex-m85,cortex-r4,cortex-r4f,cortex-r5,cortex-r52,cortex-r7,cortex-r8,cortex-x1,cortex-x1c,cyclone,ep9312,exynos-m3,exynos-m4,exynos-m5,generic,iwmmxt,krait,kryo,mpcore,mpcorenovfp,native,neoverse-n1,neoverse-n2,neoverse-v1,sc000,sc300,strongarm,strongarm110,strongarm1100,strongarm1110,swift,xscale"), + // TargetArch_arm64, + str_lit("a64fx,ampere1,ampere1a,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a7,apple-a8,apple-a9,apple-latest,apple-m1,apple-m2,apple-s4,apple-s5,carmel,cortex-a34,cortex-a35,cortex-a510,cortex-a53,cortex-a55,cortex-a57,cortex-a65,cortex-a65ae,cortex-a710,cortex-a715,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78c,cortex-r82,cortex-x1,cortex-x1c,cortex-x2,cortex-x3,cyclone,exynos-m3,exynos-m4,exynos-m5,falkor,generic,kryo,native,neoverse-512tvb,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-v1,neoverse-v2,saphira,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tsv110"), + // TargetArch_wasm32, + str_lit("generic"), + // TargetArch_wasm64p32, + str_lit("generic"), +}; + gb_global String target_endian_names[TargetEndian_COUNT] = { str_lit("little"), str_lit("big"), @@ -103,14 +133,25 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, }; +gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { + str_lit("BOOT_APPLICATION"), + str_lit("CONSOLE"), // Default + str_lit("EFI_APPLICATION"), + str_lit("EFI_BOOT_SERVICE_DRIVER"), + str_lit("EFI_ROM"), + str_lit("EFI_RUNTIME_DRIVER"), + str_lit("NATIVE"), + str_lit("POSIX"), + str_lit("WINDOWS"), + str_lit("WINDOWSCE"), +}; + #ifndef ODIN_VERSION_RAW #define ODIN_VERSION_RAW "dev-unknown-unknown" #endif gb_global String const ODIN_VERSION = str_lit(ODIN_VERSION_RAW); - - struct TargetMetrics { TargetOsKind os; TargetArchKind arch; @@ -272,14 +313,15 @@ enum SanitizerFlags : u32 { // This stores the information for the specify architecture of this build struct BuildContext { // Constants - String ODIN_OS; // target operating system - String ODIN_ARCH; // target architecture - String ODIN_VENDOR; // compiler vendor - String ODIN_VERSION; // compiler version - String ODIN_ROOT; // Odin ROOT - String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name - bool ODIN_DEBUG; // Odin in debug mode - bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not + String ODIN_OS; // Target operating system + String ODIN_ARCH; // Target architecture + String ODIN_VENDOR; // Compiler vendor + String ODIN_VERSION; // Compiler version + String ODIN_ROOT; // Odin ROOT + String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name + String ODIN_WINDOWS_SUBSYSTEM; // Empty string for non-Windows targets + bool ODIN_DEBUG; // Odin in debug mode + bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) bool ODIN_FOREIGN_ERROR_PROCEDURES; bool ODIN_VALGRIND_SUPPORT; @@ -346,12 +388,12 @@ struct BuildContext { bool ignore_warnings; bool warnings_as_errors; bool hide_error_line; + bool terse_errors; bool has_ansi_terminal_colours; bool ignore_lazy; bool ignore_llvm_build; - bool use_subsystem_windows; bool ignore_microsoft_magic; bool linker_map_file; @@ -366,6 +408,8 @@ struct BuildContext { bool dynamic_map_calls; + bool obfuscate_source_code_locations; + RelocMode reloc_mode; bool disable_red_zone; @@ -564,7 +608,13 @@ gb_global TargetMetrics target_freestanding_amd64_sysv = { TargetABI_SysV, }; - +gb_global TargetMetrics target_freestanding_arm64 = { + TargetOs_freestanding, + TargetArch_arm64, + 8, 8, 8, 16, + str_lit("aarch64-none-elf"), + str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), +}; struct NamedTargetMetrics { String name; @@ -599,6 +649,7 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("wasi_wasm64p32"), &target_wasi_wasm64p32 }, { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv }, + { str_lit("freestanding_arm64"), &target_freestanding_arm64 }, }; gb_global NamedTargetMetrics *selected_target_metrics; @@ -623,7 +674,6 @@ gb_internal TargetArchKind get_target_arch_from_string(String str) { return TargetArch_Invalid; } - gb_internal bool is_excluded_target_filename(String name) { String original_name = name; name = remove_extension_from_path(name); @@ -1258,8 +1308,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta GB_ASSERT(metrics->int_size == 2*metrics->ptr_size); } - - bc->metrics = *metrics; switch (subtarget) { case Subtarget_Default: @@ -1276,14 +1324,14 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta break; } - bc->ODIN_OS = target_os_names[metrics->os]; - bc->ODIN_ARCH = target_arch_names[metrics->arch]; - bc->endian_kind = target_endians[metrics->arch]; - bc->ptr_size = metrics->ptr_size; - bc->int_size = metrics->int_size; - bc->max_align = metrics->max_align; - bc->max_simd_align = metrics->max_simd_align; - bc->link_flags = str_lit(" "); + bc->ODIN_OS = target_os_names[metrics->os]; + bc->ODIN_ARCH = target_arch_names[metrics->arch]; + bc->endian_kind = target_endians[metrics->arch]; + bc->ptr_size = metrics->ptr_size; + bc->int_size = metrics->int_size; + bc->max_align = metrics->max_align; + bc->max_simd_align = metrics->max_simd_align; + bc->link_flags = str_lit(" "); #if defined(DEFAULT_TO_THREADED_CHECKER) bc->threaded_checker = true; @@ -1305,6 +1353,11 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } } + // Default to subsystem:CONSOLE on Windows targets + if (bc->ODIN_WINDOWS_SUBSYSTEM == "" && bc->metrics.os == TargetOs_windows) { + bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_CONSOLE]; + } + // NOTE(zangent): The linker flags to set the build architecture are different // across OSs. It doesn't make sense to allocate extra data on the heap // here, so I just #defined the linker flags to keep things concise. @@ -1476,7 +1529,7 @@ gb_internal void enable_target_feature(TokenPos pos, String const &target_featur } -gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bool with_quotes) { +gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bool with_quotes, bool with_plus) { isize len = 0; isize i = 0; for (String const &feature : build_context.target_features_set) { @@ -1485,6 +1538,7 @@ gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bo } len += feature.len; if (with_quotes) len += 2; + if (with_plus) len += 1; i += 1; } char *features = gb_alloc_array(allocator, char, len+1); @@ -1496,6 +1550,7 @@ gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bo } if (with_quotes) features[len++] = '"'; + if (with_plus) features[len++] = '+'; gb_memmove(features + len, feature.text, feature.len); len += feature.len; if (with_quotes) features[len++] = '"'; diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 77ba6b435..09ca0bc23 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1083,13 +1083,16 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String ast_node(bd, BasicDirective, ce->proc); String builtin_name = bd->name.string; - String base_dir = dir_from_path(get_file_path_string(call->file_id)); - - BlockingMutex *ignore_mutex = nullptr; - String path = {}; - bool ok = determine_path_from_string(ignore_mutex, call, base_dir, original_string, &path); - gb_unused(ok); + String path; + if (gb_path_is_absolute((char*)original_string.text)) { + path = original_string; + } else { + String base_dir = dir_from_path(get_file_path_string(call->file_id)); + BlockingMutex *ignore_mutex = nullptr; + bool ok = determine_path_from_string(ignore_mutex, call, base_dir, original_string, &path); + gb_unused(ok); + } MUTEX_GUARD(&c->info->load_file_mutex); @@ -1663,7 +1666,12 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (ce->args.count > 0) { if (ce->args[0]->kind == Ast_FieldValue) { - if (id != BuiltinProc_soa_zip) { + switch (id) { + case BuiltinProc_soa_zip: + case BuiltinProc_quaternion: + // okay + break; + default: error(call, "'field = value' calling is not allowed on built-in procedures"); return false; } @@ -2088,6 +2096,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As t = default_type(t); add_type_info_type(c, t); + GB_ASSERT(t_type_info_ptr != nullptr); + add_type_info_type(c, t_type_info_ptr); if (is_operand_value(o) && is_type_typeid(t)) { add_package_dependency(c, "runtime", "__type_info_of"); @@ -2294,61 +2304,150 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } case BuiltinProc_quaternion: { - // quaternion :: proc(real, imag, jmag, kmag: float_type) -> complex_type - Operand x = *operand; - Operand y = {}; - Operand z = {}; - Operand w = {}; + bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); + + bool fail = false; + for (Ast *arg : ce->args) { + bool mix = false; + if (first_is_field_value) { + mix = arg->kind != Ast_FieldValue; + } else { + mix = arg->kind == Ast_FieldValue; + } + if (mix) { + error(arg, "Mixture of 'field = value' and value elements in the procedure call '%.*s' is not allowed", LIT(builtin_name)); + fail = true; + break; + } + } + + if (fail) { + operand->type = t_untyped_quaternion; + operand->mode = Addressing_Constant; + operand->value = exact_value_quaternion(0.0, 0.0, 0.0, 0.0); + break; + } + + // quaternion :: proc(imag, jmag, kmag, real: float_type) -> complex_type + Operand xyzw[4] = {}; + + u32 first_index = 0; // NOTE(bill): Invalid will be the default till fixed operand->type = t_invalid; operand->mode = Addressing_Invalid; - check_expr(c, &y, ce->args[1]); - if (y.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &z, ce->args[2]); - if (y.mode == Addressing_Invalid) { - return false; - } - check_expr(c, &w, ce->args[3]); - if (y.mode == Addressing_Invalid) { - return false; - } + if (first_is_field_value) { + u32 fields_set[4] = {}; // 0 unset, 1 xyzw, 2 real/etc - convert_to_typed(c, &x, y.type); if (x.mode == Addressing_Invalid) return false; - convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; - convert_to_typed(c, &z, x.type); if (z.mode == Addressing_Invalid) return false; - convert_to_typed(c, &w, x.type); if (w.mode == Addressing_Invalid) return false; - if (x.mode == Addressing_Constant && - y.mode == Addressing_Constant && - z.mode == Addressing_Constant && - w.mode == Addressing_Constant) { - x.value = exact_value_to_float(x.value); - y.value = exact_value_to_float(y.value); - z.value = exact_value_to_float(z.value); - w.value = exact_value_to_float(w.value); - if (is_type_numeric(x.type) && x.value.kind == ExactValue_Float) { - x.type = t_untyped_float; + auto const check_field = [&fields_set, &builtin_name](CheckerContext *c, Operand *o, Ast *arg, i32 *index) -> bool { + *index = -1; + + ast_node(field, FieldValue, arg); + String name = {}; + if (field->field->kind == Ast_Ident) { + name = field->field->Ident.token.string; + } else { + error(field->field, "Expected an identifier for field argument"); + return false; + } + + u32 style = 0; + + if (name == "x") { + *index = 0; style = 1; + } else if (name == "y") { + *index = 1; style = 1; + } else if (name == "z") { + *index = 2; style = 1; + } else if (name == "w") { + *index = 3; style = 1; + } else if (name == "imag") { + *index = 0; style = 2; + } else if (name == "jmag") { + *index = 1; style = 2; + } else if (name == "kmag") { + *index = 2; style = 2; + } else if (name == "real") { + *index = 3; style = 2; + } else { + error(field->field, "Unknown name for '%.*s', expected (w, x, y, z; or real, imag, jmag, kmag), got '%.*s'", LIT(builtin_name), LIT(name)); + return false; + } + + if (fields_set[*index]) { + error(field->field, "Previously assigned field: '%.*s'", LIT(name)); + } + fields_set[*index] = style; + + check_expr(c, o, field->value); + return o->mode != Addressing_Invalid; + }; + + Operand *refs[4] = {&xyzw[0], &xyzw[1], &xyzw[2], &xyzw[3]}; + + for (i32 i = 0; i < 4; i++) { + i32 index = -1; + Operand o = {}; + bool ok = check_field(c, &o, ce->args[i], &index); + if (!ok || index < 0) { + return false; + } + first_index = cast(u32)index; + *refs[index] = o; } - if (is_type_numeric(y.type) && y.value.kind == ExactValue_Float) { - y.type = t_untyped_float; + + for (i32 i = 0; i < 4; i++) { + GB_ASSERT(fields_set[i]); } - if (is_type_numeric(z.type) && z.value.kind == ExactValue_Float) { - z.type = t_untyped_float; + for (i32 i = 1; i < 4; i++) { + if (fields_set[i] != fields_set[i-1]) { + error(call, "Mixture of xyzw and real/etc is not allowed with '%.*s'", LIT(builtin_name)); + break; + } } - if (is_type_numeric(w.type) && w.value.kind == ExactValue_Float) { - w.type = t_untyped_float; + } else { + error(call, "'%.*s' requires that all arguments are named (w, x, y, z; or real, imag, jmag, kmag)", LIT(builtin_name)); + + for (i32 i = 0; i < 4; i++) { + check_expr(c, &xyzw[i], ce->args[i]); + if (xyzw[i].mode == Addressing_Invalid) { + return false; + } } } - if (!(are_types_identical(x.type, y.type) && are_types_identical(x.type, z.type) && are_types_identical(x.type, w.type))) { - gbString tx = type_to_string(x.type); - gbString ty = type_to_string(y.type); - gbString tz = type_to_string(z.type); - gbString tw = type_to_string(w.type); - error(call, "Mismatched types to 'quaternion', '%s' vs '%s' vs '%s' vs '%s'", tx, ty, tz, tw); + + for (u32 i = 0; i < 4; i++ ){ + u32 j = (i + first_index) % 4; + if (j == first_index) { + convert_to_typed(c, &xyzw[j], xyzw[(first_index+1)%4].type); if (xyzw[j].mode == Addressing_Invalid) return false; + } else { + convert_to_typed(c, &xyzw[j], xyzw[first_index].type); if (xyzw[j].mode == Addressing_Invalid) return false; + } + } + if (xyzw[0].mode == Addressing_Constant && + xyzw[1].mode == Addressing_Constant && + xyzw[2].mode == Addressing_Constant && + xyzw[3].mode == Addressing_Constant) { + for (i32 i = 0; i < 4; i++) { + xyzw[i].value = exact_value_to_float(xyzw[i].value); + } + for (i32 i = 0; i < 4; i++) { + if (is_type_numeric(xyzw[i].type) && xyzw[i].value.kind == ExactValue_Float) { + xyzw[i].type = t_untyped_float; + } + } + } + + if (!(are_types_identical(xyzw[0].type, xyzw[1].type) && + are_types_identical(xyzw[0].type, xyzw[2].type) && + are_types_identical(xyzw[0].type, xyzw[3].type))) { + gbString tx = type_to_string(xyzw[0].type); + gbString ty = type_to_string(xyzw[1].type); + gbString tz = type_to_string(xyzw[2].type); + gbString tw = type_to_string(xyzw[3].type); + error(call, "Mismatched types to 'quaternion', 'x=%s' vs 'y=%s' vs 'z=%s' vs 'w=%s'", tx, ty, tz, tw); gb_string_free(tw); gb_string_free(tz); gb_string_free(ty); @@ -2356,31 +2455,35 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } - if (!is_type_float(x.type)) { - gbString s = type_to_string(x.type); + if (!is_type_float(xyzw[0].type)) { + gbString s = type_to_string(xyzw[0].type); error(call, "Arguments have type '%s', expected a floating point", s); gb_string_free(s); return false; } - if (is_type_endian_specific(x.type)) { - gbString s = type_to_string(x.type); + if (is_type_endian_specific(xyzw[0].type)) { + gbString s = type_to_string(xyzw[0].type); error(call, "Arguments with a specified endian are not allow, expected a normal floating point, got '%s'", s); gb_string_free(s); return false; } - if (x.mode == Addressing_Constant && y.mode == Addressing_Constant && z.mode == Addressing_Constant && w.mode == Addressing_Constant) { - f64 r = exact_value_to_float(x.value).value_float; - f64 i = exact_value_to_float(y.value).value_float; - f64 j = exact_value_to_float(z.value).value_float; - f64 k = exact_value_to_float(w.value).value_float; + + operand->mode = Addressing_Value; + + if (xyzw[0].mode == Addressing_Constant && + xyzw[1].mode == Addressing_Constant && + xyzw[2].mode == Addressing_Constant && + xyzw[3].mode == Addressing_Constant) { + f64 r = exact_value_to_float(xyzw[3].value).value_float; + f64 i = exact_value_to_float(xyzw[0].value).value_float; + f64 j = exact_value_to_float(xyzw[1].value).value_float; + f64 k = exact_value_to_float(xyzw[2].value).value_float; operand->value = exact_value_quaternion(r, i, j, k); operand->mode = Addressing_Constant; - } else { - operand->mode = Addressing_Value; } - BasicKind kind = core_type(x.type)->Basic.kind; + BasicKind kind = core_type(xyzw[first_index].type)->Basic.kind; switch (kind) { case Basic_f16: operand->type = t_quaternion64; break; case Basic_f32: operand->type = t_quaternion128; break; @@ -3087,7 +3190,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As mix = arg->kind == Ast_FieldValue; } if (mix) { - error(arg, "Mixture of 'field = value' and value elements in the procedure call 'soa_zip' is not allowed"); + error(arg, "Mixture of 'field = value' and value elements in the procedure call '%.*s' is not allowed", LIT(builtin_name)); fail = true; break; } @@ -5117,6 +5220,202 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } break; + case BuiltinProc_type_union_tag_type: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + operand->mode = Addressing_Type; + operand->type = union_tag_type(u); + } + break; + + case BuiltinProc_type_union_tag_offset: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + // NOTE(jakubtomsu): forces calculation of variant_block_size + type_size_of(u); + i64 tag_offset = u->Union.variant_block_size; + GB_ASSERT(tag_offset > 0); + + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + operand->value = exact_value_i64(tag_offset); + } + break; + + case BuiltinProc_type_union_base_tag_value: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + operand->value = exact_value_i64(u->Union.kind == UnionType_no_nil ? 0 : 1); + } break; + + case BuiltinProc_type_union_variant_count: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + operand->value = exact_value_i64(u->Union.variants.count); + } break; + + case BuiltinProc_type_variant_type_of: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + Operand x = {}; + check_expr_or_type(c, &x, ce->args[1]); + if (!is_type_integer(x.type) || x.mode != Addressing_Constant) { + error(call, "Expected a constant integer for '%.*s", LIT(builtin_name)); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + + i64 index = big_int_to_i64(&x.value.value_integer); + if (index < 0 || index >= u->Union.variants.count) { + error(call, "Variant tag out of bounds index for '%.*s", LIT(builtin_name)); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + + operand->mode = Addressing_Type; + operand->type = u->Union.variants[index]; + } + break; + + case BuiltinProc_type_variant_index_of: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *v = check_type(c, ce->args[1]); + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + i64 index = -1; + for_array(i, u->Union.variants) { + Type *vt = u->Union.variants[i]; + if (union_variant_index_types_equal(v, vt)) { + index = i64(i); + break; + } + } + + if (index < 0) { + error(operand->expr, "Expected a variant type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + operand->value = exact_value_i64(index); + } + break; + case BuiltinProc_type_struct_field_count: operand->value = exact_value_i64(0); if (operand->mode != Addressing_Type) { diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 71b897a84..ed3a109c2 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -138,11 +138,10 @@ gb_internal void check_init_variables(CheckerContext *ctx, Entity **lhs, isize l } if (o->type && is_type_no_copy(o->type)) { - begin_error_block(); + ERROR_BLOCK(); if (check_no_copy_assignment(*o, str_lit("initialization"))) { error_line("\tInitialization of a #no_copy type must be either implicitly zero, a constant literal, or a return value from a call expression"); } - end_error_block(); } } if (rhs_count > 0 && lhs_count != rhs_count) { @@ -908,7 +907,91 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { break; } + e->Procedure.entry_point_only = ac.entry_point_only; e->Procedure.is_export = ac.is_export; + + bool has_instrumentation = false; + if (pl->body == nullptr) { + has_instrumentation = false; + if (ac.no_instrumentation != Instrumentation_Default) { + error(e->token, "@(no_instrumentation) is not allowed on foreign procedures"); + } + } else { + AstFile *file = e->token.pos.file_id ? global_files[e->token.pos.file_id] : nullptr; + if (file) { + has_instrumentation = (file->flags & AstFile_NoInstrumentation) == 0; + } + + switch (ac.no_instrumentation) { + case Instrumentation_Enabled: has_instrumentation = true; break; + case Instrumentation_Default: break; + case Instrumentation_Disabled: has_instrumentation = false; break; + } + } + + auto const is_valid_instrumentation_call = [](Type *type) -> bool { + if (type == nullptr || type->kind != Type_Proc) { + return false; + } + if (type->Proc.calling_convention != ProcCC_Contextless) { + return false; + } + if (type->Proc.result_count != 0) { + return false; + } + if (type->Proc.param_count != 3) { + return false; + } + Type *p0 = type->Proc.params->Tuple.variables[0]->type; + Type *p1 = type->Proc.params->Tuple.variables[1]->type; + Type *p3 = type->Proc.params->Tuple.variables[2]->type; + return is_type_rawptr(p0) && is_type_rawptr(p1) && are_types_identical(p3, t_source_code_location); + }; + + static char const *instrumentation_proc_type_str = "proc \"contextless\" (proc_address: rawptr, call_site_return_address: rawptr, loc: runtime.Source_Code_Location)"; + + if (ac.instrumentation_enter && ac.instrumentation_exit) { + error(e->token, "A procedure cannot be marked with both @(instrumentation_enter) and @(instrumentation_exit)"); + + has_instrumentation = false; + e->flags |= EntityFlag_Require; + } else if (ac.instrumentation_enter) { + if (!is_valid_instrumentation_call(e->type)) { + init_core_source_code_location(ctx->checker); + gbString s = type_to_string(e->type); + error(e->token, "@(instrumentation_enter) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s); + gb_string_free(s); + } + MUTEX_GUARD(&ctx->info->instrumentation_mutex); + if (ctx->info->instrumentation_enter_entity != nullptr) { + error(e->token, "@(instrumentation_enter) has already been set"); + } else { + ctx->info->instrumentation_enter_entity = e; + } + + has_instrumentation = false; + e->flags |= EntityFlag_Require; + } else if (ac.instrumentation_exit) { + init_core_source_code_location(ctx->checker); + if (!is_valid_instrumentation_call(e->type)) { + gbString s = type_to_string(e->type); + error(e->token, "@(instrumentation_exit) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s); + gb_string_free(s); + } + MUTEX_GUARD(&ctx->info->instrumentation_mutex); + if (ctx->info->instrumentation_exit_entity != nullptr) { + error(e->token, "@(instrumentation_exit) has already been set"); + } else { + ctx->info->instrumentation_exit_entity = e; + } + + has_instrumentation = false; + e->flags |= EntityFlag_Require; + } + + e->Procedure.has_instrumentation = has_instrumentation; + + e->deprecated_message = ac.deprecated_message; e->warning_message = ac.warning_message; ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); @@ -1300,8 +1383,8 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D continue; } - begin_error_block(); - defer (end_error_block()); + + ERROR_BLOCK(); ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type); bool both_have_where_clauses = false; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 5cc548739..bc7ff1bbb 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -184,6 +184,8 @@ gb_internal void populate_check_did_you_mean_objc_entity(StringSet *set, Entity gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, bool is_type, char const *prefix = "") { + if (build_context.terse_errors) { return; } + ERROR_BLOCK(); GB_ASSERT(e->kind == Entity_TypeName); GB_ASSERT(e->TypeName.objc_metadata != nullptr); @@ -204,6 +206,8 @@ gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, b } gb_internal void check_did_you_mean_type(String const &name, Array const &fields, char const *prefix = "") { + if (build_context.terse_errors) { return; } + ERROR_BLOCK(); DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name); @@ -217,6 +221,8 @@ gb_internal void check_did_you_mean_type(String const &name, Array con gb_internal void check_did_you_mean_type(String const &name, Slice const &fields, char const *prefix = "") { + if (build_context.terse_errors) { return; } + ERROR_BLOCK(); DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name); @@ -229,6 +235,8 @@ gb_internal void check_did_you_mean_type(String const &name, Slice con } gb_internal void check_did_you_mean_scope(String const &name, Scope *scope, char const *prefix = "") { + if (build_context.terse_errors) { return; } + ERROR_BLOCK(); DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.count, name); @@ -2203,7 +2211,6 @@ gb_internal bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *typ ERROR_BLOCK(); - if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { error(o->expr, "'%s' truncated to '%s', got %s", a, b, s); @@ -2264,8 +2271,7 @@ gb_internal void check_old_for_or_switch_value_usage(Ast *expr) { if (e != nullptr && (e->flags & EntityFlag_OldForOrSwitchValue) != 0) { GB_ASSERT(e->kind == Entity_Variable); - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); if ((e->flags & EntityFlag_ForValue) != 0) { Type *parent_type = type_deref(e->Variable.for_loop_parent_type); @@ -2309,8 +2315,7 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * break; default: { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); error(op, "Cannot take the pointer address of '%s'", str); if (e != nullptr && (e->flags & EntityFlag_ForValue) != 0) { Type *parent_type = type_deref(e->Variable.for_loop_parent_type); @@ -2339,7 +2344,7 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * ast_node(ue, UnaryExpr, node); if (ast_node_expect(ue->expr, Ast_IndexExpr)) { ast_node(ie, IndexExpr, ue->expr); - Type *soa_type = type_of_expr(ie->expr); + Type *soa_type = type_deref(type_of_expr(ie->expr)); GB_ASSERT(is_type_soa_struct(soa_type)); o->type = alloc_type_soa_pointer(soa_type); } else { @@ -3071,7 +3076,7 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { x->mode = Addressing_Invalid; - begin_error_block(); + ERROR_BLOCK(); error(x->expr, "Cannot cast '%s' as '%s' from '%s'", expr_str, to_type, from_type); if (is_const_expr) { gbString val_str = exact_value_to_string(x->value); @@ -3094,8 +3099,6 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { } check_cast_error_suggestion(c, x, type); - end_error_block(); - return; } @@ -4047,8 +4050,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar if (check_is_assignable_to(c, operand, elem)) { if (t->Matrix.row_count != t->Matrix.column_count) { operand->mode = Addressing_Invalid; - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); convert_untyped_error(c, operand, target_type); error_line("\tNote: Only a square matrix types can be initialized with a scalar value\n"); @@ -4109,8 +4111,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar target_type = t->Union.variants[first_success_index]; break; } else if (valid_count > 1) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); GB_ASSERT(first_success_index >= 0); operand->mode = Addressing_Invalid; @@ -4136,8 +4137,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else if (is_type_untyped_uninit(operand->type)) { target_type = t_untyped_uninit; } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); @@ -4714,6 +4714,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod entity = scope_lookup_current(import_scope, entity_name); bool allow_builtin = false; if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { + ERROR_BLOCK(); error(node, "'%.*s' is not declared by '%.*s'", LIT(entity_name), LIT(import_name)); operand->mode = Addressing_Invalid; operand->expr = node; @@ -4914,6 +4915,8 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod error(op_expr, "Type '%s' has no field '%s'", op_str, sel_str); } } else { + ERROR_BLOCK(); + error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str); if (operand->type != nullptr && selector->kind == Ast_Ident) { @@ -5606,9 +5609,6 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A for (isize i = 0; i < pt->param_count; i++) { if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; - if (is_blank_ident(e->token)) { - continue; - } if (e->kind == Entity_Variable) { if (e->Variable.param_value.kind != ParameterValue_Invalid) { ordered_operands[i].mode = Addressing_Value; @@ -5652,6 +5652,14 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } else { if (show_error) { check_assignment(c, o, param_type, str_lit("procedure argument")); + + Type *src = base_type(o->type); + Type *dst = base_type(param_type); + if (is_type_slice(src) && are_types_identical(src->Slice.elem, dst)) { + gbString a = expr_to_string(o->expr); + error_line("\tSuggestion: Did you mean to pass the slice into the variadic parameter with ..%s?\n\n", a); + gb_string_free(a); + } } err = CallArgumentError_WrongTypes; } @@ -6333,8 +6341,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, }; if (valids.count == 0) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name); if (positional_operands.count == 0 && named_operands.count == 0) { @@ -6424,8 +6431,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, data.result_type = t_invalid; } else if (valids.count > 1) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name); print_argument_types(); @@ -7190,6 +7196,14 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } } add_entity_use(c, operand->expr, initial_entity); + + if (initial_entity->Procedure.entry_point_only) { + if (c->curr_proc_decl && c->curr_proc_decl->entity == c->info->entry_point) { + // Okay + } else { + error(operand->expr, "Procedures with the attribute '@(entry_point_only)' can only be called directly from the user-level entry point procedure"); + } + } } if (operand->mode != Addressing_ProcGroup) { @@ -7420,7 +7434,7 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 *max_count = t->Struct.soa_count; } o->type = t->Struct.soa_elem; - if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable) { + if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable || indirection) { o->mode = Addressing_SoaVariable; } else { o->mode = Addressing_Value; @@ -7636,6 +7650,8 @@ gb_internal ExprKind check_implicit_selector_expr(CheckerContext *c, Operand *o, String name = ise->selector->Ident.token.string; if (is_type_enum(th)) { + ERROR_BLOCK(); + Type *bt = base_type(th); GB_ASSERT(bt->kind == Type_Enum); @@ -7879,7 +7895,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A } else { if (name == "location") { init_core_source_code_location(c->checker); - error(node, "'#%.*s' must be used in a call expression", LIT(name)); + error(node, "'#location' must be used as a call, i.e. #location(proc), where #location() defaults to the procedure in which it was used."); o->type = t_source_code_location; o->mode = Addressing_Value; } else if ( @@ -9037,8 +9053,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } if (unhandled.count > 0) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); if (unhandled.count == 1) { error_no_newline(node, "Unhandled enumerated array case: %.*s", LIT(unhandled[0]->token.string)); @@ -9049,9 +9064,11 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * error_line("\t%.*s\n", LIT(f->token.string)); } } - error_line("\n"); - error_line("\tSuggestion: Was '#partial %s{...}' wanted?\n", type_to_string(type)); + if (!build_context.terse_errors) { + error_line("\n"); + error_line("\tSuggestion: Was '#partial %s{...}' wanted?\n", type_to_string(type)); + } } } @@ -9675,7 +9692,9 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, if (index < 0) { gbString str = expr_to_string(o->expr); error(o->expr, "Cannot index a constant '%s'", str); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + if (!build_context.terse_errors) { + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + } gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -9689,7 +9708,9 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, if (!success) { gbString str = expr_to_string(o->expr); error(o->expr, "Cannot index a constant '%s' with index %lld", str, cast(long long)index); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + if (!build_context.terse_errors) { + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + } gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -9877,7 +9898,9 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, if (!all_constant) { gbString str = expr_to_string(o->expr); error(o->expr, "Cannot slice '%s' with non-constant indices", str); - error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + if (!build_context.terse_errors) { + error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); + } gb_string_free(str); o->mode = Addressing_Value; // NOTE(bill): Keep subsequent values going without erring o->expr = node; @@ -10233,15 +10256,15 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast } else { gbString str = expr_to_string(o->expr); gbString typ = type_to_string(o->type); - begin_error_block(); + ERROR_BLOCK(); error(o->expr, "Cannot dereference '%s' of type '%s'", str, typ); if (o->type && is_type_multi_pointer(o->type)) { - error_line("\tDid you mean '%s[0]'?\n", str); + if (!build_context.terse_errors) { + error_line("\tDid you mean '%s[0]'?\n", str); + } } - end_error_block(); - gb_string_free(typ); gb_string_free(str); o->mode = Addressing_Invalid; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index b93be734e..d56e5e212 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1085,8 +1085,7 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags } if (unhandled.count > 0) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); if (unhandled.count == 1) { error_no_newline(node, "Unhandled switch case: %.*s", LIT(unhandled[0]->token.string)); @@ -1813,7 +1812,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f } if (new_name_count == 0) { - begin_error_block(); + ERROR_BLOCK(); error(node, "No new declarations on the left hand side"); bool all_underscore = true; for (Ast *name : vd->names) { @@ -1831,7 +1830,6 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f error_line("\tSuggestion: Try changing the declaration (:=) to an assignment (=)\n"); } - end_error_block(); } Type *init_type = nullptr; diff --git a/src/check_type.cpp b/src/check_type.cpp index d66b196bc..a95026711 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2070,33 +2070,33 @@ gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc type->Proc.diverging = pt->diverging; type->Proc.optional_ok = optional_ok; - if (param_count > 0) { - Entity *end = params->Tuple.variables[param_count-1]; - if (end->flags&EntityFlag_CVarArg) { + bool is_polymorphic = false; + for (isize i = 0; i < param_count; i++) { + Entity *e = params->Tuple.variables[i]; + + if (e->kind != Entity_Variable) { + is_polymorphic = true; + } else if (is_type_polymorphic(e->type)) { + is_polymorphic = true; + } + + if (e->flags&EntityFlag_CVarArg) { + if (i != param_count - 1) { + error(e->token, "#c_vararg can only be applied to the last parameter"); + continue; + } + switch (cc) { default: type->Proc.c_vararg = true; break; case ProcCC_Odin: case ProcCC_Contextless: - error(end->token, "Calling convention does not support #c_vararg"); + error(e->token, "Calling convention does not support #c_vararg"); break; } } } - - - bool is_polymorphic = false; - for (isize i = 0; i < param_count; i++) { - Entity *e = params->Tuple.variables[i]; - if (e->kind != Entity_Variable) { - is_polymorphic = true; - break; - } else if (is_type_polymorphic(e->type)) { - is_polymorphic = true; - break; - } - } for (isize i = 0; i < result_count; i++) { Entity *e = results->Tuple.variables[i]; if (e->kind != Entity_Variable) { @@ -2702,14 +2702,13 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T check_expr_or_type(&c, &o, pt->type); if (o.mode != Addressing_Invalid && o.mode != Addressing_Type) { // NOTE(bill): call check_type_expr again to get a consistent error message - begin_error_block(); + ERROR_BLOCK(); elem = check_type_expr(&c, pt->type, nullptr); if (o.mode == Addressing_Variable) { gbString s = expr_to_string(pt->type); error_line("\tSuggestion: ^ is used for pointer types, did you mean '&%s'?\n", s); gb_string_free(s); } - end_error_block(); } else { elem = o.type; } diff --git a/src/checker.cpp b/src/checker.cpp index 29f22bd9c..4d7514d0b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -968,10 +968,11 @@ gb_internal void init_universal(void) { add_global_bool_constant("true", true); add_global_bool_constant("false", false); - add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); - add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); - add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); + add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); + add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); + add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); + add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); { GlobalEnumValue values[TargetOs_COUNT] = { @@ -1084,7 +1085,7 @@ gb_internal void init_universal(void) { add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp())); - add_global_bool_constant("__ODIN_LLVM_F16_SUPPORTED", lb_use_new_pass_system()); + add_global_bool_constant("__ODIN_LLVM_F16_SUPPORTED", lb_use_new_pass_system() && !is_arch_wasm()); { GlobalEnumValue values[3] = { @@ -2211,9 +2212,14 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { Entity *e = entry.value; switch (bt->Struct.soa_kind) { case StructSoa_Dynamic: + add_min_dep_type_info(c, t_type_info_ptr); // append_soa + add_min_dep_type_info(c, t_allocator); /*fallthrough*/ case StructSoa_Slice: + add_min_dep_type_info(c, t_int); + add_min_dep_type_info(c, t_uint); + /*fallthrough*/ case StructSoa_Fixed: add_min_dep_type_info(c, alloc_type_pointer(e->type)); break; @@ -2289,7 +2295,6 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { if (entity->type != nullptr && is_type_polymorphic(entity->type)) { - DeclInfo *decl = decl_info_of_entity(entity); if (decl != nullptr && decl->gen_proc_type == nullptr) { return; @@ -2341,98 +2346,7 @@ gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String co } - -gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { - isize entity_count = c->info.entities.count; - isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor - - ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); - map_init(&c->info.minimum_dependency_type_info_set); - -#define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ - if (condition) { \ - String entities[] = {__VA_ARGS__}; \ - for (isize i = 0; i < gb_count_of(entities); i++) { \ - force_add_dependency_entity(c, c->info.runtime_package->scope, entities[i]); \ - } \ - } \ -} while (0) - - // required runtime entities - FORCE_ADD_RUNTIME_ENTITIES(true, - // Odin types - str_lit("Source_Code_Location"), - str_lit("Context"), - str_lit("Allocator"), - str_lit("Logger"), - - // Odin internal procedures - str_lit("__init_context"), - str_lit("cstring_to_string"), - str_lit("_cleanup_runtime"), - - // Pseudo-CRT required procedures - str_lit("memset"), - str_lit("memcpy"), - str_lit("memmove"), - - // Utility procedures - str_lit("memory_equal"), - str_lit("memory_compare"), - str_lit("memory_compare_zero"), - ); - - FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend, - // Extended data type internal procedures - str_lit("umodti3"), - str_lit("udivti3"), - str_lit("modti3"), - str_lit("divti3"), - str_lit("fixdfti"), - str_lit("fixunsdfti"), - str_lit("fixunsdfdi"), - str_lit("floattidf"), - str_lit("floattidf_unsigned"), - str_lit("truncsfhf2"), - str_lit("truncdfhf2"), - str_lit("gnu_h2f_ieee"), - str_lit("gnu_f2h_ieee"), - str_lit("extendhfsf2"), - - // WASM Specific - str_lit("__ashlti3"), - str_lit("__multi3"), - ); - - FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_rtti, - // Odin types - str_lit("Type_Info"), - - // Global variables - str_lit("type_table"), - str_lit("__type_info_of"), - ); - - FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_entry_point, - // Global variables - str_lit("args__"), - ); - - FORCE_ADD_RUNTIME_ENTITIES((build_context.no_crt && !is_arch_wasm()), - // NOTE(bill): Only if these exist - str_lit("_tls_index"), - str_lit("_fltused"), - ); - - FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_bounds_check, - // Bounds checking related procedures - str_lit("bounds_check_error"), - str_lit("matrix_bounds_check_error"), - str_lit("slice_expr_error_hi"), - str_lit("slice_expr_error_lo_hi"), - str_lit("multi_pointer_slice_expr_error"), - ); - +gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *start) { for_array(i, c->info.definitions) { Entity *e = c->info.definitions[i]; if (e->scope == builtin_pkg->scope) { @@ -2575,6 +2489,104 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { start->flags |= EntityFlag_Used; add_dependency_to_set(c, start); } +} + +gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { + isize entity_count = c->info.entities.count; + isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor + + ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); + map_init(&c->info.minimum_dependency_type_info_set); + +#define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ + if (condition) { \ + String entities[] = {__VA_ARGS__}; \ + for (isize i = 0; i < gb_count_of(entities); i++) { \ + force_add_dependency_entity(c, c->info.runtime_package->scope, entities[i]); \ + } \ + } \ +} while (0) + + // required runtime entities + FORCE_ADD_RUNTIME_ENTITIES(true, + // Odin types + str_lit("Source_Code_Location"), + str_lit("Context"), + str_lit("Allocator"), + str_lit("Logger"), + + // Odin internal procedures + str_lit("__init_context"), + str_lit("cstring_to_string"), + str_lit("_cleanup_runtime"), + + // Pseudo-CRT required procedures + str_lit("memset"), + str_lit("memcpy"), + str_lit("memmove"), + + // Utility procedures + str_lit("memory_equal"), + str_lit("memory_compare"), + str_lit("memory_compare_zero"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend, + // Extended data type internal procedures + str_lit("umodti3"), + str_lit("udivti3"), + str_lit("modti3"), + str_lit("divti3"), + str_lit("fixdfti"), + str_lit("fixunsdfti"), + str_lit("fixunsdfdi"), + str_lit("floattidf"), + str_lit("floattidf_unsigned"), + str_lit("truncsfhf2"), + str_lit("truncdfhf2"), + str_lit("gnu_h2f_ieee"), + str_lit("gnu_f2h_ieee"), + str_lit("extendhfsf2"), + + // WASM Specific + str_lit("__ashlti3"), + str_lit("__multi3"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_rtti, + // Odin types + str_lit("Type_Info"), + + // Global variables + str_lit("type_table"), + str_lit("__type_info_of"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_entry_point, + // Global variables + str_lit("args__"), + ); + + FORCE_ADD_RUNTIME_ENTITIES((build_context.no_crt && !is_arch_wasm()), + // NOTE(bill): Only if these exist + str_lit("_tls_index"), + str_lit("_fltused"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_bounds_check, + // Bounds checking related procedures + str_lit("bounds_check_error"), + str_lit("matrix_bounds_check_error"), + str_lit("slice_expr_error_hi"), + str_lit("slice_expr_error_lo_hi"), + str_lit("multi_pointer_slice_expr_error"), + ); + + add_dependency_to_set(c, c->info.instrumentation_enter_entity); + add_dependency_to_set(c, c->info.instrumentation_exit_entity); + + generate_minimum_dependency_set_internal(c, start); + #undef FORCE_ADD_RUNTIME_ENTITIES } @@ -3405,6 +3417,39 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { error(elem, "Expected a string value for '%.*s'", LIT(name)); } return true; + } else if (name == "entry_point_only") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->entry_point_only = true; + return true; + } else if (name == "no_instrumentation") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->no_instrumentation = Instrumentation_Disabled; + } else if (ev.kind == ExactValue_Bool) { + if (ev.value_bool) { + ac->no_instrumentation = Instrumentation_Disabled; + } else { + ac->no_instrumentation = Instrumentation_Enabled; + } + } else { + error(value, "Expected either a boolean or no parameter for '%.*s'", LIT(name)); + return false; + } + return true; + } else if (name == "instrumentation_enter") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->instrumentation_enter = true; + return true; + } else if (name == "instrumentation_exit") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->instrumentation_exit = true; + return true; } return false; } @@ -4014,12 +4059,11 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (c->foreign_context.default_cc > 0) { cc = c->foreign_context.default_cc; } else if (is_arch_wasm()) { - begin_error_block(); + ERROR_BLOCK(); error(init, "For wasm related targets, it is required that you either define the" " @(default_calling_convention=) on the foreign block or" " explicitly assign it on the procedure signature"); error_line("\tSuggestion: when dealing with normal Odin code (e.g. js_wasm32), use \"contextless\"; when dealing with Emscripten like code, use \"c\"\n"); - end_error_block(); } } e->Procedure.link_prefix = c->foreign_context.link_prefix; @@ -4066,8 +4110,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (e->kind != Entity_Procedure) { if (fl != nullptr) { - begin_error_block(); - defer (end_error_block()); + ERROR_BLOCK(); AstKind kind = init->kind; error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[kind])); @@ -4733,7 +4776,7 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { } if (has_asm_extension(fullpath)) { - if (build_context.metrics.arch != TargetArch_amd64) { + if (build_context.metrics.arch != TargetArch_amd64 && build_context.metrics.os != TargetOs_darwin) { error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s", LIT(target_os_names[build_context.metrics.os]), LIT(target_arch_names[build_context.metrics.arch])); } @@ -5304,6 +5347,44 @@ gb_internal void calculate_global_init_order(Checker *c) { } } +gb_internal void check_procedure_later_from_entity(Checker *c, Entity *e, char const *from_msg) { + if (e == nullptr || e->kind != Entity_Procedure) { + return; + } + if (e->Procedure.is_foreign) { + return; + } + if ((e->flags & EntityFlag_ProcBodyChecked) != 0) { + return; + } + Type *type = base_type(e->type); + GB_ASSERT(type->kind == Type_Proc); + + if (is_type_polymorphic(type) && !type->Proc.is_poly_specialized) { + return; + } + + GB_ASSERT(e->decl_info != nullptr); + + ProcInfo *pi = gb_alloc_item(permanent_allocator(), ProcInfo); + pi->file = e->file; + pi->token = e->token; + pi->decl = e->decl_info; + pi->type = e->type; + + Ast *pl = e->decl_info->proc_lit; + GB_ASSERT(pl != nullptr); + pi->body = pl->ProcLit.body; + pi->tags = pl->ProcLit.tags; + if (pi->body == nullptr) { + return; + } + if (from_msg != nullptr) { + debugf("CHECK PROCEDURE LATER [FROM %s]! %.*s :: %s {...}\n", from_msg, LIT(e->token.string), type_to_string(e->type)); + } + check_procedure_later(c, pi); +} + gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) { if (pi == nullptr) { @@ -5410,6 +5491,15 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u add_untyped_expressions(&c->info, ctx.untyped); + rw_mutex_shared_lock(&ctx.decl->deps_mutex); + for (Entity *dep : ctx.decl->deps) { + if (dep && dep->kind == Entity_Procedure && + (dep->flags & EntityFlag_ProcBodyChecked) == 0) { + check_procedure_later_from_entity(c, dep, NULL); + } + } + rw_mutex_shared_unlock(&ctx.decl->deps_mutex); + return true; } @@ -5432,30 +5522,7 @@ gb_internal void check_unchecked_bodies(Checker *c) { global_procedure_body_in_worker_queue = false; for (Entity *e : c->info.minimum_dependency_set) { - if (e == nullptr || e->kind != Entity_Procedure) { - continue; - } - if (e->Procedure.is_foreign) { - continue; - } - if ((e->flags & EntityFlag_ProcBodyChecked) == 0) { - GB_ASSERT(e->decl_info != nullptr); - - ProcInfo *pi = gb_alloc_item(permanent_allocator(), ProcInfo); - pi->file = e->file; - pi->token = e->token; - pi->decl = e->decl_info; - pi->type = e->type; - - Ast *pl = e->decl_info->proc_lit; - GB_ASSERT(pl != nullptr); - pi->body = pl->ProcLit.body; - pi->tags = pl->ProcLit.tags; - if (pi->body == nullptr) { - continue; - } - check_procedure_later(c, pi); - } + check_procedure_later_from_entity(c, e, "check_unchecked_bodies"); } if (!global_procedure_body_in_worker_queue) { @@ -5497,7 +5564,28 @@ gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) { } } +gb_internal GB_COMPARE_PROC(init_procedures_cmp); +gb_internal GB_COMPARE_PROC(fini_procedures_cmp); + +gb_internal void remove_neighbouring_duplicate_entires_from_sorted_array(Array *array) { + Entity *prev = nullptr; + + for (isize i = 0; i < array->count; /**/) { + Entity *curr = array->data[i]; + if (prev == curr) { + array_ordered_remove(array, i); + } else { + prev = curr; + i += 1; + } + } +} + + gb_internal void check_test_procedures(Checker *c) { + gb_sort_array(c->info.testing_procedures.data, c->info.testing_procedures.count, init_procedures_cmp); + remove_neighbouring_duplicate_entires_from_sorted_array(&c->info.testing_procedures); + if (build_context.test_names.entries.count == 0) { return; } @@ -5943,10 +6031,14 @@ gb_internal GB_COMPARE_PROC(fini_procedures_cmp) { return init_procedures_cmp(b, a); } - gb_internal void check_sort_init_and_fini_procedures(Checker *c) { gb_sort_array(c->info.init_procedures.data, c->info.init_procedures.count, init_procedures_cmp); gb_sort_array(c->info.fini_procedures.data, c->info.fini_procedures.count, fini_procedures_cmp); + + // NOTE(bill): remove possible duplicates from the init/fini lists + // NOTE(bill): because the arrays are sorted, you only need to check the previous element + remove_neighbouring_duplicate_entires_from_sorted_array(&c->info.init_procedures); + remove_neighbouring_duplicate_entires_from_sorted_array(&c->info.fini_procedures); } gb_internal void add_type_info_for_type_definitions(Checker *c) { @@ -6091,9 +6183,6 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("calculate global init order"); calculate_global_init_order(c); - TIME_SECTION("check test procedures"); - check_test_procedures(c); - TIME_SECTION("add type info for type definitions"); add_type_info_for_type_definitions(c); check_merge_queues_into_arrays(c); @@ -6108,7 +6197,18 @@ gb_internal void check_parsed_files(Checker *c) { check_unchecked_bodies(c); check_merge_queues_into_arrays(c); + thread_pool_wait(); + TIME_SECTION("update minimum dependency set"); + generate_minimum_dependency_set_internal(c, c->info.entry_point); + + // NOTE(laytan): has to be ran after generate_minimum_dependency_set, + // because that collects the test procedures. + TIME_SECTION("check test procedures"); + check_test_procedures(c); + + check_merge_queues_into_arrays(c); + thread_pool_wait(); TIME_SECTION("check entry point"); if (build_context.build_mode == BuildMode_Executable && !build_context.no_entry_point && build_context.command_kind != Command_test) { @@ -6150,6 +6250,17 @@ gb_internal void check_parsed_files(Checker *c) { GB_ASSERT(c->info.entity_queue.count.load(std::memory_order_relaxed) == 0); GB_ASSERT(c->info.definition_queue.count.load(std::memory_order_relaxed) == 0); + TIME_SECTION("check instrumentation calls"); + { + if ((c->info.instrumentation_enter_entity != nullptr) ^ + (c->info.instrumentation_exit_entity != nullptr)) { + Entity *e = c->info.instrumentation_enter_entity; + if (!e) e = c->info.instrumentation_exit_entity; + error(e->token, "Both @(instrumentation_enter) and @(instrumentation_exit) must be defined"); + } + } + + TIME_SECTION("add untyped expression values"); // Add untyped expression values for (UntypedExprInfo u = {}; mpsc_dequeue(&c->global_untyped_queue, &u); /**/) { diff --git a/src/checker.hpp b/src/checker.hpp index a6a5f6788..9da0f2950 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -103,6 +103,12 @@ struct DeferredProcedure { }; +enum InstrumentationFlag : i32 { + Instrumentation_Enabled = -1, + Instrumentation_Default = 0, + Instrumentation_Disabled = +1, +}; + struct AttributeContext { String link_name; String link_prefix; @@ -113,19 +119,23 @@ struct AttributeContext { String deprecated_message; String warning_message; DeferredProcedure deferred_procedure; - bool is_export : 1; - bool is_static : 1; - bool require_results : 1; - bool require_declaration : 1; - bool has_disabled_proc : 1; - bool disabled_proc : 1; - bool test : 1; - bool init : 1; - bool fini : 1; - bool set_cold : 1; + bool is_export : 1; + bool is_static : 1; + bool require_results : 1; + bool require_declaration : 1; + bool has_disabled_proc : 1; + bool disabled_proc : 1; + bool test : 1; + bool init : 1; + bool fini : 1; + bool set_cold : 1; + bool entry_point_only : 1; + bool instrumentation_enter : 1; + bool instrumentation_exit : 1; u32 optimization_mode; // ProcedureOptimizationMode i64 foreign_import_priority_index; String extra_linker_flags; + InstrumentationFlag no_instrumentation; String objc_class; String objc_name; @@ -402,6 +412,10 @@ struct CheckerInfo { BlockingMutex all_procedures_mutex; Array all_procedures; + + BlockingMutex instrumentation_mutex; + Entity *instrumentation_enter_entity; + Entity *instrumentation_exit_entity; }; struct CheckerContext { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index c89ab2429..3bab16293 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -260,6 +260,12 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_is_specialization_of, BuiltinProc_type_is_variant_of, + BuiltinProc_type_union_tag_type, + BuiltinProc_type_union_tag_offset, + BuiltinProc_type_union_base_tag_value, + BuiltinProc_type_union_variant_count, + BuiltinProc_type_variant_type_of, + BuiltinProc_type_variant_index_of, BuiltinProc_type_struct_field_count, @@ -557,7 +563,13 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_specialization_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("type_is_variant_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_variant_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_union_tag_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_union_tag_offset"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_union_base_tag_value"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_union_variant_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_variant_type_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_variant_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_struct_field_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/entity.cpp b/src/entity.cpp index ce27da3f2..e6c46d37e 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -250,6 +250,8 @@ struct Entity { bool is_export : 1; bool generated_from_polymorphic : 1; bool target_feature_disabled : 1; + bool entry_point_only : 1; + bool has_instrumentation : 1; String target_feature; } Procedure; struct { diff --git a/src/exact_value.cpp b/src/exact_value.cpp index cd499272f..b744d2db0 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -174,7 +174,7 @@ gb_internal ExactValue exact_value_integer_from_string(String const &string) { -gb_internal f64 float_from_string(String const &string) { +gb_internal f64 float_from_string(String const &string, bool *success = nullptr) { if (string.len < 128) { char buf[128] = {}; isize n = 0; @@ -187,7 +187,13 @@ gb_internal f64 float_from_string(String const &string) { buf[n++] = cast(char)c; } buf[n] = 0; - return atof(buf); + + char *end_ptr; + f64 f = strtod(buf, &end_ptr); + if (success != nullptr) { + *success = *end_ptr == '\0'; + } + return f; } else { TEMPORARY_ALLOCATOR_GUARD(); char *buf = gb_alloc_array(temporary_allocator(), char, string.len+1); @@ -201,7 +207,13 @@ gb_internal f64 float_from_string(String const &string) { buf[n++] = cast(char)c; } buf[n] = 0; - return atof(buf); + + char *end_ptr; + f64 f = strtod(buf, &end_ptr); + if (success != nullptr) { + *success = *end_ptr == '\0'; + } + return f; } /* isize i = 0; @@ -313,7 +325,11 @@ gb_internal ExactValue exact_value_float_from_string(String string) { return exact_value_integer_from_string(string); } - f64 f = float_from_string(string); + bool success; + f64 f = float_from_string(string, &success); + if (!success) { + return {ExactValue_Invalid}; + } return exact_value_float(f); } diff --git a/src/gb/gb.h b/src/gb/gb.h index 5dae7a5c4..93d250f21 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -448,7 +448,7 @@ typedef i32 b32; // NOTE(bill): Prefer this!!! #define gb_inline __forceinline #endif #else - #define gb_inline __attribute__ ((__always_inline__)) + #define gb_inline inline __attribute__ ((__always_inline__)) #endif #endif diff --git a/src/linker.cpp b/src/linker.cpp index eb3687ae2..c0952d0e0 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -7,10 +7,19 @@ struct LinkerData { Array output_temp_paths; String output_base; String output_name; +#if defined(GB_SYSTEM_OSX) + b8 needs_system_library_linked; +#endif }; gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...); +#if defined(GB_SYSTEM_OSX) +gb_internal void linker_enable_system_library_linking(LinkerData *ld) { + ld->needs_system_library_linked = 1; +} +#endif + gb_internal void linker_data_init(LinkerData *ld, CheckerInfo *info, String const &init_fullpath) { gbAllocator ha = heap_allocator(); array_init(&ld->output_object_paths, ha); @@ -18,6 +27,10 @@ gb_internal void linker_data_init(LinkerData *ld, CheckerInfo *info, String cons array_init(&ld->foreign_libraries, ha, 0, 1024); ptr_set_init(&ld->foreign_libraries_set, 1024); +#if defined(GB_SYSTEM_OSX) + ld->needs_system_library_linked = 0; +#endif + if (build_context.out_filepath.len == 0) { ld->output_name = remove_directory_from_path(init_fullpath); ld->output_name = remove_extension_from_path(ld->output_name); @@ -195,7 +208,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (build_context.pdb_filepath != "") { String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); - link_settings = gb_string_append_fmt(link_settings, " /PDB:%.*s", LIT(pdb_path)); + link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); } if (build_context.no_crt) { @@ -220,7 +233,6 @@ gb_internal i32 linker_stage(LinkerData *gen) { String windows_sdk_bin_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Win_SDK_Bin_Path]); defer (gb_free(heap_allocator(), windows_sdk_bin_path.text)); - char const *subsystem_str = build_context.use_subsystem_windows ? "WINDOWS" : "CONSOLE"; if (!build_context.use_lld) { // msvc String res_path = {}; defer (gb_free(heap_allocator(), res_path.text)); @@ -252,14 +264,14 @@ gb_internal i32 linker_stage(LinkerData *gen) { result = system_exec_command_line_app("msvc-link", "\"%.*slink.exe\" %s %.*s -OUT:\"%.*s\" %s " - "/nologo /incremental:no /opt:ref /subsystem:%s " + "/nologo /incremental:no /opt:ref /subsystem:%.*s " "%.*s " "%.*s " "%s " "", LIT(vs_exe_path), object_files, LIT(res_path), LIT(output_filename), link_settings, - subsystem_str, + LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -270,14 +282,14 @@ gb_internal i32 linker_stage(LinkerData *gen) { } else { // lld result = system_exec_command_line_app("msvc-lld-link", "\"%.*s\\bin\\lld-link\" %s -OUT:\"%.*s\" %s " - "/nologo /incremental:no /opt:ref /subsystem:%s " + "/nologo /incremental:no /opt:ref /subsystem:%.*s " "%.*s " "%.*s " "%s " "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - subsystem_str, + LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -337,20 +349,34 @@ gb_internal i32 linker_stage(LinkerData *gen) { obj_format = str_lit("elf32"); } #endif // GB_ARCH_*_BIT - // Note(bumbread): I'm assuming nasm is installed on the host machine. - // Shipping binaries on unix-likes gets into the weird territorry of - // "which version of glibc" is it linked with. - result = system_exec_command_line_app("nasm", - "nasm \"%.*s\" " - "-f \"%.*s\" " - "-o \"%.*s\" " - "%.*s " - "", - LIT(asm_file), - LIT(obj_format), - LIT(obj_file), - LIT(build_context.extra_assembler_flags) - ); + + if (is_osx) { + // `as` comes with MacOS. + result = system_exec_command_line_app("as", + "as \"%.*s\" " + "-o \"%.*s\" " + "%.*s " + "", + LIT(asm_file), + LIT(obj_file), + LIT(build_context.extra_assembler_flags) + ); + } else { + // Note(bumbread): I'm assuming nasm is installed on the host machine. + // Shipping binaries on unix-likes gets into the weird territorry of + // "which version of glibc" is it linked with. + result = system_exec_command_line_app("nasm", + "nasm \"%.*s\" " + "-f \"%.*s\" " + "-o \"%.*s\" " + "%.*s " + "", + LIT(asm_file), + LIT(obj_format), + LIT(obj_file), + LIT(build_context.extra_assembler_flags) + ); + } array_add(&gen->output_object_paths, obj_file); } else { if (string_set_update(&libs, lib)) { @@ -456,7 +482,26 @@ gb_internal i32 linker_stage(LinkerData *gen) { gbString platform_lib_str = gb_string_make(heap_allocator(), ""); defer (gb_string_free(platform_lib_str)); if (build_context.metrics.os == TargetOs_darwin) { - platform_lib_str = gb_string_appendc(platform_lib_str, "-lSystem -lm -Wl,-syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -L/usr/local/lib"); + platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -L/usr/local/lib"); + + // Homebrew's default library path, checking if it exists to avoid linking warnings. + if (gb_file_exists("/opt/homebrew/lib")) { + platform_lib_str = gb_string_appendc(platform_lib_str, " -L/opt/homebrew/lib"); + } + + // MacPort's default library path, checking if it exists to avoid linking warnings. + if (gb_file_exists("/opt/local/lib")) { + platform_lib_str = gb_string_appendc(platform_lib_str, " -L/opt/local/lib"); + } + + #if defined(GB_SYSTEM_OSX) + if(!build_context.no_crt) { + platform_lib_str = gb_string_appendc(platform_lib_str, " -lm "); + if(gen->needs_system_library_linked == 1) { + platform_lib_str = gb_string_appendc(platform_lib_str, " -lSystem "); + } + } + #endif } else { platform_lib_str = gb_string_appendc(platform_lib_str, "-lc -lm"); } @@ -465,10 +510,6 @@ gb_internal i32 linker_stage(LinkerData *gen) { // This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit. if (build_context.minimum_os_version_string.len) { link_settings = gb_string_append_fmt(link_settings, " -mmacosx-version-min=%.*s ", LIT(build_context.minimum_os_version_string)); - } else if (build_context.metrics.arch == TargetArch_arm64) { - link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=12.0.0 "); - } else { - link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=10.12.0 "); } // This points the linker to where the entry point is link_settings = gb_string_appendc(link_settings, " -e _main "); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 276abc2d4..003424e0a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -21,6 +21,25 @@ #include "llvm_backend_stmt.cpp" #include "llvm_backend_proc.cpp" +String get_default_microarchitecture() { + String default_march = str_lit("generic"); + if (build_context.metrics.arch == TargetArch_amd64) { + // NOTE(bill): x86-64-v2 is more than enough for everyone + // + // x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2 + // x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3 + // x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE + // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL + if (ODIN_LLVM_MINIMUM_VERSION_12) { + if (build_context.metrics.os == TargetOs_freestanding) { + default_march = str_lit("x86-64"); + } else { + default_march = str_lit("x86-64-v2"); + } + } + } + return default_march; +} gb_internal void lb_add_foreign_library_path(lbModule *m, Entity *e) { if (e == nullptr) { @@ -1478,8 +1497,6 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { auto passes = array_make(heap_allocator(), 0, 64); defer (array_free(&passes)); - - LLVMPassBuilderOptionsRef pb_options = LLVMCreatePassBuilderOptions(); defer (LLVMDisposePassBuilderOptions(pb_options)); @@ -2486,40 +2503,72 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMCodeModel code_mode = LLVMCodeModelDefault; if (is_arch_wasm()) { code_mode = LLVMCodeModelJITDefault; - } else if (build_context.metrics.os == TargetOs_freestanding) { + } else if (is_arch_x86() && build_context.metrics.os == TargetOs_freestanding) { code_mode = LLVMCodeModelKernel; } - char const *host_cpu_name = LLVMGetHostCPUName(); - char const *llvm_cpu = "generic"; + String host_cpu_name = copy_string(permanent_allocator(), make_string_c(LLVMGetHostCPUName())); + String llvm_cpu = get_default_microarchitecture(); char const *llvm_features = ""; if (build_context.microarch.len != 0) { if (build_context.microarch == "native") { llvm_cpu = host_cpu_name; } else { - llvm_cpu = alloc_cstring(permanent_allocator(), build_context.microarch); + llvm_cpu = copy_string(permanent_allocator(), build_context.microarch); } - if (gb_strcmp(llvm_cpu, host_cpu_name) == 0) { + if (llvm_cpu == host_cpu_name) { llvm_features = LLVMGetHostCPUFeatures(); } - } else if (build_context.metrics.arch == TargetArch_amd64) { - // NOTE(bill): x86-64-v2 is more than enough for everyone - // - // x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2 - // x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3 - // x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE - // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL - if (ODIN_LLVM_MINIMUM_VERSION_12) { - if (build_context.metrics.os == TargetOs_freestanding) { - llvm_cpu = "x86-64"; - } else { - llvm_cpu = "x86-64-v2"; - } - } } + // NOTE(Jeroen): Uncomment to get the list of supported microarchitectures. + /* + if (build_context.microarch == "?") { + string_set_add(&build_context.target_features_set, str_lit("+cpuhelp")); + } + */ + if (build_context.target_features_set.entries.count != 0) { - llvm_features = target_features_set_to_cstring(permanent_allocator(), false); + // Prefix all of the features with a `+`, because we are + // enabling additional features. + char const *additional_features = target_features_set_to_cstring(permanent_allocator(), false, true); + + String f_string = make_string_c(llvm_features); + String a_string = make_string_c(additional_features); + isize f_len = f_string.len; + + if (f_len == 0) { + // The common case is that llvm_features is empty, so + // the target_features_set additions can be used as is. + llvm_features = additional_features; + } else { + // The user probably specified `-microarch:native`, so + // llvm_features is populated by LLVM's idea of what + // the host CPU supports. + // + // As far as I can tell, (which is barely better than + // wild guessing), a bitset is formed by parsing the + // string left to right. + // + // So, llvm_features + ',' + additonal_features, will + // makes the target_features_set override llvm_features. + + char *tmp = gb_alloc_array(permanent_allocator(), char, f_len + 1 + a_string.len + 1); + isize len = 0; + + // tmp = f_string + gb_memmove(tmp, f_string.text, f_string.len); + len += f_string.len; + // tmp += ',' + tmp[len++] = ','; + // tmp += a_string + gb_memmove(tmp + len, a_string.text, a_string.len); + len += a_string.len; + // tmp += NUL + tmp[len++] = 0; + + llvm_features = tmp; + } } // GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target)); @@ -2566,7 +2615,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { for (auto const &entry : gen->modules) { LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine( - target, target_triple, llvm_cpu, + target, target_triple, (const char *)llvm_cpu.text, llvm_features, code_gen_level, reloc_mode, @@ -2685,64 +2734,22 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - { - char const *name = LB_TYPE_INFO_TYPES_NAME; - Type *t = alloc_type_array(t_type_info_ptr, count); + auto const global_type_info_make = [](lbModule *m, char const *name, Type *elem_type, i64 count) -> lbAddr { + Type *t = alloc_type_array(elem_type, count); LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); if (LB_USE_GIANT_PACKED_STRUCT) { lb_make_global_private_const(g); } - lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)}); + return lb_addr({g, alloc_type_pointer(t)}); + }; - } - { - char const *name = LB_TYPE_INFO_NAMES_NAME; - Type *t = alloc_type_array(t_string, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)}); - } - { - char const *name = LB_TYPE_INFO_OFFSETS_NAME; - Type *t = alloc_type_array(t_uintptr, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)}); - } - - { - char const *name = LB_TYPE_INFO_USINGS_NAME; - Type *t = alloc_type_array(t_bool, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)}); - } - - { - char const *name = LB_TYPE_INFO_TAGS_NAME; - Type *t = alloc_type_array(t_string, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)}); - } + lb_global_type_info_member_types = global_type_info_make(m, LB_TYPE_INFO_TYPES_NAME, t_type_info_ptr, count); + lb_global_type_info_member_names = global_type_info_make(m, LB_TYPE_INFO_NAMES_NAME, t_string, count); + lb_global_type_info_member_offsets = global_type_info_make(m, LB_TYPE_INFO_OFFSETS_NAME, t_uintptr, count); + lb_global_type_info_member_usings = global_type_info_make(m, LB_TYPE_INFO_USINGS_NAME, t_bool, count); + lb_global_type_info_member_tags = global_type_info_make(m, LB_TYPE_INFO_TAGS_NAME, t_string, count); } } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 5894dd38a..fe2c2deba 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -339,6 +339,8 @@ struct lbProcedure { bool in_multi_assignment; Array raw_input_parameters; + LLVMValueRef temp_callee_return_struct_memory; + Ast *curr_stmt; Array scope_stack; @@ -550,6 +552,7 @@ gb_internal LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLV gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false); gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false); gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile); +gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile); gb_internal gb_inline i64 lb_max_zero_init_size(void) { return cast(i64)(4*build_context.int_size); @@ -560,7 +563,9 @@ gb_internal LLVMTypeRef OdinLLVMGetVectorElementType(LLVMTypeRef type); gb_internal String lb_filepath_ll_for_module(lbModule *m); +gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type); +gb_internal lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, String const &procedure, TokenPos const &pos); gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t ElementCount) { #if LB_USE_NEW_PASS_SYSTEM diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 7584df3ee..2291f24ac 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -287,11 +287,44 @@ gb_internal lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type return lb_const_value(m, t, tv.value); } -gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos) { +gb_internal String lb_obfuscate_string(String const &s, char const *prefix) { + if (s.len == 0) { + return {}; + } + GB_ASSERT(prefix != nullptr); + u64 hash = gb_fnv64a(s.text, s.len); + gbString res = gb_string_make(temporary_allocator(), prefix); + res = gb_string_append_fmt(res, "x%llx", cast(long long unsigned)hash); + return make_string_c(res); +} + +gb_internal i32 lb_obfuscate_i32(i32 i) { + i32 x = cast(i32)gb_fnv64a(&i, sizeof(i)); + if (x < 0) { + x = 1-x; + } + return cast(i32)x; +} + +gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure_, TokenPos const &pos) { + String file = get_file_path_string(pos.file_id); + String procedure = procedure_; + + i32 line = pos.line; + i32 column = pos.column; + + if (build_context.obfuscate_source_code_locations) { + file = lb_obfuscate_string(file, "F"); + procedure = lb_obfuscate_string(procedure, "P"); + + line = lb_obfuscate_i32(line); + column = lb_obfuscate_i32(column); + } + LLVMValueRef fields[4] = {}; - fields[0]/*file*/ = lb_find_or_add_entity_string(m, get_file_path_string(pos.file_id)).value; - fields[1]/*line*/ = lb_const_int(m, t_i32, pos.line).value; - fields[2]/*column*/ = lb_const_int(m, t_i32, pos.column).value; + fields[0]/*file*/ = lb_find_or_add_entity_string(m, file).value; + fields[1]/*line*/ = lb_const_int(m, t_i32, line).value; + fields[2]/*column*/ = lb_const_int(m, t_i32, column).value; fields[3]/*procedure*/ = lb_find_or_add_entity_string(m, procedure).value; lbValue res = {}; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 8678a125c..4675e203b 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2939,6 +2939,12 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { } else if (is_type_soa_pointer(tv.type)) { ast_node(ie, IndexExpr, ue_expr); lbValue addr = lb_build_addr_ptr(p, ie->expr); + + if (is_type_pointer(type_deref(addr.type))) { + addr = lb_emit_load(p, addr); + } + GB_ASSERT(is_type_pointer(addr.type)); + lbValue index = lb_build_expr(p, ie->index); if (!build_context.no_bounds_check) { @@ -4099,7 +4105,7 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { } case Type_Basic: { - GB_ASSERT_MSG(type == t_string, "got %s", type_to_string(type)); + GB_ASSERT_MSG(are_types_identical(type, t_string), "got %s", type_to_string(type)); lbValue len = lb_string_len(p, base); if (high.value == nullptr) high = len; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index fdcf94f29..f0f5327c6 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -107,6 +107,10 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { String init_fullpath = c->parser->init_fullpath; linker_data_init(gen, &c->info, init_fullpath); + #if defined(GB_SYSTEM_OSX) && (LLVM_VERSION_MAJOR < 14) + linker_enable_system_library_linking(gen); + #endif + gen->info = &c->info; map_init(&gen->modules, gen->info->packages.count*2); @@ -1332,6 +1336,8 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV Type *pt = base_type(type_deref(parent.type)); GB_ASSERT(pt->kind == Type_Union); if (pt->Union.kind == UnionType_shared_nil) { + GB_ASSERT(type_size_of(variant_type)); + lbBlock *if_nil = lb_create_block(p, "shared_nil.if_nil"); lbBlock *if_not_nil = lb_create_block(p, "shared_nil.if_not_nil"); lbBlock *done = lb_create_block(p, "shared_nil.done"); @@ -1353,9 +1359,13 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV } else { - lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type)); - - lb_emit_store(p, underlying, variant); + if (type_size_of(variant_type) == 0) { + unsigned alignment = 1; + lb_mem_zero_ptr_internal(p, parent.value, pt->Union.variant_block_size, alignment, false); + } else { + lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type)); + lb_emit_store(p, underlying, variant); + } lb_emit_store_union_variant_tag(p, parent, variant_type); } } @@ -2338,6 +2348,15 @@ gb_internal LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char c return LLVMCreateEnumAttribute(ctx, kind, value); } +gb_internal LLVMAttributeRef lb_create_string_attribute(LLVMContextRef ctx, String const &key, String const &value) { + LLVMAttributeRef attr = LLVMCreateStringAttribute( + ctx, + cast(char const *)key.text, cast(unsigned)key.len, + cast(char const *)value.text, cast(unsigned)value.len); + return attr; +} + + gb_internal void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name, u64 value) { LLVMAttributeRef attr = lb_create_enum_attribute(p->module->ctx, name, value); GB_ASSERT(attr != nullptr); @@ -2351,6 +2370,10 @@ gb_internal void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, cha gb_internal void lb_add_attribute_to_proc(lbModule *m, LLVMValueRef proc_value, char const *name, u64 value=0) { LLVMAddAttributeAtIndex(proc_value, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(m->ctx, name, value)); } +gb_internal void lb_add_attribute_to_proc_with_string(lbModule *m, LLVMValueRef proc_value, String const &name, String const &value) { + LLVMAttributeRef attr = lb_create_string_attribute(m->ctx, name, value); + LLVMAddAttributeAtIndex(proc_value, LLVMAttributeIndex_FunctionIndex, attr); +} diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 2e03b7974..b57e74799 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -380,6 +380,86 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { } } +gb_internal LLVMValueRef lb_run_instrumentation_pass_insert_call(lbProcedure *p, Entity *entity, LLVMBuilderRef dummy_builder) { + lbModule *m = p->module; + + lbValue cc = lb_find_procedure_value_from_entity(m, entity); + + LLVMValueRef args[3] = {}; + args[0] = p->value; + + LLVMValueRef returnaddress_args[1] = {}; + + returnaddress_args[0] = LLVMConstInt(LLVMInt32TypeInContext(m->ctx), 0, false); + + char const *instrinsic_name = "llvm.returnaddress"; + unsigned id = LLVMLookupIntrinsicID(instrinsic_name, gb_strlen(instrinsic_name)); + GB_ASSERT_MSG(id != 0, "Unable to find %s", instrinsic_name); + LLVMValueRef ip = LLVMGetIntrinsicDeclaration(m->mod, id, nullptr, 0); + LLVMTypeRef call_type = LLVMIntrinsicGetType(m->ctx, id, nullptr, 0); + args[1] = LLVMBuildCall2(dummy_builder, call_type, ip, returnaddress_args, gb_count_of(returnaddress_args), ""); + + Token name = {}; + if (p->entity) { + name = p->entity->token; + } + args[2] = lb_emit_source_code_location_as_global_ptr(p, name.string, name.pos).value; + + LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, entity->type); + return LLVMBuildCall2(dummy_builder, fnp, cc.value, args, gb_count_of(args), ""); +} + + +gb_internal void lb_run_instrumentation_pass(lbProcedure *p) { + lbModule *m = p->module; + Entity *enter = m->info->instrumentation_enter_entity; + Entity *exit = m->info->instrumentation_exit_entity; + if (enter == nullptr || exit == nullptr) { + return; + } + if (!(p->entity && + p->entity->kind == Entity_Procedure && + p->entity->Procedure.has_instrumentation)) { + return; + } + +#define LLVM_V_NAME(x) x, cast(unsigned)(gb_count_of(x)-1) + + LLVMBuilderRef dummy_builder = LLVMCreateBuilderInContext(m->ctx); + defer (LLVMDisposeBuilder(dummy_builder)); + + LLVMBasicBlockRef entry_bb = p->entry_block->block; + LLVMPositionBuilder(dummy_builder, entry_bb, LLVMGetFirstInstruction(entry_bb)); + lb_run_instrumentation_pass_insert_call(p, enter, dummy_builder); + LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-entry")); + + unsigned bb_count = LLVMCountBasicBlocks(p->value); + LLVMBasicBlockRef *bbs = gb_alloc_array(temporary_allocator(), LLVMBasicBlockRef, bb_count); + LLVMGetBasicBlocks(p->value, bbs); + for (unsigned i = 0; i < bb_count; i++) { + LLVMBasicBlockRef bb = bbs[i]; + LLVMValueRef terminator = LLVMGetBasicBlockTerminator(bb); + if (terminator == nullptr || + !LLVMIsAReturnInst(terminator)) { + continue; + } + + // TODO(bill): getTerminatingMustTailCall() + // If T is preceded by a musttail call, that's the real terminator. + // if (CallInst *CI = BB.getTerminatingMustTailCall()) + // T = CI; + + + LLVMPositionBuilderBefore(dummy_builder, terminator); + lb_run_instrumentation_pass_insert_call(p, exit, dummy_builder); + } + + LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-exit")); + +#undef LLVM_V_NAME +} + + gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p, lbFunctionPassManagerKind pass_manager_kind) { if (p == nullptr) { @@ -401,6 +481,7 @@ gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedur } break; } + lb_run_instrumentation_pass(p); LLVMRunFunctionPassManager(fpm, p->value); } @@ -552,3 +633,5 @@ gb_internal void lb_run_remove_unused_globals_pass(lbModule *m) { } } } + + diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index f64cbd52a..09bebd0cf 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -329,6 +329,18 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i } } + if (p->body && entity->Procedure.has_instrumentation) { + Entity *instrumentation_enter = m->info->instrumentation_enter_entity; + Entity *instrumentation_exit = m->info->instrumentation_exit_entity; + if (instrumentation_enter && instrumentation_exit) { + String enter = lb_get_entity_name(m, instrumentation_enter); + String exit = lb_get_entity_name(m, instrumentation_exit); + + lb_add_attribute_to_proc_with_string(m, p->value, make_string_c("instrument-function-entry"), enter); + lb_add_attribute_to_proc_with_string(m, p->value, make_string_c("instrument-function-exit"), exit); + } + } + lbValue proc_value = {p->value, p->type}; lb_add_entity(m, entity, proc_value); lb_add_member(m, p->name, proc_value); @@ -1826,24 +1838,41 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } case BuiltinProc_quaternion: { - lbValue real = lb_build_expr(p, ce->args[0]); - lbValue imag = lb_build_expr(p, ce->args[1]); - lbValue jmag = lb_build_expr(p, ce->args[2]); - lbValue kmag = lb_build_expr(p, ce->args[3]); + lbValue xyzw[4] = {}; + for (i32 i = 0; i < 4; i++) { + ast_node(f, FieldValue, ce->args[i]); + GB_ASSERT(f->field->kind == Ast_Ident); + String name = f->field->Ident.token.string; + i32 index = -1; + + // @QuaternionLayout + if (name == "x" || name == "imag") { + index = 0; + } else if (name == "y" || name == "jmag") { + index = 1; + } else if (name == "z" || name == "kmag") { + index = 2; + } else if (name == "w" || name == "real") { + index = 3; + } + GB_ASSERT(index >= 0); + + xyzw[index] = lb_build_expr(p, f->value); + } + - // @QuaternionLayout lbAddr dst_addr = lb_add_local_generated(p, tv.type, false); lbValue dst = lb_addr_get_ptr(p, dst_addr); Type *ft = base_complex_elem_type(tv.type); - real = lb_emit_conv(p, real, ft); - imag = lb_emit_conv(p, imag, ft); - jmag = lb_emit_conv(p, jmag, ft); - kmag = lb_emit_conv(p, kmag, ft); - lb_emit_store(p, lb_emit_struct_ep(p, dst, 3), real); - lb_emit_store(p, lb_emit_struct_ep(p, dst, 0), imag); - lb_emit_store(p, lb_emit_struct_ep(p, dst, 1), jmag); - lb_emit_store(p, lb_emit_struct_ep(p, dst, 2), kmag); + xyzw[0] = lb_emit_conv(p, xyzw[0], ft); + xyzw[1] = lb_emit_conv(p, xyzw[1], ft); + xyzw[2] = lb_emit_conv(p, xyzw[2], ft); + xyzw[3] = lb_emit_conv(p, xyzw[3], ft); + lb_emit_store(p, lb_emit_struct_ep(p, dst, 0), xyzw[0]); + lb_emit_store(p, lb_emit_struct_ep(p, dst, 1), xyzw[1]); + lb_emit_store(p, lb_emit_struct_ep(p, dst, 2), xyzw[2]); + lb_emit_store(p, lb_emit_struct_ep(p, dst, 3), xyzw[3]); return lb_emit_load(p, dst); } @@ -3385,7 +3414,7 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { } lbValue arg = args[arg_index]; - if (arg.value == nullptr) { + if (arg.value == nullptr && arg.type == nullptr) { switch (e->kind) { case Entity_TypeName: args[arg_index] = lb_const_nil(p->module, e->type); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 9d688be6a..002fef881 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1846,9 +1846,25 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) { LLVMBuildRetVoid(p->builder); } else { LLVMValueRef ret_val = res.value; - ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type); - if (p->abi_function_type->ret.cast_type != nullptr) { - ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type); + LLVMTypeRef ret_type = p->abi_function_type->ret.type; + if (LLVMTypeRef cast_type = p->abi_function_type->ret.cast_type) { + ret_type = cast_type; + } + + if (LLVMGetTypeKind(ret_type) == LLVMStructTypeKind) { + LLVMTypeRef src_type = LLVMTypeOf(ret_val); + + if (p->temp_callee_return_struct_memory == nullptr) { + i64 max_align = gb_max(lb_alignof(ret_type), lb_alignof(src_type)); + p->temp_callee_return_struct_memory = llvm_alloca(p, ret_type, max_align); + } + // reuse the temp return value memory where possible + LLVMValueRef ptr = p->temp_callee_return_struct_memory; + LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), ""); + LLVMBuildStore(p->builder, ret_val, nptr); + ret_val = LLVMBuildLoad2(p->builder, ret_type, ptr, ""); + } else { + ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type); } lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 02dad2a3a..e291e40a5 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -9,7 +9,12 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_ } } if (err_on_not_found) { - GB_PANIC("NOT FOUND lb_type_info_index %s @ index %td", type_to_string(type), index); + gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(type), index, set->count); + for (auto const &entry : *set) { + isize type_info_index = entry.key; + gb_printf_err("\t%s\n", type_to_string(info->type_info_types[type_info_index])); + } + GB_PANIC("NOT FOUND"); } return -1; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index d8dbfd736..be3ae9c8a 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -57,6 +57,10 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) { return value; } +gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) { + return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile); +} + gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) { bool is_inlinable = false; diff --git a/src/main.cpp b/src/main.cpp index 79c2b3561..19271d667 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -199,19 +199,19 @@ gb_internal void print_usage_line(i32 indent, char const *fmt, ...) { } gb_internal void usage(String argv0) { - print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(argv0)); + print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(argv0)); print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s command [arguments]", LIT(argv0)); print_usage_line(0, "Commands:"); - print_usage_line(1, "build compile directory of .odin files, as an executable."); - print_usage_line(1, " one must contain the program's entry point, all must be in the same package."); - print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable."); - print_usage_line(1, "check parse, and type check a directory of .odin files"); - print_usage_line(1, "strip-semicolon parse, type check, and remove unneeded semicolons from the entire program"); - print_usage_line(1, "test build and runs procedures with the attribute @(test) in the initial package"); - print_usage_line(1, "doc generate documentation on a directory of .odin files"); - print_usage_line(1, "version print version"); - print_usage_line(1, "report print information useful to reporting a bug"); + print_usage_line(1, "build Compiles directory of .odin files, as an executable."); + print_usage_line(1, " One must contain the program's entry point, all must be in the same package."); + print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); + print_usage_line(1, "check Parses, and type checks a directory of .odin files."); + print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program."); + print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); + print_usage_line(1, "doc Generates documentation on a directory of .odin files."); + print_usage_line(1, "version Prints version."); + print_usage_line(1, "report Prints information useful to reporting a bug."); print_usage_line(0, ""); print_usage_line(0, "For further details on a command, invoke command help:"); print_usage_line(1, "e.g. `odin build -help` or `odin help build`"); @@ -277,6 +277,7 @@ enum BuildFlagKind { BuildFlag_ForeignErrorProcedures, BuildFlag_NoRTTI, BuildFlag_DynamicMapCalls, + BuildFlag_ObfuscateSourceCodeLocations, BuildFlag_Compact, BuildFlag_GlobalDefinitions, @@ -467,6 +468,8 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_DynamicMapCalls, str_lit("dynamic-map-calls"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_ObfuscateSourceCodeLocations, str_lit("obfuscate-source-code-locations"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_DocFormat, str_lit("doc-format"), BuildFlagParam_None, Command_doc); @@ -1113,6 +1116,11 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_DynamicMapCalls: build_context.dynamic_map_calls = true; break; + + case BuildFlag_ObfuscateSourceCodeLocations: + build_context.obfuscate_source_code_locations = true; + break; + case BuildFlag_DefaultToNilAllocator: build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; break; @@ -1152,10 +1160,12 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_TerseErrors: build_context.hide_error_line = true; + build_context.terse_errors = true; break; case BuildFlag_VerboseErrors: gb_printf_err("-verbose-errors is not the default, -terse-errors can now disable it\n"); build_context.hide_error_line = false; + build_context.terse_errors = false; break; case BuildFlag_ErrorPosStyle: @@ -1260,16 +1270,43 @@ gb_internal bool parse_build_flags(Array args) { } case BuildFlag_Subsystem: { + // TODO(Jeroen): Parse optional "[,major[.minor]]" + GB_ASSERT(value.kind == ExactValue_String); String subsystem = value.value_string; - if (str_eq_ignore_case(subsystem, str_lit("console"))) { - build_context.use_subsystem_windows = false; - } else if (str_eq_ignore_case(subsystem, str_lit("window"))) { - build_context.use_subsystem_windows = true; - } else if (str_eq_ignore_case(subsystem, str_lit("windows"))) { - build_context.use_subsystem_windows = true; - } else { - gb_printf_err("Invalid -subsystem string, got %.*s, expected either 'console' or 'windows'\n", LIT(subsystem)); + bool subsystem_found = false; + for (int i = 0; i < Windows_Subsystem_COUNT; i++) { + if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) { + build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i]; + subsystem_found = true; + break; + } + } + + // WINDOW is a hidden alias for WINDOWS. Check it. + String subsystem_windows_alias = str_lit("WINDOW"); + if (!subsystem_found && str_eq_ignore_case(subsystem, subsystem_windows_alias)) { + build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_WINDOWS]; + subsystem_found = true; + break; + } + + if (!subsystem_found) { + gb_printf_err("Invalid -subsystem string, got %.*s. Expected one of:\n", LIT(subsystem)); + gb_printf_err("\t"); + for (int i = 0; i < Windows_Subsystem_COUNT; i++) { + if (i > 0) { + gb_printf_err(", "); + } + gb_printf_err("%.*s", LIT(windows_subsystem_names[i])); + if (i == Windows_Subsystem_CONSOLE) { + gb_printf_err(" (default)"); + } + if (i == Windows_Subsystem_WINDOWS) { + gb_printf_err(" (or WINDOW)"); + } + } + gb_printf_err("\n"); bad_flags = true; } break; @@ -1580,45 +1617,45 @@ gb_internal void remove_temp_files(lbGenerator *gen) { gb_internal void print_show_help(String const arg0, String const &command) { - print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(arg0)); + print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0)); print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command)); print_usage_line(0, ""); if (command == "build") { - print_usage_line(1, "build Compile directory of .odin files as an executable."); + print_usage_line(1, "build Compiles directory of .odin files as an executable."); print_usage_line(2, "One must contain the program's entry point, all must be in the same package."); print_usage_line(2, "Use `-file` to build a single file instead."); print_usage_line(2, "Examples:"); - print_usage_line(3, "odin build . # Build package in current directory"); - print_usage_line(3, "odin build # Build package in "); - print_usage_line(3, "odin build filename.odin -file # Build single-file package, must contain entry point."); + print_usage_line(3, "odin build . Builds package in current directory."); + print_usage_line(3, "odin build Builds package in ."); + print_usage_line(3, "odin build filename.odin -file Builds single-file package, must contain entry point."); } else if (command == "run") { print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); print_usage_line(2, "Append an empty flag and then the args, '-- ', to specify args for the output."); print_usage_line(2, "Examples:"); - print_usage_line(3, "odin run . # Build and run package in current directory"); - print_usage_line(3, "odin run # Build and run package in "); - print_usage_line(3, "odin run filename.odin -file # Build and run single-file package, must contain entry point."); + print_usage_line(3, "odin run . Builds and runs package in current directory."); + print_usage_line(3, "odin run Builds and runs package in ."); + print_usage_line(3, "odin run filename.odin -file Builds and runs single-file package, must contain entry point."); } else if (command == "check") { - print_usage_line(1, "check Parse and type check directory of .odin files"); + print_usage_line(1, "check Parses and type checks directory of .odin files."); print_usage_line(2, "Examples:"); - print_usage_line(3, "odin check . # Type check package in current directory"); - print_usage_line(3, "odin check # Type check package in "); - print_usage_line(3, "odin check filename.odin -file # Type check single-file package, must contain entry point."); + print_usage_line(3, "odin check . Type checks package in current directory."); + print_usage_line(3, "odin check Type checks package in ."); + print_usage_line(3, "odin check filename.odin -file Type checks single-file package, must contain entry point."); } else if (command == "test") { - print_usage_line(1, "test Build and runs procedures with the attribute @(test) in the initial package"); + print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); } else if (command == "doc") { - print_usage_line(1, "doc generate documentation from a directory of .odin files"); + print_usage_line(1, "doc Generates documentation from a directory of .odin files."); print_usage_line(2, "Examples:"); - print_usage_line(3, "odin doc . # Generate documentation on package in current directory"); - print_usage_line(3, "odin doc # Generate documentation on package in "); - print_usage_line(3, "odin doc filename.odin -file # Generate documentation on single-file package."); + print_usage_line(3, "odin doc . Generates documentation on package in current directory."); + print_usage_line(3, "odin doc Generates documentation on package in ."); + print_usage_line(3, "odin doc filename.odin -file Generates documentation on single-file package."); } else if (command == "version") { - print_usage_line(1, "version print version"); + print_usage_line(1, "version Prints version."); } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); - print_usage_line(2, "Parse and type check .odin file(s) and then remove unneeded semicolons from the entire project"); + print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); } bool doc = command == "doc"; @@ -1642,311 +1679,322 @@ gb_internal void print_show_help(String const arg0, String const &command) { if (doc) { print_usage_line(1, "-short"); - print_usage_line(2, "Show shortened documentation for the packages"); + print_usage_line(2, "Shows shortened documentation for the packages."); print_usage_line(0, ""); print_usage_line(1, "-all-packages"); - print_usage_line(2, "Generates documentation for all packages used in the current project"); + print_usage_line(2, "Generates documentation for all packages used in the current project."); print_usage_line(0, ""); print_usage_line(1, "-doc-format"); - print_usage_line(2, "Generates documentation as the .odin-doc format (useful for external tooling)"); + print_usage_line(2, "Generates documentation as the .odin-doc format (useful for external tooling)."); print_usage_line(0, ""); } if (run_or_build) { print_usage_line(1, "-out:"); - print_usage_line(2, "Set the file name of the outputted executable"); + print_usage_line(2, "Sets the file name of the outputted executable."); print_usage_line(2, "Example: -out:foo.exe"); print_usage_line(0, ""); print_usage_line(1, "-o:"); - print_usage_line(2, "Set the optimization mode for compilation"); + print_usage_line(2, "Sets the optimization mode for compilation."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-o:none"); + print_usage_line(3, "-o:minimal"); + print_usage_line(3, "-o:size"); + print_usage_line(3, "-o:speed"); if (LB_USE_NEW_PASS_SYSTEM) { - print_usage_line(2, "Accepted values: none, minimal, size, speed, aggressive"); - } else { - print_usage_line(2, "Accepted values: none, minimal, size, speed"); + print_usage_line(3, "-o:aggressive"); } - print_usage_line(2, "Example: -o:speed"); - print_usage_line(2, "The default is -o:minimal"); + print_usage_line(2, "The default is -o:minimal."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-show-timings"); - print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds"); + print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds."); print_usage_line(0, ""); print_usage_line(1, "-show-more-timings"); - print_usage_line(2, "Shows an advanced overview of the timings of different stages within the compiler in milliseconds"); + print_usage_line(2, "Shows an advanced overview of the timings of different stages within the compiler in milliseconds."); print_usage_line(0, ""); print_usage_line(1, "-show-system-calls"); - print_usage_line(2, "Prints the whole command and arguments for calls to external tools like linker and assembler"); + print_usage_line(2, "Prints the whole command and arguments for calls to external tools like linker and assembler."); print_usage_line(0, ""); print_usage_line(1, "-export-timings:"); - print_usage_line(2, "Export timings to one of a few formats. Requires `-show-timings` or `-show-more-timings`"); + print_usage_line(2, "Exports timings to one of a few formats. Requires `-show-timings` or `-show-more-timings`."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-export-timings:json Export compile time stats to JSON"); - print_usage_line(3, "-export-timings:csv Export compile time stats to CSV"); + print_usage_line(3, "-export-timings:json Exports compile time stats to JSON."); + print_usage_line(3, "-export-timings:csv Exports compile time stats to CSV."); print_usage_line(0, ""); print_usage_line(1, "-export-timings-file:"); - print_usage_line(2, "Specify the filename for `-export-timings`"); + print_usage_line(2, "Specifies the filename for `-export-timings`."); print_usage_line(2, "Example: -export-timings-file:timings.json"); print_usage_line(0, ""); print_usage_line(1, "-thread-count:"); - print_usage_line(2, "Override the number of threads the compiler will use to compile with"); + print_usage_line(2, "Overrides the number of threads the compiler will use to compile with."); print_usage_line(2, "Example: -thread-count:2"); print_usage_line(0, ""); } if (check_only) { print_usage_line(1, "-show-unused"); - print_usage_line(2, "Shows unused package declarations within the current project"); + print_usage_line(2, "Shows unused package declarations within the current project."); print_usage_line(0, ""); print_usage_line(1, "-show-unused-with-location"); - print_usage_line(2, "Shows unused package declarations within the current project with the declarations source location"); + print_usage_line(2, "Shows unused package declarations within the current project with the declarations source location."); print_usage_line(0, ""); } if (run_or_build) { print_usage_line(1, "-keep-temp-files"); - print_usage_line(2, "Keeps the temporary files generated during compilation"); + print_usage_line(2, "Keeps the temporary files generated during compilation."); print_usage_line(0, ""); } else if (strip_semicolon) { print_usage_line(1, "-keep-temp-files"); - print_usage_line(2, "Keeps the temporary files generated during stripping the unneeded semicolons from files"); + print_usage_line(2, "Keeps the temporary files generated during stripping the unneeded semicolons from files."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-collection:="); - print_usage_line(2, "Defines a library collection used for imports"); + print_usage_line(2, "Defines a library collection used for imports."); print_usage_line(2, "Example: -collection:shared=dir/to/shared"); print_usage_line(2, "Usage in Code:"); print_usage_line(3, "import \"shared:foo\""); print_usage_line(0, ""); print_usage_line(1, "-define:="); - print_usage_line(2, "Defines a scalar boolean, integer or string as global constant"); + print_usage_line(2, "Defines a scalar boolean, integer or string as global constant."); print_usage_line(2, "Example: -define:SPAM=123"); - print_usage_line(2, "To use: #config(SPAM, default_value)"); + print_usage_line(2, "Usage in code:"); + print_usage_line(3, "#config(SPAM, default_value)"); print_usage_line(0, ""); } if (build) { print_usage_line(1, "-build-mode:"); - print_usage_line(2, "Sets the build mode"); + print_usage_line(2, "Sets the build mode."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-build-mode:exe Build as an executable"); - print_usage_line(3, "-build-mode:dll Build as a dynamically linked library"); - print_usage_line(3, "-build-mode:shared Build as a dynamically linked library"); - print_usage_line(3, "-build-mode:obj Build as an object file"); - print_usage_line(3, "-build-mode:object Build as an object file"); - print_usage_line(3, "-build-mode:assembly Build as an assembly file"); - print_usage_line(3, "-build-mode:assembler Build as an assembly file"); - print_usage_line(3, "-build-mode:asm Build as an assembly file"); - print_usage_line(3, "-build-mode:llvm-ir Build as an LLVM IR file"); - print_usage_line(3, "-build-mode:llvm Build as an LLVM IR file"); + print_usage_line(3, "-build-mode:exe Builds as an executable."); + print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:obj Builds as an object file."); + print_usage_line(3, "-build-mode:object Builds as an object file."); + print_usage_line(3, "-build-mode:assembly Builds as an assembly file."); + print_usage_line(3, "-build-mode:assembler Builds as an assembly file."); + print_usage_line(3, "-build-mode:asm Builds as an assembly file."); + print_usage_line(3, "-build-mode:llvm-ir Builds as an LLVM IR file."); + print_usage_line(3, "-build-mode:llvm Builds as an LLVM IR file."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-target:"); - print_usage_line(2, "Sets the target for the executable to be built in"); + print_usage_line(2, "Sets the target for the executable to be built in."); print_usage_line(0, ""); } if (run_or_build) { print_usage_line(1, "-debug"); - print_usage_line(2, "Enabled debug information, and defines the global constant ODIN_DEBUG to be 'true'"); + print_usage_line(2, "Enables debug information, and defines the global constant ODIN_DEBUG to be 'true'."); print_usage_line(0, ""); print_usage_line(1, "-disable-assert"); - print_usage_line(2, "Disable the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'"); + print_usage_line(2, "Disables the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'."); print_usage_line(0, ""); print_usage_line(1, "-no-bounds-check"); - print_usage_line(2, "Disables bounds checking program wide"); + print_usage_line(2, "Disables bounds checking program wide."); print_usage_line(0, ""); print_usage_line(1, "-no-crt"); - print_usage_line(2, "Disables automatic linking with the C Run Time"); + print_usage_line(2, "Disables automatic linking with the C Run Time."); print_usage_line(0, ""); print_usage_line(1, "-no-thread-local"); - print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded"); + print_usage_line(2, "Ignores @thread_local attribute, effectively treating the program as if it is single-threaded."); print_usage_line(0, ""); print_usage_line(1, "-lld"); - print_usage_line(2, "Use the LLD linker rather than the default"); + print_usage_line(2, "Uses the LLD linker rather than the default."); print_usage_line(0, ""); print_usage_line(1, "-use-separate-modules"); print_usage_line(1, "[EXPERIMENTAL]"); - print_usage_line(2, "The backend generates multiple build units which are then linked together"); - print_usage_line(2, "Normally, a single build unit is generated for a standard project"); + print_usage_line(2, "The backend generates multiple build units which are then linked together."); + print_usage_line(2, "Normally, a single build unit is generated for a standard project."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-no-threaded-checker"); - print_usage_line(2, "Disabled multithreading in the semantic checker stage"); + print_usage_line(2, "Disables multithreading in the semantic checker stage."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-vet"); - print_usage_line(2, "Do extra checks on the code"); + print_usage_line(2, "Does extra checks on the code."); print_usage_line(2, "Extra checks include:"); - print_usage_line(2, "-vet-unused"); - print_usage_line(2, "-vet-shadowing"); - print_usage_line(2, "-vet-using-stmt"); + print_usage_line(3, "-vet-unused"); + print_usage_line(3, "-vet-shadowing"); + print_usage_line(3, "-vet-using-stmt"); print_usage_line(0, ""); print_usage_line(1, "-vet-unused"); - print_usage_line(2, "Checks for unused declarations"); + print_usage_line(2, "Checks for unused declarations."); print_usage_line(0, ""); print_usage_line(1, "-vet-shadowing"); - print_usage_line(2, "Checks for variable shadowing within procedures"); + print_usage_line(2, "Checks for variable shadowing within procedures."); print_usage_line(0, ""); print_usage_line(1, "-vet-using-stmt"); - print_usage_line(2, "Checks for the use of 'using' as a statement"); - print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring"); + print_usage_line(2, "Checks for the use of 'using' as a statement."); + print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring."); print_usage_line(0, ""); print_usage_line(1, "-vet-using-param"); - print_usage_line(2, "Checks for the use of 'using' on procedure parameters"); - print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring"); + print_usage_line(2, "Checks for the use of 'using' on procedure parameters."); + print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring."); print_usage_line(0, ""); print_usage_line(1, "-vet-style"); - print_usage_line(2, "Errs on missing trailing commas followed by a newline"); - print_usage_line(2, "Errs on deprecated syntax"); - print_usage_line(2, "Does not err on unneeded tokens (unlike -strict-style)"); + print_usage_line(2, "Errs on missing trailing commas followed by a newline."); + print_usage_line(2, "Errs on deprecated syntax."); + print_usage_line(2, "Does not err on unneeded tokens (unlike -strict-style)."); print_usage_line(0, ""); print_usage_line(1, "-vet-semicolon"); - print_usage_line(2, "Errs on unneeded semicolons"); + print_usage_line(2, "Errs on unneeded semicolons."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-ignore-unknown-attributes"); - print_usage_line(2, "Ignores unknown attributes"); - print_usage_line(2, "This can be used with metaprogramming tools"); + print_usage_line(2, "Ignores unknown attributes."); + print_usage_line(2, "This can be used with metaprogramming tools."); print_usage_line(0, ""); if (command != "test") { print_usage_line(1, "-no-entry-point"); - print_usage_line(2, "Removes default requirement of an entry point (e.g. main procedure)"); + print_usage_line(2, "Removes default requirement of an entry point (e.g. main procedure)."); print_usage_line(0, ""); } } if (test_only) { print_usage_line(1, "-test-name:"); - print_usage_line(2, "Run specific test only by name"); + print_usage_line(2, "Runs specific test only by name."); print_usage_line(0, ""); } if (run_or_build) { print_usage_line(1, "-minimum-os-version:"); - print_usage_line(2, "Sets the minimum OS version targeted by the application"); - print_usage_line(2, "e.g. -minimum-os-version:12.0.0"); - print_usage_line(2, "(Only used when target is Darwin)"); + print_usage_line(2, "Sets the minimum OS version targeted by the application."); + print_usage_line(2, "Example: -minimum-os-version:12.0.0"); + print_usage_line(2, "(Only used when target is Darwin.)"); print_usage_line(0, ""); print_usage_line(1, "-extra-linker-flags:"); - print_usage_line(2, "Adds extra linker specific flags in a string"); + print_usage_line(2, "Adds extra linker specific flags in a string."); print_usage_line(0, ""); print_usage_line(1, "-extra-assembler-flags:"); - print_usage_line(2, "Adds extra assembler specific flags in a string"); + print_usage_line(2, "Adds extra assembler specific flags in a string."); print_usage_line(0, ""); print_usage_line(1, "-microarch:"); - print_usage_line(2, "Specifies the specific micro-architecture for the build in a string"); + print_usage_line(2, "Specifies the specific micro-architecture for the build in a string."); print_usage_line(2, "Examples:"); print_usage_line(3, "-microarch:sandybridge"); print_usage_line(3, "-microarch:native"); + print_usage_line(3, "-microarch:? for a list"); print_usage_line(0, ""); print_usage_line(1, "-reloc-mode:"); - print_usage_line(2, "Specifies the reloc mode"); - print_usage_line(2, "Options:"); - print_usage_line(3, "default"); - print_usage_line(3, "static"); - print_usage_line(3, "pic"); - print_usage_line(3, "dynamic-no-pic"); + print_usage_line(2, "Specifies the reloc mode."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-reloc-mode:default"); + print_usage_line(3, "-reloc-mode:static"); + print_usage_line(3, "-reloc-mode:pic"); + print_usage_line(3, "-reloc-mode:dynamic-no-pic"); print_usage_line(0, ""); print_usage_line(1, "-disable-red-zone"); - print_usage_line(2, "Disable red zone on a supported freestanding target"); + print_usage_line(2, "Disables red zone on a supported freestanding target."); print_usage_line(0, ""); print_usage_line(1, "-dynamic-map-calls"); - print_usage_line(2, "Use dynamic map calls to minimize code generation at the cost of runtime execution"); + print_usage_line(2, "Uses dynamic map calls to minimize code generation at the cost of runtime execution."); print_usage_line(0, ""); } if (check) { print_usage_line(1, "-disallow-do"); - print_usage_line(2, "Disallows the 'do' keyword in the project"); + print_usage_line(2, "Disallows the 'do' keyword in the project."); print_usage_line(0, ""); print_usage_line(1, "-default-to-nil-allocator"); - print_usage_line(2, "Sets the default allocator to be the nil_allocator, an allocator which does nothing"); + print_usage_line(2, "Sets the default allocator to be the nil_allocator, an allocator which does nothing."); print_usage_line(0, ""); print_usage_line(1, "-strict-style"); - print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons"); - print_usage_line(2, "Errs on missing trailing commas followed by a newline"); - print_usage_line(2, "Errs on deprecated syntax"); + print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons."); + print_usage_line(2, "Errs on missing trailing commas followed by a newline."); + print_usage_line(2, "Errs on deprecated syntax."); print_usage_line(0, ""); print_usage_line(1, "-ignore-warnings"); - print_usage_line(2, "Ignores warning messages"); + print_usage_line(2, "Ignores warning messages."); print_usage_line(0, ""); print_usage_line(1, "-warnings-as-errors"); - print_usage_line(2, "Treats warning messages as error messages"); + print_usage_line(2, "Treats warning messages as error messages."); print_usage_line(0, ""); print_usage_line(1, "-terse-errors"); - print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line"); + print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line."); print_usage_line(0, ""); print_usage_line(1, "-error-pos-style:"); - print_usage_line(2, "Options are 'unix', 'odin' and 'default' (odin)"); - print_usage_line(2, "'odin' file/path(45:3)"); - print_usage_line(2, "'unix' file/path:45:3:"); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-error-pos-style:unix file/path:45:3:"); + print_usage_line(3, "-error-pos-style:odin file/path(45:3)"); + print_usage_line(3, "-error-pos-style:default (Defaults to 'odin'.)"); print_usage_line(0, ""); - print_usage_line(1, "-max-error-count:"); - print_usage_line(2, "Set the maximum number of errors that can be displayed before the compiler terminates"); - print_usage_line(2, "Must be an integer >0"); - print_usage_line(2, "If not set, the default max error count is %d", DEFAULT_MAX_ERROR_COLLECTOR_COUNT); + print_usage_line(2, "Sets the maximum number of errors that can be displayed before the compiler terminates."); + print_usage_line(2, "Must be an integer >0."); + print_usage_line(2, "If not set, the default max error count is %d.", DEFAULT_MAX_ERROR_COLLECTOR_COUNT); print_usage_line(0, ""); print_usage_line(1, "-foreign-error-procedures"); - print_usage_line(2, "States that the error procedues used in the runtime are defined in a separate translation unit"); + print_usage_line(2, "States that the error procedures used in the runtime are defined in a separate translation unit."); print_usage_line(0, ""); } if (run_or_build) { + print_usage_line(1, "-obfuscate-source-code-locations"); + print_usage_line(2, "Obfuscate the file and procedure strings, and line and column numbers, stored with a 'runtime.Source_Code_Location' value."); + print_usage_line(0, ""); + print_usage_line(1, "-sanitize:"); - print_usage_line(1, "Enables sanitization analysis"); - print_usage_line(1, "Options are 'address', 'memory', and 'thread'"); - print_usage_line(1, "NOTE: This flag can be used multiple times"); + print_usage_line(2, "Enables sanitization analysis."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-sanitize:address"); + print_usage_line(3, "-sanitize:memory"); + print_usage_line(3, "-sanitize:thread"); + print_usage_line(2, "NOTE: This flag can be used multiple times."); print_usage_line(0, ""); } @@ -1955,27 +2003,27 @@ gb_internal void print_show_help(String const arg0, String const &command) { #if defined(GB_SYSTEM_WINDOWS) print_usage_line(1, "-ignore-vs-search"); print_usage_line(2, "[Windows only]"); - print_usage_line(2, "Ignores the Visual Studio search for library paths"); + print_usage_line(2, "Ignores the Visual Studio search for library paths."); print_usage_line(0, ""); print_usage_line(1, "-resource:"); print_usage_line(2, "[Windows only]"); - print_usage_line(2, "Defines the resource file for the executable"); + print_usage_line(2, "Defines the resource file for the executable."); print_usage_line(2, "Example: -resource:path/to/file.rc"); print_usage_line(0, ""); print_usage_line(1, "-pdb-name:"); print_usage_line(2, "[Windows only]"); - print_usage_line(2, "Defines the generated PDB name when -debug is enabled"); + print_usage_line(2, "Defines the generated PDB name when -debug is enabled."); print_usage_line(2, "Example: -pdb-name:different.pdb"); print_usage_line(0, ""); print_usage_line(1, "-subsystem: