|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.