#include "ex.h"
#include "ex_re.h"
static bool bigmove;
void
setdot(void)
{
setdot1();
if (bigmove)
markDOT();
}
void
setdot1(void)
{
if (addr2 == 0)
addr1 = addr2 = dot;
if (addr1 > addr2) {
notempty();
error(value(vi_TERSE) ?
gettext("Addr1 > addr2") :
gettext("First address exceeds second"));
}
}
void
setcount(void)
{
int cnt;
pastwh();
if (!isdigit(peekchar())) {
setdot();
return;
}
addr1 = addr2;
setdot();
cnt = getnum();
if (cnt <= 0)
error(value(vi_TERSE) ?
gettext("Bad count") :
gettext("Nonzero count required"));
addr2 += cnt - 1;
if (addr2 > dol)
addr2 = dol;
nonzero();
}
#ifdef XPG4
void
setcount2(void)
{
int cnt;
pastwh();
if (!isdigit(peekchar())) {
setdot();
return;
}
setdot();
cnt = getnum();
if (cnt <= 0)
error(value(vi_TERSE) ?
gettext("Bad count") :
gettext("Nonzero count required"));
addr2 = addr1 + (cnt - 1);
if (addr2 > dol)
addr2 = dol;
if (addr2 < zero) {
addr1 = addr2 = zero;
}
nonzero();
}
#endif
int
getnum(void)
{
int cnt;
for (cnt = 0; isdigit(peekcd());)
cnt = cnt * 10 + getchar() - '0';
return (cnt);
}
void
setall(void)
{
if (addr2 == 0) {
addr1 = one;
addr2 = dol;
if (dol == zero) {
dot = zero;
return;
}
}
setdot1();
}
void
setnoaddr(void)
{
if (addr2 != 0)
error(value(vi_TERSE) ?
gettext("No address allowed") :
gettext("No address allowed on this command"));
}
line *
address(inputline)
unsigned char *inputline;
{
line *addr;
int offset, c;
short lastsign;
bigmove = 0;
lastsign = 0;
offset = 0;
addr = 0;
for (;;) {
if (isdigit(peekcd())) {
if (addr == 0) {
addr = zero;
bigmove = 1;
}
loc1 = 0;
addr += offset;
offset = getnum();
if (lastsign >= 0)
addr += offset;
else
addr -= offset;
lastsign = 0;
offset = 0;
}
switch (c = getcd()) {
case '?':
case '/':
case '$':
case '\'':
case '\\':
bigmove++;
case '.':
if (addr || offset)
error(gettext("Badly formed address"));
}
offset += lastsign;
lastsign = 0;
switch (c) {
case ' ':
case '\t':
continue;
case ':':
while (peekchar() == ':')
ignchar();
continue;
case '+':
lastsign = 1;
if (addr == 0)
addr = dot;
continue;
case '^':
case '-':
lastsign = -1;
if (addr == 0)
addr = dot;
continue;
case '\\':
case '?':
case '/':
c = vi_compile(c, 1);
notempty();
savere(&scanre);
addr = dot;
if (inputline && execute(0, dot)) {
if (c == '/') {
while (loc1 <= (char *)inputline) {
if (loc1 == loc2)
loc2++;
if (!execute(1))
goto nope;
}
break;
} else if (loc1 < (char *)inputline) {
unsigned char *last;
doques:
do {
last = (unsigned char *)loc1;
if (loc1 == loc2)
loc2++;
if (!execute(1))
break;
} while (loc1 < (char *)inputline);
loc1 = (char *)last;
break;
}
}
nope:
for (;;) {
if (c == '/') {
addr++;
if (addr > dol) {
if (value(vi_WRAPSCAN) == 0)
error(value(vi_TERSE) ?
gettext("No match to BOTTOM") :
gettext("Address search hit BOTTOM without matching pattern"));
addr = zero;
}
} else {
addr--;
if (addr < zero) {
if (value(vi_WRAPSCAN) == 0)
error(value(vi_TERSE) ?
gettext("No match to TOP") :
gettext("Address search hit TOP without matching pattern"));
addr = dol;
}
}
if (execute(0, addr)) {
if (inputline && c == '?') {
inputline = &linebuf[LBSIZE];
goto doques;
}
break;
}
if (addr == dot)
error(value(vi_TERSE) ?
gettext("Fail") :
gettext("Pattern not found"));
}
continue;
case '$':
addr = dol;
continue;
case '.':
addr = dot;
continue;
case '\'':
c = markreg(getchar());
if (c == 0)
error(gettext("Marks are ' and a-z"));
addr = getmark(c);
if (addr == 0)
error(value(vi_TERSE) ?
gettext("Undefined mark") :
gettext("Undefined mark referenced"));
break;
default:
ungetchar(c);
if (offset) {
if (addr == 0)
addr = dot;
addr += offset;
loc1 = 0;
}
if (addr == 0) {
bigmove = 0;
return (0);
}
if (addr != zero)
notempty();
addr += lastsign;
if (addr < zero)
error(value(vi_TERSE) ?
gettext("Negative address") :
gettext("Negative address - "
"first buffer line is 1"));
if (addr > dol)
error(value(vi_TERSE) ?
gettext("Not that many lines") :
gettext("Not that many lines in buffer"));
return (addr);
}
}
}
void
setCNL(void)
{
setcount();
donewline();
}
void
setNAEOL(void)
{
setnoaddr();
eol();
}