home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff282.lzh / RCS / rcs.zoo / rcs / ked / ked.c,v
Text File  |  1989-09-16  |  44KB  |  2,587 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     89.09.17.10.58.39;  author rick;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     89.09.04.18.52.56;  author rick;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     89.09.01.11.02.22;  author rick;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     89.08.27.19.01.04;  author rick;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     89.08.27.17.44.11;  author rick;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @Initial checkin
  37. @
  38.  
  39.  
  40. 1.5
  41. log
  42. @Cleanup so no errors when compiled with Lattice C
  43. @
  44. text
  45. @/* ed - standard editor        Authors: Brian Beattie, Kees Bot, and others */
  46.  
  47. /* Modifications for Amiga made by Rick Schaeffer */
  48.  
  49. /*
  50.  * Copyright 1987 Brian Beattie Rights Reserved.
  51.  *
  52.  * Permission to copy and/or distribute granted under the
  53.  * following conditions:
  54.  *
  55.  * 1). No charge may be made other than reasonable charges
  56.  *    for reproduction.
  57.  *
  58.  * 2). This notice must remain intact.
  59.  *
  60.  * 3). No further restrictions may be added.
  61.  *
  62.  */
  63.  
  64. /*    This program used to be in many little pieces, with this makefile:
  65. .SUFFIXES:    .c .s
  66.  
  67. CFLAGS = -F 
  68.  
  69. OBJS =    append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\
  70.     doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
  71.     getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\
  72.     move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
  73.     unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s system.s
  74.  
  75. ed:    $(OBJS)
  76.     cc -T. -i -o ed $(OBJS)
  77. */
  78.  
  79. #include <stdio.h>
  80. #include <ios1.h>
  81. /****************************/
  82.  
  83. /*    tools.h    */
  84. static char    tools_h[] =
  85. "$Header: Rodime:ricks/rcs2/src/ked/ked.c,v 1.4 89/09/04 18:52:56 rick Exp Locker: rick $";
  86. /*
  87.  *    #defines for non-printing ASCII characters
  88.  */
  89.  
  90. #define NUL    0x00    /* ^@@ */
  91. #define EOS    0x00    /* end of string */
  92. #define SOH    0x01    /* ^A */
  93. #define STX    0x02    /* ^B */
  94. #define ETX    0x03    /* ^C */
  95. #define EOT    0x04    /* ^D */
  96. #define ENQ    0x05    /* ^E */
  97. #define ACK    0x06    /* ^F */
  98. #define BEL    0x07    /* ^G */
  99. #define BS    0x08    /* ^H */
  100. #define HT    0x09    /* ^I */
  101. #define LF    0x0a    /* ^J */
  102. #define NL    '\n'
  103. #define VT    0x0b    /* ^K */
  104. #define FF    0x0c    /* ^L */
  105. #define CR    0x0d    /* ^M */
  106. #define SO    0x0e    /* ^N */
  107. #define SI    0x0f    /* ^O */
  108. #define DLE    0x10    /* ^P */
  109. #define DC1    0x11    /* ^Q */
  110. #define DC2    0x12    /* ^R */
  111. #define DC3    0x13    /* ^S */
  112. #define DC4    0x14    /* ^T */
  113. #define NAK    0x15    /* ^U */
  114. #define SYN    0x16    /* ^V */
  115. #define ETB    0x17    /* ^W */
  116. #define CAN    0x18    /* ^X */
  117. #define EM    0x19    /* ^Y */
  118. #define SUB    0x1a    /* ^Z */
  119. #define ESC    0x1b    /* ^[ */
  120. #define FS    0x1c    /* ^\ */
  121. #define GS    0x1d    /* ^] */
  122. #define RS    0x1e    /* ^^ */
  123. #define US    0x1f    /* ^_ */
  124. #define SP    0x20    /* space */
  125. #define DEL    0x7f    /* DEL*/
  126.  
  127.  
  128. #define TRUE    1
  129. #define FALSE    0
  130. #define ERR    -2
  131.  
  132.  
  133. /*    Definitions of meta-characters used in pattern matching
  134.  *    routines.  LITCHAR & NCCL are only used as token identifiers;
  135.  *    all the others are also both token identifier and actual symbol
  136.  *    used in the regular expression.
  137.  */
  138.  
  139.  
  140. #define BOL    '^'
  141. #define EOL    '$'
  142. #define ANY    '.'
  143. #define LITCHAR    'L'
  144. #define    ESCAPE    '\\'
  145. #define CCL    '['    /* Character class: [...] */
  146. #define CCLEND    ']'
  147. #define NEGATE    '~'
  148. #define NCCL    '!'    /* Negative character class [^...] */
  149. #define CLOSURE    '*'
  150. #define OR_SYM    '|'
  151. #define DITTO    '&'
  152. #define OPEN    '('
  153. #define CLOSE    ')'
  154.  
  155. /* Largest permitted size for an expanded character class.  (i.e. the class
  156.  * [a-z] will expand into 26 symbols; [a-z0-9] will expand into 36.)
  157.  */
  158. #define CLS_SIZE    128
  159.  
  160. /*
  161.  *    Tokens are used to hold pattern templates. (see makepat())
  162.  */
  163. typedef    char    BITMAP;
  164.  
  165. typedef struct token {
  166.     char        tok;
  167.     char        lchar;
  168.     BITMAP        *bitmap;
  169.     struct token    *next;
  170. } TOKEN;
  171.  
  172. #define TOKSIZE sizeof (TOKEN)
  173.  
  174. /*
  175.  *    An absolute maximun for strings.
  176.  */
  177.  
  178. #define MAXSTR    132    /* Maximum numbers of characters in a line */
  179.  
  180.  
  181. extern    char    *matchs();
  182. extern    char    *amatch();
  183. extern    char    *in_string();
  184. extern    TOKEN    *getpat();
  185. extern    int    esc();
  186. extern    char    *dodash();
  187. extern    TOKEN    *makepat();
  188. extern    void    unmakepat();
  189. extern    int    insert();
  190. extern    int    delete();
  191. extern    int    isalphanum();
  192. extern    char    *stoupper();
  193. extern    int    pr_tok();
  194. extern    int    pr_line();
  195. extern    BITMAP    *makebitmap();
  196.  
  197. /* macros */
  198. #define toupper(c)    (c>='a'&&c<='z'?c-32:c)
  199.  
  200. /*    ed.h    */
  201. #define FATAL    (ERR-1)
  202. struct    line {
  203.     int        l_stat;        /* empty, mark */
  204.     struct line    *l_prev;
  205.     struct line    *l_next;
  206.     char        l_buff[1];
  207. };
  208.  
  209. typedef struct line    LINE;
  210.  
  211. #define LINFREE    1    /* entry not in use */
  212. #define LGLOB    2       /* line marked global */
  213.  
  214. #define MAXLINE    256    /* max number of chars per line */
  215. #define MAXPAT    256    /* max number of chars per replacement pattern */
  216. #define MAXFNAME 256    /* max file name size */
  217.  
  218. extern LINE    line0;
  219. extern int    curln, lastln, line1, line2, nlines;
  220. extern int    nflg;        /* print line number flag */
  221. extern int    lflg;        /* print line in verbose mode */
  222. extern int    pflg;        /* print current line after each command */
  223. extern char    *inptr;            /* tty input buffer */
  224. extern char    linbuf[], *linptr;    /* current line */
  225. extern int    truncflg;    /* truncate long line flag */
  226. extern int    eightbit;    /* save eighth bit */
  227. extern int    nonascii;    /* count of non-ascii chars read */
  228. extern int    nullchar;    /* count of null chars read */
  229. extern int    truncated;    /* count of lines truncated */
  230. extern int    fchanged;    /* file changed */
  231.  
  232. #define nextln(l)    ((l)+1 > lastln ? 0 : (l)+1)
  233. #define prevln(l)    ((l)-1 < 0 ? lastln : (l)-1)
  234.  
  235. extern char    *getfn();
  236. extern LINE    *getptr();
  237. extern char    *gettxt();
  238. extern char    *maksub();
  239. extern TOKEN    *optpat();
  240.  
  241. extern char    *catsub();
  242.  
  243. extern char    *strcpy();
  244. extern int    *malloc();
  245. extern void putcntl(),prntln(),relink(),clrbuf(),edsetbuf();
  246.  
  247. /*    amatch.c    */
  248. /* #include <stdio.h> */
  249. /* #include "tools.h" */
  250.  
  251. /*     Scans throught the pattern template looking for a match
  252.  * with lin.  Each element of lin is compared with the template
  253.  * until either a mis-match is found or the end of the template
  254.  * is reached.  In the former case a 0 is returned; in the latter,
  255.  * a pointer into lin (pointing to the character following the
  256.  * matched pattern) is returned.
  257.  *
  258.  *    "lin"    is a pointer to the line being searched.
  259.  *    "pat"    is a pointer to a template made by makepat().
  260.  *    "boln"    is a pointer into "lin" which points at the
  261.  *            character at the beginning of the line.
  262.  */
  263.  
  264. char *paropen[9], *parclose[9];
  265. int between, parnum;
  266. static char *match();
  267.  
  268. char    *
  269. amatch(lin, pat, boln)
  270. char    *lin;
  271. TOKEN    *pat;
  272. char    *boln;
  273. {
  274.  
  275.     between=0;
  276.     parnum=0;
  277.  
  278.     lin=match(lin, pat, boln);
  279.  
  280.     if (between) return 0;
  281.  
  282.     while (parnum<9) {
  283.         paropen[parnum] = parclose[parnum] = "";
  284.         parnum++;
  285.     }
  286.     return lin;
  287. }
  288.  
  289. static char    *
  290. match(lin, pat, boln)
  291. char    *lin;
  292. TOKEN    *pat;
  293. char    *boln;
  294. {
  295.     register char    *bocl, *rval, *strstart;
  296.  
  297.     if(pat == 0)
  298.         return 0;
  299.  
  300.     strstart = lin;
  301.  
  302.     while(pat)
  303.     {
  304.         if(pat->tok == CLOSURE && pat->next)
  305.         {
  306.                 /* Process a closure:
  307.                  * first skip over the closure token to the
  308.                  * object to be repeated.  This object can be
  309.                  * a character class.
  310.                  */
  311.  
  312.             pat = pat->next;
  313.  
  314.                 /* Now match as many occurrences of the
  315.                  * closure pattern as possible.
  316.                  */
  317.             bocl = lin;
  318.  
  319.             while( *lin && omatch(&lin, pat))
  320.                 ;
  321.  
  322.                 /* 'Lin' now points to the character that made
  323.                  * made us fail.  Now go on to process the
  324.                  * rest of the string.  A problem here is
  325.                  * a character following the closure which
  326.                  * could have been in the closure.
  327.                  * For example, in the pattern "[a-z]*t" (which
  328.                  * matches any lower-case word ending in a t),
  329.                  * the final 't' will be sucked up in the while
  330.                  * loop.  So, if the match fails, we back up a
  331.                  * notch and try to match the rest of the
  332.                  * string again, repeating this process
  333.                  * recursively until we get back to the
  334.                  * beginning of the closure.  The recursion
  335.                  * goes, at most two levels deep.
  336.                  */
  337.  
  338.             if(pat = pat->next)
  339.             {
  340.                 int savbtwn=between;
  341.                 int savprnm=parnum;
  342.  
  343.                 while(bocl <= lin)
  344.                 {
  345.                     if(rval = match(lin, pat, boln))
  346.                     {
  347.                             /* success */
  348.                         return(rval);
  349.                     } else {
  350.                         --lin;
  351.                         between=savbtwn;
  352.                         parnum=savprnm;
  353.                     }
  354.                 }
  355.                 return (0);    /* match failed */
  356.             }
  357.         } else
  358.         if (pat->tok == OPEN)
  359.         {
  360.             if (between || parnum>=9) return 0;
  361.             paropen[parnum] = lin;
  362.             between=1;
  363.             pat = pat->next;
  364.         } else
  365.         if (pat->tok == CLOSE)
  366.         {
  367.             if (!between) return 0;
  368.             parclose[parnum++] = lin;
  369.             between=0;
  370.             pat = pat->next;
  371.         } else
  372.         if (omatch(&lin, pat, boln))
  373.         {
  374.             pat = pat->next;
  375.         } else {
  376.             return (0);
  377.         }
  378.     }
  379.         /* Note that omatch() advances lin to point at the next
  380.          * character to be matched.  Consequently, when we reach
  381.          * the end of the template, lin will be pointing at the
  382.          * character following the last character matched.  The
  383.          * exceptions are templates containing only a BOLN or EOLN
  384.          * token.  In these cases omatch doesn't advance.
  385.          *
  386.          * A philosophical point should be mentioned here.  Is $
  387.          * a position or a character? (i.e. does $ mean the EOL
  388.          * character itself or does it mean the character at the end
  389.          * of the line.)  I decided here to make it mean the former,
  390.          * in order to make the behavior of match() consistent.  If
  391.          * you give match the pattern ^$ (match all lines consisting
  392.          * only of an end of line) then, since something has to be
  393.          * returned, a pointer to the end of line character itself is
  394.          * returned.
  395.          */
  396.  
  397.     return ((char *)max(strstart , lin));
  398. }
  399.  
  400. /*    append.c    */
  401. /* #include <stdio.h> */
  402. /* #include "tools.h" */
  403. /* #include "ed.h" */
  404.  
  405. append(line, glob)
  406. int    line, glob;
  407. {
  408.     int    stat;
  409.     char    lin[MAXLINE];
  410.  
  411.     if(glob)
  412.         return(ERR);
  413.     curln = line;
  414.     while(1)
  415.     {
  416.         if(nflg)
  417.             printf("%d\t",curln+1);
  418.  
  419.         if(fgets(lin, MAXLINE, stdin) == NULL)
  420.             return( EOF );
  421.         if(lin[0] == '.' && lin[1] == '\n')
  422.             return(0);
  423.         stat = ins(lin);
  424.         if(stat < 0)
  425.             return( ERR );
  426.         
  427.     }
  428. }
  429.  
  430. /*    bitmap.c    */
  431. /*
  432.  *    BITMAP.C -    makebitmap, setbit, testbit
  433.  *            bit-map manipulation routines.
  434.  *
  435.  *    Copyright (c) Allen I. Holub, all rights reserved.  This program may
  436.  *        for copied for personal, non-profit use only.
  437.  *
  438.  */
  439.  
  440. #ifdef DEBUG
  441. /* #include <stdio.h> */
  442. #endif
  443.  
  444. /* #include "tools.h" */
  445.  
  446.  
  447. BITMAP    *makebitmap( size )
  448. unsigned size;
  449. {
  450.     /*    Make a bit map with "size" bits.  The first entry in
  451.      *    the map is an "unsigned int" representing the maximum
  452.      *    bit.  The map itself is concatenated to this integer.
  453.      *    Return a pointer to a map on success, 0 if there's
  454.      *    not enough memory.
  455.      */
  456.  
  457.     unsigned *map, numbytes;
  458.  
  459.     numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0 );
  460.  
  461. #ifdef DEBUG
  462.     printf("Making a %d bit map (%d bytes required)\n", size, numbytes);
  463. #endif
  464.  
  465.     if( map = (unsigned *) malloc( numbytes + sizeof(unsigned) ))
  466.         *map = size;
  467.  
  468.     return ((BITMAP *)map);
  469. }
  470.  
  471. setbit( c, map, val )
  472. unsigned    c, val;
  473. char        *map;
  474. {
  475.     /*    Set bit c in the map to val.
  476.      *    If c > map-size, 0 is returned, else 1 is returned.
  477.      */
  478.  
  479.     if( c >= *(unsigned *)map )    /* if c >= map size */
  480.         return 0;
  481.  
  482.     map += sizeof(unsigned);    /* skip past size */
  483.     
  484.     if( val )
  485.         map[c >> 3] |= 1 << (c & 0x07);
  486.     else
  487.         map[c >> 3] &= ~(1 << (c & 0x07));
  488.  
  489.     return( 1 );
  490. }
  491.  
  492. testbit( c, map )
  493. unsigned    c;
  494. char        *map;
  495. {
  496.     /*    Return 1 if the bit corresponding to c in map is set.
  497.      *    0 if it is not.
  498.      */
  499.  
  500.     if( c >= *(unsigned *)map )
  501.         return 0;
  502.  
  503.     map += sizeof(unsigned);
  504.     
  505.     return(map[ c >> 3 ] & (1 << (c & 0x07)));
  506. }
  507.  
  508. /*    catsub.c    */
  509. /* #include <stdio.h> */
  510. /* #include "tools.h" */
  511. /* #include "ed.h" */
  512.  
  513. extern char *paropen[9], *parclose[9];
  514.  
  515. char    *
  516. catsub(from, to, sub, new, newend)
  517. char    *from, *to, *sub, *new, *newend;
  518. {
  519.     char    *cp, *cp2;
  520.  
  521.     for(cp = new; *sub != EOS && cp < newend;)
  522.     {
  523.         if(*sub == DITTO)
  524.             for(cp2 = from; cp2 < to;)
  525.             {
  526.                 *cp++ = *cp2++;
  527.                 if(cp >= newend)
  528.                     break;
  529.             }
  530.         else
  531.         if (*sub == ESCAPE) {
  532.             sub++;
  533.             if ('1' <= *sub && *sub <= '9') {
  534.                 char *parcl = parclose[*sub - '1'];
  535.  
  536.                 for (cp2 = paropen[*sub - '1']; cp2 < parcl;)
  537.                 {
  538.                     *cp++ = *cp2++;
  539.                     if (cp >= newend) break;
  540.                 }
  541.             } else
  542.                 *cp++ = *sub;
  543.         } else
  544.             *cp++ = *sub;
  545.  
  546.         sub++;
  547.     }
  548.  
  549.     return(cp);
  550. }
  551.  
  552. /*    ckglob.c    */
  553. /* #include <stdio.h> */
  554. /* #include "tools.h" */
  555. /* #include "ed.h" */
  556.  
  557. ckglob()
  558. {
  559.     TOKEN    *glbpat;
  560.     char    c, delim, *lin;
  561.     int    num;
  562.     LINE    *ptr;
  563.  
  564.     c = *inptr;
  565.  
  566.     if(c != 'g' && c != 'v')
  567.         return(0);
  568.  
  569.     if (deflt(1, lastln) < 0)
  570.         return(ERR);
  571.  
  572.     delim = *++inptr;
  573.     if(delim <= ' ')
  574.         return(ERR);
  575.  
  576.     glbpat = optpat();
  577.  
  578.     if(*inptr == delim)
  579.         inptr++;
  580.  
  581.     for (num=1; num<=lastln; num++)
  582.     {
  583.         ptr = getptr(num);
  584.         ptr->l_stat &= ~LGLOB;
  585.         if (line1 <= num && num <= line2) {
  586.             lin = gettxt(num);
  587.             if(matchs(lin, glbpat, 0)) {
  588.                 if (c=='g') ptr->l_stat |= LGLOB;
  589.             } else {
  590.                 if (c=='v') ptr->l_stat |= LGLOB;
  591.             }
  592.         }
  593.     }
  594.     return(1);
  595. }
  596.  
  597. /*    deflt.c    */
  598. /* #include <stdio.h> */
  599. /* #include "tools.h" */
  600. /* #include "ed.h" */
  601.  
  602. deflt(def1, def2)
  603. int    def1, def2;
  604. {
  605.     if(nlines == 0)
  606.     {
  607.         line1 = def1;
  608.         line2 = def2;
  609.     }
  610.     if(line1 > line2 || line1 <= 0)
  611.         return (ERR);
  612. }
  613.  
  614. /*    del.c    */
  615. /* #include <stdio.h> */
  616. /* #include "tools.h" */
  617. /* #include "ed.h" */
  618.  
  619. del(from, to)
  620. int    from, to;
  621. {
  622.     LINE    *first, *last, *next, *tmp;
  623.  
  624.     if(from < 1)
  625.         from = 1;
  626.     first = getptr(prevln(from));
  627.     last = getptr(nextln(to));
  628.     next = first->l_next;
  629.     while(next != last && next != &line0)
  630.     {
  631.         tmp = next->l_next;
  632.         free(next);
  633.         next = tmp;
  634.     }
  635.     relink(first, last, first, last);
  636.     lastln -= (to - from)+1;
  637.     curln = prevln(from);
  638.     return(1);
  639. }
  640.  
  641. /*    docmd.c    */
  642. /* #include <stdio.h> */
  643. /* #include "tools.h" */
  644. /* #include "ed.h" */
  645.  
  646. char    fname[MAXFNAME];
  647. int    fchanged;
  648. extern int nofname;
  649. extern int prompt;
  650. extern    int mark[];
  651.  
  652. docmd(glob)
  653. int    glob;
  654. {
  655.     static char    rhs[MAXPAT];
  656.     TOKEN    *subpat;
  657.     int    c, err, line3;
  658.     int    apflg, pflag, gflag;
  659.     int    nchng;
  660.     char    *fptr;
  661.  
  662.     pflag = FALSE;
  663.     while(*inptr == SP && *inptr == HT)
  664.         inptr++;
  665.  
  666.     c = *inptr++;
  667.  
  668.     switch(c)
  669.     {
  670.     case NL:                    /* print next line */
  671.         if(nlines == 0)
  672.         {
  673.             if ((line2 = nextln(curln))==0)
  674.                 return(ERR);
  675.         }
  676.         curln = line2;
  677.         return (1);
  678.         break;
  679.  
  680.     case '=':                    /* print current line number */
  681.         printf("%d\n",line2);
  682.         break;
  683.  
  684.     case 'a':                    /* append lines */
  685.         if(*inptr != NL || nlines > 1)
  686.             return(ERR);
  687.  
  688.         if(append(line1, glob) < 0)
  689.             return(ERR);;
  690.         fchanged = TRUE;
  691.         break;
  692.  
  693.     case 'c':                    /* changed lines */
  694.         if(*inptr != NL)
  695.             return(ERR);
  696.  
  697.         if(deflt(curln, curln) < 0)
  698.             return(ERR);
  699.  
  700.         if(del(line1, line2) < 0)
  701.             return(ERR);
  702.         if(append(curln, glob) < 0)
  703.             return(ERR);
  704.         fchanged = TRUE;
  705.         break;
  706.  
  707.     case 'd':                    /* delete lines */
  708.         if(*inptr != NL)
  709.             return(ERR);
  710.  
  711.         if(deflt(curln, curln) < 0)
  712.             return(ERR);
  713.  
  714.         if(del(line1, line2) < 0)
  715.             return(ERR);
  716.         if(nextln(curln) != 0)
  717.             curln = nextln(curln);
  718.         fchanged = TRUE;
  719.         break;
  720.  
  721.     case 'e':                    /* edit new file with change check */
  722.         if(nlines > 0)
  723.             return(ERR);
  724.         if(fchanged) {
  725.             fchanged = FALSE;
  726.             return(ERR);
  727.         }
  728.         /*FALL THROUGH*/
  729.     case 'E':                    /* edit new file no check */
  730.         if(nlines > 0)
  731.             return(ERR);
  732.  
  733.         if(*inptr != ' ' && *inptr != HT && *inptr != NL)
  734.             return(ERR);
  735.  
  736.         if((fptr = getfn()) == NULL)
  737.             return(ERR);
  738.  
  739.         clrbuf();
  740.         if((err = doread(0, fptr)) < 0)
  741.             return(err);
  742.  
  743.         strcpy(fname, fptr);
  744.         fchanged = FALSE;
  745.         break;
  746.  
  747.     case 'f':                    /* set or display current file name */
  748.         if(nlines > 0)
  749.             return(ERR);
  750.  
  751.         if(*inptr != ' ' && *inptr != HT && *inptr != NL)
  752.             return(ERR);
  753.  
  754.         if((fptr = getfn()) == NULL)
  755.             return(ERR);
  756.  
  757.         if (nofname)
  758.             printf("%s\n", fname);
  759.         else
  760.             strcpy(fname, fptr);
  761.         break;
  762.  
  763.     case 'H':
  764.     case 'h':                    /* print last error */
  765.         return(ERR);
  766.         break;
  767.  
  768.     case 'i':                    /* insert lines */
  769.         if(*inptr != NL || nlines > 1)
  770.             return(ERR);
  771.  
  772.         if(append(prevln(line1), glob) < 0)
  773.             return(ERR);
  774.         fchanged = TRUE;
  775.         break;
  776.  
  777.     case 'j':                    /* join lines */
  778.         if (*inptr != NL || deflt(curln, curln+1)<0)
  779.             return(ERR);
  780.  
  781.         if (join(line1, line2) < 0)
  782.             return(ERR);
  783.         break;
  784.  
  785.     case 'k':                    /* mark line address */
  786.         while (*inptr == ' ' || *inptr == HT) inptr++;
  787.  
  788.         if (*inptr < 'a' || *inptr > 'z')
  789.             return ERR;
  790.         c= *inptr++;
  791.  
  792.         if(*inptr != ' ' && *inptr != HT && *inptr != NL)
  793.             return(ERR);
  794.  
  795.         mark[c-'a'] = line1;
  796.         break;
  797.  
  798.     case 'L':                    /* toggle verbose print */
  799.         lflg = ~lflg;
  800.         break;
  801.  
  802.     case 'l':                    /* print lines verbose */
  803.         if(*inptr != NL)
  804.             return(ERR);
  805.         if(deflt(curln,curln) < 0)
  806.             return(ERR);
  807.         if (dolst(line1,line2) < 0)
  808.             return(ERR);
  809.         break;
  810.  
  811.     case 'm':                    /* move lines */
  812.         if((line3 = getone()) < 0)
  813.             return(ERR);
  814.         if(deflt(curln,curln) < 0)
  815.             return(ERR);
  816.         if(move(line3) < 0)
  817.             return(ERR);
  818.         fchanged = TRUE;
  819.         break;
  820.  
  821.     case 'N':                    /* toggle print line numbers */
  822.         nflg = ~nflg;
  823.         break;
  824.  
  825.     case 'n':                    /* print lines with numbers */
  826.         if(*inptr != NL)
  827.             return(ERR);
  828.         if(deflt(curln,curln) < 0)
  829.             return(ERR);
  830.         if (donum(line1,line2) < 0)
  831.             return(ERR);
  832.         break;
  833.  
  834.     case 'P':                    /* toggle prompt */
  835.         prompt = ~prompt;
  836.         break;
  837.  
  838.     case 'p':                    /* print lines */
  839.         if(*inptr != NL)
  840.             return(ERR);
  841.         if(deflt(curln,curln) < 0)
  842.             return(ERR);
  843.         if(doprnt(line1,line2) < 0)
  844.             return(ERR);
  845.         break;
  846.  
  847.     case 'q':                    /* quit, check changed */
  848.         if(fchanged) {
  849.             fchanged = FALSE;
  850.             return(ERR);
  851.         }
  852.         /*FALL THROUGH*/
  853.     case 'Q':                    /* quit, no check for change */
  854.         if(*inptr == NL && nlines == 0 && !glob)
  855.             return(EOF);
  856.         else
  857.             return(ERR);
  858.  
  859.     case 'r':                    /* read in file */
  860.         if(nlines > 1)
  861.             return(ERR);
  862.  
  863.         if(nlines == 0)
  864.             line2 = lastln;
  865.  
  866.         if(*inptr != ' ' && *inptr != HT && *inptr != NL)
  867.             return(ERR);
  868.  
  869.         if((fptr = getfn()) == NULL)
  870.             return(ERR);
  871.  
  872.         if((err = doread(line2, fptr)) < 0)
  873.             return(err);
  874.         fchanged = TRUE;
  875.         break;
  876.  
  877.     case 's':                    /* substitute, set */
  878.         if(*inptr == 'e')
  879.             return(set());
  880.         while(*inptr == SP || *inptr == HT)
  881.             inptr++;
  882.         if((subpat = optpat()) == NULL)
  883.             return(ERR);
  884.         if((gflag = getrhs(rhs)) < 0)
  885.             return(ERR);
  886.         if(*inptr == 'p')
  887.             pflag++;
  888.         if(deflt(curln, curln) < 0)
  889.             return(ERR);
  890.         if((nchng = subst(subpat, rhs, gflag, pflag)) < 0)
  891.             return(ERR);
  892.         if(nchng)
  893.             fchanged = TRUE;
  894.         break;
  895.  
  896.     case 't':                    /* copy lines */
  897.         if((line3 = getone()) < 0)
  898.             return(ERR);
  899.         if(deflt(curln,curln) < 0)
  900.             return(ERR);
  901.         if(transfer(line3) < 0)
  902.             return(ERR);
  903.         fchanged = TRUE;
  904.         break;
  905.  
  906.     case 'u':                    /* undo last command */
  907.         return(ERR);
  908.         break;
  909.  
  910.     case 'W':                    /* write append */
  911.     case 'w':                    /* write */ 
  912.         apflg = (c=='W');
  913.  
  914.         if(*inptr != ' ' && *inptr != HT && *inptr != NL)
  915.             return(ERR);
  916.  
  917.         if((fptr = getfn()) == NULL)
  918.             return(ERR);
  919.  
  920.         if(deflt(1, lastln) < 0)
  921.             return(ERR);
  922.         if(dowrite(line1, line2, fptr, apflg) < 0)
  923.             return(ERR);
  924.         fchanged = FALSE;
  925.         break;
  926.  
  927.     case 'x':                    /* write then quit */
  928.         if(*inptr == NL && nlines == 0 && !glob)
  929.         {
  930.             if((fptr = getfn()) == NULL)
  931.                 return(ERR);
  932.             if(dowrite(1, lastln, fptr, 0) >= 0)
  933.                 return(EOF);
  934.         }
  935.         return(ERR);
  936.  
  937.     case 'z':                    /* print +21, -21, -11.+10 lines */
  938.         if(deflt(curln,curln) < 0)
  939.             return(ERR);
  940.  
  941.         switch(*inptr)
  942.         {
  943.         case '-':
  944.             if(doprnt(line1-21,line1) < 0)
  945.                 return(ERR);
  946.             break;
  947.  
  948.         case '.':
  949.             if(doprnt(line1-11,line1+10) < 0)
  950.                 return(ERR);
  951.             break;
  952.  
  953.         case '+':
  954.         case '\n':
  955.             if(doprnt(line1,line1+21) < 0)
  956.                 return(ERR);
  957.             break;
  958.         }
  959.         break;
  960.  
  961.     default:
  962.         return(ERR);
  963.     }
  964.     return (0);
  965. }
  966.  
  967. int dolst(line1, line2) int line1, line2;
  968. {
  969.     int oldlflg=lflg, p;
  970.  
  971.     lflg=1;
  972.     p=doprnt(line1, line2);
  973.     lflg=oldlflg;
  974.  
  975.     return p;
  976. }
  977.  
  978. int donum(line1, line2) int line1, line2;
  979. {
  980.     int oldnflg=nflg, p;
  981.  
  982.     nflg=1;
  983.     p=doprnt(line1, line2);
  984.     nflg=oldnflg;
  985.  
  986.     return p;
  987. }
  988.  
  989. /*    dodash.c    */
  990. /* #include <stdio.h> */
  991. /* #include "tools.h" */
  992.  
  993. /*    Expand the set pointed to by *src into dest.
  994.  *    Stop at delim.  Return 0 on error or size of
  995.  *    character class on success.  Update *src to
  996.  *    point at delim.  A set can have one element
  997.  *    {x} or several elements ( {abcdefghijklmnopqrstuvwxyz}
  998.  *    and {a-z} are equivalent ).  Note that the dash
  999.  *    notation is expanded as sequential numbers.
  1000.  *    This means (since we are using the ASCII character
  1001.  *    set) that a-Z will contain the entire alphabet
  1002.  *    plus the symbols: [\]^_`.  The maximum number of
  1003.  *    characters in a character class is defined by maxccl.
  1004.  */
  1005. char *
  1006. dodash(delim, src, map)
  1007.  
  1008. int    delim;
  1009. char    *src, *map;
  1010. {
  1011.  
  1012.     register int    first,    last;
  1013.     char        *start;
  1014.  
  1015.     start = src;
  1016.  
  1017.     while( *src && *src != delim )
  1018.     {
  1019.         if( *src != '-')
  1020.             setbit( esc( &src ), map, 1 );
  1021.  
  1022.         else if( src == start || *(src + 1) == delim )
  1023.             setbit( '-', map, 1 );
  1024.         else {
  1025.             src++;
  1026.  
  1027.             if( *src < *(src - 2))
  1028.             {
  1029.                 first = *src;
  1030.                 last = *(src - 2);
  1031.             } else {
  1032.                 first = *(src - 2);
  1033.                 last = *src;
  1034.             }
  1035.  
  1036.             while( ++first <= last )
  1037.                 setbit( first, map, 1);
  1038.  
  1039.         }
  1040.         src++;
  1041.     }
  1042.     return( src );
  1043. }
  1044.  
  1045. /*    doglob.c    */
  1046. /* #include <stdio.h> */
  1047. /* #include "tools.h" */
  1048. /* #include "ed.h" */
  1049.  
  1050. doglob()
  1051. {
  1052.     int    lin, stat;
  1053.     char    *cmd;
  1054.     LINE    *ptr;
  1055.  
  1056.     cmd = inptr;
  1057.  
  1058.     while(1)
  1059.     {
  1060.         for (lin=1; lin<=lastln; lin++) {
  1061.             ptr = getptr(lin);
  1062.             if (ptr->l_stat & LGLOB) break;
  1063.         }
  1064.         if (lin>lastln) break;
  1065.  
  1066.         ptr->l_stat &= ~LGLOB;
  1067.         curln = lin;
  1068.         inptr = cmd;
  1069.         if((stat = getlst()) < 0)
  1070.             return(stat);
  1071.         if((stat = docmd(1)) < 0)
  1072.             return(stat);
  1073.     }
  1074.     return(0);
  1075. }
  1076.  
  1077. /*    doprnt.c    */
  1078. /* #include <stdio.h> */
  1079. /* #include "tools.h" */
  1080. /* #include "ed.h" */
  1081.  
  1082. doprnt(from, to)
  1083. int    from, to;
  1084. {
  1085.     int    i;
  1086.  
  1087.     from = from < 1 ? 1 : from;
  1088.     to = to > lastln ? lastln : to;
  1089.         
  1090.     if(to != 0)
  1091.     {
  1092.         for(i = from; i <= to; i++)
  1093.             prntln(gettxt(i), lflg, (nflg ? i : 0));
  1094.         curln = to;
  1095.     }
  1096.  
  1097.     return(0);
  1098. }
  1099.  
  1100. void prntln(str, vflg, lin)
  1101. char    *str;
  1102. int    vflg, lin;
  1103. {
  1104.     if(lin)
  1105.         printf("%d\t",lin);
  1106.     while(*str && *str != NL)
  1107.     {
  1108.         if(*str < ' ' || *str >= 0x7f)
  1109.         {
  1110.             switch(*str)
  1111.             {
  1112.             case '\t':
  1113.                 if(vflg)
  1114.                     putcntl(*str, stdout);
  1115.                 else
  1116.                     putc(*str, stdout);
  1117.                 break;
  1118.  
  1119.             case DEL:
  1120.                 putc('^', stdout);
  1121.                 putc('?', stdout);
  1122.                 break;
  1123.  
  1124.             default:
  1125.                 putcntl(*str, stdout);
  1126.                 break;
  1127.             }
  1128.         } else
  1129.             putc(*str, stdout);
  1130.         str++;
  1131.     }
  1132.     if(vflg)
  1133.         putc('$',stdout);
  1134.     putc('\n', stdout);
  1135. }
  1136.  
  1137. void putcntl(c, stream)
  1138. char    c;
  1139. FILE    *stream;
  1140. {
  1141.     putc('^', stream);
  1142.     putc((c&31)|'@@', stream);
  1143. }
  1144.  
  1145. /*    doread.c    */
  1146. /* #include <stdio.h> */
  1147. /* #include "tools.h" */
  1148. /* #include "ed.h" */
  1149.  
  1150. extern int diag;
  1151.  
  1152. doread(lin, fname)
  1153. int    lin;
  1154. char    *fname;
  1155. {
  1156.     extern FILE    *fopen();
  1157.     FILE    *fp;
  1158.     int    err;
  1159.     long    bytes;
  1160.     int    lines;
  1161.     static char    str[MAXLINE];
  1162.  
  1163.     err = 0;
  1164.     nonascii = nullchar = truncated = 0;
  1165.  
  1166.     if (diag) printf("\"%s\" ",fname);
  1167.     if((fp = fopen(fname, "r")) == NULL)
  1168.     {
  1169.         printf("file open err\n");
  1170.         return( ERR );
  1171.     }
  1172.     curln = lin;
  1173.     for(lines = 0, bytes = 0;(err = egets(str,MAXLINE,fp)) > 0;)
  1174.     {
  1175.         bytes += strlen(str);
  1176.         if(ins(str) < 0)
  1177.         {
  1178.             printf("file insert error\n");
  1179.             err++;
  1180.             break;
  1181.         }
  1182.         lines++;
  1183.     }
  1184.     fclose(fp);
  1185.     if(err < 0)
  1186.         return(err);
  1187.     if (diag) {
  1188.         printf("%d lines %d bytes",lines,bytes);
  1189.         if(nonascii)
  1190.             printf(" [%d non-ascii]",nonascii);
  1191.         if(nullchar)
  1192.             printf(" [%d nul]",nullchar);
  1193.         if(truncated)
  1194.             printf(" [%d lines truncated]",truncated);
  1195.         printf("\n");
  1196.     }
  1197.     return( err );
  1198. }
  1199.  
  1200. /*    dowrite.c    */
  1201. /* #include <stdio.h> */
  1202. /* #include "tools.h" */
  1203. /* #include "ed.h" */
  1204.  
  1205. dowrite(from, to, fname, apflg)
  1206. int    from, to;
  1207. char    *fname;
  1208. int    apflg;
  1209. {
  1210.     extern FILE    *fopen();
  1211.     FILE    *fp;
  1212.     int    lin, err;
  1213.     int    lines, bytes;
  1214.     char    *str;
  1215.  
  1216.     err = 0;
  1217.  
  1218.     lines = bytes = 0;
  1219.     if (diag)
  1220.         printf("\"%s\" ",fname);
  1221.     
  1222.     if((fp = fopen(fname,(apflg?"a":"w"))) == NULL)
  1223.     {
  1224.         printf("file open error\n");
  1225.         return( ERR );
  1226.     }
  1227.     for(lin = from; lin <= to; lin++)
  1228.     {
  1229.         str = gettxt(lin);
  1230.         lines++;
  1231.         bytes += strlen(str);
  1232.         if(fputs(str, fp) == EOF)
  1233.         {
  1234.             printf("file write error\n");
  1235.             err++;
  1236.             break;
  1237.         }
  1238.     }
  1239.     if (diag)
  1240.         printf("%d lines %d bytes\n",lines,bytes);
  1241.  
  1242.     fclose(fp);
  1243.     return( err );
  1244. }
  1245.  
  1246. /*    ed.c    */
  1247. /*
  1248.  * Copyright 1987 Brian Beattie Rights Reserved.
  1249.  *
  1250.  * Permission to copy and/or distribute granted under the
  1251.  * following conditions:
  1252.  *
  1253.  * 1). No charge may be made other than resonable charges
  1254.  *    for reproduction.
  1255.  *
  1256.  * 2). This notice must remain intact.
  1257.  *
  1258.  * 3). No further restrictions may be added.
  1259.  *
  1260.  */
  1261. /* #include <stdio.h> */
  1262. /* #include "tools.h" */
  1263. /* #include "ed.h" */
  1264. #include <setjmp.h>
  1265. jmp_buf    env;
  1266.  
  1267. LINE    line0;
  1268. int    curln = 0;
  1269. int    lastln = 0;
  1270. char    *inptr;
  1271. static char    inlin[MAXLINE];
  1272. int    nflg, lflg, pflg, pflag, prompt;
  1273. int    line1, line2, nlines;
  1274. extern char    fname[];
  1275. int    version = 103;
  1276. int    diag=1;
  1277.  
  1278. void intr()
  1279. {
  1280.     printf("?\n");
  1281.     longjmp(env, 1);
  1282. }
  1283.  
  1284. void main(argc,argv)
  1285. int    argc;
  1286. char    **argv;
  1287. {
  1288.     int    stat, i, doflush;
  1289.  
  1290.     edsetbuf();
  1291.     doflush=isatty(1);
  1292.  
  1293.     if (argc>1 && argv[1][0]=='-' && argv[1][1]==0) {
  1294.         diag=0;
  1295.         argc--;
  1296.         argv++;
  1297.     }
  1298.     if(argc > 1)
  1299.     {
  1300.         for(i = 1; i < argc; i++)
  1301.         {
  1302.             if(doread(0,argv[i])==0) {
  1303.                 curln = 1;
  1304.                 strcpy(fname, argv[i]);
  1305.                 break;
  1306.             }
  1307.         }
  1308.     }
  1309.     while(1)
  1310.     {
  1311.         setjmp(env);
  1312.         signal(2, intr);
  1313.  
  1314.         if (prompt)
  1315.         {
  1316.             if (nflg) printf("%d",curln);
  1317.             printf("*");
  1318.         }
  1319.  
  1320.         if (doflush) fflush(stdout);
  1321.  
  1322.         if (fgets(inlin, sizeof(inlin),stdin) == NULL)
  1323.         {
  1324.             break;
  1325.         }
  1326. /*
  1327.         if(*inlin == '!')
  1328.         {
  1329.             for(inptr = inlin; *inptr != NL; inptr++)
  1330.                 ;
  1331.             *inptr = EOS;
  1332.             system(inlin+1);
  1333.             continue;
  1334.         }
  1335. */
  1336.         inptr = inlin;
  1337.         if(getlst() >= 0)
  1338.             if((stat = ckglob()) != 0)
  1339.             {
  1340.                 if(stat >= 0 && (stat = doglob()) >= 0)
  1341.                 {
  1342.                     curln = stat;
  1343.                     continue;
  1344.                 }
  1345.             } else {
  1346.                 if((stat = docmd(0)) >= 0)
  1347.                 {
  1348.                     if(stat == 1)
  1349.                         doprnt(curln, curln);
  1350.                     continue;
  1351.                 }
  1352.             }
  1353.         if(stat == EOF)
  1354.         {
  1355.             exit(0);
  1356.         }
  1357.         if(stat == FATAL)
  1358.         {
  1359.             fputs("FATAL ERROR\n",stderr);
  1360.             exit(1);
  1361.         }
  1362.         printf("?\n");
  1363.     }
  1364. }
  1365.  
  1366. /*    egets.c    */
  1367. /* #include <stdio.h> */
  1368. /* #include "tools.h" */
  1369. /* #include "ed.h" */
  1370.  
  1371. int    truncflg = 1;    /* truncate long line flag */
  1372. int    eightbit = 1;    /* save eight bit */
  1373. int    nonascii, nullchar, truncated;
  1374. egets(str,size,stream)
  1375. char    *str;
  1376. int    size;
  1377. FILE    *stream;
  1378. {
  1379.     int    c, count;
  1380.     char    *cp;
  1381.  
  1382.     for(count = 0, cp = str; size > count;)
  1383.     {
  1384.         c = getc(stream);
  1385.         if(c == EOF)
  1386.         {
  1387.             *cp++ = '\n';
  1388.             *cp = EOS;
  1389.             if(count)
  1390.             {
  1391.                 printf("[Incomplete last line]\n");
  1392.             }
  1393.             return(count);
  1394.         }
  1395.         if(c == NL)
  1396.         {
  1397.             *cp++ = c;
  1398.             *cp = EOS;
  1399.             return(++count);
  1400.         }
  1401.         if(c > 127)
  1402.         {
  1403.             if(!eightbit)        /* if not saving eighth bit */
  1404.                 c = c&127;    /* strip eigth bit */
  1405.             nonascii++;        /* count it */
  1406.         }
  1407.         if(c)
  1408.         {
  1409.             *cp++ = c;    /* not null, keep it */
  1410.             count++;
  1411.         } else 
  1412.             nullchar++;    /* count nulls */
  1413.     }
  1414.     str[count-1] = EOS;
  1415.     if(c != NL)
  1416.     {
  1417.         printf("truncating line\n");
  1418.         truncated++;
  1419.         while((c = getc(stream)) != EOF)
  1420.             if(c == NL)
  1421.                 break;
  1422.     }
  1423.     return(count);
  1424. }
  1425.  
  1426. /*    esc.c    */
  1427. /* #include <stdio.h> */
  1428. /* #include "tools.h" */
  1429.  
  1430. /* Map escape sequences into their equivalent symbols.  Returns the
  1431.  * correct ASCII character.  If no escape prefix is present then s
  1432.  * is untouched and *s is returned, otherwise **s is advanced to point
  1433.  * at the escaped character and the translated character is returned.
  1434.  */
  1435. esc(s)
  1436. char    **s;
  1437. {
  1438.     register int    rval;
  1439.  
  1440.     
  1441.     if (**s != ESCAPE)
  1442.     {
  1443.         rval = **s;
  1444.     } else {
  1445.         (*s)++;
  1446.  
  1447.         switch(toupper(**s))
  1448.         {
  1449.         case '\000':
  1450.             rval = ESCAPE;    break;
  1451.         case 'S':
  1452.             rval = ' ';    break;
  1453.         case 'N':
  1454.             rval = '\n';    break;
  1455.         case 'T':
  1456.             rval = '\t';    break;
  1457.         case 'B':
  1458.             rval = '\b';    break;
  1459.         case 'R':
  1460.             rval = '\r';    break;
  1461.         default:
  1462.             rval = **s;    break;
  1463.         }
  1464.     }
  1465.  
  1466.     return (rval);
  1467. }
  1468.  
  1469. /*    find.c    */
  1470. /* #include <stdio.h> */
  1471. /* #include "tools.h" */
  1472. /* #include "ed.h" */
  1473.  
  1474. find(pat, dir)
  1475. TOKEN    *pat;
  1476. int    dir;
  1477. {
  1478.     int    i, num;
  1479.     char    *lin;
  1480.  
  1481.     num=curln;
  1482.     for(i=0; i<lastln; i++)
  1483.     {
  1484.         lin = gettxt(num);
  1485.         if(matchs(lin, pat, 0))
  1486.         {
  1487.             return(num);
  1488.         }
  1489.         num = (dir ? nextln(num) : prevln(num));
  1490.     }
  1491.     return ( ERR );
  1492. }
  1493.  
  1494. /*    getfn.c    */
  1495. /* #include <stdio.h> */
  1496. /* #include "tools.h" */
  1497. /* #include "ed.h" */
  1498.  
  1499. extern char    fname[MAXFNAME];
  1500. int nofname;
  1501.  
  1502. char    *
  1503. getfn()
  1504. {
  1505.     static char    file[256];
  1506.     char    *cp;
  1507.  
  1508.     if(*inptr == NL)
  1509.     {
  1510.         nofname=TRUE;
  1511.         strcpy(file, fname);
  1512.     } else {
  1513.         nofname=FALSE;
  1514.         while(*inptr == SP || *inptr == HT)
  1515.             inptr++;
  1516.  
  1517.         cp = file;
  1518.         while(*inptr && *inptr != NL && *inptr != SP && *inptr != HT)
  1519.         {
  1520.             *cp++ = *inptr++;
  1521.         }
  1522.         *cp = '\0';
  1523.  
  1524.         if(strlen(file) == 0)
  1525.         {
  1526.             printf("bad file name\n");
  1527.             return( NULL );
  1528.         }
  1529.     }
  1530.  
  1531.     if(strlen(file) == 0)
  1532.     {
  1533.         printf("no file name\n");
  1534.         return(NULL);
  1535.     }
  1536.     return( file );
  1537. }
  1538.  
  1539. /*    getlst.c    */
  1540. /* #include <stdio.h> */
  1541. /* #include "tools.h" */
  1542. /* #include "ed.h" */
  1543.  
  1544. getlst()
  1545. {
  1546.     int    num;
  1547.  
  1548.     line2 = 0;
  1549.     for(nlines = 0; (num = getone()) >= 0;)
  1550.     {
  1551.         line1 = line2;
  1552.         line2 = num;
  1553.         nlines++;
  1554.         if(*inptr != ',' && *inptr != ';')
  1555.             break;
  1556.         if(*inptr == ';')
  1557.             curln = num;
  1558.         inptr++;
  1559.     }
  1560.     nlines = min(nlines, 2);
  1561.     if(nlines == 0)
  1562.         line2 = curln;
  1563.     if(nlines <= 1)
  1564.         line1 = line2;
  1565.  
  1566.     if(num == ERR)
  1567.         return(num);
  1568.     else
  1569.         return(nlines);
  1570. }
  1571.  
  1572. /*    getnum.c    */
  1573. /* #include <stdio.h> */
  1574. /* #include "tools.h" */
  1575. /* #include "ed.h" */
  1576.  
  1577. int mark['z'-'a'+1];
  1578.  
  1579. getnum(first) int first;
  1580. {
  1581.     TOKEN    *srchpat;
  1582.     int    num;
  1583.     char    c;
  1584.  
  1585.     while(*inptr == SP || *inptr == HT)
  1586.         inptr++;
  1587.  
  1588.     if(*inptr >= '0' && *inptr <= '9')    /* line number */
  1589.     {
  1590.         for(num = 0; *inptr >= '0' && *inptr <= '9';)
  1591.         {
  1592.             num = (num * 10) + *inptr - '0';
  1593.             inptr++;
  1594.         }
  1595.         return num;
  1596.     }
  1597.  
  1598.     switch(c = *inptr)
  1599.     {
  1600.     case '.':
  1601.         inptr++;
  1602.         return (curln);
  1603.  
  1604.     case '$':
  1605.         inptr++;
  1606.         return (lastln);
  1607.  
  1608.     case '/':
  1609.     case '?':
  1610.         srchpat = optpat();
  1611.         if(*inptr == c)
  1612.             inptr++;
  1613.         return(find(srchpat,c == '/'?1:0));
  1614.  
  1615.     case '-':
  1616.     case '+':
  1617.         return(first ? curln : 1);
  1618.  
  1619.     case '\'':
  1620.         inptr++;
  1621.         if (*inptr < 'a' || *inptr > 'z')
  1622.             return(EOF);
  1623.  
  1624.         return mark[ *inptr++ - 'a' ];
  1625.  
  1626.     default:
  1627.         return ( first ? EOF : 1 );    /* unknown address */
  1628.     }
  1629. }
  1630.  
  1631. /*    getone.c    */
  1632. /* #include <stdio.h> */
  1633. /* #include "tools.h" */
  1634. /* #include "ed.h" */
  1635.  
  1636. #define FIRST 1
  1637. #define NOTFIRST 0
  1638.  
  1639. getone()
  1640. {
  1641.     int    c, i, num;
  1642.  
  1643.     if((num = getnum(FIRST)) >= 0)
  1644.     {
  1645.         while(1)
  1646.         {
  1647.             while(*inptr == SP || *inptr == HT)
  1648.                 inptr++;
  1649.  
  1650.             if(*inptr != '+' && *inptr != '-')
  1651.                 break;
  1652.                         c = *inptr++;
  1653.  
  1654.             if((i = getnum(NOTFIRST)) < 0)
  1655.                 return ( i );
  1656.  
  1657.             if(c == '+')
  1658.             {
  1659.                 num += i;
  1660.             } else {
  1661.                 num -= i;
  1662.             }
  1663.         }
  1664.     }
  1665.     return ( num>lastln ? ERR : num );
  1666. }
  1667.  
  1668. /*    getpat.c    */
  1669. /* #include <stdio.h> */
  1670. /* #include "tools.h" */
  1671.  
  1672. /* Translate arg into a TOKEN string */
  1673. TOKEN    *
  1674. getpat (arg)
  1675. char    *arg;
  1676. {
  1677.     
  1678.     return (makepat(arg, '\000'));
  1679. }
  1680.  
  1681. /*    getptr.c    */
  1682. /* #include <stdio.h> */
  1683. /* #include "tools.h" */
  1684. /* #include "ed.h" */
  1685.  
  1686. LINE    *
  1687. getptr(num)
  1688. int    num;
  1689. {
  1690.     LINE    *ptr;
  1691.     int    j;
  1692.  
  1693.     if (2*num>lastln && num<=lastln) {    /* high line numbers */
  1694.         ptr = line0.l_prev;
  1695.         for (j = lastln; j>num; j--)
  1696.             ptr = ptr->l_prev;
  1697.     } else {                /* low line numbers */
  1698.         ptr = &line0;
  1699.         for(j = 0; j < num; j++)
  1700.             ptr = ptr->l_next;
  1701.     }
  1702.     return(ptr);
  1703. }
  1704.  
  1705. /*    getrhs.c    */
  1706. /* #include <stdio.h> */
  1707. /* #include "tools.h" */
  1708. /* #include "ed.h" */
  1709.  
  1710. getrhs(sub)
  1711. char    *sub;
  1712. {
  1713.     if(inptr[0] == NL || inptr[1] == NL)    /* check for eol */
  1714.         return( ERR );
  1715.  
  1716.     if(maksub(sub, MAXPAT) == NULL)
  1717.         return( ERR );
  1718.     
  1719.     inptr++;        /* skip over delimter */
  1720.     while(*inptr == SP || *inptr == HT)
  1721.             inptr++;
  1722.     if(*inptr == 'g')
  1723.     {
  1724.         inptr++;
  1725.         return( 1 );
  1726.     }
  1727.     return( 0 );
  1728. }
  1729.  
  1730. /*    gettxt.c    */
  1731. /* #include <stdio.h> */
  1732. /* #include "tools.h" */
  1733. /* #include "ed.h" */
  1734.  
  1735. char    *
  1736. gettxt(num)
  1737. int    num;
  1738. {
  1739.     LINE    *lin;
  1740.     static char    txtbuf[MAXLINE];
  1741.  
  1742.     lin = getptr(num);
  1743.     strcpy(txtbuf,lin->l_buff);
  1744.     strcat(txtbuf,"\n");
  1745.     return(txtbuf);
  1746. }
  1747.  
  1748. /*    ins.c    */
  1749. /* #include <stdio.h> */
  1750. /* #include "tools.h" */
  1751. /* #include "ed.h" */
  1752.  
  1753. ins(str)
  1754. char    *str;
  1755. {
  1756.     char    buf[MAXLINE], *cp;
  1757.     LINE    *new, *cur, *nxt;
  1758.  
  1759.     cp = buf;
  1760.     while(1)
  1761.     {
  1762.         if((*cp = *str++) == NL)
  1763.             *cp = EOS;
  1764.         if(*cp)
  1765.         {
  1766.             cp++;
  1767.             continue;
  1768.         }
  1769.         if((new = (LINE *)malloc(sizeof(LINE)+strlen(buf))) == NULL)
  1770.             return( ERR );     /* no memory */
  1771.  
  1772.         new->l_stat=0;
  1773.         strcpy(new->l_buff,buf);    /* build new line */
  1774.         cur = getptr(curln);        /* get current line */
  1775.         nxt = getptr(nextln(curln));    /* get next line */
  1776.         relink(cur, new, new, nxt);    /* add to linked list */
  1777.         relink(new, nxt, cur, new);
  1778.         lastln++;
  1779.         curln++;
  1780.  
  1781.         if(*str == EOS)        /* end of line ? */
  1782.             return( 1 );
  1783.  
  1784.         cp = buf;
  1785.     }
  1786. }
  1787.  
  1788. /*    join.c    */
  1789. /* #include <stdio.h> */
  1790. /* #include "tools.h" */
  1791. /* #include "ed.h" */
  1792.  
  1793. extern int fchanged;
  1794.  
  1795. join(first, last)
  1796. int first, last;
  1797. {
  1798.     char buf[MAXLINE];
  1799.     char *cp=buf, *str;
  1800.     int num;
  1801.  
  1802.     if (first<=0 || first>last || last>lastln)
  1803.         return(ERR);
  1804.     if (first==last) {
  1805.         curln=first;
  1806.         return 0;
  1807.     }
  1808.     for (num=first; num<=last; num++) {
  1809.         str=gettxt(num);
  1810.  
  1811.         while (*str!=NL && cp<buf+MAXLINE-1) *cp++ = *str++;
  1812.  
  1813.         if (cp==buf+MAXLINE-1) {
  1814.             printf("line too long\n");
  1815.             return(ERR);
  1816.         }
  1817.     }
  1818.     *cp++ = NL;
  1819.     *cp = EOS;
  1820.     del(first, last);
  1821.     curln=first-1;
  1822.     ins(buf);
  1823.     fchanged = TRUE;
  1824.     return 0;
  1825. }
  1826.  
  1827. /*    makepat.c    */
  1828. /* #include <stdio.h> */
  1829. /* #include "tools.h" */
  1830.  
  1831. /*
  1832.  * Make a pattern template from the strinng pointed to by arg.  Stop
  1833.  * when delim or '\000' or '\n' is found in arg.  Return a pointer to
  1834.  * the pattern template.
  1835.  *
  1836.  * The pattern template used here are somewhat different than those
  1837.  * used in the "Software Tools" book; each token is a structure of
  1838.  * the form TOKEN (see tools.h).  A token consists of an identifier,
  1839.  * a pointer to a string, a literal character and a pointer to another
  1840.  * token.  This last is 0 if there is no subsequent token.
  1841.  *
  1842.  * The one strangeness here is caused (again) by CLOSURE which has
  1843.  * to be put in front of the previous token.  To make this insertion a
  1844.  * little easier, the 'next' field of the last to point at the chain
  1845.  * (the one pointed to by 'tail) is made to point at the previous node.
  1846.  * When we are finished, tail->next is set to 0.
  1847.  */
  1848. TOKEN *
  1849. makepat(arg, delim)
  1850. char    *arg;
  1851. int    delim;
  1852. {
  1853.      TOKEN    *head, *tail, *ntok;
  1854.      int    error;
  1855.  
  1856.     /*
  1857.      * Check for characters that aren't legal at the beginning of
  1858.      * a template.
  1859.      */
  1860.  
  1861.     if (*arg=='\0' || *arg==delim || *arg=='\n' || *arg==CLOSURE)
  1862.         return(0);
  1863.  
  1864.     error = 0;
  1865.     tail = head = NULL;
  1866.  
  1867.     while (*arg && *arg != delim && *arg != '\n' && !error)
  1868.     {
  1869.         ntok = (TOKEN *)malloc(TOKSIZE);
  1870.         ntok->lchar = '\000';
  1871.         ntok->next = 0;
  1872.  
  1873.         switch(*arg)
  1874.         {
  1875.         case ANY:
  1876.             ntok->tok = ANY;
  1877.             break;
  1878.  
  1879.         case BOL:
  1880.             if (head == 0)    /* then this is the first symbol */
  1881.                 ntok->tok = BOL;
  1882.             else
  1883.                 ntok->tok = LITCHAR;
  1884.                 ntok->lchar = BOL;
  1885.             break;
  1886.  
  1887.         case EOL:
  1888.             if(*(arg+1) == delim || *(arg+1) == '\000' ||
  1889.                     *(arg+1) == '\n')
  1890.             {
  1891.                 ntok->tok = EOL;
  1892.             } else {
  1893.                 ntok->tok = LITCHAR;
  1894.                 ntok->lchar = EOL;
  1895.             }
  1896.             break;
  1897.  
  1898.         case CLOSURE:
  1899.             if (head != 0)
  1900.             {
  1901.                 switch (tail->tok)
  1902.                 {
  1903.                 case BOL:
  1904.                 case EOL:
  1905.                 case CLOSURE:
  1906.                     return (0);
  1907.                 
  1908.                 default:
  1909.                     ntok->tok = CLOSURE;
  1910.                 }
  1911.             }
  1912.             break;
  1913.  
  1914.         case CCL:
  1915.  
  1916.             if(*(arg + 1) == NEGATE)
  1917.             {
  1918.                 ntok->tok = NCCL;
  1919.                 arg += 2;
  1920.             } else {
  1921.                 ntok->tok = CCL;
  1922.                 arg++;
  1923.             }
  1924.  
  1925.             if( ntok->bitmap = makebitmap(CLS_SIZE) )
  1926.                 arg = dodash(CCLEND, arg, ntok->bitmap );
  1927.             else {
  1928.                 fprintf(stderr,"Not enough memory for pat\n");
  1929.                 error = 1;
  1930.             }
  1931.             break;
  1932.  
  1933.         default:
  1934.             if (*arg == ESCAPE && *(arg+1) == OPEN) {
  1935.                 ntok->tok = OPEN;
  1936.                 arg++;
  1937.             } else
  1938.             if (*arg == ESCAPE && *(arg+1) == CLOSE) {
  1939.                 ntok->tok = CLOSE;
  1940.                 arg++;
  1941.             } else {
  1942.                 ntok->tok = LITCHAR;
  1943.                 ntok->lchar = esc(&arg);
  1944.             }
  1945.         }
  1946.  
  1947.         if (error || ntok == 0)
  1948.         {
  1949.             unmakepat(head);
  1950.             return (0);
  1951.         } else if (head == 0)
  1952.         {
  1953.                 /* This is the first node in the chain. */
  1954.             
  1955.             ntok->next = 0;
  1956.             head = tail = ntok;
  1957.         } else if (ntok->tok != CLOSURE)
  1958.         {
  1959.             /* Insert at end of list (after tail) */
  1960.  
  1961.             tail->next = ntok;
  1962.             ntok->next = tail;
  1963.             tail = ntok;
  1964.         } else if (head != tail)
  1965.         {
  1966.             /*
  1967.              * More than one node in the chain.  Insert the
  1968.              * CLOSURE node immediately in front of tail.
  1969.              */
  1970.             
  1971.             (tail->next)->next = ntok;
  1972.             ntok->next = tail;
  1973.         } else {
  1974.             /*
  1975.              * Only one node in the chain,  Insert the CLOSURE
  1976.              * node at the head of the linked list.
  1977.              */
  1978.             
  1979.             ntok->next = head;
  1980.             tail->next = ntok;
  1981.             head = ntok;
  1982.         }
  1983.         arg++;
  1984.     }
  1985.  
  1986.     tail->next = 0;
  1987.     return (head);
  1988. }
  1989.  
  1990. /*    maksub.c    */
  1991. /* #include <stdio.h> */
  1992. /* #include "tools.h" */
  1993. /* #include "ed.h" */
  1994.  
  1995. char    *
  1996. maksub(sub, subsz)
  1997. char    *sub;
  1998. int    subsz;
  1999. {
  2000.     int    size;
  2001.     char    delim, *cp;
  2002.  
  2003.     size = 0;
  2004.     cp = sub;
  2005.  
  2006.     delim = *inptr++;
  2007.     for(size = 0; *inptr != delim && *inptr != NL && size < subsz; size++)
  2008.     {
  2009.         if(*inptr == '&')
  2010.         {
  2011.             *cp++ = DITTO;
  2012.             inptr++;
  2013.         } else
  2014.         if((*cp++ = *inptr++) == ESCAPE)
  2015.         {
  2016.             if (size>=subsz) return(NULL);
  2017.  
  2018.             switch(toupper(*inptr))
  2019.             {
  2020.             case NL:
  2021.                 *cp++ = ESCAPE;
  2022.                 break;
  2023.             case 'S':
  2024.                 *cp++ = SP;
  2025.                 inptr++;
  2026.                 break;
  2027.             case 'N':
  2028.                 *cp++ = NL;
  2029.                 inptr++;
  2030.                 break;
  2031.             case 'T':
  2032.                 *cp++ = HT;
  2033.                 inptr++;
  2034.                 break;
  2035.             case 'B':
  2036.                 *cp++ = BS;
  2037.                 inptr++;
  2038.                 break;
  2039.             case 'R':
  2040.                 *cp++ = CR;
  2041.                 inptr++;
  2042.                 break;
  2043.             case '0': {
  2044.                 int i=3;
  2045.                 *cp = 0;
  2046.                 do {
  2047.                     if (*++inptr<'0' || *inptr >'7')
  2048.                         break;
  2049.  
  2050.                     *cp = (*cp<<3) | (*inptr-'0');
  2051.                 } while (--i!=0);
  2052.                 cp++;
  2053.                 } break;
  2054.             default:
  2055.                 *cp++ = *inptr++;
  2056.                 break;
  2057.             }
  2058.         }
  2059.     }
  2060.     if(size >= subsz)
  2061.         return( NULL );
  2062.  
  2063.     *cp = EOS;
  2064.     return( sub );
  2065. }
  2066.  
  2067. /*    matchs.c    */
  2068. /* #include <stdio.h> */
  2069. /* #include "tools.h" */
  2070.  
  2071. /*
  2072.  * Compares line and pattern.  Line is a character string while pat
  2073.  * is a pattern template made by getpat().
  2074.  * Returns:
  2075.  *    1. A zero if no match was found.
  2076.  *
  2077.  *    2. A pointer to the last character satisfing the match
  2078.  *       if ret_endp is non-zero.
  2079.  *
  2080.  *    3. A pointer to the beginning of the matched string if
  2081.  *       ret_endp is zero.
  2082.  *
  2083.  * e.g.:
  2084.  *
  2085.  *    matchs ("1234567890", getpat("4[0-9]*7), 0);
  2086.  * will return a pointer to the '4', while:
  2087.  *
  2088.  *    matchs ("1234567890", getpat("4[0-9]*7), 1);
  2089.  * will return a pointer to the '7'.
  2090.  */
  2091. char    *
  2092. matchs(line, pat, ret_endp)
  2093. char    *line;
  2094. TOKEN    *pat;
  2095. int    ret_endp;
  2096. {
  2097.  
  2098.     char    *rval, *bptr;
  2099.  
  2100.     bptr = line;
  2101.  
  2102.     while(*line)
  2103.     {
  2104.         if ((rval = amatch(line, pat, bptr)) == 0)
  2105.         {
  2106.             line++;
  2107.         } else {
  2108.             if(rval > bptr && rval > line)
  2109.                 rval--;    /* point to last char matched */
  2110.             rval = ret_endp ? rval : line;
  2111.             break;
  2112.         }
  2113.     }
  2114.     return (rval);
  2115. }
  2116.  
  2117. /*    move.c    */
  2118. /* #include <stdio.h> */
  2119. /* #include "tools.h" */
  2120. /* #include "ed.h" */
  2121.  
  2122. move(num)
  2123. int    num;
  2124. {
  2125.     LINE    *k0, *k1, *k2, *k3;
  2126.  
  2127.     if(line1 <= 0 || line2 < line1 || line1 <= num && num <= line2)
  2128.         return( ERR );
  2129.     k0 = getptr(prevln(line1));
  2130.     k1 = getptr(line1);
  2131.     k2 = getptr(line2);
  2132.     k3 = getptr(nextln(line2));
  2133.      lastln -= line2-line1+1;
  2134.  
  2135.     relink(k0, k3, k0, k3);
  2136.  
  2137.     if (num > line1)
  2138.         num -= line2-line1+1;
  2139.  
  2140.     curln = num + (line2 - line1 + 1);
  2141.  
  2142.     k0 = getptr(num);
  2143.     k3 = getptr(nextln(num));
  2144.      lastln += line2-line1+1;
  2145.  
  2146.     relink(k0, k1, k2, k3);
  2147.     relink(k2, k3, k0, k1);
  2148.  
  2149.     return( 1 );
  2150. }
  2151.  
  2152. int transfer(num)
  2153. int num;
  2154. {
  2155.     int mid, lin, ntrans;
  2156.  
  2157.     if (line1<=0 || line1>line2)
  2158.         return(ERR);
  2159.  
  2160.     mid= num<line2 ? num : line2;
  2161.  
  2162.     curln=num;
  2163.     ntrans=0;
  2164.  
  2165.     for (lin=line1; lin<=mid; lin++) {
  2166.         ins(gettxt(lin));
  2167.         ntrans++;
  2168.     }
  2169.     lin+=ntrans;
  2170.     line2+=ntrans;
  2171.  
  2172.     for ( ; lin<=line2; lin+=2) {
  2173.         ins(gettxt(lin));
  2174.         line2++;
  2175.     }
  2176.     return(1);
  2177. }
  2178.  
  2179. /*    omatch.c    */
  2180. /* #include <stdio.h> */
  2181. /* #include "tools.h" */
  2182.  
  2183. /*
  2184.  * Match one pattern element, pointed at by pat, with the character at
  2185.  * **linp.  Return non-zero on match.  Otherwise, return 0.  *Linp is
  2186.  * advanced to skip over the matched character; it is not advanced on
  2187.  * failure.  The amount of advance is 0 for patterns that match null
  2188.  * strings, 1 otherwise.  "boln" should point at the position that will
  2189.  * match a BOL token.
  2190.  */
  2191. omatch(linp, pat, boln)
  2192. char    **linp;
  2193. TOKEN    *pat;
  2194. char    *boln;
  2195. {
  2196.     
  2197.     register int    advance;
  2198.  
  2199.     advance = -1;
  2200.  
  2201.     if (**linp)
  2202.     {
  2203.         switch (pat->tok)
  2204.         {
  2205.         case LITCHAR:
  2206.             if (**linp == pat->lchar)
  2207.                 advance = 1;
  2208.             break;
  2209.  
  2210.         case BOL:
  2211.             if (*linp = boln)
  2212.                 advance = 0;
  2213.             break;
  2214.  
  2215.         case ANY:
  2216.             if (**linp != '\n')
  2217.                 advance = 1;
  2218.             break;
  2219.  
  2220.         case EOL:
  2221.             if (**linp == '\n')
  2222.                 advance = 0;
  2223.             break;
  2224.  
  2225.         case CCL:
  2226.             if( testbit( **linp, pat->bitmap))
  2227.                 advance = 1;
  2228.             break;
  2229.  
  2230.         case NCCL:
  2231.             if (!testbit (**linp, pat->bitmap))
  2232.                 advance = 1;
  2233.             break;
  2234.         }
  2235.     }
  2236.     if (advance >= 0)
  2237.         *linp += advance;
  2238.  
  2239.     return (++advance);
  2240. }
  2241.  
  2242. /*    optpat.c    */
  2243. /* #include <stdio.h> */
  2244. /* #include "tools.h" */
  2245. /* #include "ed.h" */
  2246.  
  2247. TOKEN    *oldpat;
  2248.  
  2249. TOKEN    *
  2250. optpat()
  2251. {
  2252.     char    delim, str[MAXPAT], *cp;
  2253.  
  2254.     delim = *inptr++;
  2255.     cp = str;
  2256.     while(*inptr != delim && *inptr != NL)
  2257.     {
  2258.         if(*inptr == ESCAPE && inptr[1] != NL)
  2259.             *cp++ = *inptr++;
  2260.         *cp++ = *inptr++;
  2261.     }
  2262.  
  2263.     *cp = EOS;
  2264.     if(*str == EOS)
  2265.         return(oldpat);
  2266.     if(oldpat)
  2267.         unmakepat(oldpat);
  2268.     oldpat=getpat(str);
  2269.     return(oldpat);
  2270. }
  2271.  
  2272. /*    set.c    */
  2273. /* #include <stdio.h> */
  2274. /* #include "tools.h" */
  2275. /* #include "ed.h" */
  2276.  
  2277. struct tbl {
  2278.     char    *t_str;
  2279.     int    *t_ptr;
  2280.     int    t_val;
  2281. } *t, tbl[] = {
  2282.     "number",    &nflg,        TRUE,
  2283.     "nonumber",    &nflg,        FALSE,
  2284.     "list",        &lflg,        TRUE,
  2285.     "nolist",    &lflg,        FALSE,
  2286.     "eightbit",    &eightbit,    TRUE,
  2287.     "noeightbit",    &eightbit,    FALSE,
  2288.     "prompt",    &prompt,    TRUE,
  2289.     "noprompt",    &prompt,    FALSE,
  2290.     0
  2291. };
  2292.  
  2293. set()
  2294. {
  2295.     char    word[16];
  2296.     int    i;
  2297.  
  2298.     inptr++;
  2299.     if(*inptr != 't')
  2300.     {
  2301.         if(*inptr != SP && *inptr != HT && *inptr != NL)
  2302.             return(ERR);
  2303.     } else
  2304.         inptr++;
  2305.  
  2306.     if(*inptr == NL)
  2307.         return(show("all"));
  2308.         /* skip white space */
  2309.     while(*inptr == SP || *inptr == HT)
  2310.         inptr++;
  2311.  
  2312.     for(i = 0; *inptr != SP && *inptr != HT && *inptr != NL;)
  2313.         word[i++] = *inptr++;
  2314.     word[i] = EOS;
  2315.     for(t = tbl; t->t_str; t++)
  2316.     {
  2317.         if(strcmp(word,t->t_str) == 0)
  2318.         {
  2319.             *t->t_ptr = t->t_val;
  2320.             return(0);
  2321.         }
  2322.     }
  2323. }
  2324.  
  2325. show()
  2326. {
  2327.     extern int    version;
  2328.  
  2329.     printf("ed version %d.%d\n",version/100,version%100);
  2330.     printf("number %s, ",nflg?"ON":"OFF");
  2331.     printf("list %s, ",lflg?"ON":"OFF");
  2332.     printf("prompt %s,\n",prompt?"ON":"OFF");
  2333.     return(0);
  2334. }
  2335.  
  2336. /*    setbuf.c    */
  2337. /* #include <stdio.h> */
  2338. /* #include "tools.h" */
  2339. /* #include "ed.h" */
  2340.  
  2341. void relink(a, x, y, b)
  2342. LINE    *a, *x, *y, *b;
  2343. {
  2344.     x->l_prev = a;
  2345.     y->l_next = b;
  2346. }
  2347.  
  2348. void clrbuf()
  2349. {
  2350.     del(1, lastln);
  2351. }
  2352.  
  2353. void edsetbuf()
  2354. {
  2355.     relink(&line0, &line0, &line0, &line0);
  2356.     curln = lastln = 0;
  2357. }
  2358.  
  2359. /*    subst.c    */
  2360. /* #include <stdio.h> */
  2361. /* #include "tools.h" */
  2362. /* #include "ed.h" */
  2363.  
  2364. subst(pat, sub, gflg, pflag)
  2365. TOKEN    *pat;
  2366. char    *sub;
  2367. int    gflg, pflag;
  2368. {
  2369.     int    lin, chngd, nchngd;
  2370.     char    *txtptr, *txt;
  2371.     char    *lastm, *m, *new, buf[MAXLINE];
  2372.  
  2373.     if(line1 <= 0)
  2374.         return( ERR );
  2375.     nchngd = 0;        /* reset count of lines changed */
  2376.     for(lin = line1; lin <= line2; lin++)
  2377.     {
  2378.         txt = txtptr = gettxt(lin);
  2379.         new = buf;
  2380.         chngd = 0;
  2381.         lastm = NULL;
  2382.         while(*txtptr)
  2383.         {
  2384.             if(gflg || !chngd)
  2385.                 m = amatch(txtptr, pat, txt);
  2386.             else
  2387.                 m = NULL;
  2388.             if(m != NULL && lastm != m)
  2389.             {
  2390.                 chngd++;
  2391.                 new = catsub(txtptr, m, sub, new,
  2392.                         buf+MAXLINE);
  2393.                 lastm = m;
  2394.             }
  2395.             if(m == NULL || m == txtptr)
  2396.             {
  2397.                 *new++ = *txtptr++;
  2398.             } else {
  2399.                 txtptr = m;
  2400.             }
  2401.         }
  2402.         if(chngd)
  2403.         {
  2404.             if(new >= buf+MAXLINE)
  2405.                 return( ERR );
  2406.             *new++ = EOS;
  2407.             del(lin,lin);
  2408.             ins(buf);
  2409.             nchngd++;
  2410.             if(pflag)
  2411.                 doprnt(curln, curln);
  2412.         }
  2413.     }
  2414.     if(nchngd == 0 && !gflg)
  2415.     {
  2416.         return(ERR);
  2417.     }
  2418.     return( nchngd );
  2419. }
  2420.  
  2421. #if 0
  2422. /*    system.c    */
  2423. #define SHELL    "/bin/sh"
  2424.  
  2425. system(c)
  2426. char *c; {
  2427.     int pid, status;
  2428.     
  2429.     switch (pid = fork()) {
  2430.     case -1:
  2431.         return -1;
  2432.     case 0:
  2433.         execl(SHELL, "sh", "-c", c, (char *) 0);
  2434.         exit(-1);
  2435.     default:
  2436.         while (wait(&status) != pid)
  2437.             ;
  2438.     }
  2439.     return status;
  2440. }
  2441. #endif
  2442.  
  2443. /*    unmkpat.c    */
  2444. /* #include <stdio.h> */
  2445. /* #include "tools.h" */
  2446.  
  2447. /* Free up the memory usde for token string */
  2448. void unmakepat(head)
  2449. TOKEN    *head;
  2450. {
  2451.  
  2452.     register TOKEN    *old_head;
  2453.  
  2454.     while (head)
  2455.     {
  2456.         switch (head->tok)
  2457.         {
  2458.         case CCL:
  2459.         case NCCL:
  2460.             free(head->bitmap);
  2461.                 /* fall through to default */
  2462.  
  2463.         default:
  2464.             old_head = head;
  2465.             head = head->next;
  2466.             free (old_head);
  2467.             break;
  2468.         }
  2469.     }
  2470. }
  2471.  
  2472. isatty(fd)
  2473. int        fd;
  2474. {
  2475.     long IsInteractive();
  2476.     struct UFB    *ufb;
  2477.  
  2478.     ufb = chkufb(fd);
  2479.     if (ufb == NULL)
  2480.         return(-1);
  2481.     return(IsInteractive(ufb->ufbfh) != 0);
  2482. }
  2483. @
  2484.  
  2485.  
  2486. 1.4
  2487. log
  2488. @More amiga changes
  2489. @
  2490. text
  2491. @d3 2
  2492. d36 1
  2493. d41 1
  2494. a41 1
  2495. "$Header: Rodime:ricks/ked2/ked2.c,v 1.3 89/09/01 11:02:22 rick Exp Locker: rick $";
  2496. d144 1
  2497. a144 1
  2498. extern    int    unmakepat();
  2499. a153 2
  2500. #define max(a,b)    ((a>b)?a:b)
  2501. #define min(a,b)    ((a<b)?a:b)
  2502. d201 1
  2503. a229 1
  2504.     register i;
  2505. d594 1
  2506. d614 1
  2507. a614 1
  2508.     int    i, apflg, pflag, gflag;
  2509. d1056 1
  2510. a1056 1
  2511. prntln(str, vflg, lin)
  2512. d1093 1
  2513. a1093 1
  2514. putcntl(c, stream)
  2515. d1234 1
  2516. a1234 1
  2517. intr()
  2518. d1240 1
  2519. a1240 1
  2520. main(argc,argv)
  2521. d1244 1
  2522. a1244 1
  2523.     int    stat, i, j, doflush;
  2524. d1246 1
  2525. a1246 1
  2526.     setbuf();
  2527. a1809 1
  2528.      char    buf[CLS_SIZE];
  2529. d2297 1
  2530. a2297 1
  2531. relink(a, x, y, b)
  2532. d2304 1
  2533. a2304 1
  2534. clrbuf()
  2535. d2309 1
  2536. a2309 1
  2537. int setbuf()
  2538. d2404 1
  2539. a2404 1
  2540. unmakepat(head)
  2541. d2428 5
  2542. d2434 5
  2543. @
  2544.  
  2545.  
  2546. 1.3
  2547. log
  2548. @Amiga changes
  2549. @
  2550. text
  2551. @d38 1
  2552. a38 1
  2553. "$Header: Quantum:ricks/ked2/ed.c,v 1.1 89/08/27 17:44:11 rick Exp Locker: rick $";
  2554. d1309 1
  2555. a1309 1
  2556.             _cleanup(); exit(0);
  2557. d1314 1
  2558. a1314 1
  2559.             _cleanup(); exit(1);
  2560. @
  2561.  
  2562.  
  2563. 1.2
  2564. log
  2565. @No changes
  2566. @
  2567. text
  2568. @d1280 1
  2569. d1289 1
  2570. d2308 1
  2571. a2308 1
  2572. void setbuf()
  2573. d2376 1
  2574. d2396 1
  2575. @
  2576.  
  2577.  
  2578. 1.1
  2579. log
  2580. @Initial revision
  2581. @
  2582. text
  2583. @d38 1
  2584. a38 1
  2585. "$Header: ed.c,v 1.6 88/05/23 16:47:56 dnix Exp $";
  2586. @
  2587.