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/cgltf/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/speed.odin -file -all-packages -o:speed -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/cgltf/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/speed.odin -file -all-packages -o:speed -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)
         if: matrix.os == 'macos-14'
         run: |
-          brew install llvm@17
+          brew install llvm@17 wasmtime
           echo "/opt/homebrew/opt/llvm@17/bin" >> $GITHUB_PATH
 
       - name: Build Odin
@@ -135,18 +135,24 @@ jobs:
           ./run.sh
 
       - 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'
       - 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'
       - 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'
       - 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'
 
+      - 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:
     name: Windows Build, Check, and Test
     runs-on: windows-2022

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

@@ -50,8 +50,8 @@ jobs:
         run: |
           wget https://apt.llvm.org/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
         run: make nightly
       - name: Odin run
@@ -82,8 +82,8 @@ jobs:
       - uses: actions/checkout@v4
       - name: Download LLVM and setup PATH
         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
         # 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.
@@ -116,8 +116,8 @@ jobs:
       - uses: actions/checkout@v4
       - name: Download LLVM and setup PATH
         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
         # 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.

+ 1 - 1
.gitignore

@@ -303,7 +303,7 @@ bin/
 # - Linux/MacOS
 odin
 !odin/
-odin.dSYM
+**/*.dSYM
 *.bin
 demo.bin
 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
 syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
+// FreeBSD, NetBSD, et cetera
+syscall_bsd :: proc(id: uintptr, args: ..uintptr) -> (uintptr, bool) ---
 
 
 // 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_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_value :: proc($T: typeid, index: int) -> $V ---

+ 28 - 0
base/runtime/core.odin

@@ -299,6 +299,8 @@ when ODIN_OS == .Windows {
 		Thread_Detach  = 3,
 	}
 	dll_forward_reason: DLL_Forward_Reason
+
+	dll_instance: rawptr
 }
 
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
@@ -397,11 +399,34 @@ Logger :: struct {
 	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 {
 	allocator:              Allocator,
 	temp_allocator:         Allocator,
 	assertion_failure_proc: Assertion_Failure_Proc,
 	logger:                 Logger,
+	random_generator:       Random_Generator,
 
 	user_ptr:   rawptr,
 	user_index: int,
@@ -708,6 +733,9 @@ __init_context :: proc "contextless" (c: ^Context) {
 
 	c.logger.procedure = default_logger_proc
 	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) -> ! {

+ 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.
 //
 // 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.
 @builtin
 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.
 //
 // 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.
 @builtin
 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`
 @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`).
 @builtin
-reserve :: proc{reserve_dynamic_array, reserve_map}
+reserve :: proc{
+	reserve_dynamic_array,
+	reserve_map,
+
+	reserve_soa,
+}
 
 @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`).
 @builtin
-resize :: proc{resize_dynamic_array}
+resize :: proc{
+	resize_dynamic_array,
+
+	resize_soa,
+}
 
 @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.
 @builtin
@@ -268,7 +290,7 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat
 	return
 }
 
-DEFAULT_RESERVE_CAPACITY :: 16
+DEFAULT_DYNAMIC_ARRAY_CAPACITY :: 8
 
 @(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 {
@@ -295,7 +317,7 @@ make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allo
 // Note: Prefer using the procedure group `make`.
 @(builtin, require_results)
 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.
 // 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_map,
 	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
 	} else {
 		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
 			if should_zero {
@@ -472,7 +500,7 @@ _append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, l
 		return arg_len, nil
 	} else {
 		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
 			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
-@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

+ 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 {
 		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))
 	return
 }
@@ -64,12 +64,7 @@ raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Ra
 	if array == 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))
 	return
 }
@@ -98,7 +93,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
 	ti = type_info_base(ti)
 	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
 	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)
 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
-	reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) or_return
+	reserve_soa(&array, 0, loc) or_return
 	return array, nil
 }
 
@@ -187,8 +182,28 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
 	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
 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 {
 		return nil
 	}
@@ -213,12 +228,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
 	ti = type_info_base(ti)
 	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)
 
 	old_size := 0
@@ -238,7 +248,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
 	old_data := (^rawptr)(array)^
 
 	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,
 	) or_return
 	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
 }
 
+
+@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
-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 {
 		return 0, nil
 	}
 
 	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)
@@ -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_base(ti)
 		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)^
 
@@ -326,7 +342,17 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
 }
 
 @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 {
 		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 {
-		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)
 
@@ -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_base(ti)
 		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)^
 
@@ -389,7 +415,8 @@ append_soa :: proc{
 
 
 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
 		ptr := (^rawptr)(&array)^
 		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 {
-	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
 		ptr := (^rawptr)(&array)^
 		footer := raw_soa_footer(&array)
@@ -416,7 +444,8 @@ delete_soa :: proc{
 
 
 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.len = 0
 	}
@@ -438,12 +467,7 @@ into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
 		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
 	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)
 		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)
 		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)
 		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)
 		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,
 }
 
-// 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 {
 	backing_allocator:  Allocator,
 	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)
 		_start :: proc "c" () {
 			context = default_context()
+
+			when ODIN_OS == .WASI {
+				_wasi_setup_args()
+			}
+
 			#force_no_inline _startup_runtime()
 			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 {
 		context = default_context()
 
-		// Populate Windows DLL-specific global
+		// Populate Windows DLL-specific globals
 		dll_forward_reason = DLL_Forward_Reason(fdwReason)
+		dll_instance       = hinstDLL
 
 		switch dll_forward_reason {
 		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)
 }
 
-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)
 }
 
-heap_free :: proc(ptr: rawptr) {
+heap_free :: proc "contextless" (ptr: rawptr) {
 	_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 ---
 }
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	if size <= 0 {
 		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)
 }
 
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	_orca_free(ptr)
 }

+ 6 - 3
base/runtime/heap_allocator_other.odin

@@ -2,14 +2,17 @@
 //+private
 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")
 }
 
-_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")
 }
 
-_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")
 }

+ 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 ---
 }
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	if size <= 0 {
 		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
 	// POSIX platforms. Ensure your caller takes this into account.
 	return _unix_realloc(ptr, new_size)
 }
 
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	_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 ---
 }
 
-_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
 	HEAP_ZERO_MEMORY :: 0x00000008
 	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 {
 		_heap_free(ptr)
 		return nil
@@ -30,7 +30,7 @@ _heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
 	HEAP_ZERO_MEMORY :: 0x00000008
 	return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size))
 }
-_heap_free :: proc(ptr: rawptr) {
+_heap_free :: proc "contextless" (ptr: rawptr) {
 	if ptr == nil {
 		return
 	}

+ 31 - 27
base/runtime/internal.odin

@@ -1,3 +1,4 @@
+//+vet !cast
 package runtime
 
 import "base:intrinsics"
@@ -29,7 +30,7 @@ is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
 	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))
 
 	p := ptr
@@ -47,7 +48,7 @@ is_power_of_two_uint :: #force_inline proc "contextless" (x: uint) -> bool {
 	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))
 
 	p := ptr
@@ -65,7 +66,7 @@ is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool
 	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))
 
 	p := ptr
@@ -642,21 +643,24 @@ abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64
 
 
 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 {
-		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 {
-	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
 	t1 := r0*q1 + r1*q0 - r2*q3 + r3*q2
 	t2 := r0*q2 + r1*q3 + r2*q0 - r3*q1
 	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 {
@@ -733,8 +737,8 @@ mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
 }
 
 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)
 
@@ -743,7 +747,7 @@ quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {
 	t2 := (r0*q2 - r1*q3 - r2*q0 + r3*q1) * invmag2
 	t3 := (r0*q3 + r1*q2 + r2*q1 - r3*q0) * invmag2
 
-	return quaternion(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 {
@@ -1012,26 +1016,26 @@ modti3 :: proc "c" (a, b: i128) -> i128 {
 	bn := (b ~ s_b) - s_b
 
 	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)
 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)
 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)
-fixdfti :: proc(a: u64) -> i128 {
+fixdfti :: proc "c" (a: u64) -> i128 {
 	significandBits :: 52
 	typeWidth       :: (size_of(u64)*8)
 	exponentBits    :: (typeWidth - significandBits - 1)

+ 18 - 5
base/runtime/os_specific_darwin.odin

@@ -5,11 +5,24 @@ package runtime
 import "base:intrinsics"
 
 _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
-	WRITE  :: 0x2000004
 	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
 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) {
-	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)
 }
+
+_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) {
 	if ti == 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]))
 		}
 
-		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 rem != nil {
 				rem^ = a
@@ -107,7 +107,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 				r[low]  = n[high] >> (sr - U64_BITS)
 			}
 		} 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 rem != nil {
@@ -143,7 +143,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 		r_all = transmute(u128)r
 		s := i128(b - r_all - 1) >> (U128_BITS - 1)
 		carry = u32(s & 1)
-		r_all -= b & transmute(u128)s
+		r_all -= b & u128(s)
 		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.
 		spill_end := uintptr(raw_data(a.spill)) + uintptr(len(a.spill))
 		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)
 		} else {
 			// 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.
 			// Reset the bit to update latest status so that we do not
 			// 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
 		}
 
@@ -760,7 +760,7 @@ free :: proc(a: ^WASM_Allocator, ptr: rawptr, loc := #caller_location) {
 	defer unlock(a)
 
 	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 := 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 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%\"
 
 if not exist .git\ goto skip_git_hash
@@ -111,7 +114,7 @@ call build_vendor.bat
 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
-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
 

+ 1 - 1
build_odin.sh

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

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

@@ -34,20 +34,7 @@ when ODIN_OS == .Windows {
 	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_DFL  :: rawptr(uintptr(0))
 	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 {
 
-        // For 64-bit platforms, we set the default max buffer size to 4 GiB,
-        // which is GZIP and PKZIP's max payload size.
+	// For 64-bit platforms, we set the default max buffer size to 4 GiB,
+	// which is GZIP and PKZIP's max payload size.
 	COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 32))
 } else {
 	
 	// For 32-bit platforms, we set the default max buffer size to 512 MiB.
-        COMPRESS_OUTPUT_ALLOCATE_MAX :: int(#config(COMPRESS_OUTPUT_ALLOCATE_MAX, 1 << 29))
+	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}
 
-@(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) {
 	#no_bounds_check {
 		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) {
 	// TODO: REMOVE ALL USE OF context.temp_allocator here
 	// 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}
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
 	b := read_slice(z, size_of(T)) or_return
 	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) {
 	#no_bounds_check {
 		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
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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
 	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
 // preferentially.
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_u8_prefer_code_buffer_lsb :: #force_inline proc(z: ^$C) -> (res: u8, err: io.Error) {
 	if z.num_bits >= 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
 }
 
-@(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) {
 	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) {
 	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) {
 	size :: size_of(T)
 
@@ -317,7 +317,7 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
 	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) {
 	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
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_back_byte :: #force_inline proc(z: ^$C, offset: i64) -> (res: u8, err: io.Error) {
 	// Look back into the sliding window.
 	return z.output.buf[z.bytes_written - offset], .None
 }
 
 // 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 := u64(width)
 	b      := u64(0)
@@ -385,7 +385,7 @@ refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width :=
 }
 
 // Generalized bit reader LSB
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width := i8(24)) {
 	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}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 consume_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) {
 	z.code_buffer >>= 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) {
 	z.code_buffer >>= 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}
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	if z.num_bits < u64(width) {
 		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))
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	if z.num_bits < u64(width) {
 		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}
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	assert(z.num_bits >= u64(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 {
 	assert(z.num_bits >= u64(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}
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
 	k := #force_inline peek_bits_lsb(z, width)
 	#force_inline consume_bits_lsb(z, width)
 	return k
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 read_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
 	k := peek_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}
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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)
 	#force_inline consume_bits_lsb(z, width)
 	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 {
 	k := peek_bits_no_refill_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}
 
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input) {
 	discard := u8(z.num_bits & 7)
 	#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 := u8(z.num_bits & 7)
 	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
 
 	for inp < inp_end {
-		val  := transmute(i8)input[inp]
+		val  := i8(input[inp])
 		mark := int(-1)
 
 		for val < 0 {
@@ -274,12 +274,9 @@ compress_string_to_buffer :: proc(input: string, output: []u8, model := DEFAULT_
 				out_ptr := raw_data(output[out:])
 
 				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:
 					return out, .Unknown_Compression_Method
 				}

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

@@ -120,7 +120,7 @@ Huffman_Table :: struct {
 }
 
 // Implementation starts here
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
 	assert(bits <= 16)
 	// 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) {
 	/*
 		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.
 */
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_check {
 	/*
 		Resize if needed.
@@ -173,7 +173,7 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch
 	return .None
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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
@@ -201,7 +201,7 @@ repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check
 	return .None
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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
@@ -234,7 +234,7 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
 	return new(Huffman_Table, allocator), nil
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
 	sizes:     [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
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 	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
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
 	if z.num_bits < 16 {
 		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)
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err: Error) #no_bounds_check {
 	#no_bounds_check for {
 		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 {
 	/*
 		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.
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.allocator) -> (err: Error) #no_bounds_check {
 	context.allocator = allocator
 	expected_output_size := expected_output_size

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

@@ -87,7 +87,7 @@ init_cmp :: proc(
 init_ordered :: proc(
 	t: ^$T/Tree($Value),
 	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)
 }
 

+ 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)
 
-	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
 }
@@ -253,7 +256,7 @@ Inputs:
 - index: Which bit in the array
 */
 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).

+ 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 {
 		e = c.tail
 		_remove_node(c, e)
-	}
-	else {
+	} else {
 		c.count += 1
 		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
 }
 
-// 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)  {
 	n := uint(builtin.len(elems))
 	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 {
 	new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
 	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),
 	_node_allocator: runtime.Allocator,
-	_cmp_fn:          proc(Key, Key) -> Ordering,
+	_cmp_fn:         proc(Key, Key) -> Ordering,
 	_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
 // 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)
 }
 

+ 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 {
-    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:])
 	}
 	a.len -= 1
 }
 
 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
 	if index != n {
 		a.data[index] = a.data[n]
 	}
-    a.len -= 1
+	a.len -= 1
 }
 
 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 = &sorter.relations[key]
+	find = &sorter.relations[key]
 	if find == nil {
 		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 {
 		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
 	// failure.
@@ -169,7 +169,7 @@ ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) {
 	if len(dst) != 32 {
 		intrinsics.trap()
 	}
-	dst_ := transmute(^[32]byte)(raw_data(dst))
+	dst_ := (^[32]byte)(raw_data(dst))
 
 	// Convert the element to affine (x, y) representation.
 	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 {
 		intrinsics.trap()
 	}
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(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 {
 		intrinsics.trap()
 	}
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(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" (
 	arg1: ^Tight_Field_Element,
 ) -> ^Loose_Field_Element {
-	return transmute(^Loose_Field_Element)(arg1)
+	return (^Loose_Field_Element)(arg1)
 }
 
 fe_tighten_cast :: #force_inline proc "contextless" (
 	arg1: ^Loose_Field_Element,
 ) -> ^Tight_Field_Element {
-	return transmute(^Tight_Field_Element)(arg1)
+	return (^Tight_Field_Element)(arg1)
 }
 
 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" (
 	arg1: ^Tight_Field_Element,
 ) -> ^Loose_Field_Element {
-	return transmute(^Loose_Field_Element)(arg1)
+	return (^Loose_Field_Element)(arg1)
 }
 
 fe_tighten_cast :: #force_inline proc "contextless" (
 	arg1: ^Loose_Field_Element,
 ) -> ^Tight_Field_Element {
-	return transmute(^Tight_Field_Element)(arg1)
+	return (^Tight_Field_Element)(arg1)
 }
 
 fe_from_bytes :: #force_inline proc "contextless" (

+ 22 - 0
core/crypto/crypto.odin

@@ -4,6 +4,7 @@ helper routines.
 */
 package crypto
 
+import "base:runtime"
 import "core:mem"
 
 // 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)
 }
+
+
+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) {
 	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
@@ -75,7 +75,7 @@ final :: proc(ctx: ^Context, dst: []byte) {
 		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.
@@ -84,7 +84,7 @@ clone :: proc(ctx, other: ^Context) {
 		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
@@ -94,7 +94,7 @@ reset :: proc(ctx: ^Context) {
 		return
 	}
 
-	shake.reset(transmute(^shake.Context)(ctx))
+	shake.reset((^shake.Context)(ctx))
 }
 
 @(private)
@@ -107,7 +107,7 @@ _init_kmac :: proc(ctx: ^Context, key, s: []byte, sec_strength: int) {
 		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.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)
 _init :: proc(ctx: ^Context) {
 	ctx.dsbyte = _sha3.DS_KECCAK
-	_sha3.init(transmute(^_sha3.Context)(ctx))
+	_sha3.init((^_sha3.Context)(ctx))
 }
 
 // update adds more data to the Context.
 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
@@ -80,16 +80,16 @@ update :: proc(ctx: ^Context, data: []byte) {
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // which is useful for for calculating rolling digests.
 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 :: 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
 // be used again.
 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) {
 	err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst))
 	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
 	}
 
-	b_ := transmute(^[32]byte)(raw_data(b))
+	b_ := (^[32]byte)(raw_data(b))
 
 	s: field.Tight_Field_Element = ---
 	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
 	// specifically, this is the encoding of the canonical
 	// 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_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)
 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:
 	//

+ 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")
 	}
 
-	b_ := transmute(^[WIDE_SCALAR_SIZE]byte)(raw_data(b))
+	b_ := (^[WIDE_SCALAR_SIZE]byte)(raw_data(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)
 _init :: proc(ctx: ^Context) {
 	ctx.dsbyte = _sha3.DS_SHA3
-	_sha3.init(transmute(^_sha3.Context)(ctx))
+	_sha3.init((^_sha3.Context)(ctx))
 }
 
 // update adds more data to the Context.
 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
@@ -82,16 +82,16 @@ update :: proc(ctx: ^Context, data: []byte) {
 // Iff finalize_clone is set, final will work on a copy of the Context,
 // which is useful for for calculating rolling digests.
 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 :: 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
 // be used again.
 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 :: 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 :: 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 :: 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 :: 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
 // after any reads have been done, and attempts to do so will panic.
 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
 // 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.
 read :: proc(ctx: ^Context, dst: []byte) {
-	ctx_ := transmute(^_sha3.Context)(ctx)
+	ctx_ := (^_sha3.Context)(ctx)
 	if !ctx.is_finalized {
 		_sha3.shake_xof(ctx_)
 	}
@@ -62,11 +62,11 @@ read :: proc(ctx: ^Context, dst: []byte) {
 
 // clone clones the Context other into ctx.
 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
 // be used again.
 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 :: 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 :: 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
 // instance.  This MUST not be called after any reads have been done, and
 // any attempts to do so will panic.
 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
@@ -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,
 // which is useful for for calculating rolling digests.
 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
@@ -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
 // write_element will panic.
 read :: proc(ctx: ^Context, dst: []byte) {
-	ctx_ := transmute(^_sha3.Context)(ctx)
+	ctx_ := (^_sha3.Context)(ctx)
 	if !ctx.is_finalized {
 		_sha3.encode_byte_len(ctx_, 0, false) // right_encode
 		_sha3.shake_xof(ctx_)
@@ -53,13 +53,13 @@ read :: proc(ctx: ^Context, dst: []byte) {
 
 // clone clones the Context other into ctx.
 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
 // be used again.
 reset :: proc(ctx: ^Context) {
-	_sha3.reset(transmute(^_sha3.Context)(ctx))
+	_sha3.reset((^_sha3.Context)(ctx))
 }
 
 @(private)

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

@@ -78,7 +78,7 @@ _Context :: struct {
 
 @(private="package")
 _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)
 	return ctx.impl.state != nil

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

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

+ 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
 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.
 
 The underlying behaviour is platform specific.
 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:
 	import "core:dynlib"
@@ -79,10 +76,7 @@ Loads the address of a procedure/variable from a dynamic library.
 
 The underlying behaviour is platform specific.
 On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`.
-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:
 	import "core:dynlib"
@@ -177,9 +171,7 @@ initialize_symbols :: proc(
 	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 {
 	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 {
 	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 {
 	err := os.dlerror()
 	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 "core:strings"
-import "base:runtime"
 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
-
-	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)
 	return handle, handle != nil
 }
@@ -21,9 +19,9 @@ _unload_library :: proc(library: Library) -> bool {
 	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)
 	found = ptr != nil
 	return
@@ -33,4 +31,4 @@ _last_error :: proc() -> string {
 	err := win32.System_Error(win32.GetLastError())
 	err_msg := reflect.enum_string(err)
 	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.
 
 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 :: '='
 
 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 {
-    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
 _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{
-    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 {
 		_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 {
@@ -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) {
 	assert(len(val) >= 0)
 	_encode_u64(e, u64(len(val)), major) or_return
-    _, err = io.write_full(e.writer, val[:])
+	_, err = io.write_full(e.writer, val[:])
 	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 {
-    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) {
@@ -480,10 +480,10 @@ _decode_array :: proc(d: Decoder, add: Add, allocator := context.allocator, loc
 _encode_array :: proc(e: Encoder, arr: Array) -> Encode_Error {
 	assert(len(arr) >= 0)
 	_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) {
@@ -576,7 +576,7 @@ _encode_map :: proc(e: Encoder, m: Map) -> (err: Encode_Error) {
 		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) {
@@ -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_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) {
@@ -739,16 +739,16 @@ _encode_nil :: proc(w: io.Writer) -> io.Error {
 // Streaming
 
 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
 }
 
 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
 }
 
@@ -757,8 +757,8 @@ encode_stream_text       :: _encode_text
 encode_stream_array_item :: encode
 
 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.

+ 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:
 	package main
 
+	import "base:intrinsics"
+
 	import "core:encoding/cbor"
 	import "core:fmt"
+	import "core:reflect"
 	import "core:time"
 
 	Possibilities :: union {
@@ -93,9 +96,32 @@ Example:
 		ignore_this: ^Data `cbor:"-"`,     // Ignored by implementation.
 		renamed: f32 `cbor:"renamed :)"`,  // Renamed when encoded.
 		my_union: Possibilities,           // Union support.
+
+		my_raw: [8]u32 `cbor_tag:"raw"`, // Custom tag that just writes the value as bytes.
 	}
 
 	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}
 
 		data := Data{
@@ -105,21 +131,22 @@ Example:
 			ignore_this = &Data{},
 			renamed     = 123123.125,
 			my_union    = 3,
+			my_raw      = {1=1, 2=2, 3=3},
 		}
-		
+
 		// Marshal the struct into binary CBOR.
 		binary, err := cbor.marshal(data, cbor.ENCODE_FULLY_DETERMINISTIC)
-		assert(err == nil)
+		fmt.assertf(err == nil, "marshal error: %v", err)
 		defer delete(binary)
-		
+
 		// Decode the binary data into a `cbor.Value`.
 		decoded, derr := cbor.decode(string(binary))
-		assert(derr == nil)
+		fmt.assertf(derr == nil, "decode error: %v", derr)
 		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]].
 		diagnosis, eerr := cbor.to_diagnostic_format(decoded)
-		assert(eerr == nil)
+		fmt.assertf(eerr == nil, "to diagnostic error: %v", eerr)
 		defer delete(diagnosis)
 
 		fmt.println(diagnosis)
@@ -127,6 +154,7 @@ Example:
 
 Output:
 	{
+		"my_raw": 200(h'00001000200030000000000000000000'),
 		"my_union": 1010([
 			"int",
 			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) }
 
-	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
 	}
 
@@ -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.
 // 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.
 // 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}
-	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.
 // 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
 
 	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 {
 		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 {
@@ -97,11 +97,14 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 		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 {
-	case runtime.Type_Info_Named:
+	case runtime.Type_Info_Named, runtime.Type_Info_Enum, runtime.Type_Info_Bit_Field:
 		unreachable()
 
 	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
+
+		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 {
 			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
 
 	case runtime.Type_Info_Enumerated_Array:
 		// index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum)
 		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 {
 			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
 		
@@ -246,9 +269,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 		array := (^mem.Raw_Dynamic_Array)(v.data)
 		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 {
 			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
 
@@ -260,9 +293,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc :=  #caller_location) -> (e
 
 		array := (^mem.Raw_Slice)(v.data)
 		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 {
 			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
 
@@ -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})
 
-	case runtime.Type_Info_Enum:
-		return marshal_into(e, any{v.data, info.base.id})
-
 	case runtime.Type_Info_Bit_Set:
 		// Store bit_set as big endian just like the protocol.
 		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.
-// 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)
 
 @(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,
 		 // 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:
 		switch &dst in v {
@@ -520,9 +520,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 
 	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 {
 			return _unsupported(v, hdr)
 		}
@@ -534,9 +532,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 
 	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 {
 			return _unsupported(v, hdr)
 		}
@@ -548,9 +544,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 
 	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 {
 			return _unsupported(v, hdr)
 		}
@@ -570,9 +564,7 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header
 		return
 	
 	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 {
 			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
 		unknown := length == -1
 		fields := reflect.struct_fields_zipped(ti.id)
-	
+
 		for idx := 0; idx < len(fields) && (unknown || idx < length); idx += 1 {
 			// Decode key, keys can only be strings.
 			key: string
@@ -646,7 +638,7 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
 				key = keyv
 			}
 			defer delete(key, context.temp_allocator)
-			
+
 			// Find matching field.
 			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
 }
 
-// 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) {
 	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.
 // 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)
 read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) {
 	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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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':
 		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

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

@@ -25,7 +25,7 @@ Marshal_Options :: struct {
 	spec: Specification,
 
 	// Use line breaks & tabs/spaces
-	pretty: bool, 
+	pretty: bool,
 
 	// Use spaces for indentation instead of tabs
 	use_spaces: bool,
@@ -34,7 +34,7 @@ Marshal_Options :: struct {
 	spaces: int,
 
 	// 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.
 	//
@@ -138,7 +138,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 		// allow uints to be printed as hex
 		if opt.write_uint_as_hex && (opt.spec == .JSON5 || opt.spec == .MJSON) {
 			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 })
 
 			case:
@@ -239,7 +239,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 	case runtime.Type_Info_Array:
 		opt_write_start(w, opt, '[') or_return
 		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)
 			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:
 		opt_write_start(w, opt, '[') or_return
 		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)
 			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
 		array := cast(^mem.Raw_Dynamic_Array)v.data
 		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)
 			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
 		slice := cast(^mem.Raw_Slice)v.data
 		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)
 			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 {
 					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
 
 					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 })
 
 				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
 					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,
 			     runtime.Type_Info_Multi_Pointer,
 			     runtime.Type_Info_Procedure:
-			     	return (^rawptr)(v.data)^ == nil
+				return (^rawptr)(v.data)^ == nil
 			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:
-			     	return (^runtime.Raw_Slice)(v.data).len == 0
+				return (^runtime.Raw_Slice)(v.data).len == 0
 			case runtime.Type_Info_Union,
 			     runtime.Type_Info_Bit_Set,
 			     runtime.Type_Info_Soa_Pointer:
 				return reflect.is_nil(v)
 			case runtime.Type_Info_Map:
-			     	return (^runtime.Raw_Map)(v.data).len == 0
+				return (^runtime.Raw_Map)(v.data).len == 0
 			}
 			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) {
 			ti := runtime.type_info_base(type_info_of(v.id))
 			info := ti.variant.(runtime.Type_Info_Struct)
+			first_iteration := true
 			for name, i in info.names {
 				omitempty := false
 
@@ -424,7 +425,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 					continue
 				}
 
-				opt_write_iteration(w, opt, i) or_return
+				opt_write_iteration(w, opt, first_iteration) or_return
+				first_iteration = false
 				if json_name != "" {
 					opt_write_key(w, opt, json_name) or_return
 				} 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
-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 {
-	case .JSON, .JSON5: 
-		if iteration > 0 {
+	case .JSON, .JSON5:
+		if !first_iteration {
 			io.write_byte(w, ',') or_return
 
 			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
 
-	case .MJSON: 
-		if iteration > 0 {
+	case .MJSON:
+		if !first_iteration {
 			// on pretty no commas necessary
 			if opt.pretty {
 				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)
 
 		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 {
-	 	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
 }

+ 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
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 advance_rune :: proc(t: ^Tokenizer) {
 	#no_bounds_check {
 		/*
@@ -170,7 +170,7 @@ peek_byte :: proc(t: ^Tokenizer, offset := 0) -> byte {
 	return 0
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 skip_whitespace :: proc(t: ^Tokenizer) {
 	for {
 		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 {
 	if r < utf8.RUNE_SELF {
 		switch r {
@@ -296,7 +296,7 @@ skip_cdata :: proc(t: ^Tokenizer) -> (err: Error) {
 	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) {
 	err = .None
 
@@ -414,4 +414,4 @@ scan :: proc(t: ^Tokenizer, multiline_string := false) -> Token {
 		lit = string(t.src[offset : t.offset])
 	}
 	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) {
 	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
 //
@@ -368,6 +368,25 @@ caprintf :: proc(format: string, args: ..any, newline := false) -> cstring {
 caprintfln :: proc(format: string, args: ..any) -> cstring {
 	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
 //
 // *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_rune(fi.writer, verb, &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)
-		fmt_value(fi, fi.arg, 'v')
+		fmt_value(fi, arg, 'v')
 	} else {
 		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
-	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)
 	prev_zero := fi.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
-	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)
 
 	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.
 	copy(buf[len(str):], units[off:off+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:] 
 		}
 	}
@@ -1441,13 +1460,10 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
 				if !fi.minus {
 					io.write_string(fi.writer, s, &fi.n)
 				}
-			}
-			else {
+			} else {
 				io.write_string(fi.writer, s, &fi.n)
 			}
-		}
-		else
-		{
+		} else {
 			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 {
 				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
 				}
 				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.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)
 	}
 	defer {
-		if hash {
+		if !is_soa && hash && !is_empty {
 			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)
@@ -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_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 {
-				if hash {
+				if hash && !is_empty {
 					fi.indent -= 1
 					fmt_write_indent(fi)
 					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 && n > 0 {
+			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
+		}
 	} else {
 		field_count := -1
 		for name, i in info.names {
@@ -2687,7 +2709,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 							return
 						}
 						if fi.indirection_level < 1 {
-						  	fi.indirection_level += 1
+							fi.indirection_level += 1
 							defer fi.indirection_level -= 1
 							io.write_byte(fi.writer, '&')
 							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_Map:
 					if fi.indirection_level < 1 {
-					  	fi.indirection_level += 1
+						fi.indirection_level += 1
 						defer fi.indirection_level -= 1
 						io.write_byte(fi.writer, '&', &fi.n)
 						fmt_value(fi, a, verb)

+ 4 - 4
core/hash/crc.odin

@@ -1,6 +1,6 @@
 package hash
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc64_ecma_182 :: proc "contextless" (data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check {
 	result = seed
 	#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.
 	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 {
 	data := data
 	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
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 crc64_iso_3306 :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check {
 
 	result := seed
@@ -738,4 +738,4 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u
 	0x9fc0, 0x9e70, 0x9ca0, 0x9d10, 
 	0x9480, 0x9530, 0x97e0, 0x9650, 
 	0x9240, 0x93f0, 0x9120, 0x9090,
-}
+}

+ 1 - 1
core/hash/crc32.odin

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

+ 11 - 11
core/hash/hash.odin

@@ -3,7 +3,7 @@ package hash
 import "core:mem"
 import "base:intrinsics"
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 adler32 :: proc "contextless" (data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
 
 	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)
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 djb2 :: proc "contextless" (data: []byte, seed := u32(5381)) -> u32 {
 	hash: u32 = seed
 	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
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv32_no_a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	h: u32 = seed
 	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
 
 // 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 {
 	h: u64 = seed
 	for b in data {
@@ -94,7 +94,7 @@ fnv64_no_a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325))
 	}
 	return h
 }
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv32a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	h: u32 = seed
 	for b in data {
@@ -103,7 +103,7 @@ fnv32a :: proc "contextless" (data: []byte, seed := u32(0x811c9dc5)) -> u32 {
 	return h
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 fnv64a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
 	h: u64 = seed
 	for b in data {
@@ -112,7 +112,7 @@ fnv64a :: proc "contextless" (data: []byte, seed := u64(0xcbf29ce484222325)) ->
 	return h
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	hash: u32 = seed
 	for b in data {
@@ -126,7 +126,7 @@ jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	return hash
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	c1_32: u32 : 0xcc9e2d51
 	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
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur64a :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	m :: 0xc6a4a7935bd1e995
 	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
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 murmur64b :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	m :: 0x5bd1e995
 	r :: 24
@@ -286,7 +286,7 @@ murmur64b :: proc "contextless" (data: []byte, seed := u64(0x9747b28c)) -> u64 {
 	return u64(h1)<<32 | u64(h2)
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 sdbm :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
 	hash: u32 = seed
 	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) {
 	return ((x << r) | (x >> (32 - r)))
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH_rotl64 :: #force_inline proc(x, r: u64) -> (res: u64) {
 	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) {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 		#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) {
 	if XXH_FORCE_MEMORY_ACCESS == 2 || alignment == .Aligned {
 		#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)
 		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
 	@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) {
 	t := u128(lhs) * u128(rhs)
 	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) {
 	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
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_avalanche :: #force_inline proc(h64: xxh_u64) -> (res: xxh_u64) {
 	res = XXH_xorshift_64(h64, 37)
 	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
 	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) {
 	/* this mix is inspired by Pelle Evensen's rrmxmx */
 	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).
 */
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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. */
 	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) {
 	length := len(input)
 	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) {
 	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
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_0to16_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
 	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.
 */
-@(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) {
 	acc128 := XXH128_hash_t{
 		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) {
 	length := len(input)
 
@@ -323,7 +323,7 @@ XXH3_len_17to128_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh
 	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) {
 	length := len(input)
 
@@ -379,7 +379,7 @@ XXH3_INIT_ACC :: [XXH_ACC_NB]xxh_u64{
 
 XXH_SECRET_MERGEACCS_START :: 11
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_hashLong_128b_internal :: #force_inline proc(
 			input: []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.
  */
-@(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) {
 	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.
  */
-@(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) {
 	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(
 								input: []u8, seed: xxh_u64, secret: []u8,
 								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.
  */
- @(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) {
 	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)
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128bits_internal :: #force_inline proc(
 	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   === */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) {
 	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) {
 	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) {
 	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.
 	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) {
 	length := u32(len(input))
 	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) {
 	length := u32(len(input))
 	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) {
 	length := u64(len(input))
 	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) {
 	length := u64(len(input))
 	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
 	about strength.
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_mix16B :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	input_lo := XXH64_read64(input[0:])
 	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. */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_len_17to128_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u64) {
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	length := len(input)
@@ -665,7 +665,7 @@ XXH3_MIDSIZE_MAX         :: 240
 XXH3_MIDSIZE_STARTOFFSET :: 3
 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) {
 	assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
 	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_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) {
 	v := 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
 
 /* scalar variants - universal */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) {
 	xacc    := acc     /* presumed aligned */
 	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) {
 	xacc    := acc     /* presumed aligned */
 	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) {
 	#assert((XXH_SECRET_DEFAULT_SIZE & 15) == 0)
 
@@ -791,7 +791,7 @@ XXH_PREFETCH_DIST :: 320
  * Loops over XXH3_accumulate_512().
  * Assumption: nbStripes will not overflow the secret size
  */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_accumulate :: #force_inline proc(
 	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,
 	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) {
 	return XXH_mul_64_to_128_fold_64(
 		acc[0] ~ XXH64_read64(secret),
 		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) {
 	result64 := start
 	#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)
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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) {
 
@@ -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.
 */
-@(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) {
 	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,
 	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) {
 	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
 	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 {
 		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.
 */
-@(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) {
 	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)
 
-@(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) {
 	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   === */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH3_64_default :: proc(input: []u8) -> (hash: xxh_u64) {
 	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) {
 	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) {
 	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_5 :: 0x165667B1     /*!< 0b00010110010101100110011110110001 */
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_round :: #force_inline proc(seed, input: XXH32_hash) -> (res: XXH32_hash) {
 	seed := seed
 
@@ -53,7 +53,7 @@ XXH32_round :: #force_inline proc(seed, input: XXH32_hash) -> (res: XXH32_hash)
 /*
 	Mix all bits
 */
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 XXH32_avalanche :: #force_inline proc(h32: u32) -> (res: u32) {
 	h32 := h32
 
@@ -65,7 +65,7 @@ XXH32_avalanche :: #force_inline proc(h32: u32) -> (res: u32) {
 	return h32
 }
 
-@(optimization_mode="speed")
+@(optimization_mode="favor_size")
 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) {
 		#no_bounds_check b := u32(buf[0])
@@ -143,7 +143,7 @@ XXH32_finalize :: #force_inline proc(h32: u32, buf: []u8, alignment: Alignment)
 	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) {
 	buf := 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) {
 	h := (^u32be)(&canonical.digest)^
 	return XXH32_hash(h)
-}
+}

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