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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
; an "identifier list" is a list of identifiers and 64-bit values associated with them.
; they are stored as
; null-terminated string
; 64-bit value (unaligned)
; ...
; null-terminated string
; 64-bit value (unaligned)
; 0 byte
function ident_list_create
argument nbytes
local list
list = malloc(nbytes)
return list
function ident_list_clear
argument list
*1list = 0
return
function ident_list_free
argument list
free(list)
return
function ident_list_len
argument list
local len
len = 0
:ilist_len_loop
if *1list == 0 goto ilist_len_ret
list = memchr(list, 0)
list += 9 ; skip null byte and value
len += 1
goto ilist_len_loop
:ilist_len_ret
return len
; idxth value stored in ident list, or 0 if idx >= length
function ident_list_value_at_index
argument list
argument idx
:ilist_vai_loop
if *1list == 0 goto return_0
list = memchr(list, 0)
list += 1
if idx <= 0 goto ilist_vai_ret
list += 8
idx -= 1
goto ilist_vai_loop
:ilist_vai_ret
return *8list
function ident_list_add
argument list
argument ident
argument value
:ilist_add_go_to_end_loop
if *1list == 0 goto ilist_add_found_end
list = memchr(list, 0)
list += 9 ; skip null byte and value
goto ilist_add_go_to_end_loop
:ilist_add_found_end
list = strcpy(list, ident)
list += 1
*8list = value ; UNALIGNED
list += 8
*1list = 0
return
; return the value associated with this identifier, or 0 if none is
function ident_list_lookup
argument list
argument ident
local b
:ilist_lookup_loop
if *1list == 0 goto return_0
b = str_equals(list, ident)
list = memchr(list, 0)
list += 9 ; skip null byte and value
if b == 0 goto ilist_lookup_loop
list -= 8 ; backtrack to value
return *8list ; UNALIGNED
; return a pointer to the value associated with ident, or 0 if none is
function ident_list_lookup_pointer
argument list
argument ident
local b
:ilist_lookup_pointer_loop
if *1list == 0 goto return_0
b = str_equals(list, ident)
list = memchr(list, 0)
list += 9 ; skip null byte and value
if b == 0 goto ilist_lookup_pointer_loop
list -= 8 ; backtrack to value
return list
; if list contains ident, change its value to `value`. otherwise, add ident with the given value.
function ident_list_set
argument list
argument ident
argument value
local p
p = ident_list_lookup_pointer(list, ident)
if p == 0 goto ident_list_set_add
*8p = value
return
:ident_list_set_add
ident_list_add(list, ident, value)
return
; if identifier in list, sets *pvalue to its value (if pvalue is not null) and returns 1
; otherwise, returns 0
function ident_list_lookup_check
argument list
argument ident
argument pvalue
local b
:ilist_lookcheck_loop
if *1list == 0 goto return_0
b = str_equals(list, ident)
list = memchr(list, 0)
list += 9 ; skip null byte and value
if b == 0 goto ilist_lookcheck_loop
if pvalue == 0 goto return_1
list -= 8 ; backtrack to value
*8pvalue = *8list
return 1
function ident_list_print
argument list
:ilist_print_loop
if *1list == 0 goto ilist_print_loop_end
puts(list)
putc(':)
putc(32)
list = memchr(list, 0)
list += 1
putnln(*8list)
list += 8
goto ilist_print_loop
:ilist_print_loop_end
return
function ident_list_printx64
argument list
:ilist_printx64_loop
if *1list == 0 goto ilist_printx64_loop_end
puts(list)
putc(':)
putc(32)
list = memchr(list, 0)
list += 1
putx64ln(*8list)
list += 8
goto ilist_printx64_loop
:ilist_printx64_loop_end
return
function ident_list_printx32
argument list
:ilist_printx32_loop
if *1list == 0 goto ilist_printx32_loop_end
puts(list)
putc(':)
putc(32)
list = memchr(list, 0)
list += 1
putx32ln(*8list)
list += 8
goto ilist_printx32_loop
:ilist_printx32_loop_end
return
|