mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-02 22:54:52 +00:00
POSIX ed version 0.6 by Andrew Moore (alm@netcom.com).
This commit is contained in:
parent
ddd9386e4d
commit
30154ac8a8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/unlabeled-1.1.1/; revision=16
7
bin/ed/Makefile
Normal file
7
bin/ed/Makefile
Normal file
|
@ -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 <bsd.prog.mk>
|
50
bin/ed/POSIX
Normal file
50
bin/ed/POSIX
Normal file
|
@ -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
|
||||
<file> arguments are processed for backslash escapes, i.e., any character
|
||||
preceded by a backslash is interpreted literally. If the first unescaped
|
||||
character of a <file> 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) !<shell-cmd> replaces the addressed lines with the output of
|
||||
the command <shell-cmd>.
|
||||
[rwe] !! reads/writes/edits the previous !<shell-cmd>.
|
||||
|
||||
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 !<shell-cmd> 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.
|
22
bin/ed/README
Normal file
22
bin/ed/README
Normal file
|
@ -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.
|
246
bin/ed/buf.c
Normal file
246
bin/ed/buf.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
435
bin/ed/cbc.c
Normal file
435
bin/ed/cbc.c
Normal file
|
@ -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 <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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 */
|
980
bin/ed/ed.1
Normal file
980
bin/ed/ed.1
Normal file
|
@ -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.
|
263
bin/ed/ed.h
Normal file
263
bin/ed/ed.h
Normal file
|
@ -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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#if defined(BSD) && BSD >= 199103 || defined(__386BSD__)
|
||||
# include <sys/param.h> /* for MAXPATHLEN */
|
||||
#endif
|
||||
#include <regex.h>
|
||||
#include <signal.h>
|
||||
|
||||
#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;
|
156
bin/ed/re.c
Normal file
156
bin/ed/re.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
1
bin/ed/test/=.err
Normal file
1
bin/ed/test/=.err
Normal file
|
@ -0,0 +1 @@
|
|||
1,$=
|
17
bin/ed/test/Makefile
Normal file
17
bin/ed/test/Makefile
Normal file
|
@ -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] *~
|
41
bin/ed/test/README
Normal file
41
bin/ed/test/README
Normal file
|
@ -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.
|
15
bin/ed/test/TODO
Normal file
15
bin/ed/test/TODO
Normal file
|
@ -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
|
5
bin/ed/test/a.d
Normal file
5
bin/ed/test/a.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
8
bin/ed/test/a.r
Normal file
8
bin/ed/test/a.r
Normal file
|
@ -0,0 +1,8 @@
|
|||
hello world
|
||||
line 1
|
||||
hello world!
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
||||
hello world!!
|
9
bin/ed/test/a.t
Normal file
9
bin/ed/test/a.t
Normal file
|
@ -0,0 +1,9 @@
|
|||
0a
|
||||
hello world
|
||||
.
|
||||
2a
|
||||
hello world!
|
||||
.
|
||||
$a
|
||||
hello world!!
|
||||
.
|
3
bin/ed/test/a1.err
Normal file
3
bin/ed/test/a1.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
1,$a
|
||||
hello world
|
||||
.
|
3
bin/ed/test/a2.err
Normal file
3
bin/ed/test/a2.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
aa
|
||||
hello world
|
||||
.
|
1
bin/ed/test/addr1.err
Normal file
1
bin/ed/test/addr1.err
Normal file
|
@ -0,0 +1 @@
|
|||
100
|
1
bin/ed/test/addr2.err
Normal file
1
bin/ed/test/addr2.err
Normal file
|
@ -0,0 +1 @@
|
|||
-100
|
BIN
bin/ed/test/ascii.d
Normal file
BIN
bin/ed/test/ascii.d
Normal file
Binary file not shown.
BIN
bin/ed/test/ascii.r
Normal file
BIN
bin/ed/test/ascii.r
Normal file
Binary file not shown.
0
bin/ed/test/ascii.t
Normal file
0
bin/ed/test/ascii.t
Normal file
5
bin/ed/test/c.d
Normal file
5
bin/ed/test/c.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
4
bin/ed/test/c.r
Normal file
4
bin/ed/test/c.r
Normal file
|
@ -0,0 +1,4 @@
|
|||
at the top
|
||||
between top/middle
|
||||
in the middle
|
||||
at the bottom
|
12
bin/ed/test/c.t
Normal file
12
bin/ed/test/c.t
Normal file
|
@ -0,0 +1,12 @@
|
|||
1c
|
||||
at the top
|
||||
.
|
||||
4c
|
||||
in the middle
|
||||
.
|
||||
$c
|
||||
at the bottom
|
||||
.
|
||||
2,3c
|
||||
between top/middle
|
||||
.
|
3
bin/ed/test/c1.err
Normal file
3
bin/ed/test/c1.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
cc
|
||||
hello world
|
||||
.
|
3
bin/ed/test/c2.err
Normal file
3
bin/ed/test/c2.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
0c
|
||||
hello world
|
||||
.
|
37
bin/ed/test/ckscripts.sh
Normal file
37
bin/ed/test/ckscripts.sh
Normal file
|
@ -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
|
5
bin/ed/test/d.d
Normal file
5
bin/ed/test/d.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
1
bin/ed/test/d.err
Normal file
1
bin/ed/test/d.err
Normal file
|
@ -0,0 +1 @@
|
|||
dd
|
1
bin/ed/test/d.r
Normal file
1
bin/ed/test/d.r
Normal file
|
@ -0,0 +1 @@
|
|||
line 2
|
3
bin/ed/test/d.t
Normal file
3
bin/ed/test/d.t
Normal file
|
@ -0,0 +1,3 @@
|
|||
1d
|
||||
2;+1d
|
||||
$d
|
1
bin/ed/test/e1.d
Normal file
1
bin/ed/test/e1.d
Normal file
|
@ -0,0 +1 @@
|
|||
hello world
|
1
bin/ed/test/e1.err
Normal file
1
bin/ed/test/e1.err
Normal file
|
@ -0,0 +1 @@
|
|||
ee e1.err
|
1
bin/ed/test/e1.r
Normal file
1
bin/ed/test/e1.r
Normal file
|
@ -0,0 +1 @@
|
|||
E e1.t
|
1
bin/ed/test/e1.t
Normal file
1
bin/ed/test/e1.t
Normal file
|
@ -0,0 +1 @@
|
|||
E e1.t
|
1
bin/ed/test/e2.d
Normal file
1
bin/ed/test/e2.d
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e2.err
Normal file
1
bin/ed/test/e2.err
Normal file
|
@ -0,0 +1 @@
|
|||
.e e2.err
|
1
bin/ed/test/e2.r
Normal file
1
bin/ed/test/e2.r
Normal file
|
@ -0,0 +1 @@
|
|||
hello world-
|
1
bin/ed/test/e2.t
Normal file
1
bin/ed/test/e2.t
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e3.d
Normal file
1
bin/ed/test/e3.d
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e3.err
Normal file
1
bin/ed/test/e3.err
Normal file
|
@ -0,0 +1 @@
|
|||
ee.err
|
1
bin/ed/test/e3.r
Normal file
1
bin/ed/test/e3.r
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e3.t
Normal file
1
bin/ed/test/e3.t
Normal file
|
@ -0,0 +1 @@
|
|||
E
|
1
bin/ed/test/e4.d
Normal file
1
bin/ed/test/e4.d
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e4.r
Normal file
1
bin/ed/test/e4.r
Normal file
|
@ -0,0 +1 @@
|
|||
E !echo hello world-
|
1
bin/ed/test/e4.t
Normal file
1
bin/ed/test/e4.t
Normal file
|
@ -0,0 +1 @@
|
|||
e
|
1
bin/ed/test/f1.err
Normal file
1
bin/ed/test/f1.err
Normal file
|
@ -0,0 +1 @@
|
|||
.f f1.err
|
1
bin/ed/test/f2.err
Normal file
1
bin/ed/test/f2.err
Normal file
|
@ -0,0 +1 @@
|
|||
ff1.err
|
5
bin/ed/test/g1.d
Normal file
5
bin/ed/test/g1.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
1
bin/ed/test/g1.err
Normal file
1
bin/ed/test/g1.err
Normal file
|
@ -0,0 +1 @@
|
|||
g/./s //x/
|
15
bin/ed/test/g1.r
Normal file
15
bin/ed/test/g1.r
Normal file
|
@ -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
|
6
bin/ed/test/g1.t
Normal file
6
bin/ed/test/g1.t
Normal file
|
@ -0,0 +1,6 @@
|
|||
g/./m0
|
||||
g/./s/$/\
|
||||
hello world
|
||||
g/hello /s/lo/p!/\
|
||||
a\
|
||||
order
|
5
bin/ed/test/g2.d
Normal file
5
bin/ed/test/g2.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
1
bin/ed/test/g2.err
Normal file
1
bin/ed/test/g2.err
Normal file
|
@ -0,0 +1 @@
|
|||
g//s/./x/
|
1
bin/ed/test/g2.r
Normal file
1
bin/ed/test/g2.r
Normal file
|
@ -0,0 +1 @@
|
|||
hello world
|
2
bin/ed/test/g2.t
Normal file
2
bin/ed/test/g2.t
Normal file
|
@ -0,0 +1,2 @@
|
|||
g/[2-4]/-1,+1c\
|
||||
hello world
|
1
bin/ed/test/g3.err
Normal file
1
bin/ed/test/g3.err
Normal file
|
@ -0,0 +1 @@
|
|||
g
|
1
bin/ed/test/h.err
Normal file
1
bin/ed/test/h.err
Normal file
|
@ -0,0 +1 @@
|
|||
.h
|
5
bin/ed/test/i.d
Normal file
5
bin/ed/test/i.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
8
bin/ed/test/i.r
Normal file
8
bin/ed/test/i.r
Normal file
|
@ -0,0 +1,8 @@
|
|||
hello world
|
||||
hello world!
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
hello world!!
|
||||
line5
|
9
bin/ed/test/i.t
Normal file
9
bin/ed/test/i.t
Normal file
|
@ -0,0 +1,9 @@
|
|||
1i
|
||||
hello world
|
||||
.
|
||||
2i
|
||||
hello world!
|
||||
.
|
||||
$i
|
||||
hello world!!
|
||||
.
|
3
bin/ed/test/i1.err
Normal file
3
bin/ed/test/i1.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
1,$i
|
||||
hello world
|
||||
.
|
3
bin/ed/test/i2.err
Normal file
3
bin/ed/test/i2.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
ii
|
||||
hello world
|
||||
.
|
3
bin/ed/test/i3.err
Normal file
3
bin/ed/test/i3.err
Normal file
|
@ -0,0 +1,3 @@
|
|||
0i
|
||||
hello world
|
||||
.
|
5
bin/ed/test/j.d
Normal file
5
bin/ed/test/j.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
4
bin/ed/test/j.r
Normal file
4
bin/ed/test/j.r
Normal file
|
@ -0,0 +1,4 @@
|
|||
line 1
|
||||
line 2line 3
|
||||
line 4
|
||||
line5
|
2
bin/ed/test/j.t
Normal file
2
bin/ed/test/j.t
Normal file
|
@ -0,0 +1,2 @@
|
|||
1,1j
|
||||
2,3j
|
5
bin/ed/test/k.d
Normal file
5
bin/ed/test/k.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
5
bin/ed/test/k.r
Normal file
5
bin/ed/test/k.r
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 3
|
||||
hello world
|
||||
line 4
|
||||
line5
|
||||
line 2
|
10
bin/ed/test/k.t
Normal file
10
bin/ed/test/k.t
Normal file
|
@ -0,0 +1,10 @@
|
|||
2ka
|
||||
1d
|
||||
'am$
|
||||
1ka
|
||||
0a
|
||||
hello world
|
||||
.
|
||||
'ad
|
||||
u
|
||||
'am0
|
1
bin/ed/test/k1.err
Normal file
1
bin/ed/test/k1.err
Normal file
|
@ -0,0 +1 @@
|
|||
1,$ka
|
1
bin/ed/test/k2.err
Normal file
1
bin/ed/test/k2.err
Normal file
|
@ -0,0 +1 @@
|
|||
kA
|
1
bin/ed/test/k3.err
Normal file
1
bin/ed/test/k3.err
Normal file
|
@ -0,0 +1 @@
|
|||
0ka
|
6
bin/ed/test/k4.err
Normal file
6
bin/ed/test/k4.err
Normal file
|
@ -0,0 +1,6 @@
|
|||
a
|
||||
hello
|
||||
.
|
||||
.ka
|
||||
'ad
|
||||
'ap
|
0
bin/ed/test/l.d
Normal file
0
bin/ed/test/l.d
Normal file
0
bin/ed/test/l.r
Normal file
0
bin/ed/test/l.r
Normal file
0
bin/ed/test/l.t
Normal file
0
bin/ed/test/l.t
Normal file
5
bin/ed/test/m.d
Normal file
5
bin/ed/test/m.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
4
bin/ed/test/m.err
Normal file
4
bin/ed/test/m.err
Normal file
|
@ -0,0 +1,4 @@
|
|||
a
|
||||
hello world
|
||||
.
|
||||
1,$m1
|
5
bin/ed/test/m.r
Normal file
5
bin/ed/test/m.r
Normal file
|
@ -0,0 +1,5 @@
|
|||
line5
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
7
bin/ed/test/m.t
Normal file
7
bin/ed/test/m.t
Normal file
|
@ -0,0 +1,7 @@
|
|||
1,2m$
|
||||
1,2m$
|
||||
1,2m$
|
||||
$m0
|
||||
$m0
|
||||
2,3m1
|
||||
2,3m3
|
71
bin/ed/test/mkscripts.sh
Normal file
71
bin/ed/test/mkscripts.sh
Normal file
|
@ -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
|
0
bin/ed/test/n.d
Normal file
0
bin/ed/test/n.d
Normal file
0
bin/ed/test/n.r
Normal file
0
bin/ed/test/n.r
Normal file
0
bin/ed/test/n.t
Normal file
0
bin/ed/test/n.t
Normal file
0
bin/ed/test/p.d
Normal file
0
bin/ed/test/p.d
Normal file
0
bin/ed/test/p.r
Normal file
0
bin/ed/test/p.r
Normal file
0
bin/ed/test/p.t
Normal file
0
bin/ed/test/p.t
Normal file
0
bin/ed/test/q.d
Normal file
0
bin/ed/test/q.d
Normal file
0
bin/ed/test/q.r
Normal file
0
bin/ed/test/q.r
Normal file
5
bin/ed/test/q.t
Normal file
5
bin/ed/test/q.t
Normal file
|
@ -0,0 +1,5 @@
|
|||
w q.o
|
||||
a
|
||||
hello
|
||||
.
|
||||
q
|
1
bin/ed/test/q1.err
Normal file
1
bin/ed/test/q1.err
Normal file
|
@ -0,0 +1 @@
|
|||
.q
|
5
bin/ed/test/r1.d
Normal file
5
bin/ed/test/r1.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
1
bin/ed/test/r1.err
Normal file
1
bin/ed/test/r1.err
Normal file
|
@ -0,0 +1 @@
|
|||
1,$r r1.err
|
7
bin/ed/test/r1.r
Normal file
7
bin/ed/test/r1.r
Normal file
|
@ -0,0 +1,7 @@
|
|||
line 1
|
||||
hello world
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
||||
hello world
|
3
bin/ed/test/r1.t
Normal file
3
bin/ed/test/r1.t
Normal file
|
@ -0,0 +1,3 @@
|
|||
1;r !echo hello world
|
||||
1
|
||||
r !echo hello world
|
5
bin/ed/test/r2.d
Normal file
5
bin/ed/test/r2.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
1
bin/ed/test/r2.err
Normal file
1
bin/ed/test/r2.err
Normal file
|
@ -0,0 +1 @@
|
|||
r a-good-book
|
10
bin/ed/test/r2.r
Normal file
10
bin/ed/test/r2.r
Normal file
|
@ -0,0 +1,10 @@
|
|||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line5
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue