Annotation of 3BSD/cmd/ex/ex_temp.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #include "ex.h"
                      3: #include "ex_temp.h"
                      4: #include "ex_vis.h"
                      5: #include "ex_tty.h"
                      6: 
                      7: /*
                      8:  * Editor temporary file routines.
                      9:  * Very similar to those of ed, except uses 2 input buffers.
                     10:  */
                     11: #define        READ    0
                     12: #define        WRITE   1
                     13: 
                     14: char   tfname[40];
                     15: char   rfname[40];
                     16: int    havetmp;
                     17: short  tfile = -1;
                     18: short  rfile = -1;
                     19: 
                     20: fileinit()
                     21: {
                     22:        register char *p;
                     23:        register int i, j;
                     24:        struct stat stbuf;
                     25: 
                     26:        if (tline == INCRMT * (HBLKS+2))
                     27:                return;
                     28:        cleanup(0);
                     29:        close(tfile);
                     30:        tline = INCRMT * (HBLKS+2);
                     31:        blocks[0] = HBLKS;
                     32:        blocks[1] = HBLKS+1;
                     33:        blocks[2] = -1;
                     34:        dirtcnt = 0;
                     35:        iblock = -1;
                     36:        iblock2 = -1;
                     37:        oblock = -1;
                     38:        CP(tfname, svalue(DIRECTORY));
                     39:        if (stat(tfname, &stbuf)) {
                     40: dumbness:
                     41:                if (setexit() == 0)
                     42:                        filioerr(tfname);
                     43:                else
                     44:                        putNFL();
                     45:                cleanup(1);
                     46:                exit(1);
                     47:        }
                     48:        if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
                     49:                errno = ENOTDIR;
                     50:                goto dumbness;
                     51:        }
                     52:        ichanged = 0;
                     53:        ichang2 = 0;
                     54:        ignore(strcat(tfname, "/ExXXXXX"));
                     55:        for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
                     56:                *--p = j % 10 | '0';
                     57:        tfile = creat(tfname, 0600);
                     58:        if (tfile < 0)
                     59:                goto dumbness;
                     60:        havetmp = 1;
                     61:        close(tfile);
                     62:        tfile = open(tfname, 2);
                     63:        if (tfile < 0)
                     64:                goto dumbness;
                     65: /*     brk((char *)fendcore); */
                     66: }
                     67: 
                     68: cleanup(all)
                     69:        bool all;
                     70: {
                     71:        if (all) {
                     72:                putpad(TE);
                     73:                flush();
                     74:        }
                     75:        if (havetmp)
                     76:                unlink(tfname);
                     77:        havetmp = 0;
                     78:        if (all && rfile >= 0) {
                     79:                unlink(rfname);
                     80:                close(rfile);
                     81:                rfile = -1;
                     82:        }
                     83: }
                     84: 
                     85: getline(tl)
                     86:        line tl;
                     87: {
                     88:        register char *bp, *lp;
                     89:        register int nl;
                     90: 
                     91:        lp = linebuf;
                     92:        bp = getblock(tl, READ);
                     93:        nl = nleft;
                     94:        tl &= ~OFFMSK;
                     95:        while (*lp++ = *bp++)
                     96:                if (--nl == 0) {
                     97:                        bp = getblock(tl += INCRMT, READ);
                     98:                        nl = nleft;
                     99:                }
                    100: }
                    101: 
                    102: putline()
                    103: {
                    104:        register char *bp, *lp;
                    105:        register int nl;
                    106:        line tl;
                    107: 
                    108:        dirtcnt++;
                    109:        lp = linebuf;
                    110:        change();
                    111:        tl = tline;
                    112:        bp = getblock(tl, WRITE);
                    113:        nl = nleft;
                    114:        tl &= ~OFFMSK;
                    115:        while (*bp = *lp++) {
                    116:                if (*bp++ == '\n') {
                    117:                        *--bp = 0;
                    118:                        linebp = lp;
                    119:                        break;
                    120:                }
                    121:                if (--nl == 0) {
                    122:                        bp = getblock(tl += INCRMT, WRITE);
                    123:                        nl = nleft;
                    124:                }
                    125:        }
                    126:        tl = tline;
                    127:        tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
                    128:        return (tl);
                    129: }
                    130: 
                    131: int    read();
                    132: int    write();
                    133: 
                    134: char *
                    135: getblock(atl, iof)
                    136:        line atl;
                    137:        int iof;
                    138: {
                    139:        register int bno, off;
                    140:        
                    141:        bno = (atl >> OFFBTS) & BLKMSK;
                    142:        off = (atl << SHFT) & LBTMSK;
                    143:        if (bno >= NMBLKS)
                    144:                error(" Tmp file too large");
                    145:        nleft = BUFSIZ - off;
                    146:        if (bno == iblock) {
                    147:                ichanged |= iof;
                    148:                hitin2 = 0;
                    149:                return (ibuff + off);
                    150:        }
                    151:        if (bno == iblock2) {
                    152:                ichang2 |= iof;
                    153:                hitin2 = 1;
                    154:                return (ibuff2 + off);
                    155:        }
                    156:        if (bno == oblock)
                    157:                return (obuff + off);
                    158:        if (iof == READ) {
                    159:                if (hitin2 == 0) {
                    160:                        if (ichang2)
                    161:                                blkio(iblock2, ibuff2, write);
                    162:                        ichang2 = 0;
                    163:                        iblock2 = bno;
                    164:                        blkio(bno, ibuff2, read);
                    165:                        hitin2 = 1;
                    166:                        return (ibuff2 + off);
                    167:                }
                    168:                hitin2 = 0;
                    169:                if (ichanged)
                    170:                        blkio(iblock, ibuff, write);
                    171:                ichanged = 0;
                    172:                iblock = bno;
                    173:                blkio(bno, ibuff, read);
                    174:                return (ibuff + off);
                    175:        }
                    176:        if (oblock >= 0)
                    177:                blkio(oblock, obuff, write);
                    178:        oblock = bno;
                    179:        return (obuff + off);
                    180: }
                    181: 
                    182: blkio(b, buf, iofcn)
                    183:        short b;
                    184:        char *buf;
                    185:        int (*iofcn)();
                    186: {
                    187: 
                    188:        lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
                    189:        if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
                    190:                filioerr(tfname);
                    191: }
                    192: 
                    193: /*
                    194:  * Synchronize the state of the temporary file in case
                    195:  * a crash occurs.
                    196:  */
                    197: synctmp()
                    198: {
                    199:        register int cnt;
                    200:        register line *a;
                    201:        register short *bp;
                    202: 
                    203:        if (dol == zero)
                    204:                return;
                    205:        if (ichanged)
                    206:                blkio(iblock, ibuff, write);
                    207:        ichanged = 0;
                    208:        if (ichang2)
                    209:                blkio(iblock2, ibuff2, write);
                    210:        ichang2 = 0;
                    211:        if (oblock != -1)
                    212:                blkio(oblock, obuff, write);
                    213:        time(&H.Time);
                    214:        uid = getuid();
                    215:        *zero = (line) H.Time;
                    216:        for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
                    217:                if (*bp < 0) {
                    218:                        tline = (tline + OFFMSK) &~ OFFMSK;
                    219:                        *bp = ((tline >> OFFBTS) & BLKMSK);
                    220:                        tline += INCRMT;
                    221:                        oblock = *bp + 1;
                    222:                        bp[1] = -1;
                    223:                }
                    224:                lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
                    225:                cnt = ((dol - a) + 2) * sizeof (line);
                    226:                if (cnt > BUFSIZ)
                    227:                        cnt = BUFSIZ;
                    228:                if (write(tfile, (char *) a, cnt) != cnt) {
                    229: oops:
                    230:                        *zero = 0;
                    231:                        filioerr(tfname);
                    232:                }
                    233:                *zero = 0;
                    234:        }
                    235:        flines = lineDOL();
                    236:        lseek(tfile, 0l, 0);
                    237:        if (write(tfile, (char *) &H, sizeof H) != sizeof H)
                    238:                goto oops;
                    239: }
                    240: 
                    241: TSYNC()
                    242: {
                    243: 
                    244:        if (dirtcnt > 12) {
                    245:                dirtcnt = 0;
                    246:                synctmp();
                    247:        }
                    248: }
                    249: 
                    250: /*
                    251:  * Named buffer routines.
                    252:  * These are implemented differently than the main buffer.
                    253:  * Each named buffer has a chain of blocks in the register file.
                    254:  * Each block contains roughly 508 chars of text,
                    255:  * and a previous and next block number.  We also have information
                    256:  * about which blocks came from deletes of multiple partial lines,
                    257:  * e.g. deleting a sentence or a LISP object.
                    258:  *
                    259:  * We maintain a free map for the temp file.  To free the blocks
                    260:  * in a register we must read the blocks to find how they are chained
                    261:  * together.
                    262:  *
                    263:  * BUG:                The default savind of deleted lines in numbered
                    264:  *             buffers may be rather inefficient; it hasn't been profiled.
                    265:  */
                    266: struct strreg {
                    267:        short   rg_flags;
                    268:        short   rg_nleft;
                    269:        short   rg_first;
                    270:        short   rg_last;
                    271: } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
                    272: 
                    273: struct rbuf {
                    274:        short   rb_prev;
                    275:        short   rb_next;
                    276:        char    rb_text[BUFSIZ - 2 * sizeof (short)];
                    277: } *rbuf;
                    278: short  rused[32];
                    279: short  rnleft;
                    280: short  rblock;
                    281: short  rnext;
                    282: char   *rbufcp;
                    283: 
                    284: regio(b, iofcn)
                    285:        short b;
                    286:        int (*iofcn)();
                    287: {
                    288: 
                    289:        if (rfile == -1) {
                    290:                CP(rfname, tfname);
                    291:                *(strend(rfname) - 7) = 'R';
                    292:                rfile = creat(rfname, 0600);
                    293:                if (rfile < 0)
                    294: oops:
                    295:                        filioerr(rfname);
                    296:                close(rfile);
                    297:                rfile = open(rfname, 2);
                    298:                if (rfile < 0)
                    299:                        goto oops;
                    300:        }
                    301:        lseek(rfile, (long) b * BUFSIZ, 0);
                    302:        if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
                    303:                goto oops;
                    304:        rblock = b;
                    305: }
                    306: 
                    307: REGblk()
                    308: {
                    309:        register int i, j, m;
                    310: 
                    311:        for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
                    312:                m = (rused[i] ^ 0177777) & 0177777;
                    313:                if (i == 0)
                    314:                        m &= ~1;
                    315:                if (m != 0) {
                    316:                        j = 0;
                    317:                        while ((m & 1) == 0)
                    318:                                j++, m >>= 1;
                    319:                        rused[i] |= (1 << j);
                    320: #ifdef RDEBUG
                    321:                        printf("allocating block %d\n", i * 16 + j);
                    322: #endif
                    323:                        return (i * 16 + j);
                    324:                }
                    325:        }
                    326:        error("Out of register space (ugh)");
                    327:        /*NOTREACHED*/
                    328: }
                    329: 
                    330: struct strreg *
                    331: mapreg(c)
                    332:        register int c;
                    333: {
                    334: 
                    335:        if (isupper(c))
                    336:                c = tolower(c);
                    337:        return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
                    338: }
                    339: 
                    340: int    shread();
                    341: 
                    342: KILLreg(c)
                    343:        register int c;
                    344: {
                    345:        struct rbuf arbuf;
                    346:        register struct strreg *sp;
                    347: 
                    348:        rbuf = &arbuf;
                    349:        sp = mapreg(c);
                    350:        rblock = sp->rg_first;
                    351:        sp->rg_first = sp->rg_last = 0;
                    352:        sp->rg_flags = sp->rg_nleft = 0;
                    353:        while (rblock != 0) {
                    354: #ifdef RDEBUG
                    355:                printf("freeing block %d\n", rblock);
                    356: #endif
                    357:                rused[rblock / 16] &= ~(1 << (rblock % 16));
                    358:                regio(rblock, shread);
                    359:                rblock = rbuf->rb_next;
                    360:        }
                    361: }
                    362: 
                    363: /*VARARGS*/
                    364: shread()
                    365: {
                    366:        struct front { short a; short b; };
                    367: 
                    368:        if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
                    369:                return (sizeof (struct rbuf));
                    370:        return (0);
                    371: }
                    372: 
                    373: int    getREG();
                    374: 
                    375: putreg(c)
                    376:        char c;
                    377: {
                    378:        struct rbuf arbuf;
                    379:        register line *odot = dot;
                    380:        register line *odol = dol;
                    381:        register int cnt;
                    382: 
                    383:        deletenone();
                    384:        appendnone();
                    385:        rbuf = &arbuf;
                    386:        rnleft = 0;
                    387:        rblock = 0;
                    388:        rnext = mapreg(c)->rg_first;
                    389:        if (rnext == 0) {
                    390:                if (inopen) {
                    391:                        splitw++;
                    392:                        vclean();
                    393:                        vgoto(WECHO, 0);
                    394:                }
                    395:                vreg = -1;
                    396:                error("Nothing in register %c", c);
                    397:        }
                    398:        if (inopen && partreg(c)) {
                    399:                squish();
                    400:                addr1 = addr2 = dol;
                    401:        }
                    402:        ignore(append(getREG, addr2));
                    403:        if (inopen && partreg(c)) {
                    404:                unddol = dol;
                    405:                dol = odol;
                    406:                dot = odot;
                    407:                pragged(0);
                    408:        }
                    409:        cnt = undap2 - undap1;
                    410:        killcnt(cnt);
                    411:        notecnt = cnt;
                    412: }
                    413: 
                    414: partreg(c)
                    415:        char c;
                    416: {
                    417: 
                    418:        return (mapreg(c)->rg_flags);
                    419: }
                    420: 
                    421: notpart(c)
                    422:        register int c;
                    423: {
                    424: 
                    425:        if (c)
                    426:                mapreg(c)->rg_flags = 0;
                    427: }
                    428: 
                    429: getREG()
                    430: {
                    431:        register char *lp = linebuf;
                    432:        register int c;
                    433: 
                    434:        for (;;) {
                    435:                if (rnleft == 0) {
                    436:                        if (rnext == 0)
                    437:                                return (EOF);
                    438:                        regio(rnext, read);
                    439:                        rnext = rbuf->rb_next;
                    440:                        rbufcp = rbuf->rb_text;
                    441:                        rnleft = sizeof rbuf->rb_text;
                    442:                }
                    443:                c = *rbufcp;
                    444:                if (c == 0)
                    445:                        return (EOF);
                    446:                rbufcp++, --rnleft;
                    447:                if (c == '\n') {
                    448:                        *lp++ = 0;
                    449:                        return (0);
                    450:                }
                    451:                *lp++ = c;
                    452:        }
                    453: }
                    454: 
                    455: YANKreg(c)
                    456:        register int c;
                    457: {
                    458:        struct rbuf arbuf;
                    459:        register line *addr;
                    460:        register struct strreg *sp;
                    461: 
                    462:        if (isdigit(c))
                    463:                kshift();
                    464:        if (islower(c))
                    465:                KILLreg(c);
                    466:        strp = sp = mapreg(c);
                    467:        sp->rg_flags = inopen && cursor && wcursor;
                    468:        rbuf = &arbuf;
                    469:        if (sp->rg_last) {
                    470:                regio(sp->rg_last, read);
                    471:                rnleft = sp->rg_nleft;
                    472:                rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
                    473:        } else {
                    474:                rblock = 0;
                    475:                rnleft = 0;
                    476:        }
                    477:        for (addr = addr1; addr <= addr2; addr++) {
                    478:                getline(*addr);
                    479:                if (sp->rg_flags) {
                    480:                        if (addr == addr2)
                    481:                                *wcursor = 0;
                    482:                        if (addr == addr1)
                    483:                                strcpy(linebuf, cursor);
                    484:                }
                    485:                YANKline();
                    486:        }
                    487:        rbflush();
                    488:        killed();
                    489: }
                    490: 
                    491: kshift()
                    492: {
                    493:        register int i;
                    494: 
                    495:        KILLreg('9');
                    496:        for (i = '8'; i >= '0'; i--)
                    497:                copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
                    498: }
                    499: 
                    500: YANKline()
                    501: {
                    502:        register char *lp = linebuf;
                    503:        register struct rbuf *rp = rbuf;
                    504:        register int c;
                    505: 
                    506:        do {
                    507:                c = *lp++;
                    508:                if (c == 0)
                    509:                        c = '\n';
                    510:                if (rnleft == 0) {
                    511:                        rp->rb_next = REGblk();
                    512:                        rbflush();
                    513:                        rblock = rp->rb_next;
                    514:                        rp->rb_next = 0;
                    515:                        rp->rb_prev = rblock;
                    516:                        rnleft = sizeof rp->rb_text;
                    517:                        rbufcp = rp->rb_text;
                    518:                }
                    519:                *rbufcp++ = c;
                    520:                --rnleft;
                    521:        } while (c != '\n');
                    522:        if (rnleft)
                    523:                *rbufcp = 0;
                    524: }
                    525: 
                    526: rbflush()
                    527: {
                    528:        register struct strreg *sp = strp;
                    529: 
                    530:        if (rblock == 0)
                    531:                return;
                    532:        regio(rblock, write);
                    533:        if (sp->rg_first == 0)
                    534:                sp->rg_first = rblock;
                    535:        sp->rg_last = rblock;
                    536:        sp->rg_nleft = rnleft;
                    537: }
                    538: 
                    539: /* Register c to char buffer buf of size buflen */
                    540: regbuf(c, buf, buflen)
                    541: char c;
                    542: char *buf;
                    543: int buflen;
                    544: {
                    545:        struct rbuf arbuf;
                    546:        register char *p, *lp;
                    547: 
                    548:        rbuf = &arbuf;
                    549:        rnleft = 0;
                    550:        rblock = 0;
                    551:        rnext = mapreg(c)->rg_first;
                    552:        if (rnext==0) {
                    553:                *buf = 0;
                    554:                error("Nothing in register %c",c);
                    555:        }
                    556:        p = buf;
                    557:        while (getREG()==0) {
                    558:                for (lp=linebuf; *lp;) {
                    559:                        if (p >= &buf[buflen])
                    560:                                error("Register too long@to fit in memory");
                    561:                        *p++ = *lp++;
                    562:                }
                    563:                *p++ = '\n';
                    564:        }
                    565:        if (partreg(c)) p--;
                    566:        *p = '\0';
                    567:        getDOT();
                    568: }

unix.superglobalmegacorp.com

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