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