home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / s1 / ed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-18  |  17.4 KB  |  1,334 lines

  1. #
  2.  
  3. /*
  4.  * Editor
  5.  */
  6.  
  7. #define    SIGHUP    1
  8. #define    SIGINTR    2
  9. #define    SIGQUIT    3
  10. #define    FNSIZE    64
  11. #define    LBSIZE    512
  12. #define    ESIZE    128
  13. #define    GBSIZE    256
  14. #define    NBRA    5
  15. #define    EOF    -1
  16.  
  17. #define    CBRA    1
  18. #define    CCHR    2
  19. #define    CDOT    4
  20. #define    CCL    6
  21. #define    NCCL    8
  22. #define    CDOL    10
  23. #define    CEOF    11
  24. #define    CKET    12
  25.  
  26. #define    STAR    01
  27.  
  28. #define    error    goto errlab
  29. #define    READ    0
  30. #define    WRITE    1
  31.  
  32. int    peekc;
  33. int    lastc;
  34. char    savedfile[FNSIZE];
  35. char    file[FNSIZE];
  36. char    linebuf[LBSIZE];
  37. char    rhsbuf[LBSIZE/2];
  38. char    expbuf[ESIZE+4];
  39. int    circfl;
  40. int    *zero;
  41. int    *dot;
  42. int    *dol;
  43. int    *endcore;
  44. int    *fendcore;
  45. int    *addr1;
  46. int    *addr2;
  47. char    genbuf[LBSIZE];
  48. int    count[2];
  49. char    *nextip;
  50. char    *linebp;
  51. int    ninbuf;
  52. int    io;
  53. int    pflag;
  54. int    onhup;
  55. int    onquit;
  56. int    vflag    1;
  57. int    listf;
  58. int    col;
  59. char    *globp;
  60. int    tfile    -1;
  61. int    tline;
  62. char    *tfname;
  63. char    *loc1;
  64. char    *loc2;
  65. char    *locs;
  66. char    ibuff[512];
  67. int    iblock    -1;
  68. char    obuff[512];
  69. int    oblock    -1;
  70. int    ichanged;
  71. int    nleft;
  72. int    errfunc();
  73. int    *errlab    errfunc;
  74. char    TMPERR[] "TMP";
  75. int    names[26];
  76. char    *braslist[NBRA];
  77. char    *braelist[NBRA];
  78.  
  79. main(argc, argv)
  80. char **argv;
  81. {
  82.     register char *p1, *p2;
  83.     extern int onintr();
  84.  
  85.     onquit = signal(SIGQUIT, 1);
  86.     onhup = signal(SIGHUP, 1);
  87.     argv++;
  88.     if (argc > 1 && **argv=='-') {
  89.         vflag = 0;
  90.         /* allow debugging quits? */
  91.         if ((*argv)[1]=='q') {
  92.             signal(SIGQUIT, 0);
  93.             vflag++;
  94.         }
  95.         argv++;
  96.         argc--;
  97.     }
  98.     if (argc>1) {
  99.         p1 = *argv;
  100.         p2 = savedfile;
  101.         while (*p2++ = *p1++);
  102.         globp = "r";
  103.     }
  104.     fendcore = sbrk(0);
  105.     init();
  106.     if ((signal(SIGINTR, 1) & 01) == 0)
  107.         signal(SIGINTR, onintr);
  108.     setexit();
  109.     commands();
  110.     unlink(tfname);
  111. }
  112.  
  113. commands()
  114. {
  115.     int getfile(), gettty();
  116.     register *a1, c;
  117.     register char *p;
  118.     int r;
  119.  
  120.     for (;;) {
  121.     if (pflag) {
  122.         pflag = 0;
  123.         addr1 = addr2 = dot;
  124.         goto print;
  125.     }
  126.     addr1 = 0;
  127.     addr2 = 0;
  128.     do {
  129.         addr1 = addr2;
  130.         if ((a1 = address())==0) {
  131.             c = getchar();
  132.             break;
  133.         }
  134.         addr2 = a1;
  135.         if ((c=getchar()) == ';') {
  136.             c = ',';
  137.             dot = a1;
  138.         }
  139.     } while (c==',');
  140.     if (addr1==0)
  141.         addr1 = addr2;
  142.     switch(c) {
  143.  
  144.     case 'a':
  145.         setdot();
  146.         newline();
  147.         append(gettty, addr2);
  148.         continue;
  149.  
  150.     case 'c':
  151.         delete();
  152.         append(gettty, addr1-1);
  153.         continue;
  154.  
  155.     case 'd':
  156.         delete();
  157.         continue;
  158.  
  159.     case 'e':
  160.         setnoaddr();
  161.         if ((peekc = getchar()) != ' ')
  162.             error;
  163.         savedfile[0] = 0;
  164.         init();
  165.         addr2 = zero;
  166.         goto caseread;
  167.  
  168.     case 'f':
  169.         setnoaddr();
  170.         if ((c = getchar()) != '\n') {
  171.             peekc = c;
  172.             savedfile[0] = 0;
  173.             filename();
  174.         }
  175.         puts(savedfile);
  176.         continue;
  177.  
  178.     case 'g':
  179.         global(1);
  180.         continue;
  181.  
  182.     case 'i':
  183.         setdot();
  184.         nonzero();
  185.         newline();
  186.         append(gettty, addr2-1);
  187.         continue;
  188.  
  189.     case 'k':
  190.         if ((c = getchar()) < 'a' || c > 'z')
  191.             error;
  192.         newline();
  193.         setdot();
  194.         nonzero();
  195.         names[c-'a'] = *addr2 | 01;
  196.         continue;
  197.  
  198.     case 'm':
  199.         move(0);
  200.         continue;
  201.  
  202.     case '\n':
  203.         if (addr2==0)
  204.             addr2 = dot+1;
  205.         addr1 = addr2;
  206.         goto print;
  207.  
  208.     case 'l':
  209.         listf++;
  210.     case 'p':
  211.         newline();
  212.     print:
  213.         setdot();
  214.         nonzero();
  215.         a1 = addr1;
  216.         do
  217.             puts(getline(*a1++));
  218.         while (a1 <= addr2);
  219.         dot = addr2;
  220.         listf = 0;
  221.         continue;
  222.  
  223.     case 'q':
  224.         setnoaddr();
  225.         newline();
  226.         unlink(tfname);
  227.         exit();
  228.  
  229.     case 'r':
  230.     caseread:
  231.         filename();
  232.         if ((io = open(file, 0)) < 0) {
  233.             lastc = '\n';
  234.             error;
  235.         }
  236.         setall();
  237.         ninbuf = 0;
  238.         append(getfile, addr2);
  239.         exfile();
  240.         continue;
  241.  
  242.     case 's':
  243.         setdot();
  244.         nonzero();
  245.         substitute(globp);
  246.         continue;
  247.  
  248.     case 't':
  249.         move(1);
  250.         continue;
  251.  
  252.     case 'v':
  253.         global(0);
  254.         continue;
  255.  
  256.     case 'w':
  257.         setall();
  258.         nonzero();
  259.         filename();
  260.         if ((io = creat(file, 0666)) < 0)
  261.             error;
  262.         putfile();
  263.         exfile();
  264.         continue;
  265.  
  266.     case '=':
  267.         setall();
  268.         newline();
  269.         count[1] = (addr2-zero)&077777;
  270.         putd();
  271.         putchar('\n');
  272.         continue;
  273.  
  274.     case '!':
  275.         unix();
  276.         continue;
  277.  
  278.     case EOF:
  279.         return;
  280.  
  281.     }
  282.     error;
  283.     }
  284. }
  285.  
  286. address()
  287. {
  288.     register *a1, minus, c;
  289.     int n, relerr;
  290.  
  291.     minus = 0;
  292.     a1 = 0;
  293.     for (;;) {
  294.         c = getchar();
  295.         if ('0'<=c && c<='9') {
  296.             n = 0;
  297.             do {
  298.                 n =* 10;
  299.                 n =+ c - '0';
  300.             } while ((c = getchar())>='0' && c<='9');
  301.             peekc = c;
  302.             if (a1==0)
  303.                 a1 = zero;
  304.             if (minus<0)
  305.                 n = -n;
  306.             a1 =+ n;
  307.             minus = 0;
  308.             continue;
  309.         }
  310.         relerr = 0;
  311.         if (a1 || minus)
  312.             relerr++;
  313.         switch(c) {
  314.         case ' ':
  315.         case '\t':
  316.             continue;
  317.     
  318.         case '+':
  319.             minus++;
  320.             if (a1==0)
  321.                 a1 = dot;
  322.             continue;
  323.  
  324.         case '-':
  325.         case '^':
  326.             minus--;
  327.             if (a1==0)
  328.                 a1 = dot;
  329.             continue;
  330.     
  331.         case '?':
  332.         case '/':
  333.             compile(c);
  334.             a1 = dot;
  335.             for (;;) {
  336.                 if (c=='/') {
  337.                     a1++;
  338.                     if (a1 > dol)
  339.                         a1 = zero;
  340.                 } else {
  341.                     a1--;
  342.                     if (a1 < zero)
  343.                         a1 = dol;
  344.                 }
  345.                 if (execute(0, a1))
  346.                     break;
  347.                 if (a1==dot)
  348.                     error;
  349.             }
  350.             break;
  351.     
  352.         case '$':
  353.             a1 = dol;
  354.             break;
  355.     
  356.         case '.':
  357.             a1 = dot;
  358.             break;
  359.  
  360.         case '\'':
  361.             if ((c = getchar()) < 'a' || c > 'z')
  362.                 error;
  363.             for (a1=zero; a1<=dol; a1++)
  364.                 if (names[c-'a'] == (*a1|01))
  365.                     break;
  366.             break;
  367.     
  368.         default:
  369.             peekc = c;
  370.             if (a1==0)
  371.                 return(0);
  372.             a1 =+ minus;
  373.             if (a1<zero || a1>dol)
  374.                 error;
  375.             return(a1);
  376.         }
  377.         if (relerr)
  378.             error;
  379.     }
  380. }
  381.  
  382. setdot()
  383. {
  384.     if (addr2 == 0)
  385.         addr1 = addr2 = dot;
  386.     if (addr1 > addr2)
  387.         error;
  388. }
  389.  
  390. setall()
  391. {
  392.     if (addr2==0) {
  393.         addr1 = zero+1;
  394.         addr2 = dol;
  395.         if (dol==zero)
  396.             addr1 = zero;
  397.     }
  398.     setdot();
  399. }
  400.  
  401. setnoaddr()
  402. {
  403.     if (addr2)
  404.         error;
  405. }
  406.  
  407. nonzero()
  408. {
  409.     if (addr1<=zero || addr2>dol)
  410.         error;
  411. }
  412.  
  413. newline()
  414. {
  415.     register c;
  416.  
  417.     if ((c = getchar()) == '\n')
  418.         return;
  419.     if (c=='p' || c=='l') {
  420.         pflag++;
  421.         if (c=='l')
  422.             listf++;
  423.         if (getchar() == '\n')
  424.             return;
  425.     }
  426.     error;
  427. }
  428.  
  429. filename()
  430. {
  431.     register char *p1, *p2;
  432.     register c;
  433.  
  434.     count[1] = 0;
  435.     c = getchar();
  436.     if (c=='\n' || c==EOF) {
  437.         p1 = savedfile;
  438.         if (*p1==0)
  439.             error;
  440.         p2 = file;
  441.         while (*p2++ = *p1++);
  442.         return;
  443.     }
  444.     if (c!=' ')
  445.         error;
  446.     while ((c = getchar()) == ' ');
  447.     if (c=='\n')
  448.         error;
  449.     p1 = file;
  450.     do {
  451.         *p1++ = c;
  452.     } while ((c = getchar()) != '\n');
  453.     *p1++ = 0;
  454.     if (savedfile[0]==0) {
  455.         p1 = savedfile;
  456.         p2 = file;
  457.         while (*p1++ = *p2++);
  458.     }
  459. }
  460.  
  461. exfile()
  462. {
  463.     close(io);
  464.     io = -1;
  465.     if (vflag) {
  466.         putd();
  467.         putchar('\n');
  468.     }
  469. }
  470.  
  471. onintr()
  472. {
  473.     signal(SIGINTR, onintr);
  474.     putchar('\n');
  475.     lastc = '\n';
  476.     error;
  477. }
  478.  
  479. errfunc()
  480. {
  481.     register c;
  482.  
  483.     listf = 0;
  484.     puts("?");
  485.     count[0] = 0;
  486.     seek(0, 0, 2);
  487.     pflag = 0;
  488.     if (globp)
  489.         lastc = '\n';
  490.     globp = 0;
  491.     peekc = lastc;
  492.     while ((c = getchar()) != '\n' && c != EOF);
  493.     if (io > 0) {
  494.         close(io);
  495.         io = -1;
  496.     }
  497.     reset();
  498. }
  499.  
  500. getchar()
  501. {
  502.     if (lastc=peekc) {
  503.         peekc = 0;
  504.         return(lastc);
  505.     }
  506.     if (globp) {
  507.         if ((lastc = *globp++) != 0)
  508.             return(lastc);
  509.         globp = 0;
  510.         return(EOF);
  511.     }
  512.     if (read(0, &lastc, 1) <= 0)
  513.         return(lastc = EOF);
  514.     lastc =& 0177;
  515.     return(lastc);
  516. }
  517.  
  518. gettty()
  519. {
  520.     register c, gf;
  521.     register char *p;
  522.  
  523.     p = linebuf;
  524.     gf = globp;
  525.     while ((c = getchar()) != '\n') {
  526.         if (c==EOF) {
  527.             if (gf)
  528.                 peekc = c;
  529.             return(c);
  530.         }
  531.         if ((c =& 0177) == 0)
  532.             continue;
  533.         *p++ = c;
  534.         if (p >= &linebuf[LBSIZE-2])
  535.             error;
  536.     }
  537.     *p++ = 0;
  538.     if (linebuf[0]=='.' && linebuf[1]==0)
  539.         return(EOF);
  540.     return(0);
  541. }
  542.  
  543. getfile()
  544. {
  545.     register c;
  546.     register char *lp, *fp;
  547.  
  548.     lp = linebuf;
  549.     fp = nextip;
  550.     do {
  551.         if (--ninbuf < 0) {
  552.             if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
  553.                 return(EOF);
  554.             fp = genbuf;
  555.         }
  556.         if (lp >= &linebuf[LBSIZE])
  557.             error;
  558.         if ((*lp++ = c = *fp++ & 0177) == 0) {
  559.             lp--;
  560.             continue;
  561.         }
  562.         if (++count[1] == 0)
  563.             ++count[0];
  564.     } while (c != '\n');
  565.     *--lp = 0;
  566.     nextip = fp;
  567.     return(0);
  568. }
  569.  
  570. putfile()
  571. {
  572.     int *a1;
  573.     register char *fp, *lp;
  574.     register nib;
  575.  
  576.     nib = 512;
  577.     fp = genbuf;
  578.     a1 = addr1;
  579.     do {
  580.         lp = getline(*a1++);
  581.         for (;;) {
  582.             if (--nib < 0) {
  583.                 write(io, genbuf, fp-genbuf);
  584.                 nib = 511;
  585.                 fp = genbuf;
  586.             }
  587.             if (++count[1] == 0)
  588.                 ++count[0];
  589.             if ((*fp++ = *lp++) == 0) {
  590.                 fp[-1] = '\n';
  591.                 break;
  592.             }
  593.         }
  594.     } while (a1 <= addr2);
  595.     write(io, genbuf, fp-genbuf);
  596. }
  597.  
  598. append(f, a)
  599. int (*f)();
  600. {
  601.     register *a1, *a2, *rdot;
  602.     int nline, tl;
  603.     struct { int integer; };
  604.  
  605.     nline = 0;
  606.     dot = a;
  607.     while ((*f)() == 0) {
  608.         if (dol >= endcore) {
  609.             if (sbrk(1024) == -1)
  610.                 error;
  611.             endcore.integer =+ 1024;
  612.         }
  613.         tl = putline();
  614.         nline++;
  615.         a1 = ++dol;
  616.         a2 = a1+1;
  617.         rdot = ++dot;
  618.         while (a1 > rdot)
  619.             *--a2 = *--a1;
  620.         *rdot = tl;
  621.     }
  622.     return(nline);
  623. }
  624.  
  625. unix()
  626. {
  627.     register savint, pid, rpid;
  628.     int retcode;
  629.  
  630.     setnoaddr();
  631.     if ((pid = fork()) == 0) {
  632.         signal(SIGHUP, onhup);
  633.         signal(SIGQUIT, onquit);
  634.         execl("/bin/sh", "sh", "-t", 0);
  635.         exit();
  636.     }
  637.     savint = signal(SIGINTR, 1);
  638.     while ((rpid = wait(&retcode)) != pid && rpid != -1);
  639.     signal(SIGINTR, savint);
  640.     puts("!");
  641. }
  642.  
  643. delete()
  644. {
  645.     register *a1, *a2, *a3;
  646.  
  647.     setdot();
  648.     newline();
  649.     nonzero();
  650.     a1 = addr1;
  651.     a2 = addr2+1;
  652.     a3 = dol;
  653.     dol =- a2 - a1;
  654.     do
  655.         *a1++ = *a2++;
  656.     while (a2 <= a3);
  657.     a1 = addr1;
  658.     if (a1 > dol)
  659.         a1 = dol;
  660.     dot = a1;
  661. }
  662.  
  663. getline(tl)
  664. {
  665.     register char *bp, *lp;
  666.     register nl;
  667.  
  668.     lp = linebuf;
  669.     bp = getblock(tl, READ);
  670.     nl = nleft;
  671.     tl =& ~0377;
  672.     while (*lp++ = *bp++)
  673.         if (--nl == 0) {
  674.             bp = getblock(tl=+0400, READ);
  675.             nl = nleft;
  676.         }
  677.     return(linebuf);
  678. }
  679.  
  680. putline()
  681. {
  682.     register char *bp, *lp;
  683.     register nl;
  684.     int tl;
  685.  
  686.     lp = linebuf;
  687.     tl = tline;
  688.     bp = getblock(tl, WRITE);
  689.     nl = nleft;
  690.     tl =& ~0377;
  691.     while (*bp = *lp++) {
  692.         if (*bp++ == '\n') {
  693.             *--bp = 0;
  694.             linebp = lp;
  695.             break;
  696.         }
  697.         if (--nl == 0) {
  698.             bp = getblock(tl=+0400, WRITE);
  699.             nl = nleft;
  700.         }
  701.     }
  702.     nl = tline;
  703.     tline =+ (((lp-linebuf)+03)>>1)&077776;
  704.     return(nl);
  705. }
  706.  
  707. getblock(atl, iof)
  708. {
  709.     extern read(), write();
  710.     register bno, off;
  711.     
  712.     bno = (atl>>8)&0377;
  713.     off = (atl<<1)&0774;
  714.     if (bno >= 255) {
  715.         puts(TMPERR);
  716.         error;
  717.     }
  718.     nleft = 512 - off;
  719.     if (bno==iblock) {
  720.         ichanged =| iof;
  721.         return(ibuff+off);
  722.     }
  723.     if (bno==oblock)
  724.         return(obuff+off);
  725.     if (iof==READ) {
  726.         if (ichanged)
  727.             blkio(iblock, ibuff, write);
  728.         ichanged = 0;
  729.         iblock = bno;
  730.         blkio(bno, ibuff, read);
  731.         return(ibuff+off);
  732.     }
  733.     if (oblock>=0)
  734.         blkio(oblock, obuff, write);
  735.     oblock = bno;
  736.     return(obuff+off);
  737. }
  738.  
  739. blkio(b, buf, iofcn)
  740. int (*iofcn)();
  741. {
  742.     seek(tfile, b, 3);
  743.     if ((*iofcn)(tfile, buf, 512) != 512) {
  744.         puts(TMPERR);
  745.         error;
  746.     }
  747. }
  748.  
  749. init()
  750. {
  751.     register char *p;
  752.     register pid;
  753.  
  754.     close(tfile);
  755.     tline = 0;
  756.     iblock = -1;
  757.     oblock = -1;
  758.     tfname = "/tmp/exxxxx";
  759.     ichanged = 0;
  760.     pid = getpid();
  761.     for (p = &tfname[11]; p > &tfname[6];) {
  762.         *--p = (pid&07) + '0';
  763.         pid =>> 3;
  764.     }
  765.     close(creat(tfname, 0600));
  766.     tfile = open(tfname, 2);
  767.     brk(fendcore);
  768.     dot = zero = dol = fendcore;
  769.     endcore = fendcore - 2;
  770. }
  771.  
  772. global(k)
  773. {
  774.     register char *gp;
  775.     register c;
  776.     register int *a1;
  777.     char globuf[GBSIZE];
  778.  
  779.     if (globp)
  780.         error;
  781.     setall();
  782.     nonzero();
  783.     if ((c=getchar())=='\n')
  784.         error;
  785.     compile(c);
  786.     gp = globuf;
  787.     while ((c = getchar()) != '\n') {
  788.         if (c==EOF)
  789.             error;
  790.         if (c=='\\') {
  791.             c = getchar();
  792.             if (c!='\n')
  793.                 *gp++ = '\\';
  794.         }
  795.         *gp++ = c;
  796.         if (gp >= &globuf[GBSIZE-2])
  797.             error;
  798.     }
  799.     *gp++ = '\n';
  800.     *gp++ = 0;
  801.     for (a1=zero; a1<=dol; a1++) {
  802.         *a1 =& ~01;
  803.         if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k)
  804.             *a1 =| 01;
  805.     }
  806.     for (a1=zero; a1<=dol; a1++) {
  807.         if (*a1 & 01) {
  808.             *a1 =& ~01;
  809.             dot = a1;
  810.             globp = globuf;
  811.             commands();
  812.             a1 = zero;
  813.         }
  814.     }
  815. }
  816.  
  817. substitute(inglob)
  818. {
  819.     register gsubf, *a1, nl;
  820.     int getsub();
  821.  
  822.     gsubf = compsub();
  823.     for (a1 = addr1; a1 <= addr2; a1++) {
  824.         if (execute(0, a1)==0)
  825.             continue;
  826.         inglob =| 01;
  827.         dosub();
  828.         if (gsubf) {
  829.             while (*loc2) {
  830.                 if (execute(1)==0)
  831.                     break;
  832.                 dosub();
  833.             }
  834.         }
  835.         *a1 = putline();
  836.         nl = append(getsub, a1);
  837.         a1 =+ nl;
  838.         addr2 =+ nl;
  839.     }
  840.     if (inglob==0)
  841.         error;
  842. }
  843.  
  844. compsub()
  845. {
  846.     register seof, c;
  847.     register char *p;
  848.     int gsubf;
  849.  
  850.     if ((seof = getchar()) == '\n')
  851.         error;
  852.     compile(seof);
  853.     p = rhsbuf;
  854.     for (;;) {
  855.         c = getchar();
  856.         if (c=='\\')
  857.             c = getchar() | 0200;
  858.         if (c=='\n')
  859.             error;
  860.         if (c==seof)
  861.             break;
  862.         *p++ = c;
  863.         if (p >= &rhsbuf[LBSIZE/2])
  864.             error;
  865.     }
  866.     *p++ = 0;
  867.     if ((peekc = getchar()) == 'g') {
  868.         peekc = 0;
  869.         newline();
  870.         return(1);
  871.     }
  872.     newline();
  873.     return(0);
  874. }
  875.  
  876. getsub()
  877. {
  878.     register char *p1, *p2;
  879.  
  880.     p1 = linebuf;
  881.     if ((p2 = linebp) == 0)
  882.         return(EOF);
  883.     while (*p1++ = *p2++);
  884.     linebp = 0;
  885.     return(0);
  886. }
  887.  
  888. dosub()
  889. {
  890.     register char *lp, *sp, *rp;
  891.     int c;
  892.  
  893.     lp = linebuf;
  894.     sp = genbuf;
  895.     rp = rhsbuf;
  896.     while (lp < loc1)
  897.         *sp++ = *lp++;
  898.     while (c = *rp++) {
  899.         if (c=='&') {
  900.             sp = place(sp, loc1, loc2);
  901.             continue;
  902.         } else if (c<0 && (c =& 0177) >='1' && c < NBRA+'1') {
  903.             sp = place(sp, braslist[c-'1'], braelist[c-'1']);
  904.             continue;
  905.         }
  906.         *sp++ = c&0177;
  907.         if (sp >= &genbuf[LBSIZE])
  908.             error;
  909.     }
  910.     lp = loc2;
  911.     loc2 = sp + linebuf - genbuf;
  912.     while (*sp++ = *lp++)
  913.         if (sp >= &genbuf[LBSIZE])
  914.             error;
  915.     lp = linebuf;
  916.     sp = genbuf;
  917.     while (*lp++ = *sp++);
  918. }
  919.  
  920. place(asp, al1, al2)
  921. {
  922.     register char *sp, *l1, *l2;
  923.  
  924.     sp = asp;
  925.     l1 = al1;
  926.     l2 = al2;
  927.     while (l1 < l2) {
  928.         *sp++ = *l1++;
  929.         if (sp >= &genbuf[LBSIZE])
  930.             error;
  931.     }
  932.     return(sp);
  933. }
  934.  
  935. move(cflag)
  936. {
  937.     register int *adt, *ad1, *ad2;
  938.     int getcopy();
  939.  
  940.     setdot();
  941.     nonzero();
  942.     if ((adt = address())==0)
  943.         error;
  944.     newline();
  945.     ad1 = addr1;
  946.     ad2 = addr2;
  947.     if (cflag) {
  948.         ad1 = dol;
  949.         append(getcopy, ad1++);
  950.         ad2 = dol;
  951.     }
  952.     ad2++;
  953.     if (adt<ad1) {
  954.         dot = adt + (ad2-ad1);
  955.         if ((++adt)==ad1)
  956.             return;
  957.         reverse(adt, ad1);
  958.         reverse(ad1, ad2);
  959.         reverse(adt, ad2);
  960.     } else if (adt >= ad2) {
  961.         dot = adt++;
  962.         reverse(ad1, ad2);
  963.         reverse(ad2, adt);
  964.         reverse(ad1, adt);
  965.     } else
  966.         error;
  967. }
  968.  
  969. reverse(aa1, aa2)
  970. {
  971.     register int *a1, *a2, t;
  972.  
  973.     a1 = aa1;
  974.     a2 = aa2;
  975.     for (;;) {
  976.         t = *--a2;
  977.         if (a2 <= a1)
  978.             return;
  979.         *a2 = *a1;
  980.         *a1++ = t;
  981.     }
  982. }
  983.  
  984. getcopy()
  985. {
  986.     if (addr1 > addr2)
  987.         return(EOF);
  988.     getline(*addr1++);
  989.     return(0);
  990. }
  991.  
  992. compile(aeof)
  993. {
  994.     register eof, c;
  995.     register char *ep;
  996.     char *lastep;
  997.     char bracket[NBRA], *bracketp;
  998.     int nbra;
  999.     int cclcnt;
  1000.  
  1001.     ep = expbuf;
  1002.     eof = aeof;
  1003.     bracketp = bracket;
  1004.     nbra = 0;
  1005.     if ((c = getchar()) == eof) {
  1006.         if (*ep==0)
  1007.             error;
  1008.         return;
  1009.     }
  1010.     circfl = 0;
  1011.     if (c=='^') {
  1012.         c = getchar();
  1013.         circfl++;
  1014.     }
  1015.     if (c=='*')
  1016.         goto cerror;
  1017.     peekc = c;
  1018.     for (;;) {
  1019.         if (ep >= &expbuf[ESIZE])
  1020.             goto cerror;
  1021.         c = getchar();
  1022.         if (c==eof) {
  1023.             *ep++ = CEOF;
  1024.             return;
  1025.         }
  1026.         if (c!='*')
  1027.             lastep = ep;
  1028.         switch (c) {
  1029.  
  1030.         case '\\':
  1031.             if ((c = getchar())=='(') {
  1032.                 if (nbra >= NBRA)
  1033.                     goto cerror;
  1034.                 *bracketp++ = nbra;
  1035.                 *ep++ = CBRA;
  1036.                 *ep++ = nbra++;
  1037.                 continue;
  1038.             }
  1039.             if (c == ')') {
  1040.                 if (bracketp <= bracket)
  1041.                     goto cerror;
  1042.                 *ep++ = CKET;
  1043.                 *ep++ = *--bracketp;
  1044.                 continue;
  1045.             }
  1046.             *ep++ = CCHR;
  1047.             if (c=='\n')
  1048.                 goto cerror;
  1049.             *ep++ = c;
  1050.             continue;
  1051.  
  1052.         case '.':
  1053.             *ep++ = CDOT;
  1054.             continue;
  1055.  
  1056.         case '\n':
  1057.             goto cerror;
  1058.  
  1059.         case '*':
  1060.             if (*lastep==CBRA || *lastep==CKET)
  1061.                 error;
  1062.             *lastep =| STAR;
  1063.             continue;
  1064.  
  1065.         case '$':
  1066.             if ((peekc=getchar()) != eof)
  1067.                 goto defchar;
  1068.             *ep++ = CDOL;
  1069.             continue;
  1070.  
  1071.         case '[':
  1072.             *ep++ = CCL;
  1073.             *ep++ = 0;
  1074.             cclcnt = 1;
  1075.             if ((c=getchar()) == '^') {
  1076.                 c = getchar();
  1077.                 ep[-2] = NCCL;
  1078.             }
  1079.             do {
  1080.                 if (c=='\n')
  1081.                     goto cerror;
  1082.                 *ep++ = c;
  1083.                 cclcnt++;
  1084.                 if (ep >= &expbuf[ESIZE])
  1085.                     goto cerror;
  1086.             } while ((c = getchar()) != ']');
  1087.             lastep[1] = cclcnt;
  1088.             continue;
  1089.  
  1090.         defchar:
  1091.         default:
  1092.             *ep++ = CCHR;
  1093.             *ep++ = c;
  1094.         }
  1095.     }
  1096.    cerror:
  1097.     expbuf[0] = 0;
  1098.     error;
  1099. }
  1100.  
  1101. execute(gf, addr)
  1102. int *addr;
  1103. {
  1104.     register char *p1, *p2, c;
  1105.  
  1106.     if (gf) {
  1107.         if (circfl)
  1108.             return(0);
  1109.         p1 = linebuf;
  1110.         p2 = genbuf;
  1111.         while (*p1++ = *p2++);
  1112.         locs = p1 = loc2;
  1113.     } else {
  1114.         if (addr==zero)
  1115.             return(0);
  1116.         p1 = getline(*addr);
  1117.         locs = 0;
  1118.     }
  1119.     p2 = expbuf;
  1120.     if (circfl) {
  1121.         loc1 = p1;
  1122.         return(advance(p1, p2));
  1123.     }
  1124.     /* fast check for first character */
  1125.     if (*p2==CCHR) {
  1126.         c = p2[1];
  1127.         do {
  1128.             if (*p1!=c)
  1129.                 continue;
  1130.             if (advance(p1, p2)) {
  1131.                 loc1 = p1;
  1132.                 return(1);
  1133.             }
  1134.         } while (*p1++);
  1135.         return(0);
  1136.     }
  1137.     /* regular algorithm */
  1138.     do {
  1139.         if (advance(p1, p2)) {
  1140.             loc1 = p1;
  1141.             return(1);
  1142.         }
  1143.     } while (*p1++);
  1144.     return(0);
  1145. }
  1146.  
  1147. advance(alp, aep)
  1148. {
  1149.     register char *lp, *ep, *curlp;
  1150.     char *nextep;
  1151.  
  1152.     lp = alp;
  1153.     ep = aep;
  1154.     for (;;) switch (*ep++) {
  1155.  
  1156.     case CCHR:
  1157.         if (*ep++ == *lp++)
  1158.             continue;
  1159.         return(0);
  1160.  
  1161.     case CDOT:
  1162.         if (*lp++)
  1163.             continue;
  1164.         return(0);
  1165.  
  1166.     case CDOL:
  1167.         if (*lp==0)
  1168.             continue;
  1169.         return(0);
  1170.  
  1171.     case CEOF:
  1172.         loc2 = lp;
  1173.         return(1);
  1174.  
  1175.     case CCL:
  1176.         if (cclass(ep, *lp++, 1)) {
  1177.             ep =+ *ep;
  1178.             continue;
  1179.         }
  1180.         return(0);
  1181.  
  1182.     case NCCL:
  1183.         if (cclass(ep, *lp++, 0)) {
  1184.             ep =+ *ep;
  1185.             continue;
  1186.         }
  1187.         return(0);
  1188.  
  1189.     case CBRA:
  1190.         braslist[*ep++] = lp;
  1191.         continue;
  1192.  
  1193.     case CKET:
  1194.         braelist[*ep++] = lp;
  1195.         continue;
  1196.  
  1197.     case CDOT|STAR:
  1198.         curlp = lp;
  1199.         while (*lp++);
  1200.         goto star;
  1201.  
  1202.     case CCHR|STAR:
  1203.         curlp = lp;
  1204.         while (*lp++ == *ep);
  1205.         ep++;
  1206.         goto star;
  1207.  
  1208.     case CCL|STAR:
  1209.     case NCCL|STAR:
  1210.         curlp = lp;
  1211.         while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
  1212.         ep =+ *ep;
  1213.         goto star;
  1214.  
  1215.     star:
  1216.         do {
  1217.             lp--;
  1218.             if (lp==locs)
  1219.                 break;
  1220.             if (advance(lp, ep))
  1221.                 return(1);
  1222.         } while (lp > curlp);
  1223.         return(0);
  1224.  
  1225.     default:
  1226.         error;
  1227.     }
  1228. }
  1229.  
  1230. cclass(aset, ac, af)
  1231. {
  1232.     register char *set, c;
  1233.     register n;
  1234.  
  1235.     set = aset;
  1236.     if ((c = ac) == 0)
  1237.         return(0);
  1238.     n = *set++;
  1239.     while (--n)
  1240.         if (*set++ == c)
  1241.             return(af);
  1242.     return(!af);
  1243. }
  1244.  
  1245. putd()
  1246. {
  1247.     register r;
  1248.     extern ldivr;
  1249.  
  1250.     count[1] = ldiv(count[0], count[1], 10);
  1251.     count[0] = 0;
  1252.     r = ldivr;
  1253.     if (count[1])
  1254.         putd();
  1255.     putchar(r + '0');
  1256. }
  1257.  
  1258. puts(as)
  1259. {
  1260.     register char *sp;
  1261.  
  1262.     sp = as;
  1263.     col = 0;
  1264.     while (*sp)
  1265.         putchar(*sp++);
  1266.     putchar('\n');
  1267. }
  1268.  
  1269. char    line[70];
  1270. char    *linp    line;
  1271.  
  1272. putchar(ac)
  1273. {
  1274.     register char *lp;
  1275.     register c;
  1276.  
  1277.     lp = linp;
  1278.     c = ac;
  1279.     if (listf) {
  1280.         col++;
  1281.         if (col >= 72) {
  1282.             col = 0;
  1283.             *lp++ = '\\';
  1284.             *lp++ = '\n';
  1285.         }
  1286.         if (c=='\t') {
  1287.             c = '>';
  1288.             goto esc;
  1289.         }
  1290.         if (c=='\b') {
  1291.             c = '<';
  1292.         esc:
  1293.             *lp++ = '-';
  1294.             *lp++ = '\b';
  1295.             *lp++ = c;
  1296.             goto out;
  1297.         }
  1298.         if (c<' ' && c!= '\n') {
  1299.             *lp++ = '\\';
  1300.             *lp++ = (c>>3)+'0';
  1301.             *lp++ = (c&07)+'0';
  1302.             col =+ 2;
  1303.             goto out;
  1304.         }
  1305.     }
  1306.     *lp++ = c;
  1307. out:
  1308.     if(c == '\n' || lp >= &line[64]) {
  1309.         linp = line;
  1310.         write(1, line, lp-line);
  1311.         return;
  1312.     }
  1313.     linp = lp;
  1314. }
  1315.  
  1316. /*
  1317.  * Get process ID routine if system call is unavailable.
  1318. getpid()
  1319. {
  1320.     register f;
  1321.     int b[1];
  1322.  
  1323.     f = open("/dev/kmem", 0);
  1324.     if(f < 0)
  1325.         return(-1);
  1326.     seek(f, 0140074, 0);
  1327.     read(f, b, 2);
  1328.     seek(f, b[0]+8, 0);
  1329.     read(f, b, 2);
  1330.     close(f);
  1331.     return(b[0]);
  1332. }
  1333.  */
  1334.