Browse Source

Merge remote-tracking branch 'upstream/master' into sys-windows-2

# Conflicts:
#	core/sys/windows/kernel32.odin
#	core/sys/windows/types.odin
#	core/sys/windows/user32.odin
#	core/sys/windows/winerror.odin
Thomas la Cour 1 year ago
parent
commit
dd75b7a4d9
100 changed files with 9166 additions and 5414 deletions
  1. 14 8
      .github/workflows/ci.yml
  2. 6 6
      .github/workflows/nightly.yml
  3. 1 1
      .gitignore
  4. BIN
      LLVM-C.dll
  5. 4 1
      base/intrinsics/intrinsics.odin
  6. 28 0
      base/runtime/core.odin
  7. 56 13
      base/runtime/core_builtin.odin
  8. 64 50
      base/runtime/core_builtin_soa.odin
  9. 2 1
      base/runtime/default_temp_allocator_arena.odin
  10. 5 0
      base/runtime/entry_wasm.odin
  11. 2 1
      base/runtime/entry_windows.odin
  12. 3 3
      base/runtime/heap_allocator.odin
  13. 3 3
      base/runtime/heap_allocator_orca.odin
  14. 6 3
      base/runtime/heap_allocator_other.odin
  15. 3 3
      base/runtime/heap_allocator_unix.odin
  16. 3 3
      base/runtime/heap_allocator_windows.odin
  17. 31 27
      base/runtime/internal.odin
  18. 18 5
      base/runtime/os_specific_darwin.odin
  19. 47 3
      base/runtime/os_specific_wasi.odin
  20. 1 1
      base/runtime/print.odin
  21. 127 0
      base/runtime/random_generator.odin
  22. 3 3
      base/runtime/udivmod128.odin
  23. 3 3
      base/runtime/wasm_allocator.odin
  24. BIN
      bin/llvm/windows/LLVM-C.lib
  25. BIN
      bin/llvm/windows/clang_rt.asan-x86_64.lib
  26. 4 1
      build.bat
  27. 1 1
      build_odin.sh
  28. 1 14
      core/c/libc/signal.odin
  29. 28 28
      core/compress/common.odin
  30. 4 7
      core/compress/shoco/shoco.odin
  31. 11 11
      core/compress/zlib/zlib.odin
  32. 1 1
      core/container/avl/avl.odin
  33. 6 3
      core/container/bit_array/bit_array.odin
  34. 1 2
      core/container/lru/lru_cache.odin
  35. 2 2
      core/container/queue/queue.odin
  36. 2 2
      core/container/rbtree/rbtree.odin
  37. 4 4
      core/container/small_array/small_array.odin
  38. 1 1
      core/container/topological_sort/topological_sort.odin
  39. 2 2
      core/crypto/_edwards25519/edwards25519.odin
  40. 2 2
      core/crypto/_edwards25519/edwards25519_scalar.odin
  41. 2 2
      core/crypto/_fiat/field_curve25519/field.odin
  42. 2 2
      core/crypto/_fiat/field_poly1305/field.odin
  43. 22 0
      core/crypto/crypto.odin
  44. 5 5
      core/crypto/kmac/kmac.odin
  45. 5 5
      core/crypto/legacy/keccak/keccak.odin
  46. 2 2
      core/crypto/rand_darwin.odin
  47. 3 3
      core/crypto/ristretto255/ristretto255.odin
  48. 1 1
      core/crypto/ristretto255/ristretto255_scalar.odin
  49. 5 5
      core/crypto/sha3/sha3.odin
  50. 8 8
      core/crypto/shake/shake.odin
  51. 7 7
      core/crypto/tuplehash/tuplehash.odin
  52. 1 1
      core/debug/trace/trace_cpp.odin
  53. 4 2
      core/debug/trace/trace_nil.odin
  54. 5 13
      core/dynlib/lib.odin
  55. 1 1
      core/dynlib/lib_js.odin
  56. 1 1
      core/dynlib/lib_unix.odin
  57. 7 9
      core/dynlib/lib_windows.odin
  58. 116 116
      core/encoding/base32/base32.odin
  59. 16 16
      core/encoding/cbor/coding.odin
  60. 33 5
      core/encoding/cbor/doc.odin
  61. 57 17
      core/encoding/cbor/marshal.odin
  62. 0 1
      core/encoding/cbor/tags.odin
  63. 13 21
      core/encoding/cbor/unmarshal.odin
  64. 4 2
      core/encoding/csv/reader.odin
  65. 4816 4816
      core/encoding/entity/generated.odin
  66. 21 19
      core/encoding/json/marshal.odin
  67. 28 0
      core/encoding/uuid/LICENSE
  68. 67 0
      core/encoding/uuid/definitions.odin
  69. 46 0
      core/encoding/uuid/doc.odin
  70. 333 0
      core/encoding/uuid/generation.odin
  71. 146 0
      core/encoding/uuid/legacy/legacy.odin
  72. 242 0
      core/encoding/uuid/reading.odin
  73. 89 0
      core/encoding/uuid/stamping.odin
  74. 131 0
      core/encoding/uuid/writing.odin
  75. 5 5
      core/encoding/xml/debug_print.odin
  76. 5 5
      core/encoding/xml/tokenizer.odin
  77. 28 0
      core/flags/LICENSE
  78. 38 0
      core/flags/constants.odin
  79. 181 0
      core/flags/doc.odin
  80. 50 0
      core/flags/errors.odin
  81. 9 0
      core/flags/errors_bsd.odin
  82. 11 0
      core/flags/errors_nonbsd.odin
  83. 132 0
      core/flags/example/example.odin
  84. 262 0
      core/flags/internal_assignment.odin
  85. 170 0
      core/flags/internal_parsing.odin
  86. 529 0
      core/flags/internal_rtti.odin
  87. 31 0
      core/flags/internal_rtti_nonbsd.odin
  88. 244 0
      core/flags/internal_validation.odin
  89. 101 0
      core/flags/parsing.odin
  90. 43 0
      core/flags/rtti.odin
  91. 293 0
      core/flags/usage.odin
  92. 130 0
      core/flags/util.odin
  93. 37 0
      core/flags/validation.odin
  94. 46 24
      core/fmt/fmt.odin
  95. 4 4
      core/hash/crc.odin
  96. 1 1
      core/hash/crc32.odin
  97. 11 11
      core/hash/hash.odin
  98. 5 5
      core/hash/xxhash/common.odin
  99. 56 55
      core/hash/xxhash/xxhash_3.odin
  100. 5 5
      core/hash/xxhash/xxhash_32.odin

+ 14 - 8
.github/workflows/ci.yml

@@ -32,8 +32,8 @@ jobs:
           gmake -C vendor/stb/src
           gmake -C vendor/stb/src
           gmake -C vendor/cgltf/src
           gmake -C vendor/cgltf/src
           gmake -C vendor/miniaudio/src
           gmake -C vendor/miniaudio/src
-          ./odin check examples/all -vet -strict-style -target:netbsd_amd64
-          ./odin check examples/all -vet -strict-style -target:netbsd_arm64
+          ./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_amd64
+          ./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_arm64
           ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
           ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
@@ -62,7 +62,7 @@ jobs:
           gmake -C vendor/stb/src
           gmake -C vendor/stb/src
           gmake -C vendor/cgltf/src
           gmake -C vendor/cgltf/src
           gmake -C vendor/miniaudio/src
           gmake -C vendor/miniaudio/src
-          ./odin check examples/all -vet -strict-style -target:freebsd_amd64
+          ./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64
           ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
           ./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
           ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
           ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
@@ -97,7 +97,7 @@ jobs:
       - name: Download LLVM (MacOS ARM)
       - name: Download LLVM (MacOS ARM)
         if: matrix.os == 'macos-14'
         if: matrix.os == 'macos-14'
         run: |
         run: |
-          brew install llvm@17
+          brew install llvm@17 wasmtime
           echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
           echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
 
 
       - name: Build Odin
       - name: Build Odin
@@ -135,18 +135,24 @@ jobs:
           ./run.sh
           ./run.sh
 
 
       - name: Odin check examples/all for Linux i386
       - name: Odin check examples/all for Linux i386
-        run: ./odin check examples/all -vet -strict-style -target:linux_i386
+        run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_i386
         if: matrix.os == 'ubuntu-latest'
         if: matrix.os == 'ubuntu-latest'
       - name: Odin check examples/all for Linux arm64
       - name: Odin check examples/all for Linux arm64
-        run: ./odin check examples/all -vet -strict-style -target:linux_arm64
+        run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_arm64
         if: matrix.os == 'ubuntu-latest'
         if: matrix.os == 'ubuntu-latest'
       - name: Odin check examples/all for FreeBSD amd64
       - name: Odin check examples/all for FreeBSD amd64
-        run: ./odin check examples/all -vet -strict-style -target:freebsd_amd64
+        run: ./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64
         if: matrix.os == 'ubuntu-latest'
         if: matrix.os == 'ubuntu-latest'
       - name: Odin check examples/all for OpenBSD amd64
       - name: Odin check examples/all for OpenBSD amd64
-        run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
+        run: ./odin check examples/all -vet -strict-style -disallow-do -target:openbsd_amd64
         if: matrix.os == 'ubuntu-latest'
         if: matrix.os == 'ubuntu-latest'
 
 
+      - name: Run demo on WASI WASM32
+        run: |
+          ./odin build examples/demo -target:wasi_wasm32 -vet -strict-style -disallow-do -out:demo.wasm
+          wasmtime ./demo.wasm
+        if: matrix.os == 'macos-14'
+
   build_windows:
   build_windows:
     name: Windows Build, Check, and Test
     name: Windows Build, Check, and Test
     runs-on: windows-2022
     runs-on: windows-2022

+ 6 - 6
.github/workflows/nightly.yml

@@ -50,8 +50,8 @@ jobs:
         run: |
         run: |
           wget https://apt.llvm.org/llvm.sh
           wget https://apt.llvm.org/llvm.sh
           chmod +x llvm.sh
           chmod +x llvm.sh
-          sudo ./llvm.sh 17
-          echo "/usr/lib/llvm-17/bin" >> $GITHUB_PATH
+          sudo ./llvm.sh 18
+          echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH
       - name: build odin
       - name: build odin
         run: make nightly
         run: make nightly
       - name: Odin run
       - name: Odin run
@@ -82,8 +82,8 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/checkout@v4
       - name: Download LLVM and setup PATH
       - name: Download LLVM and setup PATH
         run: |
         run: |
-          brew install llvm@17 dylibbundler
-          echo "/usr/local/opt/llvm@17/bin" >> $GITHUB_PATH
+          brew install llvm@18 dylibbundler
+          echo "/usr/local/opt/llvm@18/bin" >> $GITHUB_PATH
       - name: build odin
       - name: build odin
         # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
         # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
         # not link with libunwind bundled with LLVM but link with libunwind on the system.
         # not link with libunwind bundled with LLVM but link with libunwind on the system.
@@ -116,8 +116,8 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/checkout@v4
       - name: Download LLVM and setup PATH
       - name: Download LLVM and setup PATH
         run: |
         run: |
-          brew install llvm@17 dylibbundler
-          echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
+          brew install llvm@18 dylibbundler
+          echo "/opt/homebrew/opt/llvm@18/bin" >> $GITHUB_PATH
       - name: build odin
       - name: build odin
         # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
         # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to
         # not link with libunwind bundled with LLVM but link with libunwind on the system.
         # not link with libunwind bundled with LLVM but link with libunwind on the system.

+ 1 - 1
.gitignore

@@ -303,7 +303,7 @@ bin/
 # - Linux/MacOS
 # - Linux/MacOS
 odin
 odin
 !odin/
 !odin/
-odin.dSYM
+**/*.dSYM
 *.bin
 *.bin
 demo.bin
 demo.bin
 libLLVM*.so*
 libLLVM*.so*

BIN
LLVM-C.dll


+ 4 - 1
base/intrinsics/intrinsics.odin

@@ -73,6 +73,8 @@ expect :: proc(val, expected_val: T) -> T ---
 
 
 // Linux and Darwin Only
 // Linux and Darwin Only
 syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
 syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
+// FreeBSD, NetBSD, et cetera
+syscall_bsd :: proc(id: uintptr, args: ..uintptr) -> (uintptr, bool) ---
 
 
 
 
 // Atomics
 // Atomics
@@ -192,7 +194,8 @@ type_proc_return_count    :: proc($T: typeid) -> int where type_is_proc(T) ---
 type_proc_parameter_type  :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 type_proc_parameter_type  :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 type_proc_return_type     :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 type_proc_return_type     :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 
 
-type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
+type_struct_field_count          :: proc($T: typeid) -> int  where type_is_struct(T) ---
+type_struct_has_implicit_padding :: proc($T: typeid) -> bool where type_is_struct(T) ---
 
 
 type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
 type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
 type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
 type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---

+ 28 - 0
base/runtime/core.odin

@@ -299,6 +299,8 @@ when ODIN_OS == .Windows {
 		Thread_Detach  = 3,
 		Thread_Detach  = 3,
 	}
 	}
 	dll_forward_reason: DLL_Forward_Reason
 	dll_forward_reason: DLL_Forward_Reason
+
+	dll_instance: rawptr
 }
 }
 
 
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
@@ -397,11 +399,34 @@ Logger :: struct {
 	options:      Logger_Options,
 	options:      Logger_Options,
 }
 }
 
 
+
+Random_Generator_Mode :: enum {
+	Read,
+	Reset,
+	Query_Info,
+}
+
+Random_Generator_Query_Info_Flag :: enum u32 {
+	Cryptographic,
+	Uniform,
+	External_Entropy,
+	Resettable,
+}
+Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
+
+Random_Generator_Proc :: #type proc(data: rawptr, mode: Random_Generator_Mode, p: []byte)
+
+Random_Generator :: struct {
+	procedure: Random_Generator_Proc,
+	data:      rawptr,
+}
+
 Context :: struct {
 Context :: struct {
 	allocator:              Allocator,
 	allocator:              Allocator,
 	temp_allocator:         Allocator,
 	temp_allocator:         Allocator,
 	assertion_failure_proc: Assertion_Failure_Proc,
 	assertion_failure_proc: Assertion_Failure_Proc,
 	logger:                 Logger,
 	logger:                 Logger,
+	random_generator:       Random_Generator,
 
 
 	user_ptr:   rawptr,
 	user_ptr:   rawptr,
 	user_index: int,
 	user_index: int,
@@ -708,6 +733,9 @@ __init_context :: proc "contextless" (c: ^Context) {
 
 
 	c.logger.procedure = default_logger_proc
 	c.logger.procedure = default_logger_proc
 	c.logger.data = nil
 	c.logger.data = nil
+
+	c.random_generator.procedure = default_random_generator_proc
+	c.random_generator.data = nil
 }
 }
 
 
 default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
 default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {

+ 56 - 13
base/runtime/core_builtin.odin

@@ -65,7 +65,7 @@ copy :: proc{copy_slice, copy_from_string}
 // with the old value, and reducing the length of the dynamic array by 1.
 // with the old value, and reducing the length of the dynamic array by 1.
 //
 //
 // Note: This is an O(1) operation.
 // Note: This is an O(1) operation.
-// Note: If you the elements to remain in their order, use `ordered_remove`.
+// Note: If you want the elements to remain in their order, use `ordered_remove`.
 // Note: If the index is out of bounds, this procedure will panic.
 // Note: If the index is out of bounds, this procedure will panic.
 @builtin
 @builtin
 unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
 unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
@@ -79,7 +79,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
 // `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements.
 // `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements.
 //
 //
 // Note: This is an O(N) operation.
 // Note: This is an O(N) operation.
-// Note: If you the elements do not have to remain in their order, prefer `unordered_remove`.
+// Note: If the elements do not have to remain in their order, prefer `unordered_remove`.
 // Note: If the index is out of bounds, this procedure will panic.
 // Note: If the index is out of bounds, this procedure will panic.
 @builtin
 @builtin
 ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
 ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
@@ -163,21 +163,43 @@ pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bo
 
 
 // `clear` will set the length of a passed dynamic array or map to `0`
 // `clear` will set the length of a passed dynamic array or map to `0`
 @builtin
 @builtin
-clear :: proc{clear_dynamic_array, clear_map}
+clear :: proc{
+	clear_dynamic_array,
+	clear_map,
+
+	clear_soa_dynamic_array,
+}
 
 
 // `reserve` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
 // `reserve` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
 @builtin
 @builtin
-reserve :: proc{reserve_dynamic_array, reserve_map}
+reserve :: proc{
+	reserve_dynamic_array,
+	reserve_map,
+
+	reserve_soa,
+}
 
 
 @builtin
 @builtin
-non_zero_reserve :: proc{non_zero_reserve_dynamic_array}
+non_zero_reserve :: proc{
+	non_zero_reserve_dynamic_array,
+
+	non_zero_reserve_soa,
+}
 
 
 // `resize` will try to resize memory of a passed dynamic array to the requested element count (setting the `len`, and possibly `cap`).
 // `resize` will try to resize memory of a passed dynamic array to the requested element count (setting the `len`, and possibly `cap`).
 @builtin
 @builtin
-resize :: proc{resize_dynamic_array}
+resize :: proc{
+	resize_dynamic_array,
+
+	resize_soa,
+}
 
 
 @builtin
 @builtin
-non_zero_resize :: proc{non_zero_resize_dynamic_array}
+non_zero_resize :: proc{
+	non_zero_resize_dynamic_array,
+
+	non_zero_resize_soa,
+}
 
 
 // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
 // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
 @builtin
 @builtin
@@ -268,7 +290,7 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat
 	return
 	return
 }
 }
 
 
-DEFAULT_RESERVE_CAPACITY :: 16
+DEFAULT_DYNAMIC_ARRAY_CAPACITY :: 8
 
 
 @(require_results)
 @(require_results)
 make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
 make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
@@ -295,7 +317,7 @@ make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allo
 // Note: Prefer using the procedure group `make`.
 // Note: Prefer using the procedure group `make`.
 @(builtin, require_results)
 @(builtin, require_results)
 make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
 make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
-	return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc)
+	return make_dynamic_array_len_cap(T, 0, 0, allocator, loc)
 }
 }
 // `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
@@ -364,6 +386,11 @@ make :: proc{
 	make_dynamic_array_len_cap,
 	make_dynamic_array_len_cap,
 	make_map,
 	make_map,
 	make_multi_pointer,
 	make_multi_pointer,
+
+	make_soa_slice,
+	make_soa_dynamic_array,
+	make_soa_dynamic_array_len,
+	make_soa_dynamic_array_len_cap,
 }
 }
 
 
 
 
@@ -423,7 +450,8 @@ _append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero:
 		return 1, nil
 		return 1, nil
 	} else {
 	} else {
 		if cap(array) < len(array)+1 {
 		if cap(array) < len(array)+1 {
-			cap := 2 * cap(array) + max(8, 1)
+			// Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY.
+			cap := 2 * cap(array) + DEFAULT_DYNAMIC_ARRAY_CAPACITY
 
 
 			// 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 {
 			if should_zero {
@@ -472,7 +500,7 @@ _append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, l
 		return arg_len, nil
 		return arg_len, nil
 	} else {
 	} else {
 		if cap(array) < len(array)+arg_len {
 		if cap(array) < len(array)+arg_len {
-			cap := 2 * cap(array) + max(8, arg_len)
+			cap := 2 * cap(array) + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
 
 
 			// 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 {
 			if should_zero {
@@ -540,8 +568,23 @@ 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
 // 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 append :: proc{
+	append_elem,
+	append_elems,
+	append_elem_string,
+
+	append_soa_elem,
+	append_soa_elems,
+}
+
+@builtin non_zero_append :: proc{
+	non_zero_append_elem,
+	non_zero_append_elems,
+	non_zero_append_elem_string,
+
+	non_zero_append_soa_elem,
+	non_zero_append_soa_elems,
+}
 
 
 
 
 @builtin
 @builtin

+ 64 - 50
base/runtime/core_builtin_soa.odin

@@ -55,7 +55,7 @@ raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Sl
 	if array == nil {
 	if array == nil {
 		return nil
 		return nil
 	}
 	}
-	field_count := uintptr(intrinsics.type_struct_field_count(E))
+	field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 	footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr))
 	footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr))
 	return
 	return
 }
 }
@@ -64,12 +64,7 @@ raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Ra
 	if array == nil {
 	if array == nil {
 		return nil
 		return nil
 	}
 	}
-	field_count: uintptr
-	when intrinsics.type_is_array(E) {
-		field_count = len(E)
-	} else {
-		field_count = uintptr(intrinsics.type_struct_field_count(E))
-	}
+	field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 	footer = (^Raw_SOA_Footer_Dynamic_Array)(uintptr(array) + field_count*size_of(rawptr))
 	footer = (^Raw_SOA_Footer_Dynamic_Array)(uintptr(array) + field_count*size_of(rawptr))
 	return
 	return
 }
 }
@@ -98,7 +93,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
 	ti = type_info_base(ti)
 	ti = type_info_base(ti)
 	si := &ti.variant.(Type_Info_Struct)
 	si := &ti.variant.(Type_Info_Struct)
 
 
-	field_count := uintptr(intrinsics.type_struct_field_count(E))
+	field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 	total_size := 0
 	total_size := 0
 	for i in 0..<field_count {
 	for i in 0..<field_count {
@@ -147,7 +142,7 @@ make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.al
 @(builtin, require_results)
 @(builtin, require_results)
 make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
 make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
 	context.allocator = allocator
 	context.allocator = allocator
-	reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) or_return
+	reserve_soa(&array, 0, loc) or_return
 	return array, nil
 	return array, nil
 }
 }
 
 
@@ -187,8 +182,28 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
 	return nil
 	return nil
 }
 }
 
 
+@builtin
+non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+	if array == nil {
+		return nil
+	}
+	non_zero_reserve_soa(array, length, loc) or_return
+	footer := raw_soa_footer(array)
+	footer.len = length
+	return nil
+}
+
 @builtin
 @builtin
 reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
 reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+	return _reserve_soa(array, capacity, true, loc)
+}
+
+@builtin
+non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+	return _reserve_soa(array, capacity, false, loc)
+}
+
+_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: bool, loc := #caller_location) -> Allocator_Error {
 	if array == nil {
 	if array == nil {
 		return nil
 		return nil
 	}
 	}
@@ -213,12 +228,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
 	ti = type_info_base(ti)
 	ti = type_info_base(ti)
 	si := &ti.variant.(Type_Info_Struct)
 	si := &ti.variant.(Type_Info_Struct)
 
 
-	field_count: uintptr
-	when intrinsics.type_is_array(E) {
-		field_count = len(E)
-	} else {
-		field_count = uintptr(intrinsics.type_struct_field_count(E))
-	}
+	field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 	assert(footer.cap == old_cap)
 	assert(footer.cap == old_cap)
 
 
 	old_size := 0
 	old_size := 0
@@ -238,7 +248,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
 	old_data := (^rawptr)(array)^
 	old_data := (^rawptr)(array)^
 
 
 	new_bytes := array.allocator.procedure(
 	new_bytes := array.allocator.procedure(
-		array.allocator.data, .Alloc, new_size, max_align,
+		array.allocator.data, .Alloc if zero_memory else .Alloc_Non_Zeroed, new_size, max_align,
 		nil, old_size, loc,
 		nil, old_size, loc,
 	) or_return
 	) or_return
 	new_data := raw_data(new_bytes)
 	new_data := raw_data(new_bytes)
@@ -273,15 +283,26 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
 	return nil
 	return nil
 }
 }
 
 
+
+@builtin
+append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_soa_elem(array, true, arg, loc)
+}
+
 @builtin
 @builtin
-append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+non_zero_append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_soa_elem(array, false, arg, loc)
+}
+
+_append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
 	if array == nil {
 	if array == nil {
 		return 0, nil
 		return 0, nil
 	}
 	}
 
 
 	if cap(array) <= len(array) + 1 {
 	if cap(array) <= len(array) + 1 {
-		cap := 2 * cap(array) + 8
-		err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
+		// Same behavior as append_soa_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY.
+		cap := 2 * cap(array) + DEFAULT_DYNAMIC_ARRAY_CAPACITY
+		err = _reserve_soa(array, cap, zero_memory, loc) // do not 'or_return' here as it could be a partial success
 	}
 	}
 
 
 	footer := raw_soa_footer(array)
 	footer := raw_soa_footer(array)
@@ -290,12 +311,7 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
 		ti := type_info_of(T)
 		ti := type_info_of(T)
 		ti = type_info_base(ti)
 		ti = type_info_base(ti)
 		si := &ti.variant.(Type_Info_Struct)
 		si := &ti.variant.(Type_Info_Struct)
-		field_count: uintptr
-		when intrinsics.type_is_array(E) {
-			field_count = len(E)
-		} else {
-			field_count = uintptr(intrinsics.type_struct_field_count(E))
-		}
+		field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 		data := (^rawptr)(array)^
 		data := (^rawptr)(array)^
 
 
@@ -326,7 +342,17 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
 }
 }
 
 
 @builtin
 @builtin
-append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_soa_elems(array, true, args=args, loc=loc)
+}
+
+@builtin
+non_zero_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_soa_elems(array, false, args=args, loc=loc)
+}
+
+
+_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
 	if array == nil {
 	if array == nil {
 		return
 		return
 	}
 	}
@@ -337,8 +363,8 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
 	}
 	}
 
 
 	if cap(array) <= len(array)+arg_len {
 	if cap(array) <= len(array)+arg_len {
-		cap := 2 * cap(array) + max(8, arg_len)
-		err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
+		cap := 2 * cap(array) + max(DEFAULT_DYNAMIC_ARRAY_CAPACITY, arg_len)
+		err = _reserve_soa(array, cap, zero_memory, loc) // do not 'or_return' here as it could be a partial success
 	}
 	}
 	arg_len = min(cap(array)-len(array), arg_len)
 	arg_len = min(cap(array)-len(array), arg_len)
 
 
@@ -347,7 +373,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
 		ti := type_info_of(typeid_of(T))
 		ti := type_info_of(typeid_of(T))
 		ti = type_info_base(ti)
 		ti = type_info_base(ti)
 		si := &ti.variant.(Type_Info_Struct)
 		si := &ti.variant.(Type_Info_Struct)
-		field_count := uintptr(intrinsics.type_struct_field_count(E))
+		field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 		data := (^rawptr)(array)^
 		data := (^rawptr)(array)^
 
 
@@ -389,7 +415,8 @@ append_soa :: proc{
 
 
 
 
 delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
 delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
-	when intrinsics.type_struct_field_count(E) != 0 {
+	field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
+	when field_count != 0 {
 		array := array
 		array := array
 		ptr := (^rawptr)(&array)^
 		ptr := (^rawptr)(&array)^
 		free(ptr, allocator, loc) or_return
 		free(ptr, allocator, loc) or_return
@@ -398,7 +425,8 @@ delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc
 }
 }
 
 
 delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {
 delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {
-	when intrinsics.type_struct_field_count(E) != 0 {
+	field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
+	when field_count != 0 {
 		array := array
 		array := array
 		ptr := (^rawptr)(&array)^
 		ptr := (^rawptr)(&array)^
 		footer := raw_soa_footer(&array)
 		footer := raw_soa_footer(&array)
@@ -416,7 +444,8 @@ delete_soa :: proc{
 
 
 
 
 clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
 clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
-	when intrinsics.type_struct_field_count(E) != 0 {
+	field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
+	when field_count != 0 {
 		footer := raw_soa_footer(array)
 		footer := raw_soa_footer(array)
 		footer.len = 0
 		footer.len = 0
 	}
 	}
@@ -438,12 +467,7 @@ into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
 		allocator = nil_allocator(),
 		allocator = nil_allocator(),
 	}
 	}
 
 
-	field_count: uintptr
-	when intrinsics.type_is_array(E) {
-		field_count = len(E)
-	} else {
-		field_count = uintptr(intrinsics.type_struct_field_count(E))
-	}
+	field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 	array := array
 	array := array
 	dynamic_data := ([^]rawptr)(&d)[:field_count]
 	dynamic_data := ([^]rawptr)(&d)[:field_count]
@@ -467,12 +491,7 @@ unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #cal
 		ti = type_info_base(ti)
 		ti = type_info_base(ti)
 		si := &ti.variant.(Type_Info_Struct)
 		si := &ti.variant.(Type_Info_Struct)
 
 
-		field_count: uintptr
-		when intrinsics.type_is_array(E) {
-			field_count = len(E)
-		} else {
-			field_count = uintptr(intrinsics.type_struct_field_count(E))
-		}
+		field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 		data := uintptr(array)
 		data := uintptr(array)
 		for i in 0..<field_count {
 		for i in 0..<field_count {
@@ -500,12 +519,7 @@ ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #calle
 		ti = type_info_base(ti)
 		ti = type_info_base(ti)
 		si := &ti.variant.(Type_Info_Struct)
 		si := &ti.variant.(Type_Info_Struct)
 
 
-		field_count: uintptr
-		when intrinsics.type_is_array(E) {
-			field_count = len(E)
-		} else {
-			field_count = uintptr(intrinsics.type_struct_field_count(E))
-		}
+		field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
 
 
 		data := uintptr(array)
 		data := uintptr(array)
 		for i in 0..<field_count {
 		for i in 0..<field_count {

+ 2 - 1
base/runtime/default_allocators_arena.odin → base/runtime/default_temp_allocator_arena.odin

@@ -12,7 +12,8 @@ Memory_Block :: struct {
 	capacity:  uint,
 	capacity:  uint,
 }
 }
 
 
-// NOTE: This is for internal use, prefer `Arena` from `core:mem/virtual` if necessary
+// NOTE: This is a growing arena that is only used for the default temp allocator.
+// For your own growing arena needs, prefer `Arena` from `core:mem/virtual`.
 Arena :: struct {
 Arena :: struct {
 	backing_allocator:  Allocator,
 	backing_allocator:  Allocator,
 	curr_block:         ^Memory_Block,
 	curr_block:         ^Memory_Block,

+ 5 - 0
base/runtime/entry_wasm.odin

@@ -22,6 +22,11 @@ when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
 		@(link_name="_start", linkage="strong", require, export)
 		@(link_name="_start", linkage="strong", require, export)
 		_start :: proc "c" () {
 		_start :: proc "c" () {
 			context = default_context()
 			context = default_context()
+
+			when ODIN_OS == .WASI {
+				_wasi_setup_args()
+			}
+
 			#force_no_inline _startup_runtime()
 			#force_no_inline _startup_runtime()
 			intrinsics.__entry_point()
 			intrinsics.__entry_point()
 		}
 		}

+ 2 - 1
base/runtime/entry_windows.odin

@@ -10,8 +10,9 @@ when ODIN_BUILD_MODE == .Dynamic {
 	DllMain :: proc "system" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
 	DllMain :: proc "system" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
 		context = default_context()
 		context = default_context()
 
 
-		// Populate Windows DLL-specific global
+		// Populate Windows DLL-specific globals
 		dll_forward_reason = DLL_Forward_Reason(fdwReason)
 		dll_forward_reason = DLL_Forward_Reason(fdwReason)
+		dll_instance       = hinstDLL
 
 
 		switch dll_forward_reason {
 		switch dll_forward_reason {
 		case .Process_Attach:
 		case .Process_Attach:

+ 3 - 3
base/runtime/heap_allocator.odin

@@ -97,14 +97,14 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 }
 }
 
 
 
 
-heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	return _heap_alloc(size, zero_memory)
 	return _heap_alloc(size, zero_memory)
 }
 }
 
 
-heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
 	return _heap_resize(ptr, new_size)
 	return _heap_resize(ptr, new_size)
 }
 }
 
 
-heap_free :: proc(ptr: rawptr) {
+heap_free :: proc "contextless" (ptr: rawptr) {
 	_heap_free(ptr)
 	_heap_free(ptr)
 }
 }

+ 3 - 3
base/runtime/heap_allocator_orca.odin

@@ -9,7 +9,7 @@ foreign {
 	@(link_name="realloc")  _orca_realloc  :: proc "c" (ptr: rawptr, size: int) -> rawptr ---
 	@(link_name="realloc")  _orca_realloc  :: proc "c" (ptr: rawptr, size: int) -> rawptr ---
 }
 }
 
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	if size <= 0 {
 	if size <= 0 {
 		return nil
 		return nil
 	}
 	}
@@ -20,10 +20,10 @@ _heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
 	}
 	}
 }
 }
 
 
-_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
 	return _orca_realloc(ptr, new_size)
 	return _orca_realloc(ptr, new_size)
 }
 }
 
 
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	_orca_free(ptr)
 	_orca_free(ptr)
 }
 }

+ 6 - 3
base/runtime/heap_allocator_other.odin

@@ -2,14 +2,17 @@
 //+private
 //+private
 package runtime
 package runtime
 
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
+	context = default_context()
 	unimplemented("base:runtime 'heap_alloc' procedure is not supported on this platform")
 	unimplemented("base:runtime 'heap_alloc' procedure is not supported on this platform")
 }
 }
 
 
-_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
+	context = default_context()
 	unimplemented("base:runtime 'heap_resize' procedure is not supported on this platform")
 	unimplemented("base:runtime 'heap_resize' procedure is not supported on this platform")
 }
 }
 
 
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
+	context = default_context()
 	unimplemented("base:runtime 'heap_free' procedure is not supported on this platform")
 	unimplemented("base:runtime 'heap_free' procedure is not supported on this platform")
 }
 }

+ 3 - 3
base/runtime/heap_allocator_unix.odin

@@ -16,7 +16,7 @@ foreign libc {
 	@(link_name="realloc")  _unix_realloc  :: proc(ptr: rawptr, size: int) -> rawptr ---
 	@(link_name="realloc")  _unix_realloc  :: proc(ptr: rawptr, size: int) -> rawptr ---
 }
 }
 
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	if size <= 0 {
 	if size <= 0 {
 		return nil
 		return nil
 	}
 	}
@@ -27,12 +27,12 @@ _heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
 	}
 	}
 }
 }
 
 
-_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
 	// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
 	// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
 	// POSIX platforms. Ensure your caller takes this into account.
 	// POSIX platforms. Ensure your caller takes this into account.
 	return _unix_realloc(ptr, new_size)
 	return _unix_realloc(ptr, new_size)
 }
 }
 
 
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	_unix_free(ptr)
 	_unix_free(ptr)
 }
 }

+ 3 - 3
base/runtime/heap_allocator_windows.odin

@@ -14,11 +14,11 @@ foreign kernel32 {
 	HeapFree       :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr) -> b32 ---
 	HeapFree       :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr) -> b32 ---
 }
 }
 
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	HEAP_ZERO_MEMORY :: 0x00000008
 	HEAP_ZERO_MEMORY :: 0x00000008
 	return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY if zero_memory else 0, uint(size))
 	return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY if zero_memory else 0, uint(size))
 }
 }
-_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+_heap_resize :: proc "contextless" (ptr: rawptr, new_size: int) -> rawptr {
 	if new_size == 0 {
 	if new_size == 0 {
 		_heap_free(ptr)
 		_heap_free(ptr)
 		return nil
 		return nil
@@ -30,7 +30,7 @@ _heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
 	HEAP_ZERO_MEMORY :: 0x00000008
 	HEAP_ZERO_MEMORY :: 0x00000008
 	return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size))
 	return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size))
 }
 }
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	if ptr == nil {
 	if ptr == nil {
 		return
 		return
 	}
 	}

+ 31 - 27
base/runtime/internal.odin

@@ -1,3 +1,4 @@
+//+vet !cast
 package runtime
 package runtime
 
 
 import "base:intrinsics"
 import "base:intrinsics"
@@ -29,7 +30,7 @@ is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
 	return (x & (x-1)) == 0
 	return (x & (x-1)) == 0
 }
 }
 
 
-align_forward_int :: #force_inline proc(ptr, align: int) -> int {
+align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int {
 	assert(is_power_of_two_int(align))
 	assert(is_power_of_two_int(align))
 
 
 	p := ptr
 	p := ptr
@@ -47,7 +48,7 @@ is_power_of_two_uint :: #force_inline proc "contextless" (x: uint) -> bool {
 	return (x & (x-1)) == 0
 	return (x & (x-1)) == 0
 }
 }
 
 
-align_forward_uint :: #force_inline proc(ptr, align: uint) -> uint {
+align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint {
 	assert(is_power_of_two_uint(align))
 	assert(is_power_of_two_uint(align))
 
 
 	p := ptr
 	p := ptr
@@ -65,7 +66,7 @@ is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool
 	return (x & (x-1)) == 0
 	return (x & (x-1)) == 0
 }
 }
 
 
-align_forward_uintptr :: #force_inline proc(ptr, align: uintptr) -> uintptr {
+align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr {
 	assert(is_power_of_two_uintptr(align))
 	assert(is_power_of_two_uintptr(align))
 
 
 	p := ptr
 	p := ptr
@@ -642,21 +643,24 @@ abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64
 
 
 
 
 quo_complex32 :: proc "contextless" (n, m: complex32) -> complex32 {
 quo_complex32 :: proc "contextless" (n, m: complex32) -> complex32 {
-	e, f: f16
+	nr, ni := f32(real(n)), f32(imag(n))
+	mr, mi := f32(real(m)), f32(imag(m))
 
 
-	if abs(real(m)) >= abs(imag(m)) {
-		ratio := imag(m) / real(m)
-		denom := real(m) + ratio*imag(m)
-		e = (real(n) + imag(n)*ratio) / denom
-		f = (imag(n) - real(n)*ratio) / denom
+	e, f: f32
+
+	if abs(mr) >= abs(mi) {
+		ratio := mi / mr
+		denom := mr + ratio*mi
+		e = (nr + ni*ratio) / denom
+		f = (ni - nr*ratio) / denom
 	} else {
 	} else {
-		ratio := real(m) / imag(m)
-		denom := imag(m) + ratio*real(m)
-		e = (real(n)*ratio + imag(n)) / denom
-		f = (imag(n)*ratio - real(n)) / denom
+		ratio := mr / mi
+		denom := mi + ratio*mr
+		e = (nr*ratio + ni) / denom
+		f = (ni*ratio - nr) / denom
 	}
 	}
 
 
-	return complex(e, f)
+	return complex(f16(e), f16(f))
 }
 }
 
 
 
 
@@ -697,15 +701,15 @@ quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 {
 }
 }
 
 
 mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
 mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
-	q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
-	r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
+	q0, q1, q2, q3 := f32(real(q)), f32(imag(q)), f32(jmag(q)), f32(kmag(q))
+	r0, r1, r2, r3 := f32(real(r)), f32(imag(r)), f32(jmag(r)), f32(kmag(r))
 
 
 	t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
 	t0 := r0*q0 - r1*q1 - r2*q2 - r3*q3
 	t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
 	t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
 	t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
 	t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
 	t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
 	t3 := r0*q3 - r1*q2 + r2*q1 + r3*q0
 
 
-	return quaternion(w=t0, x=t1, y=t2, z=t3)
+	return quaternion(w=f16(t0), x=f16(t1), y=f16(t2), z=f16(t3))
 }
 }
 
 
 mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
 mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
@@ -733,8 +737,8 @@ mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
 }
 }
 
 
 quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
 quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
-	q0, q1, q2, q3 := real(q), imag(q), jmag(q), kmag(q)
-	r0, r1, r2, r3 := real(r), imag(r), jmag(r), kmag(r)
+	q0, q1, q2, q3 := f32(real(q)), f32(imag(q)), f32(jmag(q)), f32(kmag(q))
+	r0, r1, r2, r3 := f32(real(r)), f32(imag(r)), f32(jmag(r)), f32(kmag(r))
 
 
 	invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
 	invmag2 := 1.0 / (r0*r0 + r1*r1 + r2*r2 + r3*r3)
 
 
@@ -743,7 +747,7 @@ quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
 	t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
 	t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
 	t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
 	t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
 
 
-	return quaternion(w=t0, x=t1, y=t2, z=t3)
+	return quaternion(w=f16(t0), x=f16(t1), y=f16(t2), z=f16(t3))
 }
 }
 
 
 quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
 quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {
@@ -1012,26 +1016,26 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
 	bn := (b ~ s_b) - s_b
 	bn := (b ~ s_b) - s_b
 
 
 	r: u128 = ---
 	r: u128 = ---
-	_ = udivmod128(transmute(u128)an, transmute(u128)bn, &r)
-	return (transmute(i128)r ~ s_a) - s_a
+	_ = udivmod128(u128(an), u128(bn), &r)
+	return (i128(r) ~ s_a) - s_a
 }
 }
 
 
 
 
 @(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
 @(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
 divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
 divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 {
-	u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem)
-	return transmute(i128)u
+	u := udivmod128(u128(a), u128(b), (^u128)(rem))
+	return i128(u)
 }
 }
 
 
 @(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
 @(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
 divti3 :: proc "c" (a, b: i128) -> i128 {
 divti3 :: proc "c" (a, b: i128) -> i128 {
-	u := udivmodti4(transmute(u128)a, transmute(u128)b, nil)
-	return transmute(i128)u
+	u := udivmodti4(u128(a), u128(b), nil)
+	return i128(u)
 }
 }
 
 
 
 
 @(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
 @(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
-fixdfti :: proc(a: u64) -> i128 {
+fixdfti :: proc "c" (a: u64) -> i128 {
 	significandBits :: 52
 	significandBits :: 52
 	typeWidth       :: (size_of(u64)*8)
 	typeWidth       :: (size_of(u64)*8)
 	exponentBits    :: (typeWidth - significandBits - 1)
 	exponentBits    :: (typeWidth - significandBits - 1)

+ 18 - 5
base/runtime/os_specific_darwin.odin

@@ -5,11 +5,24 @@ package runtime
 import "base:intrinsics"
 import "base:intrinsics"
 
 
 _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
 _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
-	WRITE  :: 0x2000004
 	STDERR :: 2
 	STDERR :: 2
-	ret := intrinsics.syscall(WRITE, STDERR, uintptr(raw_data(data)), uintptr(len(data)))
-	if ret < 0 {
-		return 0, _OS_Errno(-ret)
+	when ODIN_NO_CRT {
+		WRITE  :: 0x2000004
+		ret := intrinsics.syscall(WRITE, STDERR, uintptr(raw_data(data)), uintptr(len(data)))
+		if ret < 0 {
+			return 0, _OS_Errno(-ret)
+		}
+		return int(ret), 0
+	} else {
+		foreign {
+			write   :: proc(handle: i32, buffer: [^]byte, count: uint) -> int ---
+			__error :: proc() -> ^i32 ---
+		}
+
+		if ret := write(STDERR, raw_data(data), len(data)); ret >= 0 {
+			return int(ret), 0
+		}
+
+		return 0, _OS_Errno(__error()^)
 	}
 	}
-	return int(ret), 0
 }
 }

+ 47 - 3
base/runtime/os_specific_wasi.odin

@@ -2,10 +2,54 @@
 //+private
 //+private
 package runtime
 package runtime
 
 
-import "core:sys/wasm/wasi"
+foreign import wasi "wasi_snapshot_preview1"
+
+@(default_calling_convention="contextless")
+foreign wasi {
+	fd_write :: proc(
+		fd: i32,
+		iovs: [][]byte,
+		n: ^uint,
+	) -> u16 ---
+
+	@(private="file")
+	args_sizes_get :: proc(
+		num_of_args:  ^uint,
+		size_of_args: ^uint,
+	) -> u16 ---
+
+	@(private="file")
+	args_get :: proc(
+		argv:     [^]cstring,
+		argv_buf: [^]byte,
+	) -> u16 ---
+}
 
 
 _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
 _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
-	data_iovec := (wasi.ciovec_t)(data)
-	n, err := wasi.fd_write(1, {data_iovec})
+	n: uint
+	err := fd_write(1, {data}, &n)
 	return int(n), _OS_Errno(err)
 	return int(n), _OS_Errno(err)
 }
 }
+
+_wasi_setup_args :: proc() {
+	num_of_args, size_of_args: uint
+	if errno := args_sizes_get(&num_of_args, &size_of_args); errno != 0 {
+		return
+	}
+
+	err: Allocator_Error
+	if args__, err = make([]cstring, num_of_args); err != nil {
+		return
+	}
+
+	args_buf: []byte
+	if args_buf, err = make([]byte, size_of_args); err != nil {
+		delete(args__)
+		return
+	}
+
+	if errno := args_get(raw_data(args__), raw_data(args_buf)); errno != 0 {
+		delete(args__)
+		delete(args_buf)
+	}
+}

+ 1 - 1
base/runtime/print.odin

@@ -262,7 +262,7 @@ print_typeid :: #force_no_inline proc "contextless" (id: typeid) {
 	}
 	}
 }
 }
 
 
-@(optimization_mode="size")
+@(optimization_mode="favor_size")
 print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
 print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
 	if ti == nil {
 	if ti == nil {
 		print_string("nil")
 		print_string("nil")

+ 127 - 0
base/runtime/random_generator.odin

@@ -0,0 +1,127 @@
+package runtime
+
+import "base:intrinsics"
+
+@(require_results)
+random_generator_read_bytes :: proc(rg: Random_Generator, p: []byte) -> bool {
+	if rg.procedure != nil {
+		rg.procedure(rg.data, .Read, p)
+		return true
+	}
+	return false
+}
+
+@(require_results)
+random_generator_read_ptr :: proc(rg: Random_Generator, p: rawptr, len: uint) -> bool {
+	if rg.procedure != nil {
+		rg.procedure(rg.data, .Read, ([^]byte)(p)[:len])
+		return true
+	}
+	return false
+}
+
+@(require_results)
+random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Generator_Query_Info) {
+	if rg.procedure != nil {
+		rg.procedure(rg.data, .Query_Info, ([^]byte)(&info)[:size_of(info)])
+	}
+	return
+}
+
+
+random_generator_reset_bytes :: proc(rg: Random_Generator, p: []byte) {
+	if rg.procedure != nil {
+		rg.procedure(rg.data, .Reset, p)
+	}
+}
+
+random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) {
+	if rg.procedure != nil {
+		p := p
+		rg.procedure(rg.data, .Reset, ([^]byte)(&p)[:size_of(p)])
+	}
+}
+
+
+Default_Random_State :: struct {
+	state: u64,
+	inc:   u64,
+}
+
+default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) {
+	@(require_results)
+	read_u64 :: proc "contextless" (r: ^Default_Random_State) -> u64 {
+		old_state := r.state
+		r.state = old_state * 6364136223846793005 + (r.inc|1)
+		xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
+		rot := (old_state >> 59)
+		return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
+	}
+
+	@(thread_local)
+	global_rand_seed: Default_Random_State
+
+	init :: proc "contextless" (r: ^Default_Random_State, seed: u64) {
+		seed := seed
+		if seed == 0 {
+			seed = u64(intrinsics.read_cycle_counter())
+		}
+		r.state = 0
+		r.inc = (seed << 1) | 1
+		_ = read_u64(r)
+		r.state += seed
+		_ = read_u64(r)
+	}
+
+	r: ^Default_Random_State = ---
+	if data == nil {
+		r = &global_rand_seed
+	} else {
+		r = cast(^Default_Random_State)data
+	}
+
+	switch mode {
+	case .Read:
+		if r.state == 0 && r.inc == 0 {
+			init(r, 0)
+		}
+
+		switch len(p) {
+		case size_of(u64):
+			// Fast path for a 64-bit destination.
+			intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r))
+		case:
+			// All other cases.
+			pos := i8(0)
+			val := u64(0)
+			for &v in p {
+				if pos == 0 {
+					val = read_u64(r)
+					pos = 7
+				}
+				v = byte(val)
+				val >>= 8
+				pos -= 1
+			}
+		}
+
+	case .Reset:
+		seed: u64
+		mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
+		init(r, seed)
+
+	case .Query_Info:
+		if len(p) != size_of(Random_Generator_Query_Info) {
+			return
+		}
+		info := (^Random_Generator_Query_Info)(raw_data(p))
+		info^ += {.Uniform, .Resettable}
+	}
+}
+
+default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator {
+	return {
+		procedure = default_random_generator_proc,
+		data = state,
+	}
+}

+ 3 - 3
base/runtime/udivmod128.odin

@@ -58,7 +58,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 			return u128(n[high] >> _ctz(d[high]))
 			return u128(n[high] >> _ctz(d[high]))
 		}
 		}
 
 
-		sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high])))
+		sr = u32(i32(_clz(d[high])) - i32(_clz(n[high])))
 		if sr > U64_BITS - 2 {
 		if sr > U64_BITS - 2 {
 			if rem != nil {
 			if rem != nil {
 				rem^ = a
 				rem^ = a
@@ -107,7 +107,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 				r[low]  = n[high] >> (sr - U64_BITS)
 				r[low]  = n[high] >> (sr - U64_BITS)
 			}
 			}
 		} else {
 		} else {
-			sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high])))
+			sr = u32(i32(_clz(d[high])) - i32(_clz(n[high])))
 
 
 			if sr > U64_BITS - 1 {
 			if sr > U64_BITS - 1 {
 				if rem != nil {
 				if rem != nil {
@@ -143,7 +143,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 		r_all = transmute(u128)r
 		r_all = transmute(u128)r
 		s := i128(b - r_all - 1) >> (U128_BITS - 1)
 		s := i128(b - r_all - 1) >> (U128_BITS - 1)
 		carry = u32(s & 1)
 		carry = u32(s & 1)
-		r_all -= b & transmute(u128)s
+		r_all -= b & u128(s)
 		r = transmute([2]u64)r_all
 		r = transmute([2]u64)r_all
 	}
 	}
 
 

+ 3 - 3
base/runtime/wasm_allocator.odin

@@ -495,7 +495,7 @@ claim_more_memory :: proc(a: ^WASM_Allocator, num_bytes: uint) -> bool {
 		// we can just extend the spill.
 		// we can just extend the spill.
 		spill_end := uintptr(raw_data(a.spill)) + uintptr(len(a.spill))
 		spill_end := uintptr(raw_data(a.spill)) + uintptr(len(a.spill))
 		if spill_end == uintptr(raw_data(allocated)) {
 		if spill_end == uintptr(raw_data(allocated)) {
-			raw_spill := transmute(^Raw_Slice)(&a.spill)
+			raw_spill := (^Raw_Slice)(&a.spill)
 			raw_spill.len += len(allocated)
 			raw_spill.len += len(allocated)
 		} else {
 		} else {
 			// Otherwise, we have to "waste" the previous spill.
 			// Otherwise, we have to "waste" the previous spill.
@@ -679,7 +679,7 @@ allocate_memory :: proc(a: ^WASM_Allocator, alignment: uint, size: uint, loc :=
 			// but we just had a stale bit set to mark a populated bucket.
 			// but we just had a stale bit set to mark a populated bucket.
 			// Reset the bit to update latest status so that we do not
 			// Reset the bit to update latest status so that we do not
 			// redundantly look at this bucket again.
 			// redundantly look at this bucket again.
-			a.free_region_buckets_used &= ~(BUCKET_BITMASK_T(1) << bucket_index)
+			a.free_region_buckets_used &~= BUCKET_BITMASK_T(1) << bucket_index
 			bucket_mask ~= 1
 			bucket_mask ~= 1
 		}
 		}
 
 
@@ -760,7 +760,7 @@ free :: proc(a: ^WASM_Allocator, ptr: rawptr, loc := #caller_location) {
 	defer unlock(a)
 	defer unlock(a)
 
 
 	size := region.size
 	size := region.size
-	assert(region_is_in_use(region), "double free", loc=loc)
+	assert(region_is_in_use(region), "double free or corrupt region", loc=loc)
 
 
 	prev_region_size_field := ([^]uint)(region)[-1]
 	prev_region_size_field := ([^]uint)(region)[-1]
 	prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)
 	prev_region_size := prev_region_size_field & ~uint(FREE_REGION_FLAG)

BIN
bin/llvm/windows/LLVM-C.lib


BIN
bin/llvm/windows/clang_rt.asan-x86_64.lib


+ 4 - 1
build.bat

@@ -48,6 +48,9 @@ if "%2" == "1" (
 set odin_version_raw="dev-%curr_year%-%curr_month%"
 set odin_version_raw="dev-%curr_year%-%curr_month%"
 
 
 set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
 set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
+rem Parse source code as utf-8 even on shift-jis and other codepages
+rem See https://learn.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170
+set compiler_flags= %compiler_flags% /utf-8
 set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
 set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
 
 
 if not exist .git\ goto skip_git_hash
 if not exist .git\ goto skip_git_hash
@@ -111,7 +114,7 @@ call build_vendor.bat
 if %errorlevel% neq 0 goto end_of_build
 if %errorlevel% neq 0 goto end_of_build
 
 
 rem If the demo doesn't run for you and your CPU is more than a decade old, try -microarch:native
 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
+if %release_mode% EQU 0 odin run examples/demo -vet -strict-style -- Hellope World
 
 
 del *.obj > NUL 2> NUL
 del *.obj > NUL 2> NUL
 
 

+ 1 - 1
build_odin.sh

@@ -144,7 +144,7 @@ build_odin() {
 }
 }
 
 
 run_demo() {
 run_demo() {
-	./odin run examples/demo/demo.odin -file -- Hellope World
+	./odin run examples/demo -vet -strict-style -- Hellope World
 }
 }
 
 
 if [ $# -eq 0 ]; then
 if [ $# -eq 0 ]; then

+ 1 - 14
core/c/libc/signal.odin

@@ -34,20 +34,7 @@ when ODIN_OS == .Windows {
 	SIGTERM :: 15
 	SIGTERM :: 15
 }
 }
 
 
-when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
-	SIG_ERR  :: rawptr(~uintptr(0))
-	SIG_DFL  :: rawptr(uintptr(0))
-	SIG_IGN  :: rawptr(uintptr(1)) 
-
-	SIGABRT  :: 6
-	SIGFPE   :: 8
-	SIGILL   :: 4
-	SIGINT   :: 2
-	SIGSEGV  :: 11
-	SIGTERM  :: 15
-}
-
-when ODIN_OS == .Darwin {
+when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Darwin {
 	SIG_ERR  :: rawptr(~uintptr(0))
 	SIG_ERR  :: rawptr(~uintptr(0))
 	SIG_DFL  :: rawptr(uintptr(0))
 	SIG_DFL  :: rawptr(uintptr(0))
 	SIG_IGN  :: rawptr(uintptr(1)) 
 	SIG_IGN  :: rawptr(uintptr(1)) 

+ 28 - 28
core/compress/common.odin

@@ -34,13 +34,13 @@ COMPRESS_OUTPUT_ALLOCATE_MIN :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 2
 */
 */
 when size_of(uintptr) == 8 {
 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))
 	COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32))
 } else {
 } else {
 	
 	
 	// For 32-bit platforms, we set the default max buffer size to 512 MiB.
 	// 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))
+	COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29))
 }
 }
 
 
 
 
@@ -186,7 +186,7 @@ input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Erro
 
 
 input_size :: proc{input_size_from_memory, input_size_from_stream}
 input_size :: proc{input_size_from_memory, input_size_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int) -> (res: []u8, err: io.Error) {
 read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int) -> (res: []u8, err: io.Error) {
 	#no_bounds_check {
 	#no_bounds_check {
 		if len(z.input_data) >= size {
 		if len(z.input_data) >= size {
@@ -203,7 +203,7 @@ read_slice_from_memory :: #force_inline proc(z: ^Context_Memory_Input, size: int
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int) -> (res: []u8, err: io.Error) {
 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
 	// TODO: REMOVE ALL USE OF context.temp_allocator here
 	// there is literally no need for it
 	// there is literally no need for it
@@ -214,13 +214,13 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
 
 
 read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
 read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
 read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
 	b := read_slice(z, size_of(T)) or_return
 	b := read_slice(z, size_of(T)) or_return
 	return (^T)(&b[0])^, nil
 	return (^T)(&b[0])^, nil
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8, err: io.Error) {
 read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8, err: io.Error) {
 	#no_bounds_check {
 	#no_bounds_check {
 		if len(z.input_data) >= 1 {
 		if len(z.input_data) >= 1 {
@@ -232,7 +232,7 @@ read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8,
 	return 0, .EOF
 	return 0, .EOF
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
 read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
 	b := read_slice_from_stream(z, 1) or_return
 	b := read_slice_from_stream(z, 1) or_return
 	return b[0], nil
 	return b[0], nil
@@ -242,7 +242,7 @@ 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
 // You would typically only use this at the end of Inflate, to drain bits from the code buffer
 // preferentially.
 // preferentially.
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) {
 read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) {
 	if z.num_bits >= 8 {
 	if z.num_bits >= 8 {
 		res = u8(read_bits_no_refill_lsb(z, 8))
 		res = u8(read_bits_no_refill_lsb(z, 8))
@@ -257,7 +257,7 @@ read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: i
 	return
 	return
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid) -> (res: T, err: io.Error) {
 peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid) -> (res: T, err: io.Error) {
 	size :: size_of(T)
 	size :: size_of(T)
 
 
@@ -275,7 +275,7 @@ peek_data_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_data_at_offset_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
 peek_data_at_offset_from_memory :: #force_inline proc(z: ^Context_Memory_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
 	size :: size_of(T)
 	size :: size_of(T)
 
 
@@ -293,7 +293,7 @@ peek_data_at_offset_from_memory :: #force_inline proc(z: ^Context_Memory_Input,
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid) -> (res: T, err: io.Error) {
 peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid) -> (res: T, err: io.Error) {
 	size :: size_of(T)
 	size :: size_of(T)
 
 
@@ -317,7 +317,7 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
 	return res, .None
 	return res, .None
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
 peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid, #any_int offset: int) -> (res: T, err: io.Error) {
 	size :: size_of(T)
 	size :: size_of(T)
 
 
@@ -352,14 +352,14 @@ peek_data :: proc{peek_data_from_memory, peek_data_from_stream, peek_data_at_off
 
 
 
 
 // Sliding window read back
 // Sliding window read back
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_back_byte :: #force_inline proc(z: ^$C, offset: i64) -> (res: u8, err: io.Error) {
 peek_back_byte :: #force_inline proc(z: ^$C, offset: i64) -> (res: u8, err: io.Error) {
 	// Look back into the sliding window.
 	// Look back into the sliding window.
 	return z.output.buf[z.bytes_written - offset], .None
 	return z.output.buf[z.bytes_written - offset], .None
 }
 }
 
 
 // Generalized bit reader LSB
 // Generalized bit reader LSB
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := i8(48)) {
 refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := i8(48)) {
 	refill := u64(width)
 	refill := u64(width)
 	b      := u64(0)
 	b      := u64(0)
@@ -385,7 +385,7 @@ refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width :=
 }
 }
 
 
 // Generalized bit reader LSB
 // Generalized bit reader LSB
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
 refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
 	refill := u64(width)
 	refill := u64(width)
 
 
@@ -414,13 +414,13 @@ refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
 refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream}
 refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream}
 
 
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 consume_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) {
 consume_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) {
 	z.code_buffer >>= width
 	z.code_buffer >>= width
 	z.num_bits -= u64(width)
 	z.num_bits -= u64(width)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) {
 consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) {
 	z.code_buffer >>= width
 	z.code_buffer >>= width
 	z.num_bits -= u64(width)
 	z.num_bits -= u64(width)
@@ -428,7 +428,7 @@ consume_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, wid
 
 
 consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream}
 consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	if z.num_bits < u64(width) {
 	if z.num_bits < u64(width) {
 		refill_lsb(z)
 		refill_lsb(z)
@@ -436,7 +436,7 @@ peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width:
 	return u32(z.code_buffer &~ (~u64(0) << width))
 	return u32(z.code_buffer &~ (~u64(0) << width))
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	if z.num_bits < u64(width) {
 	if z.num_bits < u64(width) {
 		refill_lsb(z)
 		refill_lsb(z)
@@ -446,13 +446,13 @@ peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
 
 
 peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
 peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	assert(z.num_bits >= u64(width))
 	assert(z.num_bits >= u64(width))
 	return u32(z.code_buffer &~ (~u64(0) << width))
 	return u32(z.code_buffer &~ (~u64(0) << width))
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	assert(z.num_bits >= u64(width))
 	assert(z.num_bits >= u64(width))
 	return u32(z.code_buffer &~ (~u64(0) << width))
 	return u32(z.code_buffer &~ (~u64(0) << width))
@@ -460,14 +460,14 @@ peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Inp
 
 
 peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
 peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 read_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	k := #force_inline peek_bits_lsb(z, width)
 	k := #force_inline peek_bits_lsb(z, width)
 	#force_inline consume_bits_lsb(z, width)
 	#force_inline consume_bits_lsb(z, width)
 	return k
 	return k
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	k := peek_bits_lsb(z, width)
 	k := peek_bits_lsb(z, width)
 	consume_bits_lsb(z, width)
 	consume_bits_lsb(z, width)
@@ -476,14 +476,14 @@ read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
 
 
 read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream}
 read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 read_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	k := #force_inline peek_bits_no_refill_lsb(z, width)
 	k := #force_inline peek_bits_no_refill_lsb(z, width)
 	#force_inline consume_bits_lsb(z, width)
 	#force_inline consume_bits_lsb(z, width)
 	return k
 	return k
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	k := peek_bits_no_refill_lsb(z, width)
 	k := peek_bits_no_refill_lsb(z, width)
 	consume_bits_lsb(z, width)
 	consume_bits_lsb(z, width)
@@ -493,14 +493,14 @@ read_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Inp
 read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream}
 read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream}
 
 
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input) {
 discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input) {
 	discard := u8(z.num_bits & 7)
 	discard := u8(z.num_bits & 7)
 	#force_inline consume_bits_lsb(z, discard)
 	#force_inline consume_bits_lsb(z, discard)
 }
 }
 
 
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input) {
 discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input) {
 	discard := u8(z.num_bits & 7)
 	discard := u8(z.num_bits & 7)
 	consume_bits_lsb(z, discard)
 	consume_bits_lsb(z, discard)

+ 4 - 7
core/compress/shoco/shoco.odin

@@ -98,7 +98,7 @@ decompress_slice_to_output_buffer :: proc(input: []u8, output: []u8, model := DE
 	validate_model(model) or_return
 	validate_model(model) or_return
 
 
 	for inp < inp_end {
 	for inp < inp_end {
-		val  := transmute(i8)input[inp]
+		val  := i8(input[inp])
 		mark := int(-1)
 		mark := int(-1)
 
 
 		for val < 0 {
 		for val < 0 {
@@ -274,12 +274,9 @@ compress_string_to_buffer :: proc(input: string, output: []u8, model := DEFAULT_
 				out_ptr := raw_data(output[out:])
 				out_ptr := raw_data(output[out:])
 
 
 				switch pack.bytes_packed {
 				switch pack.bytes_packed {
-				case 4:
-					intrinsics.unaligned_store(transmute(^u32)out_ptr, code)
-				case 2:
-					intrinsics.unaligned_store(transmute(^u16)out_ptr, u16(code))
-				case 1:
-					intrinsics.unaligned_store(transmute(^u8)out_ptr,  u8(code))
+				case 4: intrinsics.unaligned_store((^u32)(out_ptr), code)
+				case 2: intrinsics.unaligned_store((^u16)(out_ptr), u16(code))
+				case 1: intrinsics.unaligned_store( (^u8)(out_ptr),  u8(code))
 				case:
 				case:
 					return out, .Unknown_Compression_Method
 					return out, .Unknown_Compression_Method
 				}
 				}

+ 11 - 11
core/compress/zlib/zlib.odin

@@ -120,7 +120,7 @@ Huffman_Table :: struct {
 }
 }
 
 
 // Implementation starts here
 // Implementation starts here
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
 z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
 	assert(bits <= 16)
 	assert(bits <= 16)
 	// NOTE: Can optimize with llvm.bitreverse.i64 or some bit twiddling
 	// NOTE: Can optimize with llvm.bitreverse.i64 or some bit twiddling
@@ -136,7 +136,7 @@ z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
 }
 }
 
 
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
 grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
 	/*
 	/*
 		That we get here at all means that we didn't pass an expected output size,
 		That we get here at all means that we didn't pass an expected output size,
@@ -154,7 +154,7 @@ grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
 	TODO: Make these return compress.Error.
 	TODO: Make these return compress.Error.
 */
 */
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_check {
 write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_check {
 	/*
 	/*
 		Resize if needed.
 		Resize if needed.
@@ -173,7 +173,7 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch
 	return .None
 	return .None
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
 repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
 	/*
 	/*
 		TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
 		TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
@@ -201,7 +201,7 @@ repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check
 	return .None
 	return .None
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 repl_bytes :: proc(z: ^$C, count: u16, distance: u16) -> (err: io.Error) {
 repl_bytes :: proc(z: ^$C, count: u16, distance: u16) -> (err: io.Error) {
 	/*
 	/*
 		TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
 		TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
@@ -234,7 +234,7 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
 	return new(Huffman_Table, allocator), nil
 	return new(Huffman_Table, allocator), nil
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
 build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
 	sizes:     [HUFFMAN_MAX_BITS+1]int
 	sizes:     [HUFFMAN_MAX_BITS+1]int
 	next_code: [HUFFMAN_MAX_BITS+1]int
 	next_code: [HUFFMAN_MAX_BITS+1]int
@@ -293,7 +293,7 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
 	return nil
 	return nil
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 	code := u16(compress.peek_bits_lsb(z,16))
 	code := u16(compress.peek_bits_lsb(z,16))
 
 
@@ -324,7 +324,7 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
 	return r, nil
 	return r, nil
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 	if z.num_bits < 16 {
 	if z.num_bits < 16 {
 		if z.num_bits > 63 {
 		if z.num_bits > 63 {
@@ -344,7 +344,7 @@ decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bo
 	return decode_huffman_slowpath(z, t)
 	return decode_huffman_slowpath(z, t)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Error) #no_bounds_check {
 parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Error) #no_bounds_check {
 	#no_bounds_check for {
 	#no_bounds_check for {
 		value, e := decode_huffman(z, z_repeat)
 		value, e := decode_huffman(z, z_repeat)
@@ -413,7 +413,7 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := false, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
 inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := false, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
 	/*
 	/*
 		ctx.output must be a bytes.Buffer for now. We'll add a separate implementation that writes to a stream.
 		ctx.output must be a bytes.Buffer for now. We'll add a separate implementation that writes to a stream.
@@ -486,7 +486,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
 
 
 // TODO: Check alignment of reserve/resize.
 // TODO: Check alignment of reserve/resize.
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
 inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
 	context.allocator = allocator
 	context.allocator = allocator
 	expected_output_size := expected_output_size
 	expected_output_size := expected_output_size

+ 1 - 1
core/container/avl/avl.odin

@@ -87,7 +87,7 @@ init_cmp :: proc(
 init_ordered :: proc(
 init_ordered :: proc(
 	t: ^$T/Tree($Value),
 	t: ^$T/Tree($Value),
 	node_allocator := context.allocator,
 	node_allocator := context.allocator,
-) where intrinsics.type_is_ordered_numeric(Value) {
+) where intrinsics.type_is_ordered(Value) {
 	init_cmp(t, slice.cmp_proc(Value), node_allocator)
 	init_cmp(t, slice.cmp_proc(Value), node_allocator)
 }
 }
 
 

+ 6 - 3
core/container/bit_array/bit_array.odin

@@ -210,8 +210,11 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
 
 
 	ba.max_index = max(idx, ba.max_index)
 	ba.max_index = max(idx, ba.max_index)
 
 
-	if set_to{ ba.bits[leg_index] |= 1 << uint(bit_index) }
-	else { ba.bits[leg_index] &= ~(1 << uint(bit_index)) }
+	if set_to {
+		ba.bits[leg_index] |=  1 << uint(bit_index)
+	} else {
+		ba.bits[leg_index] &~= 1 << uint(bit_index)
+	}
 
 
 	return true
 	return true
 }
 }
@@ -253,7 +256,7 @@ Inputs:
 - index: Which bit in the array
 - index: Which bit in the array
 */
 */
 unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
 unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
-	b.bits[bit >> INDEX_SHIFT] &= ~(1 << uint(bit & INDEX_MASK))
+	b.bits[bit >> INDEX_SHIFT] &~= 1 << uint(bit & INDEX_MASK)
 }
 }
 /*
 /*
 A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
 A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).

+ 1 - 2
core/container/lru/lru_cache.odin

@@ -70,8 +70,7 @@ set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> runtime.Alloc
 	if c.count == c.capacity {
 	if c.count == c.capacity {
 		e = c.tail
 		e = c.tail
 		_remove_node(c, e)
 		_remove_node(c, e)
-	}
-	else {
+	} else {
 		c.count += 1
 		c.count += 1
 		e = new(Node(Key, Value), c.node_allocator) or_return
 		e = new(Node(Key, Value), c.node_allocator) or_return
 	}
 	}

+ 2 - 2
core/container/queue/queue.odin

@@ -189,7 +189,7 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
 	return
 	return
 }
 }
 
 
-// Push multiple elements to the front of the queue
+// Push multiple elements to the back of the queue
 push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error)  {
 push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error)  {
 	n := uint(builtin.len(elems))
 	n := uint(builtin.len(elems))
 	if space(q^) < int(n) {
 	if space(q^) < int(n) {
@@ -241,7 +241,7 @@ clear :: proc(q: ^$Q/Queue($T)) {
 }
 }
 
 
 
 
-// Internal growinh procedure
+// Internal growing procedure
 _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
 _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
 	new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
 	new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
 	n := uint(builtin.len(q.data))
 	n := uint(builtin.len(q.data))

+ 2 - 2
core/container/rbtree/rbtree.odin

@@ -29,7 +29,7 @@ Tree :: struct($Key: typeid, $Value: typeid) {
 
 
 	_root:           ^Node(Key, Value),
 	_root:           ^Node(Key, Value),
 	_node_allocator: runtime.Allocator,
 	_node_allocator: runtime.Allocator,
-	_cmp_fn:          proc(Key, Key) -> Ordering,
+	_cmp_fn:         proc(Key, Key) -> Ordering,
 	_size:           int,
 	_size:           int,
 }
 }
 
 
@@ -79,7 +79,7 @@ init_cmp :: proc(t: ^$T/Tree($Key, $Value), cmp_fn: proc(a, b: Key) -> Ordering,
 
 
 // init_ordered initializes a tree containing ordered keys, with
 // init_ordered initializes a tree containing ordered keys, with
 // a comparison function that results in an ascending order sort.
 // a comparison function that results in an ascending order sort.
-init_ordered :: proc(t: ^$T/Tree($Key, $Value), node_allocator := context.allocator) where intrinsics.type_is_ordered_numeric(Key) {
+init_ordered :: proc(t: ^$T/Tree($Key, $Value), node_allocator := context.allocator) where intrinsics.type_is_ordered(Key) {
 	init_cmp(t, slice.cmp_proc(Key), node_allocator)
 	init_cmp(t, slice.cmp_proc(Key), node_allocator)
 }
 }
 
 

+ 4 - 4
core/container/small_array/small_array.odin

@@ -119,20 +119,20 @@ consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_l
 }
 }
 
 
 ordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
 ordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
-    runtime.bounds_check_error_loc(loc, index, a.len)
-    if index+1 < a.len {
+	runtime.bounds_check_error_loc(loc, index, a.len)
+	if index+1 < a.len {
 		copy(a.data[index:], a.data[index+1:])
 		copy(a.data[index:], a.data[index+1:])
 	}
 	}
 	a.len -= 1
 	a.len -= 1
 }
 }
 
 
 unordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
 unordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
-    runtime.bounds_check_error_loc(loc, index, a.len)
+	runtime.bounds_check_error_loc(loc, index, a.len)
 	n := a.len-1
 	n := a.len-1
 	if index != n {
 	if index != n {
 		a.data[index] = a.data[n]
 		a.data[index] = a.data[n]
 	}
 	}
-    a.len -= 1
+	a.len -= 1
 }
 }
 
 
 clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
 clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {

+ 1 - 1
core/container/topological_sort/topological_sort.odin

@@ -61,7 +61,7 @@ add_dependency :: proc(sorter: ^$S/Sorter($K), key, dependency: K) -> bool {
 	}
 	}
 	find.dependents[key] = true
 	find.dependents[key] = true
 
 
- 	find = &sorter.relations[key]
+	find = &sorter.relations[key]
 	if find == nil {
 	if find == nil {
 		find = map_insert(&sorter.relations, key, make_relations(sorter))
 		find = map_insert(&sorter.relations, key, make_relations(sorter))
 	}
 	}

+ 2 - 2
core/crypto/_edwards25519/edwards25519.odin

@@ -110,7 +110,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
 	if len(b) != 32 {
 	if len(b) != 32 {
 		intrinsics.trap()
 		intrinsics.trap()
 	}
 	}
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 
 
 	// Do the work in a scratch element, so that ge is unchanged on
 	// Do the work in a scratch element, so that ge is unchanged on
 	// failure.
 	// failure.
@@ -169,7 +169,7 @@ ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) {
 	if len(dst) != 32 {
 	if len(dst) != 32 {
 		intrinsics.trap()
 		intrinsics.trap()
 	}
 	}
-	dst_ := transmute(^[32]byte)(raw_data(dst))
+	dst_ := (^[32]byte)(raw_data(dst))
 
 
 	// Convert the element to affine (x, y) representation.
 	// Convert the element to affine (x, y) representation.
 	x, y, z_inv: field.Tight_Field_Element = ---, ---, ---
 	x, y, z_inv: field.Tight_Field_Element = ---, ---, ---

+ 2 - 2
core/crypto/_edwards25519/edwards25519_scalar.odin

@@ -28,7 +28,7 @@ sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool {
 	if len(b) != 32 {
 	if len(b) != 32 {
 		intrinsics.trap()
 		intrinsics.trap()
 	}
 	}
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 	return field.fe_from_bytes(sc, b_)
 	return field.fe_from_bytes(sc, b_)
 }
 }
 
 
@@ -36,7 +36,7 @@ sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) {
 	if len(b) != 32 {
 	if len(b) != 32 {
 		intrinsics.trap()
 		intrinsics.trap()
 	}
 	}
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 	field.fe_from_bytes_rfc8032(sc, b_)
 	field.fe_from_bytes_rfc8032(sc, b_)
 }
 }
 
 

+ 2 - 2
core/crypto/_fiat/field_curve25519/field.odin

@@ -6,13 +6,13 @@ import "core:mem"
 fe_relax_cast :: #force_inline proc "contextless" (
 fe_relax_cast :: #force_inline proc "contextless" (
 	arg1: ^Tight_Field_Element,
 	arg1: ^Tight_Field_Element,
 ) -> ^Loose_Field_Element {
 ) -> ^Loose_Field_Element {
-	return transmute(^Loose_Field_Element)(arg1)
+	return (^Loose_Field_Element)(arg1)
 }
 }
 
 
 fe_tighten_cast :: #force_inline proc "contextless" (
 fe_tighten_cast :: #force_inline proc "contextless" (
 	arg1: ^Loose_Field_Element,
 	arg1: ^Loose_Field_Element,
 ) -> ^Tight_Field_Element {
 ) -> ^Tight_Field_Element {
-	return transmute(^Tight_Field_Element)(arg1)
+	return (^Tight_Field_Element)(arg1)
 }
 }
 
 
 fe_clear :: proc "contextless" (
 fe_clear :: proc "contextless" (

+ 2 - 2
core/crypto/_fiat/field_poly1305/field.odin

@@ -7,13 +7,13 @@ import "core:mem"
 fe_relax_cast :: #force_inline proc "contextless" (
 fe_relax_cast :: #force_inline proc "contextless" (
 	arg1: ^Tight_Field_Element,
 	arg1: ^Tight_Field_Element,
 ) -> ^Loose_Field_Element {
 ) -> ^Loose_Field_Element {
-	return transmute(^Loose_Field_Element)(arg1)
+	return (^Loose_Field_Element)(arg1)
 }
 }
 
 
 fe_tighten_cast :: #force_inline proc "contextless" (
 fe_tighten_cast :: #force_inline proc "contextless" (
 	arg1: ^Loose_Field_Element,
 	arg1: ^Loose_Field_Element,
 ) -> ^Tight_Field_Element {
 ) -> ^Tight_Field_Element {
-	return transmute(^Tight_Field_Element)(arg1)
+	return (^Tight_Field_Element)(arg1)
 }
 }
 
 
 fe_from_bytes :: #force_inline proc "contextless" (
 fe_from_bytes :: #force_inline proc "contextless" (

+ 22 - 0
core/crypto/crypto.odin

@@ -4,6 +4,7 @@ helper routines.
 */
 */
 package crypto
 package crypto
 
 
+import "base:runtime"
 import "core:mem"
 import "core:mem"
 
 
 // compare_constant_time returns 1 iff a and b are equal, 0 otherwise.
 // compare_constant_time returns 1 iff a and b are equal, 0 otherwise.
@@ -58,3 +59,24 @@ rand_bytes :: proc (dst: []byte) {
 
 
 	_rand_bytes(dst)
 	_rand_bytes(dst)
 }
 }
+
+
+random_generator :: proc() -> runtime.Random_Generator {
+	return {
+		procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
+			switch mode {
+			case .Read:
+				rand_bytes(p)
+			case .Reset:
+				// do nothing
+			case .Query_Info:
+				if len(p) != size_of(runtime.Random_Generator_Query_Info) {
+					return
+				}
+				info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
+				info^ += {.Uniform, .Cryptographic, .External_Entropy}
+			}
+		},
+		data = nil,
+	}
+}

+ 5 - 5
core/crypto/kmac/kmac.odin

@@ -61,7 +61,7 @@ init_256 :: proc(ctx: ^Context, key, domain_sep: []byte) {
 update :: proc(ctx: ^Context, data: []byte) {
 update :: proc(ctx: ^Context, data: []byte) {
 	assert(ctx.is_initialized)
 	assert(ctx.is_initialized)
 
 
-	shake.write(transmute(^shake.Context)(ctx), data)
+	shake.write((^shake.Context)(ctx), data)
 }
 }
 
 
 // final finalizes the Context, writes the tag to dst, and calls reset
 // final finalizes the Context, writes the tag to dst, and calls reset
@@ -75,7 +75,7 @@ final :: proc(ctx: ^Context, dst: []byte) {
 		panic("crypto/kmac: invalid KMAC tag_size, too short")
 		panic("crypto/kmac: invalid KMAC tag_size, too short")
 	}
 	}
 
 
-	_sha3.final_cshake(transmute(^_sha3.Context)(ctx), dst)
+	_sha3.final_cshake((^_sha3.Context)(ctx), dst)
 }
 }
 
 
 // clone clones the Context other into ctx.
 // clone clones the Context other into ctx.
@@ -84,7 +84,7 @@ clone :: proc(ctx, other: ^Context) {
 		return
 		return
 	}
 	}
 
 
-	shake.clone(transmute(^shake.Context)(ctx), transmute(^shake.Context)(other))
+	shake.clone((^shake.Context)(ctx), (^shake.Context)(other))
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to
@@ -94,7 +94,7 @@ reset :: proc(ctx: ^Context) {
 		return
 		return
 	}
 	}
 
 
-	shake.reset(transmute(^shake.Context)(ctx))
+	shake.reset((^shake.Context)(ctx))
 }
 }
 
 
 @(private)
 @(private)
@@ -107,7 +107,7 @@ _init_kmac :: proc(ctx: ^Context, key, s: []byte, sec_strength: int) {
 		panic("crypto/kmac: invalid KMAC key, too short")
 		panic("crypto/kmac: invalid KMAC key, too short")
 	}
 	}
 
 
-	ctx_ := transmute(^_sha3.Context)(ctx)
+	ctx_ := (^_sha3.Context)(ctx)
 	_sha3.init_cshake(ctx_, N_KMAC, s, sec_strength)
 	_sha3.init_cshake(ctx_, N_KMAC, s, sec_strength)
 	_sha3.bytepad(ctx_, [][]byte{key}, _sha3.rate_cshake(sec_strength))
 	_sha3.bytepad(ctx_, [][]byte{key}, _sha3.rate_cshake(sec_strength))
 }
 }

+ 5 - 5
core/crypto/legacy/keccak/keccak.odin

@@ -66,12 +66,12 @@ init_512 :: proc(ctx: ^Context) {
 @(private)
 @(private)
 _init :: proc(ctx: ^Context) {
 _init :: proc(ctx: ^Context) {
 	ctx.dsbyte = _sha3.DS_KECCAK
 	ctx.dsbyte = _sha3.DS_KECCAK
-	_sha3.init(transmute(^_sha3.Context)(ctx))
+	_sha3.init((^_sha3.Context)(ctx))
 }
 }
 
 
 // update adds more data to the Context.
 // update adds more data to the Context.
 update :: proc(ctx: ^Context, data: []byte) {
 update :: proc(ctx: ^Context, data: []byte) {
-	_sha3.update(transmute(^_sha3.Context)(ctx), data)
+	_sha3.update((^_sha3.Context)(ctx), data)
 }
 }
 
 
 // final finalizes the Context, writes the digest to hash, and calls
 // final finalizes the Context, writes the digest to hash, and calls
@@ -80,16 +80,16 @@ update :: proc(ctx: ^Context, data: []byte) {
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // which is useful for for calculating rolling digests.
 // which is useful for for calculating rolling digests.
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
-	_sha3.final(transmute(^_sha3.Context)(ctx), hash, finalize_clone)
+	_sha3.final((^_sha3.Context)(ctx), hash, finalize_clone)
 }
 }
 
 
 // clone clones the Context other into ctx.
 // clone clones the Context other into ctx.
 clone :: proc(ctx, other: ^Context) {
 clone :: proc(ctx, other: ^Context) {
-	_sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
+	_sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other))
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to
 // be used again.
 // be used again.
 reset :: proc(ctx: ^Context) {
 reset :: proc(ctx: ^Context) {
-	_sha3.reset(transmute(^_sha3.Context)(ctx))
+	_sha3.reset((^_sha3.Context)(ctx))
 }
 }

+ 2 - 2
core/crypto/rand_darwin.odin

@@ -11,7 +11,7 @@ HAS_RAND_BYTES :: true
 _rand_bytes :: proc(dst: []byte) {
 _rand_bytes :: proc(dst: []byte) {
 	err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst))
 	err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst))
 	if err != .Success {
 	if err != .Success {
-	        msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err))
-	        fmt.panicf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg)
+		msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err))
+		fmt.panicf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg)
 	}
 	}
 }
 }

+ 3 - 3
core/crypto/ristretto255/ristretto255.odin

@@ -112,7 +112,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
 		return false
 		return false
 	}
 	}
 
 
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 
 
 	s: field.Tight_Field_Element = ---
 	s: field.Tight_Field_Element = ---
 	defer field.fe_clear(&s)
 	defer field.fe_clear(&s)
@@ -297,7 +297,7 @@ ge_bytes :: proc(ge: ^Group_Element, dst: []byte) {
 	// 2.  Return the 32-byte little-endian encoding of s.  More
 	// 2.  Return the 32-byte little-endian encoding of s.  More
 	// specifically, this is the encoding of the canonical
 	// specifically, this is the encoding of the canonical
 	// representation of s as an integer between 0 and p-1, inclusive.
 	// representation of s as an integer between 0 and p-1, inclusive.
-	dst_ := transmute(^[32]byte)(raw_data(dst))
+	dst_ := (^[32]byte)(raw_data(dst))
 	field.fe_to_bytes(dst_, &tmp)
 	field.fe_to_bytes(dst_, &tmp)
 
 
 	field.fe_clear_vec([]^field.Tight_Field_Element{&u1, &u2, &tmp, &z_inv, &ix0, &iy0, &x, &y})
 	field.fe_clear_vec([]^field.Tight_Field_Element{&u1, &u2, &tmp, &z_inv, &ix0, &iy0, &x, &y})
@@ -417,7 +417,7 @@ ge_is_identity :: proc(ge: ^Group_Element) -> int {
 
 
 @(private)
 @(private)
 ge_map :: proc "contextless" (ge: ^Group_Element, b: []byte) {
 ge_map :: proc "contextless" (ge: ^Group_Element, b: []byte) {
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 
 
 	// The MAP function is defined on 32-byte strings as:
 	// The MAP function is defined on 32-byte strings as:
 	//
 	//

+ 1 - 1
core/crypto/ristretto255/ristretto255_scalar.odin

@@ -46,7 +46,7 @@ sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) {
 		panic("crypto/ristretto255: invalid wide input size")
 		panic("crypto/ristretto255: invalid wide input size")
 	}
 	}
 
 
-	b_ := transmute(^[WIDE_SCALAR_SIZE]byte)(raw_data(b))
+	b_ := (^[WIDE_SCALAR_SIZE]byte)(raw_data(b))
 	grp.sc_set_bytes_wide(sc, b_)
 	grp.sc_set_bytes_wide(sc, b_)
 }
 }
 
 

+ 5 - 5
core/crypto/sha3/sha3.odin

@@ -68,12 +68,12 @@ init_512 :: proc(ctx: ^Context) {
 @(private)
 @(private)
 _init :: proc(ctx: ^Context) {
 _init :: proc(ctx: ^Context) {
 	ctx.dsbyte = _sha3.DS_SHA3
 	ctx.dsbyte = _sha3.DS_SHA3
-	_sha3.init(transmute(^_sha3.Context)(ctx))
+	_sha3.init((^_sha3.Context)(ctx))
 }
 }
 
 
 // update adds more data to the Context.
 // update adds more data to the Context.
 update :: proc(ctx: ^Context, data: []byte) {
 update :: proc(ctx: ^Context, data: []byte) {
-	_sha3.update(transmute(^_sha3.Context)(ctx), data)
+	_sha3.update((^_sha3.Context)(ctx), data)
 }
 }
 
 
 // final finalizes the Context, writes the digest to hash, and calls
 // final finalizes the Context, writes the digest to hash, and calls
@@ -82,16 +82,16 @@ update :: proc(ctx: ^Context, data: []byte) {
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // which is useful for for calculating rolling digests.
 // which is useful for for calculating rolling digests.
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
-	_sha3.final(transmute(^_sha3.Context)(ctx), hash, finalize_clone)
+	_sha3.final((^_sha3.Context)(ctx), hash, finalize_clone)
 }
 }
 
 
 // clone clones the Context other into ctx.
 // clone clones the Context other into ctx.
 clone :: proc(ctx, other: ^Context) {
 clone :: proc(ctx, other: ^Context) {
-	_sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
+	_sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other))
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to
 // be used again.
 // be used again.
 reset :: proc(ctx: ^Context) {
 reset :: proc(ctx: ^Context) {
-	_sha3.reset(transmute(^_sha3.Context)(ctx))
+	_sha3.reset((^_sha3.Context)(ctx))
 }
 }

+ 8 - 8
core/crypto/shake/shake.odin

@@ -24,35 +24,35 @@ Context :: distinct _sha3.Context
 
 
 // init_128 initializes a Context for SHAKE128.
 // init_128 initializes a Context for SHAKE128.
 init_128 :: proc(ctx: ^Context) {
 init_128 :: proc(ctx: ^Context) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), nil, nil, 128)
+	_sha3.init_cshake((^_sha3.Context)(ctx), nil, nil, 128)
 }
 }
 
 
 // init_256 initializes a Context for SHAKE256.
 // init_256 initializes a Context for SHAKE256.
 init_256 :: proc(ctx: ^Context) {
 init_256 :: proc(ctx: ^Context) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), nil, nil, 256)
+	_sha3.init_cshake((^_sha3.Context)(ctx), nil, nil, 256)
 }
 }
 
 
 // init_cshake_128 initializes a Context for cSHAKE128.
 // init_cshake_128 initializes a Context for cSHAKE128.
 init_cshake_128 :: proc(ctx: ^Context, domain_sep: []byte) {
 init_cshake_128 :: proc(ctx: ^Context, domain_sep: []byte) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), nil, domain_sep, 128)
+	_sha3.init_cshake((^_sha3.Context)(ctx), nil, domain_sep, 128)
 }
 }
 
 
 // init_cshake_256 initializes a Context for cSHAKE256.
 // init_cshake_256 initializes a Context for cSHAKE256.
 init_cshake_256 :: proc(ctx: ^Context, domain_sep: []byte) {
 init_cshake_256 :: proc(ctx: ^Context, domain_sep: []byte) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), nil, domain_sep, 256)
+	_sha3.init_cshake((^_sha3.Context)(ctx), nil, domain_sep, 256)
 }
 }
 
 
 // write writes more data into the SHAKE instance.  This MUST not be called
 // write writes more data into the SHAKE instance.  This MUST not be called
 // after any reads have been done, and attempts to do so will panic.
 // after any reads have been done, and attempts to do so will panic.
 write :: proc(ctx: ^Context, data: []byte) {
 write :: proc(ctx: ^Context, data: []byte) {
-	_sha3.update(transmute(^_sha3.Context)(ctx), data)
+	_sha3.update((^_sha3.Context)(ctx), data)
 }
 }
 
 
 // read reads output from the SHAKE instance.  There is no practical upper
 // read reads output from the SHAKE instance.  There is no practical upper
 // limit to the amount of data that can be read from SHAKE.  After read has
 // limit to the amount of data that can be read from SHAKE.  After read has
 // been called one or more times, further calls to write will panic.
 // been called one or more times, further calls to write will panic.
 read :: proc(ctx: ^Context, dst: []byte) {
 read :: proc(ctx: ^Context, dst: []byte) {
-	ctx_ := transmute(^_sha3.Context)(ctx)
+	ctx_ := (^_sha3.Context)(ctx)
 	if !ctx.is_finalized {
 	if !ctx.is_finalized {
 		_sha3.shake_xof(ctx_)
 		_sha3.shake_xof(ctx_)
 	}
 	}
@@ -62,11 +62,11 @@ read :: proc(ctx: ^Context, dst: []byte) {
 
 
 // clone clones the Context other into ctx.
 // clone clones the Context other into ctx.
 clone :: proc(ctx, other: ^Context) {
 clone :: proc(ctx, other: ^Context) {
-	_sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
+	_sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other))
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to
 // be used again.
 // be used again.
 reset :: proc(ctx: ^Context) {
 reset :: proc(ctx: ^Context) {
-	_sha3.reset(transmute(^_sha3.Context)(ctx))
+	_sha3.reset((^_sha3.Context)(ctx))
 }
 }

+ 7 - 7
core/crypto/tuplehash/tuplehash.odin

@@ -13,19 +13,19 @@ Context :: distinct _sha3.Context
 
 
 // init_128 initializes a Context for TupleHash128 or TupleHashXOF128.
 // init_128 initializes a Context for TupleHash128 or TupleHashXOF128.
 init_128 :: proc(ctx: ^Context, domain_sep: []byte) {
 init_128 :: proc(ctx: ^Context, domain_sep: []byte) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 128)
+	_sha3.init_cshake((^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 128)
 }
 }
 
 
 // init_256 initializes a Context for TupleHash256 or TupleHashXOF256.
 // init_256 initializes a Context for TupleHash256 or TupleHashXOF256.
 init_256 :: proc(ctx: ^Context, domain_sep: []byte) {
 init_256 :: proc(ctx: ^Context, domain_sep: []byte) {
-	_sha3.init_cshake(transmute(^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 256)
+	_sha3.init_cshake((^_sha3.Context)(ctx), N_TUPLEHASH, domain_sep, 256)
 }
 }
 
 
 // write_element writes a tuple element into the TupleHash or TupleHashXOF
 // write_element writes a tuple element into the TupleHash or TupleHashXOF
 // instance.  This MUST not be called after any reads have been done, and
 // instance.  This MUST not be called after any reads have been done, and
 // any attempts to do so will panic.
 // any attempts to do so will panic.
 write_element :: proc(ctx: ^Context, data: []byte) {
 write_element :: proc(ctx: ^Context, data: []byte) {
-	_, _ = _sha3.encode_string(transmute(^_sha3.Context)(ctx), data)
+	_, _ = _sha3.encode_string((^_sha3.Context)(ctx), data)
 }
 }
 
 
 // final finalizes the Context, writes the digest to hash, and calls
 // final finalizes the Context, writes the digest to hash, and calls
@@ -34,7 +34,7 @@ write_element :: proc(ctx: ^Context, data: []byte) {
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // which is useful for for calculating rolling digests.
 // which is useful for for calculating rolling digests.
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
 final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
-	_sha3.final_cshake(transmute(^_sha3.Context)(ctx), hash, finalize_clone)
+	_sha3.final_cshake((^_sha3.Context)(ctx), hash, finalize_clone)
 }
 }
 
 
 // read reads output from the TupleHashXOF instance.  There is no practical
 // read reads output from the TupleHashXOF instance.  There is no practical
@@ -42,7 +42,7 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
 // After read has been called one or more times, further calls to
 // After read has been called one or more times, further calls to
 // write_element will panic.
 // write_element will panic.
 read :: proc(ctx: ^Context, dst: []byte) {
 read :: proc(ctx: ^Context, dst: []byte) {
-	ctx_ := transmute(^_sha3.Context)(ctx)
+	ctx_ := (^_sha3.Context)(ctx)
 	if !ctx.is_finalized {
 	if !ctx.is_finalized {
 		_sha3.encode_byte_len(ctx_, 0, false) // right_encode
 		_sha3.encode_byte_len(ctx_, 0, false) // right_encode
 		_sha3.shake_xof(ctx_)
 		_sha3.shake_xof(ctx_)
@@ -53,13 +53,13 @@ read :: proc(ctx: ^Context, dst: []byte) {
 
 
 // clone clones the Context other into ctx.
 // clone clones the Context other into ctx.
 clone :: proc(ctx, other: ^Context) {
 clone :: proc(ctx, other: ^Context) {
-	_sha3.clone(transmute(^_sha3.Context)(ctx), transmute(^_sha3.Context)(other))
+	_sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other))
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to
 // be used again.
 // be used again.
 reset :: proc(ctx: ^Context) {
 reset :: proc(ctx: ^Context) {
-	_sha3.reset(transmute(^_sha3.Context)(ctx))
+	_sha3.reset((^_sha3.Context)(ctx))
 }
 }
 
 
 @(private)
 @(private)

+ 1 - 1
core/debug/trace/trace_cpp.odin

@@ -78,7 +78,7 @@ _Context :: struct {
 
 
 @(private="package")
 @(private="package")
 _init :: proc(ctx: ^Context) -> (ok: bool) {
 _init :: proc(ctx: ^Context) -> (ok: bool) {
-	defer if !ok do destroy(ctx)
+	defer if !ok { destroy(ctx) }
 
 
 	ctx.impl.state = backtrace_create_state("odin-debug-trace", 1, nil, ctx)
 	ctx.impl.state = backtrace_create_state("odin-debug-trace", 1, nil, ctx)
 	return ctx.impl.state != nil
 	return ctx.impl.state != nil

+ 4 - 2
core/debug/trace/trace_nil.odin

@@ -1,6 +1,8 @@
 //+build !windows !linux !darwin
 //+build !windows !linux !darwin
 package debug_trace
 package debug_trace
 
 
+import "base:runtime"
+
 _Context :: struct {
 _Context :: struct {
 }
 }
 
 
@@ -10,9 +12,9 @@ _init :: proc(ctx: ^Context) -> (ok: bool) {
 _destroy :: proc(ctx: ^Context) -> bool {
 _destroy :: proc(ctx: ^Context) -> bool {
 	return true
 	return true
 }
 }
-_frames :: proc(ctx: ^Context, skip: uint, allocator: runtime.Allocator) -> []Frame {
+_frames :: proc(ctx: ^Context, skip: uint, frames_buffer: []Frame) -> []Frame {
 	return nil
 	return nil
 }
 }
-_resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (result: runtime.Source_Code_Location) {
+_resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (result: Frame_Location) {
 	return
 	return
 }
 }

+ 5 - 13
core/dynlib/lib.odin

@@ -16,15 +16,12 @@ Library :: distinct rawptr
 Loads a dynamic library from the filesystem. The paramater `global_symbols` makes the symbols in the loaded
 Loads a dynamic library from the filesystem. The paramater `global_symbols` makes the symbols in the loaded
 library available to resolve references in subsequently loaded libraries.
 library available to resolve references in subsequently loaded libraries.
 
 
-The paramater `global_symbols` is only used for the platforms `linux`, `darwin`, `freebsd` and `openbsd`.
+The parameter `global_symbols` is only used for the platforms `linux`, `darwin`, `freebsd` and `openbsd`.
 On `windows` this paramater is ignored.
 On `windows` this paramater is ignored.
 
 
 The underlying behaviour is platform specific.
 The underlying behaviour is platform specific.
 On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlopen`.
 On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlopen`.
-On `windows` refer to `LoadLibraryW`.
-
-**Implicit Allocators**
-`context.temp_allocator`
+On `windows` refer to `LoadLibraryW`. Also temporarily needs an allocator to convert a string.
 
 
 Example:
 Example:
 	import "core:dynlib"
 	import "core:dynlib"
@@ -79,10 +76,7 @@ Loads the address of a procedure/variable from a dynamic library.
 
 
 The underlying behaviour is platform specific.
 The underlying behaviour is platform specific.
 On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`.
 On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`.
-On `windows` refer to `GetProcAddress`.
-
-**Implicit Allocators**
-`context.temp_allocator`
+On `windows` refer to `GetProcAddress`. Also temporarily needs an allocator to convert a string.
 
 
 Example:
 Example:
 	import "core:dynlib"
 	import "core:dynlib"
@@ -177,9 +171,7 @@ initialize_symbols :: proc(
 	return count, count > 0
 	return count, count > 0
 }
 }
 
 
-/*
-Returns an error message for the last failed procedure call.
-*/
+// Returns an error message for the last failed procedure call.
 last_error :: proc() -> string {
 last_error :: proc() -> string {
 	return _last_error()
 	return _last_error()
-}
+}

+ 1 - 1
core/dynlib/lib_js.odin

@@ -16,4 +16,4 @@ _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found
 
 
 _last_error :: proc() -> string {
 _last_error :: proc() -> string {
 	return ""
 	return ""
-}
+}

+ 1 - 1
core/dynlib/lib_unix.odin

@@ -26,4 +26,4 @@ _symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found
 _last_error :: proc() -> string {
 _last_error :: proc() -> string {
 	err := os.dlerror()
 	err := os.dlerror()
 	return "unknown" if err == "" else err
 	return "unknown" if err == "" else err
-}
+}

+ 7 - 9
core/dynlib/lib_windows.odin

@@ -4,14 +4,12 @@ package dynlib
 
 
 import win32 "core:sys/windows"
 import win32 "core:sys/windows"
 import "core:strings"
 import "core:strings"
-import "base:runtime"
 import "core:reflect"
 import "core:reflect"
 
 
-_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
+_load_library :: proc(path: string, global_symbols := false, allocator := context.temp_allocator) -> (Library, bool) {
 	// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
 	// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
-
-	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-	wide_path := win32.utf8_to_wstring(path, context.temp_allocator)
+	wide_path := win32.utf8_to_wstring(path, allocator)
+	defer free(wide_path, allocator)
 	handle := cast(Library)win32.LoadLibraryW(wide_path)
 	handle := cast(Library)win32.LoadLibraryW(wide_path)
 	return handle, handle != nil
 	return handle, handle != nil
 }
 }
@@ -21,9 +19,9 @@ _unload_library :: proc(library: Library) -> bool {
 	return bool(ok)
 	return bool(ok)
 }
 }
 
 
-_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
-	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-	c_str := strings.clone_to_cstring(symbol, context.temp_allocator)
+_symbol_address :: proc(library: Library, symbol: string, allocator := context.temp_allocator) -> (ptr: rawptr, found: bool) {
+	c_str := strings.clone_to_cstring(symbol, allocator)
+	defer delete(c_str, allocator)
 	ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str)
 	ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str)
 	found = ptr != nil
 	found = ptr != nil
 	return
 	return
@@ -33,4 +31,4 @@ _last_error :: proc() -> string {
 	err := win32.System_Error(win32.GetLastError())
 	err := win32.System_Error(win32.GetLastError())
 	err_msg := reflect.enum_string(err)
 	err_msg := reflect.enum_string(err)
 	return "unknown" if err_msg == "" else err_msg
 	return "unknown" if err_msg == "" else err_msg
-}
+}

+ 116 - 116
core/encoding/base32/base32.odin

@@ -8,141 +8,141 @@ package encoding_base32
 // truncate it from the encoded output.
 // truncate it from the encoded output.
 
 
 ENC_TABLE := [32]byte {
 ENC_TABLE := [32]byte {
-    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-    'Y', 'Z', '2', '3', '4', '5', '6', '7',
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', '2', '3', '4', '5', '6', '7',
 }
 }
 
 
 PADDING :: '='
 PADDING :: '='
 
 
 DEC_TABLE := [?]u8 {
 DEC_TABLE := [?]u8 {
-     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, 26, 27, 28, 29, 30, 31,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
-     0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  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,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0, 26, 27, 28, 29, 30, 31,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
+	 0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  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,
 }
 }
 
 
 encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
 encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
-    out_length := (len(data) + 4) / 5 * 8
-    out := make([]byte, out_length)
-    _encode(out, data)
-    return string(out)
+	out_length := (len(data) + 4) / 5 * 8
+	out := make([]byte, out_length)
+	_encode(out, data)
+	return string(out)
 }
 }
 
 
 @private
 @private
 _encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
 _encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
-    out := out
-    data := data
+	out := out
+	data := data
 
 
-    for len(data) > 0 {
-        carry: byte
-        switch len(data) {
-            case:
-                out[7] = ENC_TABLE[data[4] & 0x1f]
-                carry = data[4] >> 5
-                fallthrough
-            case 4:
-                out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f]
-                out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f]
-                carry = data[3] >> 7
-                fallthrough
-            case 3:
-                out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f]
-                carry = (data[2] >> 4) & 0x1f
-                fallthrough
-            case 2:
-                out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f]
-                out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f]
-                carry = (data[1] >> 6) & 0x1f
-                fallthrough
-            case 1:
-                out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f]
-                out[0] = ENC_TABLE[data[0] >> 3]
-        }
+	for len(data) > 0 {
+		carry: byte
+		switch len(data) {
+		case:
+			out[7] = ENC_TABLE[data[4] & 0x1f]
+			carry = data[4] >> 5
+			fallthrough
+		case 4:
+			out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f]
+			out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f]
+			carry = data[3] >> 7
+			fallthrough
+		case 3:
+			out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f]
+			carry = (data[2] >> 4) & 0x1f
+			fallthrough
+		case 2:
+			out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f]
+			out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f]
+			carry = (data[1] >> 6) & 0x1f
+			fallthrough
+		case 1:
+			out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f]
+			out[0] = ENC_TABLE[data[0] >> 3]
+		}
 
 
-        if len(data) < 5 {
-            out[7] = byte(PADDING)
-            if len(data) < 4 {
-                out[6] = byte(PADDING)
-                out[5] = byte(PADDING)
-                if len(data) < 3 {
-                    out[4] = byte(PADDING)
-                    if len(data) < 2 {
-                        out[3] = byte(PADDING)
-                        out[2] = byte(PADDING)
-                    }
-                }
-            }
-            break
-        }
-        data = data[5:]
-        out = out[8:]
-    }
+		if len(data) < 5 {
+			out[7] = byte(PADDING)
+			if len(data) < 4 {
+				out[6] = byte(PADDING)
+				out[5] = byte(PADDING)
+				if len(data) < 3 {
+					out[4] = byte(PADDING)
+					if len(data) < 2 {
+						out[3] = byte(PADDING)
+						out[2] = byte(PADDING)
+					}
+				}
+			}
+			break
+		}
+		data = data[5:]
+		out = out[8:]
+	}
 }
 }
 
 
 decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
 decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
-    if len(data) == 0 {
-        return nil
-    }
+	if len(data) == 0 {
+		return nil
+	}
 
 
-    outi := 0
-    data := data
+	outi := 0
+	data := data
 
 
-    out := make([]byte, len(data) / 8 * 5, allocator)
-    end := false
-    for len(data) > 0 && !end {
-        dbuf : [8]byte
-        dlen := 8
+	out := make([]byte, len(data) / 8 * 5, allocator)
+	end := false
+	for len(data) > 0 && !end {
+		dbuf : [8]byte
+		dlen := 8
 
 
-        for j := 0; j < 8; {
-            if len(data) == 0 {
-                dlen, end = j, true
-                break
-            }
-            input := data[0]
-            data = data[1:]
-            if input == byte(PADDING) && j >= 2 && len(data) < 8 {
-                assert(!(len(data) + j < 8 - 1), "Corrupted input")
-                for k := 0; k < 8-1-j; k +=1 {
-                    assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input")
-                }
-                dlen, end = j, true
-                assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input")
-                break
-            }
-            dbuf[j] = DEC_TABLE[input]
-            assert(dbuf[j] != 0xff, "Corrupted input")
-            j += 1
-        }
+		for j := 0; j < 8; {
+			if len(data) == 0 {
+				dlen, end = j, true
+				break
+			}
+			input := data[0]
+			data = data[1:]
+			if input == byte(PADDING) && j >= 2 && len(data) < 8 {
+				assert(!(len(data) + j < 8 - 1), "Corrupted input")
+				for k := 0; k < 8-1-j; k +=1 {
+					assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input")
+				}
+				dlen, end = j, true
+				assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input")
+				break
+			}
+			dbuf[j] = DEC_TABLE[input]
+			assert(dbuf[j] != 0xff, "Corrupted input")
+			j += 1
+		}
 
 
-        switch dlen {
-            case 8:
-                out[outi + 4] = dbuf[6] << 5 | dbuf[7]
-                fallthrough
-            case 7:
-                out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3
-                fallthrough
-            case 5:
-                out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1
-                fallthrough
-            case 4:
-                out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4
-                fallthrough
-            case 2:
-                out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2
-        }
-        outi += 5
-    }
-    return out
+		switch dlen {
+		case 8:
+			out[outi + 4] = dbuf[6] << 5 | dbuf[7]
+			fallthrough
+		case 7:
+			out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3
+			fallthrough
+		case 5:
+			out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1
+			fallthrough
+		case 4:
+			out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4
+			fallthrough
+		case 2:
+			out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2
+		}
+		outi += 5
+	}
+	return out
 }
 }

+ 16 - 16
core/encoding/cbor/coding.odin

@@ -233,7 +233,7 @@ encode_into_encoder :: proc(e: Encoder, v: Value, loc := #caller_location) -> En
 
 
 	if .Self_Described_CBOR in e.flags {
 	if .Self_Described_CBOR in e.flags {
 		_encode_u64(e, TAG_SELF_DESCRIBED_CBOR, .Tag) or_return
 		_encode_u64(e, TAG_SELF_DESCRIBED_CBOR, .Tag) or_return
-		e.flags &~= { .Self_Described_CBOR }
+		e.flags -= { .Self_Described_CBOR }
 	}
 	}
 
 
 	switch v_spec in v {
 	switch v_spec in v {
@@ -423,7 +423,7 @@ _decode_bytes :: proc(d: Decoder, add: Add, type: Major = .Bytes, allocator := c
 _encode_bytes :: proc(e: Encoder, val: Bytes, major: Major = .Bytes) -> (err: Encode_Error) {
 _encode_bytes :: proc(e: Encoder, val: Bytes, major: Major = .Bytes) -> (err: Encode_Error) {
 	assert(len(val) >= 0)
 	assert(len(val) >= 0)
 	_encode_u64(e, u64(len(val)), major) or_return
 	_encode_u64(e, u64(len(val)), major) or_return
-    _, err = io.write_full(e.writer, val[:])
+	_, err = io.write_full(e.writer, val[:])
 	return
 	return
 }
 }
 
 
@@ -440,7 +440,7 @@ _decode_text :: proc(d: Decoder, add: Add, allocator := context.allocator, loc :
 }
 }
 
 
 _encode_text :: proc(e: Encoder, val: Text) -> Encode_Error {
 _encode_text :: proc(e: Encoder, val: Text) -> Encode_Error {
-    return _encode_bytes(e, transmute([]byte)val, .Text)
+	return _encode_bytes(e, transmute([]byte)val, .Text)
 }
 }
 
 
 _decode_array_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: ^Array, err: Decode_Error) {
 _decode_array_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: ^Array, err: Decode_Error) {
@@ -480,10 +480,10 @@ _decode_array :: proc(d: Decoder, add: Add, allocator := context.allocator, loc
 _encode_array :: proc(e: Encoder, arr: Array) -> Encode_Error {
 _encode_array :: proc(e: Encoder, arr: Array) -> Encode_Error {
 	assert(len(arr) >= 0)
 	assert(len(arr) >= 0)
 	_encode_u64(e, u64(len(arr)), .Array)
 	_encode_u64(e, u64(len(arr)), .Array)
-    for val in arr {
-        encode(e, val) or_return
-    }
-    return nil
+	for val in arr {
+		encode(e, val) or_return
+	}
+	return nil
 }
 }
 
 
 _decode_map_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: ^Map, err: Decode_Error) {
 _decode_map_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: ^Map, err: Decode_Error) {
@@ -576,7 +576,7 @@ _encode_map :: proc(e: Encoder, m: Map) -> (err: Encode_Error) {
 		encode(e, entry.entry.value) or_return
 		encode(e, entry.entry.value) or_return
 	}
 	}
 
 
-    return nil
+	return nil
 }
 }
 
 
 _decode_tag_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: Value, err: Decode_Error) {
 _decode_tag_ptr :: proc(d: Decoder, add: Add, allocator := context.allocator, loc := #caller_location) -> (v: Value, err: Decode_Error) {
@@ -626,7 +626,7 @@ _decode_uint_as_u64 :: proc(r: io.Reader, add: Add) -> (nr: u64, err: Decode_Err
 
 
 _encode_tag :: proc(e: Encoder, val: Tag) -> Encode_Error {
 _encode_tag :: proc(e: Encoder, val: Tag) -> Encode_Error {
 	_encode_u64(e, val.number, .Tag) or_return
 	_encode_u64(e, val.number, .Tag) or_return
-    return encode(e, val.value)
+	return encode(e, val.value)
 }
 }
 
 
 _decode_simple :: proc(r: io.Reader) -> (v: Simple, err: io.Error) {
 _decode_simple :: proc(r: io.Reader) -> (v: Simple, err: io.Error) {
@@ -739,16 +739,16 @@ _encode_nil :: proc(w: io.Writer) -> io.Error {
 // Streaming
 // Streaming
 
 
 encode_stream_begin :: proc(w: io.Writer, major: Major) -> (err: io.Error) {
 encode_stream_begin :: proc(w: io.Writer, major: Major) -> (err: io.Error) {
-    assert(major >= Major(.Bytes) && major <= Major(.Map), "illegal stream type")
+	assert(major >= Major(.Bytes) && major <= Major(.Map), "illegal stream type")
 
 
-    header := (u8(major) << 5) | u8(Add.Length_Unknown)
-    _, err = io.write_full(w, {header})
+	header := (u8(major) << 5) | u8(Add.Length_Unknown)
+	_, err = io.write_full(w, {header})
 	return
 	return
 }
 }
 
 
 encode_stream_end :: proc(w: io.Writer) -> io.Error {
 encode_stream_end :: proc(w: io.Writer) -> io.Error {
-    header := (u8(Major.Other) << 5) | u8(Add.Break)
-    _, err := io.write_full(w, {header})
+	header := (u8(Major.Other) << 5) | u8(Add.Break)
+	_, err := io.write_full(w, {header})
 	return err
 	return err
 }
 }
 
 
@@ -757,8 +757,8 @@ encode_stream_text       :: _encode_text
 encode_stream_array_item :: encode
 encode_stream_array_item :: encode
 
 
 encode_stream_map_entry :: proc(e: Encoder, key: Value, val: Value) -> Encode_Error {
 encode_stream_map_entry :: proc(e: Encoder, key: Value, val: Value) -> Encode_Error {
-    encode(e, key) or_return
-    return encode(e, val)
+	encode(e, key) or_return
+	return encode(e, val)
 }
 }
 
 
 // For `Bytes` and `Text` strings: Decodes the number of items the header says follows.
 // For `Bytes` and `Text` strings: Decodes the number of items the header says follows.

+ 33 - 5
core/encoding/cbor/doc.odin

@@ -77,8 +77,11 @@ You can look at the default tags provided for pointers on how these implementati
 Example:
 Example:
 	package main
 	package main
 
 
+	import "base:intrinsics"
+
 	import "core:encoding/cbor"
 	import "core:encoding/cbor"
 	import "core:fmt"
 	import "core:fmt"
+	import "core:reflect"
 	import "core:time"
 	import "core:time"
 
 
 	Possibilities :: union {
 	Possibilities :: union {
@@ -93,9 +96,32 @@ Example:
 		ignore_this: ^Data `cbor:"-"`,     // Ignored by implementation.
 		ignore_this: ^Data `cbor:"-"`,     // Ignored by implementation.
 		renamed: f32 `cbor:"renamed :)"`,  // Renamed when encoded.
 		renamed: f32 `cbor:"renamed :)"`,  // Renamed when encoded.
 		my_union: Possibilities,           // Union support.
 		my_union: Possibilities,           // Union support.
+
+		my_raw: [8]u32 `cbor_tag:"raw"`, // Custom tag that just writes the value as bytes.
 	}
 	}
 
 
 	main :: proc() {
 	main :: proc() {
+		// Example custom tag implementation that instead of breaking down all parts,
+		// just writes the value as a big byte blob. This is an advanced feature but very powerful.
+		RAW_TAG_NR :: 200
+		cbor.tag_register_number({
+			marshal = proc(_: ^cbor.Tag_Implementation, e: cbor.Encoder, v: any) -> cbor.Marshal_Error {
+				cbor._encode_u8(e.writer, RAW_TAG_NR, .Tag) or_return
+				return cbor.err_conv(cbor._encode_bytes(e, reflect.as_bytes(v)))
+			},
+			unmarshal = proc(_: ^cbor.Tag_Implementation, d: cbor.Decoder, _: cbor.Tag_Number, v: any) -> (cbor.Unmarshal_Error) {
+				hdr := cbor._decode_header(d.reader) or_return
+				maj, add := cbor._header_split(hdr)
+				if maj != .Bytes {
+					return .Bad_Tag_Value
+				}
+
+				bytes := cbor.err_conv(cbor._decode_bytes(d, add, maj)) or_return
+				intrinsics.mem_copy_non_overlapping(v.data, raw_data(bytes), len(bytes))
+				return nil
+			},
+		}, RAW_TAG_NR, "raw")
+
 		now := time.Time{_nsec = 1701117968 * 1e9}
 		now := time.Time{_nsec = 1701117968 * 1e9}
 
 
 		data := Data{
 		data := Data{
@@ -105,21 +131,22 @@ Example:
 			ignore_this = &Data{},
 			ignore_this = &Data{},
 			renamed     = 123123.125,
 			renamed     = 123123.125,
 			my_union    = 3,
 			my_union    = 3,
+			my_raw      = {1=1, 2=2, 3=3},
 		}
 		}
-		
+
 		// Marshal the struct into binary CBOR.
 		// Marshal the struct into binary CBOR.
 		binary, err := cbor.marshal(data, cbor.ENCODE_FULLY_DETERMINISTIC)
 		binary, err := cbor.marshal(data, cbor.ENCODE_FULLY_DETERMINISTIC)
-		assert(err == nil)
+		fmt.assertf(err == nil, "marshal error: %v", err)
 		defer delete(binary)
 		defer delete(binary)
-		
+
 		// Decode the binary data into a `cbor.Value`.
 		// Decode the binary data into a `cbor.Value`.
 		decoded, derr := cbor.decode(string(binary))
 		decoded, derr := cbor.decode(string(binary))
-		assert(derr == nil)
+		fmt.assertf(derr == nil, "decode error: %v", derr)
 		defer cbor.destroy(decoded)
 		defer cbor.destroy(decoded)
 
 
 		// Turn the CBOR into a human readable representation defined as the diagnostic format in [[RFC 8949 Section 8;https://www.rfc-editor.org/rfc/rfc8949.html#name-diagnostic-notation]].
 		// Turn the CBOR into a human readable representation defined as the diagnostic format in [[RFC 8949 Section 8;https://www.rfc-editor.org/rfc/rfc8949.html#name-diagnostic-notation]].
 		diagnosis, eerr := cbor.to_diagnostic_format(decoded)
 		diagnosis, eerr := cbor.to_diagnostic_format(decoded)
-		assert(eerr == nil)
+		fmt.assertf(eerr == nil, "to diagnostic error: %v", eerr)
 		defer delete(diagnosis)
 		defer delete(diagnosis)
 
 
 		fmt.println(diagnosis)
 		fmt.println(diagnosis)
@@ -127,6 +154,7 @@ Example:
 
 
 Output:
 Output:
 	{
 	{
+		"my_raw": 200(h'00001000200030000000000000000000'),
 		"my_union": 1010([
 		"my_union": 1010([
 			"int",
 			"int",
 			3
 			3

+ 57 - 17
core/encoding/cbor/marshal.odin

@@ -54,7 +54,7 @@ marshal_into_bytes :: proc(v: any, flags := ENCODE_SMALL, allocator := context.a
 
 
 	defer if err != nil { strings.builder_destroy(&b) }
 	defer if err != nil { strings.builder_destroy(&b) }
 
 
-	if err = marshal_into_builder(&b, v, flags, temp_allocator, loc=loc); err != nil {
+	if err = marshal_into_builder(&b, v, flags, temp_allocator); err != nil {
 		return
 		return
 	}
 	}
 
 
@@ -63,20 +63,20 @@ marshal_into_bytes :: proc(v: any, flags := ENCODE_SMALL, allocator := context.a
 
 
 // Marshals the given value into a CBOR byte stream written to the given builder.
 // Marshals the given value into a CBOR byte stream written to the given builder.
 // See docs on the `marshal_into` proc group for more info.
 // See docs on the `marshal_into` proc group for more info.
-marshal_into_builder :: proc(b: ^strings.Builder, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator, loc := #caller_location) -> Marshal_Error {
-	return marshal_into_writer(strings.to_writer(b), v, flags, temp_allocator, loc=loc)
+marshal_into_builder :: proc(b: ^strings.Builder, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator) -> Marshal_Error {
+	return marshal_into_writer(strings.to_writer(b), v, flags, temp_allocator)
 }
 }
 
 
 // Marshals the given value into a CBOR byte stream written to the given writer.
 // Marshals the given value into a CBOR byte stream written to the given writer.
 // See docs on the `marshal_into` proc group for more info.
 // See docs on the `marshal_into` proc group for more info.
-marshal_into_writer :: proc(w: io.Writer, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator, loc := #caller_location) -> Marshal_Error {
+marshal_into_writer :: proc(w: io.Writer, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator) -> Marshal_Error {
 	encoder := Encoder{flags, w, temp_allocator}
 	encoder := Encoder{flags, w, temp_allocator}
-	return marshal_into_encoder(encoder, v, loc=loc)
+	return marshal_into_encoder(encoder, v)
 }
 }
 
 
 // Marshals the given value into a CBOR byte stream written to the given encoder.
 // Marshals the given value into a CBOR byte stream written to the given encoder.
 // See docs on the `marshal_into` proc group for more info.
 // See docs on the `marshal_into` proc group for more info.
-marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (err: Marshal_Error) {
+marshal_into_encoder :: proc(e: Encoder, v: any) -> (err: Marshal_Error) {
 	e := e
 	e := e
 
 
 	if e.temp_allocator.procedure == nil {
 	if e.temp_allocator.procedure == nil {
@@ -85,7 +85,7 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 
 	if .Self_Described_CBOR in e.flags {
 	if .Self_Described_CBOR in e.flags {
 		err_conv(_encode_u64(e, TAG_SELF_DESCRIBED_CBOR, .Tag)) or_return
 		err_conv(_encode_u64(e, TAG_SELF_DESCRIBED_CBOR, .Tag)) or_return
-		e.flags &~= { .Self_Described_CBOR }
+		e.flags -= { .Self_Described_CBOR }
 	}
 	}
 
 
 	if v == nil {
 	if v == nil {
@@ -97,11 +97,14 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 		return impl->marshal(e, v)
 		return impl->marshal(e, v)
 	}
 	}
 
 
-	ti := runtime.type_info_base(type_info_of(v.id))
-	a := any{v.data, ti.id}
+	ti := runtime.type_info_core(type_info_of(v.id))
+	return _marshal_into_encoder(e, v, ti)
+}
 
 
+_marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (err: Marshal_Error) {
+	a := any{v.data, ti.id}
 	#partial switch info in ti.variant {
 	#partial switch info in ti.variant {
-	case runtime.Type_Info_Named:
+	case runtime.Type_Info_Named, runtime.Type_Info_Enum, runtime.Type_Info_Bit_Field:
 		unreachable()
 		unreachable()
 
 
 	case runtime.Type_Info_Pointer:
 	case runtime.Type_Info_Pointer:
@@ -223,18 +226,38 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 		}
 		}
 
 
 		err_conv(_encode_u64(e, u64(info.count), .Array)) or_return
 		err_conv(_encode_u64(e, u64(info.count), .Array)) or_return
+
+		if impl, ok := _tag_implementations_type[info.elem.id]; ok {
+			for i in 0..<info.count {
+				data := uintptr(v.data) + uintptr(i*info.elem_size)
+				impl->marshal(e, any{rawptr(data), info.elem.id}) or_return
+			}
+			return
+		}
+
+		elem_ti := runtime.type_info_core(type_info_of(info.elem.id))
 		for i in 0..<info.count {
 		for i in 0..<info.count {
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
-			marshal_into(e, any{rawptr(data), info.elem.id}) or_return
+			_marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return
 		}
 		}
 		return
 		return
 
 
 	case runtime.Type_Info_Enumerated_Array:
 	case runtime.Type_Info_Enumerated_Array:
 		// index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum)
 		// index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum)
 		err_conv(_encode_u64(e, u64(info.count), .Array)) or_return
 		err_conv(_encode_u64(e, u64(info.count), .Array)) or_return
+
+		if impl, ok := _tag_implementations_type[info.elem.id]; ok {
+			for i in 0..<info.count {
+				data := uintptr(v.data) + uintptr(i*info.elem_size)
+				impl->marshal(e, any{rawptr(data), info.elem.id}) or_return
+			}
+			return
+		}
+
+		elem_ti := runtime.type_info_core(type_info_of(info.elem.id))
 		for i in 0..<info.count {
 		for i in 0..<info.count {
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
-			marshal_into(e, any{rawptr(data), info.elem.id}) or_return
+			_marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return
 		}
 		}
 		return
 		return
 		
 		
@@ -246,9 +269,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 
 		array := (^mem.Raw_Dynamic_Array)(v.data)
 		array := (^mem.Raw_Dynamic_Array)(v.data)
 		err_conv(_encode_u64(e, u64(array.len), .Array)) or_return
 		err_conv(_encode_u64(e, u64(array.len), .Array)) or_return
+
+		if impl, ok := _tag_implementations_type[info.elem.id]; ok {
+			for i in 0..<array.len {
+				data := uintptr(array.data) + uintptr(i*info.elem_size)
+				impl->marshal(e, any{rawptr(data), info.elem.id}) or_return
+			}
+			return
+		}
+
+		elem_ti := runtime.type_info_core(type_info_of(info.elem.id))
 		for i in 0..<array.len {
 		for i in 0..<array.len {
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
-			marshal_into(e, any{rawptr(data), info.elem.id}) or_return
+			_marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return
 		}
 		}
 		return
 		return
 
 
@@ -260,9 +293,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 
 		array := (^mem.Raw_Slice)(v.data)
 		array := (^mem.Raw_Slice)(v.data)
 		err_conv(_encode_u64(e, u64(array.len), .Array)) or_return
 		err_conv(_encode_u64(e, u64(array.len), .Array)) or_return
+
+		if impl, ok := _tag_implementations_type[info.elem.id]; ok {
+			for i in 0..<array.len {
+				data := uintptr(array.data) + uintptr(i*info.elem_size)
+				impl->marshal(e, any{rawptr(data), info.elem.id}) or_return
+			}
+			return
+		}
+
+		elem_ti := runtime.type_info_core(type_info_of(info.elem.id))
 		for i in 0..<array.len {
 		for i in 0..<array.len {
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
-			marshal_into(e, any{rawptr(data), info.elem.id}) or_return
+			_marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return
 		}
 		}
 		return
 		return
 
 
@@ -542,9 +585,6 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 
 		return marshal_into(e, any{v.data, vti.id})
 		return marshal_into(e, any{v.data, vti.id})
 
 
-	case runtime.Type_Info_Enum:
-		return marshal_into(e, any{v.data, info.base.id})
-
 	case runtime.Type_Info_Bit_Set:
 	case runtime.Type_Info_Bit_Set:
 		// Store bit_set as big endian just like the protocol.
 		// Store bit_set as big endian just like the protocol.
 		do_byte_swap := !reflect.bit_set_is_big_endian(v)
 		do_byte_swap := !reflect.bit_set_is_big_endian(v)

+ 0 - 1
core/encoding/cbor/tags.odin

@@ -95,7 +95,6 @@ tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string
 }
 }
 
 
 // Controls initialization of default tag implementations.
 // Controls initialization of default tag implementations.
-// JS and WASI default to a panic allocator so we don't want to do it on those.
 INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR)
 INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR)
 
 
 @(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)
 @(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)

+ 13 - 21
core/encoding/cbor/unmarshal.odin

@@ -273,13 +273,13 @@ _unmarshal_value :: proc(d: Decoder, v: any, hdr: Header, allocator := context.a
 
 
 		 // NOTE: Because this is a special type and not to be treated as a general integer,
 		 // NOTE: Because this is a special type and not to be treated as a general integer,
 		 // We only put the value of it in fields that are explicitly of type `Simple`.
 		 // We only put the value of it in fields that are explicitly of type `Simple`.
-		 switch &dst in v {
-		 case Simple:
-			 dst = decoded
-			 return
-		 case:
-		 	return _unsupported(v, hdr, add)
-		 }
+		switch &dst in v {
+		case Simple:
+			dst = decoded
+			return
+		case:
+			return _unsupported(v, hdr, add)
+		}
 
 
 	case .Tag:
 	case .Tag:
 		switch &dst in v {
 		switch &dst in v {
@@ -520,9 +520,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 		return
 
 
 	case reflect.Type_Info_Array:
 	case reflect.Type_Info_Array:
-		_, scap := err_conv(_decode_len_container(d, add)) or_return
-		length := min(scap, t.count)
-	
+		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		if length > t.count {
 		if length > t.count {
 			return _unsupported(v, hdr)
 			return _unsupported(v, hdr)
 		}
 		}
@@ -534,9 +532,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 		return
 
 
 	case reflect.Type_Info_Enumerated_Array:
 	case reflect.Type_Info_Enumerated_Array:
-		_, scap := err_conv(_decode_len_container(d, add)) or_return
-		length := min(scap, t.count)
-	
+		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		if length > t.count {
 		if length > t.count {
 			return _unsupported(v, hdr)
 			return _unsupported(v, hdr)
 		}
 		}
@@ -548,9 +544,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 		return
 
 
 	case reflect.Type_Info_Complex:
 	case reflect.Type_Info_Complex:
-		_, scap := err_conv(_decode_len_container(d, add)) or_return
-		length := min(scap, 2)
-	
+		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		if length > 2 {
 		if length > 2 {
 			return _unsupported(v, hdr)
 			return _unsupported(v, hdr)
 		}
 		}
@@ -570,9 +564,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 		return
 	
 	
 	case reflect.Type_Info_Quaternion:
 	case reflect.Type_Info_Quaternion:
-		_, scap := err_conv(_decode_len_container(d, add)) or_return
-		length := min(scap, 4)
-	
+		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		if length > 4 {
 		if length > 4 {
 			return _unsupported(v, hdr)
 			return _unsupported(v, hdr)
 		}
 		}
@@ -633,7 +625,7 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
 		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		length, _ := err_conv(_decode_len_container(d, add)) or_return
 		unknown := length == -1
 		unknown := length == -1
 		fields := reflect.struct_fields_zipped(ti.id)
 		fields := reflect.struct_fields_zipped(ti.id)
-	
+
 		for idx := 0; idx < len(fields) && (unknown || idx < length); idx += 1 {
 		for idx := 0; idx < len(fields) && (unknown || idx < length); idx += 1 {
 			// Decode key, keys can only be strings.
 			// Decode key, keys can only be strings.
 			key: string
 			key: string
@@ -646,7 +638,7 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
 				key = keyv
 				key = keyv
 			}
 			}
 			defer delete(key, context.temp_allocator)
 			defer delete(key, context.temp_allocator)
-			
+
 			// Find matching field.
 			// Find matching field.
 			use_field_idx := -1
 			use_field_idx := -1
 			{
 			{

+ 4 - 2
core/encoding/csv/reader.odin

@@ -138,7 +138,9 @@ iterator_next :: proc(r: ^Reader) -> (record: []string, idx: int, err: Error, mo
 	return record, r.line_count - 1, r.last_iterator_error, r.last_iterator_error == nil
 	return record, r.line_count - 1, r.last_iterator_error, r.last_iterator_error == nil
 }
 }
 
 
-// Get last error if we the iterator
+// Get last CSV parse error if we ignored it in the iterator loop
+//
+// for record, row_idx in csv.iterator_next(&r) { ... }
 iterator_last_error :: proc(r: Reader) -> (err: Error) {
 iterator_last_error :: proc(r: Reader) -> (err: Error) {
 	return r.last_iterator_error
 	return r.last_iterator_error
 }
 }
@@ -169,7 +171,7 @@ is_io_error :: proc(err: Error, io_err: io.Error) -> bool {
 
 
 // read_all reads all the remaining records from r.
 // read_all reads all the remaining records from r.
 // Each record is a slice of fields.
 // Each record is a slice of fields.
-// read_all is defined to read until an EOF, and does not treat, and does not treat EOF as an error
+// read_all is defined to read until an EOF, and does not treat EOF as an error
 @(require_results)
 @(require_results)
 read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) {
 read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) {
 	context.allocator = allocator
 	context.allocator = allocator

+ 4816 - 4816
core/encoding/entity/generated.odin

@@ -61,5026 +61,5026 @@ named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) {
 
 
 	case 'A':
 	case 'A':
 		switch name {
 		switch name {
-			case "AElig":                           // LATIN CAPITAL LETTER AE
-				return rune(0xc6), true
-			case "AMP":                             // AMPERSAND
-				return rune(0x26), true
-			case "Aacgr":                           // GREEK CAPITAL LETTER ALPHA WITH TONOS
-				return rune(0x0386), true
-			case "Aacute":                          // LATIN CAPITAL LETTER A WITH ACUTE
-				return rune(0xc1), true
-			case "Abreve":                          // LATIN CAPITAL LETTER A WITH BREVE
-				return rune(0x0102), true
-			case "Acirc":                           // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
-				return rune(0xc2), true
-			case "Acy":                             // CYRILLIC CAPITAL LETTER A
-				return rune(0x0410), true
-			case "Afr":                             // MATHEMATICAL FRAKTUR CAPITAL A
-				return rune(0x01d504), true
-			case "Agr":                             // GREEK CAPITAL LETTER ALPHA
-				return rune(0x0391), true
-			case "Agrave":                          // LATIN CAPITAL LETTER A WITH GRAVE
-				return rune(0xc0), true
-			case "Alpha":                           // GREEK CAPITAL LETTER ALPHA
-				return rune(0x0391), true
-			case "Amacr":                           // LATIN CAPITAL LETTER A WITH MACRON
-				return rune(0x0100), true
-			case "And":                             // DOUBLE LOGICAL AND
-				return rune(0x2a53), true
-			case "Aogon":                           // LATIN CAPITAL LETTER A WITH OGONEK
-				return rune(0x0104), true
-			case "Aopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL A
-				return rune(0x01d538), true
-			case "ApplyFunction":                   // FUNCTION APPLICATION
-				return rune(0x2061), true
-			case "Aring":                           // LATIN CAPITAL LETTER A WITH RING ABOVE
-				return rune(0xc5), true
-			case "Ascr":                            // MATHEMATICAL SCRIPT CAPITAL A
-				return rune(0x01d49c), true
-			case "Assign":                          // COLON EQUALS
-				return rune(0x2254), true
-			case "Ast":                             // TWO ASTERISKS ALIGNED VERTICALLY
-				return rune(0x2051), true
-			case "Atilde":                          // LATIN CAPITAL LETTER A WITH TILDE
-				return rune(0xc3), true
-			case "Auml":                            // LATIN CAPITAL LETTER A WITH DIAERESIS
-				return rune(0xc4), true
+		case "AElig":                           // LATIN CAPITAL LETTER AE
+			return rune(0xc6), true
+		case "AMP":                             // AMPERSAND
+			return rune(0x26), true
+		case "Aacgr":                           // GREEK CAPITAL LETTER ALPHA WITH TONOS
+			return rune(0x0386), true
+		case "Aacute":                          // LATIN CAPITAL LETTER A WITH ACUTE
+			return rune(0xc1), true
+		case "Abreve":                          // LATIN CAPITAL LETTER A WITH BREVE
+			return rune(0x0102), true
+		case "Acirc":                           // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+			return rune(0xc2), true
+		case "Acy":                             // CYRILLIC CAPITAL LETTER A
+			return rune(0x0410), true
+		case "Afr":                             // MATHEMATICAL FRAKTUR CAPITAL A
+			return rune(0x01d504), true
+		case "Agr":                             // GREEK CAPITAL LETTER ALPHA
+			return rune(0x0391), true
+		case "Agrave":                          // LATIN CAPITAL LETTER A WITH GRAVE
+			return rune(0xc0), true
+		case "Alpha":                           // GREEK CAPITAL LETTER ALPHA
+			return rune(0x0391), true
+		case "Amacr":                           // LATIN CAPITAL LETTER A WITH MACRON
+			return rune(0x0100), true
+		case "And":                             // DOUBLE LOGICAL AND
+			return rune(0x2a53), true
+		case "Aogon":                           // LATIN CAPITAL LETTER A WITH OGONEK
+			return rune(0x0104), true
+		case "Aopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL A
+			return rune(0x01d538), true
+		case "ApplyFunction":                   // FUNCTION APPLICATION
+			return rune(0x2061), true
+		case "Aring":                           // LATIN CAPITAL LETTER A WITH RING ABOVE
+			return rune(0xc5), true
+		case "Ascr":                            // MATHEMATICAL SCRIPT CAPITAL A
+			return rune(0x01d49c), true
+		case "Assign":                          // COLON EQUALS
+			return rune(0x2254), true
+		case "Ast":                             // TWO ASTERISKS ALIGNED VERTICALLY
+			return rune(0x2051), true
+		case "Atilde":                          // LATIN CAPITAL LETTER A WITH TILDE
+			return rune(0xc3), true
+		case "Auml":                            // LATIN CAPITAL LETTER A WITH DIAERESIS
+			return rune(0xc4), true
 		}
 		}
 
 
 	case 'B':
 	case 'B':
 		switch name {
 		switch name {
-			case "Backslash":                       // SET MINUS
-				return rune(0x2216), true
-			case "Barint":                          // INTEGRAL WITH DOUBLE STROKE
-				return rune(0x2a0e), true
-			case "Barv":                            // SHORT DOWN TACK WITH OVERBAR
-				return rune(0x2ae7), true
-			case "Barwed":                          // PERSPECTIVE
-				return rune(0x2306), true
-			case "Barwedl":                         // LOGICAL AND WITH DOUBLE OVERBAR
-				return rune(0x2a5e), true
-			case "Bcy":                             // CYRILLIC CAPITAL LETTER BE
-				return rune(0x0411), true
-			case "Because":                         // BECAUSE
-				return rune(0x2235), true
-			case "Bernoullis":                      // SCRIPT CAPITAL B
-				return rune(0x212c), true
-			case "Beta":                            // GREEK CAPITAL LETTER BETA
-				return rune(0x0392), true
-			case "Bfr":                             // MATHEMATICAL FRAKTUR CAPITAL B
-				return rune(0x01d505), true
-			case "Bgr":                             // GREEK CAPITAL LETTER BETA
-				return rune(0x0392), true
-			case "Bopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL B
-				return rune(0x01d539), true
-			case "Breve":                           // BREVE
-				return rune(0x02d8), true
-			case "Bscr":                            // SCRIPT CAPITAL B
-				return rune(0x212c), true
-			case "Bumpeq":                          // GEOMETRICALLY EQUIVALENT TO
-				return rune(0x224e), true
-			case "Bvert":                           // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
-				return rune(0x2506), true
+		case "Backslash":                       // SET MINUS
+			return rune(0x2216), true
+		case "Barint":                          // INTEGRAL WITH DOUBLE STROKE
+			return rune(0x2a0e), true
+		case "Barv":                            // SHORT DOWN TACK WITH OVERBAR
+			return rune(0x2ae7), true
+		case "Barwed":                          // PERSPECTIVE
+			return rune(0x2306), true
+		case "Barwedl":                         // LOGICAL AND WITH DOUBLE OVERBAR
+			return rune(0x2a5e), true
+		case "Bcy":                             // CYRILLIC CAPITAL LETTER BE
+			return rune(0x0411), true
+		case "Because":                         // BECAUSE
+			return rune(0x2235), true
+		case "Bernoullis":                      // SCRIPT CAPITAL B
+			return rune(0x212c), true
+		case "Beta":                            // GREEK CAPITAL LETTER BETA
+			return rune(0x0392), true
+		case "Bfr":                             // MATHEMATICAL FRAKTUR CAPITAL B
+			return rune(0x01d505), true
+		case "Bgr":                             // GREEK CAPITAL LETTER BETA
+			return rune(0x0392), true
+		case "Bopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+			return rune(0x01d539), true
+		case "Breve":                           // BREVE
+			return rune(0x02d8), true
+		case "Bscr":                            // SCRIPT CAPITAL B
+			return rune(0x212c), true
+		case "Bumpeq":                          // GEOMETRICALLY EQUIVALENT TO
+			return rune(0x224e), true
+		case "Bvert":                           // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
+			return rune(0x2506), true
 		}
 		}
 
 
 	case 'C':
 	case 'C':
 		switch name {
 		switch name {
-			case "CHcy":                            // CYRILLIC CAPITAL LETTER CHE
-				return rune(0x0427), true
-			case "COPY":                            // COPYRIGHT SIGN
-				return rune(0xa9), true
-			case "Cacute":                          // LATIN CAPITAL LETTER C WITH ACUTE
-				return rune(0x0106), true
-			case "Cap":                             // DOUBLE INTERSECTION
-				return rune(0x22d2), true
-			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
-				return rune(0x010c), true
-			case "Ccedil":                          // LATIN CAPITAL LETTER C WITH CEDILLA
-				return rune(0xc7), true
-			case "Ccirc":                           // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
-				return rune(0x0108), true
-			case "Cconint":                         // VOLUME INTEGRAL
-				return rune(0x2230), true
-			case "Cdot":                            // LATIN CAPITAL LETTER C WITH DOT ABOVE
-				return rune(0x010a), true
-			case "Cedilla":                         // CEDILLA
-				return rune(0xb8), true
-			case "CenterDot":                       // MIDDLE DOT
-				return rune(0xb7), true
-			case "Cfr":                             // BLACK-LETTER CAPITAL C
-				return rune(0x212d), true
-			case "Chi":                             // GREEK CAPITAL LETTER CHI
-				return rune(0x03a7), true
-			case "CircleDot":                       // CIRCLED DOT OPERATOR
-				return rune(0x2299), true
-			case "CircleMinus":                     // CIRCLED MINUS
-				return rune(0x2296), true
-			case "CirclePlus":                      // CIRCLED PLUS
-				return rune(0x2295), true
-			case "CircleTimes":                     // CIRCLED TIMES
-				return rune(0x2297), true
-			case "ClockwiseContourIntegral":        // CLOCKWISE CONTOUR INTEGRAL
-				return rune(0x2232), true
-			case "CloseCurlyDoubleQuote":           // RIGHT DOUBLE QUOTATION MARK
-				return rune(0x201d), true
-			case "CloseCurlyQuote":                 // RIGHT SINGLE QUOTATION MARK
-				return rune(0x2019), true
-			case "Colon":                           // PROPORTION
-				return rune(0x2237), true
-			case "Colone":                          // DOUBLE COLON EQUAL
-				return rune(0x2a74), true
-			case "Congruent":                       // IDENTICAL TO
-				return rune(0x2261), true
-			case "Conint":                          // SURFACE INTEGRAL
-				return rune(0x222f), true
-			case "ContourIntegral":                 // CONTOUR INTEGRAL
-				return rune(0x222e), true
-			case "Copf":                            // DOUBLE-STRUCK CAPITAL C
-				return rune(0x2102), true
-			case "Coproduct":                       // N-ARY COPRODUCT
-				return rune(0x2210), true
-			case "CounterClockwiseContourIntegral": // ANTICLOCKWISE CONTOUR INTEGRAL
-				return rune(0x2233), true
-			case "Cross":                           // VECTOR OR CROSS PRODUCT
-				return rune(0x2a2f), true
-			case "Cscr":                            // MATHEMATICAL SCRIPT CAPITAL C
-				return rune(0x01d49e), true
-			case "Cup":                             // DOUBLE UNION
-				return rune(0x22d3), true
-			case "CupCap":                          // EQUIVALENT TO
-				return rune(0x224d), true
+		case "CHcy":                            // CYRILLIC CAPITAL LETTER CHE
+			return rune(0x0427), true
+		case "COPY":                            // COPYRIGHT SIGN
+			return rune(0xa9), true
+		case "Cacute":                          // LATIN CAPITAL LETTER C WITH ACUTE
+			return rune(0x0106), true
+		case "Cap":                             // DOUBLE INTERSECTION
+			return rune(0x22d2), true
+		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
+			return rune(0x010c), true
+		case "Ccedil":                          // LATIN CAPITAL LETTER C WITH CEDILLA
+			return rune(0xc7), true
+		case "Ccirc":                           // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+			return rune(0x0108), true
+		case "Cconint":                         // VOLUME INTEGRAL
+			return rune(0x2230), true
+		case "Cdot":                            // LATIN CAPITAL LETTER C WITH DOT ABOVE
+			return rune(0x010a), true
+		case "Cedilla":                         // CEDILLA
+			return rune(0xb8), true
+		case "CenterDot":                       // MIDDLE DOT
+			return rune(0xb7), true
+		case "Cfr":                             // BLACK-LETTER CAPITAL C
+			return rune(0x212d), true
+		case "Chi":                             // GREEK CAPITAL LETTER CHI
+			return rune(0x03a7), true
+		case "CircleDot":                       // CIRCLED DOT OPERATOR
+			return rune(0x2299), true
+		case "CircleMinus":                     // CIRCLED MINUS
+			return rune(0x2296), true
+		case "CirclePlus":                      // CIRCLED PLUS
+			return rune(0x2295), true
+		case "CircleTimes":                     // CIRCLED TIMES
+			return rune(0x2297), true
+		case "ClockwiseContourIntegral":        // CLOCKWISE CONTOUR INTEGRAL
+			return rune(0x2232), true
+		case "CloseCurlyDoubleQuote":           // RIGHT DOUBLE QUOTATION MARK
+			return rune(0x201d), true
+		case "CloseCurlyQuote":                 // RIGHT SINGLE QUOTATION MARK
+			return rune(0x2019), true
+		case "Colon":                           // PROPORTION
+			return rune(0x2237), true
+		case "Colone":                          // DOUBLE COLON EQUAL
+			return rune(0x2a74), true
+		case "Congruent":                       // IDENTICAL TO
+			return rune(0x2261), true
+		case "Conint":                          // SURFACE INTEGRAL
+			return rune(0x222f), true
+		case "ContourIntegral":                 // CONTOUR INTEGRAL
+			return rune(0x222e), true
+		case "Copf":                            // DOUBLE-STRUCK CAPITAL C
+			return rune(0x2102), true
+		case "Coproduct":                       // N-ARY COPRODUCT
+			return rune(0x2210), true
+		case "CounterClockwiseContourIntegral": // ANTICLOCKWISE CONTOUR INTEGRAL
+			return rune(0x2233), true
+		case "Cross":                           // VECTOR OR CROSS PRODUCT
+			return rune(0x2a2f), true
+		case "Cscr":                            // MATHEMATICAL SCRIPT CAPITAL C
+			return rune(0x01d49e), true
+		case "Cup":                             // DOUBLE UNION
+			return rune(0x22d3), true
+		case "CupCap":                          // EQUIVALENT TO
+			return rune(0x224d), true
 		}
 		}
 
 
 	case 'D':
 	case 'D':
 		switch name {
 		switch name {
-			case "DD":                              // DOUBLE-STRUCK ITALIC CAPITAL D
-				return rune(0x2145), true
-			case "DDotrahd":                        // RIGHTWARDS ARROW WITH DOTTED STEM
-				return rune(0x2911), true
-			case "DJcy":                            // CYRILLIC CAPITAL LETTER DJE
-				return rune(0x0402), true
-			case "DScy":                            // CYRILLIC CAPITAL LETTER DZE
-				return rune(0x0405), true
-			case "DZcy":                            // CYRILLIC CAPITAL LETTER DZHE
-				return rune(0x040f), true
-			case "Dagger":                          // DOUBLE DAGGER
-				return rune(0x2021), true
-			case "Darr":                            // DOWNWARDS TWO HEADED ARROW
-				return rune(0x21a1), true
-			case "Dashv":                           // VERTICAL BAR DOUBLE LEFT TURNSTILE
-				return rune(0x2ae4), true
-			case "Dcaron":                          // LATIN CAPITAL LETTER D WITH CARON
-				return rune(0x010e), true
-			case "Dcy":                             // CYRILLIC CAPITAL LETTER DE
-				return rune(0x0414), true
-			case "Del":                             // NABLA
-				return rune(0x2207), true
-			case "Delta":                           // GREEK CAPITAL LETTER DELTA
-				return rune(0x0394), true
-			case "Dfr":                             // MATHEMATICAL FRAKTUR CAPITAL D
-				return rune(0x01d507), true
-			case "Dgr":                             // GREEK CAPITAL LETTER DELTA
-				return rune(0x0394), true
-			case "DiacriticalAcute":                // ACUTE ACCENT
-				return rune(0xb4), true
-			case "DiacriticalDot":                  // DOT ABOVE
-				return rune(0x02d9), true
-			case "DiacriticalDoubleAcute":          // DOUBLE ACUTE ACCENT
-				return rune(0x02dd), true
-			case "DiacriticalGrave":                // GRAVE ACCENT
-				return rune(0x60), true
-			case "DiacriticalTilde":                // SMALL TILDE
-				return rune(0x02dc), true
-			case "Diamond":                         // DIAMOND OPERATOR
-				return rune(0x22c4), true
-			case "DifferentialD":                   // DOUBLE-STRUCK ITALIC SMALL D
-				return rune(0x2146), true
-			case "Dopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL D
-				return rune(0x01d53b), true
-			case "Dot":                             // DIAERESIS
-				return rune(0xa8), true
-			case "DotDot":                          // COMBINING FOUR DOTS ABOVE
-				return rune(0x20dc), true
-			case "DotEqual":                        // APPROACHES THE LIMIT
-				return rune(0x2250), true
-			case "DoubleContourIntegral":           // SURFACE INTEGRAL
-				return rune(0x222f), true
-			case "DoubleDot":                       // DIAERESIS
-				return rune(0xa8), true
-			case "DoubleDownArrow":                 // DOWNWARDS DOUBLE ARROW
-				return rune(0x21d3), true
-			case "DoubleLeftArrow":                 // LEFTWARDS DOUBLE ARROW
-				return rune(0x21d0), true
-			case "DoubleLeftRightArrow":            // LEFT RIGHT DOUBLE ARROW
-				return rune(0x21d4), true
-			case "DoubleLeftTee":                   // VERTICAL BAR DOUBLE LEFT TURNSTILE
-				return rune(0x2ae4), true
-			case "DoubleLongLeftArrow":             // LONG LEFTWARDS DOUBLE ARROW
-				return rune(0x27f8), true
-			case "DoubleLongLeftRightArrow":        // LONG LEFT RIGHT DOUBLE ARROW
-				return rune(0x27fa), true
-			case "DoubleLongRightArrow":            // LONG RIGHTWARDS DOUBLE ARROW
-				return rune(0x27f9), true
-			case "DoubleRightArrow":                // RIGHTWARDS DOUBLE ARROW
-				return rune(0x21d2), true
-			case "DoubleRightTee":                  // TRUE
-				return rune(0x22a8), true
-			case "DoubleUpArrow":                   // UPWARDS DOUBLE ARROW
-				return rune(0x21d1), true
-			case "DoubleUpDownArrow":               // UP DOWN DOUBLE ARROW
-				return rune(0x21d5), true
-			case "DoubleVerticalBar":               // PARALLEL TO
-				return rune(0x2225), true
-			case "DownArrow":                       // DOWNWARDS ARROW
-				return rune(0x2193), true
-			case "DownArrowBar":                    // DOWNWARDS ARROW TO BAR
-				return rune(0x2913), true
-			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
-				return rune(0x2950), true
-			case "DownLeftTeeVector":               // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
-				return rune(0x295e), true
-			case "DownLeftVector":                  // LEFTWARDS HARPOON WITH BARB DOWNWARDS
-				return rune(0x21bd), true
-			case "DownLeftVectorBar":               // LEFTWARDS HARPOON WITH BARB DOWN TO BAR
-				return rune(0x2956), true
-			case "DownRightTeeVector":              // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
-				return rune(0x295f), true
-			case "DownRightVector":                 // RIGHTWARDS HARPOON WITH BARB DOWNWARDS
-				return rune(0x21c1), true
-			case "DownRightVectorBar":              // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
-				return rune(0x2957), true
-			case "DownTee":                         // DOWN TACK
-				return rune(0x22a4), true
-			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
-				return rune(0x01d49f), true
-			case "Dstrok":                          // LATIN CAPITAL LETTER D WITH STROKE
-				return rune(0x0110), true
+		case "DD":                              // DOUBLE-STRUCK ITALIC CAPITAL D
+			return rune(0x2145), true
+		case "DDotrahd":                        // RIGHTWARDS ARROW WITH DOTTED STEM
+			return rune(0x2911), true
+		case "DJcy":                            // CYRILLIC CAPITAL LETTER DJE
+			return rune(0x0402), true
+		case "DScy":                            // CYRILLIC CAPITAL LETTER DZE
+			return rune(0x0405), true
+		case "DZcy":                            // CYRILLIC CAPITAL LETTER DZHE
+			return rune(0x040f), true
+		case "Dagger":                          // DOUBLE DAGGER
+			return rune(0x2021), true
+		case "Darr":                            // DOWNWARDS TWO HEADED ARROW
+			return rune(0x21a1), true
+		case "Dashv":                           // VERTICAL BAR DOUBLE LEFT TURNSTILE
+			return rune(0x2ae4), true
+		case "Dcaron":                          // LATIN CAPITAL LETTER D WITH CARON
+			return rune(0x010e), true
+		case "Dcy":                             // CYRILLIC CAPITAL LETTER DE
+			return rune(0x0414), true
+		case "Del":                             // NABLA
+			return rune(0x2207), true
+		case "Delta":                           // GREEK CAPITAL LETTER DELTA
+			return rune(0x0394), true
+		case "Dfr":                             // MATHEMATICAL FRAKTUR CAPITAL D
+			return rune(0x01d507), true
+		case "Dgr":                             // GREEK CAPITAL LETTER DELTA
+			return rune(0x0394), true
+		case "DiacriticalAcute":                // ACUTE ACCENT
+			return rune(0xb4), true
+		case "DiacriticalDot":                  // DOT ABOVE
+			return rune(0x02d9), true
+		case "DiacriticalDoubleAcute":          // DOUBLE ACUTE ACCENT
+			return rune(0x02dd), true
+		case "DiacriticalGrave":                // GRAVE ACCENT
+			return rune(0x60), true
+		case "DiacriticalTilde":                // SMALL TILDE
+			return rune(0x02dc), true
+		case "Diamond":                         // DIAMOND OPERATOR
+			return rune(0x22c4), true
+		case "DifferentialD":                   // DOUBLE-STRUCK ITALIC SMALL D
+			return rune(0x2146), true
+		case "Dopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL D
+			return rune(0x01d53b), true
+		case "Dot":                             // DIAERESIS
+			return rune(0xa8), true
+		case "DotDot":                          // COMBINING FOUR DOTS ABOVE
+			return rune(0x20dc), true
+		case "DotEqual":                        // APPROACHES THE LIMIT
+			return rune(0x2250), true
+		case "DoubleContourIntegral":           // SURFACE INTEGRAL
+			return rune(0x222f), true
+		case "DoubleDot":                       // DIAERESIS
+			return rune(0xa8), true
+		case "DoubleDownArrow":                 // DOWNWARDS DOUBLE ARROW
+			return rune(0x21d3), true
+		case "DoubleLeftArrow":                 // LEFTWARDS DOUBLE ARROW
+			return rune(0x21d0), true
+		case "DoubleLeftRightArrow":            // LEFT RIGHT DOUBLE ARROW
+			return rune(0x21d4), true
+		case "DoubleLeftTee":                   // VERTICAL BAR DOUBLE LEFT TURNSTILE
+			return rune(0x2ae4), true
+		case "DoubleLongLeftArrow":             // LONG LEFTWARDS DOUBLE ARROW
+			return rune(0x27f8), true
+		case "DoubleLongLeftRightArrow":        // LONG LEFT RIGHT DOUBLE ARROW
+			return rune(0x27fa), true
+		case "DoubleLongRightArrow":            // LONG RIGHTWARDS DOUBLE ARROW
+			return rune(0x27f9), true
+		case "DoubleRightArrow":                // RIGHTWARDS DOUBLE ARROW
+			return rune(0x21d2), true
+		case "DoubleRightTee":                  // TRUE
+			return rune(0x22a8), true
+		case "DoubleUpArrow":                   // UPWARDS DOUBLE ARROW
+			return rune(0x21d1), true
+		case "DoubleUpDownArrow":               // UP DOWN DOUBLE ARROW
+			return rune(0x21d5), true
+		case "DoubleVerticalBar":               // PARALLEL TO
+			return rune(0x2225), true
+		case "DownArrow":                       // DOWNWARDS ARROW
+			return rune(0x2193), true
+		case "DownArrowBar":                    // DOWNWARDS ARROW TO BAR
+			return rune(0x2913), true
+		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
+			return rune(0x2950), true
+		case "DownLeftTeeVector":               // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
+			return rune(0x295e), true
+		case "DownLeftVector":                  // LEFTWARDS HARPOON WITH BARB DOWNWARDS
+			return rune(0x21bd), true
+		case "DownLeftVectorBar":               // LEFTWARDS HARPOON WITH BARB DOWN TO BAR
+			return rune(0x2956), true
+		case "DownRightTeeVector":              // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
+			return rune(0x295f), true
+		case "DownRightVector":                 // RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+			return rune(0x21c1), true
+		case "DownRightVectorBar":              // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
+			return rune(0x2957), true
+		case "DownTee":                         // DOWN TACK
+			return rune(0x22a4), true
+		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
+			return rune(0x01d49f), true
+		case "Dstrok":                          // LATIN CAPITAL LETTER D WITH STROKE
+			return rune(0x0110), true
 		}
 		}
 
 
 	case 'E':
 	case 'E':
 		switch name {
 		switch name {
-			case "EEacgr":                          // GREEK CAPITAL LETTER ETA WITH TONOS
-				return rune(0x0389), true
-			case "EEgr":                            // GREEK CAPITAL LETTER ETA
-				return rune(0x0397), true
-			case "ENG":                             // LATIN CAPITAL LETTER ENG
-				return rune(0x014a), true
-			case "ETH":                             // LATIN CAPITAL LETTER ETH
-				return rune(0xd0), true
-			case "Eacgr":                           // GREEK CAPITAL LETTER EPSILON WITH TONOS
-				return rune(0x0388), true
-			case "Eacute":                          // LATIN CAPITAL LETTER E WITH ACUTE
-				return rune(0xc9), true
-			case "Ecaron":                          // LATIN CAPITAL LETTER E WITH CARON
-				return rune(0x011a), true
-			case "Ecirc":                           // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
-				return rune(0xca), true
-			case "Ecy":                             // CYRILLIC CAPITAL LETTER E
-				return rune(0x042d), true
-			case "Edot":                            // LATIN CAPITAL LETTER E WITH DOT ABOVE
-				return rune(0x0116), true
-			case "Efr":                             // MATHEMATICAL FRAKTUR CAPITAL E
-				return rune(0x01d508), true
-			case "Egr":                             // GREEK CAPITAL LETTER EPSILON
-				return rune(0x0395), true
-			case "Egrave":                          // LATIN CAPITAL LETTER E WITH GRAVE
-				return rune(0xc8), true
-			case "Element":                         // ELEMENT OF
-				return rune(0x2208), true
-			case "Emacr":                           // LATIN CAPITAL LETTER E WITH MACRON
-				return rune(0x0112), true
-			case "EmptySmallSquare":                // WHITE MEDIUM SQUARE
-				return rune(0x25fb), true
-			case "EmptyVerySmallSquare":            // WHITE SMALL SQUARE
-				return rune(0x25ab), true
-			case "Eogon":                           // LATIN CAPITAL LETTER E WITH OGONEK
-				return rune(0x0118), true
-			case "Eopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL E
-				return rune(0x01d53c), true
-			case "Epsilon":                         // GREEK CAPITAL LETTER EPSILON
-				return rune(0x0395), true
-			case "Equal":                           // TWO CONSECUTIVE EQUALS SIGNS
-				return rune(0x2a75), true
-			case "EqualTilde":                      // MINUS TILDE
-				return rune(0x2242), true
-			case "Equilibrium":                     // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
-				return rune(0x21cc), true
-			case "Escr":                            // SCRIPT CAPITAL E
-				return rune(0x2130), true
-			case "Esim":                            // EQUALS SIGN ABOVE TILDE OPERATOR
-				return rune(0x2a73), true
-			case "Eta":                             // GREEK CAPITAL LETTER ETA
-				return rune(0x0397), true
-			case "Euml":                            // LATIN CAPITAL LETTER E WITH DIAERESIS
-				return rune(0xcb), true
-			case "Exists":                          // THERE EXISTS
-				return rune(0x2203), true
-			case "ExponentialE":                    // DOUBLE-STRUCK ITALIC SMALL E
-				return rune(0x2147), true
+		case "EEacgr":                          // GREEK CAPITAL LETTER ETA WITH TONOS
+			return rune(0x0389), true
+		case "EEgr":                            // GREEK CAPITAL LETTER ETA
+			return rune(0x0397), true
+		case "ENG":                             // LATIN CAPITAL LETTER ENG
+			return rune(0x014a), true
+		case "ETH":                             // LATIN CAPITAL LETTER ETH
+			return rune(0xd0), true
+		case "Eacgr":                           // GREEK CAPITAL LETTER EPSILON WITH TONOS
+			return rune(0x0388), true
+		case "Eacute":                          // LATIN CAPITAL LETTER E WITH ACUTE
+			return rune(0xc9), true
+		case "Ecaron":                          // LATIN CAPITAL LETTER E WITH CARON
+			return rune(0x011a), true
+		case "Ecirc":                           // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+			return rune(0xca), true
+		case "Ecy":                             // CYRILLIC CAPITAL LETTER E
+			return rune(0x042d), true
+		case "Edot":                            // LATIN CAPITAL LETTER E WITH DOT ABOVE
+			return rune(0x0116), true
+		case "Efr":                             // MATHEMATICAL FRAKTUR CAPITAL E
+			return rune(0x01d508), true
+		case "Egr":                             // GREEK CAPITAL LETTER EPSILON
+			return rune(0x0395), true
+		case "Egrave":                          // LATIN CAPITAL LETTER E WITH GRAVE
+			return rune(0xc8), true
+		case "Element":                         // ELEMENT OF
+			return rune(0x2208), true
+		case "Emacr":                           // LATIN CAPITAL LETTER E WITH MACRON
+			return rune(0x0112), true
+		case "EmptySmallSquare":                // WHITE MEDIUM SQUARE
+			return rune(0x25fb), true
+		case "EmptyVerySmallSquare":            // WHITE SMALL SQUARE
+			return rune(0x25ab), true
+		case "Eogon":                           // LATIN CAPITAL LETTER E WITH OGONEK
+			return rune(0x0118), true
+		case "Eopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL E
+			return rune(0x01d53c), true
+		case "Epsilon":                         // GREEK CAPITAL LETTER EPSILON
+			return rune(0x0395), true
+		case "Equal":                           // TWO CONSECUTIVE EQUALS SIGNS
+			return rune(0x2a75), true
+		case "EqualTilde":                      // MINUS TILDE
+			return rune(0x2242), true
+		case "Equilibrium":                     // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+			return rune(0x21cc), true
+		case "Escr":                            // SCRIPT CAPITAL E
+			return rune(0x2130), true
+		case "Esim":                            // EQUALS SIGN ABOVE TILDE OPERATOR
+			return rune(0x2a73), true
+		case "Eta":                             // GREEK CAPITAL LETTER ETA
+			return rune(0x0397), true
+		case "Euml":                            // LATIN CAPITAL LETTER E WITH DIAERESIS
+			return rune(0xcb), true
+		case "Exists":                          // THERE EXISTS
+			return rune(0x2203), true
+		case "ExponentialE":                    // DOUBLE-STRUCK ITALIC SMALL E
+			return rune(0x2147), true
 		}
 		}
 
 
 	case 'F':
 	case 'F':
 		switch name {
 		switch name {
-			case "Fcy":                             // CYRILLIC CAPITAL LETTER EF
-				return rune(0x0424), true
-			case "Ffr":                             // MATHEMATICAL FRAKTUR CAPITAL F
-				return rune(0x01d509), true
-			case "FilledSmallSquare":               // BLACK MEDIUM SQUARE
-				return rune(0x25fc), true
-			case "FilledVerySmallSquare":           // BLACK SMALL SQUARE
-				return rune(0x25aa), true
-			case "Fopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL F
-				return rune(0x01d53d), true
-			case "ForAll":                          // FOR ALL
-				return rune(0x2200), true
-			case "Fouriertrf":                      // SCRIPT CAPITAL F
-				return rune(0x2131), true
-			case "Fscr":                            // SCRIPT CAPITAL F
-				return rune(0x2131), true
+		case "Fcy":                             // CYRILLIC CAPITAL LETTER EF
+			return rune(0x0424), true
+		case "Ffr":                             // MATHEMATICAL FRAKTUR CAPITAL F
+			return rune(0x01d509), true
+		case "FilledSmallSquare":               // BLACK MEDIUM SQUARE
+			return rune(0x25fc), true
+		case "FilledVerySmallSquare":           // BLACK SMALL SQUARE
+			return rune(0x25aa), true
+		case "Fopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL F
+			return rune(0x01d53d), true
+		case "ForAll":                          // FOR ALL
+			return rune(0x2200), true
+		case "Fouriertrf":                      // SCRIPT CAPITAL F
+			return rune(0x2131), true
+		case "Fscr":                            // SCRIPT CAPITAL F
+			return rune(0x2131), true
 		}
 		}
 
 
 	case 'G':
 	case 'G':
 		switch name {
 		switch name {
-			case "GJcy":                            // CYRILLIC CAPITAL LETTER GJE
-				return rune(0x0403), true
-			case "GT":                              // GREATER-THAN SIGN
-				return rune(0x3e), true
-			case "Game":                            // TURNED SANS-SERIF CAPITAL G
-				return rune(0x2141), true
-			case "Gamma":                           // GREEK CAPITAL LETTER GAMMA
-				return rune(0x0393), true
-			case "Gammad":                          // GREEK LETTER DIGAMMA
-				return rune(0x03dc), true
-			case "Gbreve":                          // LATIN CAPITAL LETTER G WITH BREVE
-				return rune(0x011e), true
-			case "Gcedil":                          // LATIN CAPITAL LETTER G WITH CEDILLA
-				return rune(0x0122), true
-			case "Gcirc":                           // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
-				return rune(0x011c), true
-			case "Gcy":                             // CYRILLIC CAPITAL LETTER GHE
-				return rune(0x0413), true
-			case "Gdot":                            // LATIN CAPITAL LETTER G WITH DOT ABOVE
-				return rune(0x0120), true
-			case "Gfr":                             // MATHEMATICAL FRAKTUR CAPITAL G
-				return rune(0x01d50a), true
-			case "Gg":                              // VERY MUCH GREATER-THAN
-				return rune(0x22d9), true
-			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
-				return rune(0x2265), true
-			case "GreaterEqualLess":                // GREATER-THAN EQUAL TO OR LESS-THAN
-				return rune(0x22db), true
-			case "GreaterFullEqual":                // GREATER-THAN OVER EQUAL TO
-				return rune(0x2267), true
-			case "GreaterGreater":                  // DOUBLE NESTED GREATER-THAN
-				return rune(0x2aa2), true
-			case "GreaterLess":                     // GREATER-THAN OR LESS-THAN
-				return rune(0x2277), true
-			case "GreaterSlantEqual":               // GREATER-THAN OR SLANTED EQUAL TO
-				return rune(0x2a7e), true
-			case "GreaterTilde":                    // GREATER-THAN OR EQUIVALENT TO
-				return rune(0x2273), true
-			case "Gscr":                            // MATHEMATICAL SCRIPT CAPITAL G
-				return rune(0x01d4a2), true
-			case "Gt":                              // MUCH GREATER-THAN
-				return rune(0x226b), true
+		case "GJcy":                            // CYRILLIC CAPITAL LETTER GJE
+			return rune(0x0403), true
+		case "GT":                              // GREATER-THAN SIGN
+			return rune(0x3e), true
+		case "Game":                            // TURNED SANS-SERIF CAPITAL G
+			return rune(0x2141), true
+		case "Gamma":                           // GREEK CAPITAL LETTER GAMMA
+			return rune(0x0393), true
+		case "Gammad":                          // GREEK LETTER DIGAMMA
+			return rune(0x03dc), true
+		case "Gbreve":                          // LATIN CAPITAL LETTER G WITH BREVE
+			return rune(0x011e), true
+		case "Gcedil":                          // LATIN CAPITAL LETTER G WITH CEDILLA
+			return rune(0x0122), true
+		case "Gcirc":                           // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+			return rune(0x011c), true
+		case "Gcy":                             // CYRILLIC CAPITAL LETTER GHE
+			return rune(0x0413), true
+		case "Gdot":                            // LATIN CAPITAL LETTER G WITH DOT ABOVE
+			return rune(0x0120), true
+		case "Gfr":                             // MATHEMATICAL FRAKTUR CAPITAL G
+			return rune(0x01d50a), true
+		case "Gg":                              // VERY MUCH GREATER-THAN
+			return rune(0x22d9), true
+		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
+			return rune(0x2265), true
+		case "GreaterEqualLess":                // GREATER-THAN EQUAL TO OR LESS-THAN
+			return rune(0x22db), true
+		case "GreaterFullEqual":                // GREATER-THAN OVER EQUAL TO
+			return rune(0x2267), true
+		case "GreaterGreater":                  // DOUBLE NESTED GREATER-THAN
+			return rune(0x2aa2), true
+		case "GreaterLess":                     // GREATER-THAN OR LESS-THAN
+			return rune(0x2277), true
+		case "GreaterSlantEqual":               // GREATER-THAN OR SLANTED EQUAL TO
+			return rune(0x2a7e), true
+		case "GreaterTilde":                    // GREATER-THAN OR EQUIVALENT TO
+			return rune(0x2273), true
+		case "Gscr":                            // MATHEMATICAL SCRIPT CAPITAL G
+			return rune(0x01d4a2), true
+		case "Gt":                              // MUCH GREATER-THAN
+			return rune(0x226b), true
 		}
 		}
 
 
 	case 'H':
 	case 'H':
 		switch name {
 		switch name {
-			case "HARDcy":                          // CYRILLIC CAPITAL LETTER HARD SIGN
-				return rune(0x042a), true
-			case "Hacek":                           // CARON
-				return rune(0x02c7), true
-			case "Hat":                             // CIRCUMFLEX ACCENT
-				return rune(0x5e), true
-			case "Hcirc":                           // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
-				return rune(0x0124), true
-			case "Hfr":                             // BLACK-LETTER CAPITAL H
-				return rune(0x210c), true
-			case "HilbertSpace":                    // SCRIPT CAPITAL H
-				return rune(0x210b), true
-			case "Hopf":                            // DOUBLE-STRUCK CAPITAL H
-				return rune(0x210d), true
-			case "HorizontalLine":                  // BOX DRAWINGS LIGHT HORIZONTAL
-				return rune(0x2500), true
-			case "Hscr":                            // SCRIPT CAPITAL H
-				return rune(0x210b), true
-			case "Hstrok":                          // LATIN CAPITAL LETTER H WITH STROKE
-				return rune(0x0126), true
-			case "HumpDownHump":                    // GEOMETRICALLY EQUIVALENT TO
-				return rune(0x224e), true
-			case "HumpEqual":                       // DIFFERENCE BETWEEN
-				return rune(0x224f), true
+		case "HARDcy":                          // CYRILLIC CAPITAL LETTER HARD SIGN
+			return rune(0x042a), true
+		case "Hacek":                           // CARON
+			return rune(0x02c7), true
+		case "Hat":                             // CIRCUMFLEX ACCENT
+			return rune(0x5e), true
+		case "Hcirc":                           // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+			return rune(0x0124), true
+		case "Hfr":                             // BLACK-LETTER CAPITAL H
+			return rune(0x210c), true
+		case "HilbertSpace":                    // SCRIPT CAPITAL H
+			return rune(0x210b), true
+		case "Hopf":                            // DOUBLE-STRUCK CAPITAL H
+			return rune(0x210d), true
+		case "HorizontalLine":                  // BOX DRAWINGS LIGHT HORIZONTAL
+			return rune(0x2500), true
+		case "Hscr":                            // SCRIPT CAPITAL H
+			return rune(0x210b), true
+		case "Hstrok":                          // LATIN CAPITAL LETTER H WITH STROKE
+			return rune(0x0126), true
+		case "HumpDownHump":                    // GEOMETRICALLY EQUIVALENT TO
+			return rune(0x224e), true
+		case "HumpEqual":                       // DIFFERENCE BETWEEN
+			return rune(0x224f), true
 		}
 		}
 
 
 	case 'I':
 	case 'I':
 		switch name {
 		switch name {
-			case "IEcy":                            // CYRILLIC CAPITAL LETTER IE
-				return rune(0x0415), true
-			case "IJlig":                           // LATIN CAPITAL LIGATURE IJ
-				return rune(0x0132), true
-			case "IOcy":                            // CYRILLIC CAPITAL LETTER IO
-				return rune(0x0401), true
-			case "Iacgr":                           // GREEK CAPITAL LETTER IOTA WITH TONOS
-				return rune(0x038a), true
-			case "Iacute":                          // LATIN CAPITAL LETTER I WITH ACUTE
-				return rune(0xcd), true
-			case "Icirc":                           // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
-				return rune(0xce), true
-			case "Icy":                             // CYRILLIC CAPITAL LETTER I
-				return rune(0x0418), true
-			case "Idigr":                           // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
-				return rune(0x03aa), true
-			case "Idot":                            // LATIN CAPITAL LETTER I WITH DOT ABOVE
-				return rune(0x0130), true
-			case "Ifr":                             // BLACK-LETTER CAPITAL I
-				return rune(0x2111), true
-			case "Igr":                             // GREEK CAPITAL LETTER IOTA
-				return rune(0x0399), true
-			case "Igrave":                          // LATIN CAPITAL LETTER I WITH GRAVE
-				return rune(0xcc), true
-			case "Im":                              // BLACK-LETTER CAPITAL I
-				return rune(0x2111), 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 "Int":                             // DOUBLE INTEGRAL
-				return rune(0x222c), true
-			case "Integral":                        // INTEGRAL
-				return rune(0x222b), true
-			case "Intersection":                    // N-ARY INTERSECTION
-				return rune(0x22c2), true
-			case "InvisibleComma":                  // INVISIBLE SEPARATOR
-				return rune(0x2063), true
-			case "InvisibleTimes":                  // INVISIBLE TIMES
-				return rune(0x2062), true
-			case "Iogon":                           // LATIN CAPITAL LETTER I WITH OGONEK
-				return rune(0x012e), true
-			case "Iopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL I
-				return rune(0x01d540), true
-			case "Iota":                            // GREEK CAPITAL LETTER IOTA
-				return rune(0x0399), true
-			case "Iscr":                            // SCRIPT CAPITAL I
-				return rune(0x2110), true
-			case "Itilde":                          // LATIN CAPITAL LETTER I WITH TILDE
-				return rune(0x0128), true
-			case "Iukcy":                           // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
-				return rune(0x0406), true
-			case "Iuml":                            // LATIN CAPITAL LETTER I WITH DIAERESIS
-				return rune(0xcf), true
+		case "IEcy":                            // CYRILLIC CAPITAL LETTER IE
+			return rune(0x0415), true
+		case "IJlig":                           // LATIN CAPITAL LIGATURE IJ
+			return rune(0x0132), true
+		case "IOcy":                            // CYRILLIC CAPITAL LETTER IO
+			return rune(0x0401), true
+		case "Iacgr":                           // GREEK CAPITAL LETTER IOTA WITH TONOS
+			return rune(0x038a), true
+		case "Iacute":                          // LATIN CAPITAL LETTER I WITH ACUTE
+			return rune(0xcd), true
+		case "Icirc":                           // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+			return rune(0xce), true
+		case "Icy":                             // CYRILLIC CAPITAL LETTER I
+			return rune(0x0418), true
+		case "Idigr":                           // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+			return rune(0x03aa), true
+		case "Idot":                            // LATIN CAPITAL LETTER I WITH DOT ABOVE
+			return rune(0x0130), true
+		case "Ifr":                             // BLACK-LETTER CAPITAL I
+			return rune(0x2111), true
+		case "Igr":                             // GREEK CAPITAL LETTER IOTA
+			return rune(0x0399), true
+		case "Igrave":                          // LATIN CAPITAL LETTER I WITH GRAVE
+			return rune(0xcc), true
+		case "Im":                              // BLACK-LETTER CAPITAL I
+			return rune(0x2111), 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 "Int":                             // DOUBLE INTEGRAL
+			return rune(0x222c), true
+		case "Integral":                        // INTEGRAL
+			return rune(0x222b), true
+		case "Intersection":                    // N-ARY INTERSECTION
+			return rune(0x22c2), true
+		case "InvisibleComma":                  // INVISIBLE SEPARATOR
+			return rune(0x2063), true
+		case "InvisibleTimes":                  // INVISIBLE TIMES
+			return rune(0x2062), true
+		case "Iogon":                           // LATIN CAPITAL LETTER I WITH OGONEK
+			return rune(0x012e), true
+		case "Iopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL I
+			return rune(0x01d540), true
+		case "Iota":                            // GREEK CAPITAL LETTER IOTA
+			return rune(0x0399), true
+		case "Iscr":                            // SCRIPT CAPITAL I
+			return rune(0x2110), true
+		case "Itilde":                          // LATIN CAPITAL LETTER I WITH TILDE
+			return rune(0x0128), true
+		case "Iukcy":                           // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+			return rune(0x0406), true
+		case "Iuml":                            // LATIN CAPITAL LETTER I WITH DIAERESIS
+			return rune(0xcf), true
 		}
 		}
 
 
 	case 'J':
 	case 'J':
 		switch name {
 		switch name {
-			case "Jcirc":                           // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
-				return rune(0x0134), true
-			case "Jcy":                             // CYRILLIC CAPITAL LETTER SHORT I
-				return rune(0x0419), true
-			case "Jfr":                             // MATHEMATICAL FRAKTUR CAPITAL J
-				return rune(0x01d50d), true
-			case "Jopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL J
-				return rune(0x01d541), true
-			case "Jscr":                            // MATHEMATICAL SCRIPT CAPITAL J
-				return rune(0x01d4a5), true
-			case "Jsercy":                          // CYRILLIC CAPITAL LETTER JE
-				return rune(0x0408), true
-			case "Jukcy":                           // CYRILLIC CAPITAL LETTER UKRAINIAN IE
-				return rune(0x0404), true
+		case "Jcirc":                           // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+			return rune(0x0134), true
+		case "Jcy":                             // CYRILLIC CAPITAL LETTER SHORT I
+			return rune(0x0419), true
+		case "Jfr":                             // MATHEMATICAL FRAKTUR CAPITAL J
+			return rune(0x01d50d), true
+		case "Jopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL J
+			return rune(0x01d541), true
+		case "Jscr":                            // MATHEMATICAL SCRIPT CAPITAL J
+			return rune(0x01d4a5), true
+		case "Jsercy":                          // CYRILLIC CAPITAL LETTER JE
+			return rune(0x0408), true
+		case "Jukcy":                           // CYRILLIC CAPITAL LETTER UKRAINIAN IE
+			return rune(0x0404), true
 		}
 		}
 
 
 	case 'K':
 	case 'K':
 		switch name {
 		switch name {
-			case "KHcy":                            // CYRILLIC CAPITAL LETTER HA
-				return rune(0x0425), true
-			case "KHgr":                            // GREEK CAPITAL LETTER CHI
-				return rune(0x03a7), true
-			case "KJcy":                            // CYRILLIC CAPITAL LETTER KJE
-				return rune(0x040c), true
-			case "Kappa":                           // GREEK CAPITAL LETTER KAPPA
-				return rune(0x039a), true
-			case "Kcedil":                          // LATIN CAPITAL LETTER K WITH CEDILLA
-				return rune(0x0136), true
-			case "Kcy":                             // CYRILLIC CAPITAL LETTER KA
-				return rune(0x041a), true
-			case "Kfr":                             // MATHEMATICAL FRAKTUR CAPITAL K
-				return rune(0x01d50e), true
-			case "Kgr":                             // GREEK CAPITAL LETTER KAPPA
-				return rune(0x039a), true
-			case "Kopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL K
-				return rune(0x01d542), true
-			case "Kscr":                            // MATHEMATICAL SCRIPT CAPITAL K
-				return rune(0x01d4a6), true
+		case "KHcy":                            // CYRILLIC CAPITAL LETTER HA
+			return rune(0x0425), true
+		case "KHgr":                            // GREEK CAPITAL LETTER CHI
+			return rune(0x03a7), true
+		case "KJcy":                            // CYRILLIC CAPITAL LETTER KJE
+			return rune(0x040c), true
+		case "Kappa":                           // GREEK CAPITAL LETTER KAPPA
+			return rune(0x039a), true
+		case "Kcedil":                          // LATIN CAPITAL LETTER K WITH CEDILLA
+			return rune(0x0136), true
+		case "Kcy":                             // CYRILLIC CAPITAL LETTER KA
+			return rune(0x041a), true
+		case "Kfr":                             // MATHEMATICAL FRAKTUR CAPITAL K
+			return rune(0x01d50e), true
+		case "Kgr":                             // GREEK CAPITAL LETTER KAPPA
+			return rune(0x039a), true
+		case "Kopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL K
+			return rune(0x01d542), true
+		case "Kscr":                            // MATHEMATICAL SCRIPT CAPITAL K
+			return rune(0x01d4a6), true
 		}
 		}
 
 
 	case 'L':
 	case 'L':
 		switch name {
 		switch name {
-			case "LJcy":                            // CYRILLIC CAPITAL LETTER LJE
-				return rune(0x0409), true
-			case "LT":                              // LESS-THAN SIGN
-				return rune(0x3c), true
-			case "Lacute":                          // LATIN CAPITAL LETTER L WITH ACUTE
-				return rune(0x0139), true
-			case "Lambda":                          // GREEK CAPITAL LETTER LAMDA
-				return rune(0x039b), true
-			case "Lang":                            // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
-				return rune(0x27ea), true
-			case "Laplacetrf":                      // SCRIPT CAPITAL L
-				return rune(0x2112), true
-			case "Larr":                            // LEFTWARDS TWO HEADED ARROW
-				return rune(0x219e), true
-			case "Lcaron":                          // LATIN CAPITAL LETTER L WITH CARON
-				return rune(0x013d), true
-			case "Lcedil":                          // LATIN CAPITAL LETTER L WITH CEDILLA
-				return rune(0x013b), true
-			case "Lcy":                             // CYRILLIC CAPITAL LETTER EL
-				return rune(0x041b), true
-			case "LeftAngleBracket":                // MATHEMATICAL LEFT ANGLE BRACKET
-				return rune(0x27e8), true
-			case "LeftArrow":                       // LEFTWARDS ARROW
-				return rune(0x2190), true
-			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
-				return rune(0x27e6), true
-			case "LeftDownTeeVector":               // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
-				return rune(0x2961), true
-			case "LeftDownVector":                  // DOWNWARDS HARPOON WITH BARB LEFTWARDS
-				return rune(0x21c3), true
-			case "LeftDownVectorBar":               // DOWNWARDS HARPOON WITH BARB LEFT TO BAR
-				return rune(0x2959), true
-			case "LeftFloor":                       // LEFT FLOOR
-				return rune(0x230a), true
-			case "LeftRightArrow":                  // LEFT RIGHT ARROW
-				return rune(0x2194), true
-			case "LeftRightVector":                 // LEFT BARB UP RIGHT BARB UP HARPOON
-				return rune(0x294e), true
-			case "LeftTee":                         // LEFT TACK
-				return rune(0x22a3), 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 "LeftTriangle":                    // NORMAL SUBGROUP OF
-				return rune(0x22b2), true
-			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
-				return rune(0x2951), true
-			case "LeftUpTeeVector":                 // UPWARDS HARPOON WITH BARB LEFT FROM BAR
-				return rune(0x2960), true
-			case "LeftUpVector":                    // UPWARDS HARPOON WITH BARB LEFTWARDS
-				return rune(0x21bf), true
-			case "LeftUpVectorBar":                 // UPWARDS HARPOON WITH BARB LEFT TO BAR
-				return rune(0x2958), true
-			case "LeftVector":                      // LEFTWARDS HARPOON WITH BARB UPWARDS
-				return rune(0x21bc), true
-			case "LeftVectorBar":                   // LEFTWARDS HARPOON WITH BARB UP TO BAR
-				return rune(0x2952), true
-			case "Leftarrow":                       // LEFTWARDS DOUBLE ARROW
-				return rune(0x21d0), true
-			case "Leftrightarrow":                  // LEFT RIGHT DOUBLE ARROW
-				return rune(0x21d4), true
-			case "LessEqualGreater":                // LESS-THAN EQUAL TO OR GREATER-THAN
-				return rune(0x22da), true
-			case "LessFullEqual":                   // LESS-THAN OVER EQUAL TO
-				return rune(0x2266), true
-			case "LessGreater":                     // LESS-THAN OR GREATER-THAN
-				return rune(0x2276), true
-			case "LessLess":                        // DOUBLE NESTED LESS-THAN
-				return rune(0x2aa1), true
-			case "LessSlantEqual":                  // LESS-THAN OR SLANTED EQUAL TO
-				return rune(0x2a7d), true
-			case "LessTilde":                       // LESS-THAN OR EQUIVALENT TO
-				return rune(0x2272), true
-			case "Lfr":                             // MATHEMATICAL FRAKTUR CAPITAL L
-				return rune(0x01d50f), true
-			case "Lgr":                             // GREEK CAPITAL LETTER LAMDA
-				return rune(0x039b), true
-			case "Ll":                              // VERY MUCH LESS-THAN
-				return rune(0x22d8), true
-			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
-				return rune(0x27f5), true
-			case "LongLeftRightArrow":              // LONG LEFT RIGHT ARROW
-				return rune(0x27f7), true
-			case "LongRightArrow":                  // LONG RIGHTWARDS ARROW
-				return rune(0x27f6), true
-			case "Longleftarrow":                   // LONG LEFTWARDS DOUBLE ARROW
-				return rune(0x27f8), true
-			case "Longleftrightarrow":              // LONG LEFT RIGHT DOUBLE ARROW
-				return rune(0x27fa), true
-			case "Longrightarrow":                  // LONG RIGHTWARDS DOUBLE ARROW
-				return rune(0x27f9), true
-			case "Lopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL L
-				return rune(0x01d543), true
-			case "LowerLeftArrow":                  // SOUTH WEST ARROW
-				return rune(0x2199), true
-			case "LowerRightArrow":                 // SOUTH EAST ARROW
-				return rune(0x2198), true
-			case "Lscr":                            // SCRIPT CAPITAL L
-				return rune(0x2112), true
-			case "Lsh":                             // UPWARDS ARROW WITH TIP LEFTWARDS
-				return rune(0x21b0), true
-			case "Lstrok":                          // LATIN CAPITAL LETTER L WITH STROKE
-				return rune(0x0141), true
-			case "Lt":                              // MUCH LESS-THAN
-				return rune(0x226a), true
-			case "Ltbar":                           // DOUBLE NESTED LESS-THAN WITH UNDERBAR
-				return rune(0x2aa3), true
+		case "LJcy":                            // CYRILLIC CAPITAL LETTER LJE
+			return rune(0x0409), true
+		case "LT":                              // LESS-THAN SIGN
+			return rune(0x3c), true
+		case "Lacute":                          // LATIN CAPITAL LETTER L WITH ACUTE
+			return rune(0x0139), true
+		case "Lambda":                          // GREEK CAPITAL LETTER LAMDA
+			return rune(0x039b), true
+		case "Lang":                            // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+			return rune(0x27ea), true
+		case "Laplacetrf":                      // SCRIPT CAPITAL L
+			return rune(0x2112), true
+		case "Larr":                            // LEFTWARDS TWO HEADED ARROW
+			return rune(0x219e), true
+		case "Lcaron":                          // LATIN CAPITAL LETTER L WITH CARON
+			return rune(0x013d), true
+		case "Lcedil":                          // LATIN CAPITAL LETTER L WITH CEDILLA
+			return rune(0x013b), true
+		case "Lcy":                             // CYRILLIC CAPITAL LETTER EL
+			return rune(0x041b), true
+		case "LeftAngleBracket":                // MATHEMATICAL LEFT ANGLE BRACKET
+			return rune(0x27e8), true
+		case "LeftArrow":                       // LEFTWARDS ARROW
+			return rune(0x2190), true
+		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
+			return rune(0x27e6), true
+		case "LeftDownTeeVector":               // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
+			return rune(0x2961), true
+		case "LeftDownVector":                  // DOWNWARDS HARPOON WITH BARB LEFTWARDS
+			return rune(0x21c3), true
+		case "LeftDownVectorBar":               // DOWNWARDS HARPOON WITH BARB LEFT TO BAR
+			return rune(0x2959), true
+		case "LeftFloor":                       // LEFT FLOOR
+			return rune(0x230a), true
+		case "LeftRightArrow":                  // LEFT RIGHT ARROW
+			return rune(0x2194), true
+		case "LeftRightVector":                 // LEFT BARB UP RIGHT BARB UP HARPOON
+			return rune(0x294e), true
+		case "LeftTee":                         // LEFT TACK
+			return rune(0x22a3), 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 "LeftTriangle":                    // NORMAL SUBGROUP OF
+			return rune(0x22b2), true
+		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
+			return rune(0x2951), true
+		case "LeftUpTeeVector":                 // UPWARDS HARPOON WITH BARB LEFT FROM BAR
+			return rune(0x2960), true
+		case "LeftUpVector":                    // UPWARDS HARPOON WITH BARB LEFTWARDS
+			return rune(0x21bf), true
+		case "LeftUpVectorBar":                 // UPWARDS HARPOON WITH BARB LEFT TO BAR
+			return rune(0x2958), true
+		case "LeftVector":                      // LEFTWARDS HARPOON WITH BARB UPWARDS
+			return rune(0x21bc), true
+		case "LeftVectorBar":                   // LEFTWARDS HARPOON WITH BARB UP TO BAR
+			return rune(0x2952), true
+		case "Leftarrow":                       // LEFTWARDS DOUBLE ARROW
+			return rune(0x21d0), true
+		case "Leftrightarrow":                  // LEFT RIGHT DOUBLE ARROW
+			return rune(0x21d4), true
+		case "LessEqualGreater":                // LESS-THAN EQUAL TO OR GREATER-THAN
+			return rune(0x22da), true
+		case "LessFullEqual":                   // LESS-THAN OVER EQUAL TO
+			return rune(0x2266), true
+		case "LessGreater":                     // LESS-THAN OR GREATER-THAN
+			return rune(0x2276), true
+		case "LessLess":                        // DOUBLE NESTED LESS-THAN
+			return rune(0x2aa1), true
+		case "LessSlantEqual":                  // LESS-THAN OR SLANTED EQUAL TO
+			return rune(0x2a7d), true
+		case "LessTilde":                       // LESS-THAN OR EQUIVALENT TO
+			return rune(0x2272), true
+		case "Lfr":                             // MATHEMATICAL FRAKTUR CAPITAL L
+			return rune(0x01d50f), true
+		case "Lgr":                             // GREEK CAPITAL LETTER LAMDA
+			return rune(0x039b), true
+		case "Ll":                              // VERY MUCH LESS-THAN
+			return rune(0x22d8), true
+		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
+			return rune(0x27f5), true
+		case "LongLeftRightArrow":              // LONG LEFT RIGHT ARROW
+			return rune(0x27f7), true
+		case "LongRightArrow":                  // LONG RIGHTWARDS ARROW
+			return rune(0x27f6), true
+		case "Longleftarrow":                   // LONG LEFTWARDS DOUBLE ARROW
+			return rune(0x27f8), true
+		case "Longleftrightarrow":              // LONG LEFT RIGHT DOUBLE ARROW
+			return rune(0x27fa), true
+		case "Longrightarrow":                  // LONG RIGHTWARDS DOUBLE ARROW
+			return rune(0x27f9), true
+		case "Lopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL L
+			return rune(0x01d543), true
+		case "LowerLeftArrow":                  // SOUTH WEST ARROW
+			return rune(0x2199), true
+		case "LowerRightArrow":                 // SOUTH EAST ARROW
+			return rune(0x2198), true
+		case "Lscr":                            // SCRIPT CAPITAL L
+			return rune(0x2112), true
+		case "Lsh":                             // UPWARDS ARROW WITH TIP LEFTWARDS
+			return rune(0x21b0), true
+		case "Lstrok":                          // LATIN CAPITAL LETTER L WITH STROKE
+			return rune(0x0141), true
+		case "Lt":                              // MUCH LESS-THAN
+			return rune(0x226a), true
+		case "Ltbar":                           // DOUBLE NESTED LESS-THAN WITH UNDERBAR
+			return rune(0x2aa3), true
 		}
 		}
 
 
 	case 'M':
 	case 'M':
 		switch name {
 		switch name {
-			case "Map":                             // RIGHTWARDS TWO-HEADED ARROW FROM BAR
-				return rune(0x2905), true
-			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
-				return rune(0x205f), true
-			case "Mellintrf":                       // SCRIPT CAPITAL M
-				return rune(0x2133), true
-			case "Mfr":                             // MATHEMATICAL FRAKTUR CAPITAL M
-				return rune(0x01d510), true
-			case "Mgr":                             // GREEK CAPITAL LETTER MU
-				return rune(0x039c), true
-			case "MinusPlus":                       // MINUS-OR-PLUS SIGN
-				return rune(0x2213), true
-			case "Mopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL M
-				return rune(0x01d544), true
-			case "Mscr":                            // SCRIPT CAPITAL M
-				return rune(0x2133), true
-			case "Mu":                              // GREEK CAPITAL LETTER MU
-				return rune(0x039c), true
+		case "Map":                             // RIGHTWARDS TWO-HEADED ARROW FROM BAR
+			return rune(0x2905), true
+		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
+			return rune(0x205f), true
+		case "Mellintrf":                       // SCRIPT CAPITAL M
+			return rune(0x2133), true
+		case "Mfr":                             // MATHEMATICAL FRAKTUR CAPITAL M
+			return rune(0x01d510), true
+		case "Mgr":                             // GREEK CAPITAL LETTER MU
+			return rune(0x039c), true
+		case "MinusPlus":                       // MINUS-OR-PLUS SIGN
+			return rune(0x2213), true
+		case "Mopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+			return rune(0x01d544), true
+		case "Mscr":                            // SCRIPT CAPITAL M
+			return rune(0x2133), true
+		case "Mu":                              // GREEK CAPITAL LETTER MU
+			return rune(0x039c), true
 		}
 		}
 
 
 	case 'N':
 	case 'N':
 		switch name {
 		switch name {
-			case "NJcy":                            // CYRILLIC CAPITAL LETTER NJE
-				return rune(0x040a), true
-			case "Nacute":                          // LATIN CAPITAL LETTER N WITH ACUTE
-				return rune(0x0143), true
-			case "Ncaron":                          // LATIN CAPITAL LETTER N WITH CARON
-				return rune(0x0147), true
-			case "Ncedil":                          // LATIN CAPITAL LETTER N WITH CEDILLA
-				return rune(0x0145), true
-			case "Ncy":                             // CYRILLIC CAPITAL LETTER EN
-				return rune(0x041d), true
-			case "NegativeMediumSpace":             // ZERO WIDTH SPACE
-				return rune(0x200b), true
-			case "NegativeThickSpace":              // ZERO WIDTH SPACE
-				return rune(0x200b), true
-			case "NegativeThinSpace":               // ZERO WIDTH SPACE
-				return rune(0x200b), true
-			case "NegativeVeryThinSpace":           // ZERO WIDTH SPACE
-				return rune(0x200b), true
-			case "NestedGreaterGreater":            // MUCH GREATER-THAN
-				return rune(0x226b), true
-			case "NestedLessLess":                  // MUCH LESS-THAN
-				return rune(0x226a), true
-			case "NewLine":                         // LINE FEED (LF)
-				return rune(0x0a), true
-			case "Nfr":                             // MATHEMATICAL FRAKTUR CAPITAL N
-				return rune(0x01d511), true
-			case "Ngr":                             // GREEK CAPITAL LETTER NU
-				return rune(0x039d), true
-			case "NoBreak":                         // WORD JOINER
-				return rune(0x2060), true
-			case "NonBreakingSpace":                // NO-BREAK SPACE
-				return rune(0xa0), true
-			case "Nopf":                            // DOUBLE-STRUCK CAPITAL N
-				return rune(0x2115), true
-			case "Not":                             // DOUBLE STROKE NOT SIGN
-				return rune(0x2aec), true
-			case "NotCongruent":                    // NOT IDENTICAL TO
-				return rune(0x2262), true
-			case "NotCupCap":                       // NOT EQUIVALENT TO
-				return rune(0x226d), true
-			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
-				return rune(0x2271), 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 "NotGreaterLess":                  // NEITHER GREATER-THAN NOR LESS-THAN
-				return rune(0x2279), true
-			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 "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 "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 "NotLess":                         // NOT LESS-THAN
-				return rune(0x226e), true
-			case "NotLessEqual":                    // NEITHER LESS-THAN NOR EQUAL TO
-				return rune(0x2270), true
-			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
-				return rune(0x2aa2), true
-			case "NotNestedLessLess":               // DOUBLE NESTED LESS-THAN with slash
-				return rune(0x2aa1), true
-			case "NotPrecedes":                     // DOES NOT PRECEDE
-				return rune(0x2280), true
-			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 "NotReverseElement":               // DOES NOT CONTAIN AS MEMBER
-				return rune(0x220c), true
-			case "NotRightTriangle":                // DOES NOT CONTAIN AS NORMAL SUBGROUP
-				return rune(0x22eb), true
-			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
-				return rune(0x228f), true
-			case "NotSquareSubsetEqual":            // NOT SQUARE IMAGE OF OR EQUAL TO
-				return rune(0x22e2), true
-			case "NotSquareSuperset":               // SQUARE ORIGINAL OF with slash
-				return rune(0x2290), true
-			case "NotSquareSupersetEqual":          // NOT SQUARE ORIGINAL OF OR EQUAL TO
-				return rune(0x22e3), true
-			case "NotSubset":                       // SUBSET OF with vertical line
-				return rune(0x2282), true
-			case "NotSubsetEqual":                  // NEITHER A SUBSET OF NOR EQUAL TO
-				return rune(0x2288), true
-			case "NotSucceeds":                     // DOES NOT SUCCEED
-				return rune(0x2281), true
-			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 "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
-				return rune(0x2289), 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 "Nscr":                            // MATHEMATICAL SCRIPT CAPITAL N
-				return rune(0x01d4a9), true
-			case "Ntilde":                          // LATIN CAPITAL LETTER N WITH TILDE
-				return rune(0xd1), true
-			case "Nu":                              // GREEK CAPITAL LETTER NU
-				return rune(0x039d), true
+		case "NJcy":                            // CYRILLIC CAPITAL LETTER NJE
+			return rune(0x040a), true
+		case "Nacute":                          // LATIN CAPITAL LETTER N WITH ACUTE
+			return rune(0x0143), true
+		case "Ncaron":                          // LATIN CAPITAL LETTER N WITH CARON
+			return rune(0x0147), true
+		case "Ncedil":                          // LATIN CAPITAL LETTER N WITH CEDILLA
+			return rune(0x0145), true
+		case "Ncy":                             // CYRILLIC CAPITAL LETTER EN
+			return rune(0x041d), true
+		case "NegativeMediumSpace":             // ZERO WIDTH SPACE
+			return rune(0x200b), true
+		case "NegativeThickSpace":              // ZERO WIDTH SPACE
+			return rune(0x200b), true
+		case "NegativeThinSpace":               // ZERO WIDTH SPACE
+			return rune(0x200b), true
+		case "NegativeVeryThinSpace":           // ZERO WIDTH SPACE
+			return rune(0x200b), true
+		case "NestedGreaterGreater":            // MUCH GREATER-THAN
+			return rune(0x226b), true
+		case "NestedLessLess":                  // MUCH LESS-THAN
+			return rune(0x226a), true
+		case "NewLine":                         // LINE FEED (LF)
+			return rune(0x0a), true
+		case "Nfr":                             // MATHEMATICAL FRAKTUR CAPITAL N
+			return rune(0x01d511), true
+		case "Ngr":                             // GREEK CAPITAL LETTER NU
+			return rune(0x039d), true
+		case "NoBreak":                         // WORD JOINER
+			return rune(0x2060), true
+		case "NonBreakingSpace":                // NO-BREAK SPACE
+			return rune(0xa0), true
+		case "Nopf":                            // DOUBLE-STRUCK CAPITAL N
+			return rune(0x2115), true
+		case "Not":                             // DOUBLE STROKE NOT SIGN
+			return rune(0x2aec), true
+		case "NotCongruent":                    // NOT IDENTICAL TO
+			return rune(0x2262), true
+		case "NotCupCap":                       // NOT EQUIVALENT TO
+			return rune(0x226d), true
+		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
+			return rune(0x2271), 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 "NotGreaterLess":                  // NEITHER GREATER-THAN NOR LESS-THAN
+			return rune(0x2279), true
+		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 "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 "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 "NotLess":                         // NOT LESS-THAN
+			return rune(0x226e), true
+		case "NotLessEqual":                    // NEITHER LESS-THAN NOR EQUAL TO
+			return rune(0x2270), true
+		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
+			return rune(0x2aa2), true
+		case "NotNestedLessLess":               // DOUBLE NESTED LESS-THAN with slash
+			return rune(0x2aa1), true
+		case "NotPrecedes":                     // DOES NOT PRECEDE
+			return rune(0x2280), true
+		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 "NotReverseElement":               // DOES NOT CONTAIN AS MEMBER
+			return rune(0x220c), true
+		case "NotRightTriangle":                // DOES NOT CONTAIN AS NORMAL SUBGROUP
+			return rune(0x22eb), true
+		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
+			return rune(0x228f), true
+		case "NotSquareSubsetEqual":            // NOT SQUARE IMAGE OF OR EQUAL TO
+			return rune(0x22e2), true
+		case "NotSquareSuperset":               // SQUARE ORIGINAL OF with slash
+			return rune(0x2290), true
+		case "NotSquareSupersetEqual":          // NOT SQUARE ORIGINAL OF OR EQUAL TO
+			return rune(0x22e3), true
+		case "NotSubset":                       // SUBSET OF with vertical line
+			return rune(0x2282), true
+		case "NotSubsetEqual":                  // NEITHER A SUBSET OF NOR EQUAL TO
+			return rune(0x2288), true
+		case "NotSucceeds":                     // DOES NOT SUCCEED
+			return rune(0x2281), true
+		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 "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
+			return rune(0x2289), 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 "Nscr":                            // MATHEMATICAL SCRIPT CAPITAL N
+			return rune(0x01d4a9), true
+		case "Ntilde":                          // LATIN CAPITAL LETTER N WITH TILDE
+			return rune(0xd1), true
+		case "Nu":                              // GREEK CAPITAL LETTER NU
+			return rune(0x039d), true
 		}
 		}
 
 
 	case 'O':
 	case 'O':
 		switch name {
 		switch name {
-			case "OElig":                           // LATIN CAPITAL LIGATURE OE
-				return rune(0x0152), true
-			case "OHacgr":                          // GREEK CAPITAL LETTER OMEGA WITH TONOS
-				return rune(0x038f), true
-			case "OHgr":                            // GREEK CAPITAL LETTER OMEGA
-				return rune(0x03a9), true
-			case "Oacgr":                           // GREEK CAPITAL LETTER OMICRON WITH TONOS
-				return rune(0x038c), true
-			case "Oacute":                          // LATIN CAPITAL LETTER O WITH ACUTE
-				return rune(0xd3), true
-			case "Ocirc":                           // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
-				return rune(0xd4), true
-			case "Ocy":                             // CYRILLIC CAPITAL LETTER O
-				return rune(0x041e), true
-			case "Odblac":                          // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
-				return rune(0x0150), true
-			case "Ofr":                             // MATHEMATICAL FRAKTUR CAPITAL O
-				return rune(0x01d512), true
-			case "Ogr":                             // GREEK CAPITAL LETTER OMICRON
-				return rune(0x039f), true
-			case "Ograve":                          // LATIN CAPITAL LETTER O WITH GRAVE
-				return rune(0xd2), true
-			case "Omacr":                           // LATIN CAPITAL LETTER O WITH MACRON
-				return rune(0x014c), true
-			case "Omega":                           // GREEK CAPITAL LETTER OMEGA
-				return rune(0x03a9), true
-			case "Omicron":                         // GREEK CAPITAL LETTER OMICRON
-				return rune(0x039f), true
-			case "Oopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL O
-				return rune(0x01d546), true
-			case "OpenCurlyDoubleQuote":            // LEFT DOUBLE QUOTATION MARK
-				return rune(0x201c), true
-			case "OpenCurlyQuote":                  // LEFT SINGLE QUOTATION MARK
-				return rune(0x2018), true
-			case "Or":                              // DOUBLE LOGICAL OR
-				return rune(0x2a54), true
-			case "Oscr":                            // MATHEMATICAL SCRIPT CAPITAL O
-				return rune(0x01d4aa), true
-			case "Oslash":                          // LATIN CAPITAL LETTER O WITH STROKE
-				return rune(0xd8), true
-			case "Otilde":                          // LATIN CAPITAL LETTER O WITH TILDE
-				return rune(0xd5), true
-			case "Otimes":                          // MULTIPLICATION SIGN IN DOUBLE CIRCLE
-				return rune(0x2a37), true
-			case "Ouml":                            // LATIN CAPITAL LETTER O WITH DIAERESIS
-				return rune(0xd6), true
-			case "OverBar":                         // OVERLINE
-				return rune(0x203e), true
-			case "OverBrace":                       // TOP CURLY BRACKET
-				return rune(0x23de), true
-			case "OverBracket":                     // TOP SQUARE BRACKET
-				return rune(0x23b4), true
-			case "OverParenthesis":                 // TOP PARENTHESIS
-				return rune(0x23dc), true
+		case "OElig":                           // LATIN CAPITAL LIGATURE OE
+			return rune(0x0152), true
+		case "OHacgr":                          // GREEK CAPITAL LETTER OMEGA WITH TONOS
+			return rune(0x038f), true
+		case "OHgr":                            // GREEK CAPITAL LETTER OMEGA
+			return rune(0x03a9), true
+		case "Oacgr":                           // GREEK CAPITAL LETTER OMICRON WITH TONOS
+			return rune(0x038c), true
+		case "Oacute":                          // LATIN CAPITAL LETTER O WITH ACUTE
+			return rune(0xd3), true
+		case "Ocirc":                           // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+			return rune(0xd4), true
+		case "Ocy":                             // CYRILLIC CAPITAL LETTER O
+			return rune(0x041e), true
+		case "Odblac":                          // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+			return rune(0x0150), true
+		case "Ofr":                             // MATHEMATICAL FRAKTUR CAPITAL O
+			return rune(0x01d512), true
+		case "Ogr":                             // GREEK CAPITAL LETTER OMICRON
+			return rune(0x039f), true
+		case "Ograve":                          // LATIN CAPITAL LETTER O WITH GRAVE
+			return rune(0xd2), true
+		case "Omacr":                           // LATIN CAPITAL LETTER O WITH MACRON
+			return rune(0x014c), true
+		case "Omega":                           // GREEK CAPITAL LETTER OMEGA
+			return rune(0x03a9), true
+		case "Omicron":                         // GREEK CAPITAL LETTER OMICRON
+			return rune(0x039f), true
+		case "Oopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+			return rune(0x01d546), true
+		case "OpenCurlyDoubleQuote":            // LEFT DOUBLE QUOTATION MARK
+			return rune(0x201c), true
+		case "OpenCurlyQuote":                  // LEFT SINGLE QUOTATION MARK
+			return rune(0x2018), true
+		case "Or":                              // DOUBLE LOGICAL OR
+			return rune(0x2a54), true
+		case "Oscr":                            // MATHEMATICAL SCRIPT CAPITAL O
+			return rune(0x01d4aa), true
+		case "Oslash":                          // LATIN CAPITAL LETTER O WITH STROKE
+			return rune(0xd8), true
+		case "Otilde":                          // LATIN CAPITAL LETTER O WITH TILDE
+			return rune(0xd5), true
+		case "Otimes":                          // MULTIPLICATION SIGN IN DOUBLE CIRCLE
+			return rune(0x2a37), true
+		case "Ouml":                            // LATIN CAPITAL LETTER O WITH DIAERESIS
+			return rune(0xd6), true
+		case "OverBar":                         // OVERLINE
+			return rune(0x203e), true
+		case "OverBrace":                       // TOP CURLY BRACKET
+			return rune(0x23de), true
+		case "OverBracket":                     // TOP SQUARE BRACKET
+			return rune(0x23b4), true
+		case "OverParenthesis":                 // TOP PARENTHESIS
+			return rune(0x23dc), true
 		}
 		}
 
 
 	case 'P':
 	case 'P':
 		switch name {
 		switch name {
-			case "PHgr":                            // GREEK CAPITAL LETTER PHI
-				return rune(0x03a6), true
-			case "PSgr":                            // GREEK CAPITAL LETTER PSI
-				return rune(0x03a8), true
-			case "PartialD":                        // PARTIAL DIFFERENTIAL
-				return rune(0x2202), true
-			case "Pcy":                             // CYRILLIC CAPITAL LETTER PE
-				return rune(0x041f), true
-			case "Pfr":                             // MATHEMATICAL FRAKTUR CAPITAL P
-				return rune(0x01d513), true
-			case "Pgr":                             // GREEK CAPITAL LETTER PI
-				return rune(0x03a0), true
-			case "Phi":                             // GREEK CAPITAL LETTER PHI
-				return rune(0x03a6), true
-			case "Pi":                              // GREEK CAPITAL LETTER PI
-				return rune(0x03a0), true
-			case "PlusMinus":                       // PLUS-MINUS SIGN
-				return rune(0xb1), true
-			case "Poincareplane":                   // BLACK-LETTER CAPITAL H
-				return rune(0x210c), true
-			case "Popf":                            // DOUBLE-STRUCK CAPITAL P
-				return rune(0x2119), true
-			case "Pr":                              // DOUBLE PRECEDES
-				return rune(0x2abb), true
-			case "Precedes":                        // PRECEDES
-				return rune(0x227a), true
-			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
-				return rune(0x227e), true
-			case "Prime":                           // DOUBLE PRIME
-				return rune(0x2033), true
-			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
-				return rune(0x03a8), true
+		case "PHgr":                            // GREEK CAPITAL LETTER PHI
+			return rune(0x03a6), true
+		case "PSgr":                            // GREEK CAPITAL LETTER PSI
+			return rune(0x03a8), true
+		case "PartialD":                        // PARTIAL DIFFERENTIAL
+			return rune(0x2202), true
+		case "Pcy":                             // CYRILLIC CAPITAL LETTER PE
+			return rune(0x041f), true
+		case "Pfr":                             // MATHEMATICAL FRAKTUR CAPITAL P
+			return rune(0x01d513), true
+		case "Pgr":                             // GREEK CAPITAL LETTER PI
+			return rune(0x03a0), true
+		case "Phi":                             // GREEK CAPITAL LETTER PHI
+			return rune(0x03a6), true
+		case "Pi":                              // GREEK CAPITAL LETTER PI
+			return rune(0x03a0), true
+		case "PlusMinus":                       // PLUS-MINUS SIGN
+			return rune(0xb1), true
+		case "Poincareplane":                   // BLACK-LETTER CAPITAL H
+			return rune(0x210c), true
+		case "Popf":                            // DOUBLE-STRUCK CAPITAL P
+			return rune(0x2119), true
+		case "Pr":                              // DOUBLE PRECEDES
+			return rune(0x2abb), true
+		case "Precedes":                        // PRECEDES
+			return rune(0x227a), true
+		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
+			return rune(0x227e), true
+		case "Prime":                           // DOUBLE PRIME
+			return rune(0x2033), true
+		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
+			return rune(0x03a8), true
 		}
 		}
 
 
 	case 'Q':
 	case 'Q':
 		switch name {
 		switch name {
-			case "QUOT":                            // QUOTATION MARK
-				return rune(0x22), true
-			case "Qfr":                             // MATHEMATICAL FRAKTUR CAPITAL Q
-				return rune(0x01d514), true
-			case "Qopf":                            // DOUBLE-STRUCK CAPITAL Q
-				return rune(0x211a), true
-			case "Qscr":                            // MATHEMATICAL SCRIPT CAPITAL Q
-				return rune(0x01d4ac), true
+		case "QUOT":                            // QUOTATION MARK
+			return rune(0x22), true
+		case "Qfr":                             // MATHEMATICAL FRAKTUR CAPITAL Q
+			return rune(0x01d514), true
+		case "Qopf":                            // DOUBLE-STRUCK CAPITAL Q
+			return rune(0x211a), true
+		case "Qscr":                            // MATHEMATICAL SCRIPT CAPITAL Q
+			return rune(0x01d4ac), true
 		}
 		}
 
 
 	case 'R':
 	case 'R':
 		switch name {
 		switch name {
-			case "RBarr":                           // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
-				return rune(0x2910), true
-			case "REG":                             // REGISTERED SIGN
-				return rune(0xae), true
-			case "Racute":                          // LATIN CAPITAL LETTER R WITH ACUTE
-				return rune(0x0154), true
-			case "Rang":                            // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
-				return rune(0x27eb), true
-			case "Rarr":                            // RIGHTWARDS TWO HEADED ARROW
-				return rune(0x21a0), true
-			case "Rarrtl":                          // RIGHTWARDS TWO-HEADED ARROW WITH TAIL
-				return rune(0x2916), true
-			case "Rcaron":                          // LATIN CAPITAL LETTER R WITH CARON
-				return rune(0x0158), true
-			case "Rcedil":                          // LATIN CAPITAL LETTER R WITH CEDILLA
-				return rune(0x0156), true
-			case "Rcy":                             // CYRILLIC CAPITAL LETTER ER
-				return rune(0x0420), true
-			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
-				return rune(0x21cb), true
-			case "ReverseUpEquilibrium":            // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
-				return rune(0x296f), true
-			case "Rfr":                             // BLACK-LETTER CAPITAL R
-				return rune(0x211c), true
-			case "Rgr":                             // GREEK CAPITAL LETTER RHO
-				return rune(0x03a1), true
-			case "Rho":                             // GREEK CAPITAL LETTER RHO
-				return rune(0x03a1), true
-			case "RightAngleBracket":               // MATHEMATICAL RIGHT ANGLE BRACKET
-				return rune(0x27e9), true
-			case "RightArrow":                      // RIGHTWARDS ARROW
-				return rune(0x2192), true
-			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
-				return rune(0x2309), true
-			case "RightDoubleBracket":              // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
-				return rune(0x27e7), true
-			case "RightDownTeeVector":              // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
-				return rune(0x295d), true
-			case "RightDownVector":                 // DOWNWARDS HARPOON WITH BARB RIGHTWARDS
-				return rune(0x21c2), true
-			case "RightDownVectorBar":              // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
-				return rune(0x2955), true
-			case "RightFloor":                      // RIGHT FLOOR
-				return rune(0x230b), true
-			case "RightTee":                        // RIGHT TACK
-				return rune(0x22a2), 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 "RightTriangle":                   // CONTAINS AS NORMAL SUBGROUP
-				return rune(0x22b3), true
-			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
-				return rune(0x294f), true
-			case "RightUpTeeVector":                // UPWARDS HARPOON WITH BARB RIGHT FROM BAR
-				return rune(0x295c), true
-			case "RightUpVector":                   // UPWARDS HARPOON WITH BARB RIGHTWARDS
-				return rune(0x21be), true
-			case "RightUpVectorBar":                // UPWARDS HARPOON WITH BARB RIGHT TO BAR
-				return rune(0x2954), true
-			case "RightVector":                     // RIGHTWARDS HARPOON WITH BARB UPWARDS
-				return rune(0x21c0), true
-			case "RightVectorBar":                  // RIGHTWARDS HARPOON WITH BARB UP TO BAR
-				return rune(0x2953), true
-			case "Rightarrow":                      // RIGHTWARDS DOUBLE ARROW
-				return rune(0x21d2), true
-			case "Ropf":                            // DOUBLE-STRUCK CAPITAL R
-				return rune(0x211d), true
-			case "RoundImplies":                    // RIGHT DOUBLE ARROW WITH ROUNDED HEAD
-				return rune(0x2970), true
-			case "Rrightarrow":                     // RIGHTWARDS TRIPLE ARROW
-				return rune(0x21db), true
-			case "Rscr":                            // SCRIPT CAPITAL R
-				return rune(0x211b), true
-			case "Rsh":                             // UPWARDS ARROW WITH TIP RIGHTWARDS
-				return rune(0x21b1), true
-			case "RuleDelayed":                     // RULE-DELAYED
-				return rune(0x29f4), true
+		case "RBarr":                           // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
+			return rune(0x2910), true
+		case "REG":                             // REGISTERED SIGN
+			return rune(0xae), true
+		case "Racute":                          // LATIN CAPITAL LETTER R WITH ACUTE
+			return rune(0x0154), true
+		case "Rang":                            // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+			return rune(0x27eb), true
+		case "Rarr":                            // RIGHTWARDS TWO HEADED ARROW
+			return rune(0x21a0), true
+		case "Rarrtl":                          // RIGHTWARDS TWO-HEADED ARROW WITH TAIL
+			return rune(0x2916), true
+		case "Rcaron":                          // LATIN CAPITAL LETTER R WITH CARON
+			return rune(0x0158), true
+		case "Rcedil":                          // LATIN CAPITAL LETTER R WITH CEDILLA
+			return rune(0x0156), true
+		case "Rcy":                             // CYRILLIC CAPITAL LETTER ER
+			return rune(0x0420), true
+		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
+			return rune(0x21cb), true
+		case "ReverseUpEquilibrium":            // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+			return rune(0x296f), true
+		case "Rfr":                             // BLACK-LETTER CAPITAL R
+			return rune(0x211c), true
+		case "Rgr":                             // GREEK CAPITAL LETTER RHO
+			return rune(0x03a1), true
+		case "Rho":                             // GREEK CAPITAL LETTER RHO
+			return rune(0x03a1), true
+		case "RightAngleBracket":               // MATHEMATICAL RIGHT ANGLE BRACKET
+			return rune(0x27e9), true
+		case "RightArrow":                      // RIGHTWARDS ARROW
+			return rune(0x2192), true
+		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
+			return rune(0x2309), true
+		case "RightDoubleBracket":              // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+			return rune(0x27e7), true
+		case "RightDownTeeVector":              // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
+			return rune(0x295d), true
+		case "RightDownVector":                 // DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+			return rune(0x21c2), true
+		case "RightDownVectorBar":              // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
+			return rune(0x2955), true
+		case "RightFloor":                      // RIGHT FLOOR
+			return rune(0x230b), true
+		case "RightTee":                        // RIGHT TACK
+			return rune(0x22a2), 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 "RightTriangle":                   // CONTAINS AS NORMAL SUBGROUP
+			return rune(0x22b3), true
+		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
+			return rune(0x294f), true
+		case "RightUpTeeVector":                // UPWARDS HARPOON WITH BARB RIGHT FROM BAR
+			return rune(0x295c), true
+		case "RightUpVector":                   // UPWARDS HARPOON WITH BARB RIGHTWARDS
+			return rune(0x21be), true
+		case "RightUpVectorBar":                // UPWARDS HARPOON WITH BARB RIGHT TO BAR
+			return rune(0x2954), true
+		case "RightVector":                     // RIGHTWARDS HARPOON WITH BARB UPWARDS
+			return rune(0x21c0), true
+		case "RightVectorBar":                  // RIGHTWARDS HARPOON WITH BARB UP TO BAR
+			return rune(0x2953), true
+		case "Rightarrow":                      // RIGHTWARDS DOUBLE ARROW
+			return rune(0x21d2), true
+		case "Ropf":                            // DOUBLE-STRUCK CAPITAL R
+			return rune(0x211d), true
+		case "RoundImplies":                    // RIGHT DOUBLE ARROW WITH ROUNDED HEAD
+			return rune(0x2970), true
+		case "Rrightarrow":                     // RIGHTWARDS TRIPLE ARROW
+			return rune(0x21db), true
+		case "Rscr":                            // SCRIPT CAPITAL R
+			return rune(0x211b), true
+		case "Rsh":                             // UPWARDS ARROW WITH TIP RIGHTWARDS
+			return rune(0x21b1), true
+		case "RuleDelayed":                     // RULE-DELAYED
+			return rune(0x29f4), true
 		}
 		}
 
 
 	case 'S':
 	case 'S':
 		switch name {
 		switch name {
-			case "SHCHcy":                          // CYRILLIC CAPITAL LETTER SHCHA
-				return rune(0x0429), true
-			case "SHcy":                            // CYRILLIC CAPITAL LETTER SHA
-				return rune(0x0428), true
-			case "SOFTcy":                          // CYRILLIC CAPITAL LETTER SOFT SIGN
-				return rune(0x042c), true
-			case "Sacute":                          // LATIN CAPITAL LETTER S WITH ACUTE
-				return rune(0x015a), true
-			case "Sc":                              // DOUBLE SUCCEEDS
-				return rune(0x2abc), true
-			case "Scaron":                          // LATIN CAPITAL LETTER S WITH CARON
-				return rune(0x0160), true
-			case "Scedil":                          // LATIN CAPITAL LETTER S WITH CEDILLA
-				return rune(0x015e), true
-			case "Scirc":                           // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
-				return rune(0x015c), true
-			case "Scy":                             // CYRILLIC CAPITAL LETTER ES
-				return rune(0x0421), true
-			case "Sfr":                             // MATHEMATICAL FRAKTUR CAPITAL S
-				return rune(0x01d516), true
-			case "Sgr":                             // GREEK CAPITAL LETTER SIGMA
-				return rune(0x03a3), true
-			case "ShortDownArrow":                  // DOWNWARDS ARROW
-				return rune(0x2193), true
-			case "ShortLeftArrow":                  // LEFTWARDS ARROW
-				return rune(0x2190), true
-			case "ShortRightArrow":                 // RIGHTWARDS ARROW
-				return rune(0x2192), true
-			case "ShortUpArrow":                    // UPWARDS ARROW
-				return rune(0x2191), true
-			case "Sigma":                           // GREEK CAPITAL LETTER SIGMA
-				return rune(0x03a3), true
-			case "SmallCircle":                     // RING OPERATOR
-				return rune(0x2218), true
-			case "Sopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL S
-				return rune(0x01d54a), true
-			case "Sqrt":                            // SQUARE ROOT
-				return rune(0x221a), true
-			case "Square":                          // WHITE SQUARE
-				return rune(0x25a1), 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 "SquareSuperset":                  // SQUARE ORIGINAL OF
-				return rune(0x2290), true
-			case "SquareSupersetEqual":             // SQUARE ORIGINAL OF OR EQUAL TO
-				return rune(0x2292), true
-			case "SquareUnion":                     // SQUARE CUP
-				return rune(0x2294), true
-			case "Sscr":                            // MATHEMATICAL SCRIPT CAPITAL S
-				return rune(0x01d4ae), true
-			case "Star":                            // STAR OPERATOR
-				return rune(0x22c6), true
-			case "Sub":                             // DOUBLE SUBSET
-				return rune(0x22d0), true
-			case "Subset":                          // DOUBLE SUBSET
-				return rune(0x22d0), true
-			case "SubsetEqual":                     // SUBSET OF OR EQUAL TO
-				return rune(0x2286), true
-			case "Succeeds":                        // SUCCEEDS
-				return rune(0x227b), true
-			case "SucceedsEqual":                   // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
-				return rune(0x2ab0), true
-			case "SucceedsSlantEqual":              // SUCCEEDS OR EQUAL TO
-				return rune(0x227d), true
-			case "SucceedsTilde":                   // SUCCEEDS OR EQUIVALENT TO
-				return rune(0x227f), true
-			case "SuchThat":                        // CONTAINS AS MEMBER
-				return rune(0x220b), true
-			case "Sum":                             // N-ARY SUMMATION
-				return rune(0x2211), true
-			case "Sup":                             // DOUBLE SUPERSET
-				return rune(0x22d1), true
-			case "Superset":                        // SUPERSET OF
-				return rune(0x2283), true
-			case "SupersetEqual":                   // SUPERSET OF OR EQUAL TO
-				return rune(0x2287), true
-			case "Supset":                          // DOUBLE SUPERSET
-				return rune(0x22d1), true
+		case "SHCHcy":                          // CYRILLIC CAPITAL LETTER SHCHA
+			return rune(0x0429), true
+		case "SHcy":                            // CYRILLIC CAPITAL LETTER SHA
+			return rune(0x0428), true
+		case "SOFTcy":                          // CYRILLIC CAPITAL LETTER SOFT SIGN
+			return rune(0x042c), true
+		case "Sacute":                          // LATIN CAPITAL LETTER S WITH ACUTE
+			return rune(0x015a), true
+		case "Sc":                              // DOUBLE SUCCEEDS
+			return rune(0x2abc), true
+		case "Scaron":                          // LATIN CAPITAL LETTER S WITH CARON
+			return rune(0x0160), true
+		case "Scedil":                          // LATIN CAPITAL LETTER S WITH CEDILLA
+			return rune(0x015e), true
+		case "Scirc":                           // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+			return rune(0x015c), true
+		case "Scy":                             // CYRILLIC CAPITAL LETTER ES
+			return rune(0x0421), true
+		case "Sfr":                             // MATHEMATICAL FRAKTUR CAPITAL S
+			return rune(0x01d516), true
+		case "Sgr":                             // GREEK CAPITAL LETTER SIGMA
+			return rune(0x03a3), true
+		case "ShortDownArrow":                  // DOWNWARDS ARROW
+			return rune(0x2193), true
+		case "ShortLeftArrow":                  // LEFTWARDS ARROW
+			return rune(0x2190), true
+		case "ShortRightArrow":                 // RIGHTWARDS ARROW
+			return rune(0x2192), true
+		case "ShortUpArrow":                    // UPWARDS ARROW
+			return rune(0x2191), true
+		case "Sigma":                           // GREEK CAPITAL LETTER SIGMA
+			return rune(0x03a3), true
+		case "SmallCircle":                     // RING OPERATOR
+			return rune(0x2218), true
+		case "Sopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL S
+			return rune(0x01d54a), true
+		case "Sqrt":                            // SQUARE ROOT
+			return rune(0x221a), true
+		case "Square":                          // WHITE SQUARE
+			return rune(0x25a1), 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 "SquareSuperset":                  // SQUARE ORIGINAL OF
+			return rune(0x2290), true
+		case "SquareSupersetEqual":             // SQUARE ORIGINAL OF OR EQUAL TO
+			return rune(0x2292), true
+		case "SquareUnion":                     // SQUARE CUP
+			return rune(0x2294), true
+		case "Sscr":                            // MATHEMATICAL SCRIPT CAPITAL S
+			return rune(0x01d4ae), true
+		case "Star":                            // STAR OPERATOR
+			return rune(0x22c6), true
+		case "Sub":                             // DOUBLE SUBSET
+			return rune(0x22d0), true
+		case "Subset":                          // DOUBLE SUBSET
+			return rune(0x22d0), true
+		case "SubsetEqual":                     // SUBSET OF OR EQUAL TO
+			return rune(0x2286), true
+		case "Succeeds":                        // SUCCEEDS
+			return rune(0x227b), true
+		case "SucceedsEqual":                   // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+			return rune(0x2ab0), true
+		case "SucceedsSlantEqual":              // SUCCEEDS OR EQUAL TO
+			return rune(0x227d), true
+		case "SucceedsTilde":                   // SUCCEEDS OR EQUIVALENT TO
+			return rune(0x227f), true
+		case "SuchThat":                        // CONTAINS AS MEMBER
+			return rune(0x220b), true
+		case "Sum":                             // N-ARY SUMMATION
+			return rune(0x2211), true
+		case "Sup":                             // DOUBLE SUPERSET
+			return rune(0x22d1), true
+		case "Superset":                        // SUPERSET OF
+			return rune(0x2283), true
+		case "SupersetEqual":                   // SUPERSET OF OR EQUAL TO
+			return rune(0x2287), true
+		case "Supset":                          // DOUBLE SUPERSET
+			return rune(0x22d1), true
 		}
 		}
 
 
 	case 'T':
 	case 'T':
 		switch name {
 		switch name {
-			case "THORN":                           // LATIN CAPITAL LETTER THORN
-				return rune(0xde), true
-			case "THgr":                            // GREEK CAPITAL LETTER THETA
-				return rune(0x0398), true
-			case "TRADE":                           // TRADE MARK SIGN
-				return rune(0x2122), true
-			case "TSHcy":                           // CYRILLIC CAPITAL LETTER TSHE
-				return rune(0x040b), true
-			case "TScy":                            // CYRILLIC CAPITAL LETTER TSE
-				return rune(0x0426), true
-			case "Tab":                             // CHARACTER TABULATION
-				return rune(0x09), true
-			case "Tau":                             // GREEK CAPITAL LETTER TAU
-				return rune(0x03a4), true
-			case "Tcaron":                          // LATIN CAPITAL LETTER T WITH CARON
-				return rune(0x0164), true
-			case "Tcedil":                          // LATIN CAPITAL LETTER T WITH CEDILLA
-				return rune(0x0162), true
-			case "Tcy":                             // CYRILLIC CAPITAL LETTER TE
-				return rune(0x0422), true
-			case "Tfr":                             // MATHEMATICAL FRAKTUR CAPITAL T
-				return rune(0x01d517), true
-			case "Tgr":                             // GREEK CAPITAL LETTER TAU
-				return rune(0x03a4), true
-			case "Therefore":                       // THEREFORE
-				return rune(0x2234), true
-			case "Theta":                           // GREEK CAPITAL LETTER THETA
-				return rune(0x0398), true
-			case "Thetav":                          // GREEK CAPITAL THETA SYMBOL
-				return rune(0x03f4), true
-			case "ThickSpace":                      // space of width 5/18 em
-				return rune(0x205f), true
-			case "ThinSpace":                       // THIN SPACE
-				return rune(0x2009), true
-			case "Tilde":                           // TILDE OPERATOR
-				return rune(0x223c), true
-			case "TildeEqual":                      // ASYMPTOTICALLY EQUAL TO
-				return rune(0x2243), true
-			case "TildeFullEqual":                  // APPROXIMATELY EQUAL TO
-				return rune(0x2245), true
-			case "TildeTilde":                      // ALMOST EQUAL TO
-				return rune(0x2248), true
-			case "Topf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL T
-				return rune(0x01d54b), true
-			case "TripleDot":                       // COMBINING THREE DOTS ABOVE
-				return rune(0x20db), true
-			case "Tscr":                            // MATHEMATICAL SCRIPT CAPITAL T
-				return rune(0x01d4af), true
-			case "Tstrok":                          // LATIN CAPITAL LETTER T WITH STROKE
-				return rune(0x0166), true
+		case "THORN":                           // LATIN CAPITAL LETTER THORN
+			return rune(0xde), true
+		case "THgr":                            // GREEK CAPITAL LETTER THETA
+			return rune(0x0398), true
+		case "TRADE":                           // TRADE MARK SIGN
+			return rune(0x2122), true
+		case "TSHcy":                           // CYRILLIC CAPITAL LETTER TSHE
+			return rune(0x040b), true
+		case "TScy":                            // CYRILLIC CAPITAL LETTER TSE
+			return rune(0x0426), true
+		case "Tab":                             // CHARACTER TABULATION
+			return rune(0x09), true
+		case "Tau":                             // GREEK CAPITAL LETTER TAU
+			return rune(0x03a4), true
+		case "Tcaron":                          // LATIN CAPITAL LETTER T WITH CARON
+			return rune(0x0164), true
+		case "Tcedil":                          // LATIN CAPITAL LETTER T WITH CEDILLA
+			return rune(0x0162), true
+		case "Tcy":                             // CYRILLIC CAPITAL LETTER TE
+			return rune(0x0422), true
+		case "Tfr":                             // MATHEMATICAL FRAKTUR CAPITAL T
+			return rune(0x01d517), true
+		case "Tgr":                             // GREEK CAPITAL LETTER TAU
+			return rune(0x03a4), true
+		case "Therefore":                       // THEREFORE
+			return rune(0x2234), true
+		case "Theta":                           // GREEK CAPITAL LETTER THETA
+			return rune(0x0398), true
+		case "Thetav":                          // GREEK CAPITAL THETA SYMBOL
+			return rune(0x03f4), true
+		case "ThickSpace":                      // space of width 5/18 em
+			return rune(0x205f), true
+		case "ThinSpace":                       // THIN SPACE
+			return rune(0x2009), true
+		case "Tilde":                           // TILDE OPERATOR
+			return rune(0x223c), true
+		case "TildeEqual":                      // ASYMPTOTICALLY EQUAL TO
+			return rune(0x2243), true
+		case "TildeFullEqual":                  // APPROXIMATELY EQUAL TO
+			return rune(0x2245), true
+		case "TildeTilde":                      // ALMOST EQUAL TO
+			return rune(0x2248), true
+		case "Topf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL T
+			return rune(0x01d54b), true
+		case "TripleDot":                       // COMBINING THREE DOTS ABOVE
+			return rune(0x20db), true
+		case "Tscr":                            // MATHEMATICAL SCRIPT CAPITAL T
+			return rune(0x01d4af), true
+		case "Tstrok":                          // LATIN CAPITAL LETTER T WITH STROKE
+			return rune(0x0166), true
 		}
 		}
 
 
 	case 'U':
 	case 'U':
 		switch name {
 		switch name {
-			case "Uacgr":                           // GREEK CAPITAL LETTER UPSILON WITH TONOS
-				return rune(0x038e), true
-			case "Uacute":                          // LATIN CAPITAL LETTER U WITH ACUTE
-				return rune(0xda), true
-			case "Uarr":                            // UPWARDS TWO HEADED ARROW
-				return rune(0x219f), true
-			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
-				return rune(0x016c), true
-			case "Ucirc":                           // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
-				return rune(0xdb), true
-			case "Ucy":                             // CYRILLIC CAPITAL LETTER U
-				return rune(0x0423), true
-			case "Udblac":                          // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
-				return rune(0x0170), true
-			case "Udigr":                           // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
-				return rune(0x03ab), true
-			case "Ufr":                             // MATHEMATICAL FRAKTUR CAPITAL U
-				return rune(0x01d518), true
-			case "Ugr":                             // GREEK CAPITAL LETTER UPSILON
-				return rune(0x03a5), true
-			case "Ugrave":                          // LATIN CAPITAL LETTER U WITH GRAVE
-				return rune(0xd9), true
-			case "Umacr":                           // LATIN CAPITAL LETTER U WITH MACRON
-				return rune(0x016a), true
-			case "UnderBar":                        // LOW LINE
-				return rune(0x5f), true
-			case "UnderBrace":                      // BOTTOM CURLY BRACKET
-				return rune(0x23df), true
-			case "UnderBracket":                    // BOTTOM SQUARE BRACKET
-				return rune(0x23b5), true
-			case "UnderParenthesis":                // BOTTOM PARENTHESIS
-				return rune(0x23dd), true
-			case "Union":                           // N-ARY UNION
-				return rune(0x22c3), true
-			case "UnionPlus":                       // MULTISET UNION
-				return rune(0x228e), true
-			case "Uogon":                           // LATIN CAPITAL LETTER U WITH OGONEK
-				return rune(0x0172), true
-			case "Uopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL U
-				return rune(0x01d54c), true
-			case "UpArrow":                         // UPWARDS ARROW
-				return rune(0x2191), true
-			case "UpArrowBar":                      // UPWARDS ARROW TO BAR
-				return rune(0x2912), true
-			case "UpArrowDownArrow":                // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
-				return rune(0x21c5), true
-			case "UpDownArrow":                     // UP DOWN ARROW
-				return rune(0x2195), true
-			case "UpEquilibrium":                   // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
-				return rune(0x296e), true
-			case "UpTee":                           // UP TACK
-				return rune(0x22a5), true
-			case "UpTeeArrow":                      // UPWARDS ARROW FROM BAR
-				return rune(0x21a5), true
-			case "Uparrow":                         // UPWARDS DOUBLE ARROW
-				return rune(0x21d1), true
-			case "Updownarrow":                     // UP DOWN DOUBLE ARROW
-				return rune(0x21d5), true
-			case "UpperLeftArrow":                  // NORTH WEST ARROW
-				return rune(0x2196), true
-			case "UpperRightArrow":                 // NORTH EAST ARROW
-				return rune(0x2197), true
-			case "Upsi":                            // GREEK UPSILON WITH HOOK SYMBOL
-				return rune(0x03d2), true
-			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
-				return rune(0x01d4b0), true
-			case "Utilde":                          // LATIN CAPITAL LETTER U WITH TILDE
-				return rune(0x0168), true
-			case "Uuml":                            // LATIN CAPITAL LETTER U WITH DIAERESIS
-				return rune(0xdc), true
+		case "Uacgr":                           // GREEK CAPITAL LETTER UPSILON WITH TONOS
+			return rune(0x038e), true
+		case "Uacute":                          // LATIN CAPITAL LETTER U WITH ACUTE
+			return rune(0xda), true
+		case "Uarr":                            // UPWARDS TWO HEADED ARROW
+			return rune(0x219f), true
+		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
+			return rune(0x016c), true
+		case "Ucirc":                           // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+			return rune(0xdb), true
+		case "Ucy":                             // CYRILLIC CAPITAL LETTER U
+			return rune(0x0423), true
+		case "Udblac":                          // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+			return rune(0x0170), true
+		case "Udigr":                           // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+			return rune(0x03ab), true
+		case "Ufr":                             // MATHEMATICAL FRAKTUR CAPITAL U
+			return rune(0x01d518), true
+		case "Ugr":                             // GREEK CAPITAL LETTER UPSILON
+			return rune(0x03a5), true
+		case "Ugrave":                          // LATIN CAPITAL LETTER U WITH GRAVE
+			return rune(0xd9), true
+		case "Umacr":                           // LATIN CAPITAL LETTER U WITH MACRON
+			return rune(0x016a), true
+		case "UnderBar":                        // LOW LINE
+			return rune(0x5f), true
+		case "UnderBrace":                      // BOTTOM CURLY BRACKET
+			return rune(0x23df), true
+		case "UnderBracket":                    // BOTTOM SQUARE BRACKET
+			return rune(0x23b5), true
+		case "UnderParenthesis":                // BOTTOM PARENTHESIS
+			return rune(0x23dd), true
+		case "Union":                           // N-ARY UNION
+			return rune(0x22c3), true
+		case "UnionPlus":                       // MULTISET UNION
+			return rune(0x228e), true
+		case "Uogon":                           // LATIN CAPITAL LETTER U WITH OGONEK
+			return rune(0x0172), true
+		case "Uopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL U
+			return rune(0x01d54c), true
+		case "UpArrow":                         // UPWARDS ARROW
+			return rune(0x2191), true
+		case "UpArrowBar":                      // UPWARDS ARROW TO BAR
+			return rune(0x2912), true
+		case "UpArrowDownArrow":                // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+			return rune(0x21c5), true
+		case "UpDownArrow":                     // UP DOWN ARROW
+			return rune(0x2195), true
+		case "UpEquilibrium":                   // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+			return rune(0x296e), true
+		case "UpTee":                           // UP TACK
+			return rune(0x22a5), true
+		case "UpTeeArrow":                      // UPWARDS ARROW FROM BAR
+			return rune(0x21a5), true
+		case "Uparrow":                         // UPWARDS DOUBLE ARROW
+			return rune(0x21d1), true
+		case "Updownarrow":                     // UP DOWN DOUBLE ARROW
+			return rune(0x21d5), true
+		case "UpperLeftArrow":                  // NORTH WEST ARROW
+			return rune(0x2196), true
+		case "UpperRightArrow":                 // NORTH EAST ARROW
+			return rune(0x2197), true
+		case "Upsi":                            // GREEK UPSILON WITH HOOK SYMBOL
+			return rune(0x03d2), true
+		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
+			return rune(0x01d4b0), true
+		case "Utilde":                          // LATIN CAPITAL LETTER U WITH TILDE
+			return rune(0x0168), true
+		case "Uuml":                            // LATIN CAPITAL LETTER U WITH DIAERESIS
+			return rune(0xdc), true
 		}
 		}
 
 
 	case 'V':
 	case 'V':
 		switch name {
 		switch name {
-			case "VDash":                           // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
-				return rune(0x22ab), true
-			case "Vbar":                            // DOUBLE UP TACK
-				return rune(0x2aeb), true
-			case "Vcy":                             // CYRILLIC CAPITAL LETTER VE
-				return rune(0x0412), true
-			case "Vdash":                           // FORCES
-				return rune(0x22a9), true
-			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
-				return rune(0x2016), true
-			case "Vert":                            // DOUBLE VERTICAL LINE
-				return rune(0x2016), true
-			case "VerticalBar":                     // DIVIDES
-				return rune(0x2223), true
-			case "VerticalLine":                    // VERTICAL LINE
-				return rune(0x7c), true
-			case "VerticalSeparator":               // LIGHT VERTICAL BAR
-				return rune(0x2758), true
-			case "VerticalTilde":                   // WREATH PRODUCT
-				return rune(0x2240), true
-			case "VeryThinSpace":                   // HAIR SPACE
-				return rune(0x200a), true
-			case "Vfr":                             // MATHEMATICAL FRAKTUR CAPITAL V
-				return rune(0x01d519), true
-			case "Vopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL V
-				return rune(0x01d54d), true
-			case "Vscr":                            // MATHEMATICAL SCRIPT CAPITAL V
-				return rune(0x01d4b1), true
-			case "Vvdash":                          // TRIPLE VERTICAL BAR RIGHT TURNSTILE
-				return rune(0x22aa), true
+		case "VDash":                           // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+			return rune(0x22ab), true
+		case "Vbar":                            // DOUBLE UP TACK
+			return rune(0x2aeb), true
+		case "Vcy":                             // CYRILLIC CAPITAL LETTER VE
+			return rune(0x0412), true
+		case "Vdash":                           // FORCES
+			return rune(0x22a9), true
+		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
+			return rune(0x2016), true
+		case "Vert":                            // DOUBLE VERTICAL LINE
+			return rune(0x2016), true
+		case "VerticalBar":                     // DIVIDES
+			return rune(0x2223), true
+		case "VerticalLine":                    // VERTICAL LINE
+			return rune(0x7c), true
+		case "VerticalSeparator":               // LIGHT VERTICAL BAR
+			return rune(0x2758), true
+		case "VerticalTilde":                   // WREATH PRODUCT
+			return rune(0x2240), true
+		case "VeryThinSpace":                   // HAIR SPACE
+			return rune(0x200a), true
+		case "Vfr":                             // MATHEMATICAL FRAKTUR CAPITAL V
+			return rune(0x01d519), true
+		case "Vopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL V
+			return rune(0x01d54d), true
+		case "Vscr":                            // MATHEMATICAL SCRIPT CAPITAL V
+			return rune(0x01d4b1), true
+		case "Vvdash":                          // TRIPLE VERTICAL BAR RIGHT TURNSTILE
+			return rune(0x22aa), true
 		}
 		}
 
 
 	case 'W':
 	case 'W':
 		switch name {
 		switch name {
-			case "Wcirc":                           // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
-				return rune(0x0174), true
-			case "Wedge":                           // N-ARY LOGICAL AND
-				return rune(0x22c0), true
-			case "Wfr":                             // MATHEMATICAL FRAKTUR CAPITAL W
-				return rune(0x01d51a), true
-			case "Wopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL W
-				return rune(0x01d54e), true
-			case "Wscr":                            // MATHEMATICAL SCRIPT CAPITAL W
-				return rune(0x01d4b2), true
+		case "Wcirc":                           // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+			return rune(0x0174), true
+		case "Wedge":                           // N-ARY LOGICAL AND
+			return rune(0x22c0), true
+		case "Wfr":                             // MATHEMATICAL FRAKTUR CAPITAL W
+			return rune(0x01d51a), true
+		case "Wopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL W
+			return rune(0x01d54e), true
+		case "Wscr":                            // MATHEMATICAL SCRIPT CAPITAL W
+			return rune(0x01d4b2), true
 		}
 		}
 
 
 	case 'X':
 	case 'X':
 		switch name {
 		switch name {
-			case "Xfr":                             // MATHEMATICAL FRAKTUR CAPITAL X
-				return rune(0x01d51b), true
-			case "Xgr":                             // GREEK CAPITAL LETTER XI
-				return rune(0x039e), true
-			case "Xi":                              // GREEK CAPITAL LETTER XI
-				return rune(0x039e), true
-			case "Xopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL X
-				return rune(0x01d54f), true
-			case "Xscr":                            // MATHEMATICAL SCRIPT CAPITAL X
-				return rune(0x01d4b3), true
+		case "Xfr":                             // MATHEMATICAL FRAKTUR CAPITAL X
+			return rune(0x01d51b), true
+		case "Xgr":                             // GREEK CAPITAL LETTER XI
+			return rune(0x039e), true
+		case "Xi":                              // GREEK CAPITAL LETTER XI
+			return rune(0x039e), true
+		case "Xopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL X
+			return rune(0x01d54f), true
+		case "Xscr":                            // MATHEMATICAL SCRIPT CAPITAL X
+			return rune(0x01d4b3), true
 		}
 		}
 
 
 	case 'Y':
 	case 'Y':
 		switch name {
 		switch name {
-			case "YAcy":                            // CYRILLIC CAPITAL LETTER YA
-				return rune(0x042f), true
-			case "YIcy":                            // CYRILLIC CAPITAL LETTER YI
-				return rune(0x0407), true
-			case "YUcy":                            // CYRILLIC CAPITAL LETTER YU
-				return rune(0x042e), true
-			case "Yacute":                          // LATIN CAPITAL LETTER Y WITH ACUTE
-				return rune(0xdd), true
-			case "Ycirc":                           // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
-				return rune(0x0176), true
-			case "Ycy":                             // CYRILLIC CAPITAL LETTER YERU
-				return rune(0x042b), true
-			case "Yfr":                             // MATHEMATICAL FRAKTUR CAPITAL Y
-				return rune(0x01d51c), true
-			case "Yopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
-				return rune(0x01d550), true
-			case "Yscr":                            // MATHEMATICAL SCRIPT CAPITAL Y
-				return rune(0x01d4b4), true
-			case "Yuml":                            // LATIN CAPITAL LETTER Y WITH DIAERESIS
-				return rune(0x0178), true
+		case "YAcy":                            // CYRILLIC CAPITAL LETTER YA
+			return rune(0x042f), true
+		case "YIcy":                            // CYRILLIC CAPITAL LETTER YI
+			return rune(0x0407), true
+		case "YUcy":                            // CYRILLIC CAPITAL LETTER YU
+			return rune(0x042e), true
+		case "Yacute":                          // LATIN CAPITAL LETTER Y WITH ACUTE
+			return rune(0xdd), true
+		case "Ycirc":                           // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+			return rune(0x0176), true
+		case "Ycy":                             // CYRILLIC CAPITAL LETTER YERU
+			return rune(0x042b), true
+		case "Yfr":                             // MATHEMATICAL FRAKTUR CAPITAL Y
+			return rune(0x01d51c), true
+		case "Yopf":                            // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+			return rune(0x01d550), true
+		case "Yscr":                            // MATHEMATICAL SCRIPT CAPITAL Y
+			return rune(0x01d4b4), true
+		case "Yuml":                            // LATIN CAPITAL LETTER Y WITH DIAERESIS
+			return rune(0x0178), true
 		}
 		}
 
 
 	case 'Z':
 	case 'Z':
 		switch name {
 		switch name {
-			case "ZHcy":                            // CYRILLIC CAPITAL LETTER ZHE
-				return rune(0x0416), true
-			case "Zacute":                          // LATIN CAPITAL LETTER Z WITH ACUTE
-				return rune(0x0179), true
-			case "Zcaron":                          // LATIN CAPITAL LETTER Z WITH CARON
-				return rune(0x017d), true
-			case "Zcy":                             // CYRILLIC CAPITAL LETTER ZE
-				return rune(0x0417), true
-			case "Zdot":                            // LATIN CAPITAL LETTER Z WITH DOT ABOVE
-				return rune(0x017b), true
-			case "ZeroWidthSpace":                  // ZERO WIDTH SPACE
-				return rune(0x200b), true
-			case "Zeta":                            // GREEK CAPITAL LETTER ZETA
-				return rune(0x0396), true
-			case "Zfr":                             // BLACK-LETTER CAPITAL Z
-				return rune(0x2128), true
-			case "Zgr":                             // GREEK CAPITAL LETTER ZETA
-				return rune(0x0396), true
-			case "Zopf":                            // DOUBLE-STRUCK CAPITAL Z
-				return rune(0x2124), true
-			case "Zscr":                            // MATHEMATICAL SCRIPT CAPITAL Z
-				return rune(0x01d4b5), true
+		case "ZHcy":                            // CYRILLIC CAPITAL LETTER ZHE
+			return rune(0x0416), true
+		case "Zacute":                          // LATIN CAPITAL LETTER Z WITH ACUTE
+			return rune(0x0179), true
+		case "Zcaron":                          // LATIN CAPITAL LETTER Z WITH CARON
+			return rune(0x017d), true
+		case "Zcy":                             // CYRILLIC CAPITAL LETTER ZE
+			return rune(0x0417), true
+		case "Zdot":                            // LATIN CAPITAL LETTER Z WITH DOT ABOVE
+			return rune(0x017b), true
+		case "ZeroWidthSpace":                  // ZERO WIDTH SPACE
+			return rune(0x200b), true
+		case "Zeta":                            // GREEK CAPITAL LETTER ZETA
+			return rune(0x0396), true
+		case "Zfr":                             // BLACK-LETTER CAPITAL Z
+			return rune(0x2128), true
+		case "Zgr":                             // GREEK CAPITAL LETTER ZETA
+			return rune(0x0396), true
+		case "Zopf":                            // DOUBLE-STRUCK CAPITAL Z
+			return rune(0x2124), true
+		case "Zscr":                            // MATHEMATICAL SCRIPT CAPITAL Z
+			return rune(0x01d4b5), true
 		}
 		}
 
 
 	case 'a':
 	case 'a':
 		switch name {
 		switch name {
-			case "aacgr":                           // GREEK SMALL LETTER ALPHA WITH TONOS
-				return rune(0x03ac), true
-			case "aacute":                          // LATIN SMALL LETTER A WITH ACUTE
-				return rune(0xe1), true
-			case "abreve":                          // LATIN SMALL LETTER A WITH BREVE
-				return rune(0x0103), true
-			case "ac":                              // INVERTED LAZY S
-				return rune(0x223e), true
-			case "acE":                             // INVERTED LAZY S with double underline
-				return rune(0x223e), true
-			case "acd":                             // SINE WAVE
-				return rune(0x223f), true
-			case "acirc":                           // LATIN SMALL LETTER A WITH CIRCUMFLEX
-				return rune(0xe2), true
-			case "actuary":                         // COMBINING ANNUITY SYMBOL
-				return rune(0x20e7), true
-			case "acute":                           // ACUTE ACCENT
-				return rune(0xb4), true
-			case "acy":                             // CYRILLIC SMALL LETTER A
-				return rune(0x0430), true
-			case "aelig":                           // LATIN SMALL LETTER AE
-				return rune(0xe6), true
-			case "af":                              // FUNCTION APPLICATION
-				return rune(0x2061), true
-			case "afr":                             // MATHEMATICAL FRAKTUR SMALL A
-				return rune(0x01d51e), true
-			case "agr":                             // GREEK SMALL LETTER ALPHA
-				return rune(0x03b1), true
-			case "agrave":                          // LATIN SMALL LETTER A WITH GRAVE
-				return rune(0xe0), true
-			case "alefsym":                         // ALEF SYMBOL
-				return rune(0x2135), true
-			case "aleph":                           // ALEF SYMBOL
-				return rune(0x2135), true
-			case "alpha":                           // GREEK SMALL LETTER ALPHA
-				return rune(0x03b1), true
-			case "amacr":                           // LATIN SMALL LETTER A WITH MACRON
-				return rune(0x0101), true
-			case "amalg":                           // AMALGAMATION OR COPRODUCT
-				return rune(0x2a3f), true
-			case "amp":                             // AMPERSAND
-				return rune(0x26), true
-			case "and":                             // LOGICAL AND
-				return rune(0x2227), 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 "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
-				return rune(0x299f), true
-			case "ange":                            // ANGLE WITH UNDERBAR
-				return rune(0x29a4), true
-			case "angle":                           // ANGLE
-				return rune(0x2220), true
-			case "angles":                          // ANGLE WITH S INSIDE
-				return rune(0x299e), true
-			case "angmsd":                          // MEASURED ANGLE
-				return rune(0x2221), 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 "angrt":                           // RIGHT ANGLE
-				return rune(0x221f), true
-			case "angrtvb":                         // RIGHT ANGLE WITH ARC
-				return rune(0x22be), true
-			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
-				return rune(0xc5), true
-			case "angupl":                          // REVERSED ANGLE
-				return rune(0x29a3), true
-			case "angzarr":                         // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
-				return rune(0x237c), true
-			case "aogon":                           // LATIN SMALL LETTER A WITH OGONEK
-				return rune(0x0105), true
-			case "aopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL A
-				return rune(0x01d552), true
-			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
-				return rune(0x2a6f), true
-			case "ape":                             // ALMOST EQUAL OR EQUAL TO
-				return rune(0x224a), true
-			case "apid":                            // TRIPLE TILDE
-				return rune(0x224b), true
-			case "apos":                            // APOSTROPHE
-				return rune(0x27), true
-			case "approx":                          // ALMOST EQUAL TO
-				return rune(0x2248), true
-			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
-				return rune(0xe4), true
-			case "awconint":                        // ANTICLOCKWISE CONTOUR INTEGRAL
-				return rune(0x2233), true
-			case "awint":                           // ANTICLOCKWISE INTEGRATION
-				return rune(0x2a11), true
+		case "aacgr":                           // GREEK SMALL LETTER ALPHA WITH TONOS
+			return rune(0x03ac), true
+		case "aacute":                          // LATIN SMALL LETTER A WITH ACUTE
+			return rune(0xe1), true
+		case "abreve":                          // LATIN SMALL LETTER A WITH BREVE
+			return rune(0x0103), true
+		case "ac":                              // INVERTED LAZY S
+			return rune(0x223e), true
+		case "acE":                             // INVERTED LAZY S with double underline
+			return rune(0x223e), true
+		case "acd":                             // SINE WAVE
+			return rune(0x223f), true
+		case "acirc":                           // LATIN SMALL LETTER A WITH CIRCUMFLEX
+			return rune(0xe2), true
+		case "actuary":                         // COMBINING ANNUITY SYMBOL
+			return rune(0x20e7), true
+		case "acute":                           // ACUTE ACCENT
+			return rune(0xb4), true
+		case "acy":                             // CYRILLIC SMALL LETTER A
+			return rune(0x0430), true
+		case "aelig":                           // LATIN SMALL LETTER AE
+			return rune(0xe6), true
+		case "af":                              // FUNCTION APPLICATION
+			return rune(0x2061), true
+		case "afr":                             // MATHEMATICAL FRAKTUR SMALL A
+			return rune(0x01d51e), true
+		case "agr":                             // GREEK SMALL LETTER ALPHA
+			return rune(0x03b1), true
+		case "agrave":                          // LATIN SMALL LETTER A WITH GRAVE
+			return rune(0xe0), true
+		case "alefsym":                         // ALEF SYMBOL
+			return rune(0x2135), true
+		case "aleph":                           // ALEF SYMBOL
+			return rune(0x2135), true
+		case "alpha":                           // GREEK SMALL LETTER ALPHA
+			return rune(0x03b1), true
+		case "amacr":                           // LATIN SMALL LETTER A WITH MACRON
+			return rune(0x0101), true
+		case "amalg":                           // AMALGAMATION OR COPRODUCT
+			return rune(0x2a3f), true
+		case "amp":                             // AMPERSAND
+			return rune(0x26), true
+		case "and":                             // LOGICAL AND
+			return rune(0x2227), 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 "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
+			return rune(0x299f), true
+		case "ange":                            // ANGLE WITH UNDERBAR
+			return rune(0x29a4), true
+		case "angle":                           // ANGLE
+			return rune(0x2220), true
+		case "angles":                          // ANGLE WITH S INSIDE
+			return rune(0x299e), true
+		case "angmsd":                          // MEASURED ANGLE
+			return rune(0x2221), 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 "angrt":                           // RIGHT ANGLE
+			return rune(0x221f), true
+		case "angrtvb":                         // RIGHT ANGLE WITH ARC
+			return rune(0x22be), true
+		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
+			return rune(0xc5), true
+		case "angupl":                          // REVERSED ANGLE
+			return rune(0x29a3), true
+		case "angzarr":                         // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+			return rune(0x237c), true
+		case "aogon":                           // LATIN SMALL LETTER A WITH OGONEK
+			return rune(0x0105), true
+		case "aopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL A
+			return rune(0x01d552), true
+		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
+			return rune(0x2a6f), true
+		case "ape":                             // ALMOST EQUAL OR EQUAL TO
+			return rune(0x224a), true
+		case "apid":                            // TRIPLE TILDE
+			return rune(0x224b), true
+		case "apos":                            // APOSTROPHE
+			return rune(0x27), true
+		case "approx":                          // ALMOST EQUAL TO
+			return rune(0x2248), true
+		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
+			return rune(0xe4), true
+		case "awconint":                        // ANTICLOCKWISE CONTOUR INTEGRAL
+			return rune(0x2233), true
+		case "awint":                           // ANTICLOCKWISE INTEGRATION
+			return rune(0x2a11), true
 		}
 		}
 
 
 	case 'b':
 	case 'b':
 		switch name {
 		switch name {
-			case "b.Delta":                         // MATHEMATICAL BOLD CAPITAL DELTA
-				return rune(0x01d6ab), true
-			case "b.Gamma":                         // MATHEMATICAL BOLD CAPITAL GAMMA
-				return rune(0x01d6aa), true
-			case "b.Gammad":                        // MATHEMATICAL BOLD CAPITAL DIGAMMA
-				return rune(0x01d7ca), true
-			case "b.Lambda":                        // MATHEMATICAL BOLD CAPITAL LAMDA
-				return rune(0x01d6b2), true
-			case "b.Omega":                         // MATHEMATICAL BOLD CAPITAL OMEGA
-				return rune(0x01d6c0), true
-			case "b.Phi":                           // MATHEMATICAL BOLD CAPITAL PHI
-				return rune(0x01d6bd), true
-			case "b.Pi":                            // MATHEMATICAL BOLD CAPITAL PI
-				return rune(0x01d6b7), true
-			case "b.Psi":                           // MATHEMATICAL BOLD CAPITAL PSI
-				return rune(0x01d6bf), true
-			case "b.Sigma":                         // MATHEMATICAL BOLD CAPITAL SIGMA
-				return rune(0x01d6ba), true
-			case "b.Theta":                         // MATHEMATICAL BOLD CAPITAL THETA
-				return rune(0x01d6af), true
-			case "b.Upsi":                          // MATHEMATICAL BOLD CAPITAL UPSILON
-				return rune(0x01d6bc), true
-			case "b.Xi":                            // MATHEMATICAL BOLD CAPITAL XI
-				return rune(0x01d6b5), true
-			case "b.alpha":                         // MATHEMATICAL BOLD SMALL ALPHA
-				return rune(0x01d6c2), true
-			case "b.beta":                          // MATHEMATICAL BOLD SMALL BETA
-				return rune(0x01d6c3), true
-			case "b.chi":                           // MATHEMATICAL BOLD SMALL CHI
-				return rune(0x01d6d8), true
-			case "b.delta":                         // MATHEMATICAL BOLD SMALL DELTA
-				return rune(0x01d6c5), true
-			case "b.epsi":                          // MATHEMATICAL BOLD SMALL EPSILON
-				return rune(0x01d6c6), true
-			case "b.epsiv":                         // MATHEMATICAL BOLD EPSILON SYMBOL
-				return rune(0x01d6dc), true
-			case "b.eta":                           // MATHEMATICAL BOLD SMALL ETA
-				return rune(0x01d6c8), true
-			case "b.gamma":                         // MATHEMATICAL BOLD SMALL GAMMA
-				return rune(0x01d6c4), true
-			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
-				return rune(0x01d6cb), true
-			case "b.kappav":                        // MATHEMATICAL BOLD KAPPA SYMBOL
-				return rune(0x01d6de), true
-			case "b.lambda":                        // MATHEMATICAL BOLD SMALL LAMDA
-				return rune(0x01d6cc), true
-			case "b.mu":                            // MATHEMATICAL BOLD SMALL MU
-				return rune(0x01d6cd), true
-			case "b.nu":                            // MATHEMATICAL BOLD SMALL NU
-				return rune(0x01d6ce), true
-			case "b.omega":                         // MATHEMATICAL BOLD SMALL OMEGA
-				return rune(0x01d6da), true
-			case "b.phi":                           // MATHEMATICAL BOLD SMALL PHI
-				return rune(0x01d6d7), true
-			case "b.phiv":                          // MATHEMATICAL BOLD PHI SYMBOL
-				return rune(0x01d6df), true
-			case "b.pi":                            // MATHEMATICAL BOLD SMALL PI
-				return rune(0x01d6d1), true
-			case "b.piv":                           // MATHEMATICAL BOLD PI SYMBOL
-				return rune(0x01d6e1), true
-			case "b.psi":                           // MATHEMATICAL BOLD SMALL PSI
-				return rune(0x01d6d9), true
-			case "b.rho":                           // MATHEMATICAL BOLD SMALL RHO
-				return rune(0x01d6d2), true
-			case "b.rhov":                          // MATHEMATICAL BOLD RHO SYMBOL
-				return rune(0x01d6e0), true
-			case "b.sigma":                         // MATHEMATICAL BOLD SMALL SIGMA
-				return rune(0x01d6d4), true
-			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
-				return rune(0x01d6c9), true
-			case "b.thetav":                        // MATHEMATICAL BOLD THETA SYMBOL
-				return rune(0x01d6dd), true
-			case "b.upsi":                          // MATHEMATICAL BOLD SMALL UPSILON
-				return rune(0x01d6d6), true
-			case "b.xi":                            // MATHEMATICAL BOLD SMALL XI
-				return rune(0x01d6cf), true
-			case "b.zeta":                          // MATHEMATICAL BOLD SMALL ZETA
-				return rune(0x01d6c7), true
-			case "bNot":                            // REVERSED DOUBLE STROKE NOT SIGN
-				return rune(0x2aed), true
-			case "backcong":                        // ALL EQUAL TO
-				return rune(0x224c), true
-			case "backepsilon":                     // GREEK REVERSED LUNATE EPSILON SYMBOL
-				return rune(0x03f6), true
-			case "backprime":                       // REVERSED PRIME
-				return rune(0x2035), true
-			case "backsim":                         // REVERSED TILDE
-				return rune(0x223d), true
-			case "backsimeq":                       // REVERSED TILDE EQUALS
-				return rune(0x22cd), true
-			case "barV":                            // DOUBLE DOWN TACK
-				return rune(0x2aea), true
-			case "barvee":                          // NOR
-				return rune(0x22bd), true
-			case "barwed":                          // PROJECTIVE
-				return rune(0x2305), true
-			case "barwedge":                        // PROJECTIVE
-				return rune(0x2305), true
-			case "bbrk":                            // BOTTOM SQUARE BRACKET
-				return rune(0x23b5), true
-			case "bbrktbrk":                        // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET
-				return rune(0x23b6), true
-			case "bcong":                           // ALL EQUAL TO
-				return rune(0x224c), true
-			case "bcy":                             // CYRILLIC SMALL LETTER BE
-				return rune(0x0431), true
-			case "bdlhar":                          // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
-				return rune(0x2961), true
-			case "bdquo":                           // DOUBLE LOW-9 QUOTATION MARK
-				return rune(0x201e), true
-			case "bdrhar":                          // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
-				return rune(0x295d), true
-			case "becaus":                          // BECAUSE
-				return rune(0x2235), true
-			case "because":                         // BECAUSE
-				return rune(0x2235), true
-			case "bemptyv":                         // REVERSED EMPTY SET
-				return rune(0x29b0), true
-			case "bepsi":                           // GREEK REVERSED LUNATE EPSILON SYMBOL
-				return rune(0x03f6), true
-			case "bernou":                          // SCRIPT CAPITAL B
-				return rune(0x212c), true
-			case "beta":                            // GREEK SMALL LETTER BETA
-				return rune(0x03b2), true
-			case "beth":                            // BET SYMBOL
-				return rune(0x2136), true
-			case "between":                         // BETWEEN
-				return rune(0x226c), true
-			case "bfr":                             // MATHEMATICAL FRAKTUR SMALL B
-				return rune(0x01d51f), true
-			case "bgr":                             // GREEK SMALL LETTER BETA
-				return rune(0x03b2), true
-			case "bigcap":                          // N-ARY INTERSECTION
-				return rune(0x22c2), true
-			case "bigcirc":                         // LARGE CIRCLE
-				return rune(0x25ef), true
-			case "bigcup":                          // N-ARY UNION
-				return rune(0x22c3), true
-			case "bigodot":                         // N-ARY CIRCLED DOT OPERATOR
-				return rune(0x2a00), true
-			case "bigoplus":                        // N-ARY CIRCLED PLUS OPERATOR
-				return rune(0x2a01), true
-			case "bigotimes":                       // N-ARY CIRCLED TIMES OPERATOR
-				return rune(0x2a02), true
-			case "bigsqcup":                        // N-ARY SQUARE UNION OPERATOR
-				return rune(0x2a06), true
-			case "bigstar":                         // BLACK STAR
-				return rune(0x2605), true
-			case "bigtriangledown":                 // WHITE DOWN-POINTING TRIANGLE
-				return rune(0x25bd), true
-			case "bigtriangleup":                   // WHITE UP-POINTING TRIANGLE
-				return rune(0x25b3), true
-			case "biguplus":                        // N-ARY UNION OPERATOR WITH PLUS
-				return rune(0x2a04), true
-			case "bigvee":                          // N-ARY LOGICAL OR
-				return rune(0x22c1), true
-			case "bigwedge":                        // N-ARY LOGICAL AND
-				return rune(0x22c0), true
-			case "bkarow":                          // RIGHTWARDS DOUBLE DASH ARROW
-				return rune(0x290d), true
-			case "blacklozenge":                    // BLACK LOZENGE
-				return rune(0x29eb), true
-			case "blacksquare":                     // BLACK SMALL SQUARE
-				return rune(0x25aa), true
-			case "blacktriangle":                   // BLACK UP-POINTING SMALL TRIANGLE
-				return rune(0x25b4), 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 "blank":                           // BLANK SYMBOL
-				return rune(0x2422), true
-			case "bldhar":                          // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
-				return rune(0x295e), true
-			case "blk12":                           // MEDIUM SHADE
-				return rune(0x2592), true
-			case "blk14":                           // LIGHT SHADE
-				return rune(0x2591), true
-			case "blk34":                           // DARK SHADE
-				return rune(0x2593), true
-			case "block":                           // FULL BLOCK
-				return rune(0x2588), true
-			case "bluhar":                          // LEFTWARDS HARPOON WITH BARB UP FROM BAR
-				return rune(0x295a), true
-			case "bne":                             // EQUALS SIGN with reverse slash
-				return rune(0x3d), true
-			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
-				return rune(0x01d553), true
-			case "bot":                             // UP TACK
-				return rune(0x22a5), true
-			case "bottom":                          // UP TACK
-				return rune(0x22a5), true
-			case "bowtie":                          // BOWTIE
-				return rune(0x22c8), true
-			case "boxDL":                           // BOX DRAWINGS DOUBLE DOWN AND LEFT
-				return rune(0x2557), true
-			case "boxDR":                           // BOX DRAWINGS DOUBLE DOWN AND RIGHT
-				return rune(0x2554), true
-			case "boxDl":                           // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
-				return rune(0x2556), true
-			case "boxDr":                           // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
-				return rune(0x2553), true
-			case "boxH":                            // BOX DRAWINGS DOUBLE HORIZONTAL
-				return rune(0x2550), 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 "boxUL":                           // BOX DRAWINGS DOUBLE UP AND LEFT
-				return rune(0x255d), true
-			case "boxUR":                           // BOX DRAWINGS DOUBLE UP AND RIGHT
-				return rune(0x255a), true
-			case "boxUl":                           // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
-				return rune(0x255c), true
-			case "boxUr":                           // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
-				return rune(0x2559), true
-			case "boxV":                            // BOX DRAWINGS DOUBLE VERTICAL
-				return rune(0x2551), 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 "boxbox":                          // TWO JOINED SQUARES
-				return rune(0x29c9), true
-			case "boxdL":                           // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
-				return rune(0x2555), true
-			case "boxdR":                           // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
-				return rune(0x2552), true
-			case "boxdl":                           // BOX DRAWINGS LIGHT DOWN AND LEFT
-				return rune(0x2510), true
-			case "boxdr":                           // BOX DRAWINGS LIGHT DOWN AND RIGHT
-				return rune(0x250c), true
-			case "boxh":                            // BOX DRAWINGS LIGHT HORIZONTAL
-				return rune(0x2500), true
-			case "boxhD":                           // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
-				return rune(0x2565), true
-			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
-				return rune(0x2534), true
-			case "boxminus":                        // SQUARED MINUS
-				return rune(0x229f), true
-			case "boxplus":                         // SQUARED PLUS
-				return rune(0x229e), true
-			case "boxtimes":                        // SQUARED TIMES
-				return rune(0x22a0), true
-			case "boxuL":                           // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
-				return rune(0x255b), true
-			case "boxuR":                           // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
-				return rune(0x2558), true
-			case "boxul":                           // BOX DRAWINGS LIGHT UP AND LEFT
-				return rune(0x2518), true
-			case "boxur":                           // BOX DRAWINGS LIGHT UP AND RIGHT
-				return rune(0x2514), true
-			case "boxv":                            // BOX DRAWINGS LIGHT VERTICAL
-				return rune(0x2502), true
-			case "boxvH":                           // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
-				return rune(0x256a), 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 "boxvh":                           // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
-				return rune(0x253c), 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 "bprime":                          // REVERSED PRIME
-				return rune(0x2035), true
-			case "brdhar":                          // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
-				return rune(0x295f), true
-			case "breve":                           // BREVE
-				return rune(0x02d8), true
-			case "bruhar":                          // RIGHTWARDS HARPOON WITH BARB UP FROM BAR
-				return rune(0x295b), true
-			case "brvbar":                          // BROKEN BAR
-				return rune(0xa6), true
-			case "bscr":                            // MATHEMATICAL SCRIPT SMALL B
-				return rune(0x01d4b7), true
-			case "bsemi":                           // REVERSED SEMICOLON
-				return rune(0x204f), true
-			case "bsim":                            // REVERSED TILDE
-				return rune(0x223d), true
-			case "bsime":                           // REVERSED TILDE EQUALS
-				return rune(0x22cd), true
-			case "bsol":                            // REVERSE SOLIDUS
-				return rune(0x5c), true
-			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
-				return rune(0x2960), true
-			case "bull":                            // BULLET
-				return rune(0x2022), true
-			case "bullet":                          // BULLET
-				return rune(0x2022), true
-			case "bump":                            // GEOMETRICALLY EQUIVALENT TO
-				return rune(0x224e), true
-			case "bumpE":                           // EQUALS SIGN WITH BUMPY ABOVE
-				return rune(0x2aae), true
-			case "bumpe":                           // DIFFERENCE BETWEEN
-				return rune(0x224f), true
-			case "bumpeq":                          // DIFFERENCE BETWEEN
-				return rune(0x224f), true
-			case "burhar":                          // UPWARDS HARPOON WITH BARB RIGHT FROM BAR
-				return rune(0x295c), true
+		case "b.Delta":                         // MATHEMATICAL BOLD CAPITAL DELTA
+			return rune(0x01d6ab), true
+		case "b.Gamma":                         // MATHEMATICAL BOLD CAPITAL GAMMA
+			return rune(0x01d6aa), true
+		case "b.Gammad":                        // MATHEMATICAL BOLD CAPITAL DIGAMMA
+			return rune(0x01d7ca), true
+		case "b.Lambda":                        // MATHEMATICAL BOLD CAPITAL LAMDA
+			return rune(0x01d6b2), true
+		case "b.Omega":                         // MATHEMATICAL BOLD CAPITAL OMEGA
+			return rune(0x01d6c0), true
+		case "b.Phi":                           // MATHEMATICAL BOLD CAPITAL PHI
+			return rune(0x01d6bd), true
+		case "b.Pi":                            // MATHEMATICAL BOLD CAPITAL PI
+			return rune(0x01d6b7), true
+		case "b.Psi":                           // MATHEMATICAL BOLD CAPITAL PSI
+			return rune(0x01d6bf), true
+		case "b.Sigma":                         // MATHEMATICAL BOLD CAPITAL SIGMA
+			return rune(0x01d6ba), true
+		case "b.Theta":                         // MATHEMATICAL BOLD CAPITAL THETA
+			return rune(0x01d6af), true
+		case "b.Upsi":                          // MATHEMATICAL BOLD CAPITAL UPSILON
+			return rune(0x01d6bc), true
+		case "b.Xi":                            // MATHEMATICAL BOLD CAPITAL XI
+			return rune(0x01d6b5), true
+		case "b.alpha":                         // MATHEMATICAL BOLD SMALL ALPHA
+			return rune(0x01d6c2), true
+		case "b.beta":                          // MATHEMATICAL BOLD SMALL BETA
+			return rune(0x01d6c3), true
+		case "b.chi":                           // MATHEMATICAL BOLD SMALL CHI
+			return rune(0x01d6d8), true
+		case "b.delta":                         // MATHEMATICAL BOLD SMALL DELTA
+			return rune(0x01d6c5), true
+		case "b.epsi":                          // MATHEMATICAL BOLD SMALL EPSILON
+			return rune(0x01d6c6), true
+		case "b.epsiv":                         // MATHEMATICAL BOLD EPSILON SYMBOL
+			return rune(0x01d6dc), true
+		case "b.eta":                           // MATHEMATICAL BOLD SMALL ETA
+			return rune(0x01d6c8), true
+		case "b.gamma":                         // MATHEMATICAL BOLD SMALL GAMMA
+			return rune(0x01d6c4), true
+		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
+			return rune(0x01d6cb), true
+		case "b.kappav":                        // MATHEMATICAL BOLD KAPPA SYMBOL
+			return rune(0x01d6de), true
+		case "b.lambda":                        // MATHEMATICAL BOLD SMALL LAMDA
+			return rune(0x01d6cc), true
+		case "b.mu":                            // MATHEMATICAL BOLD SMALL MU
+			return rune(0x01d6cd), true
+		case "b.nu":                            // MATHEMATICAL BOLD SMALL NU
+			return rune(0x01d6ce), true
+		case "b.omega":                         // MATHEMATICAL BOLD SMALL OMEGA
+			return rune(0x01d6da), true
+		case "b.phi":                           // MATHEMATICAL BOLD SMALL PHI
+			return rune(0x01d6d7), true
+		case "b.phiv":                          // MATHEMATICAL BOLD PHI SYMBOL
+			return rune(0x01d6df), true
+		case "b.pi":                            // MATHEMATICAL BOLD SMALL PI
+			return rune(0x01d6d1), true
+		case "b.piv":                           // MATHEMATICAL BOLD PI SYMBOL
+			return rune(0x01d6e1), true
+		case "b.psi":                           // MATHEMATICAL BOLD SMALL PSI
+			return rune(0x01d6d9), true
+		case "b.rho":                           // MATHEMATICAL BOLD SMALL RHO
+			return rune(0x01d6d2), true
+		case "b.rhov":                          // MATHEMATICAL BOLD RHO SYMBOL
+			return rune(0x01d6e0), true
+		case "b.sigma":                         // MATHEMATICAL BOLD SMALL SIGMA
+			return rune(0x01d6d4), true
+		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
+			return rune(0x01d6c9), true
+		case "b.thetav":                        // MATHEMATICAL BOLD THETA SYMBOL
+			return rune(0x01d6dd), true
+		case "b.upsi":                          // MATHEMATICAL BOLD SMALL UPSILON
+			return rune(0x01d6d6), true
+		case "b.xi":                            // MATHEMATICAL BOLD SMALL XI
+			return rune(0x01d6cf), true
+		case "b.zeta":                          // MATHEMATICAL BOLD SMALL ZETA
+			return rune(0x01d6c7), true
+		case "bNot":                            // REVERSED DOUBLE STROKE NOT SIGN
+			return rune(0x2aed), true
+		case "backcong":                        // ALL EQUAL TO
+			return rune(0x224c), true
+		case "backepsilon":                     // GREEK REVERSED LUNATE EPSILON SYMBOL
+			return rune(0x03f6), true
+		case "backprime":                       // REVERSED PRIME
+			return rune(0x2035), true
+		case "backsim":                         // REVERSED TILDE
+			return rune(0x223d), true
+		case "backsimeq":                       // REVERSED TILDE EQUALS
+			return rune(0x22cd), true
+		case "barV":                            // DOUBLE DOWN TACK
+			return rune(0x2aea), true
+		case "barvee":                          // NOR
+			return rune(0x22bd), true
+		case "barwed":                          // PROJECTIVE
+			return rune(0x2305), true
+		case "barwedge":                        // PROJECTIVE
+			return rune(0x2305), true
+		case "bbrk":                            // BOTTOM SQUARE BRACKET
+			return rune(0x23b5), true
+		case "bbrktbrk":                        // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET
+			return rune(0x23b6), true
+		case "bcong":                           // ALL EQUAL TO
+			return rune(0x224c), true
+		case "bcy":                             // CYRILLIC SMALL LETTER BE
+			return rune(0x0431), true
+		case "bdlhar":                          // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
+			return rune(0x2961), true
+		case "bdquo":                           // DOUBLE LOW-9 QUOTATION MARK
+			return rune(0x201e), true
+		case "bdrhar":                          // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
+			return rune(0x295d), true
+		case "becaus":                          // BECAUSE
+			return rune(0x2235), true
+		case "because":                         // BECAUSE
+			return rune(0x2235), true
+		case "bemptyv":                         // REVERSED EMPTY SET
+			return rune(0x29b0), true
+		case "bepsi":                           // GREEK REVERSED LUNATE EPSILON SYMBOL
+			return rune(0x03f6), true
+		case "bernou":                          // SCRIPT CAPITAL B
+			return rune(0x212c), true
+		case "beta":                            // GREEK SMALL LETTER BETA
+			return rune(0x03b2), true
+		case "beth":                            // BET SYMBOL
+			return rune(0x2136), true
+		case "between":                         // BETWEEN
+			return rune(0x226c), true
+		case "bfr":                             // MATHEMATICAL FRAKTUR SMALL B
+			return rune(0x01d51f), true
+		case "bgr":                             // GREEK SMALL LETTER BETA
+			return rune(0x03b2), true
+		case "bigcap":                          // N-ARY INTERSECTION
+			return rune(0x22c2), true
+		case "bigcirc":                         // LARGE CIRCLE
+			return rune(0x25ef), true
+		case "bigcup":                          // N-ARY UNION
+			return rune(0x22c3), true
+		case "bigodot":                         // N-ARY CIRCLED DOT OPERATOR
+			return rune(0x2a00), true
+		case "bigoplus":                        // N-ARY CIRCLED PLUS OPERATOR
+			return rune(0x2a01), true
+		case "bigotimes":                       // N-ARY CIRCLED TIMES OPERATOR
+			return rune(0x2a02), true
+		case "bigsqcup":                        // N-ARY SQUARE UNION OPERATOR
+			return rune(0x2a06), true
+		case "bigstar":                         // BLACK STAR
+			return rune(0x2605), true
+		case "bigtriangledown":                 // WHITE DOWN-POINTING TRIANGLE
+			return rune(0x25bd), true
+		case "bigtriangleup":                   // WHITE UP-POINTING TRIANGLE
+			return rune(0x25b3), true
+		case "biguplus":                        // N-ARY UNION OPERATOR WITH PLUS
+			return rune(0x2a04), true
+		case "bigvee":                          // N-ARY LOGICAL OR
+			return rune(0x22c1), true
+		case "bigwedge":                        // N-ARY LOGICAL AND
+			return rune(0x22c0), true
+		case "bkarow":                          // RIGHTWARDS DOUBLE DASH ARROW
+			return rune(0x290d), true
+		case "blacklozenge":                    // BLACK LOZENGE
+			return rune(0x29eb), true
+		case "blacksquare":                     // BLACK SMALL SQUARE
+			return rune(0x25aa), true
+		case "blacktriangle":                   // BLACK UP-POINTING SMALL TRIANGLE
+			return rune(0x25b4), 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 "blank":                           // BLANK SYMBOL
+			return rune(0x2422), true
+		case "bldhar":                          // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
+			return rune(0x295e), true
+		case "blk12":                           // MEDIUM SHADE
+			return rune(0x2592), true
+		case "blk14":                           // LIGHT SHADE
+			return rune(0x2591), true
+		case "blk34":                           // DARK SHADE
+			return rune(0x2593), true
+		case "block":                           // FULL BLOCK
+			return rune(0x2588), true
+		case "bluhar":                          // LEFTWARDS HARPOON WITH BARB UP FROM BAR
+			return rune(0x295a), true
+		case "bne":                             // EQUALS SIGN with reverse slash
+			return rune(0x3d), true
+		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
+			return rune(0x01d553), true
+		case "bot":                             // UP TACK
+			return rune(0x22a5), true
+		case "bottom":                          // UP TACK
+			return rune(0x22a5), true
+		case "bowtie":                          // BOWTIE
+			return rune(0x22c8), true
+		case "boxDL":                           // BOX DRAWINGS DOUBLE DOWN AND LEFT
+			return rune(0x2557), true
+		case "boxDR":                           // BOX DRAWINGS DOUBLE DOWN AND RIGHT
+			return rune(0x2554), true
+		case "boxDl":                           // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+			return rune(0x2556), true
+		case "boxDr":                           // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+			return rune(0x2553), true
+		case "boxH":                            // BOX DRAWINGS DOUBLE HORIZONTAL
+			return rune(0x2550), 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 "boxUL":                           // BOX DRAWINGS DOUBLE UP AND LEFT
+			return rune(0x255d), true
+		case "boxUR":                           // BOX DRAWINGS DOUBLE UP AND RIGHT
+			return rune(0x255a), true
+		case "boxUl":                           // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+			return rune(0x255c), true
+		case "boxUr":                           // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+			return rune(0x2559), true
+		case "boxV":                            // BOX DRAWINGS DOUBLE VERTICAL
+			return rune(0x2551), 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 "boxbox":                          // TWO JOINED SQUARES
+			return rune(0x29c9), true
+		case "boxdL":                           // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+			return rune(0x2555), true
+		case "boxdR":                           // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+			return rune(0x2552), true
+		case "boxdl":                           // BOX DRAWINGS LIGHT DOWN AND LEFT
+			return rune(0x2510), true
+		case "boxdr":                           // BOX DRAWINGS LIGHT DOWN AND RIGHT
+			return rune(0x250c), true
+		case "boxh":                            // BOX DRAWINGS LIGHT HORIZONTAL
+			return rune(0x2500), true
+		case "boxhD":                           // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+			return rune(0x2565), true
+		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
+			return rune(0x2534), true
+		case "boxminus":                        // SQUARED MINUS
+			return rune(0x229f), true
+		case "boxplus":                         // SQUARED PLUS
+			return rune(0x229e), true
+		case "boxtimes":                        // SQUARED TIMES
+			return rune(0x22a0), true
+		case "boxuL":                           // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+			return rune(0x255b), true
+		case "boxuR":                           // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+			return rune(0x2558), true
+		case "boxul":                           // BOX DRAWINGS LIGHT UP AND LEFT
+			return rune(0x2518), true
+		case "boxur":                           // BOX DRAWINGS LIGHT UP AND RIGHT
+			return rune(0x2514), true
+		case "boxv":                            // BOX DRAWINGS LIGHT VERTICAL
+			return rune(0x2502), true
+		case "boxvH":                           // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+			return rune(0x256a), 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 "boxvh":                           // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+			return rune(0x253c), 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 "bprime":                          // REVERSED PRIME
+			return rune(0x2035), true
+		case "brdhar":                          // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
+			return rune(0x295f), true
+		case "breve":                           // BREVE
+			return rune(0x02d8), true
+		case "bruhar":                          // RIGHTWARDS HARPOON WITH BARB UP FROM BAR
+			return rune(0x295b), true
+		case "brvbar":                          // BROKEN BAR
+			return rune(0xa6), true
+		case "bscr":                            // MATHEMATICAL SCRIPT SMALL B
+			return rune(0x01d4b7), true
+		case "bsemi":                           // REVERSED SEMICOLON
+			return rune(0x204f), true
+		case "bsim":                            // REVERSED TILDE
+			return rune(0x223d), true
+		case "bsime":                           // REVERSED TILDE EQUALS
+			return rune(0x22cd), true
+		case "bsol":                            // REVERSE SOLIDUS
+			return rune(0x5c), true
+		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
+			return rune(0x2960), true
+		case "bull":                            // BULLET
+			return rune(0x2022), true
+		case "bullet":                          // BULLET
+			return rune(0x2022), true
+		case "bump":                            // GEOMETRICALLY EQUIVALENT TO
+			return rune(0x224e), true
+		case "bumpE":                           // EQUALS SIGN WITH BUMPY ABOVE
+			return rune(0x2aae), true
+		case "bumpe":                           // DIFFERENCE BETWEEN
+			return rune(0x224f), true
+		case "bumpeq":                          // DIFFERENCE BETWEEN
+			return rune(0x224f), true
+		case "burhar":                          // UPWARDS HARPOON WITH BARB RIGHT FROM BAR
+			return rune(0x295c), true
 		}
 		}
 
 
 	case 'c':
 	case 'c':
 		switch name {
 		switch name {
-			case "cacute":                          // LATIN SMALL LETTER C WITH ACUTE
-				return rune(0x0107), true
-			case "cap":                             // INTERSECTION
-				return rune(0x2229), true
-			case "capand":                          // INTERSECTION WITH LOGICAL AND
-				return rune(0x2a44), true
-			case "capbrcup":                        // INTERSECTION ABOVE BAR ABOVE UNION
-				return rune(0x2a49), true
-			case "capcap":                          // INTERSECTION BESIDE AND JOINED WITH INTERSECTION
-				return rune(0x2a4b), true
-			case "capcup":                          // INTERSECTION ABOVE UNION
-				return rune(0x2a47), true
-			case "capdot":                          // INTERSECTION WITH DOT
-				return rune(0x2a40), true
-			case "capint":                          // INTEGRAL WITH INTERSECTION
-				return rune(0x2a19), true
-			case "caps":                            // INTERSECTION with serifs
-				return rune(0x2229), true
-			case "caret":                           // CARET INSERTION POINT
-				return rune(0x2041), true
-			case "caron":                           // CARON
-				return rune(0x02c7), true
-			case "ccaps":                           // CLOSED INTERSECTION WITH SERIFS
-				return rune(0x2a4d), true
-			case "ccaron":                          // LATIN SMALL LETTER C WITH CARON
-				return rune(0x010d), true
-			case "ccedil":                          // LATIN SMALL LETTER C WITH CEDILLA
-				return rune(0xe7), true
-			case "ccirc":                           // LATIN SMALL LETTER C WITH CIRCUMFLEX
-				return rune(0x0109), true
-			case "ccups":                           // CLOSED UNION WITH SERIFS
-				return rune(0x2a4c), true
-			case "ccupssm":                         // CLOSED UNION WITH SERIFS AND SMASH PRODUCT
-				return rune(0x2a50), true
-			case "cdot":                            // LATIN SMALL LETTER C WITH DOT ABOVE
-				return rune(0x010b), true
-			case "cedil":                           // CEDILLA
-				return rune(0xb8), true
-			case "cemptyv":                         // EMPTY SET WITH SMALL CIRCLE ABOVE
-				return rune(0x29b2), true
-			case "cent":                            // CENT SIGN
-				return rune(0xa2), true
-			case "centerdot":                       // MIDDLE DOT
-				return rune(0xb7), true
-			case "cfr":                             // MATHEMATICAL FRAKTUR SMALL C
-				return rune(0x01d520), true
-			case "chcy":                            // CYRILLIC SMALL LETTER CHE
-				return rune(0x0447), true
-			case "check":                           // CHECK MARK
-				return rune(0x2713), true
-			case "checkmark":                       // CHECK MARK
-				return rune(0x2713), true
-			case "chi":                             // GREEK SMALL LETTER CHI
-				return rune(0x03c7), true
-			case "cir":                             // WHITE CIRCLE
-				return rune(0x25cb), true
-			case "cirE":                            // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT
-				return rune(0x29c3), true
-			case "cirb":                            // SQUARED SMALL CIRCLE
-				return rune(0x29c7), true
-			case "circ":                            // MODIFIER LETTER CIRCUMFLEX ACCENT
-				return rune(0x02c6), 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 "circledR":                        // REGISTERED SIGN
-				return rune(0xae), 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 "cirdarr":                         // WHITE CIRCLE WITH DOWN ARROW
-				return rune(0x29ec), true
-			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
-				return rune(0x29ed), true
-			case "cirferr":                         // ERROR-BARRED BLACK CIRCLE
-				return rune(0x29f3), true
-			case "cirfnint":                        // CIRCULATION FUNCTION
-				return rune(0x2a10), true
-			case "cirmid":                          // VERTICAL LINE WITH CIRCLE ABOVE
-				return rune(0x2aef), true
-			case "cirscir":                         // CIRCLE WITH SMALL CIRCLE TO THE RIGHT
-				return rune(0x29c2), true
-			case "closur":                          // CLOSE UP
-				return rune(0x2050), true
-			case "clubs":                           // BLACK CLUB SUIT
-				return rune(0x2663), true
-			case "clubsuit":                        // BLACK CLUB SUIT
-				return rune(0x2663), true
-			case "colon":                           // COLON
-				return rune(0x3a), true
-			case "colone":                          // COLON EQUALS
-				return rune(0x2254), true
-			case "coloneq":                         // COLON EQUALS
-				return rune(0x2254), true
-			case "comma":                           // COMMA
-				return rune(0x2c), true
-			case "commat":                          // COMMERCIAL AT
-				return rune(0x40), true
-			case "comp":                            // COMPLEMENT
-				return rune(0x2201), true
-			case "compfn":                          // RING OPERATOR
-				return rune(0x2218), true
-			case "complement":                      // COMPLEMENT
-				return rune(0x2201), true
-			case "complexes":                       // DOUBLE-STRUCK CAPITAL C
-				return rune(0x2102), true
-			case "cong":                            // APPROXIMATELY EQUAL TO
-				return rune(0x2245), true
-			case "congdot":                         // CONGRUENT WITH DOT ABOVE
-				return rune(0x2a6d), true
-			case "conint":                          // CONTOUR INTEGRAL
-				return rune(0x222e), true
-			case "copf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL C
-				return rune(0x01d554), true
-			case "coprod":                          // N-ARY COPRODUCT
-				return rune(0x2210), true
-			case "copy":                            // COPYRIGHT SIGN
-				return rune(0xa9), true
-			case "copysr":                          // SOUND RECORDING COPYRIGHT
-				return rune(0x2117), true
-			case "crarr":                           // DOWNWARDS ARROW WITH CORNER LEFTWARDS
-				return rune(0x21b5), true
-			case "cross":                           // BALLOT X
-				return rune(0x2717), true
-			case "cscr":                            // MATHEMATICAL SCRIPT SMALL C
-				return rune(0x01d4b8), true
-			case "csub":                            // CLOSED SUBSET
-				return rune(0x2acf), true
-			case "csube":                           // CLOSED SUBSET OR EQUAL TO
-				return rune(0x2ad1), true
-			case "csup":                            // CLOSED SUPERSET
-				return rune(0x2ad0), true
-			case "csupe":                           // CLOSED SUPERSET OR EQUAL TO
-				return rune(0x2ad2), true
-			case "ctdot":                           // MIDLINE HORIZONTAL ELLIPSIS
-				return rune(0x22ef), true
-			case "cudarrl":                         // RIGHT-SIDE ARC CLOCKWISE ARROW
-				return rune(0x2938), true
-			case "cudarrr":                         // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
-				return rune(0x2935), true
-			case "cuepr":                           // EQUAL TO OR PRECEDES
-				return rune(0x22de), true
-			case "cuesc":                           // EQUAL TO OR SUCCEEDS
-				return rune(0x22df), true
-			case "cularr":                          // ANTICLOCKWISE TOP SEMICIRCLE ARROW
-				return rune(0x21b6), true
-			case "cularrp":                         // TOP ARC ANTICLOCKWISE ARROW WITH PLUS
-				return rune(0x293d), true
-			case "cup":                             // UNION
-				return rune(0x222a), true
-			case "cupbrcap":                        // UNION ABOVE BAR ABOVE INTERSECTION
-				return rune(0x2a48), true
-			case "cupcap":                          // UNION ABOVE INTERSECTION
-				return rune(0x2a46), true
-			case "cupcup":                          // UNION BESIDE AND JOINED WITH UNION
-				return rune(0x2a4a), true
-			case "cupdot":                          // MULTISET MULTIPLICATION
-				return rune(0x228d), true
-			case "cupint":                          // INTEGRAL WITH UNION
-				return rune(0x2a1a), true
-			case "cupor":                           // UNION WITH LOGICAL OR
-				return rune(0x2a45), true
-			case "cupre":                           // PRECEDES OR EQUAL TO
-				return rune(0x227c), true
-			case "cups":                            // UNION with serifs
-				return rune(0x222a), true
-			case "curarr":                          // CLOCKWISE TOP SEMICIRCLE ARROW
-				return rune(0x21b7), true
-			case "curarrm":                         // TOP ARC CLOCKWISE ARROW WITH MINUS
-				return rune(0x293c), true
-			case "curlyeqprec":                     // EQUAL TO OR PRECEDES
-				return rune(0x22de), true
-			case "curlyeqsucc":                     // EQUAL TO OR SUCCEEDS
-				return rune(0x22df), true
-			case "curlyvee":                        // CURLY LOGICAL OR
-				return rune(0x22ce), true
-			case "curlywedge":                      // CURLY LOGICAL AND
-				return rune(0x22cf), true
-			case "curren":                          // CURRENCY SIGN
-				return rune(0xa4), true
-			case "curvearrowleft":                  // ANTICLOCKWISE TOP SEMICIRCLE ARROW
-				return rune(0x21b6), true
-			case "curvearrowright":                 // CLOCKWISE TOP SEMICIRCLE ARROW
-				return rune(0x21b7), true
-			case "cuvee":                           // CURLY LOGICAL OR
-				return rune(0x22ce), true
-			case "cuwed":                           // CURLY LOGICAL AND
-				return rune(0x22cf), true
-			case "cwconint":                        // CLOCKWISE CONTOUR INTEGRAL
-				return rune(0x2232), true
-			case "cwint":                           // CLOCKWISE INTEGRAL
-				return rune(0x2231), true
-			case "cylcty":                          // CYLINDRICITY
-				return rune(0x232d), true
+		case "cacute":                          // LATIN SMALL LETTER C WITH ACUTE
+			return rune(0x0107), true
+		case "cap":                             // INTERSECTION
+			return rune(0x2229), true
+		case "capand":                          // INTERSECTION WITH LOGICAL AND
+			return rune(0x2a44), true
+		case "capbrcup":                        // INTERSECTION ABOVE BAR ABOVE UNION
+			return rune(0x2a49), true
+		case "capcap":                          // INTERSECTION BESIDE AND JOINED WITH INTERSECTION
+			return rune(0x2a4b), true
+		case "capcup":                          // INTERSECTION ABOVE UNION
+			return rune(0x2a47), true
+		case "capdot":                          // INTERSECTION WITH DOT
+			return rune(0x2a40), true
+		case "capint":                          // INTEGRAL WITH INTERSECTION
+			return rune(0x2a19), true
+		case "caps":                            // INTERSECTION with serifs
+			return rune(0x2229), true
+		case "caret":                           // CARET INSERTION POINT
+			return rune(0x2041), true
+		case "caron":                           // CARON
+			return rune(0x02c7), true
+		case "ccaps":                           // CLOSED INTERSECTION WITH SERIFS
+			return rune(0x2a4d), true
+		case "ccaron":                          // LATIN SMALL LETTER C WITH CARON
+			return rune(0x010d), true
+		case "ccedil":                          // LATIN SMALL LETTER C WITH CEDILLA
+			return rune(0xe7), true
+		case "ccirc":                           // LATIN SMALL LETTER C WITH CIRCUMFLEX
+			return rune(0x0109), true
+		case "ccups":                           // CLOSED UNION WITH SERIFS
+			return rune(0x2a4c), true
+		case "ccupssm":                         // CLOSED UNION WITH SERIFS AND SMASH PRODUCT
+			return rune(0x2a50), true
+		case "cdot":                            // LATIN SMALL LETTER C WITH DOT ABOVE
+			return rune(0x010b), true
+		case "cedil":                           // CEDILLA
+			return rune(0xb8), true
+		case "cemptyv":                         // EMPTY SET WITH SMALL CIRCLE ABOVE
+			return rune(0x29b2), true
+		case "cent":                            // CENT SIGN
+			return rune(0xa2), true
+		case "centerdot":                       // MIDDLE DOT
+			return rune(0xb7), true
+		case "cfr":                             // MATHEMATICAL FRAKTUR SMALL C
+			return rune(0x01d520), true
+		case "chcy":                            // CYRILLIC SMALL LETTER CHE
+			return rune(0x0447), true
+		case "check":                           // CHECK MARK
+			return rune(0x2713), true
+		case "checkmark":                       // CHECK MARK
+			return rune(0x2713), true
+		case "chi":                             // GREEK SMALL LETTER CHI
+			return rune(0x03c7), true
+		case "cir":                             // WHITE CIRCLE
+			return rune(0x25cb), true
+		case "cirE":                            // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT
+			return rune(0x29c3), true
+		case "cirb":                            // SQUARED SMALL CIRCLE
+			return rune(0x29c7), true
+		case "circ":                            // MODIFIER LETTER CIRCUMFLEX ACCENT
+			return rune(0x02c6), 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 "circledR":                        // REGISTERED SIGN
+			return rune(0xae), 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 "cirdarr":                         // WHITE CIRCLE WITH DOWN ARROW
+			return rune(0x29ec), true
+		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
+			return rune(0x29ed), true
+		case "cirferr":                         // ERROR-BARRED BLACK CIRCLE
+			return rune(0x29f3), true
+		case "cirfnint":                        // CIRCULATION FUNCTION
+			return rune(0x2a10), true
+		case "cirmid":                          // VERTICAL LINE WITH CIRCLE ABOVE
+			return rune(0x2aef), true
+		case "cirscir":                         // CIRCLE WITH SMALL CIRCLE TO THE RIGHT
+			return rune(0x29c2), true
+		case "closur":                          // CLOSE UP
+			return rune(0x2050), true
+		case "clubs":                           // BLACK CLUB SUIT
+			return rune(0x2663), true
+		case "clubsuit":                        // BLACK CLUB SUIT
+			return rune(0x2663), true
+		case "colon":                           // COLON
+			return rune(0x3a), true
+		case "colone":                          // COLON EQUALS
+			return rune(0x2254), true
+		case "coloneq":                         // COLON EQUALS
+			return rune(0x2254), true
+		case "comma":                           // COMMA
+			return rune(0x2c), true
+		case "commat":                          // COMMERCIAL AT
+			return rune(0x40), true
+		case "comp":                            // COMPLEMENT
+			return rune(0x2201), true
+		case "compfn":                          // RING OPERATOR
+			return rune(0x2218), true
+		case "complement":                      // COMPLEMENT
+			return rune(0x2201), true
+		case "complexes":                       // DOUBLE-STRUCK CAPITAL C
+			return rune(0x2102), true
+		case "cong":                            // APPROXIMATELY EQUAL TO
+			return rune(0x2245), true
+		case "congdot":                         // CONGRUENT WITH DOT ABOVE
+			return rune(0x2a6d), true
+		case "conint":                          // CONTOUR INTEGRAL
+			return rune(0x222e), true
+		case "copf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL C
+			return rune(0x01d554), true
+		case "coprod":                          // N-ARY COPRODUCT
+			return rune(0x2210), true
+		case "copy":                            // COPYRIGHT SIGN
+			return rune(0xa9), true
+		case "copysr":                          // SOUND RECORDING COPYRIGHT
+			return rune(0x2117), true
+		case "crarr":                           // DOWNWARDS ARROW WITH CORNER LEFTWARDS
+			return rune(0x21b5), true
+		case "cross":                           // BALLOT X
+			return rune(0x2717), true
+		case "cscr":                            // MATHEMATICAL SCRIPT SMALL C
+			return rune(0x01d4b8), true
+		case "csub":                            // CLOSED SUBSET
+			return rune(0x2acf), true
+		case "csube":                           // CLOSED SUBSET OR EQUAL TO
+			return rune(0x2ad1), true
+		case "csup":                            // CLOSED SUPERSET
+			return rune(0x2ad0), true
+		case "csupe":                           // CLOSED SUPERSET OR EQUAL TO
+			return rune(0x2ad2), true
+		case "ctdot":                           // MIDLINE HORIZONTAL ELLIPSIS
+			return rune(0x22ef), true
+		case "cudarrl":                         // RIGHT-SIDE ARC CLOCKWISE ARROW
+			return rune(0x2938), true
+		case "cudarrr":                         // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+			return rune(0x2935), true
+		case "cuepr":                           // EQUAL TO OR PRECEDES
+			return rune(0x22de), true
+		case "cuesc":                           // EQUAL TO OR SUCCEEDS
+			return rune(0x22df), true
+		case "cularr":                          // ANTICLOCKWISE TOP SEMICIRCLE ARROW
+			return rune(0x21b6), true
+		case "cularrp":                         // TOP ARC ANTICLOCKWISE ARROW WITH PLUS
+			return rune(0x293d), true
+		case "cup":                             // UNION
+			return rune(0x222a), true
+		case "cupbrcap":                        // UNION ABOVE BAR ABOVE INTERSECTION
+			return rune(0x2a48), true
+		case "cupcap":                          // UNION ABOVE INTERSECTION
+			return rune(0x2a46), true
+		case "cupcup":                          // UNION BESIDE AND JOINED WITH UNION
+			return rune(0x2a4a), true
+		case "cupdot":                          // MULTISET MULTIPLICATION
+			return rune(0x228d), true
+		case "cupint":                          // INTEGRAL WITH UNION
+			return rune(0x2a1a), true
+		case "cupor":                           // UNION WITH LOGICAL OR
+			return rune(0x2a45), true
+		case "cupre":                           // PRECEDES OR EQUAL TO
+			return rune(0x227c), true
+		case "cups":                            // UNION with serifs
+			return rune(0x222a), true
+		case "curarr":                          // CLOCKWISE TOP SEMICIRCLE ARROW
+			return rune(0x21b7), true
+		case "curarrm":                         // TOP ARC CLOCKWISE ARROW WITH MINUS
+			return rune(0x293c), true
+		case "curlyeqprec":                     // EQUAL TO OR PRECEDES
+			return rune(0x22de), true
+		case "curlyeqsucc":                     // EQUAL TO OR SUCCEEDS
+			return rune(0x22df), true
+		case "curlyvee":                        // CURLY LOGICAL OR
+			return rune(0x22ce), true
+		case "curlywedge":                      // CURLY LOGICAL AND
+			return rune(0x22cf), true
+		case "curren":                          // CURRENCY SIGN
+			return rune(0xa4), true
+		case "curvearrowleft":                  // ANTICLOCKWISE TOP SEMICIRCLE ARROW
+			return rune(0x21b6), true
+		case "curvearrowright":                 // CLOCKWISE TOP SEMICIRCLE ARROW
+			return rune(0x21b7), true
+		case "cuvee":                           // CURLY LOGICAL OR
+			return rune(0x22ce), true
+		case "cuwed":                           // CURLY LOGICAL AND
+			return rune(0x22cf), true
+		case "cwconint":                        // CLOCKWISE CONTOUR INTEGRAL
+			return rune(0x2232), true
+		case "cwint":                           // CLOCKWISE INTEGRAL
+			return rune(0x2231), true
+		case "cylcty":                          // CYLINDRICITY
+			return rune(0x232d), true
 		}
 		}
 
 
 	case 'd':
 	case 'd':
 		switch name {
 		switch name {
-			case "dAarr":                           // DOWNWARDS TRIPLE ARROW
-				return rune(0x290b), true
-			case "dArr":                            // DOWNWARDS DOUBLE ARROW
-				return rune(0x21d3), true
-			case "dHar":                            // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
-				return rune(0x2965), true
-			case "dagger":                          // DAGGER
-				return rune(0x2020), true
-			case "dalembrt":                        // SQUARE WITH CONTOURED OUTLINE
-				return rune(0x29e0), true
-			case "daleth":                          // DALET SYMBOL
-				return rune(0x2138), true
-			case "darr":                            // DOWNWARDS ARROW
-				return rune(0x2193), true
-			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
-				return rune(0x2908), true
-			case "dash":                            // HYPHEN
-				return rune(0x2010), true
-			case "dashV":                           // DOUBLE VERTICAL BAR LEFT TURNSTILE
-				return rune(0x2ae3), true
-			case "dashv":                           // LEFT TACK
-				return rune(0x22a3), true
-			case "dbkarow":                         // RIGHTWARDS TRIPLE DASH ARROW
-				return rune(0x290f), true
-			case "dblac":                           // DOUBLE ACUTE ACCENT
-				return rune(0x02dd), true
-			case "dcaron":                          // LATIN SMALL LETTER D WITH CARON
-				return rune(0x010f), true
-			case "dcy":                             // CYRILLIC SMALL LETTER DE
-				return rune(0x0434), true
-			case "dd":                              // DOUBLE-STRUCK ITALIC SMALL D
-				return rune(0x2146), true
-			case "ddagger":                         // DOUBLE DAGGER
-				return rune(0x2021), true
-			case "ddarr":                           // DOWNWARDS PAIRED ARROWS
-				return rune(0x21ca), 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 "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
-				return rune(0x2910), true
-			case "drcorn":                          // BOTTOM RIGHT CORNER
-				return rune(0x231f), true
-			case "drcrop":                          // BOTTOM RIGHT CROP
-				return rune(0x230c), true
-			case "drharb":                          // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
-				return rune(0x2955), true
-			case "dscr":                            // MATHEMATICAL SCRIPT SMALL D
-				return rune(0x01d4b9), true
-			case "dscy":                            // CYRILLIC SMALL LETTER DZE
-				return rune(0x0455), true
-			case "dsol":                            // SOLIDUS WITH OVERBAR
-				return rune(0x29f6), true
-			case "dstrok":                          // LATIN SMALL LETTER D WITH STROKE
-				return rune(0x0111), true
-			case "dtdot":                           // DOWN RIGHT DIAGONAL ELLIPSIS
-				return rune(0x22f1), true
-			case "dtri":                            // WHITE DOWN-POINTING SMALL TRIANGLE
-				return rune(0x25bf), true
-			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
-				return rune(0x29e9), true
-			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
-				return rune(0x296f), true
-			case "dumap":                           // DOUBLE-ENDED MULTIMAP
-				return rune(0x29df), true
-			case "dwangle":                         // OBLIQUE ANGLE OPENING UP
-				return rune(0x29a6), true
-			case "dzcy":                            // CYRILLIC SMALL LETTER DZHE
-				return rune(0x045f), true
-			case "dzigrarr":                        // LONG RIGHTWARDS SQUIGGLE ARROW
-				return rune(0x27ff), true
+		case "dAarr":                           // DOWNWARDS TRIPLE ARROW
+			return rune(0x290b), true
+		case "dArr":                            // DOWNWARDS DOUBLE ARROW
+			return rune(0x21d3), true
+		case "dHar":                            // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+			return rune(0x2965), true
+		case "dagger":                          // DAGGER
+			return rune(0x2020), true
+		case "dalembrt":                        // SQUARE WITH CONTOURED OUTLINE
+			return rune(0x29e0), true
+		case "daleth":                          // DALET SYMBOL
+			return rune(0x2138), true
+		case "darr":                            // DOWNWARDS ARROW
+			return rune(0x2193), true
+		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
+			return rune(0x2908), true
+		case "dash":                            // HYPHEN
+			return rune(0x2010), true
+		case "dashV":                           // DOUBLE VERTICAL BAR LEFT TURNSTILE
+			return rune(0x2ae3), true
+		case "dashv":                           // LEFT TACK
+			return rune(0x22a3), true
+		case "dbkarow":                         // RIGHTWARDS TRIPLE DASH ARROW
+			return rune(0x290f), true
+		case "dblac":                           // DOUBLE ACUTE ACCENT
+			return rune(0x02dd), true
+		case "dcaron":                          // LATIN SMALL LETTER D WITH CARON
+			return rune(0x010f), true
+		case "dcy":                             // CYRILLIC SMALL LETTER DE
+			return rune(0x0434), true
+		case "dd":                              // DOUBLE-STRUCK ITALIC SMALL D
+			return rune(0x2146), true
+		case "ddagger":                         // DOUBLE DAGGER
+			return rune(0x2021), true
+		case "ddarr":                           // DOWNWARDS PAIRED ARROWS
+			return rune(0x21ca), 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 "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
+			return rune(0x2910), true
+		case "drcorn":                          // BOTTOM RIGHT CORNER
+			return rune(0x231f), true
+		case "drcrop":                          // BOTTOM RIGHT CROP
+			return rune(0x230c), true
+		case "drharb":                          // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
+			return rune(0x2955), true
+		case "dscr":                            // MATHEMATICAL SCRIPT SMALL D
+			return rune(0x01d4b9), true
+		case "dscy":                            // CYRILLIC SMALL LETTER DZE
+			return rune(0x0455), true
+		case "dsol":                            // SOLIDUS WITH OVERBAR
+			return rune(0x29f6), true
+		case "dstrok":                          // LATIN SMALL LETTER D WITH STROKE
+			return rune(0x0111), true
+		case "dtdot":                           // DOWN RIGHT DIAGONAL ELLIPSIS
+			return rune(0x22f1), true
+		case "dtri":                            // WHITE DOWN-POINTING SMALL TRIANGLE
+			return rune(0x25bf), true
+		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
+			return rune(0x29e9), true
+		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
+			return rune(0x296f), true
+		case "dumap":                           // DOUBLE-ENDED MULTIMAP
+			return rune(0x29df), true
+		case "dwangle":                         // OBLIQUE ANGLE OPENING UP
+			return rune(0x29a6), true
+		case "dzcy":                            // CYRILLIC SMALL LETTER DZHE
+			return rune(0x045f), true
+		case "dzigrarr":                        // LONG RIGHTWARDS SQUIGGLE ARROW
+			return rune(0x27ff), true
 		}
 		}
 
 
 	case 'e':
 	case 'e':
 		switch name {
 		switch name {
-			case "eDDot":                           // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
-				return rune(0x2a77), true
-			case "eDot":                            // GEOMETRICALLY EQUAL TO
-				return rune(0x2251), true
-			case "eacgr":                           // GREEK SMALL LETTER EPSILON WITH TONOS
-				return rune(0x03ad), true
-			case "eacute":                          // LATIN SMALL LETTER E WITH ACUTE
-				return rune(0xe9), true
-			case "easter":                          // EQUALS WITH ASTERISK
-				return rune(0x2a6e), true
-			case "ecaron":                          // LATIN SMALL LETTER E WITH CARON
-				return rune(0x011b), true
-			case "ecir":                            // RING IN EQUAL TO
-				return rune(0x2256), true
-			case "ecirc":                           // LATIN SMALL LETTER E WITH CIRCUMFLEX
-				return rune(0xea), true
-			case "ecolon":                          // EQUALS COLON
-				return rune(0x2255), true
-			case "ecy":                             // CYRILLIC SMALL LETTER E
-				return rune(0x044d), true
-			case "edot":                            // LATIN SMALL LETTER E WITH DOT ABOVE
-				return rune(0x0117), true
-			case "ee":                              // DOUBLE-STRUCK ITALIC SMALL E
-				return rune(0x2147), true
-			case "eeacgr":                          // GREEK SMALL LETTER ETA WITH TONOS
-				return rune(0x03ae), true
-			case "eegr":                            // GREEK SMALL LETTER ETA
-				return rune(0x03b7), true
-			case "efDot":                           // APPROXIMATELY EQUAL TO OR THE IMAGE OF
-				return rune(0x2252), true
-			case "efr":                             // MATHEMATICAL FRAKTUR SMALL E
-				return rune(0x01d522), true
-			case "eg":                              // DOUBLE-LINE EQUAL TO OR GREATER-THAN
-				return rune(0x2a9a), true
-			case "egr":                             // GREEK SMALL LETTER EPSILON
-				return rune(0x03b5), true
-			case "egrave":                          // LATIN SMALL LETTER E WITH GRAVE
-				return rune(0xe8), 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 "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 "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 "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
-				return rune(0xf0), true
-			case "euml":                            // LATIN SMALL LETTER E WITH DIAERESIS
-				return rune(0xeb), true
-			case "euro":                            // EURO SIGN
-				return rune(0x20ac), true
-			case "excl":                            // EXCLAMATION MARK
-				return rune(0x21), true
-			case "exist":                           // THERE EXISTS
-				return rune(0x2203), true
-			case "expectation":                     // SCRIPT CAPITAL E
-				return rune(0x2130), true
-			case "exponentiale":                    // DOUBLE-STRUCK ITALIC SMALL E
-				return rune(0x2147), true
+		case "eDDot":                           // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
+			return rune(0x2a77), true
+		case "eDot":                            // GEOMETRICALLY EQUAL TO
+			return rune(0x2251), true
+		case "eacgr":                           // GREEK SMALL LETTER EPSILON WITH TONOS
+			return rune(0x03ad), true
+		case "eacute":                          // LATIN SMALL LETTER E WITH ACUTE
+			return rune(0xe9), true
+		case "easter":                          // EQUALS WITH ASTERISK
+			return rune(0x2a6e), true
+		case "ecaron":                          // LATIN SMALL LETTER E WITH CARON
+			return rune(0x011b), true
+		case "ecir":                            // RING IN EQUAL TO
+			return rune(0x2256), true
+		case "ecirc":                           // LATIN SMALL LETTER E WITH CIRCUMFLEX
+			return rune(0xea), true
+		case "ecolon":                          // EQUALS COLON
+			return rune(0x2255), true
+		case "ecy":                             // CYRILLIC SMALL LETTER E
+			return rune(0x044d), true
+		case "edot":                            // LATIN SMALL LETTER E WITH DOT ABOVE
+			return rune(0x0117), true
+		case "ee":                              // DOUBLE-STRUCK ITALIC SMALL E
+			return rune(0x2147), true
+		case "eeacgr":                          // GREEK SMALL LETTER ETA WITH TONOS
+			return rune(0x03ae), true
+		case "eegr":                            // GREEK SMALL LETTER ETA
+			return rune(0x03b7), true
+		case "efDot":                           // APPROXIMATELY EQUAL TO OR THE IMAGE OF
+			return rune(0x2252), true
+		case "efr":                             // MATHEMATICAL FRAKTUR SMALL E
+			return rune(0x01d522), true
+		case "eg":                              // DOUBLE-LINE EQUAL TO OR GREATER-THAN
+			return rune(0x2a9a), true
+		case "egr":                             // GREEK SMALL LETTER EPSILON
+			return rune(0x03b5), true
+		case "egrave":                          // LATIN SMALL LETTER E WITH GRAVE
+			return rune(0xe8), 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 "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 "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 "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
+			return rune(0xf0), true
+		case "euml":                            // LATIN SMALL LETTER E WITH DIAERESIS
+			return rune(0xeb), true
+		case "euro":                            // EURO SIGN
+			return rune(0x20ac), true
+		case "excl":                            // EXCLAMATION MARK
+			return rune(0x21), true
+		case "exist":                           // THERE EXISTS
+			return rune(0x2203), true
+		case "expectation":                     // SCRIPT CAPITAL E
+			return rune(0x2130), true
+		case "exponentiale":                    // DOUBLE-STRUCK ITALIC SMALL E
+			return rune(0x2147), true
 		}
 		}
 
 
 	case 'f':
 	case 'f':
 		switch name {
 		switch name {
-			case "fallingdotseq":                   // APPROXIMATELY EQUAL TO OR THE IMAGE OF
-				return rune(0x2252), true
-			case "fbowtie":                         // BLACK BOWTIE
-				return rune(0x29d3), true
-			case "fcy":                             // CYRILLIC SMALL LETTER EF
-				return rune(0x0444), true
-			case "fdiag":                           // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
-				return rune(0x2572), true
-			case "fdiordi":                         // FALLING DIAGONAL CROSSING RISING DIAGONAL
-				return rune(0x292c), true
-			case "fdonearr":                        // FALLING DIAGONAL CROSSING NORTH EAST ARROW
-				return rune(0x292f), true
-			case "female":                          // FEMALE SIGN
-				return rune(0x2640), true
-			case "ffilig":                          // LATIN SMALL LIGATURE FFI
-				return rune(0xfb03), true
-			case "fflig":                           // LATIN SMALL LIGATURE FF
-				return rune(0xfb00), true
-			case "ffllig":                          // LATIN SMALL LIGATURE FFL
-				return rune(0xfb04), true
-			case "ffr":                             // MATHEMATICAL FRAKTUR SMALL F
-				return rune(0x01d523), true
-			case "fhrglass":                        // BLACK HOURGLASS
-				return rune(0x29d7), true
-			case "filig":                           // LATIN SMALL LIGATURE FI
-				return rune(0xfb01), true
-			case "fjlig":                           // fj ligature
-				return rune(0x66), true
-			case "flat":                            // MUSIC FLAT SIGN
-				return rune(0x266d), true
-			case "fllig":                           // LATIN SMALL LIGATURE FL
-				return rune(0xfb02), true
-			case "fltns":                           // WHITE PARALLELOGRAM
-				return rune(0x25b1), true
-			case "fnof":                            // LATIN SMALL LETTER F WITH HOOK
-				return rune(0x0192), true
-			case "fopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL F
-				return rune(0x01d557), true
-			case "forall":                          // FOR ALL
-				return rune(0x2200), true
-			case "fork":                            // PITCHFORK
-				return rune(0x22d4), true
-			case "forkv":                           // ELEMENT OF OPENING DOWNWARDS
-				return rune(0x2ad9), true
-			case "fpartint":                        // FINITE PART INTEGRAL
-				return rune(0x2a0d), true
-			case "frac12":                          // VULGAR FRACTION ONE HALF
-				return rune(0xbd), true
-			case "frac13":                          // VULGAR FRACTION ONE THIRD
-				return rune(0x2153), true
-			case "frac14":                          // VULGAR FRACTION ONE QUARTER
-				return rune(0xbc), true
-			case "frac15":                          // VULGAR FRACTION ONE FIFTH
-				return rune(0x2155), true
-			case "frac16":                          // VULGAR FRACTION ONE SIXTH
-				return rune(0x2159), true
-			case "frac18":                          // VULGAR FRACTION ONE EIGHTH
-				return rune(0x215b), true
-			case "frac23":                          // VULGAR FRACTION TWO THIRDS
-				return rune(0x2154), true
-			case "frac25":                          // VULGAR FRACTION TWO FIFTHS
-				return rune(0x2156), true
-			case "frac34":                          // VULGAR FRACTION THREE QUARTERS
-				return rune(0xbe), true
-			case "frac35":                          // VULGAR FRACTION THREE FIFTHS
-				return rune(0x2157), true
-			case "frac38":                          // VULGAR FRACTION THREE EIGHTHS
-				return rune(0x215c), true
-			case "frac45":                          // VULGAR FRACTION FOUR FIFTHS
-				return rune(0x2158), true
-			case "frac56":                          // VULGAR FRACTION FIVE SIXTHS
-				return rune(0x215a), true
-			case "frac58":                          // VULGAR FRACTION FIVE EIGHTHS
-				return rune(0x215d), true
-			case "frac78":                          // VULGAR FRACTION SEVEN EIGHTHS
-				return rune(0x215e), true
-			case "frasl":                           // FRACTION SLASH
-				return rune(0x2044), true
-			case "frown":                           // FROWN
-				return rune(0x2322), true
-			case "fscr":                            // MATHEMATICAL SCRIPT SMALL F
-				return rune(0x01d4bb), true
+		case "fallingdotseq":                   // APPROXIMATELY EQUAL TO OR THE IMAGE OF
+			return rune(0x2252), true
+		case "fbowtie":                         // BLACK BOWTIE
+			return rune(0x29d3), true
+		case "fcy":                             // CYRILLIC SMALL LETTER EF
+			return rune(0x0444), true
+		case "fdiag":                           // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
+			return rune(0x2572), true
+		case "fdiordi":                         // FALLING DIAGONAL CROSSING RISING DIAGONAL
+			return rune(0x292c), true
+		case "fdonearr":                        // FALLING DIAGONAL CROSSING NORTH EAST ARROW
+			return rune(0x292f), true
+		case "female":                          // FEMALE SIGN
+			return rune(0x2640), true
+		case "ffilig":                          // LATIN SMALL LIGATURE FFI
+			return rune(0xfb03), true
+		case "fflig":                           // LATIN SMALL LIGATURE FF
+			return rune(0xfb00), true
+		case "ffllig":                          // LATIN SMALL LIGATURE FFL
+			return rune(0xfb04), true
+		case "ffr":                             // MATHEMATICAL FRAKTUR SMALL F
+			return rune(0x01d523), true
+		case "fhrglass":                        // BLACK HOURGLASS
+			return rune(0x29d7), true
+		case "filig":                           // LATIN SMALL LIGATURE FI
+			return rune(0xfb01), true
+		case "fjlig":                           // fj ligature
+			return rune(0x66), true
+		case "flat":                            // MUSIC FLAT SIGN
+			return rune(0x266d), true
+		case "fllig":                           // LATIN SMALL LIGATURE FL
+			return rune(0xfb02), true
+		case "fltns":                           // WHITE PARALLELOGRAM
+			return rune(0x25b1), true
+		case "fnof":                            // LATIN SMALL LETTER F WITH HOOK
+			return rune(0x0192), true
+		case "fopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL F
+			return rune(0x01d557), true
+		case "forall":                          // FOR ALL
+			return rune(0x2200), true
+		case "fork":                            // PITCHFORK
+			return rune(0x22d4), true
+		case "forkv":                           // ELEMENT OF OPENING DOWNWARDS
+			return rune(0x2ad9), true
+		case "fpartint":                        // FINITE PART INTEGRAL
+			return rune(0x2a0d), true
+		case "frac12":                          // VULGAR FRACTION ONE HALF
+			return rune(0xbd), true
+		case "frac13":                          // VULGAR FRACTION ONE THIRD
+			return rune(0x2153), true
+		case "frac14":                          // VULGAR FRACTION ONE QUARTER
+			return rune(0xbc), true
+		case "frac15":                          // VULGAR FRACTION ONE FIFTH
+			return rune(0x2155), true
+		case "frac16":                          // VULGAR FRACTION ONE SIXTH
+			return rune(0x2159), true
+		case "frac18":                          // VULGAR FRACTION ONE EIGHTH
+			return rune(0x215b), true
+		case "frac23":                          // VULGAR FRACTION TWO THIRDS
+			return rune(0x2154), true
+		case "frac25":                          // VULGAR FRACTION TWO FIFTHS
+			return rune(0x2156), true
+		case "frac34":                          // VULGAR FRACTION THREE QUARTERS
+			return rune(0xbe), true
+		case "frac35":                          // VULGAR FRACTION THREE FIFTHS
+			return rune(0x2157), true
+		case "frac38":                          // VULGAR FRACTION THREE EIGHTHS
+			return rune(0x215c), true
+		case "frac45":                          // VULGAR FRACTION FOUR FIFTHS
+			return rune(0x2158), true
+		case "frac56":                          // VULGAR FRACTION FIVE SIXTHS
+			return rune(0x215a), true
+		case "frac58":                          // VULGAR FRACTION FIVE EIGHTHS
+			return rune(0x215d), true
+		case "frac78":                          // VULGAR FRACTION SEVEN EIGHTHS
+			return rune(0x215e), true
+		case "frasl":                           // FRACTION SLASH
+			return rune(0x2044), true
+		case "frown":                           // FROWN
+			return rune(0x2322), true
+		case "fscr":                            // MATHEMATICAL SCRIPT SMALL F
+			return rune(0x01d4bb), true
 		}
 		}
 
 
 	case 'g':
 	case 'g':
 		switch name {
 		switch name {
-			case "gE":                              // GREATER-THAN OVER EQUAL TO
-				return rune(0x2267), true
-			case "gEl":                             // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
-				return rune(0x2a8c), true
-			case "gacute":                          // LATIN SMALL LETTER G WITH ACUTE
-				return rune(0x01f5), true
-			case "gamma":                           // GREEK SMALL LETTER GAMMA
-				return rune(0x03b3), true
-			case "gammad":                          // GREEK SMALL LETTER DIGAMMA
-				return rune(0x03dd), true
-			case "gap":                             // GREATER-THAN OR APPROXIMATE
-				return rune(0x2a86), true
-			case "gbreve":                          // LATIN SMALL LETTER G WITH BREVE
-				return rune(0x011f), true
-			case "gcedil":                          // LATIN SMALL LETTER G WITH CEDILLA
-				return rune(0x0123), true
-			case "gcirc":                           // LATIN SMALL LETTER G WITH CIRCUMFLEX
-				return rune(0x011d), true
-			case "gcy":                             // CYRILLIC SMALL LETTER GHE
-				return rune(0x0433), true
-			case "gdot":                            // LATIN SMALL LETTER G WITH DOT ABOVE
-				return rune(0x0121), true
-			case "ge":                              // GREATER-THAN OR EQUAL TO
-				return rune(0x2265), true
-			case "gel":                             // GREATER-THAN EQUAL TO OR LESS-THAN
-				return rune(0x22db), true
-			case "geq":                             // GREATER-THAN OR EQUAL TO
-				return rune(0x2265), true
-			case "geqq":                            // GREATER-THAN OVER EQUAL TO
-				return rune(0x2267), true
-			case "geqslant":                        // GREATER-THAN OR SLANTED EQUAL TO
-				return rune(0x2a7e), true
-			case "ges":                             // GREATER-THAN OR SLANTED EQUAL TO
-				return rune(0x2a7e), true
-			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
-				return rune(0x2a80), true
-			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
-				return rune(0x2a84), true
-			case "gesl":                            // GREATER-THAN slanted EQUAL TO OR LESS-THAN
-				return rune(0x22db), 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 "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 "gE":                              // GREATER-THAN OVER EQUAL TO
+			return rune(0x2267), true
+		case "gEl":                             // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+			return rune(0x2a8c), true
+		case "gacute":                          // LATIN SMALL LETTER G WITH ACUTE
+			return rune(0x01f5), true
+		case "gamma":                           // GREEK SMALL LETTER GAMMA
+			return rune(0x03b3), true
+		case "gammad":                          // GREEK SMALL LETTER DIGAMMA
+			return rune(0x03dd), true
+		case "gap":                             // GREATER-THAN OR APPROXIMATE
+			return rune(0x2a86), true
+		case "gbreve":                          // LATIN SMALL LETTER G WITH BREVE
+			return rune(0x011f), true
+		case "gcedil":                          // LATIN SMALL LETTER G WITH CEDILLA
+			return rune(0x0123), true
+		case "gcirc":                           // LATIN SMALL LETTER G WITH CIRCUMFLEX
+			return rune(0x011d), true
+		case "gcy":                             // CYRILLIC SMALL LETTER GHE
+			return rune(0x0433), true
+		case "gdot":                            // LATIN SMALL LETTER G WITH DOT ABOVE
+			return rune(0x0121), true
+		case "ge":                              // GREATER-THAN OR EQUAL TO
+			return rune(0x2265), true
+		case "gel":                             // GREATER-THAN EQUAL TO OR LESS-THAN
+			return rune(0x22db), true
+		case "geq":                             // GREATER-THAN OR EQUAL TO
+			return rune(0x2265), true
+		case "geqq":                            // GREATER-THAN OVER EQUAL TO
+			return rune(0x2267), true
+		case "geqslant":                        // GREATER-THAN OR SLANTED EQUAL TO
+			return rune(0x2a7e), true
+		case "ges":                             // GREATER-THAN OR SLANTED EQUAL TO
+			return rune(0x2a7e), true
+		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
+			return rune(0x2a80), true
+		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
+			return rune(0x2a84), true
+		case "gesl":                            // GREATER-THAN slanted EQUAL TO OR LESS-THAN
+			return rune(0x22db), 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 "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':
 	case 'h':
 		switch name {
 		switch name {
-			case "hArr":                            // LEFT RIGHT DOUBLE ARROW
-				return rune(0x21d4), true
-			case "hairsp":                          // HAIR SPACE
-				return rune(0x200a), true
-			case "half":                            // VULGAR FRACTION ONE HALF
-				return rune(0xbd), true
-			case "hamilt":                          // SCRIPT CAPITAL H
-				return rune(0x210b), true
-			case "hardcy":                          // CYRILLIC SMALL LETTER HARD SIGN
-				return rune(0x044a), true
-			case "harr":                            // LEFT RIGHT ARROW
-				return rune(0x2194), true
-			case "harrcir":                         // LEFT RIGHT ARROW THROUGH SMALL CIRCLE
-				return rune(0x2948), true
-			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
-				return rune(0x0125), true
-			case "hearts":                          // BLACK HEART SUIT
-				return rune(0x2665), true
-			case "heartsuit":                       // BLACK HEART SUIT
-				return rune(0x2665), true
-			case "hellip":                          // HORIZONTAL ELLIPSIS
-				return rune(0x2026), true
-			case "hercon":                          // HERMITIAN CONJUGATE MATRIX
-				return rune(0x22b9), true
-			case "hfr":                             // MATHEMATICAL FRAKTUR SMALL H
-				return rune(0x01d525), true
-			case "hksearow":                        // SOUTH EAST ARROW WITH HOOK
-				return rune(0x2925), true
-			case "hkswarow":                        // SOUTH WEST ARROW WITH HOOK
-				return rune(0x2926), true
-			case "hoarr":                           // LEFT RIGHT OPEN-HEADED ARROW
-				return rune(0x21ff), true
-			case "homtht":                          // HOMOTHETIC
-				return rune(0x223b), true
-			case "hookleftarrow":                   // LEFTWARDS ARROW WITH HOOK
-				return rune(0x21a9), true
-			case "hookrightarrow":                  // RIGHTWARDS ARROW WITH HOOK
-				return rune(0x21aa), true
-			case "hopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL H
-				return rune(0x01d559), true
-			case "horbar":                          // HORIZONTAL BAR
-				return rune(0x2015), true
-			case "hrglass":                         // WHITE HOURGLASS
-				return rune(0x29d6), true
-			case "hscr":                            // MATHEMATICAL SCRIPT SMALL H
-				return rune(0x01d4bd), true
-			case "hslash":                          // PLANCK CONSTANT OVER TWO PI
-				return rune(0x210f), true
-			case "hstrok":                          // LATIN SMALL LETTER H WITH STROKE
-				return rune(0x0127), true
-			case "htimes":                          // VECTOR OR CROSS PRODUCT
-				return rune(0x2a2f), true
-			case "hybull":                          // HYPHEN BULLET
-				return rune(0x2043), true
-			case "hyphen":                          // HYPHEN
-				return rune(0x2010), true
+		case "hArr":                            // LEFT RIGHT DOUBLE ARROW
+			return rune(0x21d4), true
+		case "hairsp":                          // HAIR SPACE
+			return rune(0x200a), true
+		case "half":                            // VULGAR FRACTION ONE HALF
+			return rune(0xbd), true
+		case "hamilt":                          // SCRIPT CAPITAL H
+			return rune(0x210b), true
+		case "hardcy":                          // CYRILLIC SMALL LETTER HARD SIGN
+			return rune(0x044a), true
+		case "harr":                            // LEFT RIGHT ARROW
+			return rune(0x2194), true
+		case "harrcir":                         // LEFT RIGHT ARROW THROUGH SMALL CIRCLE
+			return rune(0x2948), true
+		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
+			return rune(0x0125), true
+		case "hearts":                          // BLACK HEART SUIT
+			return rune(0x2665), true
+		case "heartsuit":                       // BLACK HEART SUIT
+			return rune(0x2665), true
+		case "hellip":                          // HORIZONTAL ELLIPSIS
+			return rune(0x2026), true
+		case "hercon":                          // HERMITIAN CONJUGATE MATRIX
+			return rune(0x22b9), true
+		case "hfr":                             // MATHEMATICAL FRAKTUR SMALL H
+			return rune(0x01d525), true
+		case "hksearow":                        // SOUTH EAST ARROW WITH HOOK
+			return rune(0x2925), true
+		case "hkswarow":                        // SOUTH WEST ARROW WITH HOOK
+			return rune(0x2926), true
+		case "hoarr":                           // LEFT RIGHT OPEN-HEADED ARROW
+			return rune(0x21ff), true
+		case "homtht":                          // HOMOTHETIC
+			return rune(0x223b), true
+		case "hookleftarrow":                   // LEFTWARDS ARROW WITH HOOK
+			return rune(0x21a9), true
+		case "hookrightarrow":                  // RIGHTWARDS ARROW WITH HOOK
+			return rune(0x21aa), true
+		case "hopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL H
+			return rune(0x01d559), true
+		case "horbar":                          // HORIZONTAL BAR
+			return rune(0x2015), true
+		case "hrglass":                         // WHITE HOURGLASS
+			return rune(0x29d6), true
+		case "hscr":                            // MATHEMATICAL SCRIPT SMALL H
+			return rune(0x01d4bd), true
+		case "hslash":                          // PLANCK CONSTANT OVER TWO PI
+			return rune(0x210f), true
+		case "hstrok":                          // LATIN SMALL LETTER H WITH STROKE
+			return rune(0x0127), true
+		case "htimes":                          // VECTOR OR CROSS PRODUCT
+			return rune(0x2a2f), true
+		case "hybull":                          // HYPHEN BULLET
+			return rune(0x2043), true
+		case "hyphen":                          // HYPHEN
+			return rune(0x2010), true
 		}
 		}
 
 
 	case 'i':
 	case 'i':
 		switch name {
 		switch name {
-			case "iacgr":                           // GREEK SMALL LETTER IOTA WITH TONOS
-				return rune(0x03af), true
-			case "iacute":                          // LATIN SMALL LETTER I WITH ACUTE
-				return rune(0xed), true
-			case "ic":                              // INVISIBLE SEPARATOR
-				return rune(0x2063), true
-			case "icirc":                           // LATIN SMALL LETTER I WITH CIRCUMFLEX
-				return rune(0xee), true
-			case "icy":                             // CYRILLIC SMALL LETTER I
-				return rune(0x0438), true
-			case "idiagr":                          // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-				return rune(0x0390), true
-			case "idigr":                           // GREEK SMALL LETTER IOTA WITH DIALYTIKA
-				return rune(0x03ca), true
-			case "iecy":                            // CYRILLIC SMALL LETTER IE
-				return rune(0x0435), true
-			case "iexcl":                           // INVERTED EXCLAMATION MARK
-				return rune(0xa1), true
-			case "iff":                             // LEFT RIGHT DOUBLE ARROW
-				return rune(0x21d4), true
-			case "ifr":                             // MATHEMATICAL FRAKTUR SMALL I
-				return rune(0x01d526), true
-			case "igr":                             // GREEK SMALL LETTER IOTA
-				return rune(0x03b9), true
-			case "igrave":                          // LATIN SMALL LETTER I WITH GRAVE
-				return rune(0xec), true
-			case "ii":                              // DOUBLE-STRUCK ITALIC SMALL I
-				return rune(0x2148), true
-			case "iiiint":                          // QUADRUPLE INTEGRAL OPERATOR
-				return rune(0x2a0c), true
-			case "iiint":                           // TRIPLE INTEGRAL
-				return rune(0x222d), true
-			case "iinfin":                          // INCOMPLETE INFINITY
-				return rune(0x29dc), true
-			case "iiota":                           // TURNED GREEK SMALL LETTER IOTA
-				return rune(0x2129), true
-			case "ijlig":                           // LATIN SMALL LIGATURE IJ
-				return rune(0x0133), true
-			case "imacr":                           // LATIN SMALL LETTER I WITH MACRON
-				return rune(0x012b), true
-			case "image":                           // BLACK-LETTER CAPITAL I
-				return rune(0x2111), true
-			case "imagline":                        // SCRIPT CAPITAL I
-				return rune(0x2110), true
-			case "imagpart":                        // BLACK-LETTER CAPITAL I
-				return rune(0x2111), true
-			case "imath":                           // LATIN SMALL LETTER DOTLESS I
-				return rune(0x0131), true
-			case "imof":                            // IMAGE OF
-				return rune(0x22b7), true
-			case "imped":                           // LATIN CAPITAL LETTER Z WITH STROKE
-				return rune(0x01b5), true
-			case "in":                              // ELEMENT OF
-				return rune(0x2208), true
-			case "incare":                          // CARE OF
-				return rune(0x2105), true
-			case "infin":                           // INFINITY
-				return rune(0x221e), true
-			case "infintie":                        // TIE OVER INFINITY
-				return rune(0x29dd), true
-			case "inodot":                          // LATIN SMALL LETTER DOTLESS I
-				return rune(0x0131), true
-			case "int":                             // INTEGRAL
-				return rune(0x222b), true
-			case "intcal":                          // INTERCALATE
-				return rune(0x22ba), true
-			case "integers":                        // DOUBLE-STRUCK CAPITAL Z
-				return rune(0x2124), true
-			case "intercal":                        // INTERCALATE
-				return rune(0x22ba), true
-			case "intlarhk":                        // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
-				return rune(0x2a17), true
-			case "intprod":                         // INTERIOR PRODUCT
-				return rune(0x2a3c), true
-			case "iocy":                            // CYRILLIC SMALL LETTER IO
-				return rune(0x0451), true
-			case "iogon":                           // LATIN SMALL LETTER I WITH OGONEK
-				return rune(0x012f), true
-			case "iopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL I
-				return rune(0x01d55a), true
-			case "iota":                            // GREEK SMALL LETTER IOTA
-				return rune(0x03b9), true
-			case "iprod":                           // INTERIOR PRODUCT
-				return rune(0x2a3c), true
-			case "iprodr":                          // RIGHTHAND INTERIOR PRODUCT
-				return rune(0x2a3d), true
-			case "iquest":                          // INVERTED QUESTION MARK
-				return rune(0xbf), true
-			case "iscr":                            // MATHEMATICAL SCRIPT SMALL I
-				return rune(0x01d4be), true
-			case "isin":                            // ELEMENT OF
-				return rune(0x2208), true
-			case "isinE":                           // ELEMENT OF WITH TWO HORIZONTAL STROKES
-				return rune(0x22f9), true
-			case "isindot":                         // ELEMENT OF WITH DOT ABOVE
-				return rune(0x22f5), true
-			case "isins":                           // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
-				return rune(0x22f4), true
-			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
-				return rune(0x22f8), true
-			case "it":                              // INVISIBLE TIMES
-				return rune(0x2062), true
-			case "itilde":                          // LATIN SMALL LETTER I WITH TILDE
-				return rune(0x0129), true
-			case "iukcy":                           // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
-				return rune(0x0456), true
-			case "iuml":                            // LATIN SMALL LETTER I WITH DIAERESIS
-				return rune(0xef), true
+		case "iacgr":                           // GREEK SMALL LETTER IOTA WITH TONOS
+			return rune(0x03af), true
+		case "iacute":                          // LATIN SMALL LETTER I WITH ACUTE
+			return rune(0xed), true
+		case "ic":                              // INVISIBLE SEPARATOR
+			return rune(0x2063), true
+		case "icirc":                           // LATIN SMALL LETTER I WITH CIRCUMFLEX
+			return rune(0xee), true
+		case "icy":                             // CYRILLIC SMALL LETTER I
+			return rune(0x0438), true
+		case "idiagr":                          // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+			return rune(0x0390), true
+		case "idigr":                           // GREEK SMALL LETTER IOTA WITH DIALYTIKA
+			return rune(0x03ca), true
+		case "iecy":                            // CYRILLIC SMALL LETTER IE
+			return rune(0x0435), true
+		case "iexcl":                           // INVERTED EXCLAMATION MARK
+			return rune(0xa1), true
+		case "iff":                             // LEFT RIGHT DOUBLE ARROW
+			return rune(0x21d4), true
+		case "ifr":                             // MATHEMATICAL FRAKTUR SMALL I
+			return rune(0x01d526), true
+		case "igr":                             // GREEK SMALL LETTER IOTA
+			return rune(0x03b9), true
+		case "igrave":                          // LATIN SMALL LETTER I WITH GRAVE
+			return rune(0xec), true
+		case "ii":                              // DOUBLE-STRUCK ITALIC SMALL I
+			return rune(0x2148), true
+		case "iiiint":                          // QUADRUPLE INTEGRAL OPERATOR
+			return rune(0x2a0c), true
+		case "iiint":                           // TRIPLE INTEGRAL
+			return rune(0x222d), true
+		case "iinfin":                          // INCOMPLETE INFINITY
+			return rune(0x29dc), true
+		case "iiota":                           // TURNED GREEK SMALL LETTER IOTA
+			return rune(0x2129), true
+		case "ijlig":                           // LATIN SMALL LIGATURE IJ
+			return rune(0x0133), true
+		case "imacr":                           // LATIN SMALL LETTER I WITH MACRON
+			return rune(0x012b), true
+		case "image":                           // BLACK-LETTER CAPITAL I
+			return rune(0x2111), true
+		case "imagline":                        // SCRIPT CAPITAL I
+			return rune(0x2110), true
+		case "imagpart":                        // BLACK-LETTER CAPITAL I
+			return rune(0x2111), true
+		case "imath":                           // LATIN SMALL LETTER DOTLESS I
+			return rune(0x0131), true
+		case "imof":                            // IMAGE OF
+			return rune(0x22b7), true
+		case "imped":                           // LATIN CAPITAL LETTER Z WITH STROKE
+			return rune(0x01b5), true
+		case "in":                              // ELEMENT OF
+			return rune(0x2208), true
+		case "incare":                          // CARE OF
+			return rune(0x2105), true
+		case "infin":                           // INFINITY
+			return rune(0x221e), true
+		case "infintie":                        // TIE OVER INFINITY
+			return rune(0x29dd), true
+		case "inodot":                          // LATIN SMALL LETTER DOTLESS I
+			return rune(0x0131), true
+		case "int":                             // INTEGRAL
+			return rune(0x222b), true
+		case "intcal":                          // INTERCALATE
+			return rune(0x22ba), true
+		case "integers":                        // DOUBLE-STRUCK CAPITAL Z
+			return rune(0x2124), true
+		case "intercal":                        // INTERCALATE
+			return rune(0x22ba), true
+		case "intlarhk":                        // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
+			return rune(0x2a17), true
+		case "intprod":                         // INTERIOR PRODUCT
+			return rune(0x2a3c), true
+		case "iocy":                            // CYRILLIC SMALL LETTER IO
+			return rune(0x0451), true
+		case "iogon":                           // LATIN SMALL LETTER I WITH OGONEK
+			return rune(0x012f), true
+		case "iopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL I
+			return rune(0x01d55a), true
+		case "iota":                            // GREEK SMALL LETTER IOTA
+			return rune(0x03b9), true
+		case "iprod":                           // INTERIOR PRODUCT
+			return rune(0x2a3c), true
+		case "iprodr":                          // RIGHTHAND INTERIOR PRODUCT
+			return rune(0x2a3d), true
+		case "iquest":                          // INVERTED QUESTION MARK
+			return rune(0xbf), true
+		case "iscr":                            // MATHEMATICAL SCRIPT SMALL I
+			return rune(0x01d4be), true
+		case "isin":                            // ELEMENT OF
+			return rune(0x2208), true
+		case "isinE":                           // ELEMENT OF WITH TWO HORIZONTAL STROKES
+			return rune(0x22f9), true
+		case "isindot":                         // ELEMENT OF WITH DOT ABOVE
+			return rune(0x22f5), true
+		case "isins":                           // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+			return rune(0x22f4), true
+		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
+			return rune(0x22f8), true
+		case "it":                              // INVISIBLE TIMES
+			return rune(0x2062), true
+		case "itilde":                          // LATIN SMALL LETTER I WITH TILDE
+			return rune(0x0129), true
+		case "iukcy":                           // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+			return rune(0x0456), true
+		case "iuml":                            // LATIN SMALL LETTER I WITH DIAERESIS
+			return rune(0xef), true
 		}
 		}
 
 
 	case 'j':
 	case 'j':
 		switch name {
 		switch name {
-			case "jcirc":                           // LATIN SMALL LETTER J WITH CIRCUMFLEX
-				return rune(0x0135), true
-			case "jcy":                             // CYRILLIC SMALL LETTER SHORT I
-				return rune(0x0439), true
-			case "jfr":                             // MATHEMATICAL FRAKTUR SMALL J
-				return rune(0x01d527), true
-			case "jmath":                           // LATIN SMALL LETTER DOTLESS J
-				return rune(0x0237), true
-			case "jnodot":                          // LATIN SMALL LETTER DOTLESS J
-				return rune(0x0237), true
-			case "jopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL J
-				return rune(0x01d55b), true
-			case "jscr":                            // MATHEMATICAL SCRIPT SMALL J
-				return rune(0x01d4bf), true
-			case "jsercy":                          // CYRILLIC SMALL LETTER JE
-				return rune(0x0458), true
-			case "jukcy":                           // CYRILLIC SMALL LETTER UKRAINIAN IE
-				return rune(0x0454), true
+		case "jcirc":                           // LATIN SMALL LETTER J WITH CIRCUMFLEX
+			return rune(0x0135), true
+		case "jcy":                             // CYRILLIC SMALL LETTER SHORT I
+			return rune(0x0439), true
+		case "jfr":                             // MATHEMATICAL FRAKTUR SMALL J
+			return rune(0x01d527), true
+		case "jmath":                           // LATIN SMALL LETTER DOTLESS J
+			return rune(0x0237), true
+		case "jnodot":                          // LATIN SMALL LETTER DOTLESS J
+			return rune(0x0237), true
+		case "jopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL J
+			return rune(0x01d55b), true
+		case "jscr":                            // MATHEMATICAL SCRIPT SMALL J
+			return rune(0x01d4bf), true
+		case "jsercy":                          // CYRILLIC SMALL LETTER JE
+			return rune(0x0458), true
+		case "jukcy":                           // CYRILLIC SMALL LETTER UKRAINIAN IE
+			return rune(0x0454), true
 		}
 		}
 
 
 	case 'k':
 	case 'k':
 		switch name {
 		switch name {
-			case "kappa":                           // GREEK SMALL LETTER KAPPA
-				return rune(0x03ba), true
-			case "kappav":                          // GREEK KAPPA SYMBOL
-				return rune(0x03f0), true
-			case "kcedil":                          // LATIN SMALL LETTER K WITH CEDILLA
-				return rune(0x0137), true
-			case "kcy":                             // CYRILLIC SMALL LETTER KA
-				return rune(0x043a), true
-			case "kfr":                             // MATHEMATICAL FRAKTUR SMALL K
-				return rune(0x01d528), true
-			case "kgr":                             // GREEK SMALL LETTER KAPPA
-				return rune(0x03ba), true
-			case "kgreen":                          // LATIN SMALL LETTER KRA
-				return rune(0x0138), true
-			case "khcy":                            // CYRILLIC SMALL LETTER HA
-				return rune(0x0445), true
-			case "khgr":                            // GREEK SMALL LETTER CHI
-				return rune(0x03c7), true
-			case "kjcy":                            // CYRILLIC SMALL LETTER KJE
-				return rune(0x045c), true
-			case "kopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL K
-				return rune(0x01d55c), true
-			case "koppa":                           // GREEK LETTER KOPPA
-				return rune(0x03de), true
-			case "kscr":                            // MATHEMATICAL SCRIPT SMALL K
-				return rune(0x01d4c0), true
+		case "kappa":                           // GREEK SMALL LETTER KAPPA
+			return rune(0x03ba), true
+		case "kappav":                          // GREEK KAPPA SYMBOL
+			return rune(0x03f0), true
+		case "kcedil":                          // LATIN SMALL LETTER K WITH CEDILLA
+			return rune(0x0137), true
+		case "kcy":                             // CYRILLIC SMALL LETTER KA
+			return rune(0x043a), true
+		case "kfr":                             // MATHEMATICAL FRAKTUR SMALL K
+			return rune(0x01d528), true
+		case "kgr":                             // GREEK SMALL LETTER KAPPA
+			return rune(0x03ba), true
+		case "kgreen":                          // LATIN SMALL LETTER KRA
+			return rune(0x0138), true
+		case "khcy":                            // CYRILLIC SMALL LETTER HA
+			return rune(0x0445), true
+		case "khgr":                            // GREEK SMALL LETTER CHI
+			return rune(0x03c7), true
+		case "kjcy":                            // CYRILLIC SMALL LETTER KJE
+			return rune(0x045c), true
+		case "kopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL K
+			return rune(0x01d55c), true
+		case "koppa":                           // GREEK LETTER KOPPA
+			return rune(0x03de), true
+		case "kscr":                            // MATHEMATICAL SCRIPT SMALL K
+			return rune(0x01d4c0), true
 		}
 		}
 
 
 	case 'l':
 	case 'l':
 		switch name {
 		switch name {
-			case "lAarr":                           // LEFTWARDS TRIPLE ARROW
-				return rune(0x21da), true
-			case "lArr":                            // LEFTWARDS DOUBLE ARROW
-				return rune(0x21d0), true
-			case "lAtail":                          // LEFTWARDS DOUBLE ARROW-TAIL
-				return rune(0x291b), true
-			case "lBarr":                           // LEFTWARDS TRIPLE DASH ARROW
-				return rune(0x290e), true
-			case "lE":                              // LESS-THAN OVER EQUAL TO
-				return rune(0x2266), true
-			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
-				return rune(0x2962), true
-			case "lacute":                          // LATIN SMALL LETTER L WITH ACUTE
-				return rune(0x013a), true
-			case "laemptyv":                        // EMPTY SET WITH LEFT ARROW ABOVE
-				return rune(0x29b4), true
-			case "lagran":                          // SCRIPT CAPITAL L
-				return rune(0x2112), true
-			case "lambda":                          // GREEK SMALL LETTER LAMDA
-				return rune(0x03bb), true
-			case "lang":                            // MATHEMATICAL LEFT ANGLE BRACKET
-				return rune(0x27e8), true
-			case "langd":                           // LEFT ANGLE BRACKET WITH DOT
-				return rune(0x2991), true
-			case "langle":                          // MATHEMATICAL LEFT ANGLE BRACKET
-				return rune(0x27e8), true
-			case "lap":                             // LESS-THAN OR APPROXIMATE
-				return rune(0x2a85), true
-			case "laquo":                           // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-				return rune(0xab), true
-			case "larr":                            // LEFTWARDS ARROW
-				return rune(0x2190), true
-			case "larr2":                           // LEFTWARDS PAIRED ARROWS
-				return rune(0x21c7), true
-			case "larrb":                           // LEFTWARDS ARROW TO BAR
-				return rune(0x21e4), true
-			case "larrbfs":                         // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND
-				return rune(0x291f), true
-			case "larrfs":                          // LEFTWARDS ARROW TO BLACK DIAMOND
-				return rune(0x291d), true
-			case "larrhk":                          // LEFTWARDS ARROW WITH HOOK
-				return rune(0x21a9), true
-			case "larrlp":                          // LEFTWARDS ARROW WITH LOOP
-				return rune(0x21ab), true
-			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 "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 "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 "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 "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 "lAarr":                           // LEFTWARDS TRIPLE ARROW
+			return rune(0x21da), true
+		case "lArr":                            // LEFTWARDS DOUBLE ARROW
+			return rune(0x21d0), true
+		case "lAtail":                          // LEFTWARDS DOUBLE ARROW-TAIL
+			return rune(0x291b), true
+		case "lBarr":                           // LEFTWARDS TRIPLE DASH ARROW
+			return rune(0x290e), true
+		case "lE":                              // LESS-THAN OVER EQUAL TO
+			return rune(0x2266), true
+		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
+			return rune(0x2962), true
+		case "lacute":                          // LATIN SMALL LETTER L WITH ACUTE
+			return rune(0x013a), true
+		case "laemptyv":                        // EMPTY SET WITH LEFT ARROW ABOVE
+			return rune(0x29b4), true
+		case "lagran":                          // SCRIPT CAPITAL L
+			return rune(0x2112), true
+		case "lambda":                          // GREEK SMALL LETTER LAMDA
+			return rune(0x03bb), true
+		case "lang":                            // MATHEMATICAL LEFT ANGLE BRACKET
+			return rune(0x27e8), true
+		case "langd":                           // LEFT ANGLE BRACKET WITH DOT
+			return rune(0x2991), true
+		case "langle":                          // MATHEMATICAL LEFT ANGLE BRACKET
+			return rune(0x27e8), true
+		case "lap":                             // LESS-THAN OR APPROXIMATE
+			return rune(0x2a85), true
+		case "laquo":                           // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+			return rune(0xab), true
+		case "larr":                            // LEFTWARDS ARROW
+			return rune(0x2190), true
+		case "larr2":                           // LEFTWARDS PAIRED ARROWS
+			return rune(0x21c7), true
+		case "larrb":                           // LEFTWARDS ARROW TO BAR
+			return rune(0x21e4), true
+		case "larrbfs":                         // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND
+			return rune(0x291f), true
+		case "larrfs":                          // LEFTWARDS ARROW TO BLACK DIAMOND
+			return rune(0x291d), true
+		case "larrhk":                          // LEFTWARDS ARROW WITH HOOK
+			return rune(0x21a9), true
+		case "larrlp":                          // LEFTWARDS ARROW WITH LOOP
+			return rune(0x21ab), true
+		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 "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 "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 "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 "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':
 	case 'm':
 		switch name {
 		switch name {
-			case "mDDot":                           // GEOMETRIC PROPORTION
-				return rune(0x223a), true
-			case "macr":                            // MACRON
-				return rune(0xaf), true
-			case "male":                            // MALE SIGN
-				return rune(0x2642), true
-			case "malt":                            // MALTESE CROSS
-				return rune(0x2720), true
-			case "maltese":                         // MALTESE CROSS
-				return rune(0x2720), true
-			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 "mapstoleft":                      // LEFTWARDS ARROW FROM BAR
-				return rune(0x21a4), true
-			case "mapstoup":                        // UPWARDS ARROW FROM BAR
-				return rune(0x21a5), true
-			case "marker":                          // BLACK VERTICAL RECTANGLE
-				return rune(0x25ae), true
-			case "mcomma":                          // MINUS SIGN WITH COMMA ABOVE
-				return rune(0x2a29), true
-			case "mcy":                             // CYRILLIC SMALL LETTER EM
-				return rune(0x043c), true
-			case "mdash":                           // EM DASH
-				return rune(0x2014), true
-			case "measuredangle":                   // MEASURED ANGLE
-				return rune(0x2221), true
-			case "mfr":                             // MATHEMATICAL FRAKTUR SMALL M
-				return rune(0x01d52a), true
-			case "mgr":                             // GREEK SMALL LETTER MU
-				return rune(0x03bc), true
-			case "mho":                             // INVERTED OHM SIGN
-				return rune(0x2127), true
-			case "micro":                           // MICRO SIGN
-				return rune(0xb5), true
-			case "mid":                             // DIVIDES
-				return rune(0x2223), true
-			case "midast":                          // ASTERISK
-				return rune(0x2a), true
-			case "midcir":                          // VERTICAL LINE WITH CIRCLE BELOW
-				return rune(0x2af0), true
-			case "middot":                          // MIDDLE DOT
-				return rune(0xb7), true
-			case "minus":                           // MINUS SIGN
-				return rune(0x2212), true
-			case "minusb":                          // SQUARED MINUS
-				return rune(0x229f), true
-			case "minusd":                          // DOT MINUS
-				return rune(0x2238), true
-			case "minusdu":                         // MINUS SIGN WITH DOT BELOW
-				return rune(0x2a2a), true
-			case "mlcp":                            // TRANSVERSAL INTERSECTION
-				return rune(0x2adb), true
-			case "mldr":                            // HORIZONTAL ELLIPSIS
-				return rune(0x2026), true
-			case "mnplus":                          // MINUS-OR-PLUS SIGN
-				return rune(0x2213), true
-			case "models":                          // MODELS
-				return rune(0x22a7), true
-			case "mopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL M
-				return rune(0x01d55e), true
-			case "mp":                              // MINUS-OR-PLUS SIGN
-				return rune(0x2213), true
-			case "mscr":                            // MATHEMATICAL SCRIPT SMALL M
-				return rune(0x01d4c2), true
-			case "mstpos":                          // INVERTED LAZY S
-				return rune(0x223e), true
-			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 "mDDot":                           // GEOMETRIC PROPORTION
+			return rune(0x223a), true
+		case "macr":                            // MACRON
+			return rune(0xaf), true
+		case "male":                            // MALE SIGN
+			return rune(0x2642), true
+		case "malt":                            // MALTESE CROSS
+			return rune(0x2720), true
+		case "maltese":                         // MALTESE CROSS
+			return rune(0x2720), true
+		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 "mapstoleft":                      // LEFTWARDS ARROW FROM BAR
+			return rune(0x21a4), true
+		case "mapstoup":                        // UPWARDS ARROW FROM BAR
+			return rune(0x21a5), true
+		case "marker":                          // BLACK VERTICAL RECTANGLE
+			return rune(0x25ae), true
+		case "mcomma":                          // MINUS SIGN WITH COMMA ABOVE
+			return rune(0x2a29), true
+		case "mcy":                             // CYRILLIC SMALL LETTER EM
+			return rune(0x043c), true
+		case "mdash":                           // EM DASH
+			return rune(0x2014), true
+		case "measuredangle":                   // MEASURED ANGLE
+			return rune(0x2221), true
+		case "mfr":                             // MATHEMATICAL FRAKTUR SMALL M
+			return rune(0x01d52a), true
+		case "mgr":                             // GREEK SMALL LETTER MU
+			return rune(0x03bc), true
+		case "mho":                             // INVERTED OHM SIGN
+			return rune(0x2127), true
+		case "micro":                           // MICRO SIGN
+			return rune(0xb5), true
+		case "mid":                             // DIVIDES
+			return rune(0x2223), true
+		case "midast":                          // ASTERISK
+			return rune(0x2a), true
+		case "midcir":                          // VERTICAL LINE WITH CIRCLE BELOW
+			return rune(0x2af0), true
+		case "middot":                          // MIDDLE DOT
+			return rune(0xb7), true
+		case "minus":                           // MINUS SIGN
+			return rune(0x2212), true
+		case "minusb":                          // SQUARED MINUS
+			return rune(0x229f), true
+		case "minusd":                          // DOT MINUS
+			return rune(0x2238), true
+		case "minusdu":                         // MINUS SIGN WITH DOT BELOW
+			return rune(0x2a2a), true
+		case "mlcp":                            // TRANSVERSAL INTERSECTION
+			return rune(0x2adb), true
+		case "mldr":                            // HORIZONTAL ELLIPSIS
+			return rune(0x2026), true
+		case "mnplus":                          // MINUS-OR-PLUS SIGN
+			return rune(0x2213), true
+		case "models":                          // MODELS
+			return rune(0x22a7), true
+		case "mopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL M
+			return rune(0x01d55e), true
+		case "mp":                              // MINUS-OR-PLUS SIGN
+			return rune(0x2213), true
+		case "mscr":                            // MATHEMATICAL SCRIPT SMALL M
+			return rune(0x01d4c2), true
+		case "mstpos":                          // INVERTED LAZY S
+			return rune(0x223e), true
+		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':
 	case 'n':
 		switch name {
 		switch name {
-			case "nGg":                             // VERY MUCH GREATER-THAN with slash
-				return rune(0x22d9), true
-			case "nGt":                             // MUCH GREATER THAN with vertical line
-				return rune(0x226b), true
-			case "nGtv":                            // MUCH GREATER THAN with slash
-				return rune(0x226b), true
-			case "nLeftarrow":                      // LEFTWARDS DOUBLE ARROW WITH STROKE
-				return rune(0x21cd), true
-			case "nLeftrightarrow":                 // LEFT RIGHT DOUBLE ARROW WITH STROKE
-				return rune(0x21ce), true
-			case "nLl":                             // VERY MUCH LESS-THAN with slash
-				return rune(0x22d8), true
-			case "nLt":                             // MUCH LESS THAN with vertical line
-				return rune(0x226a), true
-			case "nLtv":                            // MUCH LESS THAN with slash
-				return rune(0x226a), true
-			case "nRightarrow":                     // RIGHTWARDS DOUBLE ARROW WITH STROKE
-				return rune(0x21cf), true
-			case "nVDash":                          // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
-				return rune(0x22af), true
-			case "nVdash":                          // DOES NOT FORCE
-				return rune(0x22ae), true
-			case "nabla":                           // NABLA
-				return rune(0x2207), true
-			case "nacute":                          // LATIN SMALL LETTER N WITH ACUTE
-				return rune(0x0144), true
-			case "nang":                            // ANGLE with vertical line
-				return rune(0x2220), true
-			case "nap":                             // NOT ALMOST EQUAL TO
-				return rune(0x2249), true
-			case "napE":                            // APPROXIMATELY EQUAL OR EQUAL TO with slash
-				return rune(0x2a70), true
-			case "napid":                           // TRIPLE TILDE with slash
-				return rune(0x224b), true
-			case "napos":                           // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
-				return rune(0x0149), true
-			case "napprox":                         // NOT ALMOST EQUAL TO
-				return rune(0x2249), true
-			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 "nbsp":                            // NO-BREAK SPACE
-				return rune(0xa0), true
-			case "nbump":                           // GEOMETRICALLY EQUIVALENT TO with slash
-				return rune(0x224e), true
-			case "nbumpe":                          // DIFFERENCE BETWEEN with slash
-				return rune(0x224f), true
-			case "ncap":                            // INTERSECTION WITH OVERBAR
-				return rune(0x2a43), true
-			case "ncaron":                          // LATIN SMALL LETTER N WITH CARON
-				return rune(0x0148), true
-			case "ncedil":                          // LATIN SMALL LETTER N WITH CEDILLA
-				return rune(0x0146), true
-			case "ncong":                           // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
-				return rune(0x2247), true
-			case "ncongdot":                        // CONGRUENT WITH DOT ABOVE with slash
-				return rune(0x2a6d), true
-			case "ncup":                            // UNION WITH OVERBAR
-				return rune(0x2a42), true
-			case "ncy":                             // CYRILLIC SMALL LETTER EN
-				return rune(0x043d), true
-			case "ndash":                           // EN DASH
-				return rune(0x2013), true
-			case "ne":                              // NOT EQUAL TO
-				return rune(0x2260), true
-			case "neArr":                           // NORTH EAST DOUBLE ARROW
-				return rune(0x21d7), true
-			case "nearhk":                          // NORTH EAST ARROW WITH HOOK
-				return rune(0x2924), true
-			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
-				return rune(0x292e), true
-			case "nequiv":                          // NOT IDENTICAL TO
-				return rune(0x2262), true
-			case "nesear":                          // NORTH EAST ARROW AND SOUTH EAST ARROW
-				return rune(0x2928), true
-			case "nesim":                           // MINUS TILDE with slash
-				return rune(0x2242), true
-			case "neswsarr":                        // NORTH EAST AND SOUTH WEST ARROW
-				return rune(0x2922), true
-			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
-				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 "ngeqq":                           // GREATER-THAN OVER EQUAL TO with slash
-				return rune(0x2267), true
-			case "ngeqslant":                       // GREATER-THAN OR SLANTED EQUAL TO with slash
-				return rune(0x2a7e), true
-			case "nges":                            // GREATER-THAN OR SLANTED EQUAL TO with slash
-				return rune(0x2a7e), true
-			case "ngr":                             // GREEK SMALL LETTER NU
-				return rune(0x03bd), true
-			case "ngsim":                           // NEITHER GREATER-THAN NOR EQUIVALENT TO
-				return rune(0x2275), true
-			case "ngt":                             // NOT GREATER-THAN
-				return rune(0x226f), true
-			case "ngtr":                            // NOT GREATER-THAN
-				return rune(0x226f), true
-			case "nhArr":                           // LEFT RIGHT DOUBLE ARROW WITH STROKE
-				return rune(0x21ce), true
-			case "nharr":                           // LEFT RIGHT ARROW WITH STROKE
-				return rune(0x21ae), true
-			case "nhpar":                           // PARALLEL WITH HORIZONTAL STROKE
-				return rune(0x2af2), true
-			case "ni":                              // CONTAINS AS MEMBER
-				return rune(0x220b), true
-			case "nis":                             // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
-				return rune(0x22fc), true
-			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
-				return rune(0x21cd), true
-			case "nlE":                             // LESS-THAN OVER EQUAL TO with slash
-				return rune(0x2266), true
-			case "nlarr":                           // LEFTWARDS ARROW WITH STROKE
-				return rune(0x219a), true
-			case "nldr":                            // TWO DOT LEADER
-				return rune(0x2025), true
-			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
-				return rune(0x21ae), true
-			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 "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 "nlsim":                           // NEITHER LESS-THAN NOR EQUIVALENT TO
-				return rune(0x2274), true
-			case "nlt":                             // NOT LESS-THAN
-				return rune(0x226e), true
-			case "nltri":                           // NOT NORMAL SUBGROUP OF
-				return rune(0x22ea), true
-			case "nltrie":                          // NOT NORMAL SUBGROUP OF OR EQUAL TO
-				return rune(0x22ec), true
-			case "nltrivb":                         // LEFT TRIANGLE BESIDE VERTICAL BAR with slash
-				return rune(0x29cf), true
-			case "nmid":                            // DOES NOT DIVIDE
-				return rune(0x2224), true
-			case "nopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL N
-				return rune(0x01d55f), true
-			case "not":                             // NOT SIGN
-				return rune(0xac), 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 "npar":                            // NOT PARALLEL TO
-				return rune(0x2226), true
-			case "nparallel":                       // NOT PARALLEL TO
-				return rune(0x2226), true
-			case "nparsl":                          // DOUBLE SOLIDUS OPERATOR with reverse slash
-				return rune(0x2afd), true
-			case "npart":                           // PARTIAL DIFFERENTIAL with slash
-				return rune(0x2202), true
-			case "npolint":                         // LINE INTEGRATION NOT INCLUDING THE POLE
-				return rune(0x2a14), true
-			case "npr":                             // DOES NOT PRECEDE
-				return rune(0x2280), true
-			case "nprcue":                          // DOES NOT PRECEDE OR EQUAL
-				return rune(0x22e0), true
-			case "npre":                            // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
-				return rune(0x2aaf), true
-			case "nprec":                           // DOES NOT PRECEDE
-				return rune(0x2280), true
-			case "npreceq":                         // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
-				return rune(0x2aaf), true
-			case "nprsim":                          // PRECEDES OR EQUIVALENT TO with slash
-				return rune(0x227e), true
-			case "nrArr":                           // RIGHTWARDS DOUBLE ARROW WITH STROKE
-				return rune(0x21cf), true
-			case "nrarr":                           // RIGHTWARDS ARROW WITH STROKE
-				return rune(0x219b), true
-			case "nrarrc":                          // WAVE ARROW POINTING DIRECTLY RIGHT with slash
-				return rune(0x2933), true
-			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
-				return rune(0x22eb), true
-			case "nrtrie":                          // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
-				return rune(0x22ed), true
-			case "nsGt":                            // DOUBLE NESTED GREATER-THAN with slash
-				return rune(0x2aa2), true
-			case "nsLt":                            // DOUBLE NESTED LESS-THAN with slash
-				return rune(0x2aa1), true
-			case "nsc":                             // DOES NOT SUCCEED
-				return rune(0x2281), true
-			case "nsccue":                          // DOES NOT SUCCEED OR EQUAL
-				return rune(0x22e1), true
-			case "nsce":                            // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
-				return rune(0x2ab0), true
-			case "nscr":                            // MATHEMATICAL SCRIPT SMALL N
-				return rune(0x01d4c3), true
-			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
-				return rune(0x2226), true
-			case "nsim":                            // NOT TILDE
-				return rune(0x2241), true
-			case "nsime":                           // NOT ASYMPTOTICALLY EQUAL TO
-				return rune(0x2244), true
-			case "nsimeq":                          // NOT ASYMPTOTICALLY EQUAL TO
-				return rune(0x2244), true
-			case "nsmid":                           // DOES NOT DIVIDE
-				return rune(0x2224), true
-			case "nspar":                           // NOT PARALLEL TO
-				return rune(0x2226), true
-			case "nsqsub":                          // SQUARE IMAGE OF with slash
-				return rune(0x228f), true
-			case "nsqsube":                         // NOT SQUARE IMAGE OF OR EQUAL TO
-				return rune(0x22e2), true
-			case "nsqsup":                          // SQUARE ORIGINAL OF with slash
-				return rune(0x2290), true
-			case "nsqsupe":                         // NOT SQUARE ORIGINAL OF OR EQUAL TO
-				return rune(0x22e3), true
-			case "nsub":                            // NOT A SUBSET OF
-				return rune(0x2284), true
-			case "nsubE":                           // SUBSET OF ABOVE EQUALS SIGN with slash
-				return rune(0x2ac5), true
-			case "nsube":                           // NEITHER A SUBSET OF NOR EQUAL TO
-				return rune(0x2288), true
-			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
-				return rune(0x2ac5), true
-			case "nsucc":                           // DOES NOT SUCCEED
-				return rune(0x2281), true
-			case "nsucceq":                         // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
-				return rune(0x2ab0), true
-			case "nsup":                            // NOT A SUPERSET OF
-				return rune(0x2285), true
-			case "nsupE":                           // SUPERSET OF ABOVE EQUALS SIGN with slash
-				return rune(0x2ac6), true
-			case "nsupe":                           // NEITHER A SUPERSET OF NOR EQUAL TO
-				return rune(0x2289), true
-			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
-				return rune(0x2ac6), true
-			case "ntgl":                            // NEITHER GREATER-THAN NOR LESS-THAN
-				return rune(0x2279), true
-			case "ntilde":                          // LATIN SMALL LETTER N WITH TILDE
-				return rune(0xf1), true
-			case "ntlg":                            // NEITHER LESS-THAN NOR GREATER-THAN
-				return rune(0x2278), true
-			case "ntriangleleft":                   // NOT NORMAL SUBGROUP OF
-				return rune(0x22ea), true
-			case "ntrianglelefteq":                 // NOT NORMAL SUBGROUP OF OR EQUAL TO
-				return rune(0x22ec), true
-			case "ntriangleright":                  // DOES NOT CONTAIN AS NORMAL SUBGROUP
-				return rune(0x22eb), true
-			case "ntrianglerighteq":                // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
-				return rune(0x22ed), true
-			case "nu":                              // GREEK SMALL LETTER NU
-				return rune(0x03bd), true
-			case "num":                             // NUMBER SIGN
-				return rune(0x23), 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
-				return rune(0x2904), true
-			case "nvap":                            // EQUIVALENT TO with vertical line
-				return rune(0x224d), true
-			case "nvbrtri":                         // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
-				return rune(0x29d0), true
-			case "nvdash":                          // DOES NOT PROVE
-				return rune(0x22ac), true
-			case "nvge":                            // GREATER-THAN OR EQUAL TO with vertical line
-				return rune(0x2265), true
-			case "nvgt":                            // GREATER-THAN SIGN with vertical line
-				return rune(0x3e), true
-			case "nvinfin":                         // INFINITY NEGATED WITH VERTICAL BAR
-				return rune(0x29de), true
-			case "nvlArr":                          // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
-				return rune(0x2902), true
-			case "nvle":                            // LESS-THAN OR EQUAL TO with vertical line
-				return rune(0x2264), true
-			case "nvlt":                            // LESS-THAN SIGN with vertical line
-				return rune(0x3c), true
-			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
-				return rune(0x22b5), true
-			case "nvsim":                           // TILDE OPERATOR with vertical line
-				return rune(0x223c), true
-			case "nwArr":                           // NORTH WEST DOUBLE ARROW
-				return rune(0x21d6), true
-			case "nwarhk":                          // NORTH WEST ARROW WITH HOOK
-				return rune(0x2923), true
-			case "nwarr":                           // NORTH WEST ARROW
-				return rune(0x2196), true
-			case "nwarrow":                         // NORTH WEST ARROW
-				return rune(0x2196), true
-			case "nwnear":                          // NORTH WEST ARROW AND NORTH EAST ARROW
-				return rune(0x2927), true
-			case "nwonearr":                        // NORTH WEST ARROW CROSSING NORTH EAST ARROW
-				return rune(0x2932), true
-			case "nwsesarr":                        // NORTH WEST AND SOUTH EAST ARROW
-				return rune(0x2921), true
+		case "nGg":                             // VERY MUCH GREATER-THAN with slash
+			return rune(0x22d9), true
+		case "nGt":                             // MUCH GREATER THAN with vertical line
+			return rune(0x226b), true
+		case "nGtv":                            // MUCH GREATER THAN with slash
+			return rune(0x226b), true
+		case "nLeftarrow":                      // LEFTWARDS DOUBLE ARROW WITH STROKE
+			return rune(0x21cd), true
+		case "nLeftrightarrow":                 // LEFT RIGHT DOUBLE ARROW WITH STROKE
+			return rune(0x21ce), true
+		case "nLl":                             // VERY MUCH LESS-THAN with slash
+			return rune(0x22d8), true
+		case "nLt":                             // MUCH LESS THAN with vertical line
+			return rune(0x226a), true
+		case "nLtv":                            // MUCH LESS THAN with slash
+			return rune(0x226a), true
+		case "nRightarrow":                     // RIGHTWARDS DOUBLE ARROW WITH STROKE
+			return rune(0x21cf), true
+		case "nVDash":                          // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+			return rune(0x22af), true
+		case "nVdash":                          // DOES NOT FORCE
+			return rune(0x22ae), true
+		case "nabla":                           // NABLA
+			return rune(0x2207), true
+		case "nacute":                          // LATIN SMALL LETTER N WITH ACUTE
+			return rune(0x0144), true
+		case "nang":                            // ANGLE with vertical line
+			return rune(0x2220), true
+		case "nap":                             // NOT ALMOST EQUAL TO
+			return rune(0x2249), true
+		case "napE":                            // APPROXIMATELY EQUAL OR EQUAL TO with slash
+			return rune(0x2a70), true
+		case "napid":                           // TRIPLE TILDE with slash
+			return rune(0x224b), true
+		case "napos":                           // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+			return rune(0x0149), true
+		case "napprox":                         // NOT ALMOST EQUAL TO
+			return rune(0x2249), true
+		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 "nbsp":                            // NO-BREAK SPACE
+			return rune(0xa0), true
+		case "nbump":                           // GEOMETRICALLY EQUIVALENT TO with slash
+			return rune(0x224e), true
+		case "nbumpe":                          // DIFFERENCE BETWEEN with slash
+			return rune(0x224f), true
+		case "ncap":                            // INTERSECTION WITH OVERBAR
+			return rune(0x2a43), true
+		case "ncaron":                          // LATIN SMALL LETTER N WITH CARON
+			return rune(0x0148), true
+		case "ncedil":                          // LATIN SMALL LETTER N WITH CEDILLA
+			return rune(0x0146), true
+		case "ncong":                           // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+			return rune(0x2247), true
+		case "ncongdot":                        // CONGRUENT WITH DOT ABOVE with slash
+			return rune(0x2a6d), true
+		case "ncup":                            // UNION WITH OVERBAR
+			return rune(0x2a42), true
+		case "ncy":                             // CYRILLIC SMALL LETTER EN
+			return rune(0x043d), true
+		case "ndash":                           // EN DASH
+			return rune(0x2013), true
+		case "ne":                              // NOT EQUAL TO
+			return rune(0x2260), true
+		case "neArr":                           // NORTH EAST DOUBLE ARROW
+			return rune(0x21d7), true
+		case "nearhk":                          // NORTH EAST ARROW WITH HOOK
+			return rune(0x2924), true
+		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
+			return rune(0x292e), true
+		case "nequiv":                          // NOT IDENTICAL TO
+			return rune(0x2262), true
+		case "nesear":                          // NORTH EAST ARROW AND SOUTH EAST ARROW
+			return rune(0x2928), true
+		case "nesim":                           // MINUS TILDE with slash
+			return rune(0x2242), true
+		case "neswsarr":                        // NORTH EAST AND SOUTH WEST ARROW
+			return rune(0x2922), true
+		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
+			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 "ngeqq":                           // GREATER-THAN OVER EQUAL TO with slash
+			return rune(0x2267), true
+		case "ngeqslant":                       // GREATER-THAN OR SLANTED EQUAL TO with slash
+			return rune(0x2a7e), true
+		case "nges":                            // GREATER-THAN OR SLANTED EQUAL TO with slash
+			return rune(0x2a7e), true
+		case "ngr":                             // GREEK SMALL LETTER NU
+			return rune(0x03bd), true
+		case "ngsim":                           // NEITHER GREATER-THAN NOR EQUIVALENT TO
+			return rune(0x2275), true
+		case "ngt":                             // NOT GREATER-THAN
+			return rune(0x226f), true
+		case "ngtr":                            // NOT GREATER-THAN
+			return rune(0x226f), true
+		case "nhArr":                           // LEFT RIGHT DOUBLE ARROW WITH STROKE
+			return rune(0x21ce), true
+		case "nharr":                           // LEFT RIGHT ARROW WITH STROKE
+			return rune(0x21ae), true
+		case "nhpar":                           // PARALLEL WITH HORIZONTAL STROKE
+			return rune(0x2af2), true
+		case "ni":                              // CONTAINS AS MEMBER
+			return rune(0x220b), true
+		case "nis":                             // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+			return rune(0x22fc), true
+		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
+			return rune(0x21cd), true
+		case "nlE":                             // LESS-THAN OVER EQUAL TO with slash
+			return rune(0x2266), true
+		case "nlarr":                           // LEFTWARDS ARROW WITH STROKE
+			return rune(0x219a), true
+		case "nldr":                            // TWO DOT LEADER
+			return rune(0x2025), true
+		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
+			return rune(0x21ae), true
+		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 "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 "nlsim":                           // NEITHER LESS-THAN NOR EQUIVALENT TO
+			return rune(0x2274), true
+		case "nlt":                             // NOT LESS-THAN
+			return rune(0x226e), true
+		case "nltri":                           // NOT NORMAL SUBGROUP OF
+			return rune(0x22ea), true
+		case "nltrie":                          // NOT NORMAL SUBGROUP OF OR EQUAL TO
+			return rune(0x22ec), true
+		case "nltrivb":                         // LEFT TRIANGLE BESIDE VERTICAL BAR with slash
+			return rune(0x29cf), true
+		case "nmid":                            // DOES NOT DIVIDE
+			return rune(0x2224), true
+		case "nopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL N
+			return rune(0x01d55f), true
+		case "not":                             // NOT SIGN
+			return rune(0xac), 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 "npar":                            // NOT PARALLEL TO
+			return rune(0x2226), true
+		case "nparallel":                       // NOT PARALLEL TO
+			return rune(0x2226), true
+		case "nparsl":                          // DOUBLE SOLIDUS OPERATOR with reverse slash
+			return rune(0x2afd), true
+		case "npart":                           // PARTIAL DIFFERENTIAL with slash
+			return rune(0x2202), true
+		case "npolint":                         // LINE INTEGRATION NOT INCLUDING THE POLE
+			return rune(0x2a14), true
+		case "npr":                             // DOES NOT PRECEDE
+			return rune(0x2280), true
+		case "nprcue":                          // DOES NOT PRECEDE OR EQUAL
+			return rune(0x22e0), true
+		case "npre":                            // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
+			return rune(0x2aaf), true
+		case "nprec":                           // DOES NOT PRECEDE
+			return rune(0x2280), true
+		case "npreceq":                         // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
+			return rune(0x2aaf), true
+		case "nprsim":                          // PRECEDES OR EQUIVALENT TO with slash
+			return rune(0x227e), true
+		case "nrArr":                           // RIGHTWARDS DOUBLE ARROW WITH STROKE
+			return rune(0x21cf), true
+		case "nrarr":                           // RIGHTWARDS ARROW WITH STROKE
+			return rune(0x219b), true
+		case "nrarrc":                          // WAVE ARROW POINTING DIRECTLY RIGHT with slash
+			return rune(0x2933), true
+		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
+			return rune(0x22eb), true
+		case "nrtrie":                          // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+			return rune(0x22ed), true
+		case "nsGt":                            // DOUBLE NESTED GREATER-THAN with slash
+			return rune(0x2aa2), true
+		case "nsLt":                            // DOUBLE NESTED LESS-THAN with slash
+			return rune(0x2aa1), true
+		case "nsc":                             // DOES NOT SUCCEED
+			return rune(0x2281), true
+		case "nsccue":                          // DOES NOT SUCCEED OR EQUAL
+			return rune(0x22e1), true
+		case "nsce":                            // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
+			return rune(0x2ab0), true
+		case "nscr":                            // MATHEMATICAL SCRIPT SMALL N
+			return rune(0x01d4c3), true
+		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
+			return rune(0x2226), true
+		case "nsim":                            // NOT TILDE
+			return rune(0x2241), true
+		case "nsime":                           // NOT ASYMPTOTICALLY EQUAL TO
+			return rune(0x2244), true
+		case "nsimeq":                          // NOT ASYMPTOTICALLY EQUAL TO
+			return rune(0x2244), true
+		case "nsmid":                           // DOES NOT DIVIDE
+			return rune(0x2224), true
+		case "nspar":                           // NOT PARALLEL TO
+			return rune(0x2226), true
+		case "nsqsub":                          // SQUARE IMAGE OF with slash
+			return rune(0x228f), true
+		case "nsqsube":                         // NOT SQUARE IMAGE OF OR EQUAL TO
+			return rune(0x22e2), true
+		case "nsqsup":                          // SQUARE ORIGINAL OF with slash
+			return rune(0x2290), true
+		case "nsqsupe":                         // NOT SQUARE ORIGINAL OF OR EQUAL TO
+			return rune(0x22e3), true
+		case "nsub":                            // NOT A SUBSET OF
+			return rune(0x2284), true
+		case "nsubE":                           // SUBSET OF ABOVE EQUALS SIGN with slash
+			return rune(0x2ac5), true
+		case "nsube":                           // NEITHER A SUBSET OF NOR EQUAL TO
+			return rune(0x2288), true
+		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
+			return rune(0x2ac5), true
+		case "nsucc":                           // DOES NOT SUCCEED
+			return rune(0x2281), true
+		case "nsucceq":                         // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
+			return rune(0x2ab0), true
+		case "nsup":                            // NOT A SUPERSET OF
+			return rune(0x2285), true
+		case "nsupE":                           // SUPERSET OF ABOVE EQUALS SIGN with slash
+			return rune(0x2ac6), true
+		case "nsupe":                           // NEITHER A SUPERSET OF NOR EQUAL TO
+			return rune(0x2289), true
+		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
+			return rune(0x2ac6), true
+		case "ntgl":                            // NEITHER GREATER-THAN NOR LESS-THAN
+			return rune(0x2279), true
+		case "ntilde":                          // LATIN SMALL LETTER N WITH TILDE
+			return rune(0xf1), true
+		case "ntlg":                            // NEITHER LESS-THAN NOR GREATER-THAN
+			return rune(0x2278), true
+		case "ntriangleleft":                   // NOT NORMAL SUBGROUP OF
+			return rune(0x22ea), true
+		case "ntrianglelefteq":                 // NOT NORMAL SUBGROUP OF OR EQUAL TO
+			return rune(0x22ec), true
+		case "ntriangleright":                  // DOES NOT CONTAIN AS NORMAL SUBGROUP
+			return rune(0x22eb), true
+		case "ntrianglerighteq":                // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+			return rune(0x22ed), true
+		case "nu":                              // GREEK SMALL LETTER NU
+			return rune(0x03bd), true
+		case "num":                             // NUMBER SIGN
+			return rune(0x23), 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
+			return rune(0x2904), true
+		case "nvap":                            // EQUIVALENT TO with vertical line
+			return rune(0x224d), true
+		case "nvbrtri":                         // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
+			return rune(0x29d0), true
+		case "nvdash":                          // DOES NOT PROVE
+			return rune(0x22ac), true
+		case "nvge":                            // GREATER-THAN OR EQUAL TO with vertical line
+			return rune(0x2265), true
+		case "nvgt":                            // GREATER-THAN SIGN with vertical line
+			return rune(0x3e), true
+		case "nvinfin":                         // INFINITY NEGATED WITH VERTICAL BAR
+			return rune(0x29de), true
+		case "nvlArr":                          // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
+			return rune(0x2902), true
+		case "nvle":                            // LESS-THAN OR EQUAL TO with vertical line
+			return rune(0x2264), true
+		case "nvlt":                            // LESS-THAN SIGN with vertical line
+			return rune(0x3c), true
+		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
+			return rune(0x22b5), true
+		case "nvsim":                           // TILDE OPERATOR with vertical line
+			return rune(0x223c), true
+		case "nwArr":                           // NORTH WEST DOUBLE ARROW
+			return rune(0x21d6), true
+		case "nwarhk":                          // NORTH WEST ARROW WITH HOOK
+			return rune(0x2923), true
+		case "nwarr":                           // NORTH WEST ARROW
+			return rune(0x2196), true
+		case "nwarrow":                         // NORTH WEST ARROW
+			return rune(0x2196), true
+		case "nwnear":                          // NORTH WEST ARROW AND NORTH EAST ARROW
+			return rune(0x2927), true
+		case "nwonearr":                        // NORTH WEST ARROW CROSSING NORTH EAST ARROW
+			return rune(0x2932), true
+		case "nwsesarr":                        // NORTH WEST AND SOUTH EAST ARROW
+			return rune(0x2921), true
 		}
 		}
 
 
 	case 'o':
 	case 'o':
 		switch name {
 		switch name {
-			case "oS":                              // CIRCLED LATIN CAPITAL LETTER S
-				return rune(0x24c8), true
-			case "oacgr":                           // GREEK SMALL LETTER OMICRON WITH TONOS
-				return rune(0x03cc), true
-			case "oacute":                          // LATIN SMALL LETTER O WITH ACUTE
-				return rune(0xf3), true
-			case "oast":                            // CIRCLED ASTERISK OPERATOR
-				return rune(0x229b), true
-			case "obsol":                           // CIRCLED REVERSE SOLIDUS
-				return rune(0x29b8), true
-			case "ocir":                            // CIRCLED RING OPERATOR
-				return rune(0x229a), true
-			case "ocirc":                           // LATIN SMALL LETTER O WITH CIRCUMFLEX
-				return rune(0xf4), true
-			case "ocy":                             // CYRILLIC SMALL LETTER O
-				return rune(0x043e), true
-			case "odash":                           // CIRCLED DASH
-				return rune(0x229d), true
-			case "odblac":                          // LATIN SMALL LETTER O WITH DOUBLE ACUTE
-				return rune(0x0151), true
-			case "odiv":                            // CIRCLED DIVISION SIGN
-				return rune(0x2a38), true
-			case "odot":                            // CIRCLED DOT OPERATOR
-				return rune(0x2299), true
-			case "odsold":                          // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN
-				return rune(0x29bc), true
-			case "oelig":                           // LATIN SMALL LIGATURE OE
-				return rune(0x0153), true
-			case "ofcir":                           // CIRCLED BULLET
-				return rune(0x29bf), true
-			case "ofr":                             // MATHEMATICAL FRAKTUR SMALL O
-				return rune(0x01d52c), true
-			case "ogon":                            // OGONEK
-				return rune(0x02db), true
-			case "ogr":                             // GREEK SMALL LETTER OMICRON
-				return rune(0x03bf), true
-			case "ograve":                          // LATIN SMALL LETTER O WITH GRAVE
-				return rune(0xf2), true
-			case "ogt":                             // CIRCLED GREATER-THAN
-				return rune(0x29c1), true
-			case "ohacgr":                          // GREEK SMALL LETTER OMEGA WITH TONOS
-				return rune(0x03ce), true
-			case "ohbar":                           // CIRCLE WITH HORIZONTAL BAR
-				return rune(0x29b5), true
-			case "ohgr":                            // GREEK SMALL LETTER OMEGA
-				return rune(0x03c9), true
-			case "ohm":                             // GREEK CAPITAL LETTER OMEGA
-				return rune(0x03a9), true
-			case "oint":                            // CONTOUR INTEGRAL
-				return rune(0x222e), true
-			case "olarr":                           // ANTICLOCKWISE OPEN CIRCLE ARROW
-				return rune(0x21ba), true
-			case "olcir":                           // CIRCLED WHITE BULLET
-				return rune(0x29be), true
-			case "olcross":                         // CIRCLE WITH SUPERIMPOSED X
-				return rune(0x29bb), true
-			case "oline":                           // OVERLINE
-				return rune(0x203e), true
-			case "olt":                             // CIRCLED LESS-THAN
-				return rune(0x29c0), true
-			case "omacr":                           // LATIN SMALL LETTER O WITH MACRON
-				return rune(0x014d), true
-			case "omega":                           // GREEK SMALL LETTER OMEGA
-				return rune(0x03c9), true
-			case "omicron":                         // GREEK SMALL LETTER OMICRON
-				return rune(0x03bf), true
-			case "omid":                            // CIRCLED VERTICAL BAR
-				return rune(0x29b6), true
-			case "ominus":                          // CIRCLED MINUS
-				return rune(0x2296), true
-			case "oopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL O
-				return rune(0x01d560), true
-			case "opar":                            // CIRCLED PARALLEL
-				return rune(0x29b7), true
-			case "operp":                           // CIRCLED PERPENDICULAR
-				return rune(0x29b9), true
-			case "opfgamma":                        // DOUBLE-STRUCK SMALL GAMMA
-				return rune(0x213d), true
-			case "opfpi":                           // DOUBLE-STRUCK CAPITAL PI
-				return rune(0x213f), true
-			case "opfsum":                          // DOUBLE-STRUCK N-ARY SUMMATION
-				return rune(0x2140), true
-			case "oplus":                           // CIRCLED PLUS
-				return rune(0x2295), true
-			case "or":                              // LOGICAL OR
-				return rune(0x2228), true
-			case "orarr":                           // CLOCKWISE OPEN CIRCLE ARROW
-				return rune(0x21bb), true
-			case "ord":                             // LOGICAL OR WITH HORIZONTAL DASH
-				return rune(0x2a5d), true
-			case "order":                           // SCRIPT SMALL O
-				return rune(0x2134), true
-			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
-				return rune(0x2298), true
-			case "otilde":                          // LATIN SMALL LETTER O WITH TILDE
-				return rune(0xf5), true
-			case "otimes":                          // CIRCLED TIMES
-				return rune(0x2297), true
-			case "otimesas":                        // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT
-				return rune(0x2a36), true
-			case "ouml":                            // LATIN SMALL LETTER O WITH DIAERESIS
-				return rune(0xf6), true
-			case "ovbar":                           // APL FUNCTIONAL SYMBOL CIRCLE STILE
-				return rune(0x233d), true
-			case "ovrbrk":                          // TOP SQUARE BRACKET
-				return rune(0x23b4), true
-			case "ovrcub":                          // TOP CURLY BRACKET
-				return rune(0x23de), true
-			case "ovrpar":                          // TOP PARENTHESIS
-				return rune(0x23dc), true
-			case "oxuarr":                          // UP ARROW THROUGH CIRCLE
-				return rune(0x29bd), true
+		case "oS":                              // CIRCLED LATIN CAPITAL LETTER S
+			return rune(0x24c8), true
+		case "oacgr":                           // GREEK SMALL LETTER OMICRON WITH TONOS
+			return rune(0x03cc), true
+		case "oacute":                          // LATIN SMALL LETTER O WITH ACUTE
+			return rune(0xf3), true
+		case "oast":                            // CIRCLED ASTERISK OPERATOR
+			return rune(0x229b), true
+		case "obsol":                           // CIRCLED REVERSE SOLIDUS
+			return rune(0x29b8), true
+		case "ocir":                            // CIRCLED RING OPERATOR
+			return rune(0x229a), true
+		case "ocirc":                           // LATIN SMALL LETTER O WITH CIRCUMFLEX
+			return rune(0xf4), true
+		case "ocy":                             // CYRILLIC SMALL LETTER O
+			return rune(0x043e), true
+		case "odash":                           // CIRCLED DASH
+			return rune(0x229d), true
+		case "odblac":                          // LATIN SMALL LETTER O WITH DOUBLE ACUTE
+			return rune(0x0151), true
+		case "odiv":                            // CIRCLED DIVISION SIGN
+			return rune(0x2a38), true
+		case "odot":                            // CIRCLED DOT OPERATOR
+			return rune(0x2299), true
+		case "odsold":                          // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN
+			return rune(0x29bc), true
+		case "oelig":                           // LATIN SMALL LIGATURE OE
+			return rune(0x0153), true
+		case "ofcir":                           // CIRCLED BULLET
+			return rune(0x29bf), true
+		case "ofr":                             // MATHEMATICAL FRAKTUR SMALL O
+			return rune(0x01d52c), true
+		case "ogon":                            // OGONEK
+			return rune(0x02db), true
+		case "ogr":                             // GREEK SMALL LETTER OMICRON
+			return rune(0x03bf), true
+		case "ograve":                          // LATIN SMALL LETTER O WITH GRAVE
+			return rune(0xf2), true
+		case "ogt":                             // CIRCLED GREATER-THAN
+			return rune(0x29c1), true
+		case "ohacgr":                          // GREEK SMALL LETTER OMEGA WITH TONOS
+			return rune(0x03ce), true
+		case "ohbar":                           // CIRCLE WITH HORIZONTAL BAR
+			return rune(0x29b5), true
+		case "ohgr":                            // GREEK SMALL LETTER OMEGA
+			return rune(0x03c9), true
+		case "ohm":                             // GREEK CAPITAL LETTER OMEGA
+			return rune(0x03a9), true
+		case "oint":                            // CONTOUR INTEGRAL
+			return rune(0x222e), true
+		case "olarr":                           // ANTICLOCKWISE OPEN CIRCLE ARROW
+			return rune(0x21ba), true
+		case "olcir":                           // CIRCLED WHITE BULLET
+			return rune(0x29be), true
+		case "olcross":                         // CIRCLE WITH SUPERIMPOSED X
+			return rune(0x29bb), true
+		case "oline":                           // OVERLINE
+			return rune(0x203e), true
+		case "olt":                             // CIRCLED LESS-THAN
+			return rune(0x29c0), true
+		case "omacr":                           // LATIN SMALL LETTER O WITH MACRON
+			return rune(0x014d), true
+		case "omega":                           // GREEK SMALL LETTER OMEGA
+			return rune(0x03c9), true
+		case "omicron":                         // GREEK SMALL LETTER OMICRON
+			return rune(0x03bf), true
+		case "omid":                            // CIRCLED VERTICAL BAR
+			return rune(0x29b6), true
+		case "ominus":                          // CIRCLED MINUS
+			return rune(0x2296), true
+		case "oopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL O
+			return rune(0x01d560), true
+		case "opar":                            // CIRCLED PARALLEL
+			return rune(0x29b7), true
+		case "operp":                           // CIRCLED PERPENDICULAR
+			return rune(0x29b9), true
+		case "opfgamma":                        // DOUBLE-STRUCK SMALL GAMMA
+			return rune(0x213d), true
+		case "opfpi":                           // DOUBLE-STRUCK CAPITAL PI
+			return rune(0x213f), true
+		case "opfsum":                          // DOUBLE-STRUCK N-ARY SUMMATION
+			return rune(0x2140), true
+		case "oplus":                           // CIRCLED PLUS
+			return rune(0x2295), true
+		case "or":                              // LOGICAL OR
+			return rune(0x2228), true
+		case "orarr":                           // CLOCKWISE OPEN CIRCLE ARROW
+			return rune(0x21bb), true
+		case "ord":                             // LOGICAL OR WITH HORIZONTAL DASH
+			return rune(0x2a5d), true
+		case "order":                           // SCRIPT SMALL O
+			return rune(0x2134), true
+		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
+			return rune(0x2298), true
+		case "otilde":                          // LATIN SMALL LETTER O WITH TILDE
+			return rune(0xf5), true
+		case "otimes":                          // CIRCLED TIMES
+			return rune(0x2297), true
+		case "otimesas":                        // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT
+			return rune(0x2a36), true
+		case "ouml":                            // LATIN SMALL LETTER O WITH DIAERESIS
+			return rune(0xf6), true
+		case "ovbar":                           // APL FUNCTIONAL SYMBOL CIRCLE STILE
+			return rune(0x233d), true
+		case "ovrbrk":                          // TOP SQUARE BRACKET
+			return rune(0x23b4), true
+		case "ovrcub":                          // TOP CURLY BRACKET
+			return rune(0x23de), true
+		case "ovrpar":                          // TOP PARENTHESIS
+			return rune(0x23dc), true
+		case "oxuarr":                          // UP ARROW THROUGH CIRCLE
+			return rune(0x29bd), true
 		}
 		}
 
 
 	case 'p':
 	case 'p':
 		switch name {
 		switch name {
-			case "par":                             // PARALLEL TO
-				return rune(0x2225), true
-			case "para":                            // PILCROW SIGN
-				return rune(0xb6), true
-			case "parallel":                        // PARALLEL TO
-				return rune(0x2225), true
-			case "parsim":                          // PARALLEL WITH TILDE OPERATOR
-				return rune(0x2af3), true
-			case "parsl":                           // DOUBLE SOLIDUS OPERATOR
-				return rune(0x2afd), true
-			case "part":                            // PARTIAL DIFFERENTIAL
-				return rune(0x2202), true
-			case "pcy":                             // CYRILLIC SMALL LETTER PE
-				return rune(0x043f), true
-			case "percnt":                          // PERCENT SIGN
-				return rune(0x25), true
-			case "period":                          // FULL STOP
-				return rune(0x2e), true
-			case "permil":                          // PER MILLE SIGN
-				return rune(0x2030), true
-			case "perp":                            // UP TACK
-				return rune(0x22a5), true
-			case "pertenk":                         // PER TEN THOUSAND SIGN
-				return rune(0x2031), true
-			case "pfr":                             // MATHEMATICAL FRAKTUR SMALL P
-				return rune(0x01d52d), true
-			case "pgr":                             // GREEK SMALL LETTER PI
-				return rune(0x03c0), true
-			case "phgr":                            // GREEK SMALL LETTER PHI
-				return rune(0x03c6), true
-			case "phi":                             // 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 "phmmat":                          // SCRIPT CAPITAL M
-				return rune(0x2133), true
-			case "phone":                           // BLACK TELEPHONE
-				return rune(0x260e), true
-			case "pi":                              // GREEK SMALL LETTER PI
-				return rune(0x03c0), true
-			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
-				return rune(0x210e), true
-			case "plankv":                          // PLANCK CONSTANT OVER TWO PI
-				return rune(0x210f), true
-			case "plus":                            // PLUS SIGN
-				return rune(0x2b), 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 "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
-				return rune(0x01d561), true
-			case "pound":                           // POUND SIGN
-				return rune(0xa3), true
-			case "pr":                              // PRECEDES
-				return rune(0x227a), true
-			case "prE":                             // PRECEDES ABOVE EQUALS SIGN
-				return rune(0x2ab3), true
-			case "prap":                            // PRECEDES ABOVE ALMOST EQUAL TO
-				return rune(0x2ab7), true
-			case "prcue":                           // PRECEDES OR EQUAL TO
-				return rune(0x227c), true
-			case "pre":                             // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
-				return rune(0x2aaf), true
-			case "prec":                            // PRECEDES
-				return rune(0x227a), true
-			case "precapprox":                      // PRECEDES ABOVE ALMOST EQUAL TO
-				return rune(0x2ab7), true
-			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
-				return rune(0x2ab9), true
-			case "precneqq":                        // PRECEDES ABOVE NOT EQUAL TO
-				return rune(0x2ab5), true
-			case "precnsim":                        // PRECEDES BUT NOT EQUIVALENT TO
-				return rune(0x22e8), true
-			case "precsim":                         // PRECEDES OR EQUIVALENT TO
-				return rune(0x227e), true
-			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
-				return rune(0x01d4c5), true
-			case "psgr":                            // GREEK SMALL LETTER PSI
-				return rune(0x03c8), true
-			case "psi":                             // GREEK SMALL LETTER PSI
-				return rune(0x03c8), true
-			case "puncsp":                          // PUNCTUATION SPACE
-				return rune(0x2008), true
+		case "par":                             // PARALLEL TO
+			return rune(0x2225), true
+		case "para":                            // PILCROW SIGN
+			return rune(0xb6), true
+		case "parallel":                        // PARALLEL TO
+			return rune(0x2225), true
+		case "parsim":                          // PARALLEL WITH TILDE OPERATOR
+			return rune(0x2af3), true
+		case "parsl":                           // DOUBLE SOLIDUS OPERATOR
+			return rune(0x2afd), true
+		case "part":                            // PARTIAL DIFFERENTIAL
+			return rune(0x2202), true
+		case "pcy":                             // CYRILLIC SMALL LETTER PE
+			return rune(0x043f), true
+		case "percnt":                          // PERCENT SIGN
+			return rune(0x25), true
+		case "period":                          // FULL STOP
+			return rune(0x2e), true
+		case "permil":                          // PER MILLE SIGN
+			return rune(0x2030), true
+		case "perp":                            // UP TACK
+			return rune(0x22a5), true
+		case "pertenk":                         // PER TEN THOUSAND SIGN
+			return rune(0x2031), true
+		case "pfr":                             // MATHEMATICAL FRAKTUR SMALL P
+			return rune(0x01d52d), true
+		case "pgr":                             // GREEK SMALL LETTER PI
+			return rune(0x03c0), true
+		case "phgr":                            // GREEK SMALL LETTER PHI
+			return rune(0x03c6), true
+		case "phi":                             // 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 "phmmat":                          // SCRIPT CAPITAL M
+			return rune(0x2133), true
+		case "phone":                           // BLACK TELEPHONE
+			return rune(0x260e), true
+		case "pi":                              // GREEK SMALL LETTER PI
+			return rune(0x03c0), true
+		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
+			return rune(0x210e), true
+		case "plankv":                          // PLANCK CONSTANT OVER TWO PI
+			return rune(0x210f), true
+		case "plus":                            // PLUS SIGN
+			return rune(0x2b), 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 "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
+			return rune(0x01d561), true
+		case "pound":                           // POUND SIGN
+			return rune(0xa3), true
+		case "pr":                              // PRECEDES
+			return rune(0x227a), true
+		case "prE":                             // PRECEDES ABOVE EQUALS SIGN
+			return rune(0x2ab3), true
+		case "prap":                            // PRECEDES ABOVE ALMOST EQUAL TO
+			return rune(0x2ab7), true
+		case "prcue":                           // PRECEDES OR EQUAL TO
+			return rune(0x227c), true
+		case "pre":                             // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+			return rune(0x2aaf), true
+		case "prec":                            // PRECEDES
+			return rune(0x227a), true
+		case "precapprox":                      // PRECEDES ABOVE ALMOST EQUAL TO
+			return rune(0x2ab7), true
+		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
+			return rune(0x2ab9), true
+		case "precneqq":                        // PRECEDES ABOVE NOT EQUAL TO
+			return rune(0x2ab5), true
+		case "precnsim":                        // PRECEDES BUT NOT EQUIVALENT TO
+			return rune(0x22e8), true
+		case "precsim":                         // PRECEDES OR EQUIVALENT TO
+			return rune(0x227e), true
+		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
+			return rune(0x01d4c5), true
+		case "psgr":                            // GREEK SMALL LETTER PSI
+			return rune(0x03c8), true
+		case "psi":                             // GREEK SMALL LETTER PSI
+			return rune(0x03c8), true
+		case "puncsp":                          // PUNCTUATION SPACE
+			return rune(0x2008), true
 		}
 		}
 
 
 	case 'q':
 	case 'q':
 		switch name {
 		switch name {
-			case "qfr":                             // MATHEMATICAL FRAKTUR SMALL Q
-				return rune(0x01d52e), true
-			case "qint":                            // QUADRUPLE INTEGRAL OPERATOR
-				return rune(0x2a0c), true
-			case "qopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Q
-				return rune(0x01d562), true
-			case "qprime":                          // QUADRUPLE PRIME
-				return rune(0x2057), true
-			case "qscr":                            // MATHEMATICAL SCRIPT SMALL Q
-				return rune(0x01d4c6), true
-			case "quaternions":                     // DOUBLE-STRUCK CAPITAL H
-				return rune(0x210d), true
-			case "quatint":                         // QUATERNION INTEGRAL OPERATOR
-				return rune(0x2a16), true
-			case "quest":                           // QUESTION MARK
-				return rune(0x3f), true
-			case "questeq":                         // QUESTIONED EQUAL TO
-				return rune(0x225f), true
-			case "quot":                            // QUOTATION MARK
-				return rune(0x22), true
+		case "qfr":                             // MATHEMATICAL FRAKTUR SMALL Q
+			return rune(0x01d52e), true
+		case "qint":                            // QUADRUPLE INTEGRAL OPERATOR
+			return rune(0x2a0c), true
+		case "qopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Q
+			return rune(0x01d562), true
+		case "qprime":                          // QUADRUPLE PRIME
+			return rune(0x2057), true
+		case "qscr":                            // MATHEMATICAL SCRIPT SMALL Q
+			return rune(0x01d4c6), true
+		case "quaternions":                     // DOUBLE-STRUCK CAPITAL H
+			return rune(0x210d), true
+		case "quatint":                         // QUATERNION INTEGRAL OPERATOR
+			return rune(0x2a16), true
+		case "quest":                           // QUESTION MARK
+			return rune(0x3f), true
+		case "questeq":                         // QUESTIONED EQUAL TO
+			return rune(0x225f), true
+		case "quot":                            // QUOTATION MARK
+			return rune(0x22), true
 		}
 		}
 
 
 	case 'r':
 	case 'r':
 		switch name {
 		switch name {
-			case "rAarr":                           // RIGHTWARDS TRIPLE ARROW
-				return rune(0x21db), true
-			case "rArr":                            // RIGHTWARDS DOUBLE ARROW
-				return rune(0x21d2), true
-			case "rAtail":                          // RIGHTWARDS DOUBLE ARROW-TAIL
-				return rune(0x291c), true
-			case "rBarr":                           // RIGHTWARDS TRIPLE DASH ARROW
-				return rune(0x290f), true
-			case "rHar":                            // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
-				return rune(0x2964), true
-			case "race":                            // REVERSED TILDE with underline
-				return rune(0x223d), true
-			case "racute":                          // LATIN SMALL LETTER R WITH ACUTE
-				return rune(0x0155), true
-			case "radic":                           // SQUARE ROOT
-				return rune(0x221a), true
-			case "raemptyv":                        // EMPTY SET WITH RIGHT ARROW ABOVE
-				return rune(0x29b3), true
-			case "rang":                            // MATHEMATICAL RIGHT ANGLE BRACKET
-				return rune(0x27e9), true
-			case "rangd":                           // RIGHT ANGLE BRACKET WITH DOT
-				return rune(0x2992), true
-			case "range":                           // REVERSED ANGLE WITH UNDERBAR
-				return rune(0x29a5), true
-			case "rangle":                          // MATHEMATICAL RIGHT ANGLE BRACKET
-				return rune(0x27e9), true
-			case "raquo":                           // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-				return rune(0xbb), true
-			case "rarr":                            // RIGHTWARDS ARROW
-				return rune(0x2192), true
-			case "rarr2":                           // RIGHTWARDS PAIRED ARROWS
-				return rune(0x21c9), true
-			case "rarr3":                           // THREE RIGHTWARDS ARROWS
-				return rune(0x21f6), true
-			case "rarrap":                          // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO
-				return rune(0x2975), true
-			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
-				return rune(0x2933), true
-			case "rarrfs":                          // RIGHTWARDS ARROW TO BLACK DIAMOND
-				return rune(0x291e), true
-			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
-				return rune(0x2974), true
-			case "rarrtl":                          // RIGHTWARDS ARROW WITH TAIL
-				return rune(0x21a3), true
-			case "rarrw":                           // RIGHTWARDS WAVE ARROW
-				return rune(0x219d), 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 "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 "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 "rtri":                            // WHITE RIGHT-POINTING SMALL TRIANGLE
-				return rune(0x25b9), 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 "rtriltri":                        // RIGHT TRIANGLE ABOVE LEFT TRIANGLE
-				return rune(0x29ce), true
-			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
-				return rune(0x2968), true
-			case "rx":                              // PRESCRIPTION TAKE
-				return rune(0x211e), true
+		case "rAarr":                           // RIGHTWARDS TRIPLE ARROW
+			return rune(0x21db), true
+		case "rArr":                            // RIGHTWARDS DOUBLE ARROW
+			return rune(0x21d2), true
+		case "rAtail":                          // RIGHTWARDS DOUBLE ARROW-TAIL
+			return rune(0x291c), true
+		case "rBarr":                           // RIGHTWARDS TRIPLE DASH ARROW
+			return rune(0x290f), true
+		case "rHar":                            // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+			return rune(0x2964), true
+		case "race":                            // REVERSED TILDE with underline
+			return rune(0x223d), true
+		case "racute":                          // LATIN SMALL LETTER R WITH ACUTE
+			return rune(0x0155), true
+		case "radic":                           // SQUARE ROOT
+			return rune(0x221a), true
+		case "raemptyv":                        // EMPTY SET WITH RIGHT ARROW ABOVE
+			return rune(0x29b3), true
+		case "rang":                            // MATHEMATICAL RIGHT ANGLE BRACKET
+			return rune(0x27e9), true
+		case "rangd":                           // RIGHT ANGLE BRACKET WITH DOT
+			return rune(0x2992), true
+		case "range":                           // REVERSED ANGLE WITH UNDERBAR
+			return rune(0x29a5), true
+		case "rangle":                          // MATHEMATICAL RIGHT ANGLE BRACKET
+			return rune(0x27e9), true
+		case "raquo":                           // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+			return rune(0xbb), true
+		case "rarr":                            // RIGHTWARDS ARROW
+			return rune(0x2192), true
+		case "rarr2":                           // RIGHTWARDS PAIRED ARROWS
+			return rune(0x21c9), true
+		case "rarr3":                           // THREE RIGHTWARDS ARROWS
+			return rune(0x21f6), true
+		case "rarrap":                          // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO
+			return rune(0x2975), true
+		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
+			return rune(0x2933), true
+		case "rarrfs":                          // RIGHTWARDS ARROW TO BLACK DIAMOND
+			return rune(0x291e), true
+		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
+			return rune(0x2974), true
+		case "rarrtl":                          // RIGHTWARDS ARROW WITH TAIL
+			return rune(0x21a3), true
+		case "rarrw":                           // RIGHTWARDS WAVE ARROW
+			return rune(0x219d), 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 "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 "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 "rtri":                            // WHITE RIGHT-POINTING SMALL TRIANGLE
+			return rune(0x25b9), 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 "rtriltri":                        // RIGHT TRIANGLE ABOVE LEFT TRIANGLE
+			return rune(0x29ce), true
+		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
+			return rune(0x2968), true
+		case "rx":                              // PRESCRIPTION TAKE
+			return rune(0x211e), true
 		}
 		}
 
 
 	case 's':
 	case 's':
 		switch name {
 		switch name {
-			case "sacute":                          // LATIN SMALL LETTER S WITH ACUTE
-				return rune(0x015b), true
-			case "samalg":                          // N-ARY COPRODUCT
-				return rune(0x2210), true
-			case "sampi":                           // GREEK LETTER SAMPI
-				return rune(0x03e0), true
-			case "sbquo":                           // SINGLE LOW-9 QUOTATION MARK
-				return rune(0x201a), true
-			case "sbsol":                           // SMALL REVERSE SOLIDUS
-				return rune(0xfe68), true
-			case "sc":                              // SUCCEEDS
-				return rune(0x227b), true
-			case "scE":                             // SUCCEEDS ABOVE EQUALS SIGN
-				return rune(0x2ab4), true
-			case "scap":                            // SUCCEEDS ABOVE ALMOST EQUAL TO
-				return rune(0x2ab8), true
-			case "scaron":                          // LATIN SMALL LETTER S WITH CARON
-				return rune(0x0161), true
-			case "sccue":                           // SUCCEEDS OR EQUAL TO
-				return rune(0x227d), true
-			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 "scirc":                           // LATIN SMALL LETTER S WITH CIRCUMFLEX
-				return rune(0x015d), true
-			case "scnE":                            // SUCCEEDS ABOVE NOT EQUAL TO
-				return rune(0x2ab6), true
-			case "scnap":                           // SUCCEEDS ABOVE NOT ALMOST EQUAL TO
-				return rune(0x2aba), true
-			case "scnsim":                          // SUCCEEDS BUT NOT EQUIVALENT TO
-				return rune(0x22e9), true
-			case "scpolint":                        // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
-				return rune(0x2a13), true
-			case "scsim":                           // SUCCEEDS OR EQUIVALENT TO
-				return rune(0x227f), true
-			case "scy":                             // CYRILLIC SMALL LETTER ES
-				return rune(0x0441), true
-			case "sdot":                            // DOT OPERATOR
-				return rune(0x22c5), true
-			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
-				return rune(0x21d8), true
-			case "searhk":                          // SOUTH EAST ARROW WITH HOOK
-				return rune(0x2925), true
-			case "searr":                           // SOUTH EAST ARROW
-				return rune(0x2198), true
-			case "searrow":                         // SOUTH EAST ARROW
-				return rune(0x2198), true
-			case "sect":                            // SECTION SIGN
-				return rune(0xa7), true
-			case "semi":                            // SEMICOLON
-				return rune(0x3b), true
-			case "seonearr":                        // SOUTH EAST ARROW CROSSING NORTH EAST ARROW
-				return rune(0x292d), true
-			case "seswar":                          // SOUTH EAST ARROW AND SOUTH WEST ARROW
-				return rune(0x2929), true
-			case "setminus":                        // SET MINUS
-				return rune(0x2216), true
-			case "setmn":                           // SET MINUS
-				return rune(0x2216), true
-			case "sext":                            // SIX POINTED BLACK STAR
-				return rune(0x2736), true
-			case "sfgr":                            // GREEK SMALL LETTER FINAL SIGMA
-				return rune(0x03c2), true
-			case "sfr":                             // MATHEMATICAL FRAKTUR SMALL S
-				return rune(0x01d530), true
-			case "sfrown":                          // FROWN
-				return rune(0x2322), true
-			case "sgr":                             // GREEK SMALL LETTER SIGMA
-				return rune(0x03c3), true
-			case "sharp":                           // MUSIC SHARP SIGN
-				return rune(0x266f), true
-			case "shchcy":                          // CYRILLIC SMALL LETTER SHCHA
-				return rune(0x0449), true
-			case "shcy":                            // CYRILLIC SMALL LETTER SHA
-				return rune(0x0448), true
-			case "shortmid":                        // DIVIDES
-				return rune(0x2223), true
-			case "shortparallel":                   // PARALLEL TO
-				return rune(0x2225), true
-			case "shuffle":                         // SHUFFLE PRODUCT
-				return rune(0x29e2), true
-			case "shy":                             // SOFT HYPHEN
-				return rune(0xad), true
-			case "sigma":                           // GREEK SMALL LETTER SIGMA
-				return rune(0x03c3), true
-			case "sigmaf":                          // GREEK SMALL LETTER FINAL SIGMA
-				return rune(0x03c2), true
-			case "sigmav":                          // GREEK SMALL LETTER FINAL SIGMA
-				return rune(0x03c2), true
-			case "sim":                             // TILDE OPERATOR
-				return rune(0x223c), true
-			case "simdot":                          // TILDE OPERATOR WITH DOT ABOVE
-				return rune(0x2a6a), true
-			case "sime":                            // ASYMPTOTICALLY EQUAL TO
-				return rune(0x2243), true
-			case "simeq":                           // ASYMPTOTICALLY EQUAL TO
-				return rune(0x2243), true
-			case "simg":                            // SIMILAR OR GREATER-THAN
-				return rune(0x2a9e), true
-			case "simgE":                           // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN
-				return rune(0x2aa0), true
-			case "siml":                            // SIMILAR OR LESS-THAN
-				return rune(0x2a9d), true
-			case "simlE":                           // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN
-				return rune(0x2a9f), true
-			case "simne":                           // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
-				return rune(0x2246), true
-			case "simplus":                         // PLUS SIGN WITH TILDE ABOVE
-				return rune(0x2a24), true
-			case "simrarr":                         // TILDE OPERATOR ABOVE RIGHTWARDS ARROW
-				return rune(0x2972), true
-			case "slarr":                           // LEFTWARDS ARROW
-				return rune(0x2190), true
-			case "slint":                           // INTEGRAL AVERAGE WITH SLASH
-				return rune(0x2a0f), true
-			case "smallsetminus":                   // SET MINUS
-				return rune(0x2216), true
-			case "smashp":                          // SMASH PRODUCT
-				return rune(0x2a33), true
-			case "smeparsl":                        // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE
-				return rune(0x29e4), true
-			case "smid":                            // DIVIDES
-				return rune(0x2223), true
-			case "smile":                           // SMILE
-				return rune(0x2323), true
-			case "smt":                             // SMALLER THAN
-				return rune(0x2aaa), true
-			case "smte":                            // SMALLER THAN OR EQUAL TO
-				return rune(0x2aac), true
-			case "smtes":                           // SMALLER THAN OR slanted EQUAL
-				return rune(0x2aac), true
-			case "softcy":                          // CYRILLIC SMALL LETTER SOFT SIGN
-				return rune(0x044c), true
-			case "sol":                             // SOLIDUS
-				return rune(0x2f), true
-			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
-				return rune(0x2660), true
-			case "spadesuit":                       // BLACK SPADE SUIT
-				return rune(0x2660), true
-			case "spar":                            // PARALLEL TO
-				return rune(0x2225), true
-			case "sqcap":                           // SQUARE CAP
-				return rune(0x2293), true
-			case "sqcaps":                          // SQUARE CAP with serifs
-				return rune(0x2293), true
-			case "sqcup":                           // SQUARE CUP
-				return rune(0x2294), true
-			case "sqcups":                          // SQUARE CUP with serifs
-				return rune(0x2294), true
-			case "sqsub":                           // SQUARE IMAGE OF
-				return rune(0x228f), true
-			case "sqsube":                          // SQUARE IMAGE OF OR EQUAL TO
-				return rune(0x2291), true
-			case "sqsubset":                        // SQUARE IMAGE OF
-				return rune(0x228f), true
-			case "sqsubseteq":                      // SQUARE IMAGE OF OR EQUAL TO
-				return rune(0x2291), true
-			case "sqsup":                           // SQUARE ORIGINAL OF
-				return rune(0x2290), true
-			case "sqsupe":                          // SQUARE ORIGINAL OF OR EQUAL TO
-				return rune(0x2292), true
-			case "sqsupset":                        // SQUARE ORIGINAL OF
-				return rune(0x2290), true
-			case "sqsupseteq":                      // SQUARE ORIGINAL OF OR EQUAL TO
-				return rune(0x2292), true
-			case "squ":                             // WHITE SQUARE
-				return rune(0x25a1), true
-			case "square":                          // WHITE SQUARE
-				return rune(0x25a1), true
-			case "squarf":                          // BLACK SMALL SQUARE
-				return rune(0x25aa), true
-			case "squb":                            // SQUARED SQUARE
-				return rune(0x29c8), true
-			case "squerr":                          // ERROR-BARRED WHITE SQUARE
-				return rune(0x29ee), true
-			case "squf":                            // BLACK SMALL SQUARE
-				return rune(0x25aa), true
-			case "squferr":                         // ERROR-BARRED BLACK SQUARE
-				return rune(0x29ef), true
-			case "srarr":                           // RIGHTWARDS ARROW
-				return rune(0x2192), true
-			case "sscr":                            // MATHEMATICAL SCRIPT SMALL S
-				return rune(0x01d4c8), true
-			case "ssetmn":                          // SET MINUS
-				return rune(0x2216), true
-			case "ssmile":                          // SMILE
-				return rune(0x2323), true
-			case "sstarf":                          // STAR OPERATOR
-				return rune(0x22c6), true
-			case "star":                            // WHITE STAR
-				return rune(0x2606), true
-			case "starf":                           // BLACK STAR
-				return rune(0x2605), true
-			case "stigma":                          // GREEK LETTER STIGMA
-				return rune(0x03da), true
-			case "straightepsilon":                 // GREEK LUNATE EPSILON SYMBOL
-				return rune(0x03f5), true
-			case "straightphi":                     // GREEK PHI SYMBOL
-				return rune(0x03d5), true
-			case "strns":                           // MACRON
-				return rune(0xaf), true
-			case "sub":                             // SUBSET OF
-				return rune(0x2282), true
-			case "subE":                            // SUBSET OF ABOVE EQUALS SIGN
-				return rune(0x2ac5), true
-			case "subdot":                          // SUBSET WITH DOT
-				return rune(0x2abd), true
-			case "sube":                            // SUBSET OF OR EQUAL TO
-				return rune(0x2286), true
-			case "subedot":                         // SUBSET OF OR EQUAL TO WITH DOT ABOVE
-				return rune(0x2ac3), true
-			case "submult":                         // SUBSET WITH MULTIPLICATION SIGN BELOW
-				return rune(0x2ac1), true
-			case "subnE":                           // SUBSET OF ABOVE NOT EQUAL TO
-				return rune(0x2acb), true
-			case "subne":                           // SUBSET OF WITH NOT EQUAL TO
-				return rune(0x228a), true
-			case "subplus":                         // SUBSET WITH PLUS SIGN BELOW
-				return rune(0x2abf), true
-			case "subrarr":                         // SUBSET ABOVE RIGHTWARDS ARROW
-				return rune(0x2979), true
-			case "subset":                          // SUBSET OF
-				return rune(0x2282), true
-			case "subseteq":                        // SUBSET OF OR EQUAL TO
-				return rune(0x2286), true
-			case "subseteqq":                       // SUBSET OF ABOVE EQUALS SIGN
-				return rune(0x2ac5), true
-			case "subsetneq":                       // SUBSET OF WITH NOT EQUAL TO
-				return rune(0x228a), true
-			case "subsetneqq":                      // SUBSET OF ABOVE NOT EQUAL TO
-				return rune(0x2acb), true
-			case "subsim":                          // SUBSET OF ABOVE TILDE OPERATOR
-				return rune(0x2ac7), true
-			case "subsub":                          // SUBSET ABOVE SUBSET
-				return rune(0x2ad5), true
-			case "subsup":                          // SUBSET ABOVE SUPERSET
-				return rune(0x2ad3), true
-			case "succ":                            // SUCCEEDS
-				return rune(0x227b), true
-			case "succapprox":                      // SUCCEEDS ABOVE ALMOST EQUAL TO
-				return rune(0x2ab8), true
-			case "succcurlyeq":                     // SUCCEEDS OR EQUAL TO
-				return rune(0x227d), true
-			case "succeq":                          // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
-				return rune(0x2ab0), true
-			case "succnapprox":                     // SUCCEEDS ABOVE NOT ALMOST EQUAL TO
-				return rune(0x2aba), true
-			case "succneqq":                        // SUCCEEDS ABOVE NOT EQUAL TO
-				return rune(0x2ab6), true
-			case "succnsim":                        // SUCCEEDS BUT NOT EQUIVALENT TO
-				return rune(0x22e9), true
-			case "succsim":                         // SUCCEEDS OR EQUIVALENT TO
-				return rune(0x227f), true
-			case "sum":                             // N-ARY SUMMATION
-				return rune(0x2211), true
-			case "sumint":                          // SUMMATION WITH INTEGRAL
-				return rune(0x2a0b), true
-			case "sung":                            // EIGHTH NOTE
-				return rune(0x266a), true
-			case "sup":                             // SUPERSET OF
-				return rune(0x2283), true
-			case "sup1":                            // SUPERSCRIPT ONE
-				return rune(0xb9), true
-			case "sup2":                            // SUPERSCRIPT TWO
-				return rune(0xb2), true
-			case "sup3":                            // SUPERSCRIPT THREE
-				return rune(0xb3), true
-			case "supE":                            // SUPERSET OF ABOVE EQUALS SIGN
-				return rune(0x2ac6), true
-			case "supdot":                          // SUPERSET WITH DOT
-				return rune(0x2abe), true
-			case "supdsub":                         // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET
-				return rune(0x2ad8), true
-			case "supe":                            // SUPERSET OF OR EQUAL TO
-				return rune(0x2287), true
-			case "supedot":                         // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
-				return rune(0x2ac4), true
-			case "suphsol":                         // SUPERSET PRECEDING SOLIDUS
-				return rune(0x27c9), true
-			case "suphsub":                         // SUPERSET BESIDE SUBSET
-				return rune(0x2ad7), true
-			case "suplarr":                         // SUPERSET ABOVE LEFTWARDS ARROW
-				return rune(0x297b), true
-			case "supmult":                         // SUPERSET WITH MULTIPLICATION SIGN BELOW
-				return rune(0x2ac2), true
-			case "supnE":                           // SUPERSET OF ABOVE NOT EQUAL TO
-				return rune(0x2acc), true
-			case "supne":                           // SUPERSET OF WITH NOT EQUAL TO
-				return rune(0x228b), true
-			case "supplus":                         // SUPERSET WITH PLUS SIGN BELOW
-				return rune(0x2ac0), true
-			case "supset":                          // SUPERSET OF
-				return rune(0x2283), true
-			case "supseteq":                        // SUPERSET OF OR EQUAL TO
-				return rune(0x2287), true
-			case "supseteqq":                       // SUPERSET OF ABOVE EQUALS SIGN
-				return rune(0x2ac6), true
-			case "supsetneq":                       // SUPERSET OF WITH NOT EQUAL TO
-				return rune(0x228b), true
-			case "supsetneqq":                      // SUPERSET OF ABOVE NOT EQUAL TO
-				return rune(0x2acc), true
-			case "supsim":                          // SUPERSET OF ABOVE TILDE OPERATOR
-				return rune(0x2ac8), true
-			case "supsub":                          // SUPERSET ABOVE SUBSET
-				return rune(0x2ad4), true
-			case "supsup":                          // SUPERSET ABOVE SUPERSET
-				return rune(0x2ad6), true
-			case "swArr":                           // SOUTH WEST DOUBLE ARROW
-				return rune(0x21d9), true
-			case "swarhk":                          // SOUTH WEST ARROW WITH HOOK
-				return rune(0x2926), true
-			case "swarr":                           // SOUTH WEST ARROW
-				return rune(0x2199), true
-			case "swarrow":                         // SOUTH WEST ARROW
-				return rune(0x2199), true
-			case "swnwar":                          // SOUTH WEST ARROW AND NORTH WEST ARROW
-				return rune(0x292a), true
-			case "szlig":                           // LATIN SMALL LETTER SHARP S
-				return rune(0xdf), true
+		case "sacute":                          // LATIN SMALL LETTER S WITH ACUTE
+			return rune(0x015b), true
+		case "samalg":                          // N-ARY COPRODUCT
+			return rune(0x2210), true
+		case "sampi":                           // GREEK LETTER SAMPI
+			return rune(0x03e0), true
+		case "sbquo":                           // SINGLE LOW-9 QUOTATION MARK
+			return rune(0x201a), true
+		case "sbsol":                           // SMALL REVERSE SOLIDUS
+			return rune(0xfe68), true
+		case "sc":                              // SUCCEEDS
+			return rune(0x227b), true
+		case "scE":                             // SUCCEEDS ABOVE EQUALS SIGN
+			return rune(0x2ab4), true
+		case "scap":                            // SUCCEEDS ABOVE ALMOST EQUAL TO
+			return rune(0x2ab8), true
+		case "scaron":                          // LATIN SMALL LETTER S WITH CARON
+			return rune(0x0161), true
+		case "sccue":                           // SUCCEEDS OR EQUAL TO
+			return rune(0x227d), true
+		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 "scirc":                           // LATIN SMALL LETTER S WITH CIRCUMFLEX
+			return rune(0x015d), true
+		case "scnE":                            // SUCCEEDS ABOVE NOT EQUAL TO
+			return rune(0x2ab6), true
+		case "scnap":                           // SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+			return rune(0x2aba), true
+		case "scnsim":                          // SUCCEEDS BUT NOT EQUIVALENT TO
+			return rune(0x22e9), true
+		case "scpolint":                        // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
+			return rune(0x2a13), true
+		case "scsim":                           // SUCCEEDS OR EQUIVALENT TO
+			return rune(0x227f), true
+		case "scy":                             // CYRILLIC SMALL LETTER ES
+			return rune(0x0441), true
+		case "sdot":                            // DOT OPERATOR
+			return rune(0x22c5), true
+		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
+			return rune(0x21d8), true
+		case "searhk":                          // SOUTH EAST ARROW WITH HOOK
+			return rune(0x2925), true
+		case "searr":                           // SOUTH EAST ARROW
+			return rune(0x2198), true
+		case "searrow":                         // SOUTH EAST ARROW
+			return rune(0x2198), true
+		case "sect":                            // SECTION SIGN
+			return rune(0xa7), true
+		case "semi":                            // SEMICOLON
+			return rune(0x3b), true
+		case "seonearr":                        // SOUTH EAST ARROW CROSSING NORTH EAST ARROW
+			return rune(0x292d), true
+		case "seswar":                          // SOUTH EAST ARROW AND SOUTH WEST ARROW
+			return rune(0x2929), true
+		case "setminus":                        // SET MINUS
+			return rune(0x2216), true
+		case "setmn":                           // SET MINUS
+			return rune(0x2216), true
+		case "sext":                            // SIX POINTED BLACK STAR
+			return rune(0x2736), true
+		case "sfgr":                            // GREEK SMALL LETTER FINAL SIGMA
+			return rune(0x03c2), true
+		case "sfr":                             // MATHEMATICAL FRAKTUR SMALL S
+			return rune(0x01d530), true
+		case "sfrown":                          // FROWN
+			return rune(0x2322), true
+		case "sgr":                             // GREEK SMALL LETTER SIGMA
+			return rune(0x03c3), true
+		case "sharp":                           // MUSIC SHARP SIGN
+			return rune(0x266f), true
+		case "shchcy":                          // CYRILLIC SMALL LETTER SHCHA
+			return rune(0x0449), true
+		case "shcy":                            // CYRILLIC SMALL LETTER SHA
+			return rune(0x0448), true
+		case "shortmid":                        // DIVIDES
+			return rune(0x2223), true
+		case "shortparallel":                   // PARALLEL TO
+			return rune(0x2225), true
+		case "shuffle":                         // SHUFFLE PRODUCT
+			return rune(0x29e2), true
+		case "shy":                             // SOFT HYPHEN
+			return rune(0xad), true
+		case "sigma":                           // GREEK SMALL LETTER SIGMA
+			return rune(0x03c3), true
+		case "sigmaf":                          // GREEK SMALL LETTER FINAL SIGMA
+			return rune(0x03c2), true
+		case "sigmav":                          // GREEK SMALL LETTER FINAL SIGMA
+			return rune(0x03c2), true
+		case "sim":                             // TILDE OPERATOR
+			return rune(0x223c), true
+		case "simdot":                          // TILDE OPERATOR WITH DOT ABOVE
+			return rune(0x2a6a), true
+		case "sime":                            // ASYMPTOTICALLY EQUAL TO
+			return rune(0x2243), true
+		case "simeq":                           // ASYMPTOTICALLY EQUAL TO
+			return rune(0x2243), true
+		case "simg":                            // SIMILAR OR GREATER-THAN
+			return rune(0x2a9e), true
+		case "simgE":                           // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN
+			return rune(0x2aa0), true
+		case "siml":                            // SIMILAR OR LESS-THAN
+			return rune(0x2a9d), true
+		case "simlE":                           // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN
+			return rune(0x2a9f), true
+		case "simne":                           // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
+			return rune(0x2246), true
+		case "simplus":                         // PLUS SIGN WITH TILDE ABOVE
+			return rune(0x2a24), true
+		case "simrarr":                         // TILDE OPERATOR ABOVE RIGHTWARDS ARROW
+			return rune(0x2972), true
+		case "slarr":                           // LEFTWARDS ARROW
+			return rune(0x2190), true
+		case "slint":                           // INTEGRAL AVERAGE WITH SLASH
+			return rune(0x2a0f), true
+		case "smallsetminus":                   // SET MINUS
+			return rune(0x2216), true
+		case "smashp":                          // SMASH PRODUCT
+			return rune(0x2a33), true
+		case "smeparsl":                        // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE
+			return rune(0x29e4), true
+		case "smid":                            // DIVIDES
+			return rune(0x2223), true
+		case "smile":                           // SMILE
+			return rune(0x2323), true
+		case "smt":                             // SMALLER THAN
+			return rune(0x2aaa), true
+		case "smte":                            // SMALLER THAN OR EQUAL TO
+			return rune(0x2aac), true
+		case "smtes":                           // SMALLER THAN OR slanted EQUAL
+			return rune(0x2aac), true
+		case "softcy":                          // CYRILLIC SMALL LETTER SOFT SIGN
+			return rune(0x044c), true
+		case "sol":                             // SOLIDUS
+			return rune(0x2f), true
+		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
+			return rune(0x2660), true
+		case "spadesuit":                       // BLACK SPADE SUIT
+			return rune(0x2660), true
+		case "spar":                            // PARALLEL TO
+			return rune(0x2225), true
+		case "sqcap":                           // SQUARE CAP
+			return rune(0x2293), true
+		case "sqcaps":                          // SQUARE CAP with serifs
+			return rune(0x2293), true
+		case "sqcup":                           // SQUARE CUP
+			return rune(0x2294), true
+		case "sqcups":                          // SQUARE CUP with serifs
+			return rune(0x2294), true
+		case "sqsub":                           // SQUARE IMAGE OF
+			return rune(0x228f), true
+		case "sqsube":                          // SQUARE IMAGE OF OR EQUAL TO
+			return rune(0x2291), true
+		case "sqsubset":                        // SQUARE IMAGE OF
+			return rune(0x228f), true
+		case "sqsubseteq":                      // SQUARE IMAGE OF OR EQUAL TO
+			return rune(0x2291), true
+		case "sqsup":                           // SQUARE ORIGINAL OF
+			return rune(0x2290), true
+		case "sqsupe":                          // SQUARE ORIGINAL OF OR EQUAL TO
+			return rune(0x2292), true
+		case "sqsupset":                        // SQUARE ORIGINAL OF
+			return rune(0x2290), true
+		case "sqsupseteq":                      // SQUARE ORIGINAL OF OR EQUAL TO
+			return rune(0x2292), true
+		case "squ":                             // WHITE SQUARE
+			return rune(0x25a1), true
+		case "square":                          // WHITE SQUARE
+			return rune(0x25a1), true
+		case "squarf":                          // BLACK SMALL SQUARE
+			return rune(0x25aa), true
+		case "squb":                            // SQUARED SQUARE
+			return rune(0x29c8), true
+		case "squerr":                          // ERROR-BARRED WHITE SQUARE
+			return rune(0x29ee), true
+		case "squf":                            // BLACK SMALL SQUARE
+			return rune(0x25aa), true
+		case "squferr":                         // ERROR-BARRED BLACK SQUARE
+			return rune(0x29ef), true
+		case "srarr":                           // RIGHTWARDS ARROW
+			return rune(0x2192), true
+		case "sscr":                            // MATHEMATICAL SCRIPT SMALL S
+			return rune(0x01d4c8), true
+		case "ssetmn":                          // SET MINUS
+			return rune(0x2216), true
+		case "ssmile":                          // SMILE
+			return rune(0x2323), true
+		case "sstarf":                          // STAR OPERATOR
+			return rune(0x22c6), true
+		case "star":                            // WHITE STAR
+			return rune(0x2606), true
+		case "starf":                           // BLACK STAR
+			return rune(0x2605), true
+		case "stigma":                          // GREEK LETTER STIGMA
+			return rune(0x03da), true
+		case "straightepsilon":                 // GREEK LUNATE EPSILON SYMBOL
+			return rune(0x03f5), true
+		case "straightphi":                     // GREEK PHI SYMBOL
+			return rune(0x03d5), true
+		case "strns":                           // MACRON
+			return rune(0xaf), true
+		case "sub":                             // SUBSET OF
+			return rune(0x2282), true
+		case "subE":                            // SUBSET OF ABOVE EQUALS SIGN
+			return rune(0x2ac5), true
+		case "subdot":                          // SUBSET WITH DOT
+			return rune(0x2abd), true
+		case "sube":                            // SUBSET OF OR EQUAL TO
+			return rune(0x2286), true
+		case "subedot":                         // SUBSET OF OR EQUAL TO WITH DOT ABOVE
+			return rune(0x2ac3), true
+		case "submult":                         // SUBSET WITH MULTIPLICATION SIGN BELOW
+			return rune(0x2ac1), true
+		case "subnE":                           // SUBSET OF ABOVE NOT EQUAL TO
+			return rune(0x2acb), true
+		case "subne":                           // SUBSET OF WITH NOT EQUAL TO
+			return rune(0x228a), true
+		case "subplus":                         // SUBSET WITH PLUS SIGN BELOW
+			return rune(0x2abf), true
+		case "subrarr":                         // SUBSET ABOVE RIGHTWARDS ARROW
+			return rune(0x2979), true
+		case "subset":                          // SUBSET OF
+			return rune(0x2282), true
+		case "subseteq":                        // SUBSET OF OR EQUAL TO
+			return rune(0x2286), true
+		case "subseteqq":                       // SUBSET OF ABOVE EQUALS SIGN
+			return rune(0x2ac5), true
+		case "subsetneq":                       // SUBSET OF WITH NOT EQUAL TO
+			return rune(0x228a), true
+		case "subsetneqq":                      // SUBSET OF ABOVE NOT EQUAL TO
+			return rune(0x2acb), true
+		case "subsim":                          // SUBSET OF ABOVE TILDE OPERATOR
+			return rune(0x2ac7), true
+		case "subsub":                          // SUBSET ABOVE SUBSET
+			return rune(0x2ad5), true
+		case "subsup":                          // SUBSET ABOVE SUPERSET
+			return rune(0x2ad3), true
+		case "succ":                            // SUCCEEDS
+			return rune(0x227b), true
+		case "succapprox":                      // SUCCEEDS ABOVE ALMOST EQUAL TO
+			return rune(0x2ab8), true
+		case "succcurlyeq":                     // SUCCEEDS OR EQUAL TO
+			return rune(0x227d), true
+		case "succeq":                          // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+			return rune(0x2ab0), true
+		case "succnapprox":                     // SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+			return rune(0x2aba), true
+		case "succneqq":                        // SUCCEEDS ABOVE NOT EQUAL TO
+			return rune(0x2ab6), true
+		case "succnsim":                        // SUCCEEDS BUT NOT EQUIVALENT TO
+			return rune(0x22e9), true
+		case "succsim":                         // SUCCEEDS OR EQUIVALENT TO
+			return rune(0x227f), true
+		case "sum":                             // N-ARY SUMMATION
+			return rune(0x2211), true
+		case "sumint":                          // SUMMATION WITH INTEGRAL
+			return rune(0x2a0b), true
+		case "sung":                            // EIGHTH NOTE
+			return rune(0x266a), true
+		case "sup":                             // SUPERSET OF
+			return rune(0x2283), true
+		case "sup1":                            // SUPERSCRIPT ONE
+			return rune(0xb9), true
+		case "sup2":                            // SUPERSCRIPT TWO
+			return rune(0xb2), true
+		case "sup3":                            // SUPERSCRIPT THREE
+			return rune(0xb3), true
+		case "supE":                            // SUPERSET OF ABOVE EQUALS SIGN
+			return rune(0x2ac6), true
+		case "supdot":                          // SUPERSET WITH DOT
+			return rune(0x2abe), true
+		case "supdsub":                         // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET
+			return rune(0x2ad8), true
+		case "supe":                            // SUPERSET OF OR EQUAL TO
+			return rune(0x2287), true
+		case "supedot":                         // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
+			return rune(0x2ac4), true
+		case "suphsol":                         // SUPERSET PRECEDING SOLIDUS
+			return rune(0x27c9), true
+		case "suphsub":                         // SUPERSET BESIDE SUBSET
+			return rune(0x2ad7), true
+		case "suplarr":                         // SUPERSET ABOVE LEFTWARDS ARROW
+			return rune(0x297b), true
+		case "supmult":                         // SUPERSET WITH MULTIPLICATION SIGN BELOW
+			return rune(0x2ac2), true
+		case "supnE":                           // SUPERSET OF ABOVE NOT EQUAL TO
+			return rune(0x2acc), true
+		case "supne":                           // SUPERSET OF WITH NOT EQUAL TO
+			return rune(0x228b), true
+		case "supplus":                         // SUPERSET WITH PLUS SIGN BELOW
+			return rune(0x2ac0), true
+		case "supset":                          // SUPERSET OF
+			return rune(0x2283), true
+		case "supseteq":                        // SUPERSET OF OR EQUAL TO
+			return rune(0x2287), true
+		case "supseteqq":                       // SUPERSET OF ABOVE EQUALS SIGN
+			return rune(0x2ac6), true
+		case "supsetneq":                       // SUPERSET OF WITH NOT EQUAL TO
+			return rune(0x228b), true
+		case "supsetneqq":                      // SUPERSET OF ABOVE NOT EQUAL TO
+			return rune(0x2acc), true
+		case "supsim":                          // SUPERSET OF ABOVE TILDE OPERATOR
+			return rune(0x2ac8), true
+		case "supsub":                          // SUPERSET ABOVE SUBSET
+			return rune(0x2ad4), true
+		case "supsup":                          // SUPERSET ABOVE SUPERSET
+			return rune(0x2ad6), true
+		case "swArr":                           // SOUTH WEST DOUBLE ARROW
+			return rune(0x21d9), true
+		case "swarhk":                          // SOUTH WEST ARROW WITH HOOK
+			return rune(0x2926), true
+		case "swarr":                           // SOUTH WEST ARROW
+			return rune(0x2199), true
+		case "swarrow":                         // SOUTH WEST ARROW
+			return rune(0x2199), true
+		case "swnwar":                          // SOUTH WEST ARROW AND NORTH WEST ARROW
+			return rune(0x292a), true
+		case "szlig":                           // LATIN SMALL LETTER SHARP S
+			return rune(0xdf), true
 		}
 		}
 
 
 	case 't':
 	case 't':
 		switch name {
 		switch name {
-			case "target":                          // POSITION INDICATOR
-				return rune(0x2316), true
-			case "tau":                             // GREEK SMALL LETTER TAU
-				return rune(0x03c4), true
-			case "tbrk":                            // TOP SQUARE BRACKET
-				return rune(0x23b4), true
-			case "tcaron":                          // LATIN SMALL LETTER T WITH CARON
-				return rune(0x0165), true
-			case "tcedil":                          // LATIN SMALL LETTER T WITH CEDILLA
-				return rune(0x0163), true
-			case "tcy":                             // CYRILLIC SMALL LETTER TE
-				return rune(0x0442), true
-			case "tdot":                            // COMBINING THREE DOTS ABOVE
-				return rune(0x20db), true
-			case "telrec":                          // TELEPHONE RECORDER
-				return rune(0x2315), true
-			case "tfr":                             // MATHEMATICAL FRAKTUR SMALL T
-				return rune(0x01d531), true
-			case "tgr":                             // GREEK SMALL LETTER TAU
-				return rune(0x03c4), true
-			case "there4":                          // THEREFORE
-				return rune(0x2234), true
-			case "therefore":                       // THEREFORE
-				return rune(0x2234), true
-			case "thermod":                         // THERMODYNAMIC
-				return rune(0x29e7), true
-			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 "thetav":                          // GREEK THETA SYMBOL
-				return rune(0x03d1), true
-			case "thgr":                            // GREEK SMALL LETTER THETA
-				return rune(0x03b8), true
-			case "thickapprox":                     // ALMOST EQUAL TO
-				return rune(0x2248), true
-			case "thicksim":                        // TILDE OPERATOR
-				return rune(0x223c), true
-			case "thinsp":                          // THIN SPACE
-				return rune(0x2009), true
-			case "thkap":                           // ALMOST EQUAL TO
-				return rune(0x2248), true
-			case "thksim":                          // TILDE OPERATOR
-				return rune(0x223c), true
-			case "thorn":                           // LATIN SMALL LETTER THORN
-				return rune(0xfe), true
-			case "tilde":                           // SMALL TILDE
-				return rune(0x02dc), true
-			case "timeint":                         // INTEGRAL WITH TIMES SIGN
-				return rune(0x2a18), true
-			case "times":                           // MULTIPLICATION SIGN
-				return rune(0xd7), 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 "tint":                            // TRIPLE INTEGRAL
-				return rune(0x222d), true
-			case "toea":                            // NORTH EAST ARROW AND SOUTH EAST ARROW
-				return rune(0x2928), true
-			case "top":                             // DOWN TACK
-				return rune(0x22a4), true
-			case "topbot":                          // APL FUNCTIONAL SYMBOL I-BEAM
-				return rune(0x2336), true
-			case "topcir":                          // DOWN TACK WITH CIRCLE BELOW
-				return rune(0x2af1), true
-			case "topf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL T
-				return rune(0x01d565), true
-			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
-				return rune(0x2034), true
-			case "trade":                           // TRADE MARK SIGN
-				return rune(0x2122), true
-			case "triS":                            // S IN TRIANGLE
-				return rune(0x29cc), true
-			case "triangle":                        // WHITE UP-POINTING SMALL TRIANGLE
-				return rune(0x25b5), true
-			case "triangledown":                    // WHITE DOWN-POINTING SMALL TRIANGLE
-				return rune(0x25bf), true
-			case "triangleleft":                    // WHITE LEFT-POINTING SMALL TRIANGLE
-				return rune(0x25c3), true
-			case "trianglelefteq":                  // NORMAL SUBGROUP OF OR EQUAL TO
-				return rune(0x22b4), true
-			case "triangleq":                       // DELTA EQUAL TO
-				return rune(0x225c), true
-			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
-				return rune(0x2a39), true
-			case "trisb":                           // TRIANGLE WITH SERIFS AT BOTTOM
-				return rune(0x29cd), true
-			case "tritime":                         // MULTIPLICATION SIGN IN TRIANGLE
-				return rune(0x2a3b), true
-			case "trpezium":                        // WHITE TRAPEZIUM
-				return rune(0x23e2), true
-			case "tscr":                            // MATHEMATICAL SCRIPT SMALL T
-				return rune(0x01d4c9), true
-			case "tscy":                            // CYRILLIC SMALL LETTER TSE
-				return rune(0x0446), true
-			case "tshcy":                           // CYRILLIC SMALL LETTER TSHE
-				return rune(0x045b), true
-			case "tstrok":                          // LATIN SMALL LETTER T WITH STROKE
-				return rune(0x0167), true
-			case "tverbar":                         // TRIPLE VERTICAL BAR DELIMITER
-				return rune(0x2980), true
-			case "twixt":                           // BETWEEN
-				return rune(0x226c), true
-			case "twoheadleftarrow":                // LEFTWARDS TWO HEADED ARROW
-				return rune(0x219e), true
-			case "twoheadrightarrow":               // RIGHTWARDS TWO HEADED ARROW
-				return rune(0x21a0), true
+		case "target":                          // POSITION INDICATOR
+			return rune(0x2316), true
+		case "tau":                             // GREEK SMALL LETTER TAU
+			return rune(0x03c4), true
+		case "tbrk":                            // TOP SQUARE BRACKET
+			return rune(0x23b4), true
+		case "tcaron":                          // LATIN SMALL LETTER T WITH CARON
+			return rune(0x0165), true
+		case "tcedil":                          // LATIN SMALL LETTER T WITH CEDILLA
+			return rune(0x0163), true
+		case "tcy":                             // CYRILLIC SMALL LETTER TE
+			return rune(0x0442), true
+		case "tdot":                            // COMBINING THREE DOTS ABOVE
+			return rune(0x20db), true
+		case "telrec":                          // TELEPHONE RECORDER
+			return rune(0x2315), true
+		case "tfr":                             // MATHEMATICAL FRAKTUR SMALL T
+			return rune(0x01d531), true
+		case "tgr":                             // GREEK SMALL LETTER TAU
+			return rune(0x03c4), true
+		case "there4":                          // THEREFORE
+			return rune(0x2234), true
+		case "therefore":                       // THEREFORE
+			return rune(0x2234), true
+		case "thermod":                         // THERMODYNAMIC
+			return rune(0x29e7), true
+		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 "thetav":                          // GREEK THETA SYMBOL
+			return rune(0x03d1), true
+		case "thgr":                            // GREEK SMALL LETTER THETA
+			return rune(0x03b8), true
+		case "thickapprox":                     // ALMOST EQUAL TO
+			return rune(0x2248), true
+		case "thicksim":                        // TILDE OPERATOR
+			return rune(0x223c), true
+		case "thinsp":                          // THIN SPACE
+			return rune(0x2009), true
+		case "thkap":                           // ALMOST EQUAL TO
+			return rune(0x2248), true
+		case "thksim":                          // TILDE OPERATOR
+			return rune(0x223c), true
+		case "thorn":                           // LATIN SMALL LETTER THORN
+			return rune(0xfe), true
+		case "tilde":                           // SMALL TILDE
+			return rune(0x02dc), true
+		case "timeint":                         // INTEGRAL WITH TIMES SIGN
+			return rune(0x2a18), true
+		case "times":                           // MULTIPLICATION SIGN
+			return rune(0xd7), 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 "tint":                            // TRIPLE INTEGRAL
+			return rune(0x222d), true
+		case "toea":                            // NORTH EAST ARROW AND SOUTH EAST ARROW
+			return rune(0x2928), true
+		case "top":                             // DOWN TACK
+			return rune(0x22a4), true
+		case "topbot":                          // APL FUNCTIONAL SYMBOL I-BEAM
+			return rune(0x2336), true
+		case "topcir":                          // DOWN TACK WITH CIRCLE BELOW
+			return rune(0x2af1), true
+		case "topf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL T
+			return rune(0x01d565), true
+		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
+			return rune(0x2034), true
+		case "trade":                           // TRADE MARK SIGN
+			return rune(0x2122), true
+		case "triS":                            // S IN TRIANGLE
+			return rune(0x29cc), true
+		case "triangle":                        // WHITE UP-POINTING SMALL TRIANGLE
+			return rune(0x25b5), true
+		case "triangledown":                    // WHITE DOWN-POINTING SMALL TRIANGLE
+			return rune(0x25bf), true
+		case "triangleleft":                    // WHITE LEFT-POINTING SMALL TRIANGLE
+			return rune(0x25c3), true
+		case "trianglelefteq":                  // NORMAL SUBGROUP OF OR EQUAL TO
+			return rune(0x22b4), true
+		case "triangleq":                       // DELTA EQUAL TO
+			return rune(0x225c), true
+		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
+			return rune(0x2a39), true
+		case "trisb":                           // TRIANGLE WITH SERIFS AT BOTTOM
+			return rune(0x29cd), true
+		case "tritime":                         // MULTIPLICATION SIGN IN TRIANGLE
+			return rune(0x2a3b), true
+		case "trpezium":                        // WHITE TRAPEZIUM
+			return rune(0x23e2), true
+		case "tscr":                            // MATHEMATICAL SCRIPT SMALL T
+			return rune(0x01d4c9), true
+		case "tscy":                            // CYRILLIC SMALL LETTER TSE
+			return rune(0x0446), true
+		case "tshcy":                           // CYRILLIC SMALL LETTER TSHE
+			return rune(0x045b), true
+		case "tstrok":                          // LATIN SMALL LETTER T WITH STROKE
+			return rune(0x0167), true
+		case "tverbar":                         // TRIPLE VERTICAL BAR DELIMITER
+			return rune(0x2980), true
+		case "twixt":                           // BETWEEN
+			return rune(0x226c), true
+		case "twoheadleftarrow":                // LEFTWARDS TWO HEADED ARROW
+			return rune(0x219e), true
+		case "twoheadrightarrow":               // RIGHTWARDS TWO HEADED ARROW
+			return rune(0x21a0), true
 		}
 		}
 
 
 	case 'u':
 	case 'u':
 		switch name {
 		switch name {
-			case "uAarr":                           // UPWARDS TRIPLE ARROW
-				return rune(0x290a), true
-			case "uArr":                            // UPWARDS DOUBLE ARROW
-				return rune(0x21d1), true
-			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
-				return rune(0x03cd), true
-			case "uacute":                          // LATIN SMALL LETTER U WITH ACUTE
-				return rune(0xfa), true
-			case "uarr":                            // UPWARDS ARROW
-				return rune(0x2191), true
-			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
-				return rune(0x2909), true
-			case "ubrcy":                           // CYRILLIC SMALL LETTER SHORT U
-				return rune(0x045e), true
-			case "ubreve":                          // LATIN SMALL LETTER U WITH BREVE
-				return rune(0x016d), true
-			case "ucirc":                           // LATIN SMALL LETTER U WITH CIRCUMFLEX
-				return rune(0xfb), true
-			case "ucy":                             // CYRILLIC SMALL LETTER U
-				return rune(0x0443), true
-			case "udarr":                           // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
-				return rune(0x21c5), true
-			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
-				return rune(0x296e), true
-			case "udiagr":                          // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-				return rune(0x03b0), true
-			case "udigr":                           // GREEK SMALL LETTER UPSILON WITH DIALYTIKA
-				return rune(0x03cb), true
-			case "udrbrk":                          // BOTTOM SQUARE BRACKET
-				return rune(0x23b5), true
-			case "udrcub":                          // BOTTOM CURLY BRACKET
-				return rune(0x23df), true
-			case "udrpar":                          // BOTTOM PARENTHESIS
-				return rune(0x23dd), true
-			case "ufisht":                          // UP FISH TAIL
-				return rune(0x297e), true
-			case "ufr":                             // MATHEMATICAL FRAKTUR SMALL U
-				return rune(0x01d532), true
-			case "ugr":                             // GREEK SMALL LETTER UPSILON
-				return rune(0x03c5), true
-			case "ugrave":                          // LATIN SMALL LETTER U WITH GRAVE
-				return rune(0xf9), true
-			case "uharl":                           // UPWARDS HARPOON WITH BARB LEFTWARDS
-				return rune(0x21bf), true
-			case "uharr":                           // UPWARDS HARPOON WITH BARB RIGHTWARDS
-				return rune(0x21be), true
-			case "uhblk":                           // UPPER HALF BLOCK
-				return rune(0x2580), true
-			case "ulcorn":                          // TOP LEFT CORNER
-				return rune(0x231c), true
-			case "ulcorner":                        // TOP LEFT CORNER
-				return rune(0x231c), true
-			case "ulcrop":                          // TOP LEFT CROP
-				return rune(0x230f), true
-			case "uldlshar":                        // UP BARB LEFT DOWN BARB LEFT HARPOON
-				return rune(0x2951), true
-			case "ulharb":                          // UPWARDS HARPOON WITH BARB LEFT TO BAR
-				return rune(0x2958), true
-			case "ultri":                           // UPPER LEFT TRIANGLE
-				return rune(0x25f8), true
-			case "umacr":                           // LATIN SMALL LETTER U WITH MACRON
-				return rune(0x016b), true
-			case "uml":                             // DIAERESIS
-				return rune(0xa8), true
-			case "uogon":                           // LATIN SMALL LETTER U WITH OGONEK
-				return rune(0x0173), true
-			case "uopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL U
-				return rune(0x01d566), true
-			case "uparrow":                         // UPWARDS ARROW
-				return rune(0x2191), true
-			case "updownarrow":                     // UP DOWN ARROW
-				return rune(0x2195), true
-			case "upharpoonleft":                   // UPWARDS HARPOON WITH BARB LEFTWARDS
-				return rune(0x21bf), true
-			case "upharpoonright":                  // UPWARDS HARPOON WITH BARB RIGHTWARDS
-				return rune(0x21be), true
-			case "upint":                           // INTEGRAL WITH OVERBAR
-				return rune(0x2a1b), true
-			case "uplus":                           // MULTISET UNION
-				return rune(0x228e), true
-			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
-				return rune(0x03c5), true
-			case "upuparrows":                      // UPWARDS PAIRED ARROWS
-				return rune(0x21c8), true
-			case "urcorn":                          // TOP RIGHT CORNER
-				return rune(0x231d), true
-			case "urcorner":                        // TOP RIGHT CORNER
-				return rune(0x231d), true
-			case "urcrop":                          // TOP RIGHT CROP
-				return rune(0x230e), true
-			case "urdrshar":                        // UP BARB RIGHT DOWN BARB RIGHT HARPOON
-				return rune(0x294f), true
-			case "urharb":                          // UPWARDS HARPOON WITH BARB RIGHT TO BAR
-				return rune(0x2954), true
-			case "uring":                           // LATIN SMALL LETTER U WITH RING ABOVE
-				return rune(0x016f), true
-			case "urtri":                           // UPPER RIGHT TRIANGLE
-				return rune(0x25f9), true
-			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
-				return rune(0x22f0), true
-			case "utilde":                          // LATIN SMALL LETTER U WITH TILDE
-				return rune(0x0169), true
-			case "utri":                            // WHITE UP-POINTING SMALL TRIANGLE
-				return rune(0x25b5), true
-			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
-				return rune(0xfc), true
-			case "uwangle":                         // OBLIQUE ANGLE OPENING DOWN
-				return rune(0x29a7), true
+		case "uAarr":                           // UPWARDS TRIPLE ARROW
+			return rune(0x290a), true
+		case "uArr":                            // UPWARDS DOUBLE ARROW
+			return rune(0x21d1), true
+		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
+			return rune(0x03cd), true
+		case "uacute":                          // LATIN SMALL LETTER U WITH ACUTE
+			return rune(0xfa), true
+		case "uarr":                            // UPWARDS ARROW
+			return rune(0x2191), true
+		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
+			return rune(0x2909), true
+		case "ubrcy":                           // CYRILLIC SMALL LETTER SHORT U
+			return rune(0x045e), true
+		case "ubreve":                          // LATIN SMALL LETTER U WITH BREVE
+			return rune(0x016d), true
+		case "ucirc":                           // LATIN SMALL LETTER U WITH CIRCUMFLEX
+			return rune(0xfb), true
+		case "ucy":                             // CYRILLIC SMALL LETTER U
+			return rune(0x0443), true
+		case "udarr":                           // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+			return rune(0x21c5), true
+		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
+			return rune(0x296e), true
+		case "udiagr":                          // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+			return rune(0x03b0), true
+		case "udigr":                           // GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+			return rune(0x03cb), true
+		case "udrbrk":                          // BOTTOM SQUARE BRACKET
+			return rune(0x23b5), true
+		case "udrcub":                          // BOTTOM CURLY BRACKET
+			return rune(0x23df), true
+		case "udrpar":                          // BOTTOM PARENTHESIS
+			return rune(0x23dd), true
+		case "ufisht":                          // UP FISH TAIL
+			return rune(0x297e), true
+		case "ufr":                             // MATHEMATICAL FRAKTUR SMALL U
+			return rune(0x01d532), true
+		case "ugr":                             // GREEK SMALL LETTER UPSILON
+			return rune(0x03c5), true
+		case "ugrave":                          // LATIN SMALL LETTER U WITH GRAVE
+			return rune(0xf9), true
+		case "uharl":                           // UPWARDS HARPOON WITH BARB LEFTWARDS
+			return rune(0x21bf), true
+		case "uharr":                           // UPWARDS HARPOON WITH BARB RIGHTWARDS
+			return rune(0x21be), true
+		case "uhblk":                           // UPPER HALF BLOCK
+			return rune(0x2580), true
+		case "ulcorn":                          // TOP LEFT CORNER
+			return rune(0x231c), true
+		case "ulcorner":                        // TOP LEFT CORNER
+			return rune(0x231c), true
+		case "ulcrop":                          // TOP LEFT CROP
+			return rune(0x230f), true
+		case "uldlshar":                        // UP BARB LEFT DOWN BARB LEFT HARPOON
+			return rune(0x2951), true
+		case "ulharb":                          // UPWARDS HARPOON WITH BARB LEFT TO BAR
+			return rune(0x2958), true
+		case "ultri":                           // UPPER LEFT TRIANGLE
+			return rune(0x25f8), true
+		case "umacr":                           // LATIN SMALL LETTER U WITH MACRON
+			return rune(0x016b), true
+		case "uml":                             // DIAERESIS
+			return rune(0xa8), true
+		case "uogon":                           // LATIN SMALL LETTER U WITH OGONEK
+			return rune(0x0173), true
+		case "uopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL U
+			return rune(0x01d566), true
+		case "uparrow":                         // UPWARDS ARROW
+			return rune(0x2191), true
+		case "updownarrow":                     // UP DOWN ARROW
+			return rune(0x2195), true
+		case "upharpoonleft":                   // UPWARDS HARPOON WITH BARB LEFTWARDS
+			return rune(0x21bf), true
+		case "upharpoonright":                  // UPWARDS HARPOON WITH BARB RIGHTWARDS
+			return rune(0x21be), true
+		case "upint":                           // INTEGRAL WITH OVERBAR
+			return rune(0x2a1b), true
+		case "uplus":                           // MULTISET UNION
+			return rune(0x228e), true
+		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
+			return rune(0x03c5), true
+		case "upuparrows":                      // UPWARDS PAIRED ARROWS
+			return rune(0x21c8), true
+		case "urcorn":                          // TOP RIGHT CORNER
+			return rune(0x231d), true
+		case "urcorner":                        // TOP RIGHT CORNER
+			return rune(0x231d), true
+		case "urcrop":                          // TOP RIGHT CROP
+			return rune(0x230e), true
+		case "urdrshar":                        // UP BARB RIGHT DOWN BARB RIGHT HARPOON
+			return rune(0x294f), true
+		case "urharb":                          // UPWARDS HARPOON WITH BARB RIGHT TO BAR
+			return rune(0x2954), true
+		case "uring":                           // LATIN SMALL LETTER U WITH RING ABOVE
+			return rune(0x016f), true
+		case "urtri":                           // UPPER RIGHT TRIANGLE
+			return rune(0x25f9), true
+		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
+			return rune(0x22f0), true
+		case "utilde":                          // LATIN SMALL LETTER U WITH TILDE
+			return rune(0x0169), true
+		case "utri":                            // WHITE UP-POINTING SMALL TRIANGLE
+			return rune(0x25b5), true
+		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
+			return rune(0xfc), true
+		case "uwangle":                         // OBLIQUE ANGLE OPENING DOWN
+			return rune(0x29a7), true
 		}
 		}
 
 
 	case 'v':
 	case 'v':
 		switch name {
 		switch name {
-			case "vArr":                            // UP DOWN DOUBLE ARROW
-				return rune(0x21d5), true
-			case "vBar":                            // SHORT UP TACK WITH UNDERBAR
-				return rune(0x2ae8), true
-			case "vBarv":                           // SHORT UP TACK ABOVE SHORT DOWN TACK
-				return rune(0x2ae9), true
-			case "vDash":                           // TRUE
-				return rune(0x22a8), true
-			case "vDdash":                          // VERTICAL BAR TRIPLE RIGHT TURNSTILE
-				return rune(0x2ae2), true
-			case "vangrt":                          // RIGHT ANGLE VARIANT WITH SQUARE
-				return rune(0x299c), true
-			case "varepsilon":                      // GREEK LUNATE EPSILON SYMBOL
-				return rune(0x03f5), true
-			case "varkappa":                        // GREEK KAPPA SYMBOL
-				return rune(0x03f0), true
-			case "varnothing":                      // EMPTY SET
-				return rune(0x2205), true
-			case "varphi":                          // GREEK PHI SYMBOL
-				return rune(0x03d5), true
-			case "varpi":                           // GREEK PI SYMBOL
-				return rune(0x03d6), true
-			case "varpropto":                       // PROPORTIONAL TO
-				return rune(0x221d), true
-			case "varr":                            // UP DOWN ARROW
-				return rune(0x2195), true
-			case "varrho":                          // GREEK RHO SYMBOL
-				return rune(0x03f1), true
-			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
-				return rune(0x228a), true
-			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
-				return rune(0x228b), true
-			case "varsupsetneqq":                   // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
-				return rune(0x2acc), true
-			case "vartheta":                        // GREEK THETA SYMBOL
-				return rune(0x03d1), true
-			case "vartriangleleft":                 // NORMAL SUBGROUP OF
-				return rune(0x22b2), true
-			case "vartriangleright":                // CONTAINS AS NORMAL SUBGROUP
-				return rune(0x22b3), true
-			case "vbrtri":                          // VERTICAL BAR BESIDE RIGHT TRIANGLE
-				return rune(0x29d0), true
-			case "vcy":                             // CYRILLIC SMALL LETTER VE
-				return rune(0x0432), true
-			case "vdash":                           // RIGHT TACK
-				return rune(0x22a2), true
-			case "vee":                             // LOGICAL OR
-				return rune(0x2228), true
-			case "veeBar":                          // LOGICAL OR WITH DOUBLE UNDERBAR
-				return rune(0x2a63), true
-			case "veebar":                          // XOR
-				return rune(0x22bb), true
-			case "veeeq":                           // EQUIANGULAR TO
-				return rune(0x225a), true
-			case "vellip":                          // VERTICAL ELLIPSIS
-				return rune(0x22ee), true
-			case "vellip4":                         // DOTTED FENCE
-				return rune(0x2999), true
-			case "vellipv":                         // TRIPLE COLON OPERATOR
-				return rune(0x2af6), true
-			case "verbar":                          // VERTICAL LINE
-				return rune(0x7c), true
-			case "vert":                            // VERTICAL LINE
-				return rune(0x7c), true
-			case "vert3":                           // TRIPLE VERTICAL BAR BINARY RELATION
-				return rune(0x2af4), true
-			case "vfr":                             // MATHEMATICAL FRAKTUR SMALL V
-				return rune(0x01d533), true
-			case "vldash":                          // LEFT SQUARE BRACKET LOWER CORNER
-				return rune(0x23a3), true
-			case "vltri":                           // NORMAL SUBGROUP OF
-				return rune(0x22b2), true
-			case "vnsub":                           // SUBSET OF with vertical line
-				return rune(0x2282), true
-			case "vnsup":                           // SUPERSET OF with vertical line
-				return rune(0x2283), true
-			case "vopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL V
-				return rune(0x01d567), true
-			case "vprime":                          // PRIME
-				return rune(0x2032), true
-			case "vprop":                           // PROPORTIONAL TO
-				return rune(0x221d), true
-			case "vrtri":                           // CONTAINS AS NORMAL SUBGROUP
-				return rune(0x22b3), true
-			case "vscr":                            // MATHEMATICAL SCRIPT SMALL V
-				return rune(0x01d4cb), true
-			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
-				return rune(0x228a), true
-			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
-				return rune(0x228b), true
-			case "vzigzag":                         // VERTICAL ZIGZAG LINE
-				return rune(0x299a), true
+		case "vArr":                            // UP DOWN DOUBLE ARROW
+			return rune(0x21d5), true
+		case "vBar":                            // SHORT UP TACK WITH UNDERBAR
+			return rune(0x2ae8), true
+		case "vBarv":                           // SHORT UP TACK ABOVE SHORT DOWN TACK
+			return rune(0x2ae9), true
+		case "vDash":                           // TRUE
+			return rune(0x22a8), true
+		case "vDdash":                          // VERTICAL BAR TRIPLE RIGHT TURNSTILE
+			return rune(0x2ae2), true
+		case "vangrt":                          // RIGHT ANGLE VARIANT WITH SQUARE
+			return rune(0x299c), true
+		case "varepsilon":                      // GREEK LUNATE EPSILON SYMBOL
+			return rune(0x03f5), true
+		case "varkappa":                        // GREEK KAPPA SYMBOL
+			return rune(0x03f0), true
+		case "varnothing":                      // EMPTY SET
+			return rune(0x2205), true
+		case "varphi":                          // GREEK PHI SYMBOL
+			return rune(0x03d5), true
+		case "varpi":                           // GREEK PI SYMBOL
+			return rune(0x03d6), true
+		case "varpropto":                       // PROPORTIONAL TO
+			return rune(0x221d), true
+		case "varr":                            // UP DOWN ARROW
+			return rune(0x2195), true
+		case "varrho":                          // GREEK RHO SYMBOL
+			return rune(0x03f1), true
+		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
+			return rune(0x228a), true
+		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
+			return rune(0x228b), true
+		case "varsupsetneqq":                   // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
+			return rune(0x2acc), true
+		case "vartheta":                        // GREEK THETA SYMBOL
+			return rune(0x03d1), true
+		case "vartriangleleft":                 // NORMAL SUBGROUP OF
+			return rune(0x22b2), true
+		case "vartriangleright":                // CONTAINS AS NORMAL SUBGROUP
+			return rune(0x22b3), true
+		case "vbrtri":                          // VERTICAL BAR BESIDE RIGHT TRIANGLE
+			return rune(0x29d0), true
+		case "vcy":                             // CYRILLIC SMALL LETTER VE
+			return rune(0x0432), true
+		case "vdash":                           // RIGHT TACK
+			return rune(0x22a2), true
+		case "vee":                             // LOGICAL OR
+			return rune(0x2228), true
+		case "veeBar":                          // LOGICAL OR WITH DOUBLE UNDERBAR
+			return rune(0x2a63), true
+		case "veebar":                          // XOR
+			return rune(0x22bb), true
+		case "veeeq":                           // EQUIANGULAR TO
+			return rune(0x225a), true
+		case "vellip":                          // VERTICAL ELLIPSIS
+			return rune(0x22ee), true
+		case "vellip4":                         // DOTTED FENCE
+			return rune(0x2999), true
+		case "vellipv":                         // TRIPLE COLON OPERATOR
+			return rune(0x2af6), true
+		case "verbar":                          // VERTICAL LINE
+			return rune(0x7c), true
+		case "vert":                            // VERTICAL LINE
+			return rune(0x7c), true
+		case "vert3":                           // TRIPLE VERTICAL BAR BINARY RELATION
+			return rune(0x2af4), true
+		case "vfr":                             // MATHEMATICAL FRAKTUR SMALL V
+			return rune(0x01d533), true
+		case "vldash":                          // LEFT SQUARE BRACKET LOWER CORNER
+			return rune(0x23a3), true
+		case "vltri":                           // NORMAL SUBGROUP OF
+			return rune(0x22b2), true
+		case "vnsub":                           // SUBSET OF with vertical line
+			return rune(0x2282), true
+		case "vnsup":                           // SUPERSET OF with vertical line
+			return rune(0x2283), true
+		case "vopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL V
+			return rune(0x01d567), true
+		case "vprime":                          // PRIME
+			return rune(0x2032), true
+		case "vprop":                           // PROPORTIONAL TO
+			return rune(0x221d), true
+		case "vrtri":                           // CONTAINS AS NORMAL SUBGROUP
+			return rune(0x22b3), true
+		case "vscr":                            // MATHEMATICAL SCRIPT SMALL V
+			return rune(0x01d4cb), true
+		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
+			return rune(0x228a), true
+		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
+			return rune(0x228b), true
+		case "vzigzag":                         // VERTICAL ZIGZAG LINE
+			return rune(0x299a), true
 		}
 		}
 
 
 	case 'w':
 	case 'w':
 		switch name {
 		switch name {
-			case "wcirc":                           // LATIN SMALL LETTER W WITH CIRCUMFLEX
-				return rune(0x0175), true
-			case "wedbar":                          // LOGICAL AND WITH UNDERBAR
-				return rune(0x2a5f), true
-			case "wedge":                           // LOGICAL AND
-				return rune(0x2227), true
-			case "wedgeq":                          // ESTIMATES
-				return rune(0x2259), true
-			case "weierp":                          // SCRIPT CAPITAL P
-				return rune(0x2118), true
-			case "wfr":                             // MATHEMATICAL FRAKTUR SMALL W
-				return rune(0x01d534), true
-			case "wopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL W
-				return rune(0x01d568), true
-			case "wp":                              // SCRIPT CAPITAL P
-				return rune(0x2118), true
-			case "wr":                              // WREATH PRODUCT
-				return rune(0x2240), true
-			case "wreath":                          // WREATH PRODUCT
-				return rune(0x2240), true
-			case "wscr":                            // MATHEMATICAL SCRIPT SMALL W
-				return rune(0x01d4cc), true
+		case "wcirc":                           // LATIN SMALL LETTER W WITH CIRCUMFLEX
+			return rune(0x0175), true
+		case "wedbar":                          // LOGICAL AND WITH UNDERBAR
+			return rune(0x2a5f), true
+		case "wedge":                           // LOGICAL AND
+			return rune(0x2227), true
+		case "wedgeq":                          // ESTIMATES
+			return rune(0x2259), true
+		case "weierp":                          // SCRIPT CAPITAL P
+			return rune(0x2118), true
+		case "wfr":                             // MATHEMATICAL FRAKTUR SMALL W
+			return rune(0x01d534), true
+		case "wopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL W
+			return rune(0x01d568), true
+		case "wp":                              // SCRIPT CAPITAL P
+			return rune(0x2118), true
+		case "wr":                              // WREATH PRODUCT
+			return rune(0x2240), true
+		case "wreath":                          // WREATH PRODUCT
+			return rune(0x2240), true
+		case "wscr":                            // MATHEMATICAL SCRIPT SMALL W
+			return rune(0x01d4cc), true
 		}
 		}
 
 
 	case 'x':
 	case 'x':
 		switch name {
 		switch name {
-			case "xandand":                         // TWO LOGICAL AND OPERATOR
-				return rune(0x2a07), true
-			case "xbsol":                           // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
-				return rune(0x2571), true
-			case "xcap":                            // N-ARY INTERSECTION
-				return rune(0x22c2), true
-			case "xcirc":                           // LARGE CIRCLE
-				return rune(0x25ef), true
-			case "xcup":                            // N-ARY UNION
-				return rune(0x22c3), true
-			case "xcupdot":                         // N-ARY UNION OPERATOR WITH DOT
-				return rune(0x2a03), true
-			case "xdtri":                           // WHITE DOWN-POINTING TRIANGLE
-				return rune(0x25bd), true
-			case "xfr":                             // MATHEMATICAL FRAKTUR SMALL X
-				return rune(0x01d535), true
-			case "xgr":                             // GREEK SMALL LETTER XI
-				return rune(0x03be), true
-			case "xhArr":                           // LONG LEFT RIGHT DOUBLE ARROW
-				return rune(0x27fa), true
-			case "xharr":                           // LONG LEFT RIGHT ARROW
-				return rune(0x27f7), true
-			case "xi":                              // GREEK SMALL LETTER XI
-				return rune(0x03be), true
-			case "xlArr":                           // LONG LEFTWARDS DOUBLE ARROW
-				return rune(0x27f8), true
-			case "xlarr":                           // LONG LEFTWARDS ARROW
-				return rune(0x27f5), true
-			case "xmap":                            // LONG RIGHTWARDS ARROW FROM BAR
-				return rune(0x27fc), true
-			case "xnis":                            // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
-				return rune(0x22fb), true
-			case "xodot":                           // N-ARY CIRCLED DOT OPERATOR
-				return rune(0x2a00), true
-			case "xopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL X
-				return rune(0x01d569), true
-			case "xoplus":                          // N-ARY CIRCLED PLUS OPERATOR
-				return rune(0x2a01), true
-			case "xoror":                           // TWO LOGICAL OR OPERATOR
-				return rune(0x2a08), true
-			case "xotime":                          // N-ARY CIRCLED TIMES OPERATOR
-				return rune(0x2a02), true
-			case "xrArr":                           // LONG RIGHTWARDS DOUBLE ARROW
-				return rune(0x27f9), true
-			case "xrarr":                           // LONG RIGHTWARDS ARROW
-				return rune(0x27f6), true
-			case "xscr":                            // MATHEMATICAL SCRIPT SMALL X
-				return rune(0x01d4cd), true
-			case "xsol":                            // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
-				return rune(0x2572), true
-			case "xsqcap":                          // N-ARY SQUARE INTERSECTION OPERATOR
-				return rune(0x2a05), true
-			case "xsqcup":                          // N-ARY SQUARE UNION OPERATOR
-				return rune(0x2a06), true
-			case "xsqu":                            // WHITE MEDIUM SQUARE
-				return rune(0x25fb), true
-			case "xsquf":                           // BLACK MEDIUM SQUARE
-				return rune(0x25fc), true
-			case "xtimes":                          // N-ARY TIMES OPERATOR
-				return rune(0x2a09), true
-			case "xuplus":                          // N-ARY UNION OPERATOR WITH PLUS
-				return rune(0x2a04), true
-			case "xutri":                           // WHITE UP-POINTING TRIANGLE
-				return rune(0x25b3), true
-			case "xvee":                            // N-ARY LOGICAL OR
-				return rune(0x22c1), true
-			case "xwedge":                          // N-ARY LOGICAL AND
-				return rune(0x22c0), true
+		case "xandand":                         // TWO LOGICAL AND OPERATOR
+			return rune(0x2a07), true
+		case "xbsol":                           // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
+			return rune(0x2571), true
+		case "xcap":                            // N-ARY INTERSECTION
+			return rune(0x22c2), true
+		case "xcirc":                           // LARGE CIRCLE
+			return rune(0x25ef), true
+		case "xcup":                            // N-ARY UNION
+			return rune(0x22c3), true
+		case "xcupdot":                         // N-ARY UNION OPERATOR WITH DOT
+			return rune(0x2a03), true
+		case "xdtri":                           // WHITE DOWN-POINTING TRIANGLE
+			return rune(0x25bd), true
+		case "xfr":                             // MATHEMATICAL FRAKTUR SMALL X
+			return rune(0x01d535), true
+		case "xgr":                             // GREEK SMALL LETTER XI
+			return rune(0x03be), true
+		case "xhArr":                           // LONG LEFT RIGHT DOUBLE ARROW
+			return rune(0x27fa), true
+		case "xharr":                           // LONG LEFT RIGHT ARROW
+			return rune(0x27f7), true
+		case "xi":                              // GREEK SMALL LETTER XI
+			return rune(0x03be), true
+		case "xlArr":                           // LONG LEFTWARDS DOUBLE ARROW
+			return rune(0x27f8), true
+		case "xlarr":                           // LONG LEFTWARDS ARROW
+			return rune(0x27f5), true
+		case "xmap":                            // LONG RIGHTWARDS ARROW FROM BAR
+			return rune(0x27fc), true
+		case "xnis":                            // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+			return rune(0x22fb), true
+		case "xodot":                           // N-ARY CIRCLED DOT OPERATOR
+			return rune(0x2a00), true
+		case "xopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL X
+			return rune(0x01d569), true
+		case "xoplus":                          // N-ARY CIRCLED PLUS OPERATOR
+			return rune(0x2a01), true
+		case "xoror":                           // TWO LOGICAL OR OPERATOR
+			return rune(0x2a08), true
+		case "xotime":                          // N-ARY CIRCLED TIMES OPERATOR
+			return rune(0x2a02), true
+		case "xrArr":                           // LONG RIGHTWARDS DOUBLE ARROW
+			return rune(0x27f9), true
+		case "xrarr":                           // LONG RIGHTWARDS ARROW
+			return rune(0x27f6), true
+		case "xscr":                            // MATHEMATICAL SCRIPT SMALL X
+			return rune(0x01d4cd), true
+		case "xsol":                            // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
+			return rune(0x2572), true
+		case "xsqcap":                          // N-ARY SQUARE INTERSECTION OPERATOR
+			return rune(0x2a05), true
+		case "xsqcup":                          // N-ARY SQUARE UNION OPERATOR
+			return rune(0x2a06), true
+		case "xsqu":                            // WHITE MEDIUM SQUARE
+			return rune(0x25fb), true
+		case "xsquf":                           // BLACK MEDIUM SQUARE
+			return rune(0x25fc), true
+		case "xtimes":                          // N-ARY TIMES OPERATOR
+			return rune(0x2a09), true
+		case "xuplus":                          // N-ARY UNION OPERATOR WITH PLUS
+			return rune(0x2a04), true
+		case "xutri":                           // WHITE UP-POINTING TRIANGLE
+			return rune(0x25b3), true
+		case "xvee":                            // N-ARY LOGICAL OR
+			return rune(0x22c1), true
+		case "xwedge":                          // N-ARY LOGICAL AND
+			return rune(0x22c0), true
 		}
 		}
 
 
 	case 'y':
 	case 'y':
 		switch name {
 		switch name {
-			case "yacute":                          // LATIN SMALL LETTER Y WITH ACUTE
-				return rune(0xfd), true
-			case "yacy":                            // CYRILLIC SMALL LETTER YA
-				return rune(0x044f), true
-			case "ycirc":                           // LATIN SMALL LETTER Y WITH CIRCUMFLEX
-				return rune(0x0177), true
-			case "ycy":                             // CYRILLIC SMALL LETTER YERU
-				return rune(0x044b), true
-			case "yen":                             // YEN SIGN
-				return rune(0xa5), true
-			case "yfr":                             // MATHEMATICAL FRAKTUR SMALL Y
-				return rune(0x01d536), true
-			case "yicy":                            // CYRILLIC SMALL LETTER YI
-				return rune(0x0457), true
-			case "yopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Y
-				return rune(0x01d56a), true
-			case "yscr":                            // MATHEMATICAL SCRIPT SMALL Y
-				return rune(0x01d4ce), true
-			case "yucy":                            // CYRILLIC SMALL LETTER YU
-				return rune(0x044e), true
-			case "yuml":                            // LATIN SMALL LETTER Y WITH DIAERESIS
-				return rune(0xff), true
+		case "yacute":                          // LATIN SMALL LETTER Y WITH ACUTE
+			return rune(0xfd), true
+		case "yacy":                            // CYRILLIC SMALL LETTER YA
+			return rune(0x044f), true
+		case "ycirc":                           // LATIN SMALL LETTER Y WITH CIRCUMFLEX
+			return rune(0x0177), true
+		case "ycy":                             // CYRILLIC SMALL LETTER YERU
+			return rune(0x044b), true
+		case "yen":                             // YEN SIGN
+			return rune(0xa5), true
+		case "yfr":                             // MATHEMATICAL FRAKTUR SMALL Y
+			return rune(0x01d536), true
+		case "yicy":                            // CYRILLIC SMALL LETTER YI
+			return rune(0x0457), true
+		case "yopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Y
+			return rune(0x01d56a), true
+		case "yscr":                            // MATHEMATICAL SCRIPT SMALL Y
+			return rune(0x01d4ce), true
+		case "yucy":                            // CYRILLIC SMALL LETTER YU
+			return rune(0x044e), true
+		case "yuml":                            // LATIN SMALL LETTER Y WITH DIAERESIS
+			return rune(0xff), true
 		}
 		}
 
 
 	case 'z':
 	case 'z':
 		switch name {
 		switch name {
-			case "zacute":                          // LATIN SMALL LETTER Z WITH ACUTE
-				return rune(0x017a), true
-			case "zcaron":                          // LATIN SMALL LETTER Z WITH CARON
-				return rune(0x017e), true
-			case "zcy":                             // CYRILLIC SMALL LETTER ZE
-				return rune(0x0437), true
-			case "zdot":                            // LATIN SMALL LETTER Z WITH DOT ABOVE
-				return rune(0x017c), true
-			case "zeetrf":                          // BLACK-LETTER CAPITAL Z
-				return rune(0x2128), true
-			case "zeta":                            // GREEK SMALL LETTER ZETA
-				return rune(0x03b6), true
-			case "zfr":                             // MATHEMATICAL FRAKTUR SMALL Z
-				return rune(0x01d537), true
-			case "zgr":                             // GREEK SMALL LETTER ZETA
-				return rune(0x03b6), true
-			case "zhcy":                            // CYRILLIC SMALL LETTER ZHE
-				return rune(0x0436), true
-			case "zigrarr":                         // RIGHTWARDS SQUIGGLE ARROW
-				return rune(0x21dd), true
-			case "zopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Z
-				return rune(0x01d56b), true
-			case "zscr":                            // MATHEMATICAL SCRIPT SMALL Z
-				return rune(0x01d4cf), true
-			case "zwj":                             // ZERO WIDTH JOINER
-				return rune(0x200d), true
-			case "zwnj":                            // ZERO WIDTH NON-JOINER
-				return rune(0x200c), true
+		case "zacute":                          // LATIN SMALL LETTER Z WITH ACUTE
+			return rune(0x017a), true
+		case "zcaron":                          // LATIN SMALL LETTER Z WITH CARON
+			return rune(0x017e), true
+		case "zcy":                             // CYRILLIC SMALL LETTER ZE
+			return rune(0x0437), true
+		case "zdot":                            // LATIN SMALL LETTER Z WITH DOT ABOVE
+			return rune(0x017c), true
+		case "zeetrf":                          // BLACK-LETTER CAPITAL Z
+			return rune(0x2128), true
+		case "zeta":                            // GREEK SMALL LETTER ZETA
+			return rune(0x03b6), true
+		case "zfr":                             // MATHEMATICAL FRAKTUR SMALL Z
+			return rune(0x01d537), true
+		case "zgr":                             // GREEK SMALL LETTER ZETA
+			return rune(0x03b6), true
+		case "zhcy":                            // CYRILLIC SMALL LETTER ZHE
+			return rune(0x0436), true
+		case "zigrarr":                         // RIGHTWARDS SQUIGGLE ARROW
+			return rune(0x21dd), true
+		case "zopf":                            // MATHEMATICAL DOUBLE-STRUCK SMALL Z
+			return rune(0x01d56b), true
+		case "zscr":                            // MATHEMATICAL SCRIPT SMALL Z
+			return rune(0x01d4cf), true
+		case "zwj":                             // ZERO WIDTH JOINER
+			return rune(0x200d), true
+		case "zwnj":                            // ZERO WIDTH NON-JOINER
+			return rune(0x200c), true
 		}
 		}
 	}
 	}
 	return -1, false
 	return -1, false

+ 21 - 19
core/encoding/json/marshal.odin

@@ -25,7 +25,7 @@ Marshal_Options :: struct {
 	spec: Specification,
 	spec: Specification,
 
 
 	// Use line breaks & tabs/spaces
 	// Use line breaks & tabs/spaces
-	pretty: bool, 
+	pretty: bool,
 
 
 	// Use spaces for indentation instead of tabs
 	// Use spaces for indentation instead of tabs
 	use_spaces: bool,
 	use_spaces: bool,
@@ -34,7 +34,7 @@ Marshal_Options :: struct {
 	spaces: int,
 	spaces: int,
 
 
 	// Output uint as hex in JSON5 & MJSON
 	// Output uint as hex in JSON5 & MJSON
-	write_uint_as_hex: bool, 
+	write_uint_as_hex: bool,
 
 
 	// If spec is MJSON and this is true, then keys will be quoted.
 	// If spec is MJSON and this is true, then keys will be quoted.
 	//
 	//
@@ -138,7 +138,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 		// allow uints to be printed as hex
 		// allow uints to be printed as hex
 		if opt.write_uint_as_hex && (opt.spec == .JSON5 || opt.spec == .MJSON) {
 		if opt.write_uint_as_hex && (opt.spec == .JSON5 || opt.spec == .MJSON) {
 			switch i in a {
 			switch i in a {
-			case u8, u16, u32, u64, u128: 
+			case u8, u16, u32, u64, u128:
 				s = strconv.append_bits_128(buf[:], u, 16, info.signed, 8*ti.size, "0123456789abcdef", { .Prefix })
 				s = strconv.append_bits_128(buf[:], u, 16, info.signed, 8*ti.size, "0123456789abcdef", { .Prefix })
 
 
 			case:
 			case:
@@ -239,7 +239,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 	case runtime.Type_Info_Array:
 	case runtime.Type_Info_Array:
 		opt_write_start(w, opt, '[') or_return
 		opt_write_start(w, opt, '[') or_return
 		for i in 0..<info.count {
 		for i in 0..<info.count {
-			opt_write_iteration(w, opt, i) or_return
+			opt_write_iteration(w, opt, i == 0) or_return
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 		}
 		}
@@ -248,7 +248,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 	case runtime.Type_Info_Enumerated_Array:
 	case runtime.Type_Info_Enumerated_Array:
 		opt_write_start(w, opt, '[') or_return
 		opt_write_start(w, opt, '[') or_return
 		for i in 0..<info.count {
 		for i in 0..<info.count {
-			opt_write_iteration(w, opt, i) or_return
+			opt_write_iteration(w, opt, i == 0) or_return
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			data := uintptr(v.data) + uintptr(i*info.elem_size)
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 		}
 		}
@@ -258,7 +258,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 		opt_write_start(w, opt, '[') or_return
 		opt_write_start(w, opt, '[') or_return
 		array := cast(^mem.Raw_Dynamic_Array)v.data
 		array := cast(^mem.Raw_Dynamic_Array)v.data
 		for i in 0..<array.len {
 		for i in 0..<array.len {
-			opt_write_iteration(w, opt, i) or_return
+			opt_write_iteration(w, opt, i == 0) or_return
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
 			data := uintptr(array.data) + uintptr(i*info.elem_size)
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 		}
 		}
@@ -268,7 +268,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 		opt_write_start(w, opt, '[') or_return
 		opt_write_start(w, opt, '[') or_return
 		slice := cast(^mem.Raw_Slice)v.data
 		slice := cast(^mem.Raw_Slice)v.data
 		for i in 0..<slice.len {
 		for i in 0..<slice.len {
-			opt_write_iteration(w, opt, i) or_return
+			opt_write_iteration(w, opt, i == 0) or_return
 			data := uintptr(slice.data) + uintptr(i*info.elem_size)
 			data := uintptr(slice.data) + uintptr(i*info.elem_size)
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 			marshal_to_writer(w, any{rawptr(data), info.elem.id}, opt) or_return
 		}
 		}
@@ -290,7 +290,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 				for bucket_index in 0..<map_cap {
 				for bucket_index in 0..<map_cap {
 					runtime.map_hash_is_valid(hs[bucket_index]) or_continue
 					runtime.map_hash_is_valid(hs[bucket_index]) or_continue
 
 
-					opt_write_iteration(w, opt, i) or_return
+					opt_write_iteration(w, opt, i == 0) or_return
 					i += 1
 					i += 1
 
 
 					key   := rawptr(runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index))
 					key   := rawptr(runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index))
@@ -356,7 +356,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 				slice.sort_by(sorted[:], proc(i, j: Entry) -> bool { return i.key < j.key })
 				slice.sort_by(sorted[:], proc(i, j: Entry) -> bool { return i.key < j.key })
 
 
 				for s, i in sorted {
 				for s, i in sorted {
-					opt_write_iteration(w, opt, i) or_return
+					opt_write_iteration(w, opt, i == 0) or_return
 					opt_write_key(w, opt, s.key) or_return
 					opt_write_key(w, opt, s.key) or_return
 					marshal_to_writer(w, s.value, opt) or_return
 					marshal_to_writer(w, s.value, opt) or_return
 				}
 				}
@@ -387,17 +387,17 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 			case runtime.Type_Info_Pointer,
 			case runtime.Type_Info_Pointer,
 			     runtime.Type_Info_Multi_Pointer,
 			     runtime.Type_Info_Multi_Pointer,
 			     runtime.Type_Info_Procedure:
 			     runtime.Type_Info_Procedure:
-			     	return (^rawptr)(v.data)^ == nil
+				return (^rawptr)(v.data)^ == nil
 			case runtime.Type_Info_Dynamic_Array:
 			case runtime.Type_Info_Dynamic_Array:
-			     	return (^runtime.Raw_Dynamic_Array)(v.data).len == 0
+				return (^runtime.Raw_Dynamic_Array)(v.data).len == 0
 			case runtime.Type_Info_Slice:
 			case runtime.Type_Info_Slice:
-			     	return (^runtime.Raw_Slice)(v.data).len == 0
+				return (^runtime.Raw_Slice)(v.data).len == 0
 			case runtime.Type_Info_Union,
 			case runtime.Type_Info_Union,
 			     runtime.Type_Info_Bit_Set,
 			     runtime.Type_Info_Bit_Set,
 			     runtime.Type_Info_Soa_Pointer:
 			     runtime.Type_Info_Soa_Pointer:
 				return reflect.is_nil(v)
 				return reflect.is_nil(v)
 			case runtime.Type_Info_Map:
 			case runtime.Type_Info_Map:
-			     	return (^runtime.Raw_Map)(v.data).len == 0
+				return (^runtime.Raw_Map)(v.data).len == 0
 			}
 			}
 			return false
 			return false
 		}
 		}
@@ -405,6 +405,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 		marshal_struct_fields :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: Marshal_Error) {
 		marshal_struct_fields :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: Marshal_Error) {
 			ti := runtime.type_info_base(type_info_of(v.id))
 			ti := runtime.type_info_base(type_info_of(v.id))
 			info := ti.variant.(runtime.Type_Info_Struct)
 			info := ti.variant.(runtime.Type_Info_Struct)
+			first_iteration := true
 			for name, i in info.names {
 			for name, i in info.names {
 				omitempty := false
 				omitempty := false
 
 
@@ -424,7 +425,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 					continue
 					continue
 				}
 				}
 
 
-				opt_write_iteration(w, opt, i) or_return
+				opt_write_iteration(w, opt, first_iteration) or_return
+				first_iteration = false
 				if json_name != "" {
 				if json_name != "" {
 					opt_write_key(w, opt, json_name) or_return
 					opt_write_key(w, opt, json_name) or_return
 				} else {
 				} else {
@@ -588,10 +590,10 @@ opt_write_start :: proc(w: io.Writer, opt: ^Marshal_Options, c: byte) -> (err: i
 }
 }
 
 
 // insert comma separation and write indentations
 // insert comma separation and write indentations
-opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int) -> (err: io.Error) {
+opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, first_iteration: bool) -> (err: io.Error) {
 	switch opt.spec {
 	switch opt.spec {
-	case .JSON, .JSON5: 
-		if iteration > 0 {
+	case .JSON, .JSON5:
+		if !first_iteration {
 			io.write_byte(w, ',') or_return
 			io.write_byte(w, ',') or_return
 
 
 			if opt.pretty {
 			if opt.pretty {
@@ -601,8 +603,8 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
 
 
 		opt_write_indentation(w, opt) or_return
 		opt_write_indentation(w, opt) or_return
 
 
-	case .MJSON: 
-		if iteration > 0 {
+	case .MJSON:
+		if !first_iteration {
 			// on pretty no commas necessary
 			// on pretty no commas necessary
 			if opt.pretty {
 			if opt.pretty {
 				io.write_byte(w, '\n') or_return
 				io.write_byte(w, '\n') or_return

+ 28 - 0
core/encoding/uuid/LICENSE

@@ -0,0 +1,28 @@
+BSD 3-Clause License
+
+Copyright (c) 2024, Feoramund
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 67 - 0
core/encoding/uuid/definitions.odin

@@ -0,0 +1,67 @@
+package uuid
+
+// A RFC 4122 Universally Unique Identifier
+Identifier :: distinct [16]u8
+
+EXPECTED_LENGTH :: 8 + 4 + 4 + 4 + 12 + 4
+
+VERSION_BYTE_INDEX :: 6
+VARIANT_BYTE_INDEX :: 8
+
+// The number of 100-nanosecond intervals between 1582-10-15 and 1970-01-01.
+HNS_INTERVALS_BETWEEN_GREG_AND_UNIX :: 141427 * 24 * 60 * 60 * 1000 * 1000 * 10
+
+VERSION_7_TIME_MASK     :: 0xffffffff_ffff0000_00000000_00000000
+VERSION_7_TIME_SHIFT    :: 80
+VERSION_7_COUNTER_MASK  :: 0x00000000_00000fff_00000000_00000000
+VERSION_7_COUNTER_SHIFT :: 64
+
+@(private)
+NO_CSPRNG_ERROR :: "The context random generator is not cryptographic. See the documentation for an example of how to set one up."
+@(private)
+BIG_CLOCK_ERROR :: "The clock sequence can only hold 14 bits of data, therefore no number greater than 16,383 (0x3FFF)."
+@(private)
+VERSION_7_BIG_COUNTER_ERROR :: "This implementation of the version 7 UUID counter can only hold 12 bits of data, therefore no number greater than 4,095 (0xFFF)."
+
+Read_Error :: enum {
+	None,
+	Invalid_Length,
+	Invalid_Hexadecimal,
+	Invalid_Separator,
+}
+
+Variant_Type :: enum {
+	Unknown,
+	Reserved_Apollo_NCS,    // 0b0xx
+	RFC_4122,               // 0b10x
+	Reserved_Microsoft_COM, // 0b110
+	Reserved_Future,        // 0b111
+}
+
+// Name string is a fully-qualified domain name.
+@(rodata)
+Namespace_DNS := Identifier {
+	0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+}
+
+// Name string is a URL.
+@(rodata)
+Namespace_URL := Identifier {
+	0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+}
+
+// Name string is an ISO OID.
+@(rodata)
+Namespace_OID := Identifier {
+	0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+}
+
+// Name string is an X.500 DN (in DER or a text output format).
+@(rodata)
+Namespace_X500 := Identifier {
+	0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
+	0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
+}

+ 46 - 0
core/encoding/uuid/doc.odin

@@ -0,0 +1,46 @@
+/*
+package uuid implements Universally Unique Identifiers according to the
+standard originally outlined in RFC 4122 with additions from RFC 9562.
+
+The UUIDs are textually represented and read in the following string format:
+`00000000-0000-v000-V000-000000000000`
+
+`v` is where the version bits reside, and `V` is where the variant bits reside.
+The meaning of the other bits is version-dependent.
+
+Outside of string representations, UUIDs are represented in memory by a 128-bit
+structure organized as an array of 16 bytes.
+
+
+Of the UUID versions which may make use of random number generation, a
+requirement is placed upon them that the underlying generator be
+cryptographically-secure, per RFC 9562's suggestion.
+
+- Version 1 without a node argument.
+- Version 4 in all cases.
+- Version 6 without either a clock or node argument.
+- Version 7 in all cases.
+
+Here's an example of how to set up one:
+	
+	import "core:crypto"
+	import "core:encoding/uuid"
+
+	main :: proc() {
+		my_uuid: uuid.Identifier
+
+		{
+			// This scope will have a CSPRNG.
+			context.random_generator = crypto.random_generator()
+			my_uuid = uuid.generate_v7()
+		}
+
+		// Back to the default random number generator.
+	}
+
+
+For more information on the specifications, see here:
+- https://www.rfc-editor.org/rfc/rfc4122.html
+- https://www.rfc-editor.org/rfc/rfc9562.html
+*/
+package uuid

+ 333 - 0
core/encoding/uuid/generation.odin

@@ -0,0 +1,333 @@
+package uuid
+
+import "base:runtime"
+import "core:crypto/hash"
+import "core:math/rand"
+import "core:time"
+
+/*
+Generate a version 1 UUID.
+
+Inputs:
+- clock_seq: The clock sequence, a number which must be initialized to a random number once in the lifetime of a system.
+- node: An optional 48-bit spatially unique identifier, specified to be the IEEE 802 address of the system.
+  If one is not provided or available, 48 bits of random state will take its place.
+- timestamp: A timestamp from the `core:time` package, or `nil` to use the current time.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v1 :: proc(clock_seq: u16, node: Maybe([6]u8) = nil, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) {
+	assert(clock_seq <= 0x3FFF, BIG_CLOCK_ERROR)
+	unix_time_in_hns_intervals := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 100
+
+	uuid_timestamp := cast(u64le)(HNS_INTERVALS_BETWEEN_GREG_AND_UNIX + unix_time_in_hns_intervals)
+	uuid_timestamp_octets := transmute([8]u8)uuid_timestamp
+
+	result[0] = uuid_timestamp_octets[0]
+	result[1] = uuid_timestamp_octets[1]
+	result[2] = uuid_timestamp_octets[2]
+	result[3] = uuid_timestamp_octets[3]
+	result[4] = uuid_timestamp_octets[4]
+	result[5] = uuid_timestamp_octets[5]
+
+	result[6] = uuid_timestamp_octets[6] >> 4
+	result[7] = uuid_timestamp_octets[6] << 4 | uuid_timestamp_octets[7]
+
+	if realized_node, ok := node.?; ok {
+		mutable_node := realized_node
+		runtime.mem_copy_non_overlapping(&result[10], &mutable_node[0], 6)
+	} else {
+		assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+		bytes_generated := rand.read(result[10:])
+		assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
+	}
+
+	result[VERSION_BYTE_INDEX] |= 0x10
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	result[8] |= cast(u8)(clock_seq & 0x3F00 >> 8)
+	result[9]  = cast(u8)clock_seq
+
+	return
+}
+
+/*
+Generate a version 4 UUID.
+
+This UUID will be pseudorandom, save for 6 pre-determined version and variant bits.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v4 :: proc() -> (result: Identifier) {
+	assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+	bytes_generated := rand.read(result[:])
+	assert(bytes_generated == 16, "RNG failed to generate 16 bytes for UUID v4.")
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x40
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 6 UUID.
+
+Inputs:
+- clock_seq: The clock sequence from version 1, now made optional.
+  If unspecified, it will be replaced with random bits.
+- node: An optional 48-bit spatially unique identifier, specified to be the IEEE 802 address of the system.
+  If one is not provided or available, 48 bits of random state will take its place.
+- timestamp: A timestamp from the `core:time` package, or `nil` to use the current time.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) {
+	unix_time_in_hns_intervals := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 100
+
+	uuid_timestamp := cast(u128be)(HNS_INTERVALS_BETWEEN_GREG_AND_UNIX + unix_time_in_hns_intervals)
+
+	result = transmute(Identifier)(
+		uuid_timestamp & 0x0FFFFFFF_FFFFF000 << 68 |
+		uuid_timestamp & 0x00000000_00000FFF << 64
+	)
+
+	if realized_clock_seq, ok := clock_seq.?; ok {
+		assert(realized_clock_seq <= 0x3FFF, BIG_CLOCK_ERROR)
+		result[8] |= cast(u8)(realized_clock_seq & 0x3F00 >> 8)
+		result[9]  = cast(u8)realized_clock_seq
+	} else {
+		assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+		temporary: [2]u8
+		bytes_generated := rand.read(temporary[:])
+		assert(bytes_generated == 2, "RNG failed to generate 2 bytes for UUID v1.")
+		result[8] |= temporary[0] & 0x3F
+		result[9]  = temporary[1]
+	}
+
+	if realized_node, ok := node.?; ok {
+		mutable_node := realized_node
+		runtime.mem_copy_non_overlapping(&result[10], &mutable_node[0], 6)
+	} else {
+		assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+		bytes_generated := rand.read(result[10:])
+		assert(bytes_generated == 6, "RNG failed to generate 6 bytes for UUID v1.")
+	}
+
+	result[VERSION_BYTE_INDEX] |= 0x60
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 7 UUID.
+
+This UUID will be pseudorandom, save for 6 pre-determined version and variant
+bits and a 48-bit timestamp.
+
+It is designed with time-based sorting in mind, such as for database usage, as
+the highest bits are allocated from the timestamp of when it is created.
+
+Inputs:
+- timestamp: A timestamp from the `core:time` package, or `nil` to use the current time.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v7_basic :: proc(timestamp: Maybe(time.Time) = nil) -> (result: Identifier) {
+	assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+	unix_time_in_milliseconds := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 1e6
+
+	result = transmute(Identifier)(cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT)
+
+	bytes_generated := rand.read(result[6:])
+	assert(bytes_generated == 10, "RNG failed to generate 10 bytes for UUID v7.")
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x70
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 7 UUID that has an incremented counter.
+
+This UUID will be pseudorandom, save for 6 pre-determined version and variant
+bits, a 48-bit timestamp, and 12 bits of counter state.
+
+It is designed with time-based sorting in mind, such as for database usage, as
+the highest bits are allocated from the timestamp of when it is created.
+
+This procedure is preferable if you are generating hundreds or thousands of
+UUIDs as a batch within the span of a millisecond. Do note that the counter
+only has 12 bits of state, thus `counter` cannot exceed the number 4,095.
+
+Example:
+
+	import "core:uuid"
+
+	// Create a batch of UUIDs all at once.
+	batch: [dynamic]uuid.Identifier
+
+	for i: u16 = 0; i < 1000; i += 1 {
+		my_uuid := uuid.generate_v7_counter(i)
+		append(&batch, my_uuid)
+	}
+
+Inputs:
+- counter: A 12-bit value which should be incremented each time a UUID is generated in a batch.
+- timestamp: A timestamp from the `core:time` package, or `nil` to use the current time.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v7_with_counter :: proc(counter: u16, timestamp: Maybe(time.Time) = nil) -> (result: Identifier) {
+	assert(.Cryptographic in runtime.random_generator_query_info(context.random_generator), NO_CSPRNG_ERROR)
+	assert(counter <= 0x0fff, VERSION_7_BIG_COUNTER_ERROR)
+	unix_time_in_milliseconds := time.to_unix_nanoseconds(timestamp.? or_else time.now()) / 1e6
+
+	result = transmute(Identifier)(
+		cast(u128be)unix_time_in_milliseconds << VERSION_7_TIME_SHIFT |
+		cast(u128be)counter << VERSION_7_COUNTER_SHIFT
+	)
+
+	bytes_generated := rand.read(result[8:])
+	assert(bytes_generated == 8, "RNG failed to generate 8 bytes for UUID v7.")
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x70
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+generate_v7 :: proc {
+	generate_v7_basic,
+	generate_v7_with_counter,
+}
+
+/*
+Generate a version 8 UUID using a specific hashing algorithm.
+
+This UUID is generated by hashing a name with a namespace.
+
+Note that all version 8 UUIDs are for experimental or vendor-specific use
+cases, per the specification. This use case in particular is for offering a
+non-legacy alternative to UUID versions 3 and 5.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in this package.
+- name: The byte slice which will be hashed with the namespace.
+- algorithm: A hashing algorithm from `core:crypto/hash`.
+
+Returns:
+- result: The generated UUID.
+
+Example:
+	import "core:crypto/hash"
+	import "core:encoding/uuid"
+	import "core:fmt"
+
+	main :: proc() {
+		my_uuid := uuid.generate_v8_hash(uuid.Namespace_DNS, "www.odin-lang.org", .SHA256)
+		my_uuid_string := uuid.to_string(my_uuid, context.temp_allocator)
+		fmt.println(my_uuid_string)
+	}
+
+Output:
+
+	3730f688-4bff-8dce-9cbf-74a3960c5703
+
+*/
+generate_v8_hash_bytes :: proc(
+	namespace: Identifier,
+	name: []byte,
+	algorithm: hash.Algorithm,
+) -> (
+	result: Identifier,
+) {
+	// 128 bytes should be enough for the foreseeable future.
+	digest: [128]byte
+
+	assert(hash.DIGEST_SIZES[algorithm] >= 16, "Per RFC 9562, the hashing algorithm used must generate a digest of 128 bits or larger.")
+	assert(hash.DIGEST_SIZES[algorithm] < len(digest), "Digest size is too small for this algorithm. The buffer must be increased.")
+
+	hash_context: hash.Context
+	hash.init(&hash_context, algorithm)
+
+	mutable_namespace := namespace
+	hash.update(&hash_context, mutable_namespace[:])
+	hash.update(&hash_context, name[:])
+	hash.final(&hash_context, digest[:])
+
+	runtime.mem_copy_non_overlapping(&result, &digest, 16)
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x80
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 8 UUID using a specific hashing algorithm.
+
+This UUID is generated by hashing a name with a namespace.
+
+Note that all version 8 UUIDs are for experimental or vendor-specific use
+cases, per the specification. This use case in particular is for offering a
+non-legacy alternative to UUID versions 3 and 5.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in this package.
+- name: The string which will be hashed with the namespace.
+- algorithm: A hashing algorithm from `core:crypto/hash`.
+
+Returns:
+- result: The generated UUID.
+
+Example:
+	import "core:crypto/hash"
+	import "core:encoding/uuid"
+	import "core:fmt"
+
+	main :: proc() {
+		my_uuid := uuid.generate_v8_hash(uuid.Namespace_DNS, "www.odin-lang.org", .SHA256)
+		my_uuid_string := uuid.to_string(my_uuid, context.temp_allocator)
+		fmt.println(my_uuid_string)
+	}
+
+Output:
+
+	3730f688-4bff-8dce-9cbf-74a3960c5703
+
+*/
+generate_v8_hash_string :: proc(
+	namespace: Identifier,
+	name: string,
+	algorithm: hash.Algorithm,
+) -> (
+	result: Identifier,
+) {
+	return generate_v8_hash_bytes(namespace, transmute([]byte)name, algorithm)
+}
+
+generate_v8_hash :: proc {
+	generate_v8_hash_bytes,
+	generate_v8_hash_string,
+}

+ 146 - 0
core/encoding/uuid/legacy/legacy.odin

@@ -0,0 +1,146 @@
+/*
+package uuid/legacy implements versions 3 and 5 of UUID generation, both of
+which are using hashing algorithms (MD5 and SHA1, respectively) that are known
+these days to no longer be secure.
+*/
+package uuid_legacy
+
+import "base:runtime"
+import "core:crypto/legacy/md5"
+import "core:crypto/legacy/sha1"
+import "core:encoding/uuid"
+
+Identifier :: uuid.Identifier
+VERSION_BYTE_INDEX :: uuid.VERSION_BYTE_INDEX
+VARIANT_BYTE_INDEX :: uuid.VARIANT_BYTE_INDEX
+
+
+/*
+Generate a version 3 UUID.
+
+This UUID is generated with a MD5 hash of a name and a namespace.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in the `uuid` package.
+- name: The byte slice which will be hashed with the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v3_bytes :: proc(
+	namespace: Identifier,
+	name: []byte,
+) -> (
+	result: Identifier,
+) {
+	namespace := namespace
+
+	ctx: md5.Context
+	md5.init(&ctx)
+	md5.update(&ctx, namespace[:])
+	md5.update(&ctx, name)
+	md5.final(&ctx, result[:])
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x30
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 3 UUID.
+
+This UUID is generated with a MD5 hash of a name and a namespace.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in the `uuid` package.
+- name: The string which will be hashed with the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v3_string :: proc(
+	namespace: Identifier,
+	name: string,
+) -> (
+	result: Identifier,
+) {
+	return generate_v3_bytes(namespace, transmute([]byte)name)
+}
+
+generate_v3 :: proc {
+	generate_v3_bytes,
+	generate_v3_string,
+}
+
+/*
+Generate a version 5 UUID.
+
+This UUID is generated with a SHA1 hash of a name and a namespace.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in the `uuid` package.
+- name: The byte slice which will be hashed with the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v5_bytes :: proc(
+	namespace: Identifier,
+	name: []byte,
+) -> (
+	result: Identifier,
+) {
+	namespace := namespace
+	digest: [sha1.DIGEST_SIZE]byte
+
+	ctx: sha1.Context
+	sha1.init(&ctx)
+	sha1.update(&ctx, namespace[:])
+	sha1.update(&ctx, name)
+	sha1.final(&ctx, digest[:])
+
+	runtime.mem_copy_non_overlapping(&result, &digest, 16)
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x50
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Generate a version 5 UUID.
+
+This UUID is generated with a SHA1 hash of a name and a namespace.
+
+Inputs:
+- namespace: An `Identifier` that is used to represent the underlying namespace.
+  This can be any one of the `Namespace_*` values provided in the `uuid` package.
+- name: The string which will be hashed with the namespace.
+
+Returns:
+- result: The generated UUID.
+*/
+generate_v5_string :: proc(
+	namespace: Identifier,
+	name: string,
+) -> (
+	result: Identifier,
+) {
+	return generate_v5_bytes(namespace, transmute([]byte)name)
+}
+
+generate_v5 :: proc {
+	generate_v5_bytes,
+	generate_v5_string,
+}
+

+ 242 - 0
core/encoding/uuid/reading.odin

@@ -0,0 +1,242 @@
+package uuid
+
+import "base:runtime"
+import "core:time"
+
+/*
+Convert a string to a UUID.
+
+Inputs:
+- str: A string in the 8-4-4-4-12 format.
+
+Returns:
+- id: The converted identifier, or `nil` if there is an error.
+- error: A description of the error, or `nil` if successful.
+*/
+read :: proc "contextless" (str: string) -> (id: Identifier, error: Read_Error) #no_bounds_check {
+	// Only exact-length strings are acceptable.
+	if len(str) != EXPECTED_LENGTH {
+		return {}, .Invalid_Length
+	}
+
+	// Check ahead to see if the separators are in the right places.
+	if str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-' {
+		return {}, .Invalid_Separator
+	}
+
+	read_nibble :: proc "contextless" (nibble: u8) -> u8 {
+		switch nibble {
+		case '0' ..= '9':
+			return nibble - '0'
+		case 'A' ..= 'F':
+			return nibble - 'A' + 10
+		case 'a' ..= 'f':
+			return nibble - 'a' + 10
+		case:
+			// Return an error value.
+			return 0xFF
+		}
+	}
+
+	index := 0
+	octet_index := 0
+
+	CHUNKS :: [5]int{8, 4, 4, 4, 12}
+
+	for chunk in CHUNKS {
+		for i := index; i < index + chunk; i += 2 {
+			high := read_nibble(str[i])
+			low := read_nibble(str[i + 1])
+
+			if high | low > 0xF {
+				return {}, .Invalid_Hexadecimal
+			}
+
+			id[octet_index] = low | high << 4
+			octet_index += 1
+		}
+
+		index += chunk + 1
+	}
+
+	return
+}
+
+/*
+Get the version of a UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- number: The version number.
+*/
+version :: proc "contextless" (id: Identifier) -> (number: int) #no_bounds_check {
+	return cast(int)(id[VERSION_BYTE_INDEX] & 0xF0 >> 4)
+}
+
+/*
+Get the variant of a UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- variant: The variant type.
+*/
+variant :: proc "contextless" (id: Identifier) -> (variant: Variant_Type) #no_bounds_check {
+	switch {
+	case id[VARIANT_BYTE_INDEX] & 0x80 == 0:
+		return .Reserved_Apollo_NCS
+	case id[VARIANT_BYTE_INDEX] & 0xC0 == 0x80:
+		return .RFC_4122
+	case id[VARIANT_BYTE_INDEX] & 0xE0 == 0xC0:
+		return .Reserved_Microsoft_COM
+	case id[VARIANT_BYTE_INDEX] & 0xF0 == 0xE0:
+		return .Reserved_Future
+	case:
+		return .Unknown
+	}
+}
+
+/*
+Get the clock sequence of a version 1 or version 6 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- clock_seq: The 14-bit clock sequence field.
+*/
+clock_seq :: proc "contextless" (id: Identifier) -> (clock_seq: u16) {
+	return cast(u16)id[9] | cast(u16)id[8] & 0x3F << 8
+}
+
+/*
+Get the node of a version 1 or version 6 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- node: The 48-bit spatially unique identifier.
+*/
+node :: proc "contextless" (id: Identifier) -> (node: [6]u8) {
+	mutable_id := id
+	runtime.mem_copy_non_overlapping(&node, &mutable_id[10], 6)
+	return
+}
+
+/*
+Get the raw timestamp of a version 1 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp, in 100-nanosecond intervals since 1582-10-15.
+*/
+raw_time_v1 :: proc "contextless" (id: Identifier) -> (timestamp: u64) {
+	timestamp_octets: [8]u8
+
+	timestamp_octets[0] = id[0]
+	timestamp_octets[1] = id[1]
+	timestamp_octets[2] = id[2]
+	timestamp_octets[3] = id[3]
+	timestamp_octets[4] = id[4]
+	timestamp_octets[5] = id[5]
+
+	timestamp_octets[6] = id[6] << 4 | id[7] >> 4
+	timestamp_octets[7] = id[7] & 0xF
+
+	return cast(u64)transmute(u64le)timestamp_octets
+}
+
+
+/*
+Get the timestamp of a version 1 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp of the UUID.
+*/
+time_v1 :: proc "contextless" (id: Identifier) -> (timestamp: time.Time) {
+	return time.from_nanoseconds(cast(i64)(raw_time_v1(id) - HNS_INTERVALS_BETWEEN_GREG_AND_UNIX) * 100)
+}
+
+/*
+Get the raw timestamp of a version 6 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp, in 100-nanosecond intervals since 1582-10-15.
+*/
+raw_time_v6 :: proc "contextless" (id: Identifier) -> (timestamp: u64) {
+	temporary := transmute(u128be)id
+
+	timestamp |= cast(u64)(temporary & 0xFFFFFFFF_FFFF0000_00000000_00000000 >> 68)
+	timestamp |= cast(u64)(temporary & 0x00000000_00000FFF_00000000_00000000 >> 64)
+
+	return timestamp
+}
+
+/*
+Get the timestamp of a version 6 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp, in 100-nanosecond intervals since 1582-10-15.
+*/
+time_v6 :: proc "contextless" (id: Identifier) -> (timestamp: time.Time) {
+	return time.from_nanoseconds(cast(i64)(raw_time_v6(id) - HNS_INTERVALS_BETWEEN_GREG_AND_UNIX) * 100)
+}
+
+/*
+Get the raw timestamp of a version 7 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp, in milliseconds since the UNIX epoch.
+*/
+raw_time_v7 :: proc "contextless" (id: Identifier) -> (timestamp: u64) {
+	time_bits := transmute(u128be)id & VERSION_7_TIME_MASK
+	return cast(u64)(time_bits >> VERSION_7_TIME_SHIFT)
+}
+
+/*
+Get the timestamp of a version 7 UUID.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- timestamp: The timestamp, in milliseconds since the UNIX epoch.
+*/
+time_v7 :: proc "contextless" (id: Identifier) -> (timestamp: time.Time) {
+	return time.from_nanoseconds(cast(i64)raw_time_v7(id) * 1e6)
+}
+
+/*
+Get the 12-bit counter value of a version 7 UUID.
+
+The UUID must have been generated with a counter, otherwise this procedure will
+return random bits.
+
+Inputs:
+- id: The identifier.
+
+Returns:
+- counter: The 12-bit counter value.
+*/
+counter_v7 :: proc "contextless" (id: Identifier) -> (counter: u16) {
+	counter_bits := transmute(u128be)id & VERSION_7_COUNTER_MASK
+	return cast(u16)(counter_bits >> VERSION_7_COUNTER_SHIFT)
+}

+ 89 - 0
core/encoding/uuid/stamping.odin

@@ -0,0 +1,89 @@
+package uuid
+
+import "base:runtime"
+
+/*
+Stamp a 128-bit integer as being a valid version 8 UUID.
+
+Per the specification, all version 8 UUIDs are either for experimental or
+vendor-specific purposes. This procedure allows for converting arbitrary data
+into custom UUIDs.
+
+Inputs:
+- integer: Any integer type.
+
+Returns:
+- result: A valid version 8 UUID.
+*/
+stamp_v8_int :: proc(#any_int integer: u128) -> (result: Identifier) {
+	result = transmute(Identifier)cast(u128be)integer
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x80
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Stamp an array of 16 bytes as being a valid version 8 UUID.
+
+Per the specification, all version 8 UUIDs are either for experimental or
+vendor-specific purposes. This procedure allows for converting arbitrary data
+into custom UUIDs.
+
+Inputs:
+- array: An array of 16 bytes.
+
+Returns:
+- result: A valid version 8 UUID.
+*/
+stamp_v8_array :: proc(array: [16]u8) -> (result: Identifier) {
+	result = Identifier(array)
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x80
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+/*
+Stamp a slice of bytes as being a valid version 8 UUID.
+
+If the slice is less than 16 bytes long, the data available will be used.
+If it is longer than 16 bytes, only the first 16 will be used.
+
+This procedure does not modify the underlying slice.
+
+Per the specification, all version 8 UUIDs are either for experimental or
+vendor-specific purposes. This procedure allows for converting arbitrary data
+into custom UUIDs.
+
+Inputs:
+- slice: A slice of bytes.
+
+Returns:
+- result: A valid version 8 UUID.
+*/
+stamp_v8_slice :: proc(slice: []u8) -> (result: Identifier) {
+	runtime.mem_copy_non_overlapping(&result, &slice[0], min(16, len(slice)))
+
+	result[VERSION_BYTE_INDEX] &= 0x0F
+	result[VERSION_BYTE_INDEX] |= 0x80
+
+	result[VARIANT_BYTE_INDEX] &= 0x3F
+	result[VARIANT_BYTE_INDEX] |= 0x80
+
+	return
+}
+
+stamp_v8 :: proc {
+	stamp_v8_int,
+	stamp_v8_array,
+	stamp_v8_slice,
+}

+ 131 - 0
core/encoding/uuid/writing.odin

@@ -0,0 +1,131 @@
+package uuid
+
+import "base:runtime"
+import "core:io"
+import "core:strconv"
+import "core:strings"
+
+/*
+Write a UUID in the 8-4-4-4-12 format.
+
+This procedure performs error checking with every byte written.
+
+If you can guarantee beforehand that your stream has enough space to hold the
+UUID (32 bytes), then it is better to use `unsafe_write` instead as that will
+be faster.
+
+Inputs:
+- w: A writable stream.
+- id: The identifier to convert.
+
+Returns:
+- error: An `io` error, if one occurred, otherwise `nil`.
+*/
+write :: proc(w: io.Writer, id: Identifier) -> (error: io.Error) #no_bounds_check {
+	write_octet :: proc (w: io.Writer, octet: u8) -> io.Error #no_bounds_check {
+		high_nibble := octet >> 4
+		low_nibble := octet & 0xF
+
+		io.write_byte(w, strconv.digits[high_nibble]) or_return
+		io.write_byte(w, strconv.digits[low_nibble]) or_return
+		return nil
+	}
+
+	for index in  0 ..<  4 { write_octet(w, id[index]) or_return }
+	io.write_byte(w, '-') or_return
+	for index in  4 ..<  6 { write_octet(w, id[index]) or_return }
+	io.write_byte(w, '-') or_return
+	for index in  6 ..<  8 { write_octet(w, id[index]) or_return }
+	io.write_byte(w, '-') or_return
+	for index in  8 ..< 10 { write_octet(w, id[index]) or_return }
+	io.write_byte(w, '-') or_return
+	for index in 10 ..< 16 { write_octet(w, id[index]) or_return }
+
+	return nil
+}
+
+/*
+Write a UUID in the 8-4-4-4-12 format.
+
+This procedure performs no error checking on the underlying stream.
+
+Inputs:
+- w: A writable stream.
+- id: The identifier to convert.
+*/
+unsafe_write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
+	write_octet :: proc (w: io.Writer, octet: u8) #no_bounds_check {
+		high_nibble := octet >> 4
+		low_nibble := octet & 0xF
+
+		io.write_byte(w, strconv.digits[high_nibble])
+		io.write_byte(w, strconv.digits[low_nibble])
+	}
+
+	for index in  0 ..<  4 { write_octet(w, id[index]) }
+	io.write_byte(w, '-')
+	for index in  4 ..<  6 { write_octet(w, id[index]) }
+	io.write_byte(w, '-')
+	for index in  6 ..<  8 { write_octet(w, id[index]) }
+	io.write_byte(w, '-')
+	for index in  8 ..< 10 { write_octet(w, id[index]) }
+	io.write_byte(w, '-')
+	for index in 10 ..< 16 { write_octet(w, id[index]) }
+}
+
+/*
+Convert a UUID to a string in the 8-4-4-4-12 format.
+
+*Allocates Using Provided Allocator*
+
+Inputs:
+- id: The identifier to convert.
+- allocator: (default: context.allocator)
+- loc: The caller location for debugging purposes (default: #caller_location)
+
+Returns:
+- str: The allocated and converted string.
+- error: An optional allocator error if one occured, `nil` otherwise.
+*/
+to_string_allocated :: proc(
+	id: Identifier,
+	allocator := context.allocator,
+	loc := #caller_location,
+) -> (
+	str: string,
+	error: runtime.Allocator_Error,
+) #optional_allocator_error {
+	buf := make([]byte, EXPECTED_LENGTH, allocator, loc) or_return
+	builder := strings.builder_from_bytes(buf[:])
+	unsafe_write(strings.to_writer(&builder), id)
+	return strings.to_string(builder), nil
+}
+
+/*
+Convert a UUID to a string in the 8-4-4-4-12 format.
+
+Inputs:
+- id: The identifier to convert.
+- buffer: A byte buffer to store the result. Must be at least 32 bytes large.
+- loc: The caller location for debugging purposes (default: #caller_location)
+
+Returns:
+- str: The converted string which will be stored in `buffer`.
+*/
+to_string_buffer :: proc(
+	id: Identifier,
+	buffer: []byte,
+	loc := #caller_location,
+) -> (
+	str: string,
+) {
+	assert(len(buffer) >= EXPECTED_LENGTH, "The buffer provided is not at least 32 bytes large.", loc)
+	builder := strings.builder_from_bytes(buffer)
+	unsafe_write(strings.to_writer(&builder), id)
+	return strings.to_string(builder)
+}
+
+to_string :: proc {
+	to_string_allocated,
+	to_string_buffer,
+}

+ 5 - 5
core/encoding/xml/debug_print.odin

@@ -33,7 +33,7 @@ print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error
 		written += fmt.wprintf(writer, "[DOCTYPE]  %v\n", doc.doctype.ident)
 		written += fmt.wprintf(writer, "[DOCTYPE]  %v\n", doc.doctype.ident)
 
 
 		if len(doc.doctype.rest) > 0 {
 		if len(doc.doctype.rest) > 0 {
-		 	fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
+			fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
 		}
 		}
 	}
 	}
 
 
@@ -42,10 +42,10 @@ print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error
 	}
 	}
 
 
 	if len(doc.elements) > 0 {
 	if len(doc.elements) > 0 {
-	 	fmt.wprintln(writer, " --- ")
-	 	print_element(writer, doc, 0)
-	 	fmt.wprintln(writer, " --- ")
-	 }
+		fmt.wprintln(writer, " --- ")
+		print_element(writer, doc, 0)
+		fmt.wprintln(writer, " --- ")
+	}
 
 
 	return written, .None
 	return written, .None
 }
 }

+ 5 - 5
core/encoding/xml/tokenizer.odin

@@ -126,7 +126,7 @@ error :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
 	t.error_count += 1
 	t.error_count += 1
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 advance_rune :: proc(t: ^Tokenizer) {
 advance_rune :: proc(t: ^Tokenizer) {
 	#no_bounds_check {
 	#no_bounds_check {
 		/*
 		/*
@@ -170,7 +170,7 @@ peek_byte :: proc(t: ^Tokenizer, offset := 0) -> byte {
 	return 0
 	return 0
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 skip_whitespace :: proc(t: ^Tokenizer) {
 skip_whitespace :: proc(t: ^Tokenizer) {
 	for {
 	for {
 		switch t.ch {
 		switch t.ch {
@@ -182,7 +182,7 @@ skip_whitespace :: proc(t: ^Tokenizer) {
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 is_letter :: proc(r: rune) -> bool {
 is_letter :: proc(r: rune) -> bool {
 	if r < utf8.RUNE_SELF {
 	if r < utf8.RUNE_SELF {
 		switch r {
 		switch r {
@@ -296,7 +296,7 @@ skip_cdata :: proc(t: ^Tokenizer) -> (err: Error) {
 	return
 	return
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close := false, multiline := true) -> (value: string, err: Error) {
 scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close := false, multiline := true) -> (value: string, err: Error) {
 	err = .None
 	err = .None
 
 
@@ -414,4 +414,4 @@ scan :: proc(t: ^Tokenizer, multiline_string := false) -> Token {
 		lit = string(t.src[offset : t.offset])
 		lit = string(t.src[offset : t.offset])
 	}
 	}
 	return Token{kind, lit, pos}
 	return Token{kind, lit, pos}
-}
+}

+ 28 - 0
core/flags/LICENSE

@@ -0,0 +1,28 @@
+BSD 3-Clause License
+
+Copyright (c) 2024, Feoramund
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 38 - 0
core/flags/constants.odin

@@ -0,0 +1,38 @@
+package flags
+
+import "core:time"
+
+// Set to true to compile with support for core named types disabled, as a
+// fallback in the event your platform does not support one of the types, or
+// you have no need for them and want a smaller binary.
+NO_CORE_NAMED_TYPES :: #config(ODIN_CORE_FLAGS_NO_CORE_NAMED_TYPES, false)
+
+// Override support for parsing `time` types.
+IMPORTING_TIME      :: #config(ODIN_CORE_FLAGS_USE_TIME, time.IS_SUPPORTED)
+
+// Override support for parsing `net` types.
+// TODO: Update this when the BSDs are supported.
+IMPORTING_NET       :: #config(ODIN_CORE_FLAGS_USE_NET, ODIN_OS == .Windows || ODIN_OS == .Linux || ODIN_OS == .Darwin)
+
+TAG_ARGS          :: "args"
+SUBTAG_NAME       :: "name"
+SUBTAG_POS        :: "pos"
+SUBTAG_REQUIRED   :: "required"
+SUBTAG_HIDDEN     :: "hidden"
+SUBTAG_VARIADIC   :: "variadic"
+SUBTAG_FILE       :: "file"
+SUBTAG_PERMS      :: "perms"
+SUBTAG_INDISTINCT :: "indistinct"
+
+TAG_USAGE         :: "usage"
+
+UNDOCUMENTED_FLAG :: "<This flag has not been documented yet.>"
+
+INTERNAL_VARIADIC_FLAG   :: "varg"
+
+RESERVED_HELP_FLAG       :: "help"
+RESERVED_HELP_FLAG_SHORT :: "h"
+
+// If there are more than this number of flags in total, only the required and
+// positional flags will be shown in the one-line usage summary.
+ONE_LINE_FLAG_CUTOFF_COUNT :: 16

+ 181 - 0
core/flags/doc.odin

@@ -0,0 +1,181 @@
+/*
+package flags implements a command-line argument parser.
+
+It works by using Odin's run-time type information to determine where and how
+to store data on a struct provided by the program. Type conversion is handled
+automatically and errors are reported with useful messages.
+
+
+Command-Line Syntax:
+
+Arguments are treated differently depending on how they're formatted.
+The format is similar to the Odin binary's way of handling compiler flags.
+
+```
+type                  handling
+------------          ------------------------
+<positional>          depends on struct layout
+-<flag>               set a bool true
+-<flag:option>        set flag to option
+-<flag=option>        set flag to option, alternative syntax
+-<map>:<key>=<value>  set map[key] to value
+```
+
+
+Struct Tags:
+
+Users of the `core:encoding/json` package may be familiar with using tags to
+annotate struct metadata. The same technique is used here to annotate where
+arguments should go and which are required.
+
+Under the `args` tag, there are the following subtags:
+
+- `name=S`: set `S` as the flag's name.
+- `pos=N`: place positional argument `N` into this flag.
+- `hidden`: hide this flag from the usage documentation.
+- `required`: cause verification to fail if this argument is not set.
+- `variadic`: take all remaining arguments when set, UNIX-style only.
+- `file`: for `os.Handle` types, file open mode.
+- `perms`: for `os.Handle` types, file open permissions.
+- `indistinct`: allow the setting of distinct types by their base type.
+
+`required` may be given a range specifier in the following formats:
+```
+min
+<max
+min<max
+```
+
+`max` is not inclusive in this range, as noted by the less-than `<` sign, so if
+you want to require 3 and only 3 arguments in a dynamic array, you would
+specify `required=3<4`.
+
+
+`variadic` may be given a number (`variadic=N`) above 1 to limit how many extra
+arguments it consumes.
+
+
+`file` determines the file open mode for an `os.Handle`.
+It accepts a string of flags that can be mixed together:
+- r: read
+- w: write
+- c: create, create the file if it doesn't exist
+- a: append, add any new writes to the end of the file
+- t: truncate, erase the file on open
+
+
+`perms` determines the file open permissions for an `os.Handle`.
+
+The permissions are represented by three numbers in octal format. The first
+number is the owner, the second is the group, and the third is other. Read is
+represented by 4, write by 2, and execute by 1.
+
+These numbers are added together to get combined permissions. For example, 644
+represents read/write for the owner, read for the group, and read for other.
+
+Note that this may only have effect on UNIX-like platforms. By default, `perms`
+is set to 444 when only reading and 644 when writing.
+
+
+`indistinct` tells the parser that it's okay to treat distinct types as their
+underlying base type. Normally, the parser will hand those types off to the
+custom type setter (more about that later) if one is available, if it doesn't
+know how to handle the type.
+
+
+Usage Tag:
+
+There is also the `usage` tag, which is a plain string to be printed alongside
+the flag in the usage output. If `usage` contains a newline, it will be
+properly aligned when printed.
+
+All surrounding whitespace is trimmed when formatting with multiple lines.
+
+
+Supported Flag Data Types:
+
+- all booleans
+- all integers
+- all floats
+- all enums
+- all complex numbers
+- all quaternions
+- all bit_sets
+- `string` and `cstring`
+- `rune`
+- `os.Handle`
+- `time.Time`
+- `datetime.DateTime`
+- `net.Host_Or_Endpoint`,
+- additional custom types, see Custom Types below
+- `dynamic` arrays with element types of the above
+- `map[string]`s or `map[cstring]`s with value types of the above
+
+
+Validation:
+
+The parser will ensure `required` arguments are set, if no errors occurred
+during parsing. This is on by default.
+
+Additionally, you may call `register_flag_checker` to set your own argument
+validation procedure that will be called after the default checker.
+
+
+Strict:
+
+The parser will return on the first error and stop parsing. This is on by
+default. Otherwise, all arguments that can be parsed, will be, and only the
+last error is returned.
+
+
+Error Messages:
+
+All error message strings are allocated using the context's `temp_allocator`,
+so if you need them to persist, make sure to clone the underlying `message`.
+
+
+Help:
+
+By default, `-h` and `-help` are reserved flags which raise their own error
+type when set, allowing the program to handle the request differently from
+other errors.
+
+
+Custom Types:
+
+You may specify your own type setter for program-specific structs and other
+named types. Call `register_type_setter` with an appropriate proc before
+calling any of the parsing procs.
+
+A compliant `Custom_Type_Setter` must return three values:
+- an error message if one occurred,
+- a boolean indicating if the proc handles the type, and
+- an `Allocator_Error` if any occurred.
+
+If the setter does not handle the type, simply return without setting any of
+the values.
+
+
+UNIX-style:
+
+This package also supports parsing arguments in a limited flavor of UNIX.
+Odin and UNIX style are mutually exclusive, and which one to be used is chosen
+at parse time.
+
+```
+--flag
+--flag=argument
+--flag argument
+--flag argument repeating-argument
+```
+
+`-flag` may also be substituted for `--flag`.
+
+Do note that map flags are not currently supported in this parsing style.
+
+
+Example:
+
+A complete example is given in the `example` subdirectory.
+*/
+package flags

+ 50 - 0
core/flags/errors.odin

@@ -0,0 +1,50 @@
+package flags
+
+import "core:os"
+
+Parse_Error_Reason :: enum {
+	None,
+	// An extra positional argument was given, and there is no `varg` field.
+	Extra_Positional,
+	// The underlying type does not support the string value it is being set to.
+	Bad_Value,
+	// No flag was given by the user.
+	No_Flag,
+	// No value was given by the user.
+	No_Value,
+	// The flag on the struct is missing.
+	Missing_Flag,
+	// The type itself isn't supported.
+	Unsupported_Type,
+}
+
+// Raised during parsing, naturally.
+Parse_Error :: struct {
+	reason: Unified_Parse_Error_Reason,
+	message: string,
+}
+
+// Raised during parsing.
+// Provides more granular information than what just a string could hold.
+Open_File_Error :: struct {
+	filename: string,
+	errno: os.Errno,
+	mode: int,
+	perms: int,
+}
+
+// Raised during parsing.
+Help_Request :: distinct bool
+
+
+// Raised after parsing, during validation.
+Validation_Error :: struct {
+	message: string,
+}
+
+Error :: union {
+	Parse_Error,
+	Open_File_Error,
+	Help_Request,
+	Validation_Error,
+}

+ 9 - 0
core/flags/errors_bsd.odin

@@ -0,0 +1,9 @@
+//+build freebsd, netbsd, openbsd
+package flags
+
+import "base:runtime"
+
+Unified_Parse_Error_Reason :: union #shared_nil {
+	Parse_Error_Reason,
+	runtime.Allocator_Error,
+}

+ 11 - 0
core/flags/errors_nonbsd.odin

@@ -0,0 +1,11 @@
+//+build !freebsd !netbsd !openbsd
+package flags
+
+import "base:runtime"
+import "core:net"
+
+Unified_Parse_Error_Reason :: union #shared_nil {
+	Parse_Error_Reason,
+	runtime.Allocator_Error,
+	net.Parse_Endpoint_Error,
+}

+ 132 - 0
core/flags/example/example.odin

@@ -0,0 +1,132 @@
+package core_flags_example
+
+import "base:runtime"
+import "core:flags"
+import "core:fmt"
+import "core:net"
+import "core:os"
+import "core:time/datetime"
+
+
+Fixed_Point1_1 :: struct {
+	integer: u8,
+	fractional: u8,
+}
+
+Optimization_Level :: enum {
+	Slow,
+	Fast,
+	Warp_Speed,
+	Ludicrous_Speed,
+}
+
+// It's simple but powerful.
+my_custom_type_setter :: proc(
+	data: rawptr,
+	data_type: typeid,
+	unparsed_value: string,
+	args_tag: string,
+) -> (
+	error: string,
+	handled: bool,
+	alloc_error: runtime.Allocator_Error,
+) {
+	if data_type == Fixed_Point1_1 {
+		handled = true
+		ptr := cast(^Fixed_Point1_1)data
+
+		// precision := flags.get_subtag(args_tag, "precision")
+
+		if len(unparsed_value) == 3 {
+			ptr.integer = unparsed_value[0] - '0'
+			ptr.fractional = unparsed_value[2] - '0'
+		} else {
+			error = "Incorrect format. Must be in the form of `i.f`."
+		}
+
+		// Perform sanity checking here in the type parsing phase.
+		//
+		// The validation phase is flag-specific.
+		if !(0 <= ptr.integer && ptr.integer < 10) || !(0 <= ptr.fractional && ptr.fractional < 10) {
+			error = "Incorrect format. Must be between `0.0` and `9.9`."
+		}
+	}
+
+	return
+}
+
+my_custom_flag_checker :: proc(
+	model: rawptr,
+	name: string,
+	value: any,
+	args_tag: string,
+) -> (error: string) {
+	if name == "iterations" {
+		v := value.(int)
+		if !(1 <= v && v < 5) {
+			error = "Iterations only supports 1 ..< 5."
+		}
+	}
+
+	return
+}
+
+Distinct_Int :: distinct int
+
+main :: proc() {
+	Options :: struct {
+
+		file: os.Handle `args:"pos=0,required,file=r" usage:"Input file."`,
+		output: os.Handle `args:"pos=1,file=cw" usage:"Output file."`,
+
+		hub: net.Host_Or_Endpoint `usage:"Internet address to contact for updates."`,
+		schedule: datetime.DateTime `usage:"Launch tasks at this time."`,
+
+		opt: Optimization_Level `usage:"Optimization level."`,
+		todo: [dynamic]string `usage:"Todo items."`,
+
+		accuracy: Fixed_Point1_1 `args:"required" usage:"Lenience in FLOP calculations."`,
+		iterations: int `usage:"Run this many times."`,
+
+		// Note how the parser will transform this flag's name into `special-int`.
+		special_int: Distinct_Int `args:"indistinct" usage:"Able to set distinct types."`,
+
+		quat: quaternion256,
+
+		bits: bit_set[0..<8],
+
+		// Many different requirement styles:
+
+		// gadgets: [dynamic]string `args:"required=1" usage:"gadgets"`,
+		// widgets: [dynamic]string `args:"required=<3" usage:"widgets"`,
+		// foos: [dynamic]string `args:"required=2<4"`,
+		// bars: [dynamic]string `args:"required=3<4"`,
+		// bots: [dynamic]string `args:"required"`,
+
+		// (Maps) Only available in Odin style:
+
+		// assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`,
+
+		// (Variadic) Only available in UNIX style:
+
+		// bots: [dynamic]string `args:"variadic=2,required"`,
+
+		verbose: bool `usage:"Show verbose output."`,
+		debug: bool `args:"hidden" usage:"print debug info"`,
+
+		varg: [dynamic]string `usage:"Any extra arguments go here."`,
+	}
+
+	opt: Options
+	style : flags.Parsing_Style = .Odin
+
+	flags.register_type_setter(my_custom_type_setter)
+	flags.register_flag_checker(my_custom_flag_checker)
+	flags.parse_or_exit(&opt, os.args, style)
+
+	fmt.printfln("%#v", opt)
+
+	if opt.output != 0 {
+		os.write_string(opt.output, "Hellope!\n")
+	}
+}

+ 262 - 0
core/flags/internal_assignment.odin

@@ -0,0 +1,262 @@
+//+private
+package flags
+
+import "base:intrinsics"
+@require import "base:runtime"
+import "core:container/bit_array"
+@require import "core:fmt"
+@require import "core:mem"
+import "core:reflect"
+@require import "core:strconv"
+@require import "core:strings"
+
+// Push a positional argument onto a data struct, checking for specified
+// positionals first before adding it to a fallback field.
+@(optimization_mode="favor_size")
+push_positional :: #force_no_inline proc (model: ^$T, parser: ^Parser, arg: string) -> (error: Error) {
+	if bit_array.get(&parser.filled_pos, parser.filled_pos.max_index) {
+		// The max index is set, which means we're out of space.
+		// Add one free bit by setting the index above to false.
+		bit_array.set(&parser.filled_pos, 1 + parser.filled_pos.max_index, false)
+	}
+
+	pos: int = ---
+	{
+		iter := bit_array.make_iterator(&parser.filled_pos)
+		ok: bool
+		pos, ok = bit_array.iterate_by_unset(&iter)
+
+		// This may be an allocator error.
+		assert(ok, "Unable to find a free spot in the positional bit_array.")
+	}
+
+	field, index, has_pos_assigned := get_field_by_pos(model, pos)
+
+	if !has_pos_assigned {
+		when intrinsics.type_has_field(T, INTERNAL_VARIADIC_FLAG) {
+			// Add it to the fallback array.
+			field = reflect.struct_field_by_name(T, INTERNAL_VARIADIC_FLAG)
+		} else {
+			return Parse_Error {
+				.Extra_Positional,
+				fmt.tprintf("Got extra positional argument `%s` with nowhere to store it.", arg),
+			}
+		}
+	}
+
+	ptr := cast(rawptr)(cast(uintptr)model + field.offset)
+	args_tag, _ := reflect.struct_tag_lookup(field.tag, TAG_ARGS)
+	field_name := get_field_name(field)
+	error = parse_and_set_pointer_by_type(ptr, arg, field.type, args_tag)
+	#partial switch &specific_error in error {
+	case Parse_Error:
+		specific_error.message = fmt.tprintf("Unable to set positional #%i (%s) of type %v to `%s`.%s%s",
+			pos,
+			field_name,
+			field.type,
+			arg,
+			" " if len(specific_error.message) > 0 else "",
+			specific_error.message)
+	case nil:
+		bit_array.set(&parser.filled_pos, pos)
+		bit_array.set(&parser.fields_set, index)
+	}
+
+	return
+}
+
+register_field :: proc(parser: ^Parser, field: reflect.Struct_Field, index: int) {
+	if pos, ok := get_field_pos(field); ok {
+		bit_array.set(&parser.filled_pos, pos)
+	}
+
+	bit_array.set(&parser.fields_set, index)
+}
+
+// Set a `-flag` argument, Odin-style.
+@(optimization_mode="favor_size")
+set_odin_flag :: proc(model: ^$T, parser: ^Parser, name: string) -> (error: Error) {
+	// We make a special case for help requests.
+	switch name {
+	case RESERVED_HELP_FLAG, RESERVED_HELP_FLAG_SHORT:
+		return Help_Request{}
+	}
+
+	field, index := get_field_by_name(model, name) or_return
+
+	#partial switch specific_type_info in field.type.variant {
+	case runtime.Type_Info_Boolean:
+		ptr := cast(^bool)(cast(uintptr)model + field.offset)
+		ptr^ = true
+	case:
+		return Parse_Error {
+			.Bad_Value,
+			fmt.tprintf("Unable to set `%s` of type %v to true.", name, field.type),
+		}
+	}
+
+	register_field(parser, field, index)
+	return
+}
+
+// Set a `-flag` argument, UNIX-style.
+@(optimization_mode="favor_size")
+set_unix_flag :: proc(model: ^$T, parser: ^Parser, name: string) -> (future_args: int, error: Error) {
+	// We make a special case for help requests.
+	switch name {
+	case RESERVED_HELP_FLAG, RESERVED_HELP_FLAG_SHORT:
+		return 0, Help_Request{}
+	}
+
+	field, index := get_field_by_name(model, name) or_return
+
+	#partial switch specific_type_info in field.type.variant {
+	case runtime.Type_Info_Boolean:
+		ptr := cast(^bool)(cast(uintptr)model + field.offset)
+		ptr^ = true
+	case runtime.Type_Info_Dynamic_Array:
+		future_args = 1
+		if tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok {
+			if length, is_variadic := get_struct_subtag(tag, SUBTAG_VARIADIC); is_variadic {
+				// Variadic arrays may specify how many arguments they consume at once.
+				// Otherwise, they take everything that's left.
+				if value, value_ok := strconv.parse_u64_of_base(length, 10); value_ok {
+					future_args = cast(int)value
+				} else {
+					future_args = max(int)
+				}
+			}
+		}
+	case:
+		// `--flag`, waiting on its value.
+		future_args = 1
+	}
+
+	register_field(parser, field, index)
+	return
+}
+
+// Set a `-flag:option` argument.
+@(optimization_mode="favor_size")
+set_option :: proc(model: ^$T, parser: ^Parser, name, option: string) -> (error: Error) {
+	field, index := get_field_by_name(model, name) or_return
+
+	if len(option) == 0 {
+		return Parse_Error {
+			.No_Value,
+			fmt.tprintf("Setting `%s` to an empty value is meaningless.", name),
+		}
+	}
+
+	// Guard against incorrect syntax.
+	#partial switch specific_type_info in field.type.variant {
+	case runtime.Type_Info_Map:
+		return Parse_Error {
+			.No_Value,
+			fmt.tprintf("Unable to set `%s` of type %v to `%s`. Are you missing an `=`? The correct format is `map:key=value`.", name, field.type, option),
+		}
+	}
+
+	ptr := cast(rawptr)(cast(uintptr)model + field.offset)
+	args_tag := reflect.struct_tag_get(field.tag, TAG_ARGS)
+	error = parse_and_set_pointer_by_type(ptr, option, field.type, args_tag)
+	#partial switch &specific_error in error {
+	case Parse_Error:
+		specific_error.message = fmt.tprintf("Unable to set `%s` of type %v to `%s`.%s%s",
+			name,
+			field.type,
+			option,
+			" " if len(specific_error.message) > 0 else "",
+			specific_error.message)
+	case nil:
+		register_field(parser, field, index)
+	}
+
+	return
+}
+
+// Set a `-map:key=value` argument.
+@(optimization_mode="favor_size")
+set_key_value :: proc(model: ^$T, parser: ^Parser, name, key, value: string) -> (error: Error) {
+	field, index := get_field_by_name(model, name) or_return
+
+	#partial switch specific_type_info in field.type.variant {
+	case runtime.Type_Info_Map:
+		key := key
+		key_ptr := cast(rawptr)&key
+		key_cstr: cstring
+		if reflect.is_cstring(specific_type_info.key) {
+			// We clone the key here, because it's liable to be a slice of an
+			// Odin string, and we need to put a NUL terminator in it.
+			key_cstr = strings.clone_to_cstring(key)
+			key_ptr = &key_cstr
+		}
+		defer if key_cstr != nil {
+			delete(key_cstr)
+		}
+
+		raw_map := (^runtime.Raw_Map)(cast(uintptr)model + field.offset)
+
+		hash := specific_type_info.map_info.key_hasher(key_ptr, runtime.map_seed(raw_map^))
+
+		backing_alloc := false
+		elem_backing: []byte
+		value_ptr: rawptr
+
+		if raw_map.allocator.procedure == nil {
+			raw_map.allocator = context.allocator
+		} else {
+			value_ptr = runtime.__dynamic_map_get(raw_map,
+				specific_type_info.map_info,
+				hash,
+				key_ptr,
+			)
+		}
+
+		if value_ptr == nil {
+			alloc_error: runtime.Allocator_Error = ---
+			elem_backing, alloc_error = mem.alloc_bytes(specific_type_info.value.size, specific_type_info.value.align)
+			if elem_backing == nil {
+				return Parse_Error {
+					alloc_error,
+					"Failed to allocate element backing for map value.",
+				}
+			}
+
+			backing_alloc = true
+			value_ptr = raw_data(elem_backing)
+		}
+
+		args_tag, _ := reflect.struct_tag_lookup(field.tag, TAG_ARGS)
+		error = parse_and_set_pointer_by_type(value_ptr, value, specific_type_info.value, args_tag)
+		#partial switch &specific_error in error {
+		case Parse_Error:
+			specific_error.message = fmt.tprintf("Unable to set `%s` of type %v with key=value: `%s`=`%s`.%s%s",
+				name,
+				field.type,
+				key,
+				value,
+				" " if len(specific_error.message) > 0 else "",
+				specific_error.message)
+		}
+
+		if backing_alloc {
+			runtime.__dynamic_map_set(raw_map,
+				specific_type_info.map_info,
+				hash,
+				key_ptr,
+				value_ptr,
+			)
+
+			delete(elem_backing)
+		}
+
+		register_field(parser, field, index)
+		return
+	}
+
+	return Parse_Error {
+		.Bad_Value,
+		fmt.tprintf("Unable to set `%s` of type %v with key=value: `%s`=`%s`.", name, field.type, key, value),
+	}
+}

+ 170 - 0
core/flags/internal_parsing.odin

@@ -0,0 +1,170 @@
+//+private
+package flags
+
+import "core:container/bit_array"
+import "core:strconv"
+import "core:strings"
+
+// Used to group state together.
+Parser :: struct {
+	// `fields_set` tracks which arguments have been set.
+	// It uses their struct field index.
+	fields_set: bit_array.Bit_Array,
+
+	// `filled_pos` tracks which arguments have been filled into positional
+	// spots, much like how `fmt` treats them.
+	filled_pos: bit_array.Bit_Array,
+}
+
+parse_one_odin_arg :: proc(model: ^$T, parser: ^Parser, arg: string) -> (error: Error) {
+	arg := arg
+
+	if strings.has_prefix(arg, "-") {
+		arg = arg[1:]
+
+		flag: string
+		assignment_rune: rune
+		find_assignment: for r, i in arg {
+			switch r {
+			case ':', '=':
+				assignment_rune = r
+				flag = arg[:i]
+				arg = arg[1 + i:]
+				break find_assignment
+			case:
+				continue find_assignment
+			}
+		}
+
+		if assignment_rune == 0 {
+			if len(arg) == 0 {
+				return Parse_Error {
+					.No_Flag,
+					"No flag was given.",
+				}
+			}
+
+			// -flag
+			set_odin_flag(model, parser, arg) or_return
+
+		} else if assignment_rune == ':' {
+			// -flag:option <OR> -map:key=value
+			error = set_option(model, parser, flag, arg)
+
+			if error != nil {
+				// -flag:option did not work, so this may be a -map:key=value set.
+				find_equals: for r, i in arg {
+					if r == '=' {
+						key := arg[:i]
+						arg = arg[1 + i:]
+						error = set_key_value(model, parser, flag, key, arg)
+						break find_equals
+					}
+				}
+			}
+
+		} else {
+			// -flag=option, alternative syntax
+			set_option(model, parser, flag, arg) or_return
+		}
+
+	} else {
+		// positional
+		error = push_positional(model, parser, arg)
+	}
+
+	return
+}
+
+parse_one_unix_arg :: proc(model: ^$T, parser: ^Parser, arg: string) -> (
+	future_args: int,
+	current_flag: string,
+	error: Error,
+) {
+	arg := arg
+
+	if strings.has_prefix(arg, "-") {
+		// -flag
+		arg = arg[1:]
+
+		if strings.has_prefix(arg, "-") {
+			// Allow `--` to function as `-`.
+			arg = arg[1:]
+
+			if len(arg) == 0 {
+				// `--`, and only `--`.
+				// Everything from now on will be treated as an argument.
+				future_args = max(int)
+				current_flag = INTERNAL_VARIADIC_FLAG
+				return
+			}
+		}
+
+		flag: string
+		find_assignment: for r, i in arg {
+			if r == '=' {
+				// --flag=option
+				flag = arg[:i]
+				arg = arg[1 + i:]
+				error = set_option(model, parser, flag, arg)
+				return
+			}
+		}
+
+		// --flag option, potentially
+		future_args = set_unix_flag(model, parser, arg) or_return
+		current_flag = arg
+
+	} else {
+		// positional
+		error = push_positional(model, parser, arg)
+	}
+
+	return
+}
+
+// Parse a number of requirements specifier.
+//
+// Examples:
+//
+//    `min`
+//    `<max`
+//    `min<max`
+parse_requirements :: proc(str: string) -> (minimum, maximum: int, ok: bool) {
+	if len(str) == 0 {
+		return 1, max(int), true
+	}
+
+	if less_than := strings.index_byte(str, '<'); less_than != -1 {
+		if len(str) == 1 {
+			return 0, 0, false
+		}
+
+		#no_bounds_check left  := str[:less_than]
+		#no_bounds_check right := str[1 + less_than:]
+
+		if left_value, parse_ok := strconv.parse_u64_of_base(left, 10); parse_ok {
+			minimum = cast(int)left_value
+		} else if len(left) > 0 {
+			return 0, 0, false
+		}
+
+		if right_value, parse_ok := strconv.parse_u64_of_base(right, 10); parse_ok {
+			maximum = cast(int)right_value
+		} else if len(right) > 0 {
+			return 0, 0, false
+		} else {
+			maximum = max(int)
+		}
+	} else {
+		if value, parse_ok := strconv.parse_u64_of_base(str, 10); parse_ok {
+			minimum = cast(int)value
+			maximum = max(int)
+		} else {
+			return 0, 0, false
+		}
+	}
+
+	ok = true
+	return
+}

+ 529 - 0
core/flags/internal_rtti.odin

@@ -0,0 +1,529 @@
+//+private
+package flags
+
+import "base:intrinsics"
+import "base:runtime"
+import "core:fmt"
+import "core:mem"
+import "core:os"
+import "core:reflect"
+import "core:strconv"
+import "core:strings"
+@require import "core:time"
+@require import "core:time/datetime"
+import "core:unicode/utf8"
+
+@(optimization_mode="favor_size")
+parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: ^runtime.Type_Info) -> bool {
+	bounded_int :: proc(value, min, max: i128) -> (result: i128, ok: bool) {
+		return value, min <= value && value <= max
+	}
+
+	bounded_uint :: proc(value, max: u128) -> (result: u128, ok: bool) {
+		return value, value <= max
+	}
+
+	// NOTE(Feoramund): This procedure has been written with the goal in mind
+	// of generating the least amount of assembly, given that this library is
+	// likely to be called once and forgotten.
+	//
+	// I've rewritten the switch tables below in 3 different ways, and the
+	// current one generates the least amount of code for me on Linux AMD64.
+	//
+	// The other two ways were:
+	//
+	// - the original implementation: use of parametric polymorphism which led
+	//   to dozens of functions generated, one for each type.
+	//
+	// - a `value, ok` assignment statement with the `or_return` done at the
+	//   end of the switch, instead of inline.
+	//
+	// This seems to be the smallest way for now.
+
+	#partial switch specific_type_info in type_info.variant {
+	case runtime.Type_Info_Integer:
+		if specific_type_info.signed {
+			value := strconv.parse_i128(str) or_return
+			switch type_info.id {
+			case i8:     (^i8)    (ptr)^ = cast(i8)     bounded_int(value, cast(i128)min(i8),     cast(i128)max(i8)    ) or_return
+			case i16:    (^i16)   (ptr)^ = cast(i16)    bounded_int(value, cast(i128)min(i16),    cast(i128)max(i16)   ) or_return
+			case i32:    (^i32)   (ptr)^ = cast(i32)    bounded_int(value, cast(i128)min(i32),    cast(i128)max(i32)   ) or_return
+			case i64:    (^i64)   (ptr)^ = cast(i64)    bounded_int(value, cast(i128)min(i64),    cast(i128)max(i64)   ) or_return
+			case i128:   (^i128)  (ptr)^ = value
+
+			case int:    (^int)   (ptr)^ = cast(int)    bounded_int(value, cast(i128)min(int),    cast(i128)max(int)   ) or_return
+
+			case i16le:  (^i16le) (ptr)^ = cast(i16le)  bounded_int(value, cast(i128)min(i16le),  cast(i128)max(i16le) ) or_return
+			case i32le:  (^i32le) (ptr)^ = cast(i32le)  bounded_int(value, cast(i128)min(i32le),  cast(i128)max(i32le) ) or_return
+			case i64le:  (^i64le) (ptr)^ = cast(i64le)  bounded_int(value, cast(i128)min(i64le),  cast(i128)max(i64le) ) or_return
+			case i128le: (^i128le)(ptr)^ = cast(i128le) bounded_int(value, cast(i128)min(i128le), cast(i128)max(i128le)) or_return
+
+			case i16be:  (^i16be) (ptr)^ = cast(i16be)  bounded_int(value, cast(i128)min(i16be),  cast(i128)max(i16be) ) or_return
+			case i32be:  (^i32be) (ptr)^ = cast(i32be)  bounded_int(value, cast(i128)min(i32be),  cast(i128)max(i32be) ) or_return
+			case i64be:  (^i64be) (ptr)^ = cast(i64be)  bounded_int(value, cast(i128)min(i64be),  cast(i128)max(i64be) ) or_return
+			case i128be: (^i128be)(ptr)^ = cast(i128be) bounded_int(value, cast(i128)min(i128be), cast(i128)max(i128be)) or_return
+			}
+		} else {
+			value := strconv.parse_u128(str) or_return
+			switch type_info.id {
+			case u8:      (^u8)     (ptr)^ = cast(u8)      bounded_uint(value, cast(u128)max(u8)     ) or_return
+			case u16:     (^u16)    (ptr)^ = cast(u16)     bounded_uint(value, cast(u128)max(u16)    ) or_return
+			case u32:     (^u32)    (ptr)^ = cast(u32)     bounded_uint(value, cast(u128)max(u32)    ) or_return
+			case u64:     (^u64)    (ptr)^ = cast(u64)     bounded_uint(value, cast(u128)max(u64)    ) or_return
+			case u128:    (^u128)   (ptr)^ = value
+
+			case uint:    (^uint)   (ptr)^ = cast(uint)    bounded_uint(value, cast(u128)max(uint)   ) or_return
+			case uintptr: (^uintptr)(ptr)^ = cast(uintptr) bounded_uint(value, cast(u128)max(uintptr)) or_return
+
+			case u16le:   (^u16le)  (ptr)^ = cast(u16le)   bounded_uint(value, cast(u128)max(u16le)  ) or_return
+			case u32le:   (^u32le)  (ptr)^ = cast(u32le)   bounded_uint(value, cast(u128)max(u32le)  ) or_return
+			case u64le:   (^u64le)  (ptr)^ = cast(u64le)   bounded_uint(value, cast(u128)max(u64le)  ) or_return
+			case u128le:  (^u128le) (ptr)^ = cast(u128le)  bounded_uint(value, cast(u128)max(u128le) ) or_return
+
+			case u16be:   (^u16be)  (ptr)^ = cast(u16be)   bounded_uint(value, cast(u128)max(u16be)  ) or_return
+			case u32be:   (^u32be)  (ptr)^ = cast(u32be)   bounded_uint(value, cast(u128)max(u32be)  ) or_return
+			case u64be:   (^u64be)  (ptr)^ = cast(u64be)   bounded_uint(value, cast(u128)max(u64be)  ) or_return
+			case u128be:  (^u128be) (ptr)^ = cast(u128be)  bounded_uint(value, cast(u128)max(u128be) ) or_return
+			}
+		}
+
+	case runtime.Type_Info_Rune:
+		if utf8.rune_count_in_string(str) != 1 {
+			return false
+		}
+
+		(^rune)(ptr)^ = utf8.rune_at_pos(str, 0)
+
+	case runtime.Type_Info_Float:
+		value := strconv.parse_f64(str) or_return
+		switch type_info.id {
+		case f16:   (^f16)  (ptr)^ = cast(f16)   value
+		case f32:   (^f32)  (ptr)^ = cast(f32)   value
+		case f64:   (^f64)  (ptr)^ =             value
+
+		case f16le: (^f16le)(ptr)^ = cast(f16le) value
+		case f32le: (^f32le)(ptr)^ = cast(f32le) value
+		case f64le: (^f64le)(ptr)^ = cast(f64le) value
+
+		case f16be: (^f16be)(ptr)^ = cast(f16be) value
+		case f32be: (^f32be)(ptr)^ = cast(f32be) value
+		case f64be: (^f64be)(ptr)^ = cast(f64be) value
+		}
+	
+	case runtime.Type_Info_Complex:
+		value := strconv.parse_complex128(str) or_return
+		switch type_info.id {
+		case complex32:  (^complex32) (ptr)^ = (complex32)(value)
+		case complex64:  (^complex64) (ptr)^ = (complex64)(value)
+		case complex128: (^complex128)(ptr)^ = value
+		}
+	
+	case runtime.Type_Info_Quaternion:
+		value := strconv.parse_quaternion256(str) or_return
+		switch type_info.id {
+		case quaternion64:  (^quaternion64) (ptr)^ = (quaternion64)(value)
+		case quaternion128: (^quaternion128)(ptr)^ = (quaternion128)(value)
+		case quaternion256: (^quaternion256)(ptr)^ = value
+		}
+
+	case runtime.Type_Info_String:
+		if specific_type_info.is_cstring {
+			cstr_ptr := (^cstring)(ptr)
+			if cstr_ptr != nil {
+				// Prevent memory leaks from us setting this value multiple times.
+				delete(cstr_ptr^)
+			}
+			cstr_ptr^ = strings.clone_to_cstring(str)
+		} else {
+			(^string)(ptr)^ = str
+		}
+
+	case runtime.Type_Info_Boolean:
+		value := strconv.parse_bool(str) or_return
+		switch type_info.id {
+		case bool: (^bool)(ptr)^ =     value
+		case b8:   (^b8)  (ptr)^ =  b8(value)
+		case b16:  (^b16) (ptr)^ = b16(value)
+		case b32:  (^b32) (ptr)^ = b32(value)
+		case b64:  (^b64) (ptr)^ = b64(value)
+		}
+
+	case runtime.Type_Info_Bit_Set:
+		// Parse a string of 1's and 0's, from left to right,
+		// least significant bit to most significant bit.
+		value: u128
+
+		// NOTE: `upper` is inclusive, i.e: `0..=31`
+		max_bit_index := u128(1 + specific_type_info.upper - specific_type_info.lower)
+		bit_index := u128(0)
+		#no_bounds_check for string_index in 0..<uint(len(str)) {
+			if bit_index == max_bit_index {
+				// The string's too long for this bit_set.
+				return false
+			}
+
+			switch str[string_index] {
+			case '1':
+				value |= 1 << bit_index
+				bit_index += 1
+			case '0':
+				bit_index += 1
+				continue
+			case '_':
+				continue
+			case:
+				return false
+			}
+		}
+
+		if specific_type_info.underlying != nil {
+			set_unbounded_integer_by_type(ptr, value, specific_type_info.underlying.id)
+		} else {
+			switch 8*type_info.size {
+			case 8:   (^u8)  (ptr)^ = cast(u8)   value
+			case 16:  (^u16) (ptr)^ = cast(u16)  value
+			case 32:  (^u32) (ptr)^ = cast(u32)  value
+			case 64:  (^u64) (ptr)^ = cast(u64)  value
+			case 128: (^u128)(ptr)^ =            value
+			}
+		}
+
+	case:
+		fmt.panicf("Unsupported base data type: %v", specific_type_info)
+	}
+
+	return true
+}
+
+// This proc exists to make error handling easier, since everything in the base
+// type one above works on booleans. It's a simple parsing error if it's false.
+//
+// However, here we have to be more careful about how we handle errors,
+// especially with files.
+//
+// We want to provide as informative as an error as we can.
+@(optimization_mode="favor_size", disabled=NO_CORE_NAMED_TYPES)
+parse_and_set_pointer_by_named_type :: proc(ptr: rawptr, str: string, data_type: typeid, arg_tag: string, out_error: ^Error) {
+	// Core types currently supported:
+	//
+	// - os.Handle
+	// - time.Time
+	// - datetime.DateTime
+	// - net.Host_Or_Endpoint
+
+	GENERIC_RFC_3339_ERROR :: "Invalid RFC 3339 string. Try this format: `yyyy-mm-ddThh:mm:ssZ`, for example `2024-02-29T16:30:00Z`."
+
+	out_error^ = nil
+
+	if data_type == os.Handle {
+		// NOTE: `os` is hopefully available everywhere, even if it might panic on some calls.
+		wants_read := false
+		wants_write := false
+		mode: int
+
+		if file, ok := get_struct_subtag(arg_tag, SUBTAG_FILE); ok {
+			for i in 0..<len(file) {
+				#no_bounds_check switch file[i] {
+				case 'r': wants_read = true
+				case 'w': wants_write = true
+				case 'c': mode |= os.O_CREATE
+				case 'a': mode |= os.O_APPEND
+				case 't': mode |= os.O_TRUNC
+				}
+			}
+		}
+
+		// Sane default.
+		// owner/group/other: r--r--r--
+		perms: int = 0o444
+
+		if wants_read && wants_write {
+			mode |= os.O_RDWR
+			perms |= 0o200
+		} else if wants_write {
+			mode |= os.O_WRONLY
+			perms |= 0o200
+		} else {
+			mode |= os.O_RDONLY
+		}
+
+		if permstr, ok := get_struct_subtag(arg_tag, SUBTAG_PERMS); ok {
+			if value, parse_ok := strconv.parse_u64_of_base(permstr, 8); parse_ok {
+				perms = int(value)
+			}
+		}
+
+		handle, errno := os.open(str, mode, perms)
+		if errno != 0 {
+			// NOTE(Feoramund): os.Errno is system-dependent, and there's
+			// currently no good way to translate them all into strings.
+			//
+			// The upcoming `os2` package will hopefully solve this.
+			//
+			// We can at least provide the number for now, so the user can look
+			// it up.
+			out_error^ = Open_File_Error {
+				str,
+				errno,
+				mode,
+				perms,
+			}
+			return
+		}
+
+		(^os.Handle)(ptr)^ = handle
+		return
+	}
+
+	when IMPORTING_TIME {
+		if data_type == time.Time {
+			// NOTE: The leap second data is discarded.
+			res, consumed := time.rfc3339_to_time_utc(str)
+			if consumed == 0 {
+				// The RFC 3339 parsing facilities provide no indication as to what
+				// went wrong, so just treat it as a regular parsing error.
+				out_error^ = Parse_Error {
+					.Bad_Value,
+					GENERIC_RFC_3339_ERROR,
+				}
+				return
+			}
+
+			(^time.Time)(ptr)^ = res
+			return
+		} else if data_type == datetime.DateTime {
+			// NOTE: The UTC offset and leap second data are discarded.
+			res, _, _, consumed := time.rfc3339_to_components(str)
+			if consumed == 0 {
+				out_error^ = Parse_Error {
+					.Bad_Value,
+					GENERIC_RFC_3339_ERROR,
+				}
+				return
+			}
+
+			(^datetime.DateTime)(ptr)^ = res
+			return
+		}
+	}
+
+	when IMPORTING_NET {
+		if try_net_parse_workaround(data_type, str, ptr, out_error) {
+			return
+		}
+	}
+
+	out_error ^= Parse_Error {
+		// The caller will add more details.
+		.Unsupported_Type,
+		"",
+	}
+}
+
+@(optimization_mode="favor_size")
+set_unbounded_integer_by_type :: proc(ptr: rawptr, value: $T, data_type: typeid) where intrinsics.type_is_integer(T) {
+	switch data_type {
+	case i8:      (^i8)     (ptr)^ = cast(i8)      value
+	case i16:     (^i16)    (ptr)^ = cast(i16)     value
+	case i32:     (^i32)    (ptr)^ = cast(i32)     value
+	case i64:     (^i64)    (ptr)^ = cast(i64)     value
+	case i128:    (^i128)   (ptr)^ = cast(i128)    value
+
+	case int:     (^int)    (ptr)^ = cast(int)     value
+
+	case i16le:   (^i16le)  (ptr)^ = cast(i16le)   value
+	case i32le:   (^i32le)  (ptr)^ = cast(i32le)   value
+	case i64le:   (^i64le)  (ptr)^ = cast(i64le)   value
+	case i128le:  (^i128le) (ptr)^ = cast(i128le)  value
+
+	case i16be:   (^i16be)  (ptr)^ = cast(i16be)   value
+	case i32be:   (^i32be)  (ptr)^ = cast(i32be)   value
+	case i64be:   (^i64be)  (ptr)^ = cast(i64be)   value
+	case i128be:  (^i128be) (ptr)^ = cast(i128be)  value
+
+	case u8:      (^u8)     (ptr)^ = cast(u8)      value
+	case u16:     (^u16)    (ptr)^ = cast(u16)     value
+	case u32:     (^u32)    (ptr)^ = cast(u32)     value
+	case u64:     (^u64)    (ptr)^ = cast(u64)     value
+	case u128:    (^u128)   (ptr)^ = cast(u128)    value
+
+	case uint:    (^uint)   (ptr)^ = cast(uint)    value
+	case uintptr: (^uintptr)(ptr)^ = cast(uintptr) value
+
+	case u16le:   (^u16le)  (ptr)^ = cast(u16le)   value
+	case u32le:   (^u32le)  (ptr)^ = cast(u32le)   value
+	case u64le:   (^u64le)  (ptr)^ = cast(u64le)   value
+	case u128le:  (^u128le) (ptr)^ = cast(u128le)  value
+
+	case u16be:   (^u16be)  (ptr)^ = cast(u16be)   value
+	case u32be:   (^u32be)  (ptr)^ = cast(u32be)   value
+	case u64be:   (^u64be)  (ptr)^ = cast(u64be)   value
+	case u128be:  (^u128be) (ptr)^ = cast(u128be)  value
+
+	case rune:    (^rune)   (ptr)^ = cast(rune)    value
+
+	case:
+		fmt.panicf("Unsupported integer backing type: %v", data_type)
+	}
+}
+
+@(optimization_mode="favor_size")
+parse_and_set_pointer_by_type :: proc(ptr: rawptr, str: string, type_info: ^runtime.Type_Info, arg_tag: string) -> (error: Error) {
+	#partial switch specific_type_info in type_info.variant {
+	case runtime.Type_Info_Named:
+		if global_custom_type_setter != nil {
+			// The program gets to go first.
+			error_message, handled, alloc_error := global_custom_type_setter(ptr, type_info.id, str, arg_tag)
+
+			if alloc_error != nil {
+				// There was an allocation error. Bail out.
+				return Parse_Error {
+					alloc_error,
+					"Custom type setter encountered allocation error.",
+				}
+			}
+
+			if handled {
+				// The program handled the type.
+
+				if len(error_message) != 0 {
+					// However, there was an error. Pass it along.
+					error = Parse_Error {
+						.Bad_Value,
+						error_message,
+					}
+				}
+
+				return
+			}
+		}
+
+		// Might be a named enum. Need to check here first, since we handle all enums.
+		if enum_type_info, is_enum := specific_type_info.base.variant.(runtime.Type_Info_Enum); is_enum {
+			if value, ok := reflect.enum_from_name_any(type_info.id, str); ok {
+				set_unbounded_integer_by_type(ptr, value, enum_type_info.base.id)
+			} else {
+				return Parse_Error {
+					.Bad_Value,
+					fmt.tprintf("Invalid value name. Valid names are: %s", enum_type_info.names),
+				}
+			}
+		} else {
+			parse_and_set_pointer_by_named_type(ptr, str, type_info.id, arg_tag, &error)
+			
+			if error != nil {
+				// So far, it's none of the types that we recognize.
+				// Check to see if we can set it by base type, if allowed.
+				if _, is_indistinct := get_struct_subtag(arg_tag, SUBTAG_INDISTINCT); is_indistinct {
+					return parse_and_set_pointer_by_type(ptr, str, specific_type_info.base, arg_tag)
+				}
+			}
+		}
+
+	case runtime.Type_Info_Dynamic_Array:
+		ptr := cast(^runtime.Raw_Dynamic_Array)ptr
+
+		// Try to convert the value first.
+		elem_backing, alloc_error := mem.alloc_bytes(specific_type_info.elem.size, specific_type_info.elem.align)
+		if alloc_error != nil {
+			return Parse_Error {
+				alloc_error,
+				"Failed to allocate element backing for dynamic array.",
+			}
+		}
+		defer delete(elem_backing)
+		parse_and_set_pointer_by_type(raw_data(elem_backing), str, specific_type_info.elem, arg_tag) or_return
+
+		if !runtime.__dynamic_array_resize(ptr, specific_type_info.elem.size, specific_type_info.elem.align, ptr.len + 1) {
+			// NOTE: This is purely an assumption that it's OOM.
+			// Regardless, the resize failed.
+			return Parse_Error {
+				runtime.Allocator_Error.Out_Of_Memory,
+				"Failed to resize dynamic array.",
+			}
+		}
+
+		subptr := rawptr(
+			uintptr(ptr.data) +
+			uintptr((ptr.len - 1) * specific_type_info.elem.size))
+		mem.copy(subptr, raw_data(elem_backing), len(elem_backing))
+
+	case runtime.Type_Info_Enum:
+		// This is a nameless enum.
+		// The code here is virtually the same as above for named enums.
+		if value, ok := reflect.enum_from_name_any(type_info.id, str); ok {
+			set_unbounded_integer_by_type(ptr, value, specific_type_info.base.id)
+		} else {
+			return Parse_Error {
+				.Bad_Value,
+				fmt.tprintf("Invalid value name. Valid names are: %s", specific_type_info.names),
+			}
+		}
+
+	case:
+		if !parse_and_set_pointer_by_base_type(ptr, str, type_info) {
+			return Parse_Error {
+				// The caller will add more details.
+				.Bad_Value,
+				"",
+			}
+		}
+	}
+
+	return
+}
+
+get_struct_subtag :: get_subtag
+
+get_field_name :: proc(field: reflect.Struct_Field) -> string {
+	if args_tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok {
+		if name_subtag, name_ok := get_struct_subtag(args_tag, SUBTAG_NAME); name_ok {
+			return name_subtag
+		}
+	}
+
+	name, _ := strings.replace_all(field.name, "_", "-", context.temp_allocator)
+	return name
+}
+
+get_field_pos :: proc(field: reflect.Struct_Field) -> (int, bool) {
+	if args_tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok {
+		if pos_subtag, pos_ok := get_struct_subtag(args_tag, SUBTAG_POS); pos_ok {
+			if value, parse_ok := strconv.parse_u64_of_base(pos_subtag, 10); parse_ok {
+				return int(value), true
+			}
+		}
+	}
+
+	return 0, false
+}
+
+// Get a struct field by its field name or `name` subtag.
+get_field_by_name :: proc(model: ^$T, name: string) -> (result: reflect.Struct_Field, index: int, error: Error) {
+	for field, i in reflect.struct_fields_zipped(T) {
+		if get_field_name(field) == name {
+			return field, i, nil
+		}
+	}
+
+	error = Parse_Error {
+		.Missing_Flag,
+		fmt.tprintf("Unable to find any flag named `%s`.", name),
+	}
+	return
+}
+
+// Get a struct field by its `pos` subtag.
+get_field_by_pos :: proc(model: ^$T, pos: int) -> (result: reflect.Struct_Field, index: int, ok: bool) {
+	for field, i in reflect.struct_fields_zipped(T) {
+		args_tag := reflect.struct_tag_lookup(field.tag, TAG_ARGS) or_continue
+		pos_subtag := get_struct_subtag(args_tag, SUBTAG_POS)      or_continue
+
+		value, parse_ok := strconv.parse_u64_of_base(pos_subtag, 10)
+		if parse_ok && cast(int)value == pos {
+			return field, i, true
+		}
+	}
+
+	return
+}

+ 31 - 0
core/flags/internal_rtti_nonbsd.odin

@@ -0,0 +1,31 @@
+//+private
+//+build !freebsd !netbsd !openbsd
+package flags
+
+import "core:net"
+
+// This proc exists purely as a workaround for import restrictions.
+// Returns true if caller should return early.
+try_net_parse_workaround :: #force_inline proc (
+	data_type: typeid,
+	str: string,
+	ptr: rawptr,
+	out_error: ^Error,
+) -> bool {
+	if data_type == net.Host_Or_Endpoint {
+		addr, net_error := net.parse_hostname_or_endpoint(str)
+		if net_error != nil {
+			// We pass along `net.Error` here.
+			out_error^ = Parse_Error {
+				net_error,
+				"Invalid Host/Endpoint.",
+			}
+			return true
+		}
+
+		(cast(^net.Host_Or_Endpoint)ptr)^ = addr
+		return true
+	}
+
+	return false
+}

+ 244 - 0
core/flags/internal_validation.odin

@@ -0,0 +1,244 @@
+//+private
+package flags
+
+@require import "base:runtime"
+@require import "core:container/bit_array"
+@require import "core:fmt"
+@require import "core:mem"
+@require import "core:os"
+@require import "core:reflect"
+@require import "core:strconv"
+@require import "core:strings"
+
+// This proc is used to assert that `T` meets the expectations of the library.
+@(optimization_mode="favor_size", disabled=ODIN_DISABLE_ASSERT)
+validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_location) {
+	positionals_assigned_so_far: bit_array.Bit_Array
+	defer bit_array.destroy(&positionals_assigned_so_far)
+
+	check_fields: for field in reflect.struct_fields_zipped(T) {
+		if style == .Unix {
+			#partial switch specific_type_info in field.type.variant {
+			case runtime.Type_Info_Map:
+				fmt.panicf("%T.%s is a map type, and these are not supported in UNIX-style parsing mode.",
+					model_type, field.name, loc = loc)
+			}
+		}
+
+		name_is_safe := true
+		defer {
+			fmt.assertf(name_is_safe, "%T.%s is using a reserved name.",
+				model_type, field.name, loc = loc)
+		}
+
+		switch field.name {
+		case RESERVED_HELP_FLAG, RESERVED_HELP_FLAG_SHORT:
+			name_is_safe = false
+		}
+
+		args_tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS)
+		if !ok {
+			// If it has no args tag, then we've checked all we need to.
+			// Most of this proc is validating that the subtags are sane.
+			continue
+		}
+
+		if name, has_name := get_struct_subtag(args_tag, SUBTAG_NAME); has_name {
+			fmt.assertf(len(name) > 0, "%T.%s has a zero-length `%s`.",
+				model_type, field.name, SUBTAG_NAME, loc = loc)
+
+			fmt.assertf(strings.index(name, " ") == -1, "%T.%s has a `%s` with spaces in it.",
+				model_type, field.name, SUBTAG_NAME, loc = loc)
+
+			switch name {
+			case RESERVED_HELP_FLAG, RESERVED_HELP_FLAG_SHORT:
+				name_is_safe = false
+				continue check_fields
+			case:
+				name_is_safe = true
+			}
+		}
+
+		if pos_str, has_pos := get_struct_subtag(args_tag, SUBTAG_POS); has_pos {
+			#partial switch specific_type_info in field.type.variant {
+			case runtime.Type_Info_Map:
+				fmt.panicf("%T.%s has `%s` defined, and this does not make sense on a map type.",
+					model_type, field.name, SUBTAG_POS, loc = loc)
+			}
+
+			pos_value, pos_ok := strconv.parse_u64_of_base(pos_str, 10)
+			fmt.assertf(pos_ok, "%T.%s has `%s` defined as %q but cannot be parsed a base-10 integer >= 0.",
+				model_type, field.name, SUBTAG_POS, pos_str, loc = loc)
+			fmt.assertf(!bit_array.get(&positionals_assigned_so_far, pos_value), "%T.%s has `%s` set to #%i, but that position has already been assigned to another flag.",
+				model_type, field.name, SUBTAG_POS, pos_value, loc = loc)
+			bit_array.set(&positionals_assigned_so_far, pos_value)
+		}
+
+		required_min, required_max: int
+		if requirement, is_required := get_struct_subtag(args_tag, SUBTAG_REQUIRED); is_required {
+			fmt.assertf(!reflect.is_boolean(field.type), "%T.%s is a required boolean. This is disallowed.",
+				model_type, field.name, loc = loc)
+
+			fmt.assertf(field.name != INTERNAL_VARIADIC_FLAG, "%T.%s is defined as required. This is disallowed.",
+				model_type, field.name, loc = loc)
+
+			if len(requirement) > 0 {
+				if required_min, required_max, ok = parse_requirements(requirement); ok {
+					#partial switch specific_type_info in field.type.variant {
+					case runtime.Type_Info_Dynamic_Array:
+						fmt.assertf(required_min != required_max, "%T.%s has `%s` defined as %q, but the minimum and maximum are the same. Increase the maximum by 1 for an exact number of arguments: (%i<%i)",
+							model_type,
+							field.name,
+							SUBTAG_REQUIRED,
+							requirement,
+							required_min,
+							1 + required_max,
+							loc = loc)
+
+						fmt.assertf(required_min < required_max, "%T.%s has `%s` defined as %q, but the minimum and maximum are swapped.",
+							model_type, field.name, SUBTAG_REQUIRED, requirement, loc = loc)
+
+					case:
+						fmt.panicf("%T.%s has `%s` defined as %q, but ranges are only supported on dynamic arrays.",
+							model_type, field.name, SUBTAG_REQUIRED, requirement, loc = loc)
+					}
+				} else {
+					fmt.panicf("%T.%s has `%s` defined as %q, but it cannot be parsed as a valid range.",
+						model_type, field.name, SUBTAG_REQUIRED, requirement, loc = loc)
+				}
+			}
+		}
+
+		if length, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic {
+			if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok {
+				fmt.assertf(value > 0,
+					"%T.%s has `%s` set to %i. It must be greater than zero.",
+					model_type, field.name, value, SUBTAG_VARIADIC, loc = loc)
+				fmt.assertf(value != 1,
+					"%T.%s has `%s` set to 1. This has no effect.",
+					model_type, field.name, SUBTAG_VARIADIC, loc = loc)
+			}
+
+			#partial switch specific_type_info in field.type.variant {
+			case runtime.Type_Info_Dynamic_Array:
+				fmt.assertf(style != .Odin,
+					"%T.%s has `%s` defined, but this only makes sense in UNIX-style parsing mode.",
+					model_type, field.name, SUBTAG_VARIADIC, loc = loc)
+			case:
+				fmt.panicf("%T.%s has `%s` defined, but this only makes sense on dynamic arrays.",
+					model_type, field.name, SUBTAG_VARIADIC, loc = loc)
+			}
+		}
+
+		allowed_to_define_file_perms: bool = ---
+		#partial switch specific_type_info in field.type.variant {
+		case runtime.Type_Info_Map:
+			allowed_to_define_file_perms = specific_type_info.value.id == os.Handle
+		case runtime.Type_Info_Dynamic_Array:
+			allowed_to_define_file_perms = specific_type_info.elem.id == os.Handle
+		case:
+			allowed_to_define_file_perms = field.type.id == os.Handle
+		}
+
+		if _, has_file := get_struct_subtag(args_tag, SUBTAG_FILE); has_file {
+			fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `os.Handle` type.",
+				model_type, field.name, SUBTAG_FILE, loc = loc)
+		}
+
+		if _, has_perms := get_struct_subtag(args_tag, SUBTAG_PERMS); has_perms {
+			fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `os.Handle` type.",
+				model_type, field.name, SUBTAG_PERMS, loc = loc)
+		}
+
+		#partial switch specific_type_info in field.type.variant {
+		case runtime.Type_Info_Map:
+			fmt.assertf(reflect.is_string(specific_type_info.key), "%T.%s is defined as a map[%T]. Only string types are currently supported as map keys.",
+				model_type,
+				field.name,
+				specific_type_info.key)
+		}
+	}
+}
+
+// Validate that all the required arguments are set and that the set arguments
+// are up to the program's expectations.
+@(optimization_mode="favor_size")
+validate_arguments :: proc(model: ^$T, parser: ^Parser) -> Error {
+	check_fields: for field, index in reflect.struct_fields_zipped(T) {
+		was_set := bit_array.get(&parser.fields_set, index)
+
+		field_name := get_field_name(field)
+		args_tag := reflect.struct_tag_get(field.tag, TAG_ARGS)
+		requirement, is_required := get_struct_subtag(args_tag, SUBTAG_REQUIRED)
+
+		required_min, required_max: int
+		has_requirements: bool
+		if is_required {
+			required_min, required_max, has_requirements = parse_requirements(requirement)
+		}
+
+		if has_requirements && required_min == 0 {
+			// Allow `0<n` or `<n` to bypass the required condition.
+			is_required = false
+		}
+
+		if _, is_array := field.type.variant.(runtime.Type_Info_Dynamic_Array); is_array && has_requirements {
+			// If it's an array, make sure it meets the required number of arguments.
+			ptr := cast(^runtime.Raw_Dynamic_Array)(cast(uintptr)model + field.offset)
+			if required_min == required_max - 1 && ptr.len != required_min {
+				return Validation_Error {
+					fmt.tprintf("The flag `%s` had %i option%s set, but it requires exactly %i.",
+						field_name,
+						ptr.len,
+						"" if ptr.len == 1 else "s",
+						required_min),
+				}
+			} else if required_min > ptr.len || ptr.len >= required_max {
+				if required_max == max(int) {
+					return Validation_Error {
+						fmt.tprintf("The flag `%s` had %i option%s set, but it requires at least %i.",
+							field_name,
+							ptr.len,
+							"" if ptr.len == 1 else "s",
+							required_min),
+					}
+				} else {
+					return Validation_Error {
+						fmt.tprintf("The flag `%s` had %i option%s set, but it requires at least %i and at most %i.",
+							field_name,
+							ptr.len,
+							"" if ptr.len == 1 else "s",
+							required_min,
+							required_max - 1),
+					}
+				}
+			}
+		} else if !was_set {
+			if is_required {
+				return Validation_Error {
+					fmt.tprintf("The required flag `%s` was not set.", field_name),
+				}
+			}
+
+			// Not set, not required; moving on.
+			continue
+		}
+
+		// All default checks have passed. The program gets a look at it now.
+
+		if global_custom_flag_checker != nil {
+			ptr := cast(rawptr)(cast(uintptr)model + field.offset)
+			error := global_custom_flag_checker(model,
+				field.name,
+				mem.make_any(ptr, field.type.id),
+				args_tag)
+
+			if len(error) > 0 {
+				// The program reported an error message.
+				return Validation_Error { error }
+			}
+		}
+	}
+
+	return nil
+}

+ 101 - 0
core/flags/parsing.odin

@@ -0,0 +1,101 @@
+package flags
+
+@require import "core:container/bit_array"
+@require import "core:fmt"
+
+Parsing_Style :: enum {
+	// Odin-style: `-flag`, `-flag:option`, `-map:key=value`
+	Odin,
+	// UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument repeating-argument`
+	Unix,
+}
+
+/*
+Parse a slice of command-line arguments into an annotated struct.
+
+*Allocates Using Provided Allocator*
+
+By default, this proc will only allocate memory outside of its lifetime if it
+has to append to a dynamic array, set a map value, or set a cstring.
+
+The program is expected to free any allocations on `model` as a result of parsing.
+
+Inputs:
+- model: A pointer to an annotated struct with flag definitions.
+- args: A slice of strings, usually `os.args[1:]`.
+- style: The argument parsing style.
+- validate_args: If `true`, will ensure that all required arguments are set if no errors occurred.
+- strict: If `true`, will return on first error. Otherwise, parsing continues.
+- allocator: (default: context.allocator)
+- loc: The caller location for debugging purposes (default: #caller_location)
+
+Returns:
+- error: A union of errors; parsing, file open, a help request, or validation.
+*/
+@(optimization_mode="favor_size")
+parse :: proc(
+	model: ^$T,
+	args: []string,
+	style: Parsing_Style = .Odin,
+	validate_args: bool = true,
+	strict: bool = true,
+	allocator := context.allocator,
+	loc := #caller_location,
+) -> (error: Error) {
+	context.allocator = allocator
+	validate_structure(model^, style, loc)
+
+	parser: Parser
+	defer {
+		bit_array.destroy(&parser.filled_pos)
+		bit_array.destroy(&parser.fields_set)
+	}
+
+	switch style {
+	case .Odin:
+		for arg in args {
+			error = parse_one_odin_arg(model, &parser, arg)
+			if strict && error != nil {
+				return
+			}
+		}
+
+	case .Unix:
+		// Support for `-flag argument (repeating-argument ...)`
+		future_args: int
+		current_flag: string
+
+		for i := 0; i < len(args); i += 1 {
+			#no_bounds_check arg := args[i]
+			future_args, current_flag, error = parse_one_unix_arg(model, &parser, arg)
+			if strict && error != nil {
+				return
+			}
+
+			for starting_future_args := future_args; future_args > 0; future_args -= 1 {
+				i += 1
+				if i == len(args) {
+					if future_args == starting_future_args {
+						return Parse_Error {
+							.No_Value,
+							fmt.tprintf("Expected a value for `%s` but none was given.", current_flag),
+						}
+					}
+					break
+				}
+				#no_bounds_check arg = args[i]
+
+				error = set_option(model, &parser, current_flag, arg)
+				if strict && error != nil {
+					return
+				}
+			}
+		}
+	}
+
+	if error == nil && validate_args {
+		return validate_arguments(model, &parser)
+	}
+
+	return
+}

+ 43 - 0
core/flags/rtti.odin

@@ -0,0 +1,43 @@
+package flags
+
+import "base:runtime"
+
+/*
+Handle setting custom data types.
+
+Inputs:
+- data: A raw pointer to the field where the data will go.
+- data_type: Type information on the underlying field.
+- unparsed_value: The unparsed string that the flag is being set to.
+- args_tag: The `args` tag from the struct's field.
+
+Returns:
+- error: An error message, or an empty string if no error occurred.
+- handled: A boolean indicating if the setter handles this type.
+- alloc_error: If an allocation error occurred, return it here.
+*/
+Custom_Type_Setter :: #type proc(
+	data:           rawptr,
+	data_type:      typeid,
+	unparsed_value: string,
+	args_tag:       string,
+) -> (
+	error:       string,
+	handled:     bool,
+	alloc_error: runtime.Allocator_Error,
+)
+
+@(private)
+global_custom_type_setter: Custom_Type_Setter
+
+/*
+Set the global custom type setter.
+
+Note that only one can be active at a time.
+
+Inputs:
+- setter: The type setter. Pass `nil` to disable any previously set setter.
+*/
+register_type_setter :: proc(setter: Custom_Type_Setter) {
+	global_custom_type_setter = setter
+}

+ 293 - 0
core/flags/usage.odin

@@ -0,0 +1,293 @@
+package flags
+
+import "base:runtime"
+import "core:fmt"
+import "core:io"
+import "core:reflect"
+import "core:slice"
+import "core:strconv"
+import "core:strings"
+
+/*
+Write out the documentation for the command-line arguments to a stream.
+
+Inputs:
+- out: The stream to write to.
+- data_type: The typeid of the data structure to describe.
+- program: The name of the program, usually the first argument to `os.args`.
+- style: The argument parsing style, required to show flags in the proper style.
+*/
+@(optimization_mode="favor_size")
+write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", style: Parsing_Style = .Odin) {
+	// All flags get their tags parsed so they can be reasoned about later.
+	Flag :: struct {
+		name: string,
+		usage: string,
+		type_description: string,
+		full_length: int,
+		pos: int,
+		required_min, required_max: int,
+		is_positional: bool,
+		is_required: bool,
+		is_boolean: bool,
+		is_variadic: bool,
+		variadic_length: int,
+	}
+
+	//
+	// POSITIONAL+REQUIRED, POSITIONAL, REQUIRED, NON_REQUIRED+NON_POSITIONAL, ...
+	//
+	sort_flags :: proc(i, j: Flag) -> slice.Ordering {
+		// `varg` goes to the end.
+		if i.name == INTERNAL_VARIADIC_FLAG {
+			return .Greater
+		} else if j.name == INTERNAL_VARIADIC_FLAG {
+			return .Less
+		}
+
+		// Handle positionals.
+		if i.is_positional {
+			if j.is_positional {
+				return slice.cmp(i.pos, j.pos)
+			} else {
+				return .Less
+			}
+		} else {
+			if j.is_positional {
+				return .Greater
+			}
+		}
+
+		// Then required flags.
+		if i.is_required {
+			if !j.is_required {
+				return .Less
+			}
+		} else if j.is_required {
+			return .Greater
+		}
+
+		// Finally, sort by name.
+		return slice.cmp(i.name, j.name)
+	}
+
+	describe_array_requirements :: proc(flag: Flag) -> (spec: string) {
+		if flag.is_required {
+			if flag.required_min == flag.required_max - 1 {
+				spec = fmt.tprintf(", exactly %i", flag.required_min)
+			} else if flag.required_min > 0 && flag.required_max == max(int) {
+				spec = fmt.tprintf(", at least %i", flag.required_min)
+			} else if flag.required_min == 0 && flag.required_max > 1 {
+				spec = fmt.tprintf(", at most %i", flag.required_max - 1)
+			} else if flag.required_min > 0 && flag.required_max > 1 {
+				spec = fmt.tprintf(", between %i and %i", flag.required_min, flag.required_max - 1)
+			} else {
+				spec = ", required"
+			}
+		}
+		return
+	}
+
+	builder := strings.builder_make()
+	defer strings.builder_destroy(&builder)
+
+	flag_prefix, flag_assignment: string = ---, ---
+	switch style {
+	case .Odin: flag_prefix = "-";  flag_assignment = ":"
+	case .Unix: flag_prefix = "--"; flag_assignment = " "
+	}
+
+	visible_flags: [dynamic]Flag
+	defer delete(visible_flags)
+
+	longest_flag_length: int
+
+	for field in reflect.struct_fields_zipped(data_type) {
+		flag: Flag
+
+		if args_tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok {
+			if _, is_hidden := get_struct_subtag(args_tag, SUBTAG_HIDDEN); is_hidden {
+				// Hidden flags stay hidden.
+				continue
+			}
+			if pos_str, is_pos := get_struct_subtag(args_tag, SUBTAG_POS); is_pos {
+				flag.is_positional = true
+				if pos, parse_ok := strconv.parse_u64_of_base(pos_str, 10); parse_ok {
+					flag.pos = cast(int)pos
+				}
+			}
+			if requirement, is_required := get_struct_subtag(args_tag, SUBTAG_REQUIRED); is_required {
+				flag.is_required = true
+				flag.required_min, flag.required_max, _ = parse_requirements(requirement)
+			}
+			if length_str, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic {
+				flag.is_variadic = true
+				if length, parse_ok := strconv.parse_u64_of_base(length_str, 10); parse_ok {
+					flag.variadic_length = cast(int)length
+				}
+			}
+		}
+
+		flag.name = get_field_name(field)
+		flag.is_boolean = reflect.is_boolean(field.type)
+
+		if usage, ok := reflect.struct_tag_lookup(field.tag, TAG_USAGE); ok {
+			flag.usage = usage
+		} else {
+			flag.usage = UNDOCUMENTED_FLAG
+		}
+
+		#partial switch specific_type_info in field.type.variant {
+		case runtime.Type_Info_Map:
+			flag.type_description = fmt.tprintf("<%v>=<%v>%s",
+				specific_type_info.key.id,
+				specific_type_info.value.id,
+				", required" if flag.is_required else "")
+
+		case runtime.Type_Info_Dynamic_Array:
+			requirement_spec := describe_array_requirements(flag)
+
+			if flag.is_variadic || flag.name == INTERNAL_VARIADIC_FLAG {
+				if flag.variadic_length == 0 {
+					flag.type_description = fmt.tprintf("<%v, ...>%s",
+						specific_type_info.elem.id,
+						requirement_spec)
+				} else {
+					flag.type_description = fmt.tprintf("<%v, %i at once>%s",
+						specific_type_info.elem.id,
+						flag.variadic_length,
+						requirement_spec)
+				}
+			} else {
+				flag.type_description = fmt.tprintf("<%v>%s", specific_type_info.elem.id,
+					requirement_spec if len(requirement_spec) > 0 else ", multiple")
+			}
+
+		case:
+			if flag.is_boolean {
+				/*
+				if flag.is_required {
+					flag.type_description = ", required"
+				}
+				*/
+			} else {
+				flag.type_description = fmt.tprintf("<%v>%s",
+					field.type.id,
+					", required" if flag.is_required else "")
+			}
+		}
+
+		if flag.name == INTERNAL_VARIADIC_FLAG {
+			flag.full_length = len(flag.type_description)
+		} else if flag.is_boolean {
+			flag.full_length = len(flag_prefix) + len(flag.name) + len(flag.type_description)
+		} else {
+			flag.full_length = len(flag_prefix) + len(flag.name) + len(flag_assignment) + len(flag.type_description)
+		}
+
+		longest_flag_length = max(longest_flag_length, flag.full_length)
+
+		append(&visible_flags, flag)
+	}
+
+	slice.sort_by_cmp(visible_flags[:], sort_flags)
+
+	// All the flags have been figured out now.
+
+	if len(program) > 0 {
+		keep_it_short := len(visible_flags) >= ONE_LINE_FLAG_CUTOFF_COUNT
+
+		strings.write_string(&builder, "Usage:\n\t")
+		strings.write_string(&builder, program)
+
+		for flag in visible_flags {
+			if keep_it_short && !(flag.is_required || flag.is_positional || flag.name == INTERNAL_VARIADIC_FLAG) {
+				continue
+			}
+
+			strings.write_byte(&builder, ' ')
+
+			if flag.name == INTERNAL_VARIADIC_FLAG {
+				strings.write_string(&builder, "...")
+				continue
+			}
+
+			if !flag.is_required { strings.write_byte(&builder, '[') }
+			if !flag.is_positional { strings.write_string(&builder, flag_prefix) }
+			strings.write_string(&builder, flag.name)
+			if !flag.is_required { strings.write_byte(&builder, ']') }
+		}
+
+		strings.write_byte(&builder, '\n')
+	}
+
+	if len(visible_flags) == 0 {
+		// No visible flags. An unusual situation, but prevent any extra work.
+		fmt.wprint(out, strings.to_string(builder))
+		return
+	}
+
+	strings.write_string(&builder, "Flags:\n")
+	
+	// Divide the positional/required arguments and the non-required arguments.
+	divider_index := -1
+	for flag, i in visible_flags {
+		if !flag.is_positional && !flag.is_required {
+			divider_index = i
+			break
+		}
+	}
+	if divider_index == 0 {
+		divider_index = -1
+	}
+
+	for flag, i in visible_flags {
+		if i == divider_index {
+			SPACING :: 2 // Number of spaces before the '|' from below.
+			strings.write_byte(&builder, '\t')
+			spacing := strings.repeat(" ", SPACING + longest_flag_length, context.temp_allocator)
+			strings.write_string(&builder, spacing)
+			strings.write_string(&builder, "|\n")
+		}
+
+		strings.write_byte(&builder, '\t')
+
+		if flag.name == INTERNAL_VARIADIC_FLAG {
+			strings.write_string(&builder, flag.type_description)
+		} else {
+			strings.write_string(&builder, flag_prefix)
+			strings.write_string(&builder, flag.name)
+			if !flag.is_boolean {
+				strings.write_string(&builder, flag_assignment)
+			}
+			strings.write_string(&builder, flag.type_description)
+		}
+
+		if strings.contains_rune(flag.usage, '\n') {
+			// Multi-line usage documentation. Let's make it look nice.
+			usage_builder := strings.builder_make(context.temp_allocator)
+
+			strings.write_byte(&usage_builder, '\n')
+			iter := strings.trim_space(flag.usage)
+			for line in strings.split_lines_iterator(&iter) {
+				strings.write_string(&usage_builder, "\t\t")
+				strings.write_string(&usage_builder, strings.trim_left_space(line))
+				strings.write_byte(&usage_builder, '\n')
+			}
+
+			strings.write_string(&builder, strings.to_string(usage_builder))
+		} else {
+			// Single-line usage documentation.
+			spacing := strings.repeat(" ",
+				(longest_flag_length) - flag.full_length,
+				context.temp_allocator)
+
+			strings.write_string(&builder, spacing)
+			strings.write_string(&builder, "  | ")
+			strings.write_string(&builder, flag.usage)
+			strings.write_byte(&builder, '\n')
+		}
+	}
+
+	fmt.wprint(out, strings.to_string(builder))
+}

+ 130 - 0
core/flags/util.odin

@@ -0,0 +1,130 @@
+package flags
+
+import "core:fmt"
+@require import "core:os"
+@require import "core:path/filepath"
+import "core:strings"
+
+/*
+Parse any arguments into an annotated struct or exit if there was an error.
+
+*Allocates Using Provided Allocator*
+
+This is a convenience wrapper over `parse` and `print_errors`.
+
+Inputs:
+- model: A pointer to an annotated struct.
+- program_args: A slice of strings, usually `os.args`.
+- style: The argument parsing style.
+- allocator: (default: context.allocator)
+- loc: The caller location for debugging purposes (default: #caller_location)
+*/
+@(optimization_mode="favor_size")
+parse_or_exit :: proc(
+	model: ^$T,
+	program_args: []string,
+	style: Parsing_Style = .Odin,
+	allocator := context.allocator,
+	loc := #caller_location,
+) {
+	assert(len(program_args) > 0, "Program arguments slice is empty.", loc)
+
+	program := filepath.base(program_args[0])
+	args: []string
+
+	if len(program_args) > 1 {
+		args = program_args[1:]
+	}
+
+	error := parse(model, args, style)
+	if error != nil {
+		stderr := os.stream_from_handle(os.stderr)
+
+		if len(args) == 0 {
+			// No arguments entered, and there was an error; show the usage,
+			// specifically on STDERR.
+			write_usage(stderr, T, program, style)
+			fmt.wprintln(stderr)
+		}
+
+		print_errors(T, error, program, style)
+
+		_, was_help_request := error.(Help_Request)
+		os.exit(0 if was_help_request else 1)
+	}
+}
+/*
+Print out any errors that may have resulted from parsing.
+
+All error messages print to STDERR, while usage goes to STDOUT, if requested.
+
+Inputs:
+- data_type: The typeid of the data structure to describe, if usage is requested.
+- error: The error returned from `parse`.
+- style: The argument parsing style, required to show flags in the proper style, when usage is shown.
+*/
+@(optimization_mode="favor_size")
+print_errors :: proc(data_type: typeid, error: Error, program: string, style: Parsing_Style = .Odin) {
+	stderr := os.stream_from_handle(os.stderr)
+	stdout := os.stream_from_handle(os.stdout)
+
+	switch specific_error in error {
+	case Parse_Error:
+		fmt.wprintfln(stderr, "[%T.%v] %s", specific_error, specific_error.reason, specific_error.message)
+	case Open_File_Error:
+		fmt.wprintfln(stderr, "[%T#%i] Unable to open file with perms 0o%o in mode 0x%x: %s",
+			specific_error,
+			specific_error.errno,
+			specific_error.perms,
+			specific_error.mode,
+			specific_error.filename)
+	case Validation_Error:
+		fmt.wprintfln(stderr, "[%T] %s", specific_error, specific_error.message)
+	case Help_Request:
+		write_usage(stdout, data_type, program, style)
+	}
+}
+/*
+Get the value for a subtag.
+
+This is useful if you need to parse through the `args` tag for a struct field
+on a custom type setter or custom flag checker.
+
+Example:
+
+	import "core:flags"
+	import "core:fmt"
+
+	subtag_example :: proc() {
+		args_tag := "precision=3,signed"
+
+		precision, has_precision := flags.get_subtag(args_tag, "precision")
+		signed, is_signed := flags.get_subtag(args_tag, "signed")
+
+		fmt.printfln("precision = %q, %t", precision, has_precision)
+		fmt.printfln("signed = %q, %t", signed, is_signed)
+	}
+
+Output:
+
+	precision = "3", true
+	signed = "", true
+
+*/
+get_subtag :: proc(tag, id: string) -> (value: string, ok: bool) {
+	// This proc was initially private in `internal_rtti.odin`, but given how
+	// useful it would be to custom type setters and flag checkers, it lives
+	// here now.
+
+	tag := tag
+
+	for subtag in strings.split_iterator(&tag, ",") {
+		if equals := strings.index_byte(subtag, '='); equals != -1 && id == subtag[:equals] {
+			return subtag[1 + equals:], true
+		} else if id == subtag {
+			return "", true
+		}
+	}
+
+	return
+}

+ 37 - 0
core/flags/validation.odin

@@ -0,0 +1,37 @@
+package flags
+
+/*
+Check a flag after parsing, during the validation stage.
+
+Inputs:
+- model: A raw pointer to the data structure provided to `parse`.
+- name: The name of the flag being checked.
+- value: An `any` type that contains the value to be checked.
+- args_tag: The `args` tag from within the struct.
+
+Returns:
+- error: An error message, or an empty string if no error occurred.
+*/
+Custom_Flag_Checker :: #type proc(
+	model:    rawptr,
+	name:     string,
+	value:    any,
+	args_tag: string,
+) -> (
+	error: string,
+)
+
+@(private)
+global_custom_flag_checker: Custom_Flag_Checker
+
+/*
+Set the global custom flag checker.
+
+Note that only one can be active at a time.
+
+Inputs:
+- checker: The flag checker. Pass `nil` to disable any previously set checker.
+*/
+register_flag_checker :: proc(checker: Custom_Flag_Checker) {
+	global_custom_flag_checker = checker
+}

+ 46 - 24
core/fmt/fmt.odin

@@ -92,7 +92,7 @@ _user_formatters: ^map[typeid]User_Formatter
 //
 //
 set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
 set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
 	assert(_user_formatters == nil, "set_user_formatters must not be called more than once.")
 	assert(_user_formatters == nil, "set_user_formatters must not be called more than once.")
-    _user_formatters = m
+	_user_formatters = m
 }
 }
 // Registers a user-defined formatter for a specific typeid
 // Registers a user-defined formatter for a specific typeid
 //
 //
@@ -368,6 +368,25 @@ caprintf :: proc(format: string, args: ..any, newline := false) -> cstring {
 caprintfln :: proc(format: string, args: ..any) -> cstring {
 caprintfln :: proc(format: string, args: ..any) -> cstring {
 	return caprintf(format, ..args, newline=true)
 	return caprintf(format, ..args, newline=true)
 }
 }
+// 	Creates a formatted C string
+//
+// 	*Allocates Using Context's Temporary Allocator*
+//
+// 	Inputs:
+// 	- args: A variadic list of arguments to be formatted.
+// 	- sep: An optional separator string (default is a single space).
+//
+// 	Returns: A formatted C string.
+//
+@(require_results)
+ctprint :: proc(args: ..any, sep := " ") -> cstring {
+	str: strings.Builder
+	strings.builder_init(&str, context.temp_allocator)
+	sbprint(&str, ..args, sep=sep)
+	strings.write_byte(&str, 0)
+	s := strings.to_string(str)
+	return cstring(raw_data(s))
+}
 // Creates a formatted C string
 // Creates a formatted C string
 //
 //
 // *Allocates Using Context's Temporary Allocator*
 // *Allocates Using Context's Temporary Allocator*
@@ -932,10 +951,10 @@ fmt_bad_verb :: proc(fi: ^Info, verb: rune) {
 	io.write_string(fi.writer, "%!", &fi.n)
 	io.write_string(fi.writer, "%!", &fi.n)
 	io.write_rune(fi.writer, verb, &fi.n)
 	io.write_rune(fi.writer, verb, &fi.n)
 	io.write_byte(fi.writer, '(', &fi.n)
 	io.write_byte(fi.writer, '(', &fi.n)
-	if fi.arg.id != nil {
-		reflect.write_typeid(fi.writer, fi.arg.id, &fi.n)
+	if arg := fi.arg; arg != nil {
+		reflect.write_typeid(fi.writer, arg.id, &fi.n)
 		io.write_byte(fi.writer, '=', &fi.n)
 		io.write_byte(fi.writer, '=', &fi.n)
-		fmt_value(fi, fi.arg, 'v')
+		fmt_value(fi, arg, 'v')
 	} else {
 	} else {
 		io.write_string(fi.writer, "<nil>", &fi.n)
 		io.write_string(fi.writer, "<nil>", &fi.n)
 	}
 	}
@@ -1053,8 +1072,8 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d
 	}
 	}
 
 
 	flags: strconv.Int_Flags
 	flags: strconv.Int_Flags
-	if fi.hash && !fi.zero && start == 0 { flags |= {.Prefix} }
-	if fi.plus               { flags |= {.Plus}   }
+	if fi.hash && !fi.zero && start == 0 { flags += {.Prefix} }
+	if fi.plus                           { flags += {.Plus}   }
 	s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags)
 	s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags)
 	prev_zero := fi.zero
 	prev_zero := fi.zero
 	defer fi.zero = prev_zero
 	defer fi.zero = prev_zero
@@ -1138,8 +1157,8 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i
 	}
 	}
 
 
 	flags: strconv.Int_Flags
 	flags: strconv.Int_Flags
-	if fi.hash && !fi.zero && start == 0 { flags |= {.Prefix} }
-	if fi.plus                           { flags |= {.Plus}   }
+	if fi.hash && !fi.zero && start == 0 { flags += {.Prefix} }
+	if fi.plus                           { flags += {.Plus}   }
 	s := strconv.append_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags)
 	s := strconv.append_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags)
 
 
 	if fi.hash && fi.zero && fi.indent == 0 {
 	if fi.hash && fi.zero && fi.indent == 0 {
@@ -1210,10 +1229,10 @@ _fmt_memory :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, units: st
 	// Add the unit at the end.
 	// Add the unit at the end.
 	copy(buf[len(str):], units[off:off+unit_len])
 	copy(buf[len(str):], units[off:off+unit_len])
 	str = string(buf[:len(str)+unit_len])
 	str = string(buf[:len(str)+unit_len])
-	 
-	 if !fi.plus {
-	 	// Strip sign from "+<value>" but not "+Inf".
-	 	if str[0] == '+' && str[1] != 'I' {
+
+	if !fi.plus {
+		// Strip sign from "+<value>" but not "+Inf".
+		if str[0] == '+' && str[1] != 'I' {
 			str = str[1:] 
 			str = str[1:] 
 		}
 		}
 	}
 	}
@@ -1441,13 +1460,10 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
 				if !fi.minus {
 				if !fi.minus {
 					io.write_string(fi.writer, s, &fi.n)
 					io.write_string(fi.writer, s, &fi.n)
 				}
 				}
-			}
-			else {
+			} else {
 				io.write_string(fi.writer, s, &fi.n)
 				io.write_string(fi.writer, s, &fi.n)
 			}
 			}
-		}
-		else
-		{
+		} else {
 			io.write_string(fi.writer, s, &fi.n)
 			io.write_string(fi.writer, s, &fi.n)
 		}
 		}
 
 
@@ -1749,7 +1765,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
 
 
 			if is_enum {
 			if is_enum {
 				enum_name: string
 				enum_name: string
-			 	if ti_named, is_named := info.elem.variant.(runtime.Type_Info_Named); is_named {
+				if ti_named, is_named := info.elem.variant.(runtime.Type_Info_Named); is_named {
 					enum_name = ti_named.name
 					enum_name = ti_named.name
 				}
 				}
 				for ev, evi in e.values {
 				for ev, evi in e.values {
@@ -1973,11 +1989,13 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 	// fi.hash = false;
 	// fi.hash = false;
 	fi.indent += 1
 	fi.indent += 1
 
 
-	if !is_soa && hash {
+	is_empty := len(info.names) == 0
+
+	if !is_soa && hash && !is_empty {
 		io.write_byte(fi.writer, '\n', &fi.n)
 		io.write_byte(fi.writer, '\n', &fi.n)
 	}
 	}
 	defer {
 	defer {
-		if hash {
+		if !is_soa && hash && !is_empty {
 			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
 			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
 		}
 		}
 		io.write_byte(fi.writer, ']' if is_soa && the_verb == 'v' else '}', &fi.n)
 		io.write_byte(fi.writer, ']' if is_soa && the_verb == 'v' else '}', &fi.n)
@@ -2025,9 +2043,9 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 			}
 			}
 			io.write_string(fi.writer, base_type_name, &fi.n)
 			io.write_string(fi.writer, base_type_name, &fi.n)
 			io.write_byte(fi.writer, '{', &fi.n)
 			io.write_byte(fi.writer, '{', &fi.n)
-			if hash { io.write_byte(fi.writer, '\n', &fi.n) }
+			if hash && !is_empty { io.write_byte(fi.writer, '\n', &fi.n) }
 			defer {
 			defer {
-				if hash {
+				if hash && !is_empty {
 					fi.indent -= 1
 					fi.indent -= 1
 					fmt_write_indent(fi)
 					fmt_write_indent(fi)
 					fi.indent += 1
 					fi.indent += 1
@@ -2075,6 +2093,10 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 				if hash { io.write_string(fi.writer, ",\n", &fi.n) }
 				if hash { io.write_string(fi.writer, ",\n", &fi.n) }
 			}
 			}
 		}
 		}
+
+		if hash && n > 0 {
+			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
+		}
 	} else {
 	} else {
 		field_count := -1
 		field_count := -1
 		for name, i in info.names {
 		for name, i in info.names {
@@ -2687,7 +2709,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 							return
 							return
 						}
 						}
 						if fi.indirection_level < 1 {
 						if fi.indirection_level < 1 {
-						  	fi.indirection_level += 1
+							fi.indirection_level += 1
 							defer fi.indirection_level -= 1
 							defer fi.indirection_level -= 1
 							io.write_byte(fi.writer, '&')
 							io.write_byte(fi.writer, '&')
 							fmt_value(fi, a, verb)
 							fmt_value(fi, a, verb)
@@ -2756,7 +2778,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 				     runtime.Type_Info_Dynamic_Array,
 				     runtime.Type_Info_Dynamic_Array,
 				     runtime.Type_Info_Map:
 				     runtime.Type_Info_Map:
 					if fi.indirection_level < 1 {
 					if fi.indirection_level < 1 {
-					  	fi.indirection_level += 1
+						fi.indirection_level += 1
 						defer fi.indirection_level -= 1
 						defer fi.indirection_level -= 1
 						io.write_byte(fi.writer, '&', &fi.n)
 						io.write_byte(fi.writer, '&', &fi.n)
 						fmt_value(fi, a, verb)
 						fmt_value(fi, a, verb)

+ 4 - 4
core/hash/crc.odin

@@ -1,6 +1,6 @@
 package hash
 package hash
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc64_ecma_182 :: proc "contextless" (data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check {
 crc64_ecma_182 :: proc "contextless" (data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check {
 	result = seed
 	result = seed
 	#no_bounds_check for b in data {
 	#no_bounds_check for b in data {
@@ -14,7 +14,7 @@ crc64_ecma_182 :: proc "contextless" (data: []byte, seed := u64(0)) -> (result:
 	bit-reversed, with one's complement pre and post processing.
 	bit-reversed, with one's complement pre and post processing.
 	Based on Mark Adler's v1.4 implementation in C under the ZLIB license.
 	Based on Mark Adler's v1.4 implementation in C under the ZLIB license.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc64_xz :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check {
 crc64_xz :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check {
 	data := data
 	data := data
 	result := ~u64le(seed)
 	result := ~u64le(seed)
@@ -52,7 +52,7 @@ crc64_xz :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_
 /*
 /*
 	Generator polynomial: x^64 + x^4 + x^3 + x + 1
 	Generator polynomial: x^64 + x^4 + x^3 + x + 1
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc64_iso_3306 :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check {
 crc64_iso_3306 :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check {
 
 
 	result := seed
 	result := seed
@@ -738,4 +738,4 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u
 	0x9fc0, 0x9e70, 0x9ca0, 0x9d10, 
 	0x9fc0, 0x9e70, 0x9ca0, 0x9d10, 
 	0x9480, 0x9530, 0x97e0, 0x9650, 
 	0x9480, 0x9530, 0x97e0, 0x9650, 
 	0x9240, 0x93f0, 0x9120, 0x9090,
 	0x9240, 0x93f0, 0x9120, 0x9090,
-}
+}

+ 1 - 1
core/hash/crc32.odin

@@ -2,7 +2,7 @@ package hash
 
 
 import "base:intrinsics"
 import "base:intrinsics"
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
 crc32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
 	crc := ~seed
 	crc := ~seed
 	buffer := raw_data(data)
 	buffer := raw_data(data)

+ 11 - 11
core/hash/hash.odin

@@ -3,7 +3,7 @@ package hash
 import "core:mem"
 import "core:mem"
 import "base:intrinsics"
 import "base:intrinsics"
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 adler32 :: proc "contextless" (data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
 adler32 :: proc "contextless" (data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
 
 
 	ADLER_CONST :: 65521
 	ADLER_CONST :: 65521
@@ -46,7 +46,7 @@ adler32 :: proc "contextless" (data: []byte, seed := u32(1)) -> u32 #no_bounds_c
 	return (u32(b) << 16) | u32(a)
 	return (u32(b) << 16) | u32(a)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 djb2 :: proc "contextless" (data: []byte, seed := u32(5381)) -> u32 {
 djb2 :: proc "contextless" (data: []byte, seed := u32(5381)) -> u32 {
 	hash: u32 = seed
 	hash: u32 = seed
 	for b in data {
 	for b in data {
@@ -73,7 +73,7 @@ djbx33a :: proc "contextless" (data: []byte, seed := u32(5381)) -> (result: [16]
 }
 }
 
 
 // If you have a choice, prefer fnv32a
 // If you have a choice, prefer fnv32a
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv32_no_a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 fnv32_no_a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	h: u32 = seed
 	h: u32 = seed
 	for b in data {
 	for b in data {
@@ -86,7 +86,7 @@ fnv32 :: fnv32_no_a // NOTE(bill): Not a fan of these aliases but seems necessar
 fnv64 :: fnv64_no_a // NOTE(bill): Not a fan of these aliases but seems necessary
 fnv64 :: fnv64_no_a // NOTE(bill): Not a fan of these aliases but seems necessary
 
 
 // If you have a choice, prefer fnv64a
 // If you have a choice, prefer fnv64a
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv64_no_a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
 fnv64_no_a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
 	h: u64 = seed
 	h: u64 = seed
 	for b in data {
 	for b in data {
@@ -94,7 +94,7 @@ fnv64_no_a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325))
 	}
 	}
 	return h
 	return h
 }
 }
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv32a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 fnv32a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	h: u32 = seed
 	h: u32 = seed
 	for b in data {
 	for b in data {
@@ -103,7 +103,7 @@ fnv32a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	return h
 	return h
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv64a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
 fnv64a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
 	h: u64 = seed
 	h: u64 = seed
 	for b in data {
 	for b in data {
@@ -112,7 +112,7 @@ fnv64a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) ->
 	return h
 	return h
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	hash: u32 = seed
 	hash: u32 = seed
 	for b in data {
 	for b in data {
@@ -126,7 +126,7 @@ jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	return hash
 	return hash
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	c1_32: u32 : 0xcc9e2d51
 	c1_32: u32 : 0xcc9e2d51
 	c2_32: u32 : 0x1b873593
 	c2_32: u32 : 0x1b873593
@@ -177,7 +177,7 @@ murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 }
 }
 
 
 // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L96
 // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L96
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur64a :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 murmur64a :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	m :: 0xc6a4a7935bd1e995
 	m :: 0xc6a4a7935bd1e995
 	r :: 47
 	r :: 47
@@ -218,7 +218,7 @@ murmur64a :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 }
 }
 
 
 // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L140
 // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L140
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur64b :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 murmur64b :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	m :: 0x5bd1e995
 	m :: 0x5bd1e995
 	r :: 24
 	r :: 24
@@ -286,7 +286,7 @@ murmur64b :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	return u64(h1)<<32 | u64(h2)
 	return u64(h1)<<32 | u64(h2)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 sdbm :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 sdbm :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	hash: u32 = seed
 	hash: u32 = seed
 	for b in data {
 	for b in data {

+ 5 - 5
core/hash/xxhash/common.odin

@@ -67,17 +67,17 @@ when !XXH_DISABLE_PREFETCH {
 }
 }
 
 
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_rotl32 :: #force_inline proc(x, r: u32) -> (res: u32) {
 XXH_rotl32 :: #force_inline proc(x, r: u32) -> (res: u32) {
 	return ((x << r) | (x >> (32 - r)))
 	return ((x << r) | (x >> (32 - r)))
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_rotl64 :: #force_inline proc(x, r: u64) -> (res: u64) {
 XXH_rotl64 :: #force_inline proc(x, r: u64) -> (res: u64) {
 	return ((x << r) | (x >> (64 - r)))
 	return ((x << r) | (x >> (64 - r)))
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_read32 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned) -> (res: u32) {
 XXH32_read32 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned) -> (res: u32) {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 		#no_bounds_check b := (^u32le)(&buf[0])^
 		#no_bounds_check b := (^u32le)(&buf[0])^
@@ -89,7 +89,7 @@ XXH32_read32 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned)
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH64_read64 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned) -> (res: u64) {
 XXH64_read64 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned) -> (res: u64) {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 		#no_bounds_check b := (^u64le)(&buf[0])^
 		#no_bounds_check b := (^u64le)(&buf[0])^
@@ -99,4 +99,4 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned)
 		mem_copy(&b, raw_data(buf[:]), 8)
 		mem_copy(&b, raw_data(buf[:]), 8)
 		return u64(b)
 		return u64(b)
 	}
 	}
-}
+}

+ 56 - 55
core/hash/xxhash/xxhash_3.odin

@@ -111,13 +111,13 @@ XXH128_canonical :: struct {
 	@param lhs, rhs The 64-bit integers to multiply
 	@param lhs, rhs The 64-bit integers to multiply
 	@return The low 64 bits of the product XOR'd by the high 64 bits.
 	@return The low 64 bits of the product XOR'd by the high 64 bits.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_mul_64_to_128_fold_64 :: #force_inline proc(lhs, rhs: xxh_u64) -> (res: xxh_u64) {
 XXH_mul_64_to_128_fold_64 :: #force_inline proc(lhs, rhs: xxh_u64) -> (res: xxh_u64) {
 	t := u128(lhs) * u128(rhs)
 	t := u128(lhs) * u128(rhs)
 	return u64(t & 0xFFFFFFFFFFFFFFFF) ~ u64(t >> 64)
 	return u64(t & 0xFFFFFFFFFFFFFFFF) ~ u64(t >> 64)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_xorshift_64 :: #force_inline proc(v: xxh_u64, #any_int shift: uint) -> (res: xxh_u64) {
 XXH_xorshift_64 :: #force_inline proc(v: xxh_u64, #any_int shift: uint) -> (res: xxh_u64) {
 	return v ~ (v >> shift)
 	return v ~ (v >> shift)
 }
 }
@@ -125,7 +125,7 @@ XXH_xorshift_64 :: #force_inline proc(v: xxh_u64, #any_int shift: uint) -> (res:
 /*
 /*
 	This is a fast avalanche stage, suitable when input bits are already partially mixed
 	This is a fast avalanche stage, suitable when input bits are already partially mixed
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_avalanche :: #force_inline proc(h64: xxh_u64) -> (res: xxh_u64) {
 XXH3_avalanche :: #force_inline proc(h64: xxh_u64) -> (res: xxh_u64) {
 	res = XXH_xorshift_64(h64, 37)
 	res = XXH_xorshift_64(h64, 37)
 	res *= 0x165667919E3779F9
 	res *= 0x165667919E3779F9
@@ -137,7 +137,7 @@ XXH3_avalanche :: #force_inline proc(h64: xxh_u64) -> (res: xxh_u64) {
 	This is a stronger avalanche, inspired by Pelle Evensen's rrmxmx
 	This is a stronger avalanche, inspired by Pelle Evensen's rrmxmx
 	preferable when input has not been previously mixed
 	preferable when input has not been previously mixed
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_rrmxmx :: #force_inline proc(h64, length: xxh_u64) -> (res: xxh_u64) {
 XXH3_rrmxmx :: #force_inline proc(h64, length: xxh_u64) -> (res: xxh_u64) {
 	/* this mix is inspired by Pelle Evensen's rrmxmx */
 	/* this mix is inspired by Pelle Evensen's rrmxmx */
 	res = h64
 	res = h64
@@ -166,7 +166,7 @@ XXH3_rrmxmx :: #force_inline proc(h64, length: xxh_u64) -> (res: xxh_u64) {
 	fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).
 	fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).
 */
 */
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_1to3_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_1to3_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	/* A doubled version of 1to3_64b with different constants. */
 	/* A doubled version of 1to3_64b with different constants. */
 	length := len(input)
 	length := len(input)
@@ -190,7 +190,7 @@ XXH3_len_1to3_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u6
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_4to8_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_4to8_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	length := len(input)
 	length := len(input)
 	seed   := seed
 	seed   := seed
@@ -219,7 +219,7 @@ XXH3_len_4to8_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u6
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_9to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_9to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	length := len(input)
 	length := len(input)
 
 
@@ -261,7 +261,7 @@ XXH3_len_9to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u
 /*
 /*
 	Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN
 	Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_0to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_0to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	length := len(input)
 	length := len(input)
 
 
@@ -279,7 +279,7 @@ XXH3_len_0to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u
 /*
 /*
 	A bit slower than XXH3_mix16B, but handles multiply by zero better.
 	A bit slower than XXH3_mix16B, but handles multiply by zero better.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH128_mix32B :: #force_inline proc(acc: xxh_u128, input_1: []u8, input_2: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH128_mix32B :: #force_inline proc(acc: xxh_u128, input_1: []u8, input_2: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	acc128 := XXH128_hash_t{
 	acc128 := XXH128_hash_t{
 		h = acc,
 		h = acc,
@@ -293,7 +293,7 @@ XXH128_mix32B :: #force_inline proc(acc: xxh_u128, input_1: []u8, input_2: []u8,
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_17to128_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_17to128_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	length := len(input)
 	length := len(input)
 
 
@@ -323,7 +323,7 @@ XXH3_len_17to128_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh
 	unreachable()
 	unreachable()
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_129to240_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 XXH3_len_129to240_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	length := len(input)
 	length := len(input)
 
 
@@ -379,7 +379,7 @@ XXH3_INIT_ACC :: [XXH_ACC_NB]xxh_u64{
 
 
 XXH_SECRET_MERGEACCS_START :: 11
 XXH_SECRET_MERGEACCS_START :: 11
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_128b_internal :: #force_inline proc(
 XXH3_hashLong_128b_internal :: #force_inline proc(
 			input: []u8,
 			input: []u8,
 			secret: []u8,
 			secret: []u8,
@@ -407,7 +407,7 @@ XXH3_hashLong_128b_internal :: #force_inline proc(
 /*
 /*
  * It's important for performance that XXH3_hashLong is not inlined.
  * It's important for performance that XXH3_hashLong is not inlined.
  */
  */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 	return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
 	return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
 }
 }
@@ -415,12 +415,12 @@ XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64,
 /*
 /*
  * It's important for performance that XXH3_hashLong is not inlined.
  * It's important for performance that XXH3_hashLong is not inlined.
  */
  */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 	return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
 	return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
 XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
 								input: []u8, seed: xxh_u64, secret: []u8,
 								input: []u8, seed: xxh_u64, secret: []u8,
 								f_acc512: XXH3_accumulate_512_f,
 								f_acc512: XXH3_accumulate_512_f,
@@ -441,14 +441,14 @@ XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
 /*
 /*
  * It's important for performance that XXH3_hashLong is not inlined.
  * It's important for performance that XXH3_hashLong is not inlined.
  */
  */
- @(optimization_mode="speed")
+ @(optimization_mode="favor_size")
 XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
 	return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret)
 	return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret)
 }
 }
 
 
 XXH3_hashLong128_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8)  -> (res: XXH3_128_hash)
 XXH3_hashLong128_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8)  -> (res: XXH3_128_hash)
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128bits_internal :: #force_inline proc(
 XXH3_128bits_internal :: #force_inline proc(
 	input: []u8, seed: xxh_u64, secret: []u8, f_hl128: XXH3_hashLong128_f) -> (res: XXH3_128_hash) {
 	input: []u8, seed: xxh_u64, secret: []u8, f_hl128: XXH3_hashLong128_f) -> (res: XXH3_128_hash) {
 
 
@@ -474,17 +474,17 @@ XXH3_128bits_internal :: #force_inline proc(
 }
 }
 
 
 /* ===   Public XXH128 API   === */
 /* ===   Public XXH128 API   === */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) {
 XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) {
 	return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
 	return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: XXH3_128_hash) {
 XXH3_128_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: XXH3_128_hash) {
 	return XXH3_128bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
 	return XXH3_128bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128_with_secret :: proc(input: []u8, secret: []u8) -> (hash: XXH3_128_hash) {
 XXH3_128_with_secret :: proc(input: []u8, secret: []u8) -> (hash: XXH3_128_hash) {
 	return XXH3_128bits_internal(input, 0, secret, XXH3_hashLong_128b_withSecret)
 	return XXH3_128bits_internal(input, 0, secret, XXH3_hashLong_128b_withSecret)
 }
 }
@@ -519,7 +519,7 @@ XXH3_128 :: proc { XXH3_128_default, XXH3_128_with_seed, XXH3_128_with_secret }
 	The XOR mixing hides individual parts of the secret and increases entropy.
 	The XOR mixing hides individual parts of the secret and increases entropy.
 	This adds an extra layer of strength for custom secrets.
 	This adds an extra layer of strength for custom secrets.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_1to3_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_1to3_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	length := u32(len(input))
 	length := u32(len(input))
 	assert(input != nil)
 	assert(input != nil)
@@ -542,7 +542,7 @@ XXH3_len_1to3_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_4to8_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_4to8_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	length := u32(len(input))
 	length := u32(len(input))
 	assert(input != nil)
 	assert(input != nil)
@@ -562,7 +562,7 @@ XXH3_len_4to8_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_9to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_9to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	length := u64(len(input))
 	length := u64(len(input))
 	assert(input != nil)
 	assert(input != nil)
@@ -579,7 +579,7 @@ XXH3_len_9to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u6
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_0to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_0to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	length := u64(len(input))
 	length := u64(len(input))
 	assert(input != nil)
 	assert(input != nil)
@@ -621,7 +621,7 @@ XXH3_len_0to16_64b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u6
 	by this, although it is always a good idea to use a proper seed if you care
 	by this, although it is always a good idea to use a proper seed if you care
 	about strength.
 	about strength.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_mix16B :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_mix16B :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	input_lo := XXH64_read64(input[0:])
 	input_lo := XXH64_read64(input[0:])
 	input_hi := XXH64_read64(input[8:])
 	input_hi := XXH64_read64(input[8:])
@@ -632,7 +632,7 @@ XXH3_mix16B :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (
 }
 }
 
 
 /* For mid range keys, XXH3 uses a Mum-hash variant. */
 /* For mid range keys, XXH3 uses a Mum-hash variant. */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_17to128_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_17to128_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	length := len(input)
 	length := len(input)
@@ -665,7 +665,7 @@ XXH3_MIDSIZE_MAX         :: 240
 XXH3_MIDSIZE_STARTOFFSET :: 3
 XXH3_MIDSIZE_STARTOFFSET :: 3
 XXH3_MIDSIZE_LASTOFFSET  :: 17
 XXH3_MIDSIZE_LASTOFFSET  :: 17
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_129to240_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 XXH3_len_129to240_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	length := len(input)
 	length := len(input)
@@ -699,7 +699,7 @@ XXH_SECRET_CONSUME_RATE  :: 8 /* nb of secret bytes consumed at each accumulatio
 XXH_ACC_NB               :: (XXH_STRIPE_LEN / size_of(xxh_u64))
 XXH_ACC_NB               :: (XXH_STRIPE_LEN / size_of(xxh_u64))
 XXH_SECRET_LASTACC_START :: 7 /* not aligned on 8, last secret is different from acc & scrambler */
 XXH_SECRET_LASTACC_START :: 7 /* not aligned on 8, last secret is different from acc & scrambler */
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_writeLE64 :: #force_inline proc(dst: []u8, v64: u64le) {
 XXH_writeLE64 :: #force_inline proc(dst: []u8, v64: u64le) {
 	v := v64
 	v := v64
 	mem_copy(raw_data(dst), &v, size_of(v64))
 	mem_copy(raw_data(dst), &v, size_of(v64))
@@ -737,7 +737,7 @@ XXH3_scramble_accumulator : XXH3_scramble_accumulator_f = XXH3_scramble_accumula
 XXH3_init_custom_secret   : XXH3_init_custom_secret_f   = XXH3_init_custom_secret_scalar
 XXH3_init_custom_secret   : XXH3_init_custom_secret_f   = XXH3_init_custom_secret_scalar
 
 
 /* scalar variants - universal */
 /* scalar variants - universal */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) {
 XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) {
 	xacc    := acc     /* presumed aligned */
 	xacc    := acc     /* presumed aligned */
 	xinput  := input   /* no alignment restriction */
 	xinput  := input   /* no alignment restriction */
@@ -754,7 +754,7 @@ XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, se
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_scramble_accumulator_scalar :: #force_inline proc(acc: []xxh_u64, secret: []u8) {
 XXH3_scramble_accumulator_scalar :: #force_inline proc(acc: []xxh_u64, secret: []u8) {
 	xacc    := acc     /* presumed aligned */
 	xacc    := acc     /* presumed aligned */
 	xsecret := secret  /* no alignment restriction */
 	xsecret := secret  /* no alignment restriction */
@@ -771,7 +771,7 @@ XXH3_scramble_accumulator_scalar :: #force_inline proc(acc: []xxh_u64, secret: [
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_init_custom_secret_scalar :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64) {
 XXH3_init_custom_secret_scalar :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64) {
 	#assert((XXH_SECRET_DEFAULT_SIZE & 15) == 0)
 	#assert((XXH_SECRET_DEFAULT_SIZE & 15) == 0)
 
 
@@ -791,7 +791,7 @@ XXH_PREFETCH_DIST :: 320
  * Loops over XXH3_accumulate_512().
  * Loops over XXH3_accumulate_512().
  * Assumption: nbStripes will not overflow the secret size
  * Assumption: nbStripes will not overflow the secret size
  */
  */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_accumulate :: #force_inline proc(
 XXH3_accumulate :: #force_inline proc(
 	acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) {
 	acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) {
 
 
@@ -804,7 +804,7 @@ XXH3_accumulate :: #force_inline proc(
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_internal_loop :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8,
 XXH3_hashLong_internal_loop :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8,
 	f_acc512: XXH3_accumulate_512_f, f_scramble: XXH3_scramble_accumulator_f) {
 	f_acc512: XXH3_accumulate_512_f, f_scramble: XXH3_scramble_accumulator_f) {
 
 
@@ -833,14 +833,14 @@ XXH3_hashLong_internal_loop :: #force_inline proc(acc: []xxh_u64, input: []u8, s
 	}
 	}
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_mix2Accs :: #force_inline proc(acc: []xxh_u64, secret: []u8) -> (res: xxh_u64) {
 XXH3_mix2Accs :: #force_inline proc(acc: []xxh_u64, secret: []u8) -> (res: xxh_u64) {
 	return XXH_mul_64_to_128_fold_64(
 	return XXH_mul_64_to_128_fold_64(
 		acc[0] ~ XXH64_read64(secret),
 		acc[0] ~ XXH64_read64(secret),
 		acc[1] ~ XXH64_read64(secret[8:]))
 		acc[1] ~ XXH64_read64(secret[8:]))
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_mergeAccs :: #force_inline proc(acc: []xxh_u64, secret: []u8, start: xxh_u64) -> (res: xxh_u64) {
 XXH3_mergeAccs :: #force_inline proc(acc: []xxh_u64, secret: []u8, start: xxh_u64) -> (res: xxh_u64) {
 	result64 := start
 	result64 := start
 	#no_bounds_check for i := 0; i < 4; i += 1 {
 	#no_bounds_check for i := 0; i < 4; i += 1 {
@@ -849,7 +849,7 @@ XXH3_mergeAccs :: #force_inline proc(acc: []xxh_u64, secret: []u8, start: xxh_u6
 	return XXH3_avalanche(result64)
 	return XXH3_avalanche(result64)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8,
 XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8,
 			f_acc512: XXH3_accumulate_512_f, f_scramble: XXH3_scramble_accumulator_f) -> (hash: xxh_u64) {
 			f_acc512: XXH3_accumulate_512_f, f_scramble: XXH3_scramble_accumulator_f) -> (hash: xxh_u64) {
 
 
@@ -868,7 +868,7 @@ XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8,
 /*
 /*
 	It's important for performance that XXH3_hashLong is not inlined.
 	It's important for performance that XXH3_hashLong is not inlined.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 	return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
 	return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
 }
 }
@@ -880,7 +880,7 @@ XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u
 	This variant enforces that the compiler can detect that,
 	This variant enforces that the compiler can detect that,
 	and uses this opportunity to streamline the generated code for better performance.
 	and uses this opportunity to streamline the generated code for better performance.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 	return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
 	return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
 }
 }
@@ -896,26 +896,27 @@ XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64,
 	It's important for performance that XXH3_hashLong is not inlined. Not sure
 	It's important for performance that XXH3_hashLong is not inlined. Not sure
 	why (uop cache maybe?), but the difference is large and easily measurable.
 	why (uop cache maybe?), but the difference is large and easily measurable.
 */
 */
-@(optimization_mode="speed")
-XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(input: []u8,
-									seed:        xxh_u64,
-									f_acc512:    XXH3_accumulate_512_f,
-									f_scramble:  XXH3_scramble_accumulator_f,
-									f_init_sec:  XXH3_init_custom_secret_f) -> (hash: xxh_u64) {
+@(optimization_mode="favor_size")
+XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(
+	input:       []u8,
+	seed:        xxh_u64,
+	f_acc512:    XXH3_accumulate_512_f,
+	f_scramble:  XXH3_scramble_accumulator_f,
+	f_init_sec:  XXH3_init_custom_secret_f,
+) -> (hash: xxh_u64) {
 	if seed == 0 {
 	if seed == 0 {
 		return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], f_acc512, f_scramble)
 		return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], f_acc512, f_scramble)
 	}
 	}
-	{
-		secret: [XXH_SECRET_DEFAULT_SIZE]u8
-		f_init_sec(secret[:], seed)
-		return XXH3_hashLong_64b_internal(input, secret[:], f_acc512, f_scramble)
-	}
+
+	secret: [XXH_SECRET_DEFAULT_SIZE]u8
+	f_init_sec(secret[:], seed)
+	return XXH3_hashLong_64b_internal(input, secret[:], f_acc512, f_scramble)
 }
 }
 
 
 /*
 /*
 	It's important for performance that XXH3_hashLong is not inlined.
 	It's important for performance that XXH3_hashLong is not inlined.
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
 	return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret)
 	return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret)
 }
 }
@@ -923,7 +924,7 @@ XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64,
 
 
 XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8)  -> (res: xxh_u64)
 XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8)  -> (res: xxh_u64)
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) {
 XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) {
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	/*
 	/*
@@ -943,19 +944,19 @@ XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLon
 }
 }
 
 
 /* ===   Public entry point   === */
 /* ===   Public entry point   === */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_64_default :: proc(input: []u8) -> (hash: xxh_u64) {
 XXH3_64_default :: proc(input: []u8) -> (hash: xxh_u64) {
 	return XXH3_64bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_64b_default)
 	return XXH3_64bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_64b_default)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_64_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: xxh_u64) {
 XXH3_64_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: xxh_u64) {
 	return XXH3_64bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_64b_withSeed)
 	return XXH3_64bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_64b_withSeed)
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_64_with_secret :: proc(input, secret: []u8) -> (hash: xxh_u64) {
 XXH3_64_with_secret :: proc(input, secret: []u8) -> (hash: xxh_u64) {
 	return XXH3_64bits_internal(input, 0, secret, XXH3_hashLong_64b_withSecret)
 	return XXH3_64bits_internal(input, 0, secret, XXH3_hashLong_64b_withSecret)
 }
 }
 
 
-XXH3_64 :: proc { XXH3_64_default, XXH3_64_with_seed, XXH3_64_with_secret }
+XXH3_64 :: proc { XXH3_64_default, XXH3_64_with_seed, XXH3_64_with_secret }

+ 5 - 5
core/hash/xxhash/xxhash_32.odin

@@ -40,7 +40,7 @@ XXH_PRIME32_3 :: 0xC2B2AE3D     /*!< 0b11000010101100101010111000111101 */
 XXH_PRIME32_4 :: 0x27D4EB2F     /*!< 0b00100111110101001110101100101111 */
 XXH_PRIME32_4 :: 0x27D4EB2F     /*!< 0b00100111110101001110101100101111 */
 XXH_PRIME32_5 :: 0x165667B1     /*!< 0b00010110010101100110011110110001 */
 XXH_PRIME32_5 :: 0x165667B1     /*!< 0b00010110010101100110011110110001 */
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_round :: #force_inline proc(seed, input: XXH32_hash) -> (res: XXH32_hash) {
 XXH32_round :: #force_inline proc(seed, input: XXH32_hash) -> (res: XXH32_hash) {
 	seed := seed
 	seed := seed
 
 
@@ -53,7 +53,7 @@ XXH32_round :: #force_inline proc(seed, input: XXH32_hash) -> (res: XXH32_hash)
 /*
 /*
 	Mix all bits
 	Mix all bits
 */
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_avalanche :: #force_inline proc(h32: u32) -> (res: u32) {
 XXH32_avalanche :: #force_inline proc(h32: u32) -> (res: u32) {
 	h32 := h32
 	h32 := h32
 
 
@@ -65,7 +65,7 @@ XXH32_avalanche :: #force_inline proc(h32: u32) -> (res: u32) {
 	return h32
 	return h32
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_finalize :: #force_inline proc(h32: u32, buf: []u8, alignment: Alignment) -> (res: u32) {
 XXH32_finalize :: #force_inline proc(h32: u32, buf: []u8, alignment: Alignment) -> (res: u32) {
 	process_1 :: #force_inline proc(h32: u32, buf: []u8) -> (h32_res: u32, buf_res: []u8) {
 	process_1 :: #force_inline proc(h32: u32, buf: []u8) -> (h32_res: u32, buf_res: []u8) {
 		#no_bounds_check b := u32(buf[0])
 		#no_bounds_check b := u32(buf[0])
@@ -143,7 +143,7 @@ XXH32_finalize :: #force_inline proc(h32: u32, buf: []u8, alignment: Alignment)
 	unreachable()
 	unreachable()
 }
 }
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_endian_align :: #force_inline proc(input: []u8, seed := XXH32_DEFAULT_SEED, alignment: Alignment) -> (res: XXH32_hash) {
 XXH32_endian_align :: #force_inline proc(input: []u8, seed := XXH32_DEFAULT_SEED, alignment: Alignment) -> (res: XXH32_hash) {
 	buf := input
 	buf := input
 	length := len(input)
 	length := len(input)
@@ -318,4 +318,4 @@ XXH32_canonical_from_hash :: proc(hash: XXH32_hash) -> (canonical: XXH32_canonic
 XXH32_hash_from_canonical :: proc(canonical: ^XXH32_canonical) -> (hash: XXH32_hash) {
 XXH32_hash_from_canonical :: proc(canonical: ^XXH32_canonical) -> (hash: XXH32_hash) {
 	h := (^u32be)(&canonical.digest)^
 	h := (^u32be)(&canonical.digest)^
 	return XXH32_hash(h)
 	return XXH32_hash(h)
-}
+}

Some files were not shown because too many files changed in this diff