1 /*
2 $Id: labelobj.c 2573 2021-04-12 00:12:54Z 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 "labelobj.h"
20 #include <string.h>
21 #include "values.h"
22 #include "error.h"
23 #include "unicode.h"
24 #include "file.h"
25
26 #include "strobj.h"
27 #include "typeobj.h"
28 #include "errorobj.h"
29
30 static Type obj;
31
32 Type *const LABEL_OBJ = &obj;
33
destroy(Obj * o1)34 static FAST_CALL void destroy(Obj *o1) {
35 Label *v1 = Label(o1);
36 const struct file_s *cfile = v1->file_list->file;
37 if (not_in_file(v1->name.data, cfile)) free((char *)v1->name.data);
38 if (v1->name.data != v1->cfname.data) free((uint8_t *)v1->cfname.data);
39 val_destroy(v1->value);
40 }
41
garbage(Obj * o1,int i)42 static FAST_CALL void garbage(Obj *o1, int i) {
43 Label *v1 = Label(o1);
44 Obj *v;
45 const struct file_s *cfile;
46 switch (i) {
47 case -1:
48 v1->value->refcount--;
49 return;
50 case 0:
51 cfile = v1->file_list->file;
52 if (not_in_file(v1->name.data, cfile)) free((char *)v1->name.data);
53 if (v1->name.data != v1->cfname.data) free((uint8_t *)v1->cfname.data);
54 return;
55 case 1:
56 v = v1->value;
57 if ((v->refcount & SIZE_MSB) != 0) {
58 v->refcount -= SIZE_MSB - 1;
59 v->obj->garbage(v, 1);
60 } else v->refcount++;
61 return;
62 }
63 }
64
same(const Obj * o1,const Obj * o2)65 static FAST_CALL bool same(const Obj *o1, const Obj *o2) {
66 const Label *v1 = Label(o1), *v2 = Label(o2);
67 return o1->obj == o2->obj
68 && v1->epoint.pos == v2->epoint.pos
69 && v1->epoint.line == v2->epoint.line
70 && v1->file_list == v2->file_list
71 && v1->strength == v2->strength
72 && str_cmp(&v1->name, &v2->name) == 0
73 && (v1->value == v2->value || v1->value->obj->same(v1->value, v2->value));
74 }
75
repr(Obj * o1,linepos_t epoint,size_t maxlen)76 static MUST_CHECK Obj *repr(Obj *o1, linepos_t epoint, size_t maxlen) {
77 Label *v1 = Label(o1);
78 size_t len, len2;
79 uint8_t *s;
80 Str *v;
81 if (epoint == NULL) return NULL;
82 switch (v1->name.data[0]) {
83 case '+':
84 case '-': len = 1; break;
85 case '#':
86 case '.': len = 0; break;
87 default: len = v1->name.len;
88 }
89 len2 = len + 10;
90 if (len2 > maxlen) return NULL;
91 v = new_str2(len2);
92 if (v == NULL) return NULL;
93 v->chars = calcpos(v1->name.data, len);
94 s = v->data;
95 memcpy(s, "<label '", 8);
96 s += 8;
97 memcpy(s, v1->name.data, len);
98 s[len] = '\'';
99 s[len + 1] = '>';
100 return Obj(v);
101 }
102
str(Obj * o1,linepos_t UNUSED (epoint),size_t maxlen)103 static MUST_CHECK Obj *str(Obj *o1, linepos_t UNUSED(epoint), size_t maxlen) {
104 Label *v1 = Label(o1);
105 size_t len, chars;
106 Str *v;
107 switch (v1->name.data[0]) {
108 case '+':
109 case '-': len = 1; break;
110 case '#':
111 case '.': return NULL;
112 default: len = v1->name.len;
113 }
114 chars = calcpos(v1->name.data, len);
115 if (chars > maxlen) return NULL;
116 v = new_str2(len);
117 if (v == NULL) return NULL;
118 v->chars = chars;
119 memcpy(v->data, v1->name.data, len);
120 return Obj(v);
121 }
122
labelobj_init(void)123 void labelobj_init(void) {
124 new_type(&obj, T_LABEL, "label", sizeof(Label));
125 obj.destroy = destroy;
126 obj.garbage = garbage;
127 obj.same = same;
128 obj.repr = repr;
129 obj.str = str;
130 }
131