/* undefine a #define symbol */ void tok_del_define(tokcxdef *ctx, char *sym, int len) { int hsh; tokdfdef *df; tokdfdef *prv; /* find the appropriate chain the hash table */ hsh = tokdfhsh(sym, len); /* search the chain for this symbol */ for (prv = 0, df = ctx->tokcxdf[hsh] ; df ; prv = df, df = df->nxt) { /* if this one matches, delete it */ if (df->len == len && !memcmp(df->nm, sym, (size_t)len)) { /* unlink it from the chain */ if (prv) prv->nxt = df->nxt; else ctx->tokcxdf[hsh] = df->nxt; /* delete this symbol, and we're done */ mchfre(df); break; } } }
/* * Read preprocessor state from a file */ void tok_read_defines(tokcxdef *ctx, osfildef *fp, errcxdef *ec) { int i; tokdfdef **dfp; tokdfdef *df; char buf[4]; /* write each element of the hash chains */ for (i = TOKDFHSHSIZ, dfp = ctx->tokcxdf ; i ; ++dfp, --i) { /* read this hash chain */ for (;;) { /* read the next entry's header, and stop if this is the end */ if (osfrb(fp, buf, 4)) errsig(ec, ERR_RDGAM); if (osrp2(buf) == 0) break; /* set up a new symbol of the appropriate size */ df = (tokdfdef *)mchalo(ec, (sizeof(tokdfdef) + osrp2(buf) + osrp2(buf+2) - 1), "tok_read_defines"); df->explen = osrp2(buf+2); df->nm = df->expan + df->explen; df->len = osrp2(buf); /* read the rest of the symbol */ if (osfrb(fp, df->nm, df->len) || (df->explen != 0 && osfrb(fp, df->expan, df->explen))) errsig(ec, ERR_RDGAM); /* * If a symbol with this name already exists in the table, * discard the new one -- the symbols defined by -D and the * current set of built-in symbols takes precedence over the * set loaded from the file. */ if (tok_find_define(ctx, df->nm, df->len)) { /* simply discard this symbol */ mchfre(df); } else { /* link it into this hash chain */ df->nxt = *dfp; *dfp = df; } } } }
/* set up contents property for load-on-demand */ void supcont(void *ctx0, objnum obj, prpnum prp) { supcxdef *ctx = (supcxdef *)ctx0; vocidef ***vpg; vocidef **v; voccxdef *voc = ctx->supcxvoc; int i; int j; int len = 2; objnum chi; objnum loc; /* be sure the buffer is allocated */ if (!ctx->supcxbuf) { ctx->supcxlen = 512; ctx->supcxbuf = mchalo(ctx->supcxerr, ctx->supcxlen, "supcont"); } assert(prp == PRP_CONTENTS); /* the only thing that makes sense */ for (vpg = voc->voccxinh, i = 0 ; i < VOCINHMAX ; ++vpg, ++i) { if (!*vpg) continue; /* no entries on this page */ for (v = *vpg, chi = (i << 8), j = 0 ; j < 256 ; ++v, ++chi, ++j) { /* if there's no record at this location, skip it */ if (!*v) continue; /* inherit the location if it hasn't been set to any value */ if ((*v)->vociloc == MCMONINV && !((*v)->vociflg & VOCIFLOCNIL)) loc = (*v)->vociilc; else loc = (*v)->vociloc; /* if this object is in the indicated location, add it */ if (loc == obj && !((*v)->vociflg & VOCIFCLASS)) { /* see if we have room in list buffer; expand buffer if not */ if (len + 3 > ctx->supcxlen) { uchar *newbuf; /* allocate a new buffer */ newbuf = mchalo(ctx->supcxerr, (len + 512), "supcont"); /* copy the old buffer's contents into the new buffer */ memcpy(newbuf, ctx->supcxbuf, ctx->supcxlen); /* remember the new buffer length */ ctx->supcxlen = len + 512; /* free the old buffer */ mchfre(ctx->supcxbuf); /* remember the new buffer */ ctx->supcxbuf = newbuf; /* sanity check for integer overflow */ if (len + 3 > ctx->supcxlen) errsig(ctx->supcxmem->mcmcxgl->mcmcxerr, ERR_SUPOVF); } ctx->supcxbuf[len] = DAT_OBJECT; oswp2(ctx->supcxbuf + len + 1, chi); len += 3; } } } oswp2(ctx->supcxbuf, len); objsetp(ctx->supcxmem, obj, prp, DAT_LIST, ctx->supcxbuf, ctx->supcxrun->runcxundo); }
/* get a new line from line source, processing '#' directives */ static int tokgetlin(tokcxdef *ctx, int dopound) { for (;;) { if (linget(ctx->tokcxlin)) { /* at eof in current source; resume parent if there is one */ if (ctx->tokcxlin->linpar) { lindef *parent; parent = ctx->tokcxlin->linpar; /* remember parent */ lincls(ctx->tokcxlin); /* close included file */ if (!ctx->tokcxdbg) /* if no debug context... */ mchfre(ctx->tokcxlin); /* free line source */ ctx->tokcxlin = parent; /* reset to parent line source */ if (parent->linflg & LINFCMODE) ctx->tokcxflg |= TOKCXFCMODE; else ctx->tokcxflg &= ~TOKCXFCMODE; continue; /* back for another attempt */ } else { /* check for outstanding #if/#ifdef */ if (ctx->tokcxifcnt) errlog(ctx->tokcxerr, ERR_NOENDIF); /* return end-of-file indication */ return TRUE; } } /* if this is a multi-segment line, copy it into our own buffer */ if (ctx->tokcxlin->linflg & LINFMORE) { char *p; uint rem; int done; if (!ctx->tokcxbuf) { /* allocate 1k as a default buffer */ ctx->tokcxbuf = (char *)mchalo(ctx->tokcxerr, 1024, "tok"); ctx->tokcxbsz = 1024; } ctx->tokcxlen = 0; for (done = FALSE, p = ctx->tokcxbuf, rem = ctx->tokcxbsz ; !done ; ) { size_t len = ctx->tokcxlin->linlen; /* add the current segment's length into line length */ ctx->tokcxlen += len; /* we're done after this piece if the last fetch was all */ done = !(ctx->tokcxlin->linflg & LINFMORE); if (len + 1 > rem) { char *newp; /* increase the size of the buffer */ if (ctx->tokcxbsz > (unsigned)0x8000) errsig(ctx->tokcxerr, ERR_LONGLIN); rem += 4096; ctx->tokcxbsz += 4096; /* allocate a new buffer and copy line into it */ newp = (char *)mchalo(ctx->tokcxerr, ctx->tokcxbsz, "tok"); memcpy(newp, ctx->tokcxbuf, (size_t)(p - ctx->tokcxbuf)); /* free the original buffer, and use the new one */ p = (p - ctx->tokcxbuf) + newp; mchfre(ctx->tokcxbuf); ctx->tokcxbuf = newp; } /* add the line to the buffer */ memcpy(p, ctx->tokcxlin->linbuf, len); p += len; rem -= len; /* get the next piece of the line if there is one */ if (!done) { if (linget(ctx->tokcxlin)) break; } } /* null-terminate the buffer, and use it for input */ *p = '\0'; ctx->tokcxptr = ctx->tokcxbuf; } else { ctx->tokcxptr = ctx->tokcxlin->linbuf; ctx->tokcxlen = ctx->tokcxlin->linlen; } /* check for preprocessor directives */ if (dopound && ctx->tokcxlen != 0 && ctx->tokcxptr[0] == '#' && !(ctx->tokcxlin->linflg & LINFNOINC)) { char *p; int len; static struct { char *nm; int len; int ok_in_if; void (*fn)(tokcxdef *, char *, int); } *dirp, dir[] = { { "include", 7, FALSE, tokinclude }, { "pragma", 6, FALSE, tokpragma }, { "define", 6, FALSE, tokdefine }, { "ifdef", 5, TRUE, tokifdef }, { "ifndef", 6, TRUE, tokifndef }, { "if", 2, TRUE, tokif }, { "else", 4, TRUE, tokelse }, { "elif", 4, TRUE, tokelif }, { "endif", 5, TRUE, tokendif }, { "undef", 5, FALSE, tokundef }, { "error", 5, FALSE, tok_p_error } }; int i; /* scan off spaces between '#' and directive */ for (len = ctx->tokcxlen - 1, p = &ctx->tokcxptr[1] ; len && t_isspace(*p) ; --len, ++p) ; /* find and process the directive */ for (dirp = dir, i = sizeof(dir)/sizeof(dir[0]) ; i ; --i, ++dirp) { /* compare this directive; if it wins, call its function */ if (len >= dirp->len && !memcmp(p, dirp->nm, (size_t)dirp->len) && (len == dirp->len || t_isspace(*(p + dirp->len)))) { int cnt; int stat; /* * if we're not in a #if's false part, or if the * directive is processed even in #if false parts, * process the line, otherwise skip it */ cnt = ctx->tokcxifcnt; if (dirp->ok_in_if || cnt == 0 || ((stat = ctx->tokcxifcur) == TOKIF_IF_YES || stat == TOKIF_ELSE_YES)) { /* skip whitespace following the directive */ for (p += dirp->len, len -= dirp->len ; len && t_isspace(*p) ; --len, ++p) ; /* invoke the function to process this directive */ (*dirp->fn)(ctx, p, len); } /* there's no need to look at more directives */ break; } } /* if we didn't find anything, flag the error */ if (i == 0) errlog(ctx->tokcxerr, ERR_PRPDIR); /* ignore this line */ continue; } else { /* * Check the #if level. If we're in an #if, and we're to * ignore lines (because of a false condition or an #else * part for a true condition), skip this line. */ if (ctx->tokcxifcnt != 0) { switch(ctx->tokcxifcur) { case TOKIF_IF_NO: case TOKIF_ELSE_NO: /* ignore this line */ continue; default: /* we're in a true part - keep the line */ break; } } ctx->tokcxlin->linflg &= ~LINFDBG; /* no debug record yet */ return(FALSE); /* return the line we found */ } } }