RPA Toolkit
fcd90aefb614a0a3b15852bbb6c7faba69b7f81f
[rpatk.git] / rvm / rvmreg.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include "rlib/rmem.h"
22 #include "rvm/rvmreg.h"
23 #include "rlib/rref.h"
24
25
26 /*
27  * Recursively go over array data to unref any GC managed
28  * objects. We need this because when GC is destroying arrays,
29  * array's oncleanup might try to destroy the data, that should really
30  * be destroyed by the GC. To avoid any attempts the same data
31  * to be destroyed twice we remove the references of all GC managed
32  * data from the arrays and leave the destruction of such data to
33  * the GC.
34  */
35 void rvm_reg_array_unref_gcdata(robject_t *obj)
36 {
37         unsigned long i, size;
38         rvmreg_t *r;
39
40         if (obj->type == R_OBJECT_ARRAY) {
41                 rarray_t *array = (rarray_t*)obj;
42                 if ((size = r_array_length(array)) > 0) {
43                         /*
44                          * set the size to 0, to prevent circular references to come back here
45                          */
46                         r_array_setlength(array, 0);
47                         for (i = 0; i < size; i++) {
48                                 r = (rvmreg_t*) r_array_slot(array, i);
49                                 if (rvm_reg_tstflag(r, RVM_INFOBIT_ROBJECT)) {
50                                         robject_t *p = RVM_REG_GETP(r);
51                                         if (!r_list_empty(&p->lnk)) {
52                                                 /*
53                                                  * if this entry is robject_t that is on GC
54                                                  * list, it can be RVM_REG_CLEARed. It will be
55                                                  * cleaned up by the GC.
56                                                  */
57                                                 rvm_reg_array_unref_gcdata(p);
58                                                 RVM_REG_CLEAR(r);
59                                         }
60                                 }
61
62                         }
63                         /*
64                          * Restore the size
65                          */
66                         r_array_setlength(array, size);
67                 }
68         } else if (obj->type == R_OBJECT_CARRAY || obj->type == R_OBJECT_HARRAY) {
69                 rcarray_t *array = (rcarray_t*)obj;
70                 if (obj->type == R_OBJECT_HARRAY)
71                         array = ((rharray_t*)obj)->members;
72                 if ((size = r_carray_length(array)) > 0) {
73                         /*
74                          * set the size to 0, to prevent circular references to come back here
75                          */
76                         array->alloc_size = 0;
77                         for (i = 0; i < size; i++) {
78                                 r = (rvmreg_t*) r_carray_slot(array, i);
79                                 if (rvm_reg_tstflag(r, RVM_INFOBIT_ROBJECT)) {
80                                         robject_t *p = RVM_REG_GETP(r);
81                                         if (!r_list_empty(&p->lnk)) {
82                                                 /*
83                                                  * if this entry is robject_t that is on GC
84                                                  * list, it can be RVM_REG_CLEARed. It will be
85                                                  * cleaned up by the GC.
86                                                  */
87                                                 rvm_reg_array_unref_gcdata(p);
88                                                 RVM_REG_CLEAR(r);
89                                         }
90                                 }
91
92                         }
93                         /*
94                          * Restore the size
95                          */
96                         array->alloc_size = size;
97                 }
98         }
99 }
100
101
102 rvmreg_t rvm_reg_create_string_ansi(const char *s)
103 {
104         rvmreg_t r;
105         r_memset(&r, 0, sizeof(r));
106         RVM_REG_SETP(&r, r_string_create_from_ansistr(s));
107         RVM_REG_SETTYPE(&r, RVM_DTYPE_STRING);
108         RVM_REG_SETFLAG(&r, RVM_INFOBIT_ROBJECT);
109         return r;
110 }
111
112
113 rvmreg_t rvm_reg_create_string(const rstr_t *s)
114 {
115         rvmreg_t r;
116         r_memset(&r, 0, sizeof(r));
117         RVM_REG_SETP(&r, r_string_create_from_rstr(s));
118         RVM_REG_SETTYPE(&r, RVM_DTYPE_STRING);
119         RVM_REG_SETFLAG(&r, RVM_INFOBIT_ROBJECT);
120         return r;
121 }
122
123
124 void rvm_reg_setstring(rvmreg_t *r, rstring_t *ptr)
125 {
126         r_memset(r, 0, sizeof(*r));
127         RVM_REG_SETP(r, ptr);
128         RVM_REG_SETTYPE(r, RVM_DTYPE_STRING);
129         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
130 }
131
132
133 void rvm_reg_setpair(rvmreg_t *r, ruint32 p1, ruint32 p2)
134 {
135         r_memset(r, 0, sizeof(*r));
136         RVM_REG_SETPAIR(r, p1, p2);
137         RVM_REG_SETTYPE(r, RVM_DTYPE_PAIR);
138 }
139
140
141 void rvm_reg_setstrptr(rvmreg_t *r, char *s, unsigned int size)
142 {
143         r_memset(r, 0, sizeof(*r));
144         RVM_REG_SETSTR(r, s, size);
145         RVM_REG_SETTYPE(r, RVM_DTYPE_STRPTR);
146 }
147
148
149 void rvm_reg_setarray(rvmreg_t *r, robject_t *ptr)
150 {
151         r_memset(r, 0, sizeof(*r));
152         RVM_REG_SETP(r, ptr);
153         RVM_REG_SETTYPE(r, RVM_DTYPE_ARRAY);
154         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
155 }
156
157
158 void rvm_reg_setmap(rvmreg_t *r, robject_t *ptr)
159 {
160         r_memset(r, 0, sizeof(*r));
161         RVM_REG_SETP(r, ptr);
162         RVM_REG_SETTYPE(r, RVM_DTYPE_MAP);
163         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
164 }
165
166
167 void rvm_reg_setjsobject(rvmreg_t *r, robject_t *ptr)
168 {
169         rvm_reg_setmap(r, ptr);
170 }
171
172
173 void rvm_reg_setharray(rvmreg_t *r, robject_t *ptr)
174 {
175         r_memset(r, 0, sizeof(*r));
176         RVM_REG_SETP(r, ptr);
177         RVM_REG_SETTYPE(r, RVM_DTYPE_HARRAY);
178         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
179 }
180
181
182 void rvm_reg_setswi(rvmreg_t *r, ruword swiid)
183 {
184         r_memset(r, 0, sizeof(*r));
185         RVM_REG_SETU(r, swiid);
186         RVM_REG_SETTYPE(r, RVM_DTYPE_SWIID);
187 }
188
189
190 rvmreg_t rvm_reg_create_swi(ruword swiid)
191 {
192         rvmreg_t r;
193         rvm_reg_setswi(&r, swiid);
194         return r;
195 }
196
197
198 rvmreg_t rvm_reg_create_pair(ruint32 p1, ruint32 p2)
199 {
200         rvmreg_t r;
201         rvm_reg_setpair(&r, p1, p2);
202         return r;
203 }
204
205
206 rvmreg_t rvm_reg_create_strptr(char *s, unsigned int size)
207 {
208         rvmreg_t r;
209         rvm_reg_setstrptr(&r, s, size);
210         return r;
211 }
212
213
214 rvmreg_t rvm_reg_create_double(double d)
215 {
216         rvmreg_t r;
217         rvm_reg_setdouble(&r, d);
218         return r;
219 }
220
221
222 rvmreg_t rvm_reg_create_signed(rword l)
223 {
224         rvmreg_t r;
225         rvm_reg_setsigned(&r, l);
226         return r;
227 }
228
229
230 rvmreg_t rvm_reg_create_pointer(rpointer p)
231 {
232         rvmreg_t r;
233         rvm_reg_setpointer(&r, p);
234         return r;
235
236 }
237
238 rvmreg_t rvm_reg_create_ophandler(rpointer p)
239 {
240         rvmreg_t r;
241         rvm_reg_setophandler(&r, p);
242         return r;
243 }
244
245
246 rvmreg_t rvm_reg_create_prophandler(rpointer p)
247 {
248         rvmreg_t r;
249         rvm_reg_setprophandler(&r, p);
250         return r;
251 }
252
253
254 void rvm_reg_cleanup(rvmreg_t *reg)
255 {
256         RVM_REG_CLEAR(reg);
257 }
258
259
260 void rvm_reg_init(rvmreg_t *reg)
261 {
262         RVM_REG_CLEAR(reg);
263 }
264
265
266 rvmreg_t *rvm_reg_copy(rvmreg_t *dst, const rvmreg_t *src)
267 {
268         if (dst != src)
269                 *dst = *src;
270         if (rvm_reg_tstflag(dst, RVM_INFOBIT_ROBJECT))
271                 dst->v.p = r_object_v_copy(dst->v.p);
272         return dst;
273 }
274
275
276 void rvm_reg_settype(rvmreg_t *r, unsigned int type)
277 {
278         RVM_REG_SETTYPE(r, type);
279 }
280
281
282 rvmreg_type_t rvm_reg_gettype(const rvmreg_t *r)
283 {
284         rvmreg_type_t type = RVM_REG_GETTYPE(r);
285         return type;
286 }
287
288
289 rboolean rvm_reg_tstflag(const rvmreg_t *r, ruint16 flag)
290 {
291         return RVM_REG_TSTFLAG(r, flag);
292 }
293
294
295 void rvm_reg_setflag(rvmreg_t *r, ruint16 flag)
296 {
297         RVM_REG_SETFLAG(r, flag);
298 }
299
300
301 void rvm_reg_clrflag(rvmreg_t *r, ruint16 flag)
302 {
303         RVM_REG_CLRFLAG(r, flag);
304 }
305
306
307 void rvm_reg_setundef(rvmreg_t *r)
308 {
309         r_memset(r, 0, sizeof(*r));
310         RVM_REG_SETTYPE(r, RVM_DTYPE_UNDEF);
311 }
312
313
314 void rvm_reg_setunsigned(rvmreg_t *r, ruword u)
315 {
316         r_memset(r, 0, sizeof(*r));
317         RVM_REG_SETU(r, u);
318         RVM_REG_SETTYPE(r, RVM_DTYPE_UNSIGNED);
319 }
320
321
322 void rvm_reg_setsigned(rvmreg_t *r, rword l)
323 {
324         r_memset(r, 0, sizeof(*r));
325         RVM_REG_SETL(r, l);
326         RVM_REG_SETTYPE(r, RVM_DTYPE_SIGNED);
327 }
328
329
330 void rvm_reg_setboolean(rvmreg_t *r, rboolean b)
331 {
332         r_memset(r, 0, sizeof(*r));
333         RVM_REG_SETU(r, b ? 1 : 0);
334         RVM_REG_SETTYPE(r, RVM_DTYPE_BOOLEAN);
335 }
336
337
338 void rvm_reg_setdouble(rvmreg_t *r, double d)
339 {
340         r_memset(r, 0, sizeof(*r));
341         RVM_REG_SETD(r, d);
342         RVM_REG_SETTYPE(r, RVM_DTYPE_DOUBLE);
343 }
344
345
346 void rvm_reg_setpointer(rvmreg_t *r, rpointer p)
347 {
348         r_memset(r, 0, sizeof(*r));
349         RVM_REG_SETP(r, p);
350         RVM_REG_SETTYPE(r, RVM_DTYPE_POINTER);
351 }
352
353
354 void rvm_reg_setophandler(rvmreg_t *r, rpointer p)
355 {
356         r_memset(r, 0, sizeof(*r));
357         RVM_REG_SETP(r, p);
358         RVM_REG_SETTYPE(r, RVM_DTYPE_OPHANDLER);
359 }
360
361
362 void rvm_reg_setprophandler(rvmreg_t *r, rpointer p)
363 {
364         r_memset(r, 0, sizeof(*r));
365         RVM_REG_SETP(r, p);
366         RVM_REG_SETTYPE(r, RVM_DTYPE_PROPHANDLER);
367 }
368
369
370 int rvm_reg_str2num(rvmreg_t *dst, const rvmreg_t *src)
371 {
372         char *dptr, *lptr;
373         double d;
374         long l;
375
376         l = r_strtol(R_STRING2ANSI(RVM_REG_GETP(src)), &lptr, 10);
377         if (!lptr)
378                 return -1;
379         if (*lptr != '.') {
380                 rvm_reg_setsigned(dst, l);
381                 return 0;
382         }
383         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
384         if (!dptr)
385                 return -1;
386         rvm_reg_setdouble(dst, d);
387         return 0;
388 }
389
390
391 int rvm_reg_str2signed(rvmreg_t *dst, const rvmreg_t *src)
392 {
393         char *dptr;
394         double d;
395
396         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
397         if (!dptr)
398                 return -1;
399         rvm_reg_setsigned(dst, (rword)d);
400         return 0;
401 }
402
403
404 int rvm_reg_str2double(rvmreg_t *dst, const rvmreg_t *src)
405 {
406         char *dptr;
407         double d;
408
409         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
410         if (!dptr)
411                 return -1;
412         rvm_reg_setdouble(dst, d);
413         return 0;
414 }
415
416
417 int rvm_reg_int(const rvmreg_t *src)
418 {
419         R_ASSERT(src);
420         return (int)RVM_REG_GETL(src);
421 }
422
423
424 rword rvm_reg_signed(const rvmreg_t *src)
425 {
426         R_ASSERT(src);
427         return (long)RVM_REG_GETL(src);
428 }
429
430
431 rboolean rvm_reg_boolean(const rvmreg_t *src)
432 {
433         R_ASSERT(src);
434         return (rboolean)(RVM_REG_GETL(src) ? 1 : 0);
435 }
436
437
438 double rvm_reg_double(const rvmreg_t *src)
439 {
440         R_ASSERT(src);
441         return (double)RVM_REG_GETL(src);
442 }
443
444
445 rpointer rvm_reg_pointer(const rvmreg_t *src)
446 {
447         R_ASSERT(src);
448         return (rpointer)RVM_REG_GETP(src);
449 }
450
451
452 rstring_t *rvm_reg_string(const rvmreg_t *src)
453 {
454         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_STRING);
455         return (rstring_t*)RVM_REG_GETP(src);
456 }
457
458
459 rmap_t *rvm_reg_jsobject(const rvmreg_t *src)
460 {
461         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_MAP);
462         return (rmap_t*)RVM_REG_GETP(src);
463 }