1 /*
2     $Id: errorobj.c 2616 2021-04-25 11:08:26Z soci $
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
18 */
19 #include <string.h>
20 #include "errorobj.h"
21 #include "eval.h"
22 #include "values.h"
23 #include "error.h"
24 #include "64tass.h"
25 #include "file.h"
26 #include "macro.h"
27 
28 #include "typeobj.h"
29 #include "registerobj.h"
30 #include "namespaceobj.h"
31 
32 static Type obj;
33 
34 Type *const ERROR_OBJ = &obj;
35 
destroy(Obj * o1)36 static FAST_CALL void destroy(Obj *o1) {
37     Error *v1 = Error(o1);
38     if (v1->line != NULL) free((uint8_t *)v1->line);
39     switch (v1->num) {
40     case ERROR__INVALID_OPER:
41         val_destroy(v1->u.invoper.v1);
42         if (v1->u.invoper.v2 != NULL) val_destroy(v1->u.invoper.v2);
43         return;
44     case ERROR___NO_REGISTER:
45         val_destroy(Obj(v1->u.reg.reg));
46         return;
47     case ERROR_____CANT_UVAL:
48     case ERROR_____CANT_IVAL:
49     case ERROR______NOT_UVAL:
50         val_destroy(v1->u.intconv.val);
51         return;
52     case ERROR___NOT_DEFINED:
53         val_destroy(v1->u.notdef.symbol);
54         val_destroy(Obj(v1->u.notdef.names));
55         return;
56     case ERROR__NOT_KEYVALUE:
57     case ERROR__NOT_HASHABLE:
58     case ERROR_____CANT_SIGN:
59     case ERROR______CANT_ABS:
60     case ERROR______CANT_INT:
61     case ERROR______CANT_LEN:
62     case ERROR_____CANT_SIZE:
63     case ERROR_____CANT_BOOL:
64     case ERROR______NOT_ITER:
65     case ERROR___MATH_DOMAIN:
66     case ERROR_LOG_NON_POSIT:
67     case ERROR_SQUARE_ROOT_N:
68     case ERROR___INDEX_RANGE:
69     case ERROR_____KEY_ERROR:
70     case ERROR_DIVISION_BY_Z:
71     case ERROR_ZERO_NEGPOWER:
72         val_destroy(v1->u.obj);
73         return;
74     case ERROR__INVALID_CONV:
75         val_destroy(v1->u.conv.val);
76         return;
77     default: return;
78     }
79 }
80 
garbage(Obj * o1,int i)81 static FAST_CALL void garbage(Obj *o1, int i) {
82     Error *v1 = Error(o1);
83     Obj *v;
84     if (i == 0) {
85         if (v1->line != NULL) free((uint8_t *)v1->line);
86         return;
87     }
88     switch (v1->num) {
89     case ERROR__INVALID_OPER:
90         v = v1->u.invoper.v1;
91         if (v1->u.invoper.v2 != NULL) {
92             if (i < 0) v->refcount--;
93             else if ((v->refcount & SIZE_MSB) != 0) {
94                 v->refcount -= SIZE_MSB - 1;
95                 v->obj->garbage(v, 1);
96             } else v->refcount++;
97             v = v1->u.invoper.v2;
98         }
99         break;
100     case ERROR___NO_REGISTER:
101         v = Obj(v1->u.reg.reg);
102         break;
103     case ERROR_____CANT_UVAL:
104     case ERROR_____CANT_IVAL:
105     case ERROR______NOT_UVAL:
106         v = v1->u.intconv.val;
107         break;
108     case ERROR___NOT_DEFINED:
109         v = v1->u.notdef.symbol;
110         if (i < 0) v->refcount--;
111         else if ((v->refcount & SIZE_MSB) != 0) {
112             v->refcount -= SIZE_MSB - 1;
113             v->obj->garbage(v, 1);
114         } else v->refcount++;
115         v = Obj(v1->u.notdef.names);
116         break;
117     case ERROR__NOT_KEYVALUE:
118     case ERROR__NOT_HASHABLE:
119     case ERROR_____CANT_SIGN:
120     case ERROR______CANT_ABS:
121     case ERROR______CANT_INT:
122     case ERROR______CANT_LEN:
123     case ERROR_____CANT_SIZE:
124     case ERROR_____CANT_BOOL:
125     case ERROR______NOT_ITER:
126     case ERROR___MATH_DOMAIN:
127     case ERROR_LOG_NON_POSIT:
128     case ERROR_SQUARE_ROOT_N:
129     case ERROR___INDEX_RANGE:
130     case ERROR_____KEY_ERROR:
131     case ERROR_DIVISION_BY_Z:
132     case ERROR_ZERO_NEGPOWER:
133         v = v1->u.obj;
134         break;
135     case ERROR__INVALID_CONV:
136         v = v1->u.conv.val;
137         break;
138     default:
139         return;
140     }
141     if (i < 0) v->refcount--;
142     else if ((v->refcount & SIZE_MSB) != 0) {
143         v->refcount -= SIZE_MSB - 1;
144         v->obj->garbage(v, 1);
145     } else v->refcount++;
146 }
147 
new_error(Error_types num,linepos_t epoint)148 MALLOC Error *new_error(Error_types num, linepos_t epoint) {
149     Error *v = Error(val_alloc(ERROR_OBJ));
150     v->num = num;
151     v->file_list = current_file_list;
152     v->epoint.line = epoint->line;
153     v->caret = epoint->pos;
154     v->epoint.pos = macro_error_translate2(epoint->pos);
155     if (not_in_file(pline, current_file_list->file)) {
156         size_t ln = strlen((const char *)pline) + 1;
157         uint8_t *l = (uint8_t *)malloc(ln);
158         if (l != NULL) memcpy(l, pline, ln);
159         v->line = l;
160     } else v->line = NULL;
161     return v;
162 }
163 
new_error_mem(linepos_t epoint)164 MALLOC Obj *new_error_mem(linepos_t epoint) {
165     return Obj(new_error(ERROR_OUT_OF_MEMORY, epoint));
166 }
167 
new_error_obj(Error_types num,Obj * v1,linepos_t epoint)168 MALLOC Obj *new_error_obj(Error_types num, Obj *v1, linepos_t epoint) {
169     Error *v = new_error(num, epoint);
170     v->u.obj = val_reference(v1);
171     return Obj(v);
172 }
173 
new_error_conv(Obj * v1,Type * t,linepos_t epoint)174 MALLOC Obj *new_error_conv(Obj *v1, Type *t, linepos_t epoint) {
175     Error *v = new_error(ERROR__INVALID_CONV, epoint);
176     v->u.conv.t = t;
177     v->u.conv.val = val_reference(v1);
178     return Obj(v);
179 }
180 
new_error_argnum(argcount_t num,argcount_t min,argcount_t max,linepos_t epoint)181 MALLOC Obj *new_error_argnum(argcount_t num, argcount_t min, argcount_t max, linepos_t epoint) {
182     Error *v = new_error(ERROR__WRONG_ARGNUM, epoint);
183     v->u.argnum.num = num;
184     v->u.argnum.min = min;
185     v->u.argnum.max = max;
186     return Obj(v);
187 }
188 
calc1(oper_t op)189 static MUST_CHECK Obj *calc1(oper_t op) {
190     return val_reference(op->v1);
191 }
192 
calc2(oper_t op)193 static MUST_CHECK Obj *calc2(oper_t op) {
194     return val_reference(op->v1);
195 }
196 
rcalc2(oper_t op)197 static MUST_CHECK Obj *rcalc2(oper_t op) {
198     return val_reference(op->v2);
199 }
200 
slice(oper_t op,argcount_t UNUSED (indx))201 static MUST_CHECK Obj *slice(oper_t op, argcount_t UNUSED(indx)) {
202     return val_reference(op->v1);
203 }
204 
errorobj_init(void)205 void errorobj_init(void) {
206     new_type(&obj, T_ERROR, "error", sizeof(Error));
207     obj.destroy = destroy;
208     obj.garbage = garbage;
209     obj.calc1 = calc1;
210     obj.calc2 = calc2;
211     obj.rcalc2 = rcalc2;
212     obj.slice = slice;
213 }
214 
error_obj_update(Error * err,const Obj * v1,Obj * v2)215 void error_obj_update(Error *err, const Obj *v1, Obj *v2) {
216     switch (err->num) {
217     case ERROR__INVALID_OPER:
218         if (err->u.invoper.v1 == v1) {
219             val_replace(&err->u.invoper.v1, v2);
220         }
221         if (err->u.invoper.v2 == v1) {
222             val_replace(&err->u.invoper.v2, v2);
223         }
224         return;
225     case ERROR_____CANT_UVAL:
226     case ERROR_____CANT_IVAL:
227     case ERROR______NOT_UVAL:
228         if (err->u.intconv.val == v1) {
229             val_replace(&err->u.intconv.val, v2);
230         }
231         return;
232     case ERROR__NOT_KEYVALUE:
233     case ERROR__NOT_HASHABLE:
234     case ERROR_____CANT_SIGN:
235     case ERROR______CANT_ABS:
236     case ERROR______CANT_INT:
237     case ERROR______CANT_LEN:
238     case ERROR_____CANT_SIZE:
239     case ERROR_____CANT_BOOL:
240     case ERROR______NOT_ITER:
241     case ERROR___MATH_DOMAIN:
242     case ERROR_LOG_NON_POSIT:
243     case ERROR_SQUARE_ROOT_N:
244     case ERROR___INDEX_RANGE:
245     case ERROR_____KEY_ERROR:
246     case ERROR_DIVISION_BY_Z:
247     case ERROR_ZERO_NEGPOWER:
248         if (err->u.obj == v1) {
249             val_replace(&err->u.obj, v2);
250         }
251         return;
252     default:
253         return;
254     }
255 }
256