Allow compiling with -vet -vet-tabs -strict-style -vet-style -vet-cast -warnings-as-errors -disallow-do

Support the same strict flags as used throughout the CI tests.
This commit is contained in:
Jeroen van Rijn
2026-03-09 16:47:53 +01:00
parent 3f330752cd
commit 7b79f28522
4 changed files with 133 additions and 177 deletions

View File

@@ -4,7 +4,7 @@ package unicode
------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------
*/
/*
/*
This file is generated from UnicodeData.txt and PropList.txt. These files
are part of the Unicode Database (UCD) and are covered by the license
listed further down. They may be downloaded from the following locations;
@@ -15,17 +15,17 @@ package unicode
------------------------------------------------------------------------------
UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2026 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
@@ -36,19 +36,19 @@ package unicode
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written

View File

@@ -1,7 +1,6 @@
package ucd
import "core:fmt"
import path "core:path/filepath"
import "core:os"
import "core:strings"
import "base:runtime"
@@ -26,16 +25,12 @@ Inputs:
- name: Prefix to add to any array that is written to `writer`
- range: The Dynamic_Range to format and write to writer.
*/
write_range_arrays :: proc(
writer: io.Writer,
name: string,
range : Dynamic_Range,
) -> int {
write_range_arrays :: proc(writer: io.Writer, name: string, range: Dynamic_Range) -> int {
n_written : int
if len(range.single_16) > 0 {
if len(range.single_16) > 0 {
n_written += fmt.wprintln(writer, "@(rodata)")
n_written += fmt.wprintf(writer, "%s_singles16 := [?]u16{{", name)
line_length := 100
line_length := 100
for v in range.single_16 {
str_buffer : [32]byte
str := fmt.bprintf(str_buffer[:], " 0x%4X,",v)
@@ -52,7 +47,7 @@ write_range_arrays :: proc(
}
n_written += fmt.wprintln(writer, "\n}\n")
}
if len(range.ranges_16) > 0 {
n_written += fmt.wprintln(writer, "@(rodata)")
n_written += fmt.wprintfln(writer, "%s_ranges16 := [?]u16{{", name)
@@ -70,7 +65,7 @@ write_range_arrays :: proc(
str_buffer : [32]byte
str := fmt.bprintf(str_buffer[:], " 0x%4X,",v)
if line_length + len(str) > 80 {
if line_length + len(str) > 80 {
n_written += fmt.wprint(writer, "\n")
line_length = fmt.wprintf(writer, "\t0x%4X,",v)
n_written += line_length
@@ -95,12 +90,7 @@ write_range_arrays :: proc(
return n_written
}
write_range :: proc(
writer: io.Writer,
name: union{string,
General_Category},
range: Dynamic_Range,
) -> (n_written: int) {
write_range :: proc(writer: io.Writer, name: union{string, General_Category}, range: Dynamic_Range) -> (n_written: int) {
buffer: [128]byte
str: string
@@ -124,16 +114,16 @@ write_range :: proc(
n_written += fmt.wprintfln(writer, "%s_ranges := Range{{", str)
if len(range.single_16) > 0 {
n_written += fmt.wprintfln(writer, "\tsingle_16 = %s_singles16[:],", str)
n_written += fmt.wprintfln(writer, "\tsingle_16 = %s_singles16[:],", str)
}
if len(range.ranges_16) > 0 {
n_written += fmt.wprintfln(writer, "\tranges_16 = %s_ranges16[:],", str)
n_written += fmt.wprintfln(writer, "\tranges_16 = %s_ranges16[:],", str)
}
if len(range.single_32) > 0 {
n_written += fmt.wprintfln(writer, "\tsingle_32 = %s_singles32[:],", str)
n_written += fmt.wprintfln(writer, "\tsingle_32 = %s_singles32[:],", str)
}
if len(range.ranges_32) > 0 {
n_written += fmt.wprintfln(writer, "\tranges_32 = %s_ranges32[:],", str)
n_written += fmt.wprintfln(writer, "\tranges_32 = %s_ranges32[:],", str)
}
n_written += fmt.wprintln(writer, "}\n")
@@ -145,7 +135,7 @@ GENERATED :: `/*
*/
`
MESSAGE :: `/*
MESSAGE :: `/*
This file is generated from UnicodeData.txt and PropList.txt. These files
are part of the Unicode Database (UCD) and are covered by the license
listed further down. They may be downloaded from the following locations;
@@ -156,17 +146,17 @@ MESSAGE :: `/*
------------------------------------------------------------------------------
UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2026 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
@@ -177,19 +167,19 @@ MESSAGE :: `/*
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
@@ -217,9 +207,7 @@ main :: proc() {
context.logger = log.create_console_logger()
defer log.destroy_console_logger(context.logger)
ucd_path, _ := path.join({ODIN_ROOT,
"tests","core","assets","UCD","UnicodeData.txt"}, context.allocator)
defer delete(ucd_path)
ucd_path := ODIN_ROOT + "tests/core/assets/UCD/UnicodeData.txt"
unicode_data, ucd_err := load_unicode_data(ucd_path)
if ucd_err != nil {
@@ -234,39 +222,34 @@ main :: proc() {
defer destroy_dynamic_range(extra_digits)
proplist_path, _ := path.join({ODIN_ROOT,
"tests","core","assets","UCD","PropList.txt"}, context.allocator)
defer delete(proplist_path)
proplist, proplist_err := load_protperty_list(proplist_path)
proplist_path := ODIN_ROOT + "tests/core/assets/UCD/PropList.txt"
proplist, proplist_err := load_property_list(proplist_path)
if proplist_err != nil {
log.errorf("Error loading PropList.txt. %s", proplist_err)
return
}
defer destroy_protperty_list(proplist)
defer destroy_property_list(proplist)
sb := strings.builder_make_len_cap(0, 1024*32)
defer strings.builder_destroy(&sb)
writer := strings.to_writer(&sb)
sb := strings.builder_make_len_cap(0, 1024*32)
defer strings.builder_destroy(&sb)
writer := strings.to_writer(&sb)
fmt.wprintfln(writer, "package unicode\n")
fmt.wprintln(writer, GENERATED)
fmt.wprintln(writer, MESSAGE)
Range_Type :: "Range :: struct {\n" +
"\tsingle_16 : []u16,\n" +
"\tranges_16 : []u16,\n" +
"\tsingle_32 : []i32,\n" +
"\tranges_32 : []i32,\n" +
"}\n"
fmt.wprintfln(writer, "%s", Range_Type)
fmt.wprintfln(writer, "package unicode\n")
fmt.wprintln(writer, GENERATED)
fmt.wprintln(writer, MESSAGE)
Range_Type :: "Range :: struct {\n" +
"\tsingle_16 : []u16,\n" +
"\tranges_16 : []u16,\n" +
"\tsingle_32 : []i32,\n" +
"\tranges_32 : []i32,\n" +
"}\n"
fmt.wprintfln(writer, "%s", Range_Type)
//List of the general categories to skip when generating the code for
//core/unicode/generated.txt.
//core/unicode/generated.txt.
to_exclude := [?]General_Category{
.Cc, // Control, a C0 or C1 control code
.Cf, // Format, a format control character
@@ -299,27 +282,23 @@ main :: proc() {
.Zp, // Paragraph_Separator, U+2029 PARAGRAPH SEPARATOR only
//.Zs, // Space_Separator, a space character (of various non-zero widths)
}
write_loop : for gc, i in general_category_ranges {
for excluded in to_exclude {
if i == excluded do continue write_loop
}
write_range(writer, i, gc)
}
write_range(writer, "extra_digits", extra_digits )
write_range(writer,"other_lowercase", proplist[.Other_Lowercase])
write_range(writer,"other_uppercase", proplist[.Other_Uppercase])
write_loop : for gc, i in general_category_ranges {
for excluded in to_exclude {
if i == excluded {
continue write_loop
}
}
write_range(writer, i, gc)
}
file_name, _ := path.join({ODIN_ROOT, "core", "unicode", "generated.odin"}, context.allocator)
defer delete(file_name)
str := strings.to_string(sb)
write_range(writer, "extra_digits", extra_digits)
write_range(writer, "other_lowercase", proplist[.Other_Lowercase])
write_range(writer, "other_uppercase", proplist[.Other_Uppercase])
write_error := os.write_entire_file_from_string(file_name, str)
if write_error != nil {
log.errorf("Error writting %s. %s", file_name, write_error)
}
}
file_name := ODIN_ROOT + "core/unicode/generated.odin"
if write_error := os.write_entire_file_from_string(file_name, strings.to_string(sb)); write_error != nil {
log.errorf("Error %v writing %q", write_error, file_name)
}
}

View File

@@ -214,55 +214,53 @@ string_to_paired_bracket_type :: proc "contextless"(str: string) -> Paired_Brack
string_to_bidi_class :: proc "contextless"(str: string) -> Bidi_Class {
switch str {
case "AL":
case "AL":
return .AL
case "AN":
case "AN":
return .AN
case "B":
case "B":
return .B
case "BN":
case "BN":
return .BN
case "CS":
case "CS":
return .CS
case "EN":
case "EN":
return .EN
case "ES":
case "ES":
return .ES
case "ET":
case "ET":
return .ET
case "FSI":
case "FSI":
return .FSI
case "L":
case "L":
return .L
case "LRE":
case "LRE":
return .LRE
case "LRI":
case "LRI":
return .LRI
case "LRO":
case "LRO":
return .LRO
case "NSM":
case "NSM":
return .NSM
case "ON":
case "ON":
return .ON
case "PDF":
case "PDF":
return .PDF
case "PDI":
case "PDI":
return .PDI
case "R":
case "R":
return .R
case "RLE":
case "RLE":
return .RLE
case "RLI":
case "RLI":
return .RLI
case "RLO":
case "RLO":
return .RLO
case "S":
case "S":
return .S
case "WS":
case "WS":
return .WS
case:
// TODO: Add error for this
unreachable()
case: unreachable() // TODO: Add error for this
}
}

View File

@@ -2,20 +2,12 @@ package ucd
import "core:strings"
import "core:os"
// import "core:fmt"
load_unicode_data :: proc(
filename: string,
allocator := context.allocator,
) -> (unicode_data : Unicode_Data, err: Error) {
data, os_error := os.read_entire_file(filename, context.temp_allocator)
if os_error != nil {
err = os_error
return
}
load_unicode_data :: proc(filename: string, allocator := context.allocator) -> (unicode_data: Unicode_Data, err: Error) {
data := os.read_entire_file(filename, context.temp_allocator) or_return
defer free_all(context.temp_allocator)
// line_iter := Line_Iterator{data = data }
first_cp: rune
str := string(data)
@@ -23,7 +15,7 @@ load_unicode_data :: proc(
line_loop: for _line in strings.split_lines_iterator(&str) {
defer line_no += 1
line, _, _ := strings.partition(_line, "#")
if len(line) == 0 do continue
if len(line) == 0 { continue }
// field_iter := Field_Iterator{line = line}
is_range := false
@@ -34,31 +26,29 @@ load_unicode_data :: proc(
num_6 : string
num_7 : string
nt := Numeric_Type.None
nv : Numberic_Value
field_num := 0
for field in strings.split_iterator(&line, ";") {
for _field in strings.split_iterator(&line, ";") {
defer field_num += 1
field := strings.trim_space(field)
field := strings.trim_space(_field)
switch field_num {
case 0: // Code point
cp = 0
for c in field {
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F') do break
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F') { break }
cp *= 16
cp += cast(rune)(c >= '0' && c <= '9') * cast(rune)(c - '0')
cp += cast(rune)(c >= 'A' && c <= 'F') * cast(rune)(c - 'A' + 10)
cp += (c - '0') if c >= '0' && c <= '9' else (c - 'A' + 10)
}
case 1: // Name
if len(field) > 9 && field[0] == '<' && strings.ends_with(transmute(string) field, ", First>") {
if len(field) > 9 && field[0] == '<' && strings.ends_with(field, ", First>") {
first_cp = cp
continue line_loop
}
if len(field) > 9 && field[0] == '<' && strings.ends_with(transmute(string) field, ", Last>") {
if len(field) > 9 && field[0] == '<' && strings.ends_with(field, ", Last>") {
name = strings.clone(field[1:len(field)-7], allocator)
is_range = true
} else {
@@ -67,27 +57,27 @@ load_unicode_data :: proc(
case 2: // General_Category
// NOTE: This is currently igorning a possible error it should probably be fixed
gc, _ = string_to_general_category(transmute(string)field)
gc, _ = string_to_general_category(field)
case 3: // Canonical_Combining_Class
case 4: // Bidi Class
case 5: // Decomposition_Type and Decomposition_Mapping
// Numeric_Type and Numberic_Value
case 6:
num_6 = transmute(string)field
num_6 = field
case 7:
num_7 = transmute(string)field
num_7 = field
case 8:
switch {
case num_6 != "" && num_7 != "" && transmute(string) field != "" :
case num_6 != "" && num_7 != "" && field != "" :
nt = .Decimal
case num_6 == "" && num_7 != "" && transmute(string) field != "" :
case num_6 == "" && num_7 != "" && field != "" :
nt = .Digit
case num_6 == "" && num_7 == "" && transmute(string) field != "" :
case num_6 == "" && num_7 == "" && field != "" :
nt = .Numeric
case:
@@ -154,12 +144,14 @@ gc_ranges :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (lst: [G
range.last = -1
}
range.first = transmute(rune) min(transmute(u32)range.first, transmute(u32)p.cp)
range.first = rune(min(u32(range.first), u32(p.cp)))
gc = p.gc
range.last = p.cp
case Char_Range:
if range.first != -1 do append_to_dynamic_range(&lst[gc], range, allocator)
if range.first != -1 {
append_to_dynamic_range(&lst[gc], range, allocator)
}
range.first = p.first_cp
range.last = p.last_cp
@@ -168,7 +160,9 @@ gc_ranges :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (lst: [G
range.last = -1
}
}
if range.first != -1 do append_to_dynamic_range(&lst[gc], range, allocator)
if range.first != -1 {
append_to_dynamic_range(&lst[gc], range, allocator)
}
return
}
@@ -194,14 +188,16 @@ extra_digits :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (Dyna
}
if exd_type {
range.first = transmute(rune) min(transmute(u32)range.first, transmute(u32)p.cp)
range.first = rune(min(u32(range.first), u32(p.cp)))
range.last = p.cp
}
case Char_Range:
exd_type := p.gc != .Nd && (p.nt == .Decimal || p.nt == .Digit)
if range.first != -1 do append_to_dynamic_range(&exd, range, allocator)
if range.first != -1 {
append_to_dynamic_range(&exd, range, allocator)
}
if exd_type {
range.first = p.first_cp
@@ -212,29 +208,28 @@ extra_digits :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (Dyna
range.last = -1
}
}
if range.first != -1 do append_to_dynamic_range(&exd, range, allocator)
if range.first != -1 {
append_to_dynamic_range(&exd, range, allocator)
}
return exd
}
/*
Data containted in the Unicode fiel PropList.txt
Data contained in the Unicode fiel PropList.txt
A `PropList` is the data containted in the Unicode Database (UCD) file
PropList.txt. It is created with the procedure `load_property_list` and
destroy with the procedure `destroy_property_list`.
A `Prop_List` is the data contained in the Unicode Database (UCD) file `PropList.txt`.
It is created with the procedure `load_property_list` and destroyed with the procedure `destroy_property_list`.
*/
PropList ::[PropList_Property]Dynamic_Range
Prop_List :: [PropList_Property]Dynamic_Range
/*
This function destroys a `PropList` created by `load_property_list`.
This function destroys a `Prop_List` created by `load_property_list`.
Inputs:
- props: The PropList to destroy
- props: The Prop_List to destroy
*/
destroy_protperty_list :: proc(
props: [PropList_Property]Dynamic_Range,
){
destroy_property_list :: proc(props: Prop_List) {
for r in props {
delete(r.ranges_16)
delete(r.ranges_32)
@@ -243,31 +238,18 @@ destroy_protperty_list :: proc(
}
}
import "core:fmt"
load_protperty_list :: proc (
filename : string,
allocator := context.allocator,
) -> (props: [PropList_Property]Dynamic_Range, err: Error) {
data, os_error := os.read_entire_file(filename, allocator)
if os_error != nil {
err = os_error
return
}
load_property_list :: proc(filename: string, allocator := context.allocator) -> (props: Prop_List, err: Error) {
data := os.read_entire_file(filename, allocator) or_return
defer delete(data)
line_iter := Line_Iterator{
data = data
}
str := string(data)
line_no := 1
for _line in strings.split_lines_iterator(&str) {
defer line_no += 1
line, _, _ := strings.partition(_line, "#")
if len(line) == 0 do continue
fmt.printfln("%d: %q", line_no, line)
if len(line) == 0 {
continue
}
is_range: bool
@@ -275,10 +257,9 @@ load_protperty_list :: proc (
prop: PropList_Property
i := 0
for field in strings.split_iterator(&line, ";") {
for _field in strings.split_iterator(&line, ";") {
defer i += 1
field := strings.trim_space(field)
fmt.printfln("%d: %q", i, field)
field := strings.trim_space(_field)
switch i {
case 0: // Code point or code point range
@@ -295,18 +276,16 @@ load_protperty_list :: proc (
}
if is_range {
rr.last *= 16
rr.last += cast(rune)(c >= '0' && c <= '9') * cast(rune)(c - '0')
rr.last += cast(rune)(c >= 'A' && c <= 'F') * cast(rune)(c - 'A' + 10)
rr.last += (c - '0') if (c >= '0' && c <= '9') else (c - 'A' + 10)
} else {
rr.first *= 16
rr.first += cast(rune)(c >= '0' && c <= '9') * cast(rune)(c - '0')
rr.first += cast(rune)(c >= 'A' && c <= 'F') * cast(rune)(c - 'A' + 10)
rr.first += (c - '0') if (c >= '0' && c <= '9') else (c - 'A' + 10)
rr.last = rr.first
}
}
case 1:
prop, err = string_to_proplist_property(transmute(string)field)
prop, err = string_to_proplist_property(field)
if err != nil {
return
}