From 30154ac8a86b4987758047cd7b94de39dab9d8d8 Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Fri, 18 Jun 1993 13:00:14 +0000 Subject: [PATCH] POSIX ed version 0.6 by Andrew Moore (alm@netcom.com). --- bin/ed/Makefile | 7 + bin/ed/POSIX | 50 ++ bin/ed/README | 22 + bin/ed/buf.c | 246 ++++++++++ bin/ed/cbc.c | 435 +++++++++++++++++ bin/ed/ed.1 | 980 +++++++++++++++++++++++++++++++++++++++ bin/ed/ed.h | 263 +++++++++++ bin/ed/re.c | 156 +++++++ bin/ed/test/=.err | 1 + bin/ed/test/Makefile | 17 + bin/ed/test/README | 41 ++ bin/ed/test/TODO | 15 + bin/ed/test/a.d | 5 + bin/ed/test/a.r | 8 + bin/ed/test/a.t | 9 + bin/ed/test/a1.err | 3 + bin/ed/test/a2.err | 3 + bin/ed/test/addr1.err | 1 + bin/ed/test/addr2.err | 1 + bin/ed/test/ascii.d | Bin 0 -> 256 bytes bin/ed/test/ascii.r | Bin 0 -> 256 bytes bin/ed/test/ascii.t | 0 bin/ed/test/c.d | 5 + bin/ed/test/c.r | 4 + bin/ed/test/c.t | 12 + bin/ed/test/c1.err | 3 + bin/ed/test/c2.err | 3 + bin/ed/test/ckscripts.sh | 37 ++ bin/ed/test/d.d | 5 + bin/ed/test/d.err | 1 + bin/ed/test/d.r | 1 + bin/ed/test/d.t | 3 + bin/ed/test/e1.d | 1 + bin/ed/test/e1.err | 1 + bin/ed/test/e1.r | 1 + bin/ed/test/e1.t | 1 + bin/ed/test/e2.d | 1 + bin/ed/test/e2.err | 1 + bin/ed/test/e2.r | 1 + bin/ed/test/e2.t | 1 + bin/ed/test/e3.d | 1 + bin/ed/test/e3.err | 1 + bin/ed/test/e3.r | 1 + bin/ed/test/e3.t | 1 + bin/ed/test/e4.d | 1 + bin/ed/test/e4.r | 1 + bin/ed/test/e4.t | 1 + bin/ed/test/f1.err | 1 + bin/ed/test/f2.err | 1 + bin/ed/test/g1.d | 5 + bin/ed/test/g1.err | 1 + bin/ed/test/g1.r | 15 + bin/ed/test/g1.t | 6 + bin/ed/test/g2.d | 5 + bin/ed/test/g2.err | 1 + bin/ed/test/g2.r | 1 + bin/ed/test/g2.t | 2 + bin/ed/test/g3.err | 1 + bin/ed/test/h.err | 1 + bin/ed/test/i.d | 5 + bin/ed/test/i.r | 8 + bin/ed/test/i.t | 9 + bin/ed/test/i1.err | 3 + bin/ed/test/i2.err | 3 + bin/ed/test/i3.err | 3 + bin/ed/test/j.d | 5 + bin/ed/test/j.r | 4 + bin/ed/test/j.t | 2 + bin/ed/test/k.d | 5 + bin/ed/test/k.r | 5 + bin/ed/test/k.t | 10 + bin/ed/test/k1.err | 1 + bin/ed/test/k2.err | 1 + bin/ed/test/k3.err | 1 + bin/ed/test/k4.err | 6 + bin/ed/test/l.d | 0 bin/ed/test/l.r | 0 bin/ed/test/l.t | 0 bin/ed/test/m.d | 5 + bin/ed/test/m.err | 4 + bin/ed/test/m.r | 5 + bin/ed/test/m.t | 7 + bin/ed/test/mkscripts.sh | 71 +++ bin/ed/test/n.d | 0 bin/ed/test/n.r | 0 bin/ed/test/n.t | 0 bin/ed/test/p.d | 0 bin/ed/test/p.r | 0 bin/ed/test/p.t | 0 bin/ed/test/q.d | 0 bin/ed/test/q.r | 0 bin/ed/test/q.t | 5 + bin/ed/test/q1.err | 1 + bin/ed/test/r1.d | 5 + bin/ed/test/r1.err | 1 + bin/ed/test/r1.r | 7 + bin/ed/test/r1.t | 3 + bin/ed/test/r2.d | 5 + bin/ed/test/r2.err | 1 + bin/ed/test/r2.r | 10 + bin/ed/test/r2.t | 1 + bin/ed/test/r3.d | 1 + bin/ed/test/r3.r | 2 + bin/ed/test/r3.t | 1 + bin/ed/test/s1.d | 5 + bin/ed/test/s1.err | 1 + bin/ed/test/s1.r | 5 + bin/ed/test/s1.t | 6 + bin/ed/test/s10.err | 4 + bin/ed/test/s2.d | 5 + bin/ed/test/s2.err | 4 + bin/ed/test/s2.r | 5 + bin/ed/test/s2.t | 4 + bin/ed/test/s3.d | 0 bin/ed/test/s3.err | 1 + bin/ed/test/s3.r | 1 + bin/ed/test/s3.t | 6 + bin/ed/test/s4.err | 1 + bin/ed/test/s5.err | 1 + bin/ed/test/s6.err | 1 + bin/ed/test/s7.err | 5 + bin/ed/test/s8.err | 4 + bin/ed/test/s9.err | 4 + bin/ed/test/t.d | 5 + bin/ed/test/t.r | 16 + bin/ed/test/t1.d | 5 + bin/ed/test/t1.err | 1 + bin/ed/test/t1.r | 16 + bin/ed/test/t1.t | 3 + bin/ed/test/t2.d | 5 + bin/ed/test/t2.err | 1 + bin/ed/test/t2.r | 6 + bin/ed/test/t2.t | 1 + bin/ed/test/u.d | 5 + bin/ed/test/u.err | 1 + bin/ed/test/u.r | 9 + bin/ed/test/u.t | 31 ++ bin/ed/test/v.d | 5 + bin/ed/test/v.r | 11 + bin/ed/test/v.t | 6 + bin/ed/test/w.d | 5 + bin/ed/test/w.r | 10 + bin/ed/test/w.t | 2 + bin/ed/test/w1.err | 1 + bin/ed/test/w2.err | 1 + bin/ed/test/w3.err | 1 + bin/ed/test/x.err | 1 + bin/ed/test/z.err | 2 + 148 files changed, 2811 insertions(+) create mode 100644 bin/ed/Makefile create mode 100644 bin/ed/POSIX create mode 100644 bin/ed/README create mode 100644 bin/ed/buf.c create mode 100644 bin/ed/cbc.c create mode 100644 bin/ed/ed.1 create mode 100644 bin/ed/ed.h create mode 100644 bin/ed/re.c create mode 100644 bin/ed/test/=.err create mode 100644 bin/ed/test/Makefile create mode 100644 bin/ed/test/README create mode 100644 bin/ed/test/TODO create mode 100644 bin/ed/test/a.d create mode 100644 bin/ed/test/a.r create mode 100644 bin/ed/test/a.t create mode 100644 bin/ed/test/a1.err create mode 100644 bin/ed/test/a2.err create mode 100644 bin/ed/test/addr1.err create mode 100644 bin/ed/test/addr2.err create mode 100644 bin/ed/test/ascii.d create mode 100644 bin/ed/test/ascii.r create mode 100644 bin/ed/test/ascii.t create mode 100644 bin/ed/test/c.d create mode 100644 bin/ed/test/c.r create mode 100644 bin/ed/test/c.t create mode 100644 bin/ed/test/c1.err create mode 100644 bin/ed/test/c2.err create mode 100644 bin/ed/test/ckscripts.sh create mode 100644 bin/ed/test/d.d create mode 100644 bin/ed/test/d.err create mode 100644 bin/ed/test/d.r create mode 100644 bin/ed/test/d.t create mode 100644 bin/ed/test/e1.d create mode 100644 bin/ed/test/e1.err create mode 100644 bin/ed/test/e1.r create mode 100644 bin/ed/test/e1.t create mode 100644 bin/ed/test/e2.d create mode 100644 bin/ed/test/e2.err create mode 100644 bin/ed/test/e2.r create mode 100644 bin/ed/test/e2.t create mode 100644 bin/ed/test/e3.d create mode 100644 bin/ed/test/e3.err create mode 100644 bin/ed/test/e3.r create mode 100644 bin/ed/test/e3.t create mode 100644 bin/ed/test/e4.d create mode 100644 bin/ed/test/e4.r create mode 100644 bin/ed/test/e4.t create mode 100644 bin/ed/test/f1.err create mode 100644 bin/ed/test/f2.err create mode 100644 bin/ed/test/g1.d create mode 100644 bin/ed/test/g1.err create mode 100644 bin/ed/test/g1.r create mode 100644 bin/ed/test/g1.t create mode 100644 bin/ed/test/g2.d create mode 100644 bin/ed/test/g2.err create mode 100644 bin/ed/test/g2.r create mode 100644 bin/ed/test/g2.t create mode 100644 bin/ed/test/g3.err create mode 100644 bin/ed/test/h.err create mode 100644 bin/ed/test/i.d create mode 100644 bin/ed/test/i.r create mode 100644 bin/ed/test/i.t create mode 100644 bin/ed/test/i1.err create mode 100644 bin/ed/test/i2.err create mode 100644 bin/ed/test/i3.err create mode 100644 bin/ed/test/j.d create mode 100644 bin/ed/test/j.r create mode 100644 bin/ed/test/j.t create mode 100644 bin/ed/test/k.d create mode 100644 bin/ed/test/k.r create mode 100644 bin/ed/test/k.t create mode 100644 bin/ed/test/k1.err create mode 100644 bin/ed/test/k2.err create mode 100644 bin/ed/test/k3.err create mode 100644 bin/ed/test/k4.err create mode 100644 bin/ed/test/l.d create mode 100644 bin/ed/test/l.r create mode 100644 bin/ed/test/l.t create mode 100644 bin/ed/test/m.d create mode 100644 bin/ed/test/m.err create mode 100644 bin/ed/test/m.r create mode 100644 bin/ed/test/m.t create mode 100644 bin/ed/test/mkscripts.sh create mode 100644 bin/ed/test/n.d create mode 100644 bin/ed/test/n.r create mode 100644 bin/ed/test/n.t create mode 100644 bin/ed/test/p.d create mode 100644 bin/ed/test/p.r create mode 100644 bin/ed/test/p.t create mode 100644 bin/ed/test/q.d create mode 100644 bin/ed/test/q.r create mode 100644 bin/ed/test/q.t create mode 100644 bin/ed/test/q1.err create mode 100644 bin/ed/test/r1.d create mode 100644 bin/ed/test/r1.err create mode 100644 bin/ed/test/r1.r create mode 100644 bin/ed/test/r1.t create mode 100644 bin/ed/test/r2.d create mode 100644 bin/ed/test/r2.err create mode 100644 bin/ed/test/r2.r create mode 100644 bin/ed/test/r2.t create mode 100644 bin/ed/test/r3.d create mode 100644 bin/ed/test/r3.r create mode 100644 bin/ed/test/r3.t create mode 100644 bin/ed/test/s1.d create mode 100644 bin/ed/test/s1.err create mode 100644 bin/ed/test/s1.r create mode 100644 bin/ed/test/s1.t create mode 100644 bin/ed/test/s10.err create mode 100644 bin/ed/test/s2.d create mode 100644 bin/ed/test/s2.err create mode 100644 bin/ed/test/s2.r create mode 100644 bin/ed/test/s2.t create mode 100644 bin/ed/test/s3.d create mode 100644 bin/ed/test/s3.err create mode 100644 bin/ed/test/s3.r create mode 100644 bin/ed/test/s3.t create mode 100644 bin/ed/test/s4.err create mode 100644 bin/ed/test/s5.err create mode 100644 bin/ed/test/s6.err create mode 100644 bin/ed/test/s7.err create mode 100644 bin/ed/test/s8.err create mode 100644 bin/ed/test/s9.err create mode 100644 bin/ed/test/t.d create mode 100644 bin/ed/test/t.r create mode 100644 bin/ed/test/t1.d create mode 100644 bin/ed/test/t1.err create mode 100644 bin/ed/test/t1.r create mode 100644 bin/ed/test/t1.t create mode 100644 bin/ed/test/t2.d create mode 100644 bin/ed/test/t2.err create mode 100644 bin/ed/test/t2.r create mode 100644 bin/ed/test/t2.t create mode 100644 bin/ed/test/u.d create mode 100644 bin/ed/test/u.err create mode 100644 bin/ed/test/u.r create mode 100644 bin/ed/test/u.t create mode 100644 bin/ed/test/v.d create mode 100644 bin/ed/test/v.r create mode 100644 bin/ed/test/v.t create mode 100644 bin/ed/test/w.d create mode 100644 bin/ed/test/w.r create mode 100644 bin/ed/test/w.t create mode 100644 bin/ed/test/w1.err create mode 100644 bin/ed/test/w2.err create mode 100644 bin/ed/test/w3.err create mode 100644 bin/ed/test/x.err create mode 100644 bin/ed/test/z.err diff --git a/bin/ed/Makefile b/bin/ed/Makefile new file mode 100644 index 000000000000..a48b0d20fd85 --- /dev/null +++ b/bin/ed/Makefile @@ -0,0 +1,7 @@ +PROG= ed +CFLAGS+=-I${.CURDIR} -DVI_BANG -DDES -DGNU_REGEX -DHAVE_STRING_H=1 +SRCS= ed.c re.c buf.c cbc.c regex.c +LINKS= ${BINDIR}/ed ${BINDIR}/red +MLINKS= ed.1 red.1 + +.include diff --git a/bin/ed/POSIX b/bin/ed/POSIX new file mode 100644 index 000000000000..dd506fb5a606 --- /dev/null +++ b/bin/ed/POSIX @@ -0,0 +1,50 @@ +This version of ed is not strictly POSIX compliant, as described in the +POSIX 1003.2 Draft 11.2 document. BSD commands have been implemented +wherever they do not conflict with the POSIX standard. For backwards +compatibility, the POSIX rule that says a range of addresses cannot be +used where only a single address is expected has been relaxed. + +The BSD commands included are: + 1) `s' (i.e., s[rgp]*) to repeat a previous substitution, + 2) `W' for appending text to an existing file, + 3) `wq' for exiting after a write, and + 4) `z' for scrolling through the buffer. +BSD line addressing syntax (i.e., `^' and `%'). is also recognized. + +The POSIX interactive global commands `G' and `V' are extended to support +multiple commands, including `a', `i' and `c'. The command format is the +same as for the global commands `g' and `v', i.e., one command per line +with each line, except for the last, ending in a backslash (\). + +If crypt is available, files can be read and written using DES encryption. +The `x' command prompts the user to enter a key used for encrypting/ +decrypting subsequent reads and writes. If only a newline is entered as +the key, then encryption is disabled. Otherwise, a key is read in the +same manner as a password entry. The key remains in effect until +encryption is disabled. For more information on the encryption algorithm, +see the bdes(1) man page. Encryption/decryption should be fully compatible +with SunOS DES. + +An extension to the POSIX file commands `E', `e', `r', `W' and `w' is that + arguments are processed for backslash escapes, i.e., any character +preceded by a backslash is interpreted literally. If the first unescaped +character of a argument is a bang (!), then the rest of the line +is interpreted as a shell command, and no escape processing is performed +by ed. + +The vi editor's bang command syntax is supported, i.e., +(addr1,addr2) ! replaces the addressed lines with the output of + the command . +[rwe] !! reads/writes/edits the previous !. + +If ed is invoked with a name argument prefixed by a bang, then the +remainder of the argument is interpreted as a shell command. To invoke +ed on a file whose name starts with bang, prefix the name with a backslash. + +ed runs in restricted mode if invoked as red. This limits editing of +files in the local directory only and prohibits ! commands. + +Though ed is not a binary editor, it can be used (if painfully) to edit +binary files. To assist in binary editing, when a file containing at +least one ASCII NUL character is written, a newline is not appended +if it did not already contain one upon reading. diff --git a/bin/ed/README b/bin/ed/README new file mode 100644 index 000000000000..9dada652ad02 --- /dev/null +++ b/bin/ed/README @@ -0,0 +1,22 @@ +ed is an 8-bit-clean, POSIX-compliant line editor. It should work with +any regular expression package that conforms to the POSIX interface +standard, such as GNU regex(3). + +If reliable signals are supported (e.g., POSIX sigaction(2)), it should +compile with little trouble. Otherwise, the macros spl1() and spl0() +should be redefined to disable interrupts. + +The following compiler directives are recognized: +GNU_REGEX - use with GNU regex(3) +DES - use to add encryption support (requires crypt(3)) +NO_REALLOC_NULL - use if realloc(3) does not accept a NULL pointer +BACKWARDS - use for backwards compatibility + +The file `POSIX' describes extensions to and deviations from the POSIX +standard. + +The ./test directory contains regression tests for ed. The README +file in that directory explains how to run these. + +For a description of the ed algorithm, see Kernighan and Plauger's book +"Software Tools in Pascal," Addison-Wesley, 1981. diff --git a/bin/ed/buf.c b/bin/ed/buf.c new file mode 100644 index 000000000000..57c336121ca1 --- /dev/null +++ b/bin/ed/buf.c @@ -0,0 +1,246 @@ +/* buf.c: This file contains the scratch-file buffer rountines for the + ed line editor. */ +/*- + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rodney Ruddock of the University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)buf.c 5.5 (Berkeley) 3/28/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "ed.h" + +extern char errmsg[]; +extern line_t line0; + +FILE *sfp; /* scratch file pointer */ +char *sfbuf = NULL; /* scratch file input buffer */ +int sfbufsz = 0; /* scratch file input buffer size */ +off_t sfseek; /* scratch file position */ +int seek_write; /* seek before writing */ + +/* gettxt: get a line of text from the scratch file; return pointer + to the text */ +char * +gettxt(lp) + line_t *lp; +{ + int len, ct; + + if (lp == &line0) + return NULL; + seek_write = 1; /* force seek on write */ + /* out of position */ + if (sfseek != lp->seek) { + sfseek = lp->seek; + if (fseek(sfp, sfseek, SEEK_SET) < 0) { + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "cannot seek temp file"); + return NULL; + } + } + len = lp->len & ~ACTV; + CKBUF(sfbuf, sfbufsz, len + 1, NULL); + if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "cannot read temp file"); + return NULL; + } + sfseek += len; /* update file position */ + sfbuf[len] = '\0'; + return sfbuf; +} + + +extern long curln; +extern long lastln; + +/* puttxt: write a line of text to the scratch file and add a line node + to the editor buffer; return a pointer to the end of the text */ +char * +puttxt(cs) + char *cs; +{ + line_t *lp; + int len, ct; + char *s; + + if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "out of memory"); + return NULL; + } + /* assert: cs is '\n' terminated */ + for (s = cs; *s != '\n'; s++) + ; + if (s - cs >= LINECHARS) { + sprintf(errmsg, "line too long"); + return NULL; + } + len = (s - cs) & ~ACTV; + /* out of position */ + if (seek_write) { + if (fseek(sfp, 0L, SEEK_END) < 0) { + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "cannot seek temp file"); + return NULL; + } + sfseek = ftell(sfp); + seek_write = 0; + } + /* assert: spl1() */ + if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { + sfseek = -1; + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "cannot write temp file"); + return NULL; + } + lp->len = len; + lp->seek = sfseek; + lpqueue(lp); + sfseek += len; /* update file position */ + return ++s; +} + + +/* lpqueue: add a line node in the editor buffer after the current line */ +void +lpqueue(lp) + line_t *lp; +{ + line_t *cp; + + cp = getlp(curln); /* this getlp last! */ + insqueue(lp, cp); + lastln++; + curln++; +} + + +/* getaddr: return line number of pointer */ +long +getaddr(lp) + line_t *lp; +{ + line_t *cp = &line0; + long n = 0; + + while (cp != lp && (cp = cp->next) != &line0) + n++; + return (cp != &line0) ? n : 0; +} + + +/* getlp: return pointer to a line node in the editor buffer */ +line_t * +getlp(n) + long n; +{ + static line_t *lp = &line0; + static long on = 0; + + spl1(); + if (n > on) + if (n <= (on + lastln) >> 1) + for (; on < n; on++) + lp = lp->next; + else { + lp = line0.prev; + for (on = lastln; on > n; on--) + lp = lp->prev; + } + else + if (n >= on >> 1) + for (; on > n; on--) + lp = lp->prev; + else { + lp = &line0; + for (on = 0; on < n; on++) + lp = lp->next; + } + spl0(); + return lp; +} + + +char sfn[15] = ""; /* scratch file name */ + +/* sbopen: open scratch file */ +sbopen() +{ + strcpy(sfn, "/tmp/ed.XXXXXX"); + if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL) { + fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); + sprintf(errmsg, "cannot open temp file"); + return ERR; + } + return 0; +} + + +/* sbclose: close scratch file */ +sbclose() +{ + if (sfp) { + if (fclose(sfp) < 0) { + fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); + sprintf(errmsg, "cannot close temp file"); + return ERR; + } + sfp = NULL; + unlink(sfn); + } + sfseek = seek_write = 0; + return 0; +} + + +/* quit: remove scratch file and exit */ +void +quit(n) + int n; +{ + if (sfp) { + fclose(sfp); + unlink(sfn); + } + exit(n); +} diff --git a/bin/ed/cbc.c b/bin/ed/cbc.c new file mode 100644 index 000000000000..95ce63cd2967 --- /dev/null +++ b/bin/ed/cbc.c @@ -0,0 +1,435 @@ +/* cbc.c: This file contains the encryption routines for the ed line editor */ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Matt Bishop of Dartmouth College. + * + * The United States Government has rights in this work pursuant + * to contract no. NAG 2-680 between the National Aeronautics and + * Space Administration and Dartmouth College. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cbc.c 5.5 (Berkeley) 6/27/91"; +#endif /* not lint */ + +/* Author: Matt Bishop + * Department of Mathematics and Computer Science + * Dartmouth College + * Hanover, NH 03755 + * Email: Matt.Bishop@dartmouth.edu + * ...!decvax!dartvax!Matt.Bishop + * + * See Technical Report PCS-TR91-158, Department of Mathematics and Computer + * Science, Dartmouth College, for a detailed description of the implemen- + * tation and differences between it and Sun's. The DES is described in + * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page + * or the technical report for a complete reference). + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ed.h" + +/* + * Define a divisor for rand() that yields a uniform distribution in the + * range 0-255. + */ +#define RAND_DIV (((unsigned) RAND_MAX + 1) >> 8) + +/* + * BSD and System V systems offer special library calls that do + * block moves and fills, so if possible we take advantage of them + */ +#define MEMCPY(dest,src,len) memcpy((dest),(src),(len)) +#define MEMZERO(dest,len) memset((dest), 0, (len)) + +/* Hide the calls to the primitive encryption routines. */ +#define DES_KEY(buf) \ + if (des_setkey(buf)) \ + err("des_setkey"); +#define DES_XFORM(buf) \ + if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \ + err("des_cipher"); + +/* + * read/write - no error checking + */ +#define READ(buf, n, fp) fread(buf, sizeof(char), n, fp) +#define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp) + +/* + * some things to make references easier + */ +typedef char Desbuf[8]; +#define CHAR(x,i) (x[i]) +#define UCHAR(x,i) (x[i]) +#define BUFFER(x) (x) +#define UBUFFER(x) (x) + +/* + * global variables and related macros + */ + +enum { /* encrypt, decrypt, authenticate */ + MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE +} mode = MODE_ENCRYPT; + +Desbuf ivec; /* initialization vector */ +Desbuf pvec; /* padding vector */ +char bits[] = { /* used to extract bits from a char */ + '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' +}; +int pflag; /* 1 to preserve parity bits */ + +char des_buf[8]; /* shared buffer for desgetc/desputc */ +int des_ct = 0; /* count for desgetc/desputc */ +int des_n = 0; /* index for desputc/desgetc */ + + +/* desinit: initialize DES */ +void +desinit() +{ +#ifdef DES + int i; + + des_ct = des_n = 0; + + /* initialize the initialization vctor */ + MEMZERO(ivec, 8); + + /* intialize the padding vector */ + srand((unsigned) time((time_t *) 0)); + for (i = 0; i < 8; i++) + CHAR(pvec, i) = (char) (rand()/RAND_DIV); +#endif +} + + +/* desgetc: return next char in an encrypted file */ +desgetc(fp) + FILE *fp; +{ +#ifdef DES + if (des_n >= des_ct) { + des_n = 0; + des_ct = cbcdec(des_buf, fp); + } + return (des_ct > 0) ? des_buf[des_n++] : EOF; +#endif +} + + +/* desputc: write a char to an encrypted file; return char written */ +desputc(c, fp) + int c; + FILE *fp; +{ +#ifdef DES + if (des_n == sizeof des_buf) { + des_ct = cbcenc(des_buf, des_n, fp); + des_n = 0; + } + return (des_ct >= 0) ? (des_buf[des_n++] = c) : EOF; +#endif +} + + +/* desflush: flush an encrypted file's output; return status */ +desflush(fp) + FILE *fp; +{ +#ifdef DES + if (des_n == sizeof des_buf) { + des_ct = cbcenc(des_buf, des_n, fp); + des_n = 0; + } + return (des_ct >= 0 && cbcenc(des_buf, des_n, fp) >= 0) ? 0 : EOF; +#endif +} + +#ifdef DES +/* + * get keyword from tty or stdin + */ +getkey() +{ + register char *p; /* used to obtain the key */ + Desbuf msgbuf; /* I/O buffer */ + + /* + * get the key + */ + if (*(p = getpass("Enter key: "))) { + + /* + * copy it, nul-padded, into the key area + */ + cvtkey(BUFFER(msgbuf), p); + MEMZERO(p, _PASSWORD_LEN); + makekey(msgbuf); + MEMZERO(msgbuf, sizeof msgbuf); + return 1; + } + return 0; +} + + +extern char errmsg[]; + +/* + * print a warning message and, possibly, terminate + */ +void +err(s) + char *s; /* the message */ +{ + (void)sprintf(errmsg, "%s", s ? s : strerror(errno)); +} + +/* + * map a hex character to an integer + */ +tobinhex(c, radix) + int c; /* char to be converted */ + int radix; /* base (2 to 16) */ +{ + switch(c) { + case '0': return(0x0); + case '1': return(0x1); + case '2': return(radix > 2 ? 0x2 : -1); + case '3': return(radix > 3 ? 0x3 : -1); + case '4': return(radix > 4 ? 0x4 : -1); + case '5': return(radix > 5 ? 0x5 : -1); + case '6': return(radix > 6 ? 0x6 : -1); + case '7': return(radix > 7 ? 0x7 : -1); + case '8': return(radix > 8 ? 0x8 : -1); + case '9': return(radix > 9 ? 0x9 : -1); + case 'A': case 'a': return(radix > 10 ? 0xa : -1); + case 'B': case 'b': return(radix > 11 ? 0xb : -1); + case 'C': case 'c': return(radix > 12 ? 0xc : -1); + case 'D': case 'd': return(radix > 13 ? 0xd : -1); + case 'E': case 'e': return(radix > 14 ? 0xe : -1); + case 'F': case 'f': return(radix > 15 ? 0xf : -1); + } + /* + * invalid character + */ + return(-1); +} + +/* + * convert the key to a bit pattern + */ +void +cvtkey(obuf, ibuf) + char *obuf; /* bit pattern */ + char *ibuf; /* the key itself */ +{ + register int i, j; /* counter in a for loop */ + int nbuf[64]; /* used for hex/key translation */ + + /* + * leading '0x' or '0X' == hex key + */ + if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) { + ibuf = &ibuf[2]; + /* + * now translate it, bombing on any illegal hex digit + */ + for (i = 0; ibuf[i] && i < 16; i++) + if ((nbuf[i] = tobinhex((int) ibuf[i], 16)) == -1) + err("bad hex digit in key"); + while (i < 16) + nbuf[i++] = 0; + for (i = 0; i < 8; i++) + obuf[i] = + ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf); + /* preserve parity bits */ + pflag = 1; + return; + } + /* + * leading '0b' or '0B' == binary key + */ + if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) { + ibuf = &ibuf[2]; + /* + * now translate it, bombing on any illegal binary digit + */ + for (i = 0; ibuf[i] && i < 16; i++) + if ((nbuf[i] = tobinhex((int) ibuf[i], 2)) == -1) + err("bad binary digit in key"); + while (i < 64) + nbuf[i++] = 0; + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + obuf[i] = (obuf[i]<<1)|nbuf[8*i+j]; + /* preserve parity bits */ + pflag = 1; + return; + } + /* + * no special leader -- ASCII + */ + (void)strncpy(obuf, ibuf, 8); +} + +/***************** + * DES FUNCTIONS * + *****************/ +/* + * This sets the DES key and (if you're using the deszip version) + * the direction of the transformation. This uses the Sun + * to map the 64-bit key onto the 56 bits that the key schedule + * generation routines use: the old way, which just uses the user- + * supplied 64 bits as is, and the new way, which resets the parity + * bit to be the same as the low-order bit in each character. The + * new way generates a greater variety of key schedules, since many + * systems set the parity (high) bit of each character to 0, and the + * DES ignores the low order bit of each character. + */ +void +makekey(buf) + Desbuf buf; /* key block */ +{ + register int i, j; /* counter in a for loop */ + register int par; /* parity counter */ + + /* + * if the parity is not preserved, flip it + */ + if (!pflag) { + for (i = 0; i < 8; i++) { + par = 0; + for (j = 1; j < 8; j++) + if ((bits[j]&UCHAR(buf, i)) != 0) + par++; + if ((par&01) == 01) + UCHAR(buf, i) = UCHAR(buf, i)&0177; + else + UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200; + } + } + + DES_KEY(UBUFFER(buf)); +} + + +/* + * This encrypts using the Cipher Block Chaining mode of DES + */ +cbcenc(msgbuf, n, fp) + char *msgbuf; + int n; + FILE *fp; +{ + int inverse = 0; /* 0 to encrypt, 1 to decrypt */ + + /* + * do the transformation + */ + if (n == 8) { + for (n = 0; n < 8; n++) + CHAR(msgbuf, n) ^= CHAR(ivec, n); + DES_XFORM(UBUFFER(msgbuf)); + MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8); + return WRITE(BUFFER(msgbuf), 8, fp); + } + /* + * at EOF or last block -- in either case, the last byte contains + * the character representation of the number of bytes in it + */ +/* + MEMZERO(msgbuf + n, 8 - n); +*/ + /* + * Pad the last block randomly + */ + (void)MEMCPY(BUFFER(msgbuf + n), BUFFER(pvec), 8 - n); + CHAR(msgbuf, 7) = n; + for (n = 0; n < 8; n++) + CHAR(msgbuf, n) ^= CHAR(ivec, n); + DES_XFORM(UBUFFER(msgbuf)); + return WRITE(BUFFER(msgbuf), 8, fp); +} + +/* + * This decrypts using the Cipher Block Chaining mode of DES + */ +cbcdec(msgbuf, fp) + char *msgbuf; /* I/O buffer */ + FILE *fp; /* input file descriptor */ +{ + Desbuf ibuf; /* temp buffer for initialization vector */ + register int n; /* number of bytes actually read */ + register int c; /* used to test for EOF */ + int inverse = 1; /* 0 to encrypt, 1 to decrypt */ + + if ((n = READ(BUFFER(msgbuf), 8, fp)) == 8) { + /* + * do the transformation + */ + MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8); + DES_XFORM(UBUFFER(msgbuf)); + for (c = 0; c < 8; c++) + UCHAR(msgbuf, c) ^= UCHAR(ivec, c); + MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8); + /* + * if the last one, handle it specially + */ + if ((c = fgetc(fp)) == EOF) { + n = CHAR(msgbuf, 7); + if (n < 0 || n > 7) { + err("decryption failed (block corrupted)"); + return EOF; + } + } else + (void)ungetc(c, fp); + return n; + } + if (n > 0) + err("decryption failed (incomplete block)"); + else if (n < 0) + err("cannot read file"); + return EOF; +} +#endif /* DES */ diff --git a/bin/ed/ed.1 b/bin/ed/ed.1 new file mode 100644 index 000000000000..ff6a8499ffc4 --- /dev/null +++ b/bin/ed/ed.1 @@ -0,0 +1,980 @@ +.TH ED 1 "21 May 1993" +.SH NAME +ed, red \- text editor +.SH SYNOPSIS +ed [-] [-sx] [-p \fIstring\fR] [\fIfile\fR] +.LP +red [-] [-sx] [-p \fIstring\fR] [\fIfile\fR] +.SH DESCRIPTION +.B ed +is a line-oriented text editor. +It is used to create, display, modify and otherwise manipulate text +files. +.B red +is a restricted +.BR ed : +it can only edit files in the current +directory and cannot execute shell commands. + +If invoked with a +.I file +argument, then a copy of +.I file +is read into the editor's buffer. +Changes are made to this copy and not directly to +.I file +itself. +Upon quitting +.BR ed , +any changes not explicitly saved with a +.I `w' +command are lost. + +Editing is done in two distinct modes: +.I command +and +.IR input . +When first invoked, +.B ed +is in command mode. +In this mode commands are read from the standard input and +executed to manipulate the contents of the editor buffer. +A typical command might look like: +.sp +.RS +,s/\fIold\fR/\fInew\fR/g +.RE +.sp +which replaces all occurences of the string +.I old +with +.IR new . + +When an input command, such as +.I `a' +(append), +.I `i' +(insert) or +.I `c' +(change), is given, +.B ed +enters input mode. This is the primary means +of adding text to a file. +In this mode, no commands are available; +instead, the standard input is written +directly to the editor buffer. Lines consist of text up to and +including a +.IR newline +character. +Input mode is terminated by +entering a single period (\fI.\fR) on a line. + +All +.B ed +commands operate on whole lines or ranges of lines; e.g., +the +.I `d' +command deletes lines; the +.I `m' +command moves lines, and so on. +It is possible to modify only a portion of a line by means of replacement, +as in the example above. However even here, the +.I `s' +command is applied to whole lines at a time. + +In general, +.B ed +commands consist of zero or more line addresses, followed by a single +character command and possibly additional parameters; i.e., +commands have the structure: +.sp +.RS +.I [address [,address]]command[parameters] +.RE +.sp +The address(es) indicate the line(s) to be affected by the command. +If fewer addresses are given than the command accepts, then default +addresses are supplied. + +.SS OPTIONS +.TP 8 +-s +Suppresses diagnostics. This should be used if +.BR ed 's +standard input is from a script. + +.TP 8 +-x +Prompts for an encryption key to be used in subsequent reads and writes +(see the +.I `x' +command). + +.TP 8 +.RI \-p \ string +Specifies a command prompt. This may be toggled on and off with the +.I `P' +command. + +.TP 8 +.I file +Specifies the name of a file to read. If +.I file +is prefixed with a +bang (!), then it is interpreted as a shell command. In this case, +what is read is +the standard output of +.I file +executed via +.IR sh (1). +To read a file whose name begins with a bang, prefix the +name with a backslash (\\). +The default filename is set to +.I file +only if it is not prefixed with a bang. + +.SS LINE ADDRESSING +An address represents the number of line in the buffer. +.B ed +maintains a +.I current address +which is +typically supplied to commands as the default address when none is specified. +When a file is first read, the current address is set to the last line +of the file. In general, the current address is set to the last line +affected by a command. + +A line address is +constructed from one of the bases in the list below, optionally followed +by a numeric offset. The offset may include any combination +of digits, operators (i.e., +.IR + , +.I - +and +.IR ^ ) +and whitespace. +Addresses are read from left to right, and their values are computed +relative to the current address. + +One exception to the rule that addresses represent line numbers is the +address +.I 0 +(zero). +This means "before the first line," +and is legal wherever it makes sense. + +An address range is two addresses separated either by a comma or +semi-colon. The value of the first address in a range cannot exceed the +value of the the second. If an +.IR n- tuple +of addresses is given where +.I n > 2, +then the corresponding range is determined by the last two addresses +in the +.IR n- tuple. +If only one address is expected, then the last +address is used. + +Each address in a comma-delimited range is interpreted relative to the +current address. In a semi-colon-delimited range, the first address is +used to set the current address, and the second address is interpreted +relative to the first. + +The following address symbols are recognized. + +.TP 8 +\fR.\fR +The current line (address) in the buffer. + +.TP 8 +$ +The last line in the buffer. + +.TP 8 +n +The +.IR n th, +line in the buffer +where +.I n +is a number in the range +.I [0,$]. + +.TP 8 +- or ^ +The previous line. +This is equivalent to +.I -1 +and may be repeated with cumulative effect. + +.TP 8 +-\fIn\fR or ^\fIn\fR +The +.IR n th +previous line, where +.I n +is a non-negative number. + +.TP 8 ++ +The +next line. +This is equivalent to +.I +1 +and may be repeated with cumulative effect. + +.TP 8 ++\fIn\fR or whitespace\fIn\fR +The +.IR n th +next line, where +.I n +is a non-negative number. +.I whitespace +followed by a number +.I n +is interpreted as +.IR +n . + +.TP 8 +, \fRor\fB % +The first through last lines in the buffer. This is equivalent to +the address range +.I 1,$. + +.TP 8 +; +The +current through last lines in the buffer. This is equivalent to +the address range +.I .,$. + +.TP 8 +.RI / re/ +The +next line containing the regular expression +.IR re . +The search wraps to the beginning of the buffer and continues down to the +current line, if necessary. +// repeats the last search. + +.TP 8 +.RI ? re? +The +previous line containing the regular expression +.IR re . +The search wraps to the end of the buffer and continues up to the +current line, if necessary. +?? repeats the last search. + +.TP 8 +.RI \' lc +The +line previously marked by a +.I `k' +(mark) command, where +.I lc +is a lower case letter. + +.SS REGULAR EXPRESSIONS +Regular expressions are patterns used in selecting text. +For example, the +.B ed +command +.sp +.RS +g/\fIstring\fR/ +.RE +.sp +prints all lines containing +.IR string . +Regular expressions are also +used by the +.I `s' +command for selecting old text to be replaced with new. + +In addition to a specifying string literals, regular expressions can +represent +classes of strings. Strings thus represented are said to be matched +by the corresponding regular expression. +If it is possible for a regular expression +to match several strings in a line, then the left-most longest match is +the one selected. + +The following symbols are used in constructing regular expressions: + +.TP 8 +c +Any character +.I c +not listed below, including `{', '}', `(', `)', `<' and `>', +matches itself. + +.TP 8 +\fR\\\fIc\fR +Any backslash-escaped character +.IR c , +except for `{', '}', `(', `)', `<' and `>', +matches itself. + +.TP 8 +\fR.\fR +Matches any single character. + +.TP 8 +.I [char-class] +Matches any single character in +.IR char-class . +To include a `]' +in +.IR char-class , +it must be the first character. +A range of characters may be specified by separating the end characters +of the range with a `-', e.g., `a-z' specifies the lower case characters. +The following literal expressions can also be used in +.I char-class +to specify sets of characters: +.sp +\ \ [:alnum:]\ \ [:cntrl:]\ \ [:lower:]\ \ [:space:] +.PD 0 +\ \ [:alpha:]\ \ [:digit:]\ \ [:print:]\ \ [:upper:] +.PD 0 +\ \ [:blank:]\ \ [:graph:]\ \ [:punct:]\ \ [:xdigit:] +.sp +If `-' appears as the first or last +character of +.IR char-class , +then it matches itself. +All other characters in +.I char-class +match themselves. +.sp +Patterns in +.I char-class +of the form: +.sp +\ \ [.\fIcol-elm\fR.] or, +.PD 0 +\ \ [=\fIcol-elm\fR=] +.sp +where +.I col-elm +is a +.I collating element +are interpreted according to +.IR locale (5) +(not currently supported). +See +.IR regex (3) +for an explanation of these constructs. + +.TP 8 +[^\fIchar-class\fR] +Matches any single character, other than newline, not in +.IR char-class . +.IR char-class +is defined +as above. + +.TP 8 +^ +If `^' is the first character of a regular expression, then it +anchors the regular expression to the beginning of a line. +Otherwise, it matches itself. + +.TP 8 +$ +If `$' is the last character of a regular expression, it +anchors the regular expression to the end of a line. +Otherwise, it matches itself. + +.TP 8 +\fR\\<\fR +Anchors the single character regular expression or subexpression +immediately following it to the beginning of a word. +(This may not be available) + +.TP 8 +\fR\\>\fR +Anchors the single character regular expression or subexpression +immediately following it to the end of a word. +(This may not be available) + +.TP 8 +\fR\\(\fIre\fR\\)\fR +Defines a subexpression +.IR re . +Subexpressions may be nested. +A subsequent backreference of the form \fI`\\n'\fR, where +.I n +is a number in the range [1,9], expands to the text matched by the +.IR n th +subexpression. +For example, the regular expression `\\(.*\\)\\1' matches any string +consisting of identical adjacent substrings. +Subexpressions are ordered relative to +their left delimiter. + +.TP 8 +* +Matches the single character regular expression or subexpression +immediately preceding it zero or more times. If '*' is the first +character of a regular expression or subexpression, then it matches +itself. The `*' operator sometimes yields unexpected results. +For example, the regular expression `b*' matches the beginning of +the string `abbb' (as opposed to the substring `bbb'), since a null match +is the only left-most match. + +.TP 8 +\fR\\{\fIn,m\fR\\}\fR or \fR\\{\fIn,\fR\\}\fR or \fR\\{\fIn\fR\\}\fR +Matches the single character regular expression or subexpression +immediately preceding it at least +.I n +and at most +.I m +times. +If +.I m +is omitted, then it matches at least +.I n +times. +If the comma is also omitted, then it matches exactly +.I n +times. + +.LP +Additional regular expression operators may be defined depending on the +particular +.IR regex (3) +implementation. + +.SS COMMANDS +All +.B ed +commands are single characters, though some require additonal parameters. +If a command's parameters extend over several lines, then +each line except for the last +must be terminated with a backslash (\\). + +In general, at most one command is allowed per line. +However, most commands accept a print suffix, which is any of +.I `p' +(print), +.I `l' +(list) , +or +.I `n' +(enumerate), +to print the last line affected by the command. + +An interrupt (typically ^C) has the effect of aborting the current command +and returning the editor to command mode. + +.B ed +recognizes the following commands. The commands are shown together with +the default address or address range supplied if none is +specified (in parenthesis). + +.TP 8 +(.)a +Appends text to the buffer after the addressed line. +Text is entered in input mode. +The current address is set to last line entered. + +.TP 8 +(.,.)c +Changes lines in the buffer. The addressed lines are deleted +from the buffer, and text is appended in their place. +Text is entered in input mode. +The current address is set to last line entered. + +.TP 8 +(.,.)d +Deletes the addressed lines from the buffer. +If there is a line after the deleted range, then the current address is set +to this line. Otherwise the current address is set to the line +before the deleted range. + +.TP 8 +.RI e \ file +Edits +.IR file , +and sets the default filename. +If +.I file +is not specified, then the default filename is used. +Any lines in the buffer are deleted before +the new file is read. +The current address is set to the last line read. + +.TP 8 +.RI e \ !command +Edits the standard output of +.IR `!command' , +executed as described below. +The default filename is unchanged. +Any lines in the buffer are deleted before the output of +.I command +is read. +The current address is set to the last line read. + +.TP 8 +.RI E \ file +Edits +.I file +unconditionally. +This is similar to the +.I e +command, +except that unwritten changes are discarded without warning. +The current address is set to the last line read. + +.TP 8 +.RI f \ file +Sets the default filename to +.IR file . +If +.I file +is not specified, then the default unescaped filename is printed. + +.TP 8 +.RI (1,$)g /re/command-list +Applies +.I command-list +to each of the addressed lines matching a regular expression +.IR re . +The current address is set to the +line currently matched before +.I command-list +is executed. +At the end of the +.I `g' +command, the current address is set to the last line affected by +.IR command-list . + +Each command in +.I command-list +must be on a separate line, +and every line except for the last must be terminated by a backslash +(\\). +Any commands are allowed, except for +.IR `g' , +.IR `G' , +.IR `v' , +and +.IR `V' . +A newline alone in +.I command-list +is equivalent to a +.I `p' +command. + +.TP 8 +.RI (1,$)G /re/ +Interactively edits the addressed lines matching a regular expression +.IR re. +For each matching line, +the line is printed, +the current address is set, +and the user is prompted to enter a +.IR command-list . +At the end of the +.I `G' +command, the current address +is set to the last line affected by (the last) +.IR command-list . + +The format of +.I command-list +is the same as that of the +.I `g' +command. A newline alone acts as a null command list. +A single `&' repeats the last non-null command list. + +.TP 8 +H +Toggles the printing of error explanations. +By default, explanations are not printed. +It is recommended that ed scripts begin with this command to +aid in debugging. + +.TP 8 +h +Prints an explanation of the last error. + +.TP 8 +(.)i +Inserts text in the buffer before the current line. +Text is entered in input mode. +The current address is set to the last line entered. + +.TP 8 +(.,.+1)j +Joins the addressed lines. The addressed lines are +deleted from the buffer and replaced by a single +line containing their joined text. +The current address is set to the resultant line. + +.TP 8 +.RI (.)k lc +Marks a line with a lower case letter +.IR lc . +The line can then be addressed as +.I 'lc +(i.e., a single quote followed by +.I lc +) in subsequent commands. The mark is not cleared until the line is +deleted or otherwise modified. + +.TP 8 +(.,.)l +Prints the addressed lines unambiguously. +The current address is set to the last line +printed. + +.TP 8 +(.,.)m(.) +Moves lines in the buffer. The addressed lines are moved to after the +right-hand destination address, which may be the address +.IR 0 +(zero). +The current address is set to the +last line moved. + +.TP 8 +(.,.)n +Prints the addressed lines along with +their line numbers. The current address is set to the last line +printed. + +.TP 8 +(.,.)p +Prints the addressed lines. The current address is set to the last line +printed. + +.TP 8 +P +Toggles the command prompt on and off. +Unless a prompt was specified by with command-line option +\fI-p string\fR, the command prompt is by default turned off. + +.TP 8 +q +Quits ed. + +.TP 8 +Q +Quits ed unconditionally. +This is similar to the +.I q +command, +except that unwritten changes are discarded without warning. + +.TP 8 +.RI ($)r \ file +Reads +.I file +to after the addressed line. If +.I file +is not specified, then the default +filename is used. If there was no default filename prior to the command, +then the default filename is set to +.IR file . +Otherwise, the default filename is unchanged. +The current address is set to the last line read. + +.TP 8 +.RI ($)r \ !command +Reads +to after the addressed line +the standard output of +.IR `!command' , +executed as described below. +The default filename is unchanged. +The current address is set to the last line read. + +.HP +.RI (.,.)s /re/replacement/ +.PD 0 +.HP +.RI (.,.)s /re/replacement/\fRg\fR +.HP +.RI (.,.)s /re/replacement/n +.br +Replaces text in the addressed lines +matching a regular expression +.I re +with +.IR replacement . +By default, only the first match in each line is replaced. +The +.I `g' +(global) suffix causes every match to be replaced. +The +.I `n' +suffix, where +.I n +is a postive number, causes only the +.IR n th +match to be replaced. +It is an error if no substitutions are performed on any of the addressed +lines. +The current address is set the last line affected. + +.I re +and +.I replacement +may be delimited by any character other than space and newline. +If one or two of the last delimiters is omitted, then the last line +affected is printed as though the print suffix +.I `p' +were specified. + + +An unescaped `&' in +.I replacement +is replaced by the currently matched text. +The character sequence +\fI`\\m'\fR, +where +.I m +is a number in the range [1,9], is replaced by the +.IR m th +backreference expression of the matched text. +If +.I replacement +consists of a single `%', then +.I replacement +from the last substitution is used. +Newlines may be embedded in +.I replacement +if they are escaped with a backslash (\\). + +.TP 8 +(.,.)s +Repeats the last substitution. +This form of the +.I `s' +command may be suffixed with +any combination of the characters +.IR `r' , +.IR `g' , +and +.IR `p' . +The +.I `r' +suffix causes +the regular expression of the last search to be used instead of the +that of the last substitution. +The +.I `g' +suffix toggles the global suffix of the last substitution. +The +.I `p' +suffix toggles the print suffix of the last substitution +The current address is set to the last line affected. + +.TP 8 +(.,.)t(.) +Copies (i.e., transfers) the addressed lines to after the right-hand +destination address, which may be the address +.IR 0 +(zero). +The current address is set to the last line +copied. + +.TP 8 +u +Undoes the last command and restores the current address +to what it was before the command. +The global commands +.IR `g' , +.IR `G' , +.IR `v' , +and +.IR `V' . +are treated as a single command by undo. +.I `u' +is its own inverse. + +.TP 8 +.RI (1,$)v /pat/command-list +Applies +.I command-list +to each of the addressed lines not matching a regular expression +.IR re . +This is similar to the +.I `g' +command. + +.TP 8 +.RI (1,$)V /re/ +Interactively edits the addressed lines not matching a regular expression +.IR re. +This is similar to the +.I `G' +command. + +.TP 8 +.RI (1,$)w \ file +Writes the addressed lines to +.IR file . +Any previous contents of +.I file +is lost without warning. +If there is no default filename, then the default filename is set to +.IR file, +otherwise it is unchanged. If no filename is specified, then the default +filename is used. +The current address is unchanged. + +.TP 8 +.RI (1,$)wq \ file +Writes the addressed lines to +.IR file , +and then executes a +.I `q' +command. + +.TP 8 +.RI (1,$)w \ !command +Writes the addressed lines to the standard input of +.IR `!command' , +executed as described below. +The default filename and current address are unchanged. + +.TP 8 +.RI (1,$)W \ file +Appends the addressed lines to the end of +.IR file . +This is similar to the +.I `w' +command, expect that the previous contents of file is not clobbered. +The current address is unchanged. + +.TP 8 +x +Prompts for an encryption key which is used in subsequent reads and +writes. If a newline alone is entered as the key, then encryption is +turned off. Otherwise, echoing is disabled while a key is read. +Encryption/decryption is done using the bdes(1) algorithm. + +.TP 8 +.RI (.+1)z n +Scrolls +.I n +lines at a time starting at addressed line. If +.I n +is not specified, then the current window size is used. +The current address is set to the last line printed. + +.TP 8 +.RI ! command +Executes +.I command +via +.IR sh (1). +If the first character of +.I command +is `!', then it is replaced by text of the +previous +.IR `!command' . +.B ed +does not process +.I command +for backslash (\\) escapes. +However, an unescaped +.I `%' +is replaced by the default filename. +When the shell returns from execution, a `!' +is printed to the standard output. +The current line is unchanged. + +.TP 8 +.RI (.,.)! command +Replaces the addressed lines with the output of +.I `!command' +as described above. +The current address is set to the last line read. + +.TP 8 +($)= +Prints the line number of the addressed line. + +.TP 8 +(.+1)newline +Prints the addressed line, and sets the current address to +that line. + +.SH FILES +.TP 20 +/tmp/ed.* +Buffer file +.PD 0 +.TP 20 +\fR./ed.hup\fR, $HOME/ed.hup +First and second files to which +.B ed +attempts to write the buffer if the terminal hangs up. + +.SH SEE ALSO + +.IR vi (1), +.IR sed (1), +.IR regex (3), +.IR bdes (1), +.IR sh (1). + +USD:12-13 + +B. W. Kernighan and P. J. Plauger, +.I Software Tools in Pascal , +Addison-Wesley, 1981. + +.SH LIMITATIONS +.B ed +processes +.I file +arguments for backslash escapes, i.e., in a filename, +any characters preceded by a backslash (\\) are +interpreted literally. + +If a text (non-binary) file is not terminated by a newline character, +then +.B ed +appends one on reading/writing it. In the case of a binary file, +.B ed +does not append a newline on reading/writing. + +per line overhead: 4 ints + +.SH DIAGNOSTICS +When an error occurs, +.B ed +prints a `?' and either returns to command mode +or exits if its input is from a script. +An explanation of the last error can be +printed with the +.I `h' +(help) command. + +Since the +.I `g' +(global) command masks any errors from failed searches and substitutions, +it can be used to perform conditional operations in scripts; e.g., +.sp +.RS +g/\fIold\fR/s//\fInew\fR/ +.RE +.sp +replaces any occurrences of +.I old +with +.IR new . + +If diagnostics are not disabled, attempting to quit +.B ed +or edit another file before writing a modified buffer +results in an error. +If the command is entered a second time, it succeeds, +but any changes to the buffer are lost. diff --git a/bin/ed/ed.h b/bin/ed/ed.h new file mode 100644 index 000000000000..1b277fe9359d --- /dev/null +++ b/bin/ed/ed.h @@ -0,0 +1,263 @@ +/* ed.h: type and constant definitions for the ed editor. */ +/* + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Andrew Moore, Talke Studio. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ed.h 5.5 (Berkeley) 3/28/93 + */ + +#include +#include +#if defined(BSD) && BSD >= 199103 || defined(__386BSD__) +# include /* for MAXPATHLEN */ +#endif +#include +#include + +#define BITSPERBYTE 8 +#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) +#define CHARBITS BITS(char) +#define INTBITS BITS(int) +#define INTHIBIT (1 << (INTBITS - 1)) + +#define ERR (-2) +#define EMOD (-3) +#define FATAL (-4) + +#ifndef MAXPATHLEN +# define MAXPATHLEN 255 /* _POSIX_PATH_MAX */ +#endif + +#define MAXFNAME MAXPATHLEN /* max file name size */ +#define MINBUFSZ 512 /* minimum buffer size - must be > 0 */ +#define LINECHARS (INTHIBIT - 1) /* max chars per line */ +#define SE_MAX 30 /* max subexpressions in a regular expression */ + +typedef regex_t pattern_t; + +/* Line node */ +typedef struct line { + struct line *next; + struct line *prev; + off_t seek; /* address of line in scratch buffer */ + +#define ACTV INTHIBIT /* active bit: high bit of len */ + + int len; /* length of line */ +} line_t; + + +typedef struct undo { + +/* type of undo nodes */ +#define UADD 0 +#define UDEL 1 +#define UMOV 2 +#define VMOV 3 + + int type; /* command type */ + line_t *h; /* head of list */ + line_t *t; /* tail of list */ +} undo_t; + +#ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* nextln: return line after l mod k */ +#define nextln(l,k) ((l)+1 > (k) ? 0 : (l)+1) + +/* nextln: return line before l mod k */ +#define prevln(l,k) ((l)-1 < 0 ? (k) : (l)-1) + +#define skipblanks() while (isspace(*ibufp) && *ibufp != '\n') ibufp++ + +/* spl1: disable some interrupts (requires reliable signals) */ +#define spl1() mutex++ + +/* spl0: enable all interrupts; check sigflags (requires reliable signals) */ +#define spl0() \ +if (--mutex == 0) { \ + if (sigflags & (1 << SIGHUP)) dohup(SIGHUP); \ + if (sigflags & (1 << SIGINT)) dointr(SIGINT); \ +} + +#if defined(sun) || defined(NO_REALLOC_NULL) +/* CKBUF: assure at least a minimum size for buffer b */ +#define CKBUF(b,n,i,err) \ +if ((i) > (n)) { \ + int ti = (n); \ + char *ts; \ + spl1(); \ + if ((b) != NULL) { \ + if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \ + fprintf(stderr, "%s\n", strerror(errno)); \ + sprintf(errmsg, "out of memory"); \ + spl0(); \ + return err; \ + } \ + } else { \ + if ((ts = (char *) malloc(ti += max((i), MINBUFSZ))) == NULL) { \ + fprintf(stderr, "%s\n", strerror(errno)); \ + sprintf(errmsg, "out of memory"); \ + spl0(); \ + return err; \ + } \ + } \ + (n) = ti; \ + (b) = ts; \ + spl0(); \ +} +#else /* NO_REALLOC_NULL */ +/* CKBUF: assure at least a minimum size for buffer b */ +#define CKBUF(b,n,i,err) \ +if ((i) > (n)) { \ + int ti = (n); \ + char *ts; \ + spl1(); \ + if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \ + fprintf(stderr, "%s\n", strerror(errno)); \ + sprintf(errmsg, "out of memory"); \ + spl0(); \ + return err; \ + } \ + (n) = ti; \ + (b) = ts; \ + spl0(); \ +} +#endif /* NO_REALLOC_NULL */ + +/* requeue: link pred before succ */ +#define requeue(pred, succ) (pred)->next = (succ), (succ)->prev = (pred) + +/* insqueue: insert elem in circular queue after pred */ +#define insqueue(elem, pred) \ +{ \ + requeue((elem), (pred)->next); \ + requeue((pred), elem); \ +} + +/* remqueue: remove elem from circular queue */ +#define remqueue(elem) requeue((elem)->prev, (elem)->next); + +/* nultonl: overwrite ASCII NULs with newlines */ +#define nultonl(s, l) translit(s, l, '\0', '\n') + +/* nltonul: overwrite newlines with ASCII NULs */ +#define nltonul(s, l) translit(s, l, '\n', '\0') + +#ifndef strerror +# define strerror(n) sys_errlist[n] +#endif + +#ifndef __P +# ifndef __STDC__ +# define __P(proto) () +# else +# define __P(proto) proto +# endif +#endif + +/* local function declarations */ +int append __P((long, int)); +int cbcdec __P((char *, FILE *)); +int cbcenc __P((char *, int, FILE *)); +char *ckfn __P((char *)); +int ckglob __P((void)); +int ckrange __P((long, long)); +int desflush __P((FILE *)); +int desgetc __P((FILE *)); +void desinit __P((void)); +int desputc __P((int, FILE *)); +int docmd __P((int)); +void err __P((char *)); +char *ccl __P((char *)); +void cvtkey __P((char *, char *)); +long doglob __P((int)); +void dohup __P((int)); +void dointr __P((int)); +void dowinch __P((int)); +int doprint __P((long, long, int)); +long doread __P((long, char *)); +long dowrite __P((long, long, char *, char *)); +char *esctos __P((char *)); +long patscan __P((pattern_t *, int)); +long getaddr __P((line_t *)); +char *getcmdv __P((int *, int)); +char *getfn __P((void)); +int getkey __P((void)); +char *getlhs __P((int)); +int getline __P((void)); +int getlist __P((void)); +long getnum __P((int)); +long getone __P((void)); +line_t *getlp __P((long)); +int getrhs __P((int)); +int getshcmd __P((void)); +char *gettxt __P((line_t *)); +void init_buf __P((void)); +int join __P((long, long)); +int lndelete __P((long, long)); +line_t *lpdup __P((line_t *)); +void lpqueue __P((line_t *)); +void makekey __P((char *)); +char *makesub __P((int)); +char *translit __P((char *, int, int, int)); +int move __P((long)); +int oddesc __P((char *, char *)); +void onhup __P((int)); +void onintr __P((int)); +pattern_t *optpat __P((void)); +void putstr __P((char *, int, long, int)); +char *puttxt __P((char *)); +void quit __P((int)); +int regsub __P((pattern_t *, line_t *, int)); +int sbclose __P((void)); +int sbopen __P((void)); +int sgetline __P((FILE *)); +int catsub __P((char *, regmatch_t *, int)); +int subst __P((pattern_t *, int)); +int tobinhex __P((int, int)); +int transfer __P((long)); +int undo __P((void)); +undo_t *upush __P((int, long, long)); +void ureset __P((void)); + + +extern char *sys_errlist[]; +extern int mutex; +extern int sigflags; diff --git a/bin/ed/re.c b/bin/ed/re.c new file mode 100644 index 000000000000..462c816626f2 --- /dev/null +++ b/bin/ed/re.c @@ -0,0 +1,156 @@ +/* re.c: This file contains the regular expression interface routines for + the ed line editor. */ +/*- + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Andrew Moore, Talke Studio. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)re.c 5.5 (Berkeley) 3/28/93"; +#endif /* not lint */ + +#include +#include +#include + +#include "ed.h" + +extern char *lhbuf; +extern int lhbufsz; +extern char *ibufp; +extern int ibufsz; +extern int patlock; + +char errmsg[MAXFNAME + 40] = ""; + +/* optpat: return pointer to compiled pattern from command buffer */ +pattern_t * +optpat() +{ + static pattern_t *exp = NULL; + + char *exps; + char delim; + int n; + + if ((delim = *ibufp) == '\n') { + if (!exp) sprintf(errmsg, "no previous pattern"); + return exp; + } else if (delim == ' ' || *++ibufp == '\n') { + sprintf(errmsg, "invalid pattern delimiter"); + return NULL; + } else if (*ibufp == delim) { + sprintf(errmsg, "no previous pattern"); + return exp; + } else if ((exps = getlhs(delim)) == NULL) + return NULL; + /* buffer alloc'd && not reserved */ + if (exp && !patlock) + regfree(exp); + else if ((exp = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) { + fprintf(stderr, "%s\n", strerror(errno)); + sprintf(errmsg, "out of memory"); + return NULL; + } + patlock = 0; +#ifdef GNU_REGEX + /* initialize pattern buffer */ + exp->buffer = NULL; + exp->allocated = 0L; + exp->fastmap = 0; /* not used by GNU regex after 0.12 */ + exp->translate = 0; +#endif + if (n = regcomp(exp, exps, 0)) { + regerror(n, exp, errmsg, sizeof errmsg); + return NULL; + } + return exp; +} + + +extern int isbinary; + +/* getlhs: copy a pattern string from the command buffer; return pointer + to the copy */ +char * +getlhs(delim) + int delim; +{ + char *nd; + int len; + + for (nd = ibufp; *nd != delim && *nd != '\n'; nd++) + switch (*nd) { + default: + break; + case '[': + if ((nd = ccl(++nd)) == NULL) { + sprintf(errmsg, "unbalanced brackets ([])"); + return NULL; + } + break; + case '\\': + if (*++nd == '\n') { + sprintf(errmsg, "trailing backslash (\\)"); + return NULL; + } + break; + } + len = nd - ibufp; + CKBUF(lhbuf, lhbufsz, len + 1, NULL); + memcpy(lhbuf, ibufp, len); + lhbuf[len] = '\0'; + ibufp = nd; + return (isbinary) ? nultonl(lhbuf, len) : lhbuf; +} + + +/* ccl: expand a POSIX character class */ +char * +ccl(s) + char *s; +{ + int c, d; + + if (*s == '^') + s++; + if (*s == ']') + s++; + for (; *s != ']' && *s != '\n'; s++) + if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) + for (s++, c = *++s; *s != ']' || c != d; s++) + if ((c = *s) == '\n') + return NULL; + return (*s == ']') ? s : NULL; +} diff --git a/bin/ed/test/=.err b/bin/ed/test/=.err new file mode 100644 index 000000000000..6a6055955b16 --- /dev/null +++ b/bin/ed/test/=.err @@ -0,0 +1 @@ +1,$= diff --git a/bin/ed/test/Makefile b/bin/ed/test/Makefile new file mode 100644 index 000000000000..750f388fe433 --- /dev/null +++ b/bin/ed/test/Makefile @@ -0,0 +1,17 @@ +ED= ../obj/ed + +all: build test + @echo done + +build: mkscripts.sh + @echo building test scripts... + @chmod +x mkscripts.sh + @mkscripts.sh ${ED} + +test: build ckscripts.sh + @echo running test scripts... + @chmod +x ckscripts.sh + @ckscripts.sh ${ED} + +clean: + rm -f *.ed *.[oz] *~ diff --git a/bin/ed/test/README b/bin/ed/test/README new file mode 100644 index 000000000000..46d41335034c --- /dev/null +++ b/bin/ed/test/README @@ -0,0 +1,41 @@ +The files in this directory with suffixes `.t', `.d', `.r' and `.err' are +used for testing ed. To run the tests, set the ED variable in the Makefile +for the path name of the program to be tested (e.g., /bin/ed), and type +`make'. The tests do not exhaustively verify POSIX compliance nor do +they verify correct 8-bit or long line support. + +The test file suffixes have the following meanings: +.t Template - a list of ed commands from which an ed script is + constructed +.d Data - read by an ed script +.r Result - the expected output after processing data via an ed + script. +.err Error - invalid ed commands that should generate an error + +The output of the tests is written to the two files err.o and scripts.o. +At the end of the tests, these files are grep'ed for error messages, +which look like: + *** The script u.ed exited abnormally *** +or: + *** Output u.o of script u.ed is incorrect *** + +It is assumed that the ed being tested processes escapes (\) in file names. +This is so that a name starting with bang (!) can be read, via: + r \!file +Without the escape, a POSIX ed would attempt to read the output of +the shell command `file'. If the ed being tested does not support escape +processing on file names, then the script `mkscripts.sh' should be modified +accordingly. + +The POSIX requirement that an address range not be used where at most +a single address is expected has been relaxed in this version of ed. +Therefore, the following scripts which test for compliance with this +POSIX rule exit abnormally: +=-err.ed +a1-err.ed +i1-err.ed +k1-err.ed +r1-err.ed + +In addition, one of !1-err.ed or !2.ed will fail, depending on whether or +not ed was compiled with the VI_BANG directive. diff --git a/bin/ed/test/TODO b/bin/ed/test/TODO new file mode 100644 index 000000000000..7a4b74fb7419 --- /dev/null +++ b/bin/ed/test/TODO @@ -0,0 +1,15 @@ +Some missing tests: +0) g/./s^@^@ - okay: NULs in commands +1) g/./s/^@/ - okay: NULs in patterns +2) a + hello^V^Jworld + . - okay: embedded newlines in insert mode +3) ed "" - error: invalid filename +4) red .. - error: restricted +5) red / - error: restricted +5) red !xx - error: restricted +6) ed -x - verify: 8-bit clean +7) ed - verify: long-line support +8) ed - verify: interactive/help mode +9) G/pat/ - verify: global interactive command +10) V/pat/ - verify: global interactive command diff --git a/bin/ed/test/a.d b/bin/ed/test/a.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/a.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/a.r b/bin/ed/test/a.r new file mode 100644 index 000000000000..26257bd3b3c2 --- /dev/null +++ b/bin/ed/test/a.r @@ -0,0 +1,8 @@ +hello world +line 1 +hello world! +line 2 +line 3 +line 4 +line5 +hello world!! diff --git a/bin/ed/test/a.t b/bin/ed/test/a.t new file mode 100644 index 000000000000..ac98c40d085f --- /dev/null +++ b/bin/ed/test/a.t @@ -0,0 +1,9 @@ +0a +hello world +. +2a +hello world! +. +$a +hello world!! +. diff --git a/bin/ed/test/a1.err b/bin/ed/test/a1.err new file mode 100644 index 000000000000..e80815ff50d9 --- /dev/null +++ b/bin/ed/test/a1.err @@ -0,0 +1,3 @@ +1,$a +hello world +. diff --git a/bin/ed/test/a2.err b/bin/ed/test/a2.err new file mode 100644 index 000000000000..ec4b00b40c4c --- /dev/null +++ b/bin/ed/test/a2.err @@ -0,0 +1,3 @@ +aa +hello world +. diff --git a/bin/ed/test/addr1.err b/bin/ed/test/addr1.err new file mode 100644 index 000000000000..29d6383b52c1 --- /dev/null +++ b/bin/ed/test/addr1.err @@ -0,0 +1 @@ +100 diff --git a/bin/ed/test/addr2.err b/bin/ed/test/addr2.err new file mode 100644 index 000000000000..e96acb9254be --- /dev/null +++ b/bin/ed/test/addr2.err @@ -0,0 +1 @@ +-100 diff --git a/bin/ed/test/ascii.d b/bin/ed/test/ascii.d new file mode 100644 index 0000000000000000000000000000000000000000..c86626638e0bc8cf47ca49bb1525b40e9737ee64 GIT binary patch literal 256 zcmV+b0ssC00RjUA1qKHQ2?`4g4Gs?w5fT#=6&4p585$cL9UdPbAtECrB_<~*DJm;0 zEiNxGF)}kWH8wXmIXXK$Jw87`K|(`BMMg(RNlHshO-@fxQBqS>RaRG6Sz23MU0z>c zVPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3t+%eSUv{fr5jCg@%WSiHeJijgF6yk&=^? zm6n&7nVOrNot~edp`xRtrKYE-sj922t*)=Iv9hzYwYImoxw^Z&y}rM|!NSAD#m2|T z$;!*j&Cbuz(bCh@)z;V8+1lIO-QM5e;o{@u<>u$;>FVq3?e6dJ@$&QZ_4fDp`TG0( G{r>;0_J4r@ literal 0 HcmV?d00001 diff --git a/bin/ed/test/ascii.r b/bin/ed/test/ascii.r new file mode 100644 index 0000000000000000000000000000000000000000..c86626638e0bc8cf47ca49bb1525b40e9737ee64 GIT binary patch literal 256 zcmV+b0ssC00RjUA1qKHQ2?`4g4Gs?w5fT#=6&4p585$cL9UdPbAtECrB_<~*DJm;0 zEiNxGF)}kWH8wXmIXXK$Jw87`K|(`BMMg(RNlHshO-@fxQBqS>RaRG6Sz23MU0z>c zVPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3t+%eSUv{fr5jCg@%WSiHeJijgF6yk&=^? zm6n&7nVOrNot~edp`xRtrKYE-sj922t*)=Iv9hzYwYImoxw^Z&y}rM|!NSAD#m2|T z$;!*j&Cbuz(bCh@)z;V8+1lIO-QM5e;o{@u<>u$;>FVq3?e6dJ@$&QZ_4fDp`TG0( G{r>;0_J4r@ literal 0 HcmV?d00001 diff --git a/bin/ed/test/ascii.t b/bin/ed/test/ascii.t new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/c.d b/bin/ed/test/c.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/c.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/c.r b/bin/ed/test/c.r new file mode 100644 index 000000000000..0fb3e4fffc0d --- /dev/null +++ b/bin/ed/test/c.r @@ -0,0 +1,4 @@ +at the top +between top/middle +in the middle +at the bottom diff --git a/bin/ed/test/c.t b/bin/ed/test/c.t new file mode 100644 index 000000000000..ebdd536f8171 --- /dev/null +++ b/bin/ed/test/c.t @@ -0,0 +1,12 @@ +1c +at the top +. +4c +in the middle +. +$c +at the bottom +. +2,3c +between top/middle +. diff --git a/bin/ed/test/c1.err b/bin/ed/test/c1.err new file mode 100644 index 000000000000..658ec38b4649 --- /dev/null +++ b/bin/ed/test/c1.err @@ -0,0 +1,3 @@ +cc +hello world +. diff --git a/bin/ed/test/c2.err b/bin/ed/test/c2.err new file mode 100644 index 000000000000..24b322776a66 --- /dev/null +++ b/bin/ed/test/c2.err @@ -0,0 +1,3 @@ +0c +hello world +. diff --git a/bin/ed/test/ckscripts.sh b/bin/ed/test/ckscripts.sh new file mode 100644 index 000000000000..87a7e9beb560 --- /dev/null +++ b/bin/ed/test/ckscripts.sh @@ -0,0 +1,37 @@ +#!/bin/sh - +# This script runs the .ed scripts generated by mkscripts.sh +# and compares their output against the .r files, which contain +# the correct output + +PATH="/bin:/usr/bin:/usr/local/bin/:." +ED=$1 +[ X"$ED" = X -o ! -x $ED ] && ED="../ed" +[ ! -x $ED ] && { echo "$ED: cannot execute"; exit 1; } + +# Run the *-err.ed scripts first, since these don't generate output; +# rename then to *-err.ed~; they exit with non-zero status +for i in *-err.ed; do + echo $i~ + if $i; then + echo "*** The script $i~ exited abnormally ***" + fi + mv $i $i~ +done >errs.o 2>&1 + +# Run the remainding scripts; they exit with zero status +for i in *.ed; do + base=`expr $i : '\([^.]*\)'` +# base=`echo $i | sed 's/\..*//'` +# base=`$ED - \!"echo \\\\$i" <<-EOF +# s/\..* +# EOF` + if $base.ed; then + if cmp -s $base.o $base.r; then :; else + echo "*** Output $base.o of script $i is incorrect ***" + fi + else + echo "*** The script $i exited abnormally ***" + fi +done >scripts.o 2>&1 + +grep -h '\*\*\*' errs.o scripts.o diff --git a/bin/ed/test/d.d b/bin/ed/test/d.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/d.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/d.err b/bin/ed/test/d.err new file mode 100644 index 000000000000..f03f6945fbf9 --- /dev/null +++ b/bin/ed/test/d.err @@ -0,0 +1 @@ +dd diff --git a/bin/ed/test/d.r b/bin/ed/test/d.r new file mode 100644 index 000000000000..b7e242c00cda --- /dev/null +++ b/bin/ed/test/d.r @@ -0,0 +1 @@ +line 2 diff --git a/bin/ed/test/d.t b/bin/ed/test/d.t new file mode 100644 index 000000000000..c7c473febdf7 --- /dev/null +++ b/bin/ed/test/d.t @@ -0,0 +1,3 @@ +1d +2;+1d +$d diff --git a/bin/ed/test/e1.d b/bin/ed/test/e1.d new file mode 100644 index 000000000000..3b18e512dba7 --- /dev/null +++ b/bin/ed/test/e1.d @@ -0,0 +1 @@ +hello world diff --git a/bin/ed/test/e1.err b/bin/ed/test/e1.err new file mode 100644 index 000000000000..827cc292b6bb --- /dev/null +++ b/bin/ed/test/e1.err @@ -0,0 +1 @@ +ee e1.err diff --git a/bin/ed/test/e1.r b/bin/ed/test/e1.r new file mode 100644 index 000000000000..e656728bab21 --- /dev/null +++ b/bin/ed/test/e1.r @@ -0,0 +1 @@ +E e1.t diff --git a/bin/ed/test/e1.t b/bin/ed/test/e1.t new file mode 100644 index 000000000000..e656728bab21 --- /dev/null +++ b/bin/ed/test/e1.t @@ -0,0 +1 @@ +E e1.t diff --git a/bin/ed/test/e2.d b/bin/ed/test/e2.d new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e2.d @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e2.err b/bin/ed/test/e2.err new file mode 100644 index 000000000000..779a64b54ff9 --- /dev/null +++ b/bin/ed/test/e2.err @@ -0,0 +1 @@ +.e e2.err diff --git a/bin/ed/test/e2.r b/bin/ed/test/e2.r new file mode 100644 index 000000000000..59ebf11fd099 --- /dev/null +++ b/bin/ed/test/e2.r @@ -0,0 +1 @@ +hello world- diff --git a/bin/ed/test/e2.t b/bin/ed/test/e2.t new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e2.t @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e3.d b/bin/ed/test/e3.d new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e3.d @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e3.err b/bin/ed/test/e3.err new file mode 100644 index 000000000000..80a7fdcf92ee --- /dev/null +++ b/bin/ed/test/e3.err @@ -0,0 +1 @@ +ee.err diff --git a/bin/ed/test/e3.r b/bin/ed/test/e3.r new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e3.r @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e3.t b/bin/ed/test/e3.t new file mode 100644 index 000000000000..1c507261389e --- /dev/null +++ b/bin/ed/test/e3.t @@ -0,0 +1 @@ +E diff --git a/bin/ed/test/e4.d b/bin/ed/test/e4.d new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e4.d @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e4.r b/bin/ed/test/e4.r new file mode 100644 index 000000000000..aa44630d22a6 --- /dev/null +++ b/bin/ed/test/e4.r @@ -0,0 +1 @@ +E !echo hello world- diff --git a/bin/ed/test/e4.t b/bin/ed/test/e4.t new file mode 100644 index 000000000000..d905d9da82c9 --- /dev/null +++ b/bin/ed/test/e4.t @@ -0,0 +1 @@ +e diff --git a/bin/ed/test/f1.err b/bin/ed/test/f1.err new file mode 100644 index 000000000000..e60975adabb3 --- /dev/null +++ b/bin/ed/test/f1.err @@ -0,0 +1 @@ +.f f1.err diff --git a/bin/ed/test/f2.err b/bin/ed/test/f2.err new file mode 100644 index 000000000000..26d1c5e3a756 --- /dev/null +++ b/bin/ed/test/f2.err @@ -0,0 +1 @@ +ff1.err diff --git a/bin/ed/test/g1.d b/bin/ed/test/g1.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/g1.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/g1.err b/bin/ed/test/g1.err new file mode 100644 index 000000000000..f95ea22232c6 --- /dev/null +++ b/bin/ed/test/g1.err @@ -0,0 +1 @@ +g/./s //x/ diff --git a/bin/ed/test/g1.r b/bin/ed/test/g1.r new file mode 100644 index 000000000000..578a44b6b21c --- /dev/null +++ b/bin/ed/test/g1.r @@ -0,0 +1,15 @@ +line5 +help! world +order +line 4 +help! world +order +line 3 +help! world +order +line 2 +help! world +order +line 1 +help! world +order diff --git a/bin/ed/test/g1.t b/bin/ed/test/g1.t new file mode 100644 index 000000000000..2d0b54f35ad3 --- /dev/null +++ b/bin/ed/test/g1.t @@ -0,0 +1,6 @@ +g/./m0 +g/./s/$/\ +hello world +g/hello /s/lo/p!/\ +a\ +order diff --git a/bin/ed/test/g2.d b/bin/ed/test/g2.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/g2.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/g2.err b/bin/ed/test/g2.err new file mode 100644 index 000000000000..0ff6a5a601dd --- /dev/null +++ b/bin/ed/test/g2.err @@ -0,0 +1 @@ +g//s/./x/ diff --git a/bin/ed/test/g2.r b/bin/ed/test/g2.r new file mode 100644 index 000000000000..3b18e512dba7 --- /dev/null +++ b/bin/ed/test/g2.r @@ -0,0 +1 @@ +hello world diff --git a/bin/ed/test/g2.t b/bin/ed/test/g2.t new file mode 100644 index 000000000000..831ee8367bcf --- /dev/null +++ b/bin/ed/test/g2.t @@ -0,0 +1,2 @@ +g/[2-4]/-1,+1c\ +hello world diff --git a/bin/ed/test/g3.err b/bin/ed/test/g3.err new file mode 100644 index 000000000000..01058d844a98 --- /dev/null +++ b/bin/ed/test/g3.err @@ -0,0 +1 @@ +g diff --git a/bin/ed/test/h.err b/bin/ed/test/h.err new file mode 100644 index 000000000000..a71e506f6dd0 --- /dev/null +++ b/bin/ed/test/h.err @@ -0,0 +1 @@ +.h diff --git a/bin/ed/test/i.d b/bin/ed/test/i.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/i.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/i.r b/bin/ed/test/i.r new file mode 100644 index 000000000000..5f27af09c03d --- /dev/null +++ b/bin/ed/test/i.r @@ -0,0 +1,8 @@ +hello world +hello world! +line 1 +line 2 +line 3 +line 4 +hello world!! +line5 diff --git a/bin/ed/test/i.t b/bin/ed/test/i.t new file mode 100644 index 000000000000..d1d98057d882 --- /dev/null +++ b/bin/ed/test/i.t @@ -0,0 +1,9 @@ +1i +hello world +. +2i +hello world! +. +$i +hello world!! +. diff --git a/bin/ed/test/i1.err b/bin/ed/test/i1.err new file mode 100644 index 000000000000..aaddede2599d --- /dev/null +++ b/bin/ed/test/i1.err @@ -0,0 +1,3 @@ +1,$i +hello world +. diff --git a/bin/ed/test/i2.err b/bin/ed/test/i2.err new file mode 100644 index 000000000000..b63f5ac507f5 --- /dev/null +++ b/bin/ed/test/i2.err @@ -0,0 +1,3 @@ +ii +hello world +. diff --git a/bin/ed/test/i3.err b/bin/ed/test/i3.err new file mode 100644 index 000000000000..6d200c8c97ee --- /dev/null +++ b/bin/ed/test/i3.err @@ -0,0 +1,3 @@ +0i +hello world +. diff --git a/bin/ed/test/j.d b/bin/ed/test/j.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/j.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/j.r b/bin/ed/test/j.r new file mode 100644 index 000000000000..66f36a8f8ab5 --- /dev/null +++ b/bin/ed/test/j.r @@ -0,0 +1,4 @@ +line 1 +line 2line 3 +line 4 +line5 diff --git a/bin/ed/test/j.t b/bin/ed/test/j.t new file mode 100644 index 000000000000..9b5d28ddf178 --- /dev/null +++ b/bin/ed/test/j.t @@ -0,0 +1,2 @@ +1,1j +2,3j diff --git a/bin/ed/test/k.d b/bin/ed/test/k.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/k.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/k.r b/bin/ed/test/k.r new file mode 100644 index 000000000000..eeb38db20c6e --- /dev/null +++ b/bin/ed/test/k.r @@ -0,0 +1,5 @@ +line 3 +hello world +line 4 +line5 +line 2 diff --git a/bin/ed/test/k.t b/bin/ed/test/k.t new file mode 100644 index 000000000000..53d588dd07ad --- /dev/null +++ b/bin/ed/test/k.t @@ -0,0 +1,10 @@ +2ka +1d +'am$ +1ka +0a +hello world +. +'ad +u +'am0 diff --git a/bin/ed/test/k1.err b/bin/ed/test/k1.err new file mode 100644 index 000000000000..eba1f3d8ff1d --- /dev/null +++ b/bin/ed/test/k1.err @@ -0,0 +1 @@ +1,$ka diff --git a/bin/ed/test/k2.err b/bin/ed/test/k2.err new file mode 100644 index 000000000000..b34a18d51958 --- /dev/null +++ b/bin/ed/test/k2.err @@ -0,0 +1 @@ +kA diff --git a/bin/ed/test/k3.err b/bin/ed/test/k3.err new file mode 100644 index 000000000000..70190c473df4 --- /dev/null +++ b/bin/ed/test/k3.err @@ -0,0 +1 @@ +0ka diff --git a/bin/ed/test/k4.err b/bin/ed/test/k4.err new file mode 100644 index 000000000000..345764222947 --- /dev/null +++ b/bin/ed/test/k4.err @@ -0,0 +1,6 @@ +a +hello +. +.ka +'ad +'ap diff --git a/bin/ed/test/l.d b/bin/ed/test/l.d new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/l.r b/bin/ed/test/l.r new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/l.t b/bin/ed/test/l.t new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/m.d b/bin/ed/test/m.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/m.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/m.err b/bin/ed/test/m.err new file mode 100644 index 000000000000..3aec4c32c1f9 --- /dev/null +++ b/bin/ed/test/m.err @@ -0,0 +1,4 @@ +a +hello world +. +1,$m1 diff --git a/bin/ed/test/m.r b/bin/ed/test/m.r new file mode 100644 index 000000000000..186cf5403b9f --- /dev/null +++ b/bin/ed/test/m.r @@ -0,0 +1,5 @@ +line5 +line 1 +line 2 +line 3 +line 4 diff --git a/bin/ed/test/m.t b/bin/ed/test/m.t new file mode 100644 index 000000000000..c39c08872452 --- /dev/null +++ b/bin/ed/test/m.t @@ -0,0 +1,7 @@ +1,2m$ +1,2m$ +1,2m$ +$m0 +$m0 +2,3m1 +2,3m3 diff --git a/bin/ed/test/mkscripts.sh b/bin/ed/test/mkscripts.sh new file mode 100644 index 000000000000..724db0cc05a9 --- /dev/null +++ b/bin/ed/test/mkscripts.sh @@ -0,0 +1,71 @@ +#!/bin/sh - +# This script generates ed test scripts (.ed) from .t files + +PATH="/bin:/usr/bin:/usr/local/bin/:." +ED=$1 +[ X"$ED" = X -o ! -x $ED ] && ED="../ed" +[ ! -x $ED ] && { echo "$ED: cannot execute"; exit 1; } + +for i in *.t; do +# base=${i%.*} +# base=`echo $i | sed 's/\..*//'` + base=`expr $i : '\([^.]*\)'` + ( + echo "#!/bin/sh -" + echo "$ED - <<\EOT" + echo "r \\$base.d" + cat $i + echo "w \\$base.o" + echo EOT + ) >$base.ed + chmod +x $base.ed +# The following is pretty ugly and not appropriate use of ed +# but the point is that it can be done... +# base=`$ED - \!"echo \\\\$i" <<-EOF +# s/\..* +# EOF` +# $ED - <<-EOF +# a +# #!/bin/sh - +# $ED - <<\EOT +# r \\$base.d +# w \\$base.o +# EOT +# . +# -2r \\$i +# w \\$base.ed +# !chmod +x \\$base.ed +# EOF +done + +for i in *.err; do +# base=${i%.*} +# base=`echo $i | sed 's/\..*//'` + base=`expr $i : '\([^.]*\)'` + ( + echo "#!/bin/sh -" + echo "$ED - <<\EOT" + echo H + echo "r \\$base.err" + cat $i + echo "w \\$base.o" + echo EOT + ) >$base-err.ed + chmod +x $base-err.ed +# base=`$ED - \!"echo \\\\$i" <<-EOF +# s/\..* +# EOF` +# $ED - <<-EOF +# a +# #!/bin/sh - +# $ED - <<\EOT +# H +# r \\$base.err +# w \\$base.o +# EOT +# . +# -2r \\$i +# w \\${base}-err.ed +# !chmod +x ${base}-err.ed +# EOF +done diff --git a/bin/ed/test/n.d b/bin/ed/test/n.d new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/n.r b/bin/ed/test/n.r new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/n.t b/bin/ed/test/n.t new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/p.d b/bin/ed/test/p.d new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/p.r b/bin/ed/test/p.r new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/p.t b/bin/ed/test/p.t new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/q.d b/bin/ed/test/q.d new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/q.r b/bin/ed/test/q.r new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/q.t b/bin/ed/test/q.t new file mode 100644 index 000000000000..123a2c8e2cf4 --- /dev/null +++ b/bin/ed/test/q.t @@ -0,0 +1,5 @@ +w q.o +a +hello +. +q diff --git a/bin/ed/test/q1.err b/bin/ed/test/q1.err new file mode 100644 index 000000000000..0a7e178d2062 --- /dev/null +++ b/bin/ed/test/q1.err @@ -0,0 +1 @@ +.q diff --git a/bin/ed/test/r1.d b/bin/ed/test/r1.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/r1.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/r1.err b/bin/ed/test/r1.err new file mode 100644 index 000000000000..269aa7cbcb8c --- /dev/null +++ b/bin/ed/test/r1.err @@ -0,0 +1 @@ +1,$r r1.err diff --git a/bin/ed/test/r1.r b/bin/ed/test/r1.r new file mode 100644 index 000000000000..a3ff506ec7c2 --- /dev/null +++ b/bin/ed/test/r1.r @@ -0,0 +1,7 @@ +line 1 +hello world +line 2 +line 3 +line 4 +line5 +hello world diff --git a/bin/ed/test/r1.t b/bin/ed/test/r1.t new file mode 100644 index 000000000000..d787a923e3f2 --- /dev/null +++ b/bin/ed/test/r1.t @@ -0,0 +1,3 @@ +1;r !echo hello world +1 +r !echo hello world diff --git a/bin/ed/test/r2.d b/bin/ed/test/r2.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/r2.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/r2.err b/bin/ed/test/r2.err new file mode 100644 index 000000000000..1c44fa3ea9ca --- /dev/null +++ b/bin/ed/test/r2.err @@ -0,0 +1 @@ +r a-good-book diff --git a/bin/ed/test/r2.r b/bin/ed/test/r2.r new file mode 100644 index 000000000000..ac152ba9d0a2 --- /dev/null +++ b/bin/ed/test/r2.r @@ -0,0 +1,10 @@ +line 1 +line 2 +line 3 +line 4 +line5 +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/r2.t b/bin/ed/test/r2.t new file mode 100644 index 000000000000..4286f428e3b1 --- /dev/null +++ b/bin/ed/test/r2.t @@ -0,0 +1 @@ +r diff --git a/bin/ed/test/r3.d b/bin/ed/test/r3.d new file mode 100644 index 000000000000..593eec6192b4 --- /dev/null +++ b/bin/ed/test/r3.d @@ -0,0 +1 @@ +r r3.t diff --git a/bin/ed/test/r3.r b/bin/ed/test/r3.r new file mode 100644 index 000000000000..86d5f904fc11 --- /dev/null +++ b/bin/ed/test/r3.r @@ -0,0 +1,2 @@ +r r3.t +r r3.t diff --git a/bin/ed/test/r3.t b/bin/ed/test/r3.t new file mode 100644 index 000000000000..593eec6192b4 --- /dev/null +++ b/bin/ed/test/r3.t @@ -0,0 +1 @@ +r r3.t diff --git a/bin/ed/test/s1.d b/bin/ed/test/s1.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/s1.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/s1.err b/bin/ed/test/s1.err new file mode 100644 index 000000000000..d7ca0cf480d2 --- /dev/null +++ b/bin/ed/test/s1.err @@ -0,0 +1 @@ +s . x diff --git a/bin/ed/test/s1.r b/bin/ed/test/s1.r new file mode 100644 index 000000000000..4eb0980cfe79 --- /dev/null +++ b/bin/ed/test/s1.r @@ -0,0 +1,5 @@ +liene 1 +(liene) (2) +(liene) (3) +liene (4) +(()liene5) diff --git a/bin/ed/test/s1.t b/bin/ed/test/s1.t new file mode 100644 index 000000000000..b0028bb6c921 --- /dev/null +++ b/bin/ed/test/s1.t @@ -0,0 +1,6 @@ +s/\([^ ][^ ]*\)/(\1)/g +2s +/3/s +/\(4\)/sr +/\(.\)/srg +%s/i/&e/ diff --git a/bin/ed/test/s10.err b/bin/ed/test/s10.err new file mode 100644 index 000000000000..0d8d83de19ac --- /dev/null +++ b/bin/ed/test/s10.err @@ -0,0 +1,4 @@ +a +hello +. +s/[h[.]/x/ diff --git a/bin/ed/test/s2.d b/bin/ed/test/s2.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/s2.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/s2.err b/bin/ed/test/s2.err new file mode 100644 index 000000000000..b5c851df7b28 --- /dev/null +++ b/bin/ed/test/s2.err @@ -0,0 +1,4 @@ +a +a +. +s/x*/a/g diff --git a/bin/ed/test/s2.r b/bin/ed/test/s2.r new file mode 100644 index 000000000000..ca305c8d506a --- /dev/null +++ b/bin/ed/test/s2.r @@ -0,0 +1,5 @@ +li(n)e 1 +i(n)e 200 +li(n)e 3 +li(n)e 4 +li(n)e500 diff --git a/bin/ed/test/s2.t b/bin/ed/test/s2.t new file mode 100644 index 000000000000..f36584997c97 --- /dev/null +++ b/bin/ed/test/s2.t @@ -0,0 +1,4 @@ +,s/./(&)/3 +s/$/00 +2s//%/g +s/^l diff --git a/bin/ed/test/s3.d b/bin/ed/test/s3.d new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/bin/ed/test/s3.err b/bin/ed/test/s3.err new file mode 100644 index 000000000000..d68c7d07f99c --- /dev/null +++ b/bin/ed/test/s3.err @@ -0,0 +1 @@ +s/[xyx/a/ diff --git a/bin/ed/test/s3.r b/bin/ed/test/s3.r new file mode 100644 index 000000000000..d6cada2212fd --- /dev/null +++ b/bin/ed/test/s3.r @@ -0,0 +1 @@ +hello world diff --git a/bin/ed/test/s3.t b/bin/ed/test/s3.t new file mode 100644 index 000000000000..fbf880304b7a --- /dev/null +++ b/bin/ed/test/s3.t @@ -0,0 +1,6 @@ +a +hello/[]world +. +s/[/]/ / +s/[[:digit:][]/ / +s/[]]/ / diff --git a/bin/ed/test/s4.err b/bin/ed/test/s4.err new file mode 100644 index 000000000000..35b609fc625c --- /dev/null +++ b/bin/ed/test/s4.err @@ -0,0 +1 @@ +s/\a\b\c/xyz/ diff --git a/bin/ed/test/s5.err b/bin/ed/test/s5.err new file mode 100644 index 000000000000..89104c55232c --- /dev/null +++ b/bin/ed/test/s5.err @@ -0,0 +1 @@ +s//xyz/ diff --git a/bin/ed/test/s6.err b/bin/ed/test/s6.err new file mode 100644 index 000000000000..b4785957bc98 --- /dev/null +++ b/bin/ed/test/s6.err @@ -0,0 +1 @@ +s diff --git a/bin/ed/test/s7.err b/bin/ed/test/s7.err new file mode 100644 index 000000000000..30ba4fded765 --- /dev/null +++ b/bin/ed/test/s7.err @@ -0,0 +1,5 @@ +a +hello world +. +/./ +sr diff --git a/bin/ed/test/s8.err b/bin/ed/test/s8.err new file mode 100644 index 000000000000..5665767c3fa0 --- /dev/null +++ b/bin/ed/test/s8.err @@ -0,0 +1,4 @@ +a +hello +. +s/[h[=]/x/ diff --git a/bin/ed/test/s9.err b/bin/ed/test/s9.err new file mode 100644 index 000000000000..1ff16dd8470f --- /dev/null +++ b/bin/ed/test/s9.err @@ -0,0 +1,4 @@ +a +hello +. +s/[h[:]/x/ diff --git a/bin/ed/test/t.d b/bin/ed/test/t.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/t.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t.r b/bin/ed/test/t.r new file mode 100644 index 000000000000..2b2854758d5d --- /dev/null +++ b/bin/ed/test/t.r @@ -0,0 +1,16 @@ +line 1 +line 1 +line 1 +line 2 +line 2 +line 3 +line 4 +line5 +line 1 +line 1 +line 1 +line 2 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t1.d b/bin/ed/test/t1.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/t1.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t1.err b/bin/ed/test/t1.err new file mode 100644 index 000000000000..c49c556e0e47 --- /dev/null +++ b/bin/ed/test/t1.err @@ -0,0 +1 @@ +tt diff --git a/bin/ed/test/t1.r b/bin/ed/test/t1.r new file mode 100644 index 000000000000..2b2854758d5d --- /dev/null +++ b/bin/ed/test/t1.r @@ -0,0 +1,16 @@ +line 1 +line 1 +line 1 +line 2 +line 2 +line 3 +line 4 +line5 +line 1 +line 1 +line 1 +line 2 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t1.t b/bin/ed/test/t1.t new file mode 100644 index 000000000000..6b66163793ad --- /dev/null +++ b/bin/ed/test/t1.t @@ -0,0 +1,3 @@ +1t0 +2,3t2 +,t$ diff --git a/bin/ed/test/t2.d b/bin/ed/test/t2.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/t2.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t2.err b/bin/ed/test/t2.err new file mode 100644 index 000000000000..c202051b7f18 --- /dev/null +++ b/bin/ed/test/t2.err @@ -0,0 +1 @@ +t0;-1 diff --git a/bin/ed/test/t2.r b/bin/ed/test/t2.r new file mode 100644 index 000000000000..0c75ff554ca8 --- /dev/null +++ b/bin/ed/test/t2.r @@ -0,0 +1,6 @@ +line 1 +line5 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/t2.t b/bin/ed/test/t2.t new file mode 100644 index 000000000000..5175abdec90d --- /dev/null +++ b/bin/ed/test/t2.t @@ -0,0 +1 @@ +t0;/./ diff --git a/bin/ed/test/u.d b/bin/ed/test/u.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/u.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/u.err b/bin/ed/test/u.err new file mode 100644 index 000000000000..caa1ba114885 --- /dev/null +++ b/bin/ed/test/u.err @@ -0,0 +1 @@ +.u diff --git a/bin/ed/test/u.r b/bin/ed/test/u.r new file mode 100644 index 000000000000..ad558d82d02d --- /dev/null +++ b/bin/ed/test/u.r @@ -0,0 +1,9 @@ +line 1 +hello +hello world!! +line 2 +line 3 +line 4 +line5 +hello +hello world!! diff --git a/bin/ed/test/u.t b/bin/ed/test/u.t new file mode 100644 index 000000000000..131cb6e25c1b --- /dev/null +++ b/bin/ed/test/u.t @@ -0,0 +1,31 @@ +1;r u.t +u +a +hello +world +. +g/./s//x/\ +a\ +hello\ +world +u +u +u +a +hello world! +. +u +1,$d +u +2,3d +u +c +hello world!! +. +u +u +-1;.,+1j +u +u +u +.,+1t$ diff --git a/bin/ed/test/v.d b/bin/ed/test/v.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/v.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/v.r b/bin/ed/test/v.r new file mode 100644 index 000000000000..714db63e357b --- /dev/null +++ b/bin/ed/test/v.r @@ -0,0 +1,11 @@ +line5 +order +hello world +line 1 +order +line 2 +order +line 3 +order +line 4 +order diff --git a/bin/ed/test/v.t b/bin/ed/test/v.t new file mode 100644 index 000000000000..608a77fb6a43 --- /dev/null +++ b/bin/ed/test/v.t @@ -0,0 +1,6 @@ +v/[ ]/m0 +v/[ ]/s/$/\ +hello world +v/hello /s/lo/p!/\ +a\ +order diff --git a/bin/ed/test/w.d b/bin/ed/test/w.d new file mode 100644 index 000000000000..92f337e977f2 --- /dev/null +++ b/bin/ed/test/w.d @@ -0,0 +1,5 @@ +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/w.r b/bin/ed/test/w.r new file mode 100644 index 000000000000..ac152ba9d0a2 --- /dev/null +++ b/bin/ed/test/w.r @@ -0,0 +1,10 @@ +line 1 +line 2 +line 3 +line 4 +line5 +line 1 +line 2 +line 3 +line 4 +line5 diff --git a/bin/ed/test/w.t b/bin/ed/test/w.t new file mode 100644 index 000000000000..c2e18bd2f659 --- /dev/null +++ b/bin/ed/test/w.t @@ -0,0 +1,2 @@ +w !cat >\!.z +r \!.z diff --git a/bin/ed/test/w1.err b/bin/ed/test/w1.err new file mode 100644 index 000000000000..e2c8a603f7e3 --- /dev/null +++ b/bin/ed/test/w1.err @@ -0,0 +1 @@ +w /to/some/far-away/place diff --git a/bin/ed/test/w2.err b/bin/ed/test/w2.err new file mode 100644 index 000000000000..9daf89cfa71d --- /dev/null +++ b/bin/ed/test/w2.err @@ -0,0 +1 @@ +ww.o diff --git a/bin/ed/test/w3.err b/bin/ed/test/w3.err new file mode 100644 index 000000000000..39bbf4c95b9b --- /dev/null +++ b/bin/ed/test/w3.err @@ -0,0 +1 @@ +wqp w.o diff --git a/bin/ed/test/x.err b/bin/ed/test/x.err new file mode 100644 index 000000000000..0953f01dd071 --- /dev/null +++ b/bin/ed/test/x.err @@ -0,0 +1 @@ +.x diff --git a/bin/ed/test/z.err b/bin/ed/test/z.err new file mode 100644 index 000000000000..6a51a2d58306 --- /dev/null +++ b/bin/ed/test/z.err @@ -0,0 +1,2 @@ +z +z