main.ha (3819B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use ascii; 5 use bufio; 6 use fmt; 7 use io; 8 use os; 9 use strconv; 10 use strings; 11 12 type entry = struct { 13 name: str, 14 val: str, 15 idx: size, 16 }; 17 18 // Parses an oid database from stdin and writes the database as hare code to 19 // stdout. 20 export fn main() void = { 21 let oids = parse_oids(); 22 defer free_oids(oids); 23 24 fmt::println("// SPDX-License-Identifier: MPL-2.0\n" 25 "// (c) Hare authors <https://harelang.org>\n" 26 "// This is an auto generated file. Do not edit.\n" 27 "\n" 28 "use encoding::asn1;\n")!; 29 30 fmt::println("const _db = asn1::oiddb {")!; 31 32 write_db(os::stdout, oids)!; 33 34 fmt::println("\tnames = [")!; 35 for (let oid .. oids) { 36 fmt::printfln("\t\t\"{}\",", oid.name)!; 37 }; 38 fmt::println("\t],")!; 39 fmt::println("};\n")!; 40 41 fmt::println("// Database")!; 42 fmt::println("export const db = &_db;")!; 43 44 for (let i = 0z; i < len(oids); i += 1) { 45 let oid = &oids[i]; 46 fmt::println()!; 47 fmt::println("// id: ", oid.val)!; 48 fmt::println("// name:", oid.name)!; 49 fmt::print("export def ")!; 50 write_varname(os::stdout, oid.name)!; 51 fmt::printfln(": asn1::oid = {};", i)!; 52 }; 53 }; 54 55 fn parse_oids() []entry = { 56 let s = bufio::newscanner(os::stdin); 57 defer bufio::finish(&s); 58 let oids: []entry = []; 59 60 for (let line => bufio::scan_line(&s)!) { 61 if (line == "" || strings::hasprefix(line, '#')) { 62 continue; 63 }; 64 65 const p = strings::split(line, " "); 66 defer free(p); 67 const name = p[0]; 68 const val = p[len(p)-1]; 69 70 append(oids, entry { 71 name = strings::dup(name), 72 val = strings::dup(val), 73 ... 74 })!; 75 }; 76 77 return oids; 78 }; 79 80 fn free_oids(oids: []entry) void = { 81 for (let oid .. oids) { 82 free(oid.name); 83 free(oid.val); 84 }; 85 86 free(oids); 87 }; 88 89 fn write_db(h: io::handle, oids: []entry) (void | io::error) = { 90 fmt::print("\tlut = [")?; 91 92 const maxcols = 12z; 93 let idx = 0z; 94 95 for (let e &.. oids) { 96 e.idx = idx; 97 98 let der = oidtoder(e.val); 99 assert(len(der) <= 0xff); 100 insert(der[0], len(der): u8)!; 101 defer free(der); 102 103 for (let byte .. der) { 104 fmt::print(if (idx % maxcols == 0) "\n\t\t" else " ")?; 105 fmt::printf("0x{:.2x},", byte)?; 106 idx += 1; 107 }; 108 }; 109 fmt::println("\n\t],")?; 110 111 const maxcols = 9z; 112 fmt::print("\tindex = [")?; 113 for (let i = 0z; i < len(oids); i += 1) { 114 fmt::print(if (i % maxcols == 0) "\n\t\t" else " ")?; 115 fmt::printf("0x{:.4x},", oids[i].idx)?; 116 }; 117 fmt::println("\n\t],")?; 118 }; 119 120 fn oidtoder(oid: str) []u8 = { 121 let nums = oidtou64s(oid); 122 defer free(nums); 123 124 let der: []u8 = alloc([0...], 1)!; 125 assert(nums[0] <= 6); 126 assert(nums[1] < 40); 127 der[0] = nums[0]: u8 * 40 + nums[1]: u8; 128 let end = 1z; 129 130 for (let i = 2z; i < len(nums); i += 1) { 131 let n = nums[i]; 132 if (n == 0) { 133 insert(der[end], 0u8)!; 134 end = len(der); 135 continue; 136 }; 137 138 let first = true; 139 for (n > 0) { 140 let p: u8 = n: u8 & 0x7f; 141 n >>= 7; 142 if (first) { 143 first = false; 144 } else { 145 p |= 0x80; 146 }; 147 insert(der[end], p)!; 148 }; 149 150 end = len(der); 151 }; 152 153 return der; 154 }; 155 156 fn oidtou64s(oid: str) []u64 = { 157 let nums = strings::tokenize(oid, "."); 158 let intnums: []u64 = []; 159 160 for (let s => strings::next_token(&nums)) { 161 append(intnums, strconv::stou64(s)!)!; 162 }; 163 164 return intnums; 165 }; 166 167 fn write_varname(h: io::handle, name: str) (void | io::error) = { 168 // assume that names are in ascii 169 let i = strings::iter(name); 170 let prevlow = false; 171 for (let r => strings::next(&i)) { 172 let r = if (r == '-') { 173 prevlow = false; 174 yield '_'; 175 } else if (ascii::isdigit(r)) { 176 prevlow = true; 177 yield r; 178 } else if (ascii::isupper(r)) { 179 if (prevlow) { 180 fmt::fprint(h, "_")?; 181 prevlow = false; 182 }; 183 yield r; 184 } else if (ascii::islower(r)) { 185 prevlow = true; 186 yield ascii::toupper(r); 187 } else { 188 fmt::fatalf("Unexpected character in oid name: {}", r); 189 }; 190 191 fmt::fprint(h, r)?; 192 }; 193 };