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