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