home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_temp.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  9KB  |  532 lines

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