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:             if (*bp > NMBLKS)
 221:                 error(" Tmp file too large");
 222:             tline += INCRMT;
 223:             oblock = *bp + 1;
 224:             bp[1] = -1;
 225:         }
 226:         lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
 227:         cnt = ((dol - a) + 2) * sizeof (line);
 228:         if (cnt > BUFSIZ)
 229:             cnt = BUFSIZ;
 230:         if (write(tfile, (char *) a, cnt) != cnt) {
 231: oops:
 232:             *zero = 0;
 233:             filioerr(tfname);
 234:         }
 235:         *zero = 0;
 236:     }
 237:     flines = lineDOL();
 238:     lseek(tfile, 0l, 0);
 239:     if (write(tfile, (char *) &H, sizeof H) != sizeof H)
 240:         goto oops;
 241: }
 242: 
 243: TSYNC()
 244: {
 245: 
 246:     if (dirtcnt > 12) {
 247:         dirtcnt = 0;
 248:         synctmp();
 249:     }
 250: }
 251: 
 252: /*
 253:  * Named buffer routines.
 254:  * These are implemented differently than the main buffer.
 255:  * Each named buffer has a chain of blocks in the register file.
 256:  * Each block contains roughly 508 chars of text,
 257:  * and a previous and next block number.  We also have information
 258:  * about which blocks came from deletes of multiple partial lines,
 259:  * e.g. deleting a sentence or a LISP object.
 260:  *
 261:  * We maintain a free map for the temp file.  To free the blocks
 262:  * in a register we must read the blocks to find how they are chained
 263:  * together.
 264:  *
 265:  * BUG:		The default savind of deleted lines in numbered
 266:  *		buffers may be rather inefficient; it hasn't been profiled.
 267:  */
 268: struct  strreg {
 269:     short   rg_flags;
 270:     short   rg_nleft;
 271:     short   rg_first;
 272:     short   rg_last;
 273: } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
 274: 
 275: struct  rbuf {
 276:     short   rb_prev;
 277:     short   rb_next;
 278:     char    rb_text[BUFSIZ - 2 * sizeof (short)];
 279: } *rbuf;
 280: short   rused[32];
 281: short   rnleft;
 282: short   rblock;
 283: short   rnext;
 284: char    *rbufcp;
 285: 
 286: regio(b, iofcn)
 287:     short b;
 288:     int (*iofcn)();
 289: {
 290: 
 291:     if (rfile == -1) {
 292:         CP(rfname, tfname);
 293:         *(strend(rfname) - 7) = 'R';
 294:         rfile = creat(rfname, 0600);
 295:         if (rfile < 0)
 296: oops:
 297:             filioerr(rfname);
 298:         close(rfile);
 299:         rfile = open(rfname, 2);
 300:         if (rfile < 0)
 301:             goto oops;
 302:     }
 303:     lseek(rfile, (long) b * BUFSIZ, 0);
 304:     if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
 305:         goto oops;
 306:     rblock = b;
 307: }
 308: 
 309: REGblk()
 310: {
 311:     register int i, j, m;
 312: 
 313:     for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
 314:         m = (rused[i] ^ 0177777) & 0177777;
 315:         if (i == 0)
 316:             m &= ~1;
 317:         if (m != 0) {
 318:             j = 0;
 319:             while ((m & 1) == 0)
 320:                 j++, m >>= 1;
 321:             rused[i] |= (1 << j);
 322: #ifdef RDEBUG
 323:             printf("allocating block %d\n", i * 16 + j);
 324: #endif
 325:             return (i * 16 + j);
 326:         }
 327:     }
 328:     error("Out of register space (ugh)");
 329:     /*NOTREACHED*/
 330: }
 331: 
 332: struct  strreg *
 333: mapreg(c)
 334:     register int c;
 335: {
 336: 
 337:     if (isupper(c))
 338:         c = tolower(c);
 339:     return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
 340: }
 341: 
 342: int shread();
 343: 
 344: KILLreg(c)
 345:     register int c;
 346: {
 347:     struct rbuf arbuf;
 348:     register struct strreg *sp;
 349: 
 350:     rbuf = &arbuf;
 351:     sp = mapreg(c);
 352:     rblock = sp->rg_first;
 353:     sp->rg_first = sp->rg_last = 0;
 354:     sp->rg_flags = sp->rg_nleft = 0;
 355:     while (rblock != 0) {
 356: #ifdef RDEBUG
 357:         printf("freeing block %d\n", rblock);
 358: #endif
 359:         rused[rblock / 16] &= ~(1 << (rblock % 16));
 360:         regio(rblock, shread);
 361:         rblock = rbuf->rb_next;
 362:     }
 363: }
 364: 
 365: /*VARARGS*/
 366: shread()
 367: {
 368:     struct front { short a; short b; };
 369: 
 370:     if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
 371:         return (sizeof (struct rbuf));
 372:     return (0);
 373: }
 374: 
 375: int getREG();
 376: 
 377: putreg(c)
 378:     char c;
 379: {
 380:     struct rbuf arbuf;
 381:     register line *odot = dot;
 382:     register line *odol = dol;
 383:     register int cnt;
 384: 
 385:     deletenone();
 386:     appendnone();
 387:     rbuf = &arbuf;
 388:     rnleft = 0;
 389:     rblock = 0;
 390:     rnext = mapreg(c)->rg_first;
 391:     if (rnext == 0) {
 392:         if (inopen) {
 393:             splitw++;
 394:             vclean();
 395:             vgoto(WECHO, 0);
 396:         }
 397:         vreg = -1;
 398:         error("Nothing in register %c", c);
 399:     }
 400:     if (inopen && partreg(c)) {
 401:         squish();
 402:         addr1 = addr2 = dol;
 403:     }
 404:     ignore(append(getREG, addr2));
 405:     if (inopen && partreg(c)) {
 406:         unddol = dol;
 407:         dol = odol;
 408:         dot = odot;
 409:         pragged(0);
 410:     }
 411:     cnt = undap2 - undap1;
 412:     killcnt(cnt);
 413:     notecnt = cnt;
 414: }
 415: 
 416: partreg(c)
 417:     char c;
 418: {
 419: 
 420:     return (mapreg(c)->rg_flags);
 421: }
 422: 
 423: notpart(c)
 424:     register int c;
 425: {
 426: 
 427:     if (c)
 428:         mapreg(c)->rg_flags = 0;
 429: }
 430: 
 431: getREG()
 432: {
 433:     register char *lp = linebuf;
 434:     register int c;
 435: 
 436:     for (;;) {
 437:         if (rnleft == 0) {
 438:             if (rnext == 0)
 439:                 return (EOF);
 440:             regio(rnext, read);
 441:             rnext = rbuf->rb_next;
 442:             rbufcp = rbuf->rb_text;
 443:             rnleft = sizeof rbuf->rb_text;
 444:         }
 445:         c = *rbufcp;
 446:         if (c == 0)
 447:             return (EOF);
 448:         rbufcp++, --rnleft;
 449:         if (c == '\n') {
 450:             *lp++ = 0;
 451:             return (0);
 452:         }
 453:         *lp++ = c;
 454:     }
 455: }
 456: 
 457: YANKreg(c)
 458:     register int c;
 459: {
 460:     struct rbuf arbuf;
 461:     register line *addr;
 462:     register struct strreg *sp;
 463: 
 464:     if (isdigit(c))
 465:         kshift();
 466:     if (islower(c))
 467:         KILLreg(c);
 468:     strp = sp = mapreg(c);
 469:     sp->rg_flags = inopen && cursor && wcursor;
 470:     rbuf = &arbuf;
 471:     if (sp->rg_last) {
 472:         regio(sp->rg_last, read);
 473:         rnleft = sp->rg_nleft;
 474:         rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
 475:     } else {
 476:         rblock = 0;
 477:         rnleft = 0;
 478:     }
 479:     for (addr = addr1; addr <= addr2; addr++) {
 480:         getline(*addr);
 481:         if (sp->rg_flags) {
 482:             if (addr == addr2)
 483:                 *wcursor = 0;
 484:             if (addr == addr1)
 485:                 strcpy(linebuf, cursor);
 486:         }
 487:         YANKline();
 488:     }
 489:     rbflush();
 490:     killed();
 491: }
 492: 
 493: kshift()
 494: {
 495:     register int i;
 496: 
 497:     KILLreg('9');
 498:     for (i = '8'; i >= '0'; i--)
 499:         copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
 500: }
 501: 
 502: YANKline()
 503: {
 504:     register char *lp = linebuf;
 505:     register struct rbuf *rp = rbuf;
 506:     register int c;
 507: 
 508:     do {
 509:         c = *lp++;
 510:         if (c == 0)
 511:             c = '\n';
 512:         if (rnleft == 0) {
 513:             rp->rb_next = REGblk();
 514:             rbflush();
 515:             rblock = rp->rb_next;
 516:             rp->rb_next = 0;
 517:             rp->rb_prev = rblock;
 518:             rnleft = sizeof rp->rb_text;
 519:             rbufcp = rp->rb_text;
 520:         }
 521:         *rbufcp++ = c;
 522:         --rnleft;
 523:     } while (c != '\n');
 524:     if (rnleft)
 525:         *rbufcp = 0;
 526: }
 527: 
 528: rbflush()
 529: {
 530:     register struct strreg *sp = strp;
 531: 
 532:     if (rblock == 0)
 533:         return;
 534:     regio(rblock, write);
 535:     if (sp->rg_first == 0)
 536:         sp->rg_first = rblock;
 537:     sp->rg_last = rblock;
 538:     sp->rg_nleft = rnleft;
 539: }

Defined functions

KILLreg defined in line 344; used 2 times
REGblk defined in line 309; used 1 times
YANKline defined in line 502; used 1 times
blkio defined in line 182; used 8 times
cleanup defined in line 68; used 6 times
fileinit defined in line 20; used 1 times
getREG defined in line 431; used 2 times
getblock defined in line 134; used 5 times
kshift defined in line 493; used 1 times
mapreg defined in line 332; used 7 times
notpart defined in line 423; used 2 times
partreg defined in line 416; used 3 times
putline defined in line 102; used 1 times
putreg defined in line 377; used 2 times
rbflush defined in line 528; used 2 times
regio defined in line 286; used 4 times
shread defined in line 366; used 2 times
synctmp defined in line 197; used 4 times

Defined variables

havetmp defined in line 16; used 3 times
rblock defined in line 282; used 16 times
rbuf defined in line 279; used 12 times
rbufcp defined in line 284; used 7 times
rfile defined in line 18; used 12 times
rfname defined in line 15; used 6 times
rnext defined in line 283; used 5 times
rnleft defined in line 281; used 12 times
rused defined in line 280; used 5 times
strp defined in line 273; used 2 times
strregs defined in line 273; used 2 times
  • in line 339(2)
tfile defined in line 17; used 12 times
tfname defined in line 14; used 11 times

Defined struct's

front defined in line 368; used 4 times
  • in line 370(4)
rbuf defined in line 275; used 10 times
strreg defined in line 268; used 10 times

Defined macros

READ defined in line 11; used 3 times
WRITE defined in line 12; used 2 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1684
Valid CSS Valid XHTML 1.0 Strict