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