/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1995-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Editor (snarfed from v10, now posix compliant, no hard limits)
*/
static const char usage[] =
"[-?\n@(#)$Id: ed (AT&T Research) 2004-06-08 $\n]"
"[+NAME?ed - edit text]"
"[+DESCRIPTION?\bed\b is a line-oriented text editor that has two modes:"
" command mode and input mode. In command mode characters on the"
" standard input are interpreted as commands, and in input mode they"
" are interpreted as text.]"
"[h:explain?Explain the details of error conditions rather than the default"
" ``\b?\b'' on the standard error.]"
"[o:output?Write output to the standard output and error messages to the"
" standard error. By default output is written to the file being edited"
" and error messages are printed on the standard output.]"
"[p:prompt?Sets the command line prompt to \astring\a. The default is"
" no prompt.]:[string]"
"[q:test?For testing; enable verbose messages and reset the \bQUIT\b signal"
" handler to the default action.]"
"[s:silent?Disable verbose messages.]"
"[O:lenient?Enable lenient regular expression interpretation."
" This is the default if \bgetconf CONFORMANCE\b is not \bstandard\b.]"
"[S:strict?Enable strict regular expression interpretation. This is the"
" default if \bgetconf CONFORMANCE\b is \bstandard\b. You'd be"
" suprised what the lenient mode lets by.]"
"\n"
"\n[ file ]\n"
"\n"
"[+SEE ALSO?\bsed\b(1), \bregex\b(3)]"
;
#include <ast.h>
#include <error.h>
#include <ls.h>
#include <sfdisc.h>
#include <sig.h>
#include <ctype.h>
#include <regex.h>
#include <setjmp.h>
typedef struct
{
unsigned long event;
} Line_t;
static struct /* program state -- no other dynamic globals */
{
struct
{
} buffer;
struct
{
int print;
int size;
} page;
struct
{
unsigned long dol;
unsigned long dot;
} undo;
char* base;
char* spbeg;
char* spend;
char* global;
char* input;
char* line;
char* linebreak;
char* tmpfile;
int caught;
int compiled;
int evented;
int given;
int help;
int initialized;
int interactive;
int lastc;
int marked;
int modified;
int peekc;
int pending;
int print;
int prompt;
int reflags;
int restricted;
int verbose;
int warn_newline;
int warn_null;
unsigned long all;
unsigned long bytes;
unsigned long event;
unsigned long lines;
} ed;
{
'g', REG_SUB_ALL,
'l', REG_SUB_LIST,
'n', REG_SUB_NUMBER,
'p', REG_SUB_PRINT,
'L', REG_SUB_LOWER,
'U', REG_SUB_UPPER,
0, 0
};
static void commands(void);
static void handle(void);
static void quit(int);
static void
eat(void)
{
{
}
else
}
static void
{
if (level >= 2) {
error_info.file = 0;
}
quit(1);
eat();
if (ed.initialized)
}
}
static void
{
trap();
}
static int
{
trap();
return 0;
}
static void
{
if (ed.initialized) {
}
}
static int
getchr(void)
{
int n;
}
return EOF;
}
trap();
return EOF;
}
}
}
}
static void
splice(void)
{
char* s;
int n;
n--;
if (n > 0 && s[n - 1] == '\\') {
}
else {
break;
}
}
}
}
static char*
input(int n)
{
n--;
}
else
return 0;
}
static ssize_t
{
ssize_t n;
return n;
}
static void
init(void)
{
register int c;
if (!conformance(0, 0))
for (c = 0; c < elementsof(signals); c++)
}
}
static char*
{
register int c;
register char* glob;
if (c == '\n') {
break;
}
if (c == EOF) {
if (glob)
return 0;
break;
}
if (c == '\\' && ((c = getchr()) != delimiter || (flags & REC_SPLICE) && c != '\n') && c && !(flags & REC_IGNORE))
if (!c)
else if (!(flags & REC_IGNORE))
}
if (flags & REC_TERMINATE)
return glob;
}
static void
putrec(register char* s)
{
register int n;
register char* t;
s = t;
n = strlen(s);
while (n > BREAK_LINE) {
n -= BREAK_LINE;
s += BREAK_LINE;
}
}
else
}
static void
modify(void)
{
register int c;
}
}
}
static void
undo(void)
{
register unsigned long event;
int c;
off_t t;
unsigned long n;
c = 0;
c = 1;
}
if (!c)
}
}
static char*
{
char* s;
return s;
}
static off_t
lineput(char* s)
{
modify();
return off;
}
static void
{
off |= LINE_MARKED;
}
}
static void
squeeze(int i)
{
}
static void
nonzero(void)
{
squeeze(1);
}
static char*
getfile(void)
{
register char* s;
register int n;
register int m;
return 0;
}
s[--n] = 0;
if ((m = strlen(s)) < n) {
register char* t;
register char* u;
register char* x;
t = u = s + m;
x = s + n;
while (u < x)
if (!(*t++ = *u++))
t--;
*t++ = 0;
n = t - s;
}
return s;
}
static char*
getline(void)
{
register char* s;
s = 0;
return s;
}
static char*
getbreak(void)
{
char* s;
return s;
}
static char*
getcopy(void)
{
return 0;
}
static void
print(void)
{
nonzero();
do {
}
static int
getnum(void)
{
register int c;
register int r;
r = 0;
r = r * 10 + c - '0';
return r;
}
static void
compile(void)
{
register char* s;
int c;
s = input(0);
if (*s) {
if (*(s + 1)) {
if (*s == *(s + 1))
input(2);
else {
}
eat();
}
else
return;
}
}
else
input(1);
}
}
static int
{
register char* s;
register int c;
trap();
if (!addr)
s = CUR();
return 0;
else {
SET(s, 0);
}
if (c != REG_NOMATCH)
return 0;
}
return 1;
}
static Line_t*
address(void)
{
register int c;
register int sign;
register Line_t* a;
register Line_t* b;
int opcnt;
int nextopand;
nextopand = -1;
sign = 1;
opcnt = 0;
do {
if (c >= '0' && c <= '9') {
if (!opcnt)
}
else switch (c) {
case '$':
/*FALLTHROUGH*/
case '.':
if (opcnt)
break;
case '\'':
do {
break;
case '?':
/*FALLTHROUGH*/
case '/':
input(-1);
compile();
b = a;
for (;;) {
a += sign;
if (execute(a, 0))
break;
if (a == b)
}
break;
default:
a += sign;
continue; /* error? */
}
if (c != '+' && c != '-' && c != '^') {
if (!opcnt)
a = 0;
return a;
}
sign = 1;
if (c != '+')
continue;
}
sign = 1;
opcnt++;
return 0;
}
static void
setwide(void)
{
}
}
static void
setnoaddr(void)
{
}
static void
newline(void)
{
register int warned = 0;
for (;;)
switch (getchr()) {
case EOF:
case '\n':
return;
case 'l':
continue;
case 'n':
continue;
case 'p':
continue;
default:
if (!warned) {
warned = 1;
}
continue;
}
}
static char*
{
}
static void
exfile(void)
{
sfprintf(ed.msg, "\"%s\" %lu line%s, %lu character%s", error_info.file, ed.lines, plural(ed.lines), ed.bytes, plural(ed.bytes));
}
if (ed.warn_newline) {
ed.warn_newline = 0;
}
}
else
}
sep = ", ";
}
if (ed.warn_newline) {
ed.warn_newline = 0;
}
}
error_info.file = 0;
}
static void
putfile(void)
{
register int n;
do {
}
static void
{
}
}
}
}
static void
handle(void)
{
register int c;
char* s;
char* b;
}
for (c = 0; c < elementsof(signals); c++)
b = "ed.hup";
}
else {
error_info.file = b;
putfile();
}
}
quit(0);
}
static Line_t*
{
register char* s;
off_t t;
long added;
added = 0;
while (s = (*f)()) {
trap();
trap();
}
if (r)
}
t = lineput(s);
added++;
}
}
if (r)
*r += added;
}
static void
add(int i)
{
}
squeeze(0);
newline();
}
static void
page(void)
{
register int direction;
register int n;
case '-':
case '.':
case '+':
break;
default:
direction = '+';
break;
}
if ((n = getnum()) > 0)
newline();
else
switch (direction) {
case '-':
break;
case '.':
break;
case '+':
break;
}
print();
}
static void
{
modify();
do {
}
}
static void
gdelete(void)
{
return;
modify();
a2++;
}
else
}
}
}
static void
shell(void)
{
register char* s;
register char* f = 0;
register int c;
if (s[0] == '!' && !s[1]) {
}
else if (!s[0])
else
while (c = *s++) {
if (c == '\\') {
if (*s != '%')
}
else if (c == '%')
else
}
putfile();
exfile();
error_info.file = s;
exfile();
}
else {
s++;
if (f)
putrec(s);
}
putrec("!");
}
}
static void
edit(void)
{
}
if (!ed.initialized) {
}
}
static void
filename(int c)
{
register char* p;
register int sh = 0;
if (*p) {
if (!isspace(*p))
for (p++; isspace(*p); p++)
;
if (!*p)
if (c != 'f') {
if (*p == '!') {
p++;
sh = 1;
}
else if (*p == '\\' && *(p + 1) == '!')
p++;
}
if (ed.restricted) {
register char* s = p;
if (sh)
p--;
else
for (;;)
{
switch (*s++)
{
case 0:
break;
case '/':
case '\n':
case '\\':
sh = 1;
break;
default:
continue;
}
break;
}
if (sh)
}
}
if (c == 'f')
return;
}
else if (c == 'f')
return;
if (c == 'e') {
edit();
}
if (sh) {
p--;
}
else if (c == 'e' || c == 'r') {
}
error_info.file = p;
}
static void
{
register char* s;
register int c;
setwide();
compile();
if (query)
newline();
else {
if (s[0] == '\n' && !s[1])
}
}
/* special case: g/.../d (avoid n^2 algorithm) */
gdelete();
else {
if (query) {
break;
else if (c == '\n')
continue;
else if (c == '&') {
newline();
}
else {
}
}
else
commands();
}
}
}
}
static void
join(void)
{
char* s;
nonzero();
}
static void
{
char* s;
char* e;
int n;
n = getnum();
compile();
splice();
else {
}
eat();
inglob = 1;
if (e = strchr(s, '\n'))
*e++ = 0;
if (e) {
}
}
}
}
if (!inglob)
}
static void
{
modify();
}
}
static void
{
unsigned long ad1_off;
unsigned long adt_off;
nonzero();
newline();
if (cflag) {
}
else {
}
ad2++;
return;
}
}
else
}
static void
commands(void)
{
register int c;
register int n;
char* s;
int lastsep;
for (;;) {
trap();
print();
}
}
c = getchr();
}
else {
c = '\n';
for (;;) {
lastsep = c;
c = getchr();
if (c != ',' && c != ';')
break;
if (lastsep == ',')
if (!a1) {
a1--;
}
if (c == ';')
}
}
}
else
switch (c) {
case 'a':
add(0);
continue;
case 'c':
nonzero();
newline();
continue;
case 'd':
nonzero();
newline();
continue;
case 'E':
c = 'e';
/*FALLTHROUGH*/
case 'e':
setnoaddr();
}
/*FALLTHROUGH*/
case 'r':
filename(c);
setwide();
squeeze(0);
exfile();
continue;
case 'f':
setnoaddr();
filename(c);
continue;
case 'G':
continue;
case 'g':
global(1, 0);
continue;
case 'H':
/*FALLTHROUGH*/
case 'h':
setnoaddr();
newline();
continue;
case 'i':
add(-1);
continue;
case 'j':
newline();
join();
continue;
case 'k':
nonzero();
newline();
continue;
case 'm':
move(0);
continue;
case 'n':
newline();
print();
continue;
case '\n':
if (!a1) {
}
if (lastsep == ';')
print();
continue;
case 'l':
/*FALLTHROUGH*/
case 'p':
newline();
print();
continue;
case 'P':
setnoaddr();
}
continue;
case 'Q':
/*FALLTHROUGH*/
case 'q':
setnoaddr();
newline();
quit(0);
continue;
case 'S':
setnoaddr();
newline();
sfprintf(ed.msg, "file=\"%s\"%s%s%s prompt=\"%s\" tmp=%lu%s event=%lu version=\"%-.*s\"\n", sfstrbase(ed.buffer.file), ed.modified ? " modified" : "", ed.help ? " help" : "", ed.verbose ? " verbose" : "", sfstrbase(ed.buffer.prompt), ed.tmpoff, ed.tmpoff > BLOCK_TMP ? "[file]" : "", ed.event, strchr(s, '\n') - s, s);
continue;
case 's':
nonzero();
continue;
case 't':
move(1);
continue;
case 'u':
setnoaddr();
newline();
undo();
continue;
case 'V':
global(0, 1);
continue;
case 'v':
global(0, 0);
continue;
case 'W':
case 'w':
setwide();
n = 0;
}
filename(c);
putfile();
exfile();
if (n)
quit(0);
continue;
case 'z':
nonzero();
page();
continue;
case '=':
setwide();
squeeze(0);
newline();
continue;
case '!':
if (ed.restricted)
shell();
continue;
case '#':
setnoaddr();
continue;
case EOF:
return;
}
}
}
int
{
char* s;
else s = *argv;
error_info.id = s;
init();
for (;;)
{
for (;;) {
case 'O':
continue;
case 'S':
continue;
case 'h':
continue;
case 'o':
continue;
case 'p':
continue;
case 'q':
continue;
case 's':
continue;
case '?':
break;
case ':':
continue;
}
break;
}
break;
}
if (*argv) {
if (*(argv + 1))
}
edit();
commands();
quit(0);
exit(0);
}