RPA Toolkit
7bdb3fb7802384531b4e917916f4fc3bc93c5b8a
[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 void rvm_reg_cleanup(rvmreg_t *reg)
231 {
232         RVM_REG_CLEAR(reg);
233 }
234
235
236 void rvm_reg_init(rvmreg_t *reg)
237 {
238         RVM_REG_CLEAR(reg);
239 }
240
241
242 rvmreg_t *rvm_reg_copy(rvmreg_t *dst, const rvmreg_t *src)
243 {
244         if (dst != src)
245                 *dst = *src;
246         if (rvm_reg_tstflag(dst, RVM_INFOBIT_ROBJECT))
247                 dst->v.p = r_object_v_copy(dst->v.p);
248         return dst;
249 }
250
251
252 void rvm_reg_settype(rvmreg_t *r, unsigned int type)
253 {
254         RVM_REG_SETTYPE(r, type);
255 }
256
257
258 rvmreg_type_t rvm_reg_gettype(const rvmreg_t *r)
259 {
260         rvmreg_type_t type = RVM_REG_GETTYPE(r);
261         return type;
262 }
263
264
265 rboolean rvm_reg_tstflag(const rvmreg_t *r, ruint16 flag)
266 {
267         return RVM_REG_TSTFLAG(r, flag);
268 }
269
270
271 void rvm_reg_setflag(rvmreg_t *r, ruint16 flag)
272 {
273         RVM_REG_SETFLAG(r, flag);
274 }
275
276
277 void rvm_reg_clrflag(rvmreg_t *r, ruint16 flag)
278 {
279         RVM_REG_CLRFLAG(r, flag);
280 }
281
282
283 void rvm_reg_setundef(rvmreg_t *r)
284 {
285         r_memset(r, 0, sizeof(*r));
286         RVM_REG_SETTYPE(r, RVM_DTYPE_UNDEF);
287 }
288
289
290 void rvm_reg_setunsigned(rvmreg_t *r, ruword u)
291 {
292         r_memset(r, 0, sizeof(*r));
293         RVM_REG_SETU(r, u);
294         RVM_REG_SETTYPE(r, RVM_DTYPE_UNSIGNED);
295 }
296
297
298 void rvm_reg_setsigned(rvmreg_t *r, rword l)
299 {
300         r_memset(r, 0, sizeof(*r));
301         RVM_REG_SETL(r, l);
302         RVM_REG_SETTYPE(r, RVM_DTYPE_SIGNED);
303 }
304
305
306 void rvm_reg_setboolean(rvmreg_t *r, rboolean b)
307 {
308         r_memset(r, 0, sizeof(*r));
309         RVM_REG_SETU(r, b ? 1 : 0);
310         RVM_REG_SETTYPE(r, RVM_DTYPE_BOOLEAN);
311 }
312
313
314 void rvm_reg_setdouble(rvmreg_t *r, double d)
315 {
316         r_memset(r, 0, sizeof(*r));
317         RVM_REG_SETD(r, d);
318         RVM_REG_SETTYPE(r, RVM_DTYPE_DOUBLE);
319 }
320
321
322 void rvm_reg_setpointer(rvmreg_t *r, rpointer p)
323 {
324         r_memset(r, 0, sizeof(*r));
325         RVM_REG_SETP(r, p);
326         RVM_REG_SETTYPE(r, RVM_DTYPE_POINTER);
327 }
328
329
330 int rvm_reg_str2num(rvmreg_t *dst, const rvmreg_t *src)
331 {
332         char *dptr, *lptr;
333         double d;
334         long l;
335
336         l = r_strtol(R_STRING2ANSI(RVM_REG_GETP(src)), &lptr, 10);
337         if (!lptr)
338                 return -1;
339         if (*lptr != '.') {
340                 rvm_reg_setsigned(dst, l);
341                 return 0;
342         }
343         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
344         if (!dptr)
345                 return -1;
346         rvm_reg_setdouble(dst, d);
347         return 0;
348 }
349
350
351 int rvm_reg_str2signed(rvmreg_t *dst, const rvmreg_t *src)
352 {
353         char *dptr;
354         double d;
355
356         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
357         if (!dptr)
358                 return -1;
359         rvm_reg_setsigned(dst, (rword)d);
360         return 0;
361 }
362
363
364 int rvm_reg_str2double(rvmreg_t *dst, const rvmreg_t *src)
365 {
366         char *dptr;
367         double d;
368
369         d = r_strtod(R_STRING2ANSI(RVM_REG_GETP(src)), &dptr);
370         if (!dptr)
371                 return -1;
372         rvm_reg_setdouble(dst, d);
373         return 0;
374 }
375
376
377 int rvm_reg_int(const rvmreg_t *src)
378 {
379         R_ASSERT(src);
380         return (int)RVM_REG_GETL(src);
381 }
382
383
384 rword rvm_reg_signed(const rvmreg_t *src)
385 {
386         R_ASSERT(src);
387         return (long)RVM_REG_GETL(src);
388 }
389
390
391 rboolean rvm_reg_boolean(const rvmreg_t *src)
392 {
393         R_ASSERT(src);
394         return (rboolean)(RVM_REG_GETL(src) ? 1 : 0);
395 }
396
397
398 double rvm_reg_double(const rvmreg_t *src)
399 {
400         R_ASSERT(src);
401         return (double)RVM_REG_GETL(src);
402 }
403
404
405 rpointer rvm_reg_pointer(const rvmreg_t *src)
406 {
407         R_ASSERT(src);
408         return (rpointer)RVM_REG_GETP(src);
409 }
410
411
412 rstring_t *rvm_reg_string(const rvmreg_t *src)
413 {
414         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_STRING);
415         return (rstring_t*)RVM_REG_GETP(src);
416 }
417
418
419 rmap_t *rvm_reg_jsobject(const rvmreg_t *src)
420 {
421         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_MAP);
422         return (rmap_t*)RVM_REG_GETP(src);
423 }