gen/
.clang-format
570 B
.gitignore
30 B
.gitsigners
112 B
LICENSE
1.1 KiB
Makefile
911 B
README
1.8 KiB
ast.c
5.0 KiB
ast.h
15.1 KiB
desugar.c
23.1 KiB
desugar.h
286 B
gen.c
108.5 KiB
gen.h
4.9 KiB
io.c
1.1 KiB
io.h
444 B
limits.h
1.3 KiB
module.c
10.0 KiB
module.h
2.2 KiB
options.c
1.4 KiB
options.h
472 B
parser.c
68.3 KiB
parser.h
942 B
radiance.c
3.7 KiB
ralloc.c
2.0 KiB
ralloc.h
1.1 KiB
resolver.c
109.7 KiB
resolver.h
5.6 KiB
riscv.c
12.0 KiB
riscv.h
12.0 KiB
scanner.c
10.2 KiB
scanner.h
3.2 KiB
strings.c
2.6 KiB
strings.h
407 B
symtab.c
5.7 KiB
symtab.h
4.6 KiB
types.h
1.0 KiB
util.h
1.5 KiB
strings.c
raw
| 1 | #include <string.h> |
| 2 | |
| 3 | #include "strings.h" |
| 4 | #include "types.h" |
| 5 | |
| 6 | /* Global string interning system */ |
| 7 | static struct { |
| 8 | char strings[MAX_STRINGS][MAX_STRING_LEN]; |
| 9 | usize nstrings; |
| 10 | bool initialized; |
| 11 | } table = { 0 }; |
| 12 | |
| 13 | /* Initialize the global string interning system */ |
| 14 | void strings_init(void) { |
| 15 | table.nstrings = 0; |
| 16 | table.initialized = true; |
| 17 | } |
| 18 | |
| 19 | /* Process escape sequences in a string */ |
| 20 | static usize escape(const char *src, usize src_len, char *dst, usize dst_size) { |
| 21 | usize dst_idx = 0; |
| 22 | |
| 23 | for (usize i = 0; i < src_len && dst_idx < dst_size - 1; i++) { |
| 24 | if (src[i] == '\\' && i + 1 < src_len) { |
| 25 | switch (src[i + 1]) { |
| 26 | case 'n': |
| 27 | dst[dst_idx++] = '\n'; |
| 28 | i++; /* Skip the next character */ |
| 29 | break; |
| 30 | case 't': |
| 31 | dst[dst_idx++] = '\t'; |
| 32 | i++; |
| 33 | break; |
| 34 | case 'r': |
| 35 | dst[dst_idx++] = '\r'; |
| 36 | i++; |
| 37 | break; |
| 38 | case '\\': |
| 39 | dst[dst_idx++] = '\\'; |
| 40 | i++; |
| 41 | break; |
| 42 | case '"': |
| 43 | dst[dst_idx++] = '"'; |
| 44 | i++; |
| 45 | break; |
| 46 | case '0': |
| 47 | dst[dst_idx++] = '\0'; |
| 48 | i++; |
| 49 | break; |
| 50 | default: |
| 51 | /* Unknown escape sequence, keep the backslash */ |
| 52 | dst[dst_idx++] = src[i]; |
| 53 | break; |
| 54 | } |
| 55 | } else { |
| 56 | dst[dst_idx++] = src[i]; |
| 57 | } |
| 58 | } |
| 59 | dst[dst_idx] = '\0'; |
| 60 | |
| 61 | return dst_idx; |
| 62 | } |
| 63 | |
| 64 | /* Find an existing interned string */ |
| 65 | static const char *find(const char *str) { |
| 66 | for (usize i = 0; i < table.nstrings; i++) { |
| 67 | if (!strcmp(table.strings[i], str)) { |
| 68 | return table.strings[i]; |
| 69 | } |
| 70 | } |
| 71 | return NULL; |
| 72 | } |
| 73 | |
| 74 | /* Intern a raw string without escape sequence processing */ |
| 75 | static const char *strings_alloc_raw(const char *str) { |
| 76 | /* Check if already interned */ |
| 77 | const char *existing = find(str); |
| 78 | if (existing) { |
| 79 | return existing; |
| 80 | } |
| 81 | |
| 82 | char *slot = table.strings[table.nstrings++]; |
| 83 | strncpy(slot, str, MAX_STRING_LEN); |
| 84 | |
| 85 | return slot; |
| 86 | } |
| 87 | |
| 88 | /* Intern a string with escape sequence processing */ |
| 89 | const char *strings_alloc_len(const char *str, u16 len) { |
| 90 | /* Process escape sequences first */ |
| 91 | char escaped[MAX_STRING_LEN]; |
| 92 | escape(str, len, escaped, MAX_STRING_LEN); |
| 93 | |
| 94 | return strings_alloc_raw(escaped); |
| 95 | } |
| 96 | |
| 97 | /* Intern a string with escape sequence processing */ |
| 98 | const char *strings_alloc(const char *str) { |
| 99 | return strings_alloc_len(str, strlen(str)); |
| 100 | } |