/* cLowBinary.c - Underlying routines for the new Binary functions. */ #include "cLowBinary.h" #include #include #include void clearcache (BinHandle bh) { int i; for (i=CACHESIZE; i>0;) { bh->cache[--i]=0; } bh->cptr = 0; /*fprintf(stderr,"clearcache: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } /* invariant: virtual fileptr is at beginning of cache */ void nextcache (BinHandle bh) { if (bh->file) { switch (bh->mode) { case RO: bh->adjust.vptr += CACHESIZE - bh->attrib.eof; vread(bh); break; case WO: vwrite(bh); bh->adjust.vptr += CACHESIZE; clearcache(bh); break; case RW: vwrite(bh); bh->adjust.vptr += CACHESIZE; vread(bh); break; } } else { /*MEMORY*/ switch (bh->mode) { case RO: bh->adjust.here += CACHESIZE; mread(bh); break; case RW: mwrite(bh); bh->adjust.here += CACHESIZE; mread(bh); break; default: break; } } bh->cptr = 0; /*fprintf(stderr,"nextcache: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } void vread (BinHandle bh) { /* reads from the virtual fileptr */ vsync(bh); if (bh->attrib.eof = CACHESIZE - read(bh->loc.fd,bh->cache,CACHESIZE)) { int i; for (i=bh->attrib.eof; i>0; i--) { bh->cache[CACHESIZE-i]=0; } bh->adjust.vptr -= CACHESIZE - bh->attrib.eof; } else { bh->adjust.vptr -= CACHESIZE; } bh->cptr = 0; /*fprintf(stderr,"vread: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } /* invariant now holds again -> vptr is at start of cache */ void vwrite (BinHandle bh) { if (bh->w) { vsync(bh); write(bh->loc.fd,bh->cache,bh->w); bh->adjust.vptr = -bh->w; bh->w = CACHESIZE - bh->w; /* invert w */ bh->attrib.eof = (bh->attrib.eof<=bh->w ? bh->attrib.eof : bh->w); bh->w = 0; } /* invariant holds -> vptr still at *start* of cache */ /*fprintf(stderr,"vwrite: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } void opencache (BinHandle bh) { bh->w = 0; if (bh->file) bh->adjust.vptr = 0; switch (bh->mode) { case RO: case RW: if (bh->file) vread(bh); else mread(bh); break; case WO: clearcache(bh); break; } /*fprintf(stderr,"opencache: opened\n");*/ /*fprintf(stderr,"opencache: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } void closecache (BinHandle bh) { int end; /*fprintf(stderr,"before closecache: cache[0]=%x cptr=%d vptr=%d w=%d\n", bh->cache[0],bh->cptr,bh->adjust.vptr,bh->w);*/ switch (bh->mode) { case RO: break; case WO: case RW: if (bh->file) vwrite(bh); else mwrite(bh); break; } if (bh->file) bh->adjust.vptr += (bh->cptr/8); else bh->adjust.here += (bh->cptr/8); bh->cptr = 0; /*fprintf(stderr,"closecache: closed\n");*/ /*fprintf(stderr,"after closecache: cache[0]=%x cptr=%d vptr=%d w=%d\n", bh->cache[0],bh->cptr,bh->fm.f.vptr,bh->fm.f.w);*/ } int forceCacheTo (BinHandle bh, int bp) { int cacheStart; int bpbyte = bp / 8; if (bh->file) cacheStart=lseek(bh->loc.fd,0,SEEK_CUR) + bh->adjust.vptr; else cacheStart=bh->adjust.here; if ((cacheStart <= bpbyte) && (bpbyte < cacheStart + CACHESIZE)) { return cacheStart; } else { closecache(bh); if (bh->file) lseek(bh->loc.fd,bpbyte,SEEK_SET); else bh->adjust.here = bpbyte; /* ???? Maybe need to word-align ???? */ opencache(bh); return bpbyte; } /*fprintf(stderr,"forceCacheTo: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } void preFinaliseBH (BinHandle bh) { char c; int i; if (bh->file) { closecache(bh); if (bh->mode != RO) { c = (char)(bh->highwater%8); i = (c ? 1+(bh->highwater/8) : (bh->highwater/8)); c = (c ? 16-c : 8); lseek(bh->loc.fd,i,SEEK_SET); write(bh->loc.fd,&c,1); close(bh->loc.fd); } } else stableRelease(bh->loc.sp); } void finaliseBH (BinHandle bh) { preFinaliseBH(bh); free(bh); } void mread (BinHandle bh) { /* reads from heap space */ int avail = bh->attrib.size - bh->adjust.here; if (avail > 0) { if (avail < CACHESIZE) { clearcache(bh); memcpy (bh->cache, (void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here,avail); /*fprintf(stderr,"mread: cached %d bytes from location 0x%x\n", avail, (void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here);*/ } else { memcpy (bh->cache, (void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here,CACHESIZE); /*fprintf(stderr,"mread: cached %d bytes from location 0x%x\n", CACHESIZE, (void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here);*/ } } else { clearcache(bh); } bh->cptr = 0; /*fprintf(stderr,"vread: cache=%x cptr=%d\n",bh->cache[0],bh->cptr);*/ } /* invariant holds -> adjust.here is at start of cache */ void mwrite (BinHandle bh) { /*fprintf(stderr,"mwrite: cache=0x%x cptr=%d\n",bh->cache[0],bh->cptr);*/ /*fprintf(stderr," w=%d size=%d here=%d sp=%d\n",bh->w,*/ /* bh->attrib.size,bh->adjust.here,bh->loc.sp);*/ if (bh->w) { memcheck(bh,bh->w); /*fprintf(stderr," memcpy(sp,cache)\n");*/ memcpy((void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here, bh->cache,bh->w); /*fprintf(stderr,"mwrite: flushed %d bytes from cache to mem at 0x%x\n", bh->w, (void*)(stableRef(bh->loc.sp)+1+EXTRA)+bh->adjust.here);*/ bh->w = 0; } /* invariant holds -> adjust.here still at *start* of cache */ } void memcheck(BinHandle bh,int extrarequired) { int avail = bh->attrib.size - bh->adjust.here; if (availattrib.size = bh->adjust.here + extrarequired; words = words/sizeof(NodePtr) + (words%sizeof(NodePtr) ? 1 : 0) ; C_CHECK(words); /* call garbage collector if needed */ /* allocate more space, then copy old data across */ new = C_ALLOC(1+EXTRA+words); new[0] = CONSTRW(words,EXTRA); old = stableRef(bh->loc.sp); if (bh->adjust.here) { memcpy((void*)(&new[1+EXTRA]),(void*)(&old[1+EXTRA]),bh->adjust.here); } for (avail=1+(bh->adjust.here/sizeof(NodePtr)); availadjust.here, (void*)(&old[1+EXTRA]), (void*)(&new[1+EXTRA]));*/ /* and release old pointer */ stableRelease(bh->loc.sp); bh->loc.sp = stableInsert(new); } }