[comp.sources.atari.st] v02i016: sed -- GNU sed

koreth@ssyx.ucsc.edu (Steven Grimm) (02/25/89)

Submitted-by: saj@chinet.chi.il.us (Stephen Jacobs)
Posting-number: Volume 2, Issue 16
Archive-name: sed/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  sedexec.c sedtest.bat
# Wrapped by saj@chinet on Mon Jan 30 20:12:03 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f sedexec.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sedexec.c\"
else
echo shar: Extracting \"sedexec.c\" \(28811 characters\)
sed "s/^X//" >sedexec.c <<'END_OF_sedexec.c'
X#if 0					/* SAJ */
X#include "compiler.h"
X#ifdef LATTICE
X#define void int
X#endif
X
X#endif					/* SAJ */
X#include "debug.h"
X/*
Xsedexec.c -- execute compiled form of stream editor commands
X
X   The single entry point of this module is the function execute(). It
Xmay take a string argument (the name of a file to be used as text)  or
Xthe argument NULL which tells it to filter standard input. It executes
Xthe compiled commands in cmds[] on each line in turn.
X   The function command() does most of the work. Match() and advance()
Xare used for matching text against precompiled regular expressions and
Xdosub() does right-hand-side substitution.  Getline() does text input;
Xreadout() and memcmp() are output and string-comparison utilities.  
X
X==== Written for the GNU operating system by Eric S. Raymond ==== 
X*/
X
X#include <stdio.h>      /* {f}puts, {f}printf, getc/putc, f{re}open, fclose */
X#include <ctype.h>      /* for isprint(), isdigit(), toascii() macros */
X#include "sed.h"        /* command type structures & miscellaneous constants */
X
Xextern char     *strcpy();      /* used in dosub */
X
X/***** shared variables imported from the main ******/
X
X/* main data areas */
Xextern char     linebuf[];      /* current-line buffer */
Xextern sedcmd   cmds[];         /* hold compiled commands */
Xextern long     linenum[];      /* numeric-addresses table */
X
X/* miscellaneous shared variables */
Xextern int      nflag;          /* -n option flag */
Xextern int      eargc;          /* scratch copy of argument count */
Xextern sedcmd   *pending;       /* ptr to command waiting to be executed */
Xextern char     bits[];         /* the bits table */
X
X/***** end of imported stuff *****/
X
X#define MAXHOLD         MAXBUF  /* size of the hold space */
X#if 0		/* I had to leave this in.  Is it a joke, or what? 
X		 *3 Hours single stepping a broken program isn't funny  SAJ */
X#define GENSIZ          71      /* maximum genbuf size */
X#endif
X#define GENSIZ          500      /* maximum genbuf size */
X#define TRUE            1
X#define FALSE           0
X
Xstatic char LTLMSG[]    = "sed: line too long\n";
X
Xstatic char     *spend;         /* current end-of-line-buffer pointer */
Xstatic long     lnum = 0L;      /* current source line number */
X
X/* append buffer maintenance */
Xstatic sedcmd   *appends[MAXAPPENDS];   /* array of ptrs to a,i,c commands */
Xstatic sedcmd   **aptr = appends;       /* ptr to current append */
X
X/* genbuf and its pointers */
Xstatic char     genbuf[GENSIZ];
Xstatic char     *lcomend = genbuf + GENSIZ;
Xstatic char     *loc1;
Xstatic char     *loc2;
Xstatic char     *locs;
X
X/* command-logic flags */
Xstatic int      lastline;               /* do-line flag */
Xstatic int      jump;                   /* jump to cmd's link address if set */
Xstatic int      delete;                 /* delete command flag */
X
X/* tagged-pattern tracking */
Xstatic char     *bracend[MAXTAGS];      /* tagged pattern start pointers */
Xstatic char     *brastart[MAXTAGS];     /* tagged pattern end pointers */
X
X
Xvoid execute(file)
X/* execute the compiled commands in cmds[] on a file */
Xchar *file;             /* name of text source file to be filtered */
X{
X        register char           *p1, *p2;       /* dummy copy ptrs */
X        register sedcmd         *ipc;           /* ptr to current command */
X        char                    *execp;         /* ptr to source */
X        char                    *getline();     /* input-getting functions */
X        void                    command(), readout();
X
XPASS("execute(): entry");
X
X        if (file != NULL)       /* filter text from a named file */ 
X                if (freopen(file, "r", stdin) == NULL)
X                        fprintf(stderr, "sed: can't open %s\n", file);
XPASS("execute(): reopen");
X
X        if (pending)            /* there's a command waiting */
X        {
X                ipc = pending;          /* it will be first executed */
X                pending = FALSE;        /*   turn off the waiting flag */
X                goto doit;              /*   go to execute it immediately */
X        }
X
X        /* here's the main command-execution loop */
X        for(;;)
X        {
XPASS("execute(): main loop entry");
X
X                /* get next line to filter */
X                if ((execp = getline(linebuf)) == BAD)
X                        return;
XPASS("execute(): getline");
X                spend = execp;
X
X                /* loop through compiled commands, executing them */
X                for(ipc = cmds; ipc->command; )
X                {
XPASS("execute(): command loop entry");
X                        /* all no-address commands are selected */
X                        if (ipc->addr1 && !selected(ipc))
X                        {
X                                ipc++;
X                                continue;
X                        }
X        doit:
XPASS("execute(): doit");
X                        command(ipc);   /* execute the command pointed at */
XPASS("execute(): command");
X
X                        if (delete)     /* if delete flag is set */
X                                break;  /* don't exec rest of compiled cmds */
X
X                        if (jump)       /* if jump set, follow cmd's link */
X                        {
X                                jump = FALSE;
X                                if ((ipc = ipc->u.link) == 0)
X                                {
X                                        ipc = cmds;
X                                        break;
X                                }
X                        }
X                        else            /* normal goto next command */
X                                ipc++;
XPASS("execute(): end command loop");
X                }
X                /* we've now done all modification commands on the line */
X
X                /* here's where the transformed line is output */
XPASS("execute(): output");
X                if (!nflag && !delete)
X                {
X                        for(p1 = linebuf; p1 < spend; p1++)
X                                putc(*p1, stdout);
X                        putc('\n', stdout);
X                }
X
X                /* if we've been set up for append, emit the text from it */
X                if (aptr > appends)
X                        readout();
X
X                delete = FALSE; /* clear delete flag; about to get next cmd */
XPASS("execute(): end main loop");
X        }
XPASS("execute(): end execute");
X}
X
Xstatic int selected(ipc)
X/* is current command selected */
Xsedcmd  *ipc;
X{
X        register char   *p1 = ipc->addr1;       /* point p1 at first address */
X        register char   *p2 = ipc->addr2;       /*   and p2 at second */
X        char            c;
X
X        if (ipc->flags.inrange)
X        {
X                if (*p2 == CEND)
X                        p1 = NULL;
X                else if (*p2 == CLNUM)
X                {
X                        c = p2[1];
X                        if (lnum > linenum[c])
X                        {
X                                ipc->flags.inrange = FALSE;
X                                if (ipc->flags.allbut)
X                                        return(TRUE);
X                                ipc++;
X                                return(FALSE);
X                        }
X                        if (lnum == linenum[c])
X                                ipc->flags.inrange = FALSE;
X                }
X                else if (match(p2, 0))
X                        ipc->flags.inrange = FALSE;
X        }
X        else if (*p1 == CEND)
X        {
X                if (!lastline)
X                {
X                        if (ipc->flags.allbut)
X                                return(TRUE);
X                        ipc++;
X                        return(FALSE);
X                }
X        }
X        else if (*p1 == CLNUM)
X        {
X                c = p1[1];
X                if (lnum != linenum[c])
X                {
X                        if (ipc->flags.allbut)
X                                return(TRUE);
X                        ipc++;
X                        return(FALSE);
X                }
X                if (p2)
X                        ipc->flags.inrange = TRUE;
X        }
X        else if (match(p1, 0))
X        {
X                if (p2)
X                        ipc->flags.inrange = TRUE;
X        }
X        else
X        {
X                if (ipc->flags.allbut)
X                        return(TRUE);
X                ipc++;
X                return(FALSE);
X        }
X        return(TRUE);		/* SAJ for Atari ST, Mark Williams C */
X}
X
Xstatic int match(expbuf, gf)    /* uses genbuf */
X/* match RE at expbuf against linebuf; if gf set, copy linebuf from genbuf */
Xchar    *expbuf;
X{
X        register char   *p1, *p2, c;
X
X        if (gf)
X        {
X                if (*expbuf)
X                        return(FALSE);
X                p1 = linebuf; p2 = genbuf;
X                while (*p1++ = *p2++);
X                locs = p1 = loc2;
X        }
X        else
X        {
X                p1 = linebuf;
X                locs = FALSE;
X        }
X
X        p2 = expbuf;
X        if (*p2++)
X        {
X                loc1 = p1;
X                if(*p2 == CCHR && p2[1] != *p1) /* 1st char is wrong */
X                        return(FALSE);          /*   so fail */
X                return(advance(p1, p2));        /* else try to match rest */
X        }
X
X        /* quick check for 1st character if it's literal */
X        if (*p2 == CCHR)
X        {
X                c = p2[1];              /* pull out character to search for */
X                do {
X                        if (*p1 != c)
X                                continue;       /* scan the source string */
X                        if (advance(p1, p2))    /* found it, match the rest */
X                                return(loc1 = p1, 1);
X                } while
X                        (*p1++);
X                return(FALSE);          /* didn't find that first char */
X        }
X
X        /* else try for unanchored match of the pattern */
X        do {
X                if (advance(p1, p2))
X                        return(loc1 = p1, 1);
X        } while
X                (*p1++);
X
X        /* if got here, didn't match either way */
X        return(FALSE);
X}
X
Xstatic int advance(lp, ep)
X/* attempt to advance match pointer by one pattern element */
Xregister char   *lp;            /* source (linebuf) ptr */
Xregister char   *ep;            /* regular expression element ptr */
X{
X        register char   *curlp;         /* save ptr for closures */ 
X        char            c;              /* scratch character holder */
X        char            *bbeg;
X        int             ct;
X
X        for (;;)
X                switch (*ep++)
X                {
X                case CCHR:              /* literal character */
X                        if (*ep++ == *lp++)     /* if chars are equal */
X                                continue;       /* matched */
X                        return(FALSE);          /* else return false */
X
X                case CDOT:              /* anything but newline */
X                        if (*lp++)              /* first NUL is at EOL */
X                                continue;       /* keep going if didn't find */
X                        return(FALSE);          /* else return false */
X
X                case CNL:               /* start-of-line */
X                case CDOL:              /* end-of-line */
X                        if (*lp == 0)           /* found that first NUL? */
X                                continue;       /* yes, keep going */
X                        return(FALSE);          /* else return false */
X
X                case CEOF:              /* end-of-address mark */
X                        loc2 = lp;              /* set second loc */
X                        return(TRUE);           /* return true */
X
X                case CCL:               /* a closure */
X                        c = *lp++ & 0177;
X                        if (ep[c>>3] & bits[c & 07])    /* is char in set? */
X                        {
X                                ep += 16;       /* then skip rest of bitmask */
X                                continue;       /*   and keep going */
X                        }
X                        return(FALSE);          /* else return false */
X
X                case CBRA:              /* start of tagged pattern */
X                        brastart[*ep++] = lp;   /* mark it */
X                        continue;               /* and go */
X
X                case CKET:              /* end of tagged pattern */
X                        bracend[*ep++] = lp;    /* mark it */
X                        continue;               /* and go */
X
X                case CBACK: 
X                        bbeg = brastart[*ep];
X                        ct = bracend[*ep++] - bbeg;
X
X                        if (memcmp(bbeg, lp, ct))
X                        {
X                                lp += ct;
X                                continue;
X                        }
X                        return(FALSE);
X
X                case CBACK|STAR:
X                        bbeg = brastart[*ep];
X                        ct = bracend[*ep++] - bbeg;
X                        curlp = lp;
X                        while(memcmp(bbeg, lp, ct))
X                                lp += ct;
X
X                        while(lp >= curlp)
X                        {
X                                if (advance(lp, ep))
X                                        return(TRUE);
X                                lp -= ct;
X                        }
X                        return(FALSE);
X
X
X                case CDOT|STAR:         /* match .* */
X                        curlp = lp;             /* save closure start loc */
X                        while (*lp++);          /* match anything */ 
X                        goto star;              /* now look for followers */
X
X                case CCHR|STAR:         /* match <literal char>* */
X                        curlp = lp;             /* save closure start loc */
X                        while (*lp++ == *ep);   /* match many of that char */
X                        ep++;                   /* to start of next element */
X                        goto star;              /* match it and followers */
X
X                case CCL|STAR:          /* match [...]* */
X                        curlp = lp;             /* save closure start loc */
X                        do {
X                                c = *lp++ & 0x7F;       /* match any in set */
X                        } while
X                                (ep[c>>3] & bits[c & 07]);
X                        ep += 16;               /* skip past the set */
X                        goto star;              /* match followers */
X
X                star:           /* the recursion part of a * or + match */
X                        if (--lp == curlp)      /* 0 matches */
X                                continue;
X
X                        if (*ep == CCHR)
X                        {
X                                c = ep[1];
X                                do {
X                                        if (*lp != c)
X                                                continue;
X                                        if (advance(lp, ep))
X                                                return(TRUE);
X                                } while
X                                        (lp-- > curlp);
X                                return(FALSE);
X                        }
X
X                        if (*ep == CBACK)
X                        {
X                                c = *(brastart[ep[1]]);
X                                do {
X                                        if (*lp != c)
X                                                continue;
X                                        if (advance(lp, ep))
X                                                return(TRUE);
X                                } while
X                                        (lp-- > curlp);
X                                return(FALSE);
X                        }
X        
X                        do {
X                                if (lp == locs)
X                                        break;
X                                if (advance(lp, ep))
X                                        return(TRUE);
X                        } while
X                                (lp-- > curlp);
X                        return(FALSE);
X
X                default:
X                        fprintf(stderr, "sed: RE error, %o\n", *--ep);
X                }
X}
X
Xstatic int substitute(ipc)
X/* perform s command */
Xsedcmd  *ipc;                           /* ptr to s command struct */
X{
X        void dosub();                   /* for if we find a match */
X
X        if (match(ipc->u.lhs, 0))               /* if no match */
X                dosub(ipc->rhs);                /* perform it once */
X        else
X                return(FALSE);                  /* command fails */
X
X        if (ipc->flags.global)                  /* if global flag enabled */
X                while(*loc2)                    /* cycle through possibles */
X                        if (match(ipc->u.lhs, 1))       /* found another */
X                                dosub(ipc->rhs);        /* so substitute */
X                        else                            /* otherwise, */
X                                break;                  /* we're done */
X        return(TRUE);                           /* we succeeded */
X}
X
Xstatic void dosub(rhsbuf)               /* uses linebuf, genbuf, spend */
X/* generate substituted right-hand side (of s command) */
Xchar    *rhsbuf;        /* where to put the result */
X{
X        register char   *lp, *sp, *rp;
X        int             c;
X        char            *place();
X
X        /* copy linebuf to genbuf up to location  1 */
X        lp = linebuf; sp = genbuf;
X        while (lp < loc1) *sp++ = *lp++;
X
X        for (rp = rhsbuf; c = *rp++; )
X        {
X                if (c == '&')
X                {
X                        sp = place(sp, loc1, loc2);
X                        continue;
X                }
X                else if (c & 0200 && (c &= 0177) >= '1' && c < MAXTAGS+'1')
X                {
X                        sp = place(sp, brastart[c-'1'], bracend[c-'1']);
X                        continue;
X                }
X                *sp++ = c & 0177;
X                if (sp >= genbuf + MAXBUF)
X                        fprintf(stderr, LTLMSG);
X        }
X        lp = loc2;
X/* MRY  loc2 = sp - genbuf + linebuf; */
X        loc2 = sp - (genbuf - linebuf);
X        while (*sp++ = *lp++)
X                if (sp >= genbuf + MAXBUF)
X                        fprintf(stderr, LTLMSG);
X        lp = linebuf; sp = genbuf;
X        while (*lp++ = *sp++);
X        spend = lp-1;
X}
X
Xstatic char *place(asp, al1, al2)               /* uses genbuf */
X/* place chars at *al1...*(al1 - 1) at asp... in genbuf[] */
Xregister char   *asp, *al1, *al2;
X{
X        while (al1 < al2)
X        {
X                *asp++ = *al1++;
X                if (asp >= genbuf + MAXBUF)
X                        fprintf(stderr, LTLMSG);
X        }
X        return(asp);
X}
X
Xstatic void listto(p1, fp)
X/* write a hex dump expansion of *p1... to fp */
Xregister char   *p1;            /* the source */
XFILE            *fp;            /* output stream to write to */
X{
X        p1--;
X        while(*p1++)
X                if (isprint(*p1))
X                        putc(*p1, fp);          /* pass it through */
X                else
X                {
X                        putc('\134', fp);               /* emit a backslash */
X                        switch(*p1)
X                        {
X                        case '\10':     putc('b', fp); break;   /* BS */
X                        case '\11':     putc('t', fp); break;   /* TAB */
X/* \11 was \9 --MRY */
X                        case '\12':     putc('n', fp); break;   /* NL */
X                        case '\15':     putc('r', fp); break;   /* CR */
X                        case '\33':     putc('e', fp); break;   /* ESC */
X                        default:        fprintf(fp, "%02x", *p1 & 0xFF);
X                        }
X                }
X        putc('\n', fp);
X}
X
Xstatic void command(ipc)
X/* execute compiled command pointed at by ipc */
Xsedcmd  *ipc;
X{
X        static int      didsub;                 /* true if last s succeeded */
X        static char     holdsp[MAXHOLD];        /* the hold space */
X        static char     *hspend = holdsp;       /* hold space end pointer */
X        register char   *p1, *p2, *p3;
X        register int    i;
X        char            *execp;
X
X        switch(ipc->command)
X        {
X        case ACMD:              /* append */
X                *aptr++ = ipc;
X                if (aptr >= appends + MAXAPPENDS)
X                        fprintf(stderr,
X                                "sed: too many appends after line %ld\n",
X                                lnum);
X                *aptr = 0;
X                break;
X
X        case CCMD:              /* change pattern space */
X                delete = TRUE;
X                if (!ipc->flags.inrange || lastline)
X                        printf("%s\n", ipc->u.lhs);             
X                break;
X
X        case DCMD:              /* delete pattern space */
X                delete++;
X                break;
X
X        case CDCMD:             /* delete a line in hold space */
X                p1 = p2 = linebuf;
X                while(*p1 != '\n')
X                        if (delete = (*p1++ == 0))
X                                return;
X                p1++;
X                while(*p2++ = *p1++) continue;
X                spend = p2-1;
X                jump++;
X                break;
X
X        case EQCMD:             /* show current line number */
X                fprintf(stdout, "%ld\n", lnum);
X                break;
X
X        case GCMD:              /* copy hold space to pattern space */
X                p1 = linebuf;   p2 = holdsp;    while(*p1++ = *p2++);
X                spend = p1-1;
X                break;
X
X        case CGCMD:             /* append hold space to pattern space */
X                *spend++ = '\n';
X                p1 = spend;     p2 = holdsp;
X                while(*p1++ = *p2++)
X                        if (p1 >= linebuf + MAXBUF)
X                                break;
X                spend = p1-1;
X                break;
X
X        case HCMD:              /* copy pattern space to hold space */
X                p1 = holdsp;    p2 = linebuf;   while(*p1++ = *p2++);
X                hspend = p1-1;
X                break;
X
X        case CHCMD:             /* append pattern space to hold space */
X                *hspend++ = '\n';
X                p1 = hspend;    p2 = linebuf;
X                while(*p1++ = *p2++)
X                        if (p1 >= holdsp + MAXBUF)
X                                break;
X                hspend = p1-1;
X                break;
X
X        case ICMD:              /* insert text */
X                printf("%s\n", ipc->u.lhs);
X                break;
X
X        case BCMD:              /* branch to label */
X                jump = TRUE;
X                break;
X
X        case LCMD:              /* list text */
X                listto(linebuf, (ipc->fout != NULL)?ipc->fout:stdout); break;
X
X        case NCMD:      /* read next line into pattern space */
X                if (!nflag)
X                        puts(linebuf);  /* flush out the current line */
X                if (aptr > appends)
X                        readout();      /* do pending a, r commands */
X                if ((execp = getline(linebuf)) == BAD)
X                {
X                        pending = ipc;
X                        delete = TRUE;
X                        break;
X                }
X                spend = execp;
X                break;
X
X        case CNCMD:     /* append next line to pattern space */
X                if (aptr > appends)
X                        readout();
X                *spend++ = '\n';
X                if ((execp = getline(spend)) == BAD)
X                {
X                        pending = ipc;
X                        delete = TRUE;
X                        break;
X                }
X                spend = execp;
X                break;
X
X        case PCMD:              /* print pattern space */
X                puts(linebuf);
X                break;
X
X        case CPCMD:             /* print one line from pattern space */
X                cpcom:          /* so s command can jump here */
X                for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
X                        putc(*p1++, stdout);
X                putc('\n', stdout);
X                break;
X
X        case QCMD:              /* quit the stream editor */
X                if (!nflag)
X                        puts(linebuf);  /* flush out the current line */
X                if (aptr > appends)
X                        readout();      /* do any pending a and r commands */
X                exit(0);
X
X        case RCMD:              /* read a file into the stream */
X                *aptr++ = ipc;
X                if (aptr >= appends + MAXAPPENDS)
X                        fprintf(stderr,
X                                "sed: too many reads after line %ld\n",
X                                lnum);
X                *aptr = 0;
X                break;
X
X        case SCMD:              /* substitute RE */
X                didsub = substitute(ipc);
X                if (ipc->flags.print && didsub)
X                        if (ipc->flags.print == TRUE)
X                                puts(linebuf);
X                        else
X                                goto cpcom;
X                if (didsub && ipc->fout)
X                        fprintf(ipc->fout, "%s\n", linebuf);
X                break;
X
X        case TCMD:              /* branch on last s successful */
X        case CTCMD:             /* branch on last s failed */
X                if (didsub == (ipc->command == CTCMD))
X                        break;          /* no branch if last s failed, else */
X                didsub = FALSE;
X                jump = TRUE;            /*  set up to jump to assoc'd label */
X                break;
X
X        case CWCMD:             /* write one line from pattern space */
X                for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
X                        putc(*p1++, ipc->fout);
X                putc('\n', ipc->fout);
X                break;
X
X        case WCMD:              /* write pattern space to file */
X                fprintf(ipc->fout, "%s\n", linebuf);
X                break;
X
X        case XCMD:              /* exchange pattern and hold spaces */
X                p1 = linebuf;   p2 = genbuf;    while(*p2++ = *p1++) continue;
X                p1 = holdsp;    p2 = linebuf;   while(*p2++ = *p1++) continue;
X                spend = p2 - 1;
X                p1 = genbuf;    p2 = holdsp;    while(*p2++ = *p1++) continue;
X                hspend = p2 - 1;
X                break;
X
X        case YCMD:
X                p1 = linebuf;   p2 = ipc->u.lhs;
X                while(*p1 = p2[*p1])
X                        p1++;
X                break;
X        }
X}
X
Xstatic char *getline(buf)
X/* get next line of text to be filtered */
Xregister char   *buf;           /* where to send the input */
X{
X        if (gets(buf) != NULL)
X        {
X                lnum++;                 /* note that we got another line */
X                while(*buf++);          /* find the end of the input */
X                return(--buf);          /* return ptr to terminating null */ 
X        }
X        else
X        {
X                if (eargc == 0)                 /* if no more args */
X                        lastline = TRUE;        /*    set a flag */
X                return(BAD);
X        }
X}
X
Xstatic int memcmp(a, b, count)
X/* return TRUE if *a... == *b... for count chars, FALSE otherwise */
Xregister char   *a, *b;
X{
X        while(count--)                  /* look at count characters */
X                if (*a++ != *b++)       /* if any are nonequal   */
X                        return(FALSE);  /*    return FALSE for false */
X        return(TRUE);                   /* compare succeeded */
X}
X
Xstatic void readout()
X/* write file indicated by r command to output */
X{
X        register char   *p1;    /* character-fetching dummy */
X        register int    t;      /* hold input char or EOF */
X        FILE            *fi;    /* ptr to file to be read */
X
X        aptr = appends - 1;     /* arrange for pre-increment to work right */
X        while(*++aptr)
X                if ((*aptr)->command == ACMD)           /* process "a" cmd */
X                        printf("%s\n", (*aptr)->u.lhs);
X                else                                    /* process "r" cmd */
X                {
X                        if ((fi = fopen((*aptr)->u.lhs, "r")) == NULL)
X                                continue;
X                        while((t = getc(fi)) != EOF)
X                                putc((char) t, stdout);
X                        fclose(fi);
X                }
X        aptr = appends;         /* reset the append ptr */
X        *aptr = 0;
X}
X
X/* sedexec.c ends here */
END_OF_sedexec.c
if test 28811 -ne `wc -c <sedexec.c`; then
    echo shar: \"sedexec.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sedtest.bat -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sedtest.bat\"
else
echo shar: Extracting \"sedtest.bat\" \(21 characters\)
sed "s/^X//" >sedtest.bat <<'END_OF_sedtest.bat'
Xsed -f ctrans pascal
END_OF_sedtest.bat
if test 21 -ne `wc -c <sedtest.bat`; then
    echo shar: \"sedtest.bat\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0