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