-
Notifications
You must be signed in to change notification settings - Fork 1
/
objcomp.c
240 lines (203 loc) · 7.48 KB
/
objcomp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#ifdef RCSID
static char RCSid[] =
"$Header: d:/cvsroot/tads/TADS2/OBJCOMP.C,v 1.3 1999/07/11 00:46:30 MJRoberts Exp $";
#endif
/*
* Copyright (c) 1992, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
objcomp.c - object manipulation routines for compiler
Function
Provides routines used only by the compiler
Notes
Split off from obj main module to make run-time smaller
Modified
12/18/92 MJRoberts - creation
*/
#include "os.h"
#include "std.h"
#include "err.h"
#include "mcm.h"
#include "obj.h"
/*
* Set up for emitting code into an object. No undo information is
* kept for this type of operation, as it is presumed that the object is
* being compiled rather than being manipulated at run-time. Any
* previous value for the property is deleted, a property header is set
* up, and the offset of the next free byte in the object is returned.
*/
uint objemt(mcmcxdef *ctx, objnum objn, prpnum prop, dattyp typ)
{
objdef *objptr;
prpdef *p;
objptr = (objdef *)mcmlck(ctx, (mcmon)objn);
ERRBEGIN(ctx->mcmcxgl->mcmcxerr)
objdelp(ctx, objn, prop, FALSE); /* delete old property value, if any */
p = objpfre(objptr); /* get top of property area */
if ((char *)p - (char *)objptr + PRPHDRSIZ >=
mcmobjsiz(ctx, (mcmon)objn))
{
ushort newsiz = 64 + ((objfree(objptr) + PRPHDRSIZ) -
mcmobjsiz(ctx, (mcmon)objn));
objptr = objexp(ctx, objn, &newsiz);
p = objpfre(objptr); /* object may have moved */
}
/* set up property header as much as we can (don't know size yet) */
prpsetprop(p, prop);
prptype(p) = typ;
prpflg(p) = 0;
objsnp(objptr, objnprop(objptr) + 1); /* one more property */
ERRCLEAN(ctx->mcmcxgl->mcmcxerr)
mcmunlck(ctx, (mcmon)objn);
ERRENDCLN(ctx->mcmcxgl->mcmcxerr)
/* dirty the cache object and release the lock before return */
mcmtch(ctx, objn);
mcmunlck(ctx, (mcmon)objn);
return(((uchar *)prpvalp(p)) - ((uchar *)objptr));
}
/* done emitting code into property - finish setting object information */
void objendemt(mcmcxdef *ctx, objnum objn, prpnum prop, uint endofs)
{
objdef *objptr;
prpdef *p;
uint siz;
objptr = (objdef *)mcmlck(ctx, (mcmon)objn);
p = objofsp(objptr, objgetp(ctx, objn, prop, (dattyp *)0));
siz = endofs - (((uchar *)prpvalp(p)) - ((uchar *)objptr));
prpsetsize(p, siz);
objsfree(objptr, objfree(objptr) + siz + PRPHDRSIZ);
/* mark the object as changed, and unlock it */
mcmtch(ctx, (mcmon)objn);
mcmunlck(ctx, (mcmon)objn);
}
/* add superclasses to an object */
void objaddsc(mcmcxdef *mctx, int sccnt, objnum objn)
{
objdef *o;
ushort siz;
/* get lock on object */
o = (objdef *)mcmlck(mctx, objn);
/* make sure there's enough space, adding space if needed */
if (mcmobjsiz(mctx, (mcmon)objn) - objfree(o) < 2 * sccnt)
{
siz = 64 + ((2 * sccnt + objfree(o)) -
mcmobjsiz(mctx, (mcmon)objn));
o = objexp(mctx, objn, &siz); /* expand the object */
}
/* move properties, if any, above added superclasses */
if (objnprop(o))
memmove(objprp(o), ((uchar *)objprp(o)) + 2 * sccnt,
(size_t)(((uchar *)o) + objfree(o) - (uchar *)objprp(o)));
/* set new free pointer */
objsfree(o, objfree(o) + 2 * sccnt);
/* mark cache object modified and unlock it */
mcmtch(mctx, objn);
mcmunlck(mctx, objn);
}
/* delete an object's properties and superclasses */
void objclr(mcmcxdef *mctx, objnum objn, prpnum mindel)
{
objdef *o;
prpdef *p;
int cnt;
prpnum prop;
int indexed;
/* get a lock on the object */
o = (objdef *)mcmlck(mctx, objn);
indexed = objflg(o) & OBJFINDEX;
/* delete superclasses - move properties down over former sc array */
if (objnprop(o))
memmove(objsc(o), objprp(o),
(size_t)(((uchar *)o) + objfree(o) - (uchar *)objprp(o)));
objsnsc(o, 0); /* zero superclasses now */
/* delete non-"system" properties (propnum < mindel) */
for (p = objprp(o), cnt = objnprop(o) ; cnt ; --cnt)
{
if ((prop = prpprop(p)) >= mindel)
{
prpflg(p) &= ~PRPFIGN; /* delete even if it was marked ignore */
objdelp(mctx, objn, prop, FALSE); /* remove prpdef from object */
/* p is left pointing at next prop, as it was moved down */
}
else
p = objpnxt(p); /* advance over this property */
}
/* mark cache object modified and unlock it */
mcmtch(mctx, objn);
mcmunlck(mctx, objn);
if (indexed) objindx(mctx, objn);
}
/* set up just-compiled object: mark static part and original props */
void objcomp(mcmcxdef *mctx, objnum objn, int for_debug)
{
objdef *objptr;
prpdef *p;
prpdef *nxt;
int cnt;
/* lock object */
objptr = (objdef *)mcmlck(mctx, (mcmon)objn);
/*
* first, go through the properties, and delete each one that's
* marked as ignored
*/
for (cnt = objnprop(objptr), p = objprp(objptr) ; cnt != 0 ;
p = nxt, --cnt)
{
/* remember the next property */
nxt = objpnxt(p);
/* if this is marked as being ignored, delete it */
if ((prpflg(p) & PRPFIGN) != 0)
{
/*
* Delete the property. If we're compiling in debug mode,
* don't really delete anything, but simply mark the
* property as deleted; this is necessary because certain
* debug records are not self-relative, hence are not
* tolerant of changes to the internal structure of the
* object. If we're not compiling for debugging, we can
* actually delete properties, because all non-debug code is
* completely self-relative and thus can be moved around
* inside the object without any problems.
*/
if (for_debug)
{
/* simply mark the property as deleted */
prpflg(p) |= PRPFDEL;
/*
* clear the IGNORE flag, since we IGNORE and DELETED
* are mutually exclusive
*/
prpflg(p) &= ~PRPFIGN;
}
else
{
/* clear the flags so we can really delete it */
prpflg(p) &= ~(PRPFORG | PRPFIGN | PRPFDEL);
/* delete it */
objdelp(mctx, objn, (prpnum)prpprop(p), FALSE);
/*
* continue from the present location, since we moved
* the next property to the current location
*/
nxt = p;
}
}
}
/* set static entries: free space pointer, and number of properties */
objsetst(objptr, objnprop(objptr));
objsetrst(objptr, objfree(objptr));
/* go through properties, marking each as original */
for (cnt = objnprop(objptr), p = objprp(objptr) ; cnt != 0 ;
p = objpnxt(p), --cnt)
{
assert(p < objptr + mcmobjsiz(mctx, (mcmon)objn));
prpflg(p) |= PRPFORG; /* set ORIGINAL flag for property */
}
/* mark object changed, and unlock it */
mcmtch(mctx, objn);
mcmunlck(mctx, objn);
}