]> git.mxchange.org Git - simgear.git/blob - simgear/nasal/misc.c
Fix memory leak discovered by Mathias Froehlich
[simgear.git] / simgear / nasal / misc.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 #include "nasal.h"
6 #include "code.h"
7
8 void naFree(void* m) { free(m); }
9 void* naAlloc(int n) { return malloc(n); }
10 void* naRealloc(void* b, int n) { return realloc(b, n); }
11 void naBZero(void* m, int n) { memset(m, 0, n); }
12
13 void naTempSave(naContext c, naRef r)
14 {
15     int i;
16     if(!IS_OBJ(r)) return;
17     if(c->ntemps >= c->tempsz) {
18         struct naObj** newtemps;
19         c->tempsz *= 2;
20         newtemps = naAlloc(c->tempsz * sizeof(struct naObj*));
21         for(i=0; i<c->ntemps; i++)
22             newtemps[i] = c->temps[i];
23         naFree(c->temps);
24         c->temps = newtemps;
25     }
26     c->temps[c->ntemps++] = r.ref.ptr.obj;
27 }
28
29 naRef naObj(int type, struct naObj* o)
30 {
31     naRef r;
32     r.ref.reftag = NASAL_REFTAG;
33     r.ref.ptr.obj = o;
34     o->type = type;
35     return r;
36 }
37
38 int naTrue(naRef r)
39 {
40     if(IS_NIL(r)) return 0;
41     if(IS_NUM(r)) return r.num != 0;
42     if(IS_STR(r)) return 1;
43     return 0;
44 }
45
46 naRef naNumValue(naRef n)
47 {
48     double d;
49     if(IS_NUM(n)) return n;
50     if(IS_NIL(n)) return naNil();
51     if(IS_STR(n) && naStr_tonum(n, &d))
52         return naNum(d);
53     return naNil();
54 }
55
56 naRef naStringValue(naContext c, naRef r)
57 {
58     if(IS_NIL(r) || IS_STR(r)) return r;
59     if(IS_NUM(r)) {
60         naRef s = naNewString(c);
61         naStr_fromnum(s, r.num);
62         return s;
63     }
64     return naNil();
65 }
66
67 naRef naNew(struct Context* c, int type)
68 {
69     naRef result;
70     if(c->nfree[type] == 0)
71         c->free[type] = naGC_get(&globals->pools[type],
72                                  OBJ_CACHE_SZ, &c->nfree[type]);
73     result = naObj(type, c->free[type][--c->nfree[type]]);
74     naTempSave(c, result);
75     return result;
76 }
77
78 naRef naNewString(struct Context* c)
79 {
80     naRef s = naNew(c, T_STR);
81     s.ref.ptr.str->len = 0;
82     s.ref.ptr.str->data = 0;
83     s.ref.ptr.str->hashcode = 0;
84     return s;
85 }
86
87 naRef naNewVector(struct Context* c)
88 {
89     naRef r = naNew(c, T_VEC);
90     r.ref.ptr.vec->rec = 0;
91     return r;
92 }
93
94 naRef naNewHash(struct Context* c)
95 {
96     naRef r = naNew(c, T_HASH);
97     r.ref.ptr.hash->rec = 0;
98     return r;
99 }
100
101 naRef naNewCode(struct Context* c)
102 {
103     return naNew(c, T_CODE);
104 }
105
106 naRef naNewCCode(struct Context* c, naCFunction fptr)
107 {
108     naRef r = naNew(c, T_CCODE);
109     r.ref.ptr.ccode->fptr = fptr;
110     return r;
111 }
112
113 naRef naNewFunc(struct Context* c, naRef code)
114 {
115     naRef func = naNew(c, T_FUNC);
116     func.ref.ptr.func->code = code;
117     func.ref.ptr.func->namespace = naNil();
118     func.ref.ptr.func->next = naNil();
119     return func;
120 }
121
122 naRef naNewGhost(naContext c, naGhostType* type, void* ptr)
123 {
124     naRef ghost = naNew(c, T_GHOST);
125     ghost.ref.ptr.ghost->gtype = type;
126     ghost.ref.ptr.ghost->ptr = ptr;
127     return ghost;
128 }
129
130 naGhostType* naGhost_type(naRef ghost)
131 {
132     if(!IS_GHOST(ghost)) return 0;
133     return ghost.ref.ptr.ghost->gtype;
134 }
135
136 void* naGhost_ptr(naRef ghost)
137 {
138     if(!IS_GHOST(ghost)) return 0;
139     return ghost.ref.ptr.ghost->ptr;
140 }
141
142 naRef naNil()
143 {
144     naRef r;
145     r.ref.reftag = NASAL_REFTAG;
146     r.ref.ptr.obj = 0;
147     return r;
148 }
149
150 naRef naNum(double num)
151 {
152     naRef r;
153     r.ref.reftag = ~NASAL_REFTAG;
154     r.num = num;
155     return r;
156 }
157
158 int naEqual(naRef a, naRef b)
159 {
160     double na=0, nb=0;
161     if(IS_REF(a) && IS_REF(b) && a.ref.ptr.obj == b.ref.ptr.obj)
162         return 1; // Object identity (and nil == nil)
163     if(IS_NIL(a) || IS_NIL(b))
164         return 0;
165     if(IS_NUM(a) && IS_NUM(b) && a.num == b.num)
166         return 1; // Numeric equality
167     if(IS_STR(a) && IS_STR(b) && naStr_equal(a, b))
168         return 1; // String equality
169
170     // Numeric equality after conversion
171     if(IS_NUM(a)) { na = a.num; }
172     else if(!(IS_STR(a) && naStr_tonum(a, &na))) { return 0; }
173
174     if(IS_NUM(b)) { nb = b.num; }
175     else if(!(IS_STR(b) && naStr_tonum(b, &nb))) { return 0; }
176
177     return na == nb ? 1 : 0;
178 }
179
180 int naStrEqual(naRef a, naRef b)
181 {
182     int i;
183     if(!(IS_STR(a) && IS_STR(b)))
184         return 0;
185     if(a.ref.ptr.str->len != b.ref.ptr.str->len)
186         return 0;
187     for(i=0; i<a.ref.ptr.str->len; i++)
188         if(a.ref.ptr.str->data[i] != b.ref.ptr.str->data[i])
189             return 0;
190     return 1;
191 }
192
193 int naTypeSize(int type)
194 {
195     switch(type) {
196     case T_STR: return sizeof(struct naStr);
197     case T_VEC: return sizeof(struct naVec);
198     case T_HASH: return sizeof(struct naHash);
199     case T_CODE: return sizeof(struct naCode);
200     case T_FUNC: return sizeof(struct naFunc);
201     case T_CCODE: return sizeof(struct naCCode);
202     case T_GHOST: return sizeof(struct naGhost);
203     };
204     return 0x7fffffff; // Make sure the answer is nonsense :)
205 }
206
207 int naIsNil(naRef r)    { return IS_NIL(r); }
208 int naIsNum(naRef r)    { return IS_NUM(r); }
209 int naIsString(naRef r) { return IS_STR(r); }
210 int naIsScalar(naRef r) { return IS_SCALAR(r); }
211 int naIsVector(naRef r) { return IS_VEC(r); }
212 int naIsHash(naRef r)   { return IS_HASH(r); }
213 int naIsFunc(naRef r)   { return IS_FUNC(r); }
214 int naIsCode(naRef r)   { return IS_CODE(r); }
215 int naIsCCode(naRef r)  { return IS_CCODE(r); }
216 int naIsGhost(naRef r)  { return IS_GHOST(r); }