|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 10429 (0x28bd)
Types: TextFile
Notes: UNIX file
Names: »ed3.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/ed/ed3.c«
/*
* An editor.
* Regular expressions and the substitute and global commands.
*/
#include <stdio.h>
#include <ctype.h>
#include "ed.h"
/*
* Global command.
*/
global(a1, a2, not)
{
register int a, c;
register char *gp;
if (a1>a2 || a1<1 || a2>doladd) {
derror("Address out of range");
return (0);
}
if (gcp != NULL) {
derror("Global inside global not allowed");
return (0);
}
if ((c=getx()) == '\n') {
ungetx(c);
derror("Syntax error");
return (0);
}
if (compile(c) == 0)
return;
gp = globbuf;
while ((c=getx()) != '\n') {
if (gp >= &globbuf[GBSIZE-3]) {
derror("Global buffer overflow");
return (0);
}
if (c == '\\')
if ((c=getx())!='\n' && c!='\\')
*gp++ = '\\';
*gp++ = c;
}
if (gp == globbuf)
goto out;
*gp++ = '\n';
*gp = '\0';
for (a=a1; a<=a2; a++) {
if (intflag)
goto out;
if (execute(a) != not)
line[a] |= 1;
}
a = 1;
while (a <= doladd) {
if (intflag)
goto out;
if ((line[a]&1) == 0) {
a++;
continue;
}
--line[a];
dotadd = a;
gcp = globbuf;
while (*gcp != '\0')
if (command() == 0)
goto out;
a = 1;
}
out:
for (a=1; a<=doladd; a++)
line[a] &= ~1;
gcp = NULL;
ungetx('\n');
return (1);
}
/*
* Substitute part 1.
* Check that address range is legal and parse substitute command.
*/
subs1(a1, a2)
{
register int ec, c;
register char *sp;
if (a1>a2 || a1<1 || a2>doladd) {
derror("Address out of range");
return (0);
}
subnewl = 0;
subnths = 1;
if (isascii(c=getx()) && isdigit(c)) {
subnths = 0;
while (isascii(c) && isdigit(c)) {
subnths = subnths*10 + c-'0';
c = getx();
}
}
if ((ec=c) == '\n') {
ungetx(c);
derror("Syntax error");
return (0);
}
if (compile(ec) == 0)
return (0);
sp = subsbuf;
while ((c=getx()) != ec) {
if (sp >= &subsbuf[SBSIZE-4]) {
derror("Temporary buffer overflow");
return (0);
}
switch (c) {
case '\n':
ungetx(c);
derror("Syntax error");
return (0);
case '&':
*sp++ = '\\';
*sp++ = '0';
continue;
case '\\':
if ((c=getx()) == '\\') {
*sp++ = '\\';
*sp++ = '\\';
continue;
}
if (c >= '1' && c <= '9') {
*sp++ = '\\';
*sp++ = c;
continue;
}
if (c == '\n')
subnewl++;
default:
*sp++ = c;
continue;
}
}
*sp++ = '\0';
if ((c=getx()) == 'g')
subnths = 0;
else
ungetx(c);
return (1);
}
/*
* Substitute (part 2).
* Execute substitute command.
*/
subs2(a1, a2)
{
long seek, mark;
int len, nth, err, a;
char *mp, *sp;
register int n;
register char *lp, *rp;
err = 1;
for (a=a1; a<=a2; a++) {
if (intflag)
return (1);
if (getline(a, tempbuf) == 0)
return (0);
for (n=0; n<1+BRSIZE; n++) {
brace[n].b_bp = NULL;
brace[n].b_ep = NULL;
}
brace[0].b_ep = tempbuf;
mp = tempbuf;
lp = linebuf;
nth = 0;
for (;;) {
rp = codebuf;
if (*rp == CSSOL) {
if (mp != tempbuf)
break;
rp++;
}
if ((rp=match(mp, rp)) == NULL) {
if (*mp++ == '\0')
break;
continue;
}
nth++;
if (subnths) {
if (nth < subnths) {
mp = rp;
continue;
}
if (nth > subnths)
goto done;
}
err = 0;
saved = 0;
dotadd = a;
brace[0].b_bp = mp;
mp = rp;
rp = brace[0].b_ep;
brace[0].b_ep = mp;
len = mp - brace[0].b_bp;
n = brace[0].b_bp - rp;
if (lp+n >= &linebuf[LBSIZE-1])
goto ovf;
while (n--)
*lp++ = *rp++;
sp = subsbuf;
while (*sp) {
if (lp >= &linebuf[LBSIZE-4])
goto ovf;
if (*sp != '\\') {
*lp++ = *sp++;
continue;
}
if (*++sp == '\\') {
*lp++ = *sp++;
continue;
}
n = *sp++ - '0';
if ((rp=brace[n].b_bp) == NULL)
continue;
n = brace[n].b_ep-rp;
if (lp+n >= &linebuf[LBSIZE-4])
goto ovf;
while (n--)
*lp++ = *rp++;
}
if (*mp == '\0')
break;
if (len == 0)
mp++;
if (subnths!=0 && nth==subnths)
break;
}
done:
if (dotadd != a)
continue;
rp = brace[0].b_ep;
while (*rp) {
if (lp >= &linebuf[LBSIZE-1])
goto ovf;
*lp++ = *rp++;
}
*lp++ = '\0';
seek = linead();
if (subnewl) {
lp = linebuf;
while (*lp != '\n')
lp++;
*lp++ = '\0';
}
if (putline(linebuf, lp-linebuf) == 0)
return (0);
suborig = line[a];
if (suborig&1)
--suborig;
subseek = seek|1;
line[a] = seek;
mark = suborig|1;
for (n=0; n<MKSIZE; n++)
if (marklin[n] == mark)
marklin[n] = subseek;
if (subnewl != 0) {
n = 1;
do {
mp = lp;
while (*lp!='\n' && *lp!='\0')
lp++;
if (*lp == '\0')
n = 0;
*lp++ = '\0';
seek = linead();
if (putline(mp, lp-mp) == 0)
return (0);
if (expand(a) == 0)
return (0);
line[++a] = seek;
dotadd = a;
a2++;
} while (n);
}
}
if (err!=0 && gcp==NULL) {
derror("Pattern not matched");
return (0);
}
return (1);
ovf:
derror("Temporary buffer overflow");
return (0);
}
/*
* Compile a regular expression. `ec' is the character upon which
* the regular expression ends. If an error is encountered, the
* pattern is restored and input characters are thrown away until
* a new line is found.
*/
compile(ec)
{
int bstack[BRSIZE], bcount, blevel, n;
register int c;
register char *cp, *lcp;
bcopy(tempbuf, codebuf);
bcount = 1;
blevel = 0;
cp = &codebuf[0];
if ((c=getx()) == ec) {
if (*cp == CSNUL) {
derror("No saved pattern");
goto err;
}
return (1);
}
if (c == '^') {
*cp++ = CSSOL;
c = getx();
}
while (c != ec) {
if (c == '\n') {
goto nwl;
}
if (cp > &codebuf[CBSIZE-4])
goto ovf;
switch (c) {
case '*':
goto syn;
case '.':
if ((c=getx()) != '*') {
*cp++ = CSDOT;
continue;
}
*cp++ = CMDOT;
c = getx();
continue;
case '$':
if ((c=getx()) != ec) {
ungetx(c);
c = '$';
goto character;
}
*cp++ = CSEOL;
continue;
case '[':
lcp = cp;
if ((c=getx()) == '^')
*cp++ = CSNCL;
else {
ungetx(c);
*cp++ = CSCCL;
}
*cp++ = 0;
if ((c=getx()) == ']')
*cp++ = c;
else
ungetx(c);
while ((c=getx()) != ']') {
if (c == '\n')
goto nwl;
if (c!='-' || cp==lcp+2) {
if (cp >= &codebuf[CBSIZE-4])
goto ovf;
*cp++ = c;
if (sflag && isascii(c) && isallet(c))
*cp++ = toother(c);
continue;
}
if ((c=getx()) == '\n')
goto nwl;
if (c == ']') {
*cp++ = '-';
ungetx(c);
continue;
}
if ((n=cp[-1]) > c)
goto syn;
while (++n <= c) {
if (cp >= &codebuf[CBSIZE-4])
goto ovf;
*cp++ = n;
if (sflag && isascii(c) && isallet(c))
*cp++ = toother(c);
}
}
if ((c=getx()) == '*') {
(*lcp)++;
c = getx();
}
if ((n=cp-(lcp+2)) > 255) {
derror("Character class too large");
goto err;
}
*++lcp = n;
continue;
case '\\':
switch (c=getx()) {
case '\n':
goto nwl;
case '(':
if (bcount > BRSIZE) {
derror("Too many \\(");
goto err;
}
*cp++ = CSOPR;
*cp++ = bstack[blevel++] = bcount++;
c = getx();
continue;
case ')':
if (blevel == 0)
goto syn;
*cp++ = CSCPR;
*cp++ = bstack[--blevel];
c = getx();
continue;
default:
if (isascii(c) && isdigit(c)) {
*cp++ = CSBRN;
*cp++ = c-'0';
c = getx();
continue;
}
}
default:
character:
if (sflag && isascii(c) && isallet(c)) {
*cp++ = CSSCC;
if (isupper(c))
c = tolower(c);
} else
*cp++ = CSCHR;
*cp++ = c;
if ((c=getx()) == '*') {
cp[-2]++;
c = getx();
}
}
}
*cp++ = CSNUL;
return (1);
ovf:
derror("Code buffer overflow");
bcopy(codebuf, tempbuf);
return (0);
nwl:
ungetx(c);
syn:
derror("Syntax error");
err:
bcopy(codebuf, tempbuf);
return (0);
}
/*
* Copy BSIZE buffer into dest from source
*/
bcopy(dest, source)
register char *dest;
register char *source;
{
register int n;
n = CBSIZE;
do
*dest++ = *source++;
while (--n > 0);
}
/*
* Return 1 if the compiled expression in `codebuf' matches the line in
* `linebuf', else 0.
*/
execute(a)
{
register int i;
register char *lp, *ep;
if (getline(a, linebuf) == 0)
return (0);
for (i=0; i<1+BRSIZE; i++) {
brace[i].b_bp = NULL;
brace[i].b_ep = NULL;
}
if (codebuf[0] == CSSOL)
ep = match(lp=linebuf, &codebuf[1]);
else {
ep = NULL;
lp = linebuf;
do {
if (ep=match(lp, codebuf))
break;
} while (*lp++);
}
if (ep) {
brace[0].b_bp = lp;
brace[0].b_ep = ep;
}
return (ep ? 1 : 0);
}
/*
* Given a pointer to a compiled expression, `cp', and a pointer to
* a line, `lp', return 1 if the expression matches, else 0.
*/
char *
match(lp, cp)
register char *lp, *cp;
{
register int n;
char *llp, *lcp;
for (;;) {
switch (*cp++) {
case CSNUL:
return (lp);
case CSEOL:
if (*lp)
return (NULL);
return (lp);
case CSOPR:
brace[*cp++].b_bp = lp;
continue;
case CSCPR:
brace[*cp++].b_ep = lp;
continue;
case CSBRN:
n = *cp++;
lcp = cp;
cp = brace[n].b_bp;
n = brace[n].b_ep - cp;
if (n > LBSIZE)
return (NULL);
while (n-- > 0)
if (*lp++ != *cp++)
return (NULL);
cp = lcp;
continue;
case CSDOT:
if (*lp++ == '\0')
return (NULL);
continue;
case CMDOT:
llp = lp;
while (*lp)
lp++;
goto star;
case CSCHR:
if (*cp++ != *lp++)
return (NULL);
continue;
case CMCHR:
llp = lp;
while (*cp == *lp)
lp++;
cp++;
goto star;
case CSSCC:
if (*cp++ == tolower(*lp++))
continue;
return (NULL);
case CMSCC:
llp = lp;
while (*cp == tolower(*lp++))
;
cp++;
goto star;
case CSCCL:
n = *cp++;
while (*cp++ != *lp)
if (--n == 0)
return (NULL);
lp++;
cp += n-1;
continue;
case CMCCL:
llp = lp;
lcp = cp;
while (*lp) {
cp = lcp;
n = *cp++;
while (*cp++ != *lp)
if (--n == 0)
goto star;
lp++;
}
cp = lcp + *lcp + 1;
goto star;
case CSNCL:
if (*lp == '\0')
return (NULL);
n = *cp++;
while (n--)
if (*cp++ == *lp)
return (NULL);
lp++;
continue;
case CMNCL:
llp = lp;
lcp = cp;
while (*lp) {
cp = lcp;
n = *cp++;
while (n--) {
if (*cp++ == *lp) {
cp = lcp + *lcp + 1;
goto star;
}
}
lp++;
}
cp = lcp + *lcp + 1;
star:
do {
if (lcp=match(lp, cp))
return (lcp);
} while (--lp >= llp);
return (NULL);
}
}
}