1 /*
2 * Copyright © 1988-2004 Keith Packard and Bart Massey.
3 * All Rights Reserved. See the file COPYING in this directory
4 * for licensing information.
5 */
6
7 #include "nickle.h"
8
9 Value
StructMemRef(Value sv,Atom name)10 StructMemRef (Value sv, Atom name)
11 {
12 ENTER ();
13 Struct *s = &sv->structs;
14 StructType *st = s->type;
15 int i;
16
17 for (i = 0; i < st->nelements; i++)
18 if (StructTypeAtoms(st)[i] == name)
19 RETURN (NewRef (s->values, i));
20 RETURN (0);
21 }
22
23 Value
StructMemValue(Value sv,Atom name)24 StructMemValue (Value sv, Atom name)
25 {
26 ENTER ();
27 Struct *s = &sv->structs;
28 StructType *st = s->type;
29 int i;
30
31 for (i = 0; i < st->nelements; i++)
32 if (StructTypeAtoms(st)[i] == name)
33 RETURN (BoxValue (s->values, i));
34 RETURN (0);
35 }
36
37 Type *
StructMemType(StructType * st,Atom name)38 StructMemType (StructType *st, Atom name)
39 {
40 int i;
41
42 for (i = 0; i < st->nelements; i++)
43 if (StructTypeAtoms(st)[i] == name)
44 return (BoxTypesElements(st->types)[i]);
45 return (0);
46 }
47
48 static Bool
StructPrint(Value f,Value av,char format,int base,int width,int prec,int fill)49 StructPrint (Value f, Value av, char format, int base, int width, int prec, int fill)
50 {
51 Struct *s = &av->structs;
52 StructType *st = s->type;
53 int i;
54 Bool pretty = format == 'v' || format == 'g' || format == 'G';
55 char down_format = format == 'g' ? 'G' : format;
56
57 if (pretty)
58 FileOutput (f, '{');
59 for (i = 0; i < st->nelements; i++)
60 {
61 FilePuts (f, AtomName (StructTypeAtoms(st)[i]));
62 if (format != 'G') {
63 FilePuts (f, " = ");
64 if (!Print (f, BoxValueGet (s->values, i), down_format, base, width, prec, fill))
65 return False;
66 }
67 if (i < st->nelements - 1)
68 {
69 if (pretty)
70 FileOutput (f, ',');
71 FileOutput (f, ' ');
72 }
73 }
74 if (pretty)
75 FileOutput (f, '}');
76 return True;
77 }
78
79 static void
StructMark(void * object)80 StructMark (void *object)
81 {
82 Struct *s = object;
83
84 MemReference (s->type);
85 MemReference (s->values);
86 }
87
88 static Value
StructEqual(Value a,Value b,int expandOk)89 StructEqual (Value a, Value b, int expandOk)
90 {
91 int i;
92 StructType *at = a->structs.type;
93
94 if (at->nelements != b->structs.type->nelements)
95 return FalseVal;
96 for (i = 0; i < at->nelements; i++)
97 {
98 if (False (Equal (BoxValue (a->structs.values, i),
99 StructMemValue (b, StructTypeAtoms(at)[i]))))
100 return FalseVal;
101 }
102 return TrueVal;
103 }
104
105 static HashValue
StructHash(Value a)106 StructHash (Value a)
107 {
108 Struct *s = &a->structs;
109 StructType *at = s->type;
110 HashValue h = 0;
111 int i;
112
113 for (i = 0; i < at->nelements; i++)
114 h = h ^ ValueInt (ValueHash (BoxValue (a->structs.values, i)));
115 return h;
116 }
117
118 ValueRep StructRep = {
119 { StructMark, 0, "StructRep" }, /* base */
120 rep_struct, /* tag */
121 { /* binary */
122 0,
123 0,
124 0,
125 0,
126 0,
127 0,
128 0,
129 StructEqual,
130 0,
131 0,
132 },
133 { /* unary */
134 0,
135 0,
136 0,
137 },
138 0,
139 0,
140 StructPrint,
141 0,
142 StructHash,
143 };
144
145 Value
NewStruct(StructType * type,Bool constant)146 NewStruct (StructType *type, Bool constant)
147 {
148 ENTER ();
149 Value ret;
150
151 ret = ALLOCATE (&StructRep.data, sizeof (Struct));
152 ret->structs.type = type;
153 ret->structs.values = 0;
154 ret->structs.values = NewTypedBox (False, type->types);
155 RETURN (ret);
156 }
157
158 static void
StructTypeMark(void * object)159 StructTypeMark (void *object)
160 {
161 StructType *st = object;
162
163 MemReference (st->types);
164 }
165
166 DataType StructTypeType = { StructTypeMark, 0, "StructTypeType" };
167
168 StructType *
NewStructType(int nelements)169 NewStructType (int nelements)
170 {
171 ENTER ();
172 StructType *st;
173 int i;
174 Atom *atoms;
175
176 st = ALLOCATE (&StructTypeType, sizeof (StructType) +
177 nelements * sizeof (Atom));
178 st->nelements = nelements;
179 st->types = NewBoxTypes (nelements);
180 atoms = StructTypeAtoms(st);
181 for (i = 0; i < nelements; i++)
182 atoms[i] = 0;
183 RETURN (st);
184 }
185
186 Value Elementless;
187 StructType *ElementlessType;
188
189 int
StructInit(void)190 StructInit (void)
191 {
192 ENTER ();
193
194 ElementlessType = NewStructType (0);
195 MemAddRoot (ElementlessType);
196 Elementless = NewStruct (ElementlessType, True);
197 MemAddRoot (Elementless);
198 EXIT ();
199 return 1;
200 }
201
202 Type *
BuildStructType(int nelements,...)203 BuildStructType (int nelements, ...)
204 {
205 ENTER ();
206 StructType *st;
207 int i;
208 char *name;
209 Type *type;
210 va_list ap;
211
212 st = NewStructType (nelements);
213 va_start (ap, nelements);
214 for (i = 0; i < nelements; i++)
215 {
216 type = va_arg (ap, Type *);
217 name = va_arg (ap, char *);
218 AddBoxType (&st->types, type);
219 StructTypeAtoms (st)[i] = AtomId (name);
220 }
221 va_end (ap);
222 RETURN (NewTypeStruct (st));
223 }
224