Annotation of researchv9/jtools/src/sam/file.c, revision 1.1.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.