-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvariables.fs
301 lines (267 loc) · 6.46 KB
/
variables.fs
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
require cstrarrays.fs
require help-words.fs
require lib.fs
require struct-array.fs
struct
cell% field var-name-data
cell% field var-name-size
cell% field var-value-data
cell% field var-value-size
end-struct var%
: var-free ( var -- )
dup var-name-data @ free drop
var-value-data @ free drop ;
: var-set-name ( c-addrN uN var -- )
>r
\ We assume that the name is only set once.
dup chars allocate throw
dup r@ var-name-data !
over r> var-name-size !
swap chars move ;
: var-get-name ( var -- c-addrN uN )
dup var-name-data @ swap var-name-size @ ;
: var-set ( c-addrV uV var -- )
>r
r@ var-value-data @ free drop
0 r@ var-value-data ! \ to prevent double free
0 r@ var-value-size ! \ to prevent double free
dup chars allocate throw
dup r@ var-value-data !
over r> var-value-size !
swap chars move ;
: var-get ( var -- c-addrV uV )
dup var-value-data @ swap var-value-size @ ;
: var-str-deepcopy ( c-addrV uV c-addrN uN -- c-addrV2 uV2 c-addrN2 uN2 )
dup chars allocate throw
swap 2dup >r >r
move
dup chars allocate dup if
r> r> drop free drop
endif throw
swap 2dup >r >r
move
r> r> r> r> ;
struct
cell% field var-list-next
cell% field var-list-table
cell% field var-list-vars
end-struct var-list%
: var-list-init ( w next -- list )
var-list% %allocate throw >r
r@ var-list-next !
r@ var-list-table !
var% ['] struct-array-init catch dup if
r> free drop
endif throw
r@ var-list-vars !
r> ;
: var-list-free ( list -- )
dup 0<> if
assert( dup var-list-vars @ 0<> )
dup var-list-vars @
['] var-free over struct-array-foreach
struct-array-free
endif
free drop ;
: var-list-find-in-table ( c-addrN uN list -- var )
assert( dup var-list-vars @ 0<> )
assert( dup var-list-table @ 0<> )
var-list-table @ search-wordlist if
execute @
else
0
endif ;
: var-list-find-in-vars ( c-addrN uN list -- var )
assert( dup var-list-vars @ 0<> )
var-list-vars @
dup struct-array-size @ 0 u+do
3dup i swap struct-array-i
dup var-name-data @ swap var-name-size @
str= if
i swap 2nip struct-array-i
unloop
exit
endif
loop 2drop drop 0 ;
: var-list-find ( c-addrN uN list -- var )
assert( dup var-list-vars @ 0<> )
dup var-list-table @ 0= if
var-list-find-in-vars
else
var-list-find-in-table
endif ;
: var-link-from-table ( table var -- )
swap
2dup swap var-get-name rot search-wordlist 0= if
over var-get-name nextname
get-current over set-current
variable
set-current
over var-get-name rot search-wordlist
assert( dup 0<> ) drop
else
nip
endif
execute ! ;
: var-list-put-new ( c-addrV uV c-addrN uN list -- )
>r
var% %allot >r
0 r@ var-value-data !
0 r@ var-value-size !
r@ var-set-name
r@ var-set
r> r@ var-list-vars @ ['] struct-array-append catch
var% -1 * %allot drop
throw
r> dup var-list-table @ 0<> if
dup var-list-table @ swap var-list-vars @ ['] var-link-from-table swap
struct-array-foreach-with-data
else
drop
endif ;
: var-list-put ( c-addrV uV c-addrN uN list -- )
assert( dup var-list-vars @ 0<> )
3dup var-list-find dup 0= if
drop var-list-put-new
else
>r 3drop r> var-set
endif ;
: var-list-get ( c-addrN uN list -- c-addrV uV -1 | 0 )
assert( dup var-list-vars @ 0<> )
var-list-find dup 0= if
drop 0
else
var-get -1
endif ;
: var-copy-to-list ( list var -- )
swap >r
dup var-get
rot var-get-name
var-str-deepcopy
2over 2over drop nip
r> rot rot >r >r
['] var-list-put catch dup if
r> free drop
r> free drop
endif throw
r> r> 2drop ;
: var-list-merge ( listS listD -- )
assert( dup var-list-vars @ 0<> )
assert( over var-list-vars @ 0<> )
swap var-list-vars @ ['] var-copy-to-list swap
struct-array-foreach-with-data ;
: var-export ( var -- )
dup var-get rot var-get-name putenv ;
: var-list-export ( list -- )
assert( dup var-list-vars @ 0<> )
var-list-vars @ ['] var-export swap
struct-array-foreach ;
: var-store-envp ( a-addr var -- )
\ get variable contents and store as C string
dup var-get rot var-get-name >env-c-string ( a-addr c-addr -- )
\ save address of C string in array
over @ tuck ! ( a-addr a-addr -- )
\ increase array index and store
cell+ swap ! ;
: var-list-to-envp ( list -- a-addr )
var-list-vars @ dup struct-array-size @ ( arr u -- )
alloc-argv dup >r ( arr aN; r: aN -- )
swap >r sp@ ['] var-store-envp r> ( aN a-aN xt arr; r: aN -- )
['] struct-array-foreach-with-data catch dup if
r> free-argv
endif throw ( aNn; r: aN -- )
drop r> ;
: envp-to-var-list ( a-addr -- list )
0 0 var-list-init >r
begin
dup @ dup while
['] env-c-string> catch dup if
r> var-list-free
endif throw
['] var-str-deepcopy catch dup if
r> var-list-free
endif throw ( a-addr c-addrV uV c-addrN uN; r: list -- )
2over 2over drop nip
r@ rot rot >r >r ( a-addr c-addrV uV c-addrN uN list;
r: list c-addrN c-addrV -- )
['] var-list-put catch dup if
r> free drop
r> free drop
r> var-list-free
endif throw
r> r> 2drop
cell+
repeat 2drop r> ;
: var-list-make-envp ( list -- a-addr )
environ> envp-to-var-list dup >r
['] var-list-merge catch dup if
r> var-list-free
endif throw
r@ ['] var-list-to-envp catch
r> var-list-free
throw ;
\ if you free this and stored env vars the environ array will be fucked
table 0 var-list-init constant variables-main
variable variables-head
variables-main variables-head !
: var-push ( list -- )
variables-head @ over var-list-next !
variables-head ! ;
: var-pop ( -- list )
variables-head @ var-list-next @
assert( dup 0<> )
variables-head @
swap variables-head ! ;
: var-load ( c-addr u -- c-addr u )
assert( dup 0<> )
variables-head @
begin
3dup var-list-get 0= while
var-list-next @
dup 0= if
\ not found
drop
getenv
exit
endif
repeat
\ found
>r >r 3drop r> r> ;
: var-store ( c-addrV uV c-addrN uN -- )
assert( dup 0<> )
assert( variables-main 0<> )
assert( variables-head @ 0<> )
0 >r
variables-head @ variables-main = if
2dup getenv over 0<> if
r> drop
2over >r >r
>r >r -1 >r
2over 2over putenv
else
2drop
endif
endif
variables-head @ ['] var-list-put catch dup if
r> if
r> r> r> r> ['] putenv catch drop
endif
else
r> if r> r> r> r> 2drop 2drop endif
endif throw ;
: var-store-var ( var -- )
dup var-get
rot var-get-name
var-str-deepcopy
2over 2over drop nip >r >r
['] var-store catch dup if
r> free drop
r> free drop
endif throw
r> r> 2drop ;
: var-collapse ( list -- )
variables-head @ dup variables-main = if
drop ['] var-store-var swap var-list-vars @
struct-array-foreach
exit
endif var-list-merge ;