#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
extern int getchar(void);
bool pflag, nflag;
int poffset;
#define nochng() lchng = chng
extern unsigned char *Version;
void
commands(noprompt, exitoneof)
bool noprompt, exitoneof;
{
line *addr;
int c;
int lchng;
int given;
int seensemi;
int cnt;
bool hadpr;
bool gotfile;
#ifdef XPG4
int d;
#endif
unsigned char *vgetpass();
resetflav();
nochng();
for (;;) {
if (!firstpat)
laste = 0;
if (dot <= zero) {
dot = zero;
if (dol > zero)
dot = one;
}
shudclob = 0;
if ((pflag || lchng != chng && value(vi_AUTOPRINT) &&
!inglobal && !inopen && endline) || poffset != 0) {
pflag = 0;
nochng();
if (dol != zero) {
addr1 = addr2 = dot + poffset;
poffset = 0;
if (addr1 < one || addr1 > dol)
error(value(vi_TERSE) ?
gettext("Offset out-of-bounds") :
gettext("Offset after command "
"too large"));
dot = addr1;
setdot1();
goto print;
}
}
nochng();
if (inglobal == 0) {
flush();
if (!hush && value(vi_PROMPT) && !globp &&
!noprompt && endline) {
putchar(':');
hadpr = 1;
}
TSYNC();
}
addr2 = 0;
given = seensemi = 0;
do {
addr1 = addr2;
addr = address(0);
c = getcd();
if (addr == 0) {
if (c == ',' || c == ';')
addr = dot;
else if (addr1 != 0) {
addr2 = dot;
break;
} else
break;
}
addr2 = addr;
given++;
if (c == ';') {
c = ',';
dot = addr;
seensemi = 1;
}
} while (c == ',');
if (c == '%') {
addr1 = one;
addr2 = dol;
given = 2;
c = getchar();
}
if (addr1 == 0)
addr1 = addr2;
while (c == ':')
c = getchar();
tailspec(c);
if (inopen) {
if (c == '\n' || c == '\r' ||
c == CTRL('d') || c == EOF) {
if (addr2)
dot = addr2;
if (c == EOF)
return;
continue;
}
if (any(c, "o"))
notinvis:
tailprim(Command, 1, 1);
}
switch (c) {
case 'a':
switch (peekchar()) {
case 'b':
tail("abbreviate");
setnoaddr();
mapcmd(0, 1);
anyabbrs = 1;
continue;
case 'r':
tail("args");
setnoaddr();
eol();
pargs();
continue;
}
if (inopen)
goto notinvis;
tail("append");
setdot();
aiflag = exclam();
donewline();
vmacchng(0);
deletenone();
setin(addr2);
inappend = 1;
(void) append(gettty, addr2);
inappend = 0;
nochng();
continue;
case 'c':
switch (peekchar()) {
case 'o':
tail("copy");
vmacchng(0);
vi_move();
continue;
case 'r':
tail("crypt");
crflag = -1;
ent_crypt:
setnoaddr();
xflag = 1;
if (permflag)
(void) crypt_close(perm);
permflag = 1;
if ((kflag = run_setkey(perm,
(key = vgetpass(
gettext("Enter key:"))))) == -1) {
xflag = 0;
kflag = 0;
crflag = 0;
smerror(gettext("Encryption facility "
"not available\n"));
}
if (kflag == 0)
crflag = 0;
continue;
case 'd':
tail("cd");
goto changdir;
case 'h':
ignchar();
if (peekchar() == 'd') {
unsigned char *p;
tail2of("chdir");
changdir:
if (savedfile[0] == '/' ||
!value(vi_WARN))
(void) exclam();
else
(void) quickly();
if (skipend()) {
p = (unsigned char *)
getenv("HOME");
if (p == NULL)
error(gettext(
"Home directory"
" unknown"));
} else
getone(), p = file;
eol();
if (chdir((char *)p) < 0)
filioerr(p);
if (savedfile[0] != '/')
edited = 0;
continue;
}
if (inopen)
tailprim((unsigned char *)"change",
2, 1);
tail2of("change");
break;
default:
if (inopen)
goto notinvis;
tail("change");
break;
}
aiflag = exclam();
#ifdef XPG4ONLY
setcount2();
donewline();
#else
setCNL();
#endif
vmacchng(0);
setin(addr1);
(void) delete(0);
inappend = 1;
if (append(gettty, addr1 - 1) == 0) {
#ifdef XPG4
dot = addr1 - 1;
#else
dot = addr1;
#endif
if (dot > dol)
dot = dol;
}
inappend = 0;
nochng();
continue;
case 'd':
tail("delete");
c = cmdreg();
#ifdef XPG4ONLY
setcount2();
donewline();
#else
setCNL();
#endif
vmacchng(0);
if (c)
(void) YANKreg(c);
(void) delete(0);
appendnone();
continue;
case 'e':
if (crflag == 2 || crflag == -2)
crflag = -1;
tail(peekchar() == 'x' ? "ex" : "edit");
editcmd:
if (!exclam() && chng)
c = 'E';
gotfile = 0;
if (c == 'E') {
if (inopen && !value(vi_AUTOWRITE)) {
filename(c);
gotfile = 1;
}
ungetchar(lastchar());
if (!exclam()) {
ckaw();
if (chng && dol > zero) {
xchng = 0;
error(value(vi_TERSE) ?
gettext("No write") :
gettext("No write since "
"last change (:%s! "
"overrides)"),
Command);
}
}
}
if (gotfile == 0)
filename(c);
setnoaddr();
doecmd:
init();
addr2 = zero;
laste++;
sync();
rop(c);
nochng();
continue;
case 'f':
tail("file");
setnoaddr();
filename(c);
noonl();
continue;
case 'g':
tail("global");
global(!exclam());
nochng();
continue;
case 'i':
if (inopen)
goto notinvis;
tail("insert");
setdot();
nonzero();
aiflag = exclam();
donewline();
vmacchng(0);
deletenone();
setin(addr2);
inappend = 1;
(void) append(gettty, addr2 - 1);
inappend = 0;
if (dot == zero && dol > zero)
dot = one;
nochng();
continue;
case 'j':
tail("join");
c = exclam();
setcount();
nonzero();
donewline();
vmacchng(0);
#ifdef XPG4ONLY
if (given < 2 && (addr1 == addr2) && (addr2 != dol))
addr2++;
#else
if (given < 2 && addr2 != dol)
addr2++;
#endif
(void) join(c);
continue;
case 'k':
casek:
pastwh();
c = getchar();
if (endcmd(c))
serror((vi_TERSE) ?
(unsigned char *)gettext("Mark what?") :
(unsigned char *)
gettext("%s requires following "
"letter"), Command);
donewline();
if (!islower(c))
error((vi_TERSE) ? gettext("Bad mark") :
gettext("Mark must specify a letter"));
setdot();
nonzero();
names[c - 'a'] = *addr2 &~ 01;
anymarks = 1;
continue;
case 'l':
tail("list");
#ifdef XPG4ONLY
setcount2();
donewline();
#else
setCNL();
#endif
(void) setlist(1);
pflag = 0;
goto print;
case 'm':
if (peekchar() == 'a') {
ignchar();
if (peekchar() == 'p') {
tail2of("map");
setnoaddr();
mapcmd(0, 0);
continue;
}
tail2of("mark");
goto casek;
}
tail("move");
vmacchng(0);
vi_move();
continue;
case 'n':
if (peekchar() == 'u') {
tail("number");
goto numberit;
}
tail("next");
setnoaddr();
if (!exclam()) {
ckaw();
if (chng && dol > zero) {
xchng = 0;
error(value(vi_TERSE) ?
gettext("No write") :
gettext("No write since last "
"change (:%s! overrides)"),
Command);
}
}
if (getargs())
makargs();
next();
c = 'e';
filename(c);
goto doecmd;
case 'o':
tail("open");
oop();
pflag = 0;
nochng();
continue;
case 'p':
case 'P':
switch (peekchar()) {
#ifdef TAG_STACK
case 'o':
tail("pop");
poptag(exclam());
if (!inopen)
lchng = chng - 1;
else
nochng();
continue;
#endif
case 'u':
tail("put");
setdot();
c = cmdreg();
eol();
vmacchng(0);
if (c)
(void) putreg(c);
else
(void) put();
continue;
case 'r':
ignchar();
if (peekchar() == 'e') {
tail2of("preserve");
eol();
if (preserve() == 0)
error(gettext(
"Preserve failed!"));
else {
#ifdef XPG4
noerror(
gettext("File preserved."));
#else
error(
gettext("File preserved."));
#endif
}
}
tail2of("print");
break;
default:
tail("print");
break;
}
setCNL();
pflag = 0;
print:
nonzero();
if (clear_screen && span() > lines) {
flush1();
vclear();
}
if (poffset == 0)
plines(addr1, addr2, 1);
else
dot = addr2;
continue;
case 'q':
tail("quit");
setnoaddr();
c = quickly();
eol();
if (!c)
quit:
if (nomore())
continue;
if (inopen) {
vgoto(WECHO, 0);
if (!ateopr())
vnfl();
else {
tostop();
}
flush();
setty(normf);
ixlatctl(1);
}
cleanup(1);
exit(errcnt);
case 'r':
if (peekchar() == 'e') {
ignchar();
switch (peekchar()) {
case 'w':
tail2of("rewind");
setnoaddr();
if (!exclam()) {
ckaw();
if (chng && dol > zero)
error((vi_TERSE) ?
gettext("No write") :
gettext("No write "
"since last "
"change (:rewi"
"nd! overrides)"));
}
eol();
erewind();
next();
c = 'e';
ungetchar(lastchar());
filename(c);
goto doecmd;
case 'c':
tail2of("recover");
setnoaddr();
c = 'e';
if (!exclam() && chng)
c = 'E';
filename(c);
if (c == 'E') {
ungetchar(lastchar());
(void) quickly();
}
init();
addr2 = zero;
laste++;
sync();
recover();
rop2();
revocer();
if (status == 0)
rop3(c);
if (dol != zero)
change();
nochng();
continue;
}
tail2of("read");
} else
tail("read");
if (crflag == 2 || crflag == -2)
crflag = -1;
if (savedfile[0] == 0 && dol == zero)
c = 'e';
pastwh();
vmacchng(0);
if (peekchar() == '!') {
setdot();
ignchar();
unix0(0, 1);
(void) vi_filter(0);
continue;
}
filename(c);
rop(c);
nochng();
if (inopen && endline && addr1 > zero && addr1 < dol)
dot = addr1 + 1;
continue;
case 's':
switch (peekchar()) {
case 'e':
tail("set");
setnoaddr();
set();
continue;
case 'h':
tail("shell");
setNAEOL();
vnfl();
putpad((unsigned char *)exit_ca_mode);
flush();
resetterm();
unixwt(1, unixex("-i", (char *)0, 0, 0));
vcontin(0);
continue;
case 'o':
#ifdef notdef
if (inopen)
goto notinvis;
#endif
tail("source");
setnoaddr();
getone();
eol();
source(file, 0);
continue;
#ifdef SIGTSTP
case 't':
tail("stop");
goto suspend;
case 'u':
#ifdef XPG4
switch (d = peekchar()) {
case 's':
case '!':
#endif
tail("suspend");
suspend:
c = exclam();
eol();
if (!c)
ckaw();
onsusp(0);
continue;
#ifdef XPG4
}
#endif
#endif
}
case '&':
case '~':
Command = (unsigned char *)"substitute";
if (c == 's')
tail(Command);
vmacchng(0);
if (!substitute(c))
pflag = 0;
continue;
case 't':
if (peekchar() == 'a') {
tagflg = 1;
tail("tag");
tagfind(exclam());
tagflg = 0;
if (!inopen)
lchng = chng - 1;
else
nochng();
continue;
}
tail("t");
vmacchng(0);
vi_move();
continue;
case 'u':
if (peekchar() == 'n') {
ignchar();
switch (peekchar()) {
case 'm':
tail2of("unmap");
setnoaddr();
mapcmd(1, 0);
continue;
case 'a':
tail2of("unabbreviate");
setnoaddr();
mapcmd(1, 1);
anyabbrs = 1;
continue;
}
tail2of("undo");
} else
tail("undo");
setnoaddr();
markDOT();
c = exclam();
donewline();
undo(c);
continue;
case 'v':
switch (peekchar()) {
case 'e':
tail("version");
setNAEOL();
viprintf("%s", Version);
noonl();
continue;
case 'i':
tail("visual");
if (inopen) {
c = 'e';
goto editcmd;
}
vop();
pflag = 0;
nochng();
continue;
}
tail("v");
global(0);
nochng();
continue;
case 'w':
c = peekchar();
tail(c == 'q' ? "wq" : "write");
wq:
if (skipwh() && peekchar() == '!') {
pofix();
ignchar();
setall();
unix0(0, 1);
(void) vi_filter(1);
} else {
setall();
if (c == 'q')
write_quit = 1;
else
write_quit = 0;
wop(1);
nochng();
}
if (c == 'q')
goto quit;
continue;
case 'X':
crflag = -1;
goto ent_crypt;
case 'C':
crflag = 1;
goto ent_crypt;
case 'x':
tail("xit");
if (!chng)
goto quit;
c = 'q';
goto wq;
case 'y':
tail("yank");
c = cmdreg();
#ifdef XPG4ONLY
setcount2();
#else
setcount();
#endif
eol();
vmacchng(0);
if (c)
(void) YANKreg(c);
else
(void) yank();
continue;
case 'z':
zop(0);
pflag = 0;
continue;
case '*':
case '@':
c = getchar();
if (c == '\n' || c == '\r')
ungetchar(c);
if (any(c, "@*\n\r"))
c = lastmac;
if (isupper(c))
c = tolower(c);
if (!islower(c))
error(gettext("Bad register"));
donewline();
setdot();
cmdmac(c);
continue;
case '|':
endline = 0;
goto caseline;
case '\n':
endline = 1;
caseline:
notempty();
if (addr2 == 0) {
if (cursor_up != NOSTR && c == '\n' &&
!inglobal)
c = CTRL('k');
if (inglobal)
addr1 = addr2 = dot;
else {
if (dot == dol)
error((vi_TERSE) ?
gettext("At EOF") :
gettext("At end-of-file"));
addr1 = addr2 = dot + 1;
}
}
setdot();
nonzero();
if (seensemi)
addr1 = addr2;
getaline(*addr1);
if (c == CTRL('k')) {
flush1();
destline--;
if (hadpr)
shudclob = 1;
}
plines(addr1, addr2, 1);
continue;
case '"':
comment();
continue;
case '#':
numberit:
setCNL();
(void) setnumb(1);
pflag = 0;
goto print;
case '=':
donewline();
setall();
if (inglobal == 2)
pofix();
viprintf("%d", lineno(addr2));
noonl();
continue;
case '!':
if (addr2 != 0) {
vmacchng(0);
unix0(0, 1);
setdot();
(void) vi_filter(2);
} else {
unix0(1, 1);
pofix();
putpad((unsigned char *)exit_ca_mode);
flush();
resetterm();
if (!tagflg) {
unixwt(1, unixex("-c", uxb, 0, 0));
} else {
error(gettext("Invalid tags file:"
" contains shell escape"));
}
vclrech(1);
nochng();
}
continue;
case '<':
case '>':
for (cnt = 1; peekchar() == c; cnt++)
ignchar();
setCNL();
vmacchng(0);
shift(c, cnt);
continue;
case CTRL('d'):
case EOF:
if (exitoneof) {
if (addr2 != 0)
dot = addr2;
return;
}
if (!isatty(0)) {
if (intty)
onhup(0);
return;
}
if (addr2 != 0) {
setlastchar('\n');
putnl();
}
if (dol == zero) {
if (addr2 == 0)
putnl();
notempty();
}
ungetchar(EOF);
zop(hadpr);
continue;
default:
if (!isalpha(c) || !isascii(c))
break;
ungetchar(c);
tailprim((unsigned char *)"", 0, 0);
}
ungetchar(c);
{
int length;
char multic[MULTI_BYTE_MAX];
wchar_t wchar;
length = _mbftowc(multic, &wchar, getchar, &peekc);
if (length < 0)
length = -length;
multic[length] = '\0';
error((vi_TERSE) ? gettext("What?") :
gettext("Unknown command character '%s'"),
multic);
}
}
}