Annotation of researchv9/jtools/src/sam/file.c, revision 1.1

1.1     ! root        1: #include "sam.h"
        !             2: 
        !             3: /*
        !             4:  * Files are splayed out a factor of NDISC to reduce indirect block access
        !             5:  */
        !             6: Discdesc       *files[NDISC];
        !             7: Discdesc       *transcripts[NDISC];
        !             8: Buffer         *undobuf;
        !             9: static String  *ftempstr();
        !            10: int            fcount;
        !            11: 
        !            12: #ifdef SUN
        !            13: #define SKIP 50
        !            14: #define MAXCACHE 25000
        !            15: #else
        !            16: enum{
        !            17:        SKIP=50,        /* max dist between file changes folded together */
        !            18:        MAXCACHE=25000, /* max length of cache. must be < 32K-BLOCKSIZE */
        !            19: };
        !            20: #endif
        !            21: 
        !            22: Fstart()
        !            23: {
        !            24:        undobuf=Bopen(Dstart());
        !            25:        snarfbuf=Bopen(Dstart());
        !            26: }
        !            27: File *
        !            28: Fopen()
        !            29: {
        !            30:        register File *f;
        !            31:        f=new(File, 1);
        !            32:        if(files[fcount]==0){
        !            33:                files[fcount]=Dstart();
        !            34:                transcripts[fcount]=Dstart();
        !            35:        }
        !            36:        f->buf=Bopen(files[fcount]);
        !            37:        f->transcript=Bopen(transcripts[fcount]);
        !            38:        if(++fcount==NDISC)
        !            39:                fcount=0;
        !            40:        f->nbytes=0;
        !            41:        f->markp=0;
        !            42:        f->mod=0;
        !            43:        f->dot.f=f;
        !            44:        strinit(&f->name);
        !            45:        straddc(&f->name, '\0');
        !            46:        strinit(&f->cache);
        !            47:        f->state=Unread;
        !            48:        Fmark(f, (Mod)0);
        !            49:        return f;
        !            50: }
        !            51: Fclose(f)
        !            52:        File *f;
        !            53: {
        !            54:        Bclose(f->buf);
        !            55:        Bclose(f->transcript);
        !            56:        strclose(&f->name);
        !            57:        strclose(&f->cache);
        !            58:        if(f->rasp)
        !            59:                listfree(f->rasp);
        !            60:        free((uchar *)f);
        !            61: }
        !            62: Fmark(f, m)
        !            63:        register File *f;
        !            64:        Mod m;
        !            65: {
        !            66:        register Buffer *t=f->transcript;
        !            67:        Posn p;
        !            68:        if(f->state==Unread)    /* this is implicit 'e' of a file */
        !            69:                return;
        !            70:        p=m==0? -1 : f->markp;
        !            71:        f->markp=t->nbytes;
        !            72:        puthdr_M(t, p, f->dot.r, f->mark, f->mod, f->state);
        !            73:        f->marked=TRUE;
        !            74:        f->mod=m;
        !            75:        f->hiposn= -1;
        !            76:        /* Safety first */
        !            77:        f->cp1=f->cp2=0;
        !            78:        strzero(&f->cache);
        !            79: }
        !            80: Finsert(f, str, p1)
        !            81:        register File *f;
        !            82:        String *str;
        !            83:        Posn p1;
        !            84: {
        !            85:        register Buffer *t=f->transcript;
        !            86:        if(str->n==0)
        !            87:                return;
        !            88:        if(str->n<0 || str->n>32767)
        !            89:                panic("Finsert");
        !            90:        if(f->mod<modnum)
        !            91:                Fmark(f, modnum);
        !            92:        if(p1<f->hiposn)
        !            93:                error(Esequence);
        !            94:        if(str->n>=BLOCKSIZE){  /* don't bother with the cache */
        !            95:                Fflush(f);
        !            96:                puthdr_csP(t, 'i', str->n, p1);
        !            97:                Binsert(t, str, t->nbytes);
        !            98:        }else{  /* insert into the cache instead of the transcript */
        !            99:                if(f->cp2==0 && f->cp1==0 && f->cache.n==0)     /* empty cache */
        !           100:                        f->cp1=f->cp2=p1;
        !           101:                if(p1-f->cp2>SKIP || (long)f->cache.n+(long)str->n>MAXCACHE){
        !           102:                        Fflush(f);
        !           103:                        f->cp1=f->cp2=p1;
        !           104:                }
        !           105:                if(f->cp2!=p1){ /* grab the piece in between */
        !           106:                        unsigned char buf[SKIP];
        !           107:                        String s;
        !           108:                        Fchars(f, buf, f->cp2, p1);
        !           109:                        s.s=buf;
        !           110:                        s.n=p1-f->cp2;
        !           111:                        strinsert(&f->cache, &s, (long)f->cache.n);
        !           112:                        f->cp2=p1;
        !           113:                }
        !           114:                strinsert(&f->cache, str, (long)f->cache.n);
        !           115:        }
        !           116:        if(f!=cmd)
        !           117:                quitok=FALSE;
        !           118:        f->closeok=FALSE;
        !           119:        if(f->state==Clean)
        !           120:                state(f, Dirty);
        !           121:        f->hiposn=p1;
        !           122: }
        !           123: Fdelete(f, p1, p2)
        !           124:        register File *f;
        !           125:        Posn p1, p2;
        !           126: {
        !           127:        if(p1==p2)
        !           128:                return;
        !           129:        if(f->mod<modnum)
        !           130:                Fmark(f, modnum);
        !           131:        if(p1<f->hiposn)
        !           132:                error(Esequence);
        !           133:        if(p1-f->cp2>SKIP)
        !           134:                Fflush(f);
        !           135:        if(f->cp2==0 && f->cp1==0 && f->cache.n==0)     /* empty cache */
        !           136:                f->cp1=f->cp2=p1;
        !           137:        if(f->cp2!=p1){ /* grab the piece in between */
        !           138:                if(f->cache.n+(p1-f->cp2)>MAXCACHE){
        !           139:                        Fflush(f);
        !           140:                        f->cp1=f->cp2=p1;
        !           141:                }else{
        !           142:                        unsigned char buf[SKIP];
        !           143:                        String s;
        !           144:                        Fchars(f, buf, f->cp2, p1);
        !           145:                        s.s=buf;
        !           146:                        s.n=p1-f->cp2;
        !           147:                        strinsert(&f->cache, &s, (long)f->cache.n);
        !           148:                }
        !           149:        }
        !           150:        f->cp2=p2;
        !           151:        if(f!=cmd)
        !           152:                quitok=FALSE;
        !           153:        f->closeok=FALSE;
        !           154:        if(f->state==Clean)
        !           155:                state(f, Dirty);
        !           156:        f->hiposn=p2;
        !           157: }
        !           158: Fflush(f)
        !           159:        register File *f;
        !           160: {
        !           161:        register Buffer *t=f->transcript;
        !           162:        register Posn p1=f->cp1, p2=f->cp2;
        !           163:        if(p1!=p2)
        !           164:                puthdr_cPP(t, 'd', p1, p2);
        !           165:        if(f->cache.n){
        !           166:                puthdr_csP(t, 'i', f->cache.n, p2);
        !           167:                Binsert(t, &f->cache, t->nbytes);
        !           168:                strzero(&f->cache);
        !           169:        }
        !           170:        f->cp1=f->cp2=0;
        !           171: }
        !           172: Fsetname(f)
        !           173:        register File *f;
        !           174: {
        !           175:        register Buffer *t=f->transcript;
        !           176:        if(f->state==Unread){   /* This is setting initial file name */
        !           177:                strdupstr(&f->name, &genstr);
        !           178:                sortname(f);
        !           179:        }else{
        !           180:                if(f->mod<modnum)
        !           181:                        Fmark(f, modnum);
        !           182:                if(genstr.n>BLOCKSIZE)
        !           183:                        error(Elong);
        !           184:                puthdr_cs(t, 'f', genstr.n);
        !           185:                Binsert(t, &genstr, t->nbytes);
        !           186:        }
        !           187: }
        !           188: /*
        !           189:  * The heart of it all. Fupdate will run along the transcript list, executing
        !           190:  * the commands and converting them into their inverses for a later undo pass.
        !           191:  * The pass runs top to bottom, so addresses in the transcript are tracked
        !           192:  * (by the var. delta) so they stay valid during the operation.  This causes
        !           193:  * all operations to appear to happen simultaneously, which is why the addresses
        !           194:  * passed to Fdelete and Finsert never take into account other changes occurring
        !           195:  * in this command (and is why things are done this way).
        !           196:  */
        !           197: Fupdate(f, isundo, toterm)
        !           198:        register File *f;
        !           199: {
        !           200:        register Buffer *t=f->transcript;
        !           201:        register Buffer *u=undobuf;
        !           202:        register n, ni;
        !           203:        register Posn p0, p1, p2, p, deltadot=0, deltamark=0, delta=0;
        !           204:        int changes=FALSE;
        !           205:        uchar buf[32];
        !           206:        uchar tmp[BLOCKSIZE];
        !           207:        Fflush(f);
        !           208:        if(f->marked)
        !           209:                p0=f->markp+sizeof(Mark);
        !           210:        else
        !           211:                p0=0;
        !           212:        while((n=Bread(t, buf, sizeof buf, p0))>0){
        !           213:                switch(buf[0]){
        !           214:                default:
        !           215:                        panic("unknown in Fupdate");
        !           216:                case 'd':
        !           217:                        GETPOSN(p1, buf+1);
        !           218:                        GETPOSN(p2, buf+1+sizeof(Posn));
        !           219:                        p0+=1+2*sizeof(Posn);
        !           220:                        if(p2<=f->dot.r.p1)
        !           221:                                deltadot-=p2-p1;
        !           222:                        if(p2<=f->mark.p1)
        !           223:                                deltamark-=p2-p1;
        !           224:                        p1+=delta, p2+=delta;
        !           225:                        delta-=p2-p1;
        !           226:                        if(!isundo)
        !           227:                                for(p=p1; p<p2; p+=ni){
        !           228:                                        if(p2-p>BLOCKSIZE)
        !           229:                                                ni=BLOCKSIZE;
        !           230:                                        else
        !           231:                                                ni=p2-p;
        !           232:                                        puthdr_csP(u, 'i', ni, p1);
        !           233:                                        Bread(f->buf, tmp, ni, p);
        !           234:                                        Binsert(u, ftempstr(tmp, ni), u->nbytes);
        !           235:                                }
        !           236:                        f->nbytes-=p2-p1;
        !           237:                        Bdelete(f->buf, p1, p2);
        !           238:                        changes=TRUE;
        !           239:                        break;
        !           240:                case 'f':
        !           241:                        n=buf[1]&0xFF;
        !           242:                        n|=buf[2]<<8;
        !           243:                        p0+=1+SS;
        !           244:                        strinsure(&genstr, (ulong)n);
        !           245:                        Bread(t, tmp, n, p0);
        !           246:                        p0+=n;
        !           247:                        strdup(&genstr, tmp);
        !           248:                        if(!isundo){
        !           249:                                puthdr_cs(u, 'f', f->name.n);
        !           250:                                Binsert(u, &f->name, u->nbytes);
        !           251:                        }
        !           252:                        strdupstr(&f->name, &genstr);
        !           253:                        sortname(f);
        !           254:                        changes=TRUE;
        !           255:                        break;
        !           256:                case 'i':
        !           257:                        n=buf[1]&0xFF;
        !           258:                        n|=buf[2]<<8;
        !           259:                        GETPOSN(p1, (buf+1+SS));
        !           260:                        p0+=1+SS+sizeof(Posn);
        !           261:                        if(p1<f->dot.r.p1)
        !           262:                                deltadot+=n;
        !           263:                        if(p1<f->mark.p1)
        !           264:                                deltamark+=n;
        !           265:                        p1+=delta;
        !           266:                        delta+=n;
        !           267:                        if(!isundo)
        !           268:                                puthdr_cPP(u, 'd', p1, p1+n);
        !           269:                        changes=TRUE;
        !           270:                        f->nbytes+=n;
        !           271:                        while(n>0){
        !           272:                                if(n>BLOCKSIZE)
        !           273:                                        ni=BLOCKSIZE;
        !           274:                                else
        !           275:                                        ni=n;
        !           276:                                Bread(t, tmp, ni, p0);
        !           277:                                Binsert(f->buf, ftempstr(tmp, ni), p1);
        !           278:                                n-=ni;
        !           279:                                p1+=ni;
        !           280:                                p0+=ni;
        !           281:                        }
        !           282:                        break;
        !           283:                }
        !           284:        }
        !           285:        toterminal(f, toterm);
        !           286:        f->dot.r.p1+=deltadot;
        !           287:        f->dot.r.p2+=deltadot;
        !           288:        if(f->dot.r.p1>f->nbytes)
        !           289:                f->dot.r.p1=f->nbytes;
        !           290:        if(f->dot.r.p2>f->nbytes)
        !           291:                f->dot.r.p2=f->nbytes;
        !           292:        f->mark.p1+=deltamark;
        !           293:        f->mark.p2+=deltamark;
        !           294:        if(f->mark.p1>f->nbytes)
        !           295:                f->mark.p1=f->nbytes;
        !           296:        if(f->mark.p2>f->nbytes)
        !           297:                f->mark.p2=f->nbytes;
        !           298:        if(n<0)
        !           299:                panic("Fupdate read");
        !           300:        if(f==cmd)
        !           301:                f->mod=0;       /* can't undo command file */
        !           302:        if(p0>f->markp+sizeof(Posn)){   /* for undo, this throws away the undo transcript */
        !           303:                if(f->mod>0){   /* can't undo the dawn of time */
        !           304:                        Bdelete(t, f->markp+sizeof(Mark), t->nbytes);
        !           305:                        /* copy the undo list back into the transcript */
        !           306:                        for(p=0; p<u->nbytes; p+=ni){
        !           307:                                if(u->nbytes-p>BLOCKSIZE)
        !           308:                                        ni=BLOCKSIZE;
        !           309:                                else
        !           310:                                        ni=u->nbytes-p;
        !           311:                                Bread(u, tmp, ni, p);
        !           312:                                Binsert(t, ftempstr(tmp, ni), t->nbytes);
        !           313:                        }
        !           314:                }
        !           315:                Bdelete(u, (Posn)0, u->nbytes);
        !           316:        }
        !           317:        return f==cmd? FALSE : changes;
        !           318: }
        !           319: puthdr_csP(b, c, s, p)
        !           320:        Buffer *b;
        !           321:        char c;
        !           322:        short s;
        !           323:        Posn p;
        !           324: {
        !           325:        uchar buf[1+2+sizeof p];
        !           326:        register uchar *a=buf;
        !           327:        if(p<0)
        !           328:                panic("puthdr_csP");
        !           329:        *a++=c;
        !           330:        *a++=s;
        !           331:        *a++=s>>8;
        !           332:        PUTPOSN(a, &p);
        !           333:        Binsert(b, ftempstr(buf, sizeof buf), b->nbytes);
        !           334: }
        !           335: puthdr_cs(b, c, s)
        !           336:        Buffer *b;
        !           337:        char c;
        !           338:        short s;
        !           339: {
        !           340:        uchar buf[1+2];
        !           341:        register uchar *a=buf;
        !           342:        *a++=c;
        !           343:        *a++=s;
        !           344:        *a=s>>8;
        !           345:        Binsert(b, ftempstr(buf, sizeof buf), b->nbytes);
        !           346: }
        !           347: puthdr_M(b, p, dot, mk, m, s1)
        !           348:        Buffer *b;
        !           349:        Posn p;
        !           350:        Range dot;
        !           351:        Range mk;
        !           352:        Mod m;
        !           353:        short s1;
        !           354: {
        !           355:        Mark mark;
        !           356:        static first=1;
        !           357:        if(!first && p<0)
        !           358:                panic("puthdr_M");
        !           359:        mark.p=p;
        !           360:        mark.dot=dot;
        !           361:        mark.mark=mk;
        !           362:        mark.m=m;
        !           363:        mark.s1=s1;
        !           364:        Binsert(b, ftempstr((uchar *)&mark, sizeof mark), b->nbytes);
        !           365: }
        !           366: puthdr_cPP(b, c, p1, p2)
        !           367:        Buffer *b;
        !           368:        char c;
        !           369:        Posn p1, p2;
        !           370: {
        !           371:        uchar buf[1+2*sizeof p1];
        !           372:        register uchar *a=buf;
        !           373:        if(p1<0 || p2<0)
        !           374:                panic("puthdr_cPP");
        !           375:        *a++=c;
        !           376:        PUTPOSN(a, &p1);
        !           377:        PUTPOSN(a, &p2);
        !           378:        Binsert(b, ftempstr(buf, sizeof buf), b->nbytes);
        !           379: }
        !           380: Fchars(f, addr, p1, p2)
        !           381:        register File *f;
        !           382:        uchar *addr;
        !           383:        Posn p1, p2;
        !           384: {
        !           385:        return Bread(f->buf, addr, (int)(p2-p1), p1);
        !           386: }
        !           387: Fgetcset(f, p)
        !           388:        File *f;
        !           389:        Posn p;
        !           390: {
        !           391:        if(p<0 || p>f->nbytes)
        !           392:                panic("Fgetcset out of range");
        !           393:        if((f->ngetc=Fchars(f, f->getcbuf, p, p+NGETC))<0)
        !           394:                panic("Fgetcset Bread fail");
        !           395:        f->getcp=p;
        !           396:        f->getci=0;
        !           397:        return f->ngetc;
        !           398: }
        !           399: Fbgetcset(f, p)
        !           400:        File *f;
        !           401:        Posn p;
        !           402: {
        !           403:        if(p<0 || p>f->nbytes)
        !           404:                panic("Fbgetcset out of range");
        !           405:        if((f->ngetc=Fchars(f, f->getcbuf, p<NGETC? (Posn)0 : p-NGETC, p))<0)
        !           406:                panic("Fbgetcset Bread fail");
        !           407:        f->getcp=p;
        !           408:        f->getci=f->ngetc;
        !           409:        return f->ngetc;
        !           410: }
        !           411: Fgetcload(f, p)
        !           412:        File *f;
        !           413:        Posn p;
        !           414: {
        !           415:        if(Fgetcset(f, p)){
        !           416:                --f->ngetc;
        !           417:                f->getcp++;
        !           418:                return f->getcbuf[f->getci++];
        !           419:        }
        !           420:        return -1;
        !           421: }
        !           422: Fbgetcload(f, p)
        !           423:        File *f;
        !           424:        Posn p;
        !           425: {
        !           426:        if(Fbgetcset(f, p)){
        !           427:                --f->getcp;
        !           428:                return f->getcbuf[--f->getci];
        !           429:        }
        !           430:        return -1;
        !           431: }
        !           432: static String *
        !           433: ftempstr(s, n)
        !           434:        uchar *s;
        !           435: {
        !           436:        static String p;
        !           437:        p.s=(uchar *)s;
        !           438:        p.n=n;
        !           439:        p.size=n;
        !           440:        return &p;
        !           441: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.