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

Defined functions

KILLreg defined in line 426; used 2 times
REGblk defined in line 391; used 1 times
TSYNC defined in line 317; used 3 times
YANKline defined in line 587; used 1 times
YANKreg defined in line 540; used 6 times
blkio defined in line 209; used 8 times
cleanup defined in line 83; used 6 times
fileinit defined in line 29; used 1 times
getREG defined in line 514; used 3 times
getblock defined in line 149; used 5 times
kshift defined in line 578; used 1 times
mapreg defined in line 414; used 8 times
notpart defined in line 506; used 2 times
partreg defined in line 499; used 4 times
putline defined in line 117; used 1 times
putreg defined in line 458; used 2 times
rbflush defined in line 613; used 2 times
regbuf defined in line 627; used 2 times
regio defined in line 368; used 4 times
shread defined in line 447; used 2 times
synctmp defined in line 258; used 2 times
tflush defined in line 243; used 3 times
tlaste defined in line 236; used 2 times

Defined variables

KILLrbuf defined in line 357; used 1 times
YANKrbuf defined in line 357; used 1 times
havetmp defined in line 25; used 3 times
incorb defined in line 204; used 3 times
putrbuf defined in line 357; used 1 times
rblock defined in line 364; used 17 times
rbuf defined in line 357; used 13 times
rbufcp defined in line 366; used 7 times
regrbuf defined in line 357; used 1 times
rfile defined in line 27; used 12 times
rfname defined in line 24; used 6 times
rnext defined in line 365; used 7 times
rnleft defined in line 363; used 13 times
rused defined in line 361; used 5 times
sccsid defined in line 8; never used
stilinc defined in line 206; used 10 times
strp defined in line 351; used 2 times
strregs defined in line 351; used 2 times
  • in line 421(2)
tfile defined in line 26; used 51 times
tfname defined in line 23; used 12 times

Defined struct's

front defined in line 449; used 4 times
  • in line 451(4)
rbuf defined in line 353; used 4 times
strreg defined in line 346; used 10 times

Defined macros

INCORB defined in line 203; used 2 times
READ defined in line 20; used 3 times
WRITE defined in line 21; used 2 times
pagrnd defined in line 205; used 3 times
Last modified: 1991-09-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4792
Valid CSS Valid XHTML 1.0 Strict