1
0
mirror of synced 2026-04-19 00:17:23 +00:00

QED for Unix, from 1985

This commit is contained in:
Arnold D. Robbins
1985-04-16 21:25:23 +00:00
parent 6f656f99fe
commit a65d3754f1
26 changed files with 5934 additions and 0 deletions

19
unix-1985/L.q Normal file
View File

@@ -0,0 +1,19 @@
" Left justify addressed lines (default to (1,$))
" (Terminating blanks are appended to bring all lines out to same width)
zL#=\zM yf'fi
1,$zL#r
"fi
\zL,\zMs/^[ ]*//
\zL,\zMs/[ ]*$//
zW:0
\zL,\zM g/^/ zI#n<\czW yt zW:\czI
zW#>35 yf zW:35
zD: |
zD)\zW
\zL,\zM s/$/\zD/
" Turn spaces into periods
zD+14
\zL,\zM s/^\(\zD\) *$/\1/
zD-14
\zL,\zM s/\zD$//
zL)0 zM)0 zI)0 zD)0 zW)0

18
unix-1985/R.q Normal file
View File

@@ -0,0 +1,18 @@
" Right justify addressed lines (default to (1,$))
zL#=\zM yf'fi
1,$zL#r
"fi
\zL,\zMs/^[ ]*//
\zL,\zMs/[ ]*$//
zW:0
\zL,\zM g/^/ zI#n<\czW yt zW:\czI
zW#>35 yf zW:35
zD: |
zD)\zW
\zL,\zM s/^/\zD/
" Turn spaces into periods
zD+14
\zL,\zM s/^ *\(\zD\)$/\1/
zD-14
\zL,\zM s/^\zD//
zL)0 zM)0 zI)0 zD)0 zW)0

82
unix-1985/address.c Normal file
View File

@@ -0,0 +1,82 @@
/*% cc -c -O %
*/
#include "vars.h"
int *
address()
{
register int sign, *a;
int opcnt, nextopand, *b;
register c;
nextopand = -1;
sign = 1;
opcnt = 0;
a = dot;
do {
do c = getchar(); while (c==' ' || c=='\t');
if ('0'<=c && c<='9') {
peekc = c;
if (!opcnt)
a = zero;
a += sign*getnum();
} else switch (c) {
case '$':
a = dol;
/* fall through */
case '.':
if (opcnt)
error('a');
break;
case '\'':
c = getchar();
if (opcnt)
error('a');
if(posn(c, bname)<0)
error('k');
a = zero;
c = posn(c, bname); /* outside loop for efficiency */
do a++; while (a<=dol && names[c]!=(*a|01));
break;
case '?':
sign = -sign;
/* fall through */
case '/':
compile(c);
b = a;
for (;;) {
a += sign;
if (a<zero)
a = dol;
if (a>dol)
a = zero;
if (execute(a))
break;
if (a==b)
error('/');
}
break;
default:
if (nextopand == opcnt) {
a += sign;
if (a<zero || dol<a)
continue; /* error('$'); */
}
if (c!='+' && c!='-' && c!='^') {
peekc = c;
if (opcnt==0)
a = 0;
return (a);
}
sign = 1;
if (c!='+')
sign = -sign;
nextopand = ++opcnt;
continue;
}
sign = 1;
opcnt++;
} while (zero<=a && a<=dol);
error('$');
/*NOTREACHED*/
}

93
unix-1985/blkio.c Normal file
View File

@@ -0,0 +1,93 @@
/*% cc -c -O %
*/
#include "vars.h"
#define BLKSIZE 512
#ifdef BIGTMP
#define MAXBLOCKS 4095
#else
#define MAXBLOCKS 255
#endif
#define BLMASK MAXBLOCKS
char ibuff[512];
int iblock = -1;
int oblock = 0;
char obuff[512];
int ooff; /* offset of next byte in obuff */
initio()
{
lock++;
iblock = -1;
oblock = 0;
ooff = 0;
unlock();
}
char *getline(tl, lbuf)
int tl;
char *lbuf;
{
register char *bp, *lp;
register int nl;
extern int read();
lp = lbuf;
nl = -((tl<<1) & 0774);
tl = (tl>>8) & BLMASK;
do {
if (nl<=0) {
if (tl==oblock)
bp = obuff;
else {
bp = ibuff;
if (tl!=iblock) {
iblock = -1; /* signal protection */
blkio(tl, bp, read);
iblock = tl;
}
}
tl++;
bp -= nl;
nl += BLKSIZE;
}
nl--;
} while (*lp++ = *bp++);
return(lbuf);
}
int putline()
{
register char *op, *lp;
register int r;
extern int write();
modified();
lp = linebuf;
r = (oblock<<8) + (ooff>>1); /* ooff may be 512! */
op = obuff + ooff;
lock++;
do {
if (op >= obuff+BLKSIZE) {
/* delay updating oblock until after blkio succeeds */
blkio(oblock, op=obuff, write);
oblock++;
ooff = 0;
}
if((*op = *lp++) == '\n') {
*op++ = '\0';
linebp = lp;
break;
}
} while (*op++);
ooff = (((op-obuff)+3)&~3);
unlock();
return (r);
}
blkio(b, buf, iofcn)
char *buf;
int (*iofcn)();
{
if (b>=MAXBLOCKS
|| (lseek(tfile, ((long) b) * 512L, 0)<0L)
|| (*iofcn)(tfile, buf, 512) != 512) {
error('T');
}
}

50
unix-1985/col.q Normal file
View File

@@ -0,0 +1,50 @@
" Buffer to columnate a buffer of file names, etc.
" takes a range of lines; defaults to 1,$
zB:\B
zL#=\zM yf 1,$zL#r
bZ Z
b\zB
\zL,\zM tZ0
" Calculate the width W of the widest line
zW#:0
g/^/ zM#n>\czW yf zW#:\czM
zW#>35 yf'fi
1,$p
yo
"fi
" L = width of column; C = # of columns
zN#:70 zL#:\zW+1 zN#/\zL
" now make each line have W spaces
zA: |
zA)\zW
1,$s/$/\zA/
" Turn the spaces into periods
zA+14
1,$s/\(\zA.\).*/\1/
" C = number of columns.
" L = 1st line of join
" M = last line of join
$zM#a $zL#a/\zN*\zN+1
zL#=\zM yf'else
zM#-1 zL#-\zN
y'fi
"else
zL#>\zM yf'else
zL#-\zN
y'fi
"else
\zL,\zM j/ /
zM#:\zL-1
zL#-\zN
"fi
"do
zL#>0 yf'od
\zL,\zM j/ /
zL#-\zN
zM#-\zN
y`do
"od
1,$p
b\zB
" Clean up the variables
zA)0 zB)0 zI)0 zL)0 zM)0 zN)0 zW)0

668
unix-1985/com.c Normal file
View File

@@ -0,0 +1,668 @@
/*% cc -c -O %
*/
#include "vars.h"
#define OUT 10
#define BACKWARD 11
#define FORWARD 12
char jumpcs[] = "0123456789o`'";
jump() /* this should be pronounced with a Swedish accent */
{
register int i;
register cond;
register c;
if(stackp->type==TTY)
error('y');
c = getchar();
cond = TRUE;
if(c=='t' || c=='f'){
cond = ((c=='t') == truth());
c = getchar();
}
i = posn(c, jumpcs);
if(i==-1){ /* to handle y[tf] without labels for globals */
ungetchar(c);
if(cond){
while((c = getc())!='\n')
if(c==EOF)
return;
}
}
else if(i<=9){
stacktype(BUF);
ungetchar(c);
i = getnum();
stacktype(BUF); /* we may have popped stack! */
if(cond){
/* getchar will handle problems if off end of buffer */
bbempty = TRUE;
stackp->lineno = i;
stackp->charno = 0;
}
}
else if(i==OUT){
if(cond){
if(stackp==stack)
error('y');
if(stackp->type==GLOB){
--nestlevel;
stackp->globp = "";
}else
popinp();
}
}
else if(i==FORWARD || i==BACKWARD){
stacktype(BUF);
getlabel(); /* must eat label even if not yumping */
stacktype(BUF);
if(cond)
search(i==FORWARD);
}
}
stacktype(t)
{
if(stackp->type != t)
error('y');
}
getlabel(){
register char *p, c;
p = genbuf;
for(c=getchar(); posn(c," \"\t\n")<0; c=getchar()){
*p++ = c;
*p = '\0';
}
if(p==genbuf)
error('y');
}
int *looper(a1,a2,str,dir)
register int *a1, *a2;
register char *str;
{
register char *p1;
register char *p2;
while(dir ? a1<=a2 : a1>=a2){
p2 = getline(*a1, linebuf);
while(*p2==' ' || *p2=='\t')
p2++;
if(*p2++=='"' && *p2!=' ' && *p2!='\t' && *p2!='\0') {
for(p1=str; *p2 && (*p1 == *p2); p2++)
p1++;
if(*p1==0 && (*p2==0 || *p2==' ' || *p2=='\t'))
return(a1);
}
if(dir)
a1++;
else
--a1;
}
return((int *)0);
}
search(forward)
{
register int *a1;
struct buffer *bufp;
bufp = stackp->bufptr;
if(forward){
if((a1 = looper(bufp->zero + (stackp->lineno + 1),
bufp->dol,genbuf,1))==0){
a1 = looper(bufp->zero + 1,bufp->zero + (stackp->lineno - 1),genbuf,1);
}
}else{
if((a1 = looper(bufp->zero + (stackp->lineno - 1),
bufp->zero + 1,genbuf,0))==0){
a1 = looper(bufp->dol,bufp->zero + stackp->lineno + 1,genbuf,0);
}
}
if(a1){
stackp->lineno = a1 - bufp->zero;
stackp->charno = 0;
}
}
int pchar;
setapp()
{
register c;
c=getchar();
if(posn(c, lchars)>=0) {
pchar = c;
c = getchar();
}
if(c==' ' || c=='\t'){
oneline++;
if(c=='\t')
ungetchar(c);
}
else if(c!='\n')
error('x');
}
#define LDCHUNK 512
append(f, a)
int (*f)();
int *a;
{
register *a1, *a2, *rdot;
int nline, tl;
struct integer { int iint; };
appflag++;
nline = 0;
dot = a;
while ((*f)()==0) {
if (lastdol>=endcore) {
if (sbrk(LDCHUNK*(sizeof *endcore))==(char *)-1)
error('c');
endcore += LDCHUNK;
}
tl = putline();
nline++;
lock++;
++dol;
a1 = ++lastdol;
fixbufs(1);
a2 = a1+1;
rdot = ++dot;
while (a1 > rdot)
*--a2 = *--a1;
*rdot = tl;
unlock();
if(oneline)
break;
}
appflag=0;
oneline=0;
if(pchar) {
a1 = addr1; addr1 = dot;
a2 = addr2; addr2 = dot;
display(pchar);
pchar = 0;
addr1 = a1; addr2 = a2;
}
return(nline);
}
char bformat = 'p';
bcom()
{
register dir, n;
register psize;
register *olddot=addr2; /* for b. */
dir=1;
if((peekc=getchar())!='\n'){ /* really nextchar() */
if (peekc=='-' || peekc=='+' || peekc=='.') {
if(peekc=='-')
dir= -1;
else if(peekc=='.')
dir=0;
getchar(); /* eat peekc */
}
if((n=getnum())>0)
pagesize=n;
}
psize=pagesize;
if(dir==0)
psize/=2;
if(posn(nextchar(), lchars)>=0)
bformat=getchar();
if(dir<=0) {
if((addr1=addr2-(psize-1))<=zero)
addr1=zero+1;
if(dir==0){
display(bformat);
puts("^^^^^");
addr2++;
}
}
if (dir>=0) {
addr1=addr2;
if((addr2+=(psize-1))>dol)
addr2=dol;
}
display(bformat);
if(dir==0)
dot=olddot;
}
delete()
{
register *a1, *a2, *a3;
setdot();
a1 = addr1;
a2 = addr2;
if(a1==zero) {
if(a2!=zero)
*(a1++);
else
return; /* 0,$d on an empty buffer */
}
*(a2++);
a3 = lastdol;
lock++;
dol -= a2 - a1;
lastdol -= a2 - a1;
fixbufs(a1-a2);
do
*a1++ = *a2++;
while (a2<=a3);
a1 = addr1;
if (a1 > dol)
a1 = dol;
dot = a1;
unlock();
modified();
}
allnums()
{
register int i;
register char *p;
setdot();
for(i=0; i<NBUFS; i++){
p = string[i].str;
if(*p!='\0' && alldigs(p)){
putct(bname[i]);
puts(p);
}
}
}
numcom(z)
{
register n;
register struct string *sp;
register char *l;
char c;
int numeric;
extern char digits[]; /* defined in getchar.c = "0123456789" */
/*
* Must generate error if attempt is made to do arithmetic on
* a register which is not numeric; this is done by remembering
* (via `numeric') whether the initial string was numeric or not.
*/
sp = &string[z];
numeric = alldigs(sp->str);
n = atoi(sp->str);
for(;;){
switch(c=getchar()){
default:
goto Done;
case ':':
n=getsigned();
goto Not_numeric;
case 'a':
n=addr2-zero;
goto Not_numeric;
case 'r':
if(z+1>=NBUFS)
error('z');
n = addr1-zero;
numset(z+1, addr2-zero);
goto Not_numeric;
case 'n':
nonzero();
l = getline(*addr2,linebuf);
do; while(*l++);
n = l - linebuf - 1;
goto Not_numeric;
case 'P':
n = getpid();
Not_numeric:
numeric = TRUE; /* It's numeric now! */
break;
case 'p':
if(n<0)
putchar('-');
putdn(abs(n));
goto Numeric;
case '+':
n += getsigned();
goto Numeric;
case '-':
n -= getsigned();
goto Numeric;
case '*':
n *= getsigned();
goto Numeric;
case '/':
n /= getsigned();
goto Numeric;
case '%':
n %= getsigned();
goto Numeric;
case '!':
if(posn(c=getchar(), "=><")<0)
error('#');
settruth(condition(n, getsigned(), c, 1));
goto Numeric;
case '<':
case '>':
case '=':
settruth(condition(n, getsigned(), c, 0));
Numeric:
if(numeric == FALSE)
error('#');
break;
}
}
Done:
ungetchar(c);
numset(z, n);
}
condition(n, m, cond, negate)
register n, m, cond, negate;
{
int retval;
if(cond=='=')
retval = (n==m);
else if(cond=='<')
retval = (n<m);
else if(cond=='>')
retval = (n>m);
else
error("!");
return(negate^retval);
}
numset(z, n)
register z;
register n;
{
startstring();
numbuild(n);
setstring(z);
}
numbuild(n)
register n;
{
register i;
if(n<0){
addstring('-');
n = -n;
}
i = n/10;
if(i)
numbuild(i);
addstring(n%10+'0');
}
strcom(z)
{
register char *q;
register n;
int getchar();
register struct string *sp;
int cond, c, negate;
setdot();
sp = &string[z];
if(nextchar()=='#'){
getchar(); /* eat the '#' */
numcom(z);
return;
}
negate=FALSE;
switch(cond=getchar()){
default:
error('x');
case 'p':
puts(sp->str);
break;
case 'l':
putl(sp->str);
break;
case ':':
startstring();
for(;;){
c = getquote("\n", getchar);
if(c=='\n'){
setstring(z);
return;
}
addstring(c&0177);
}
case '\'':
startstring();
dupstring(getname('z'));
setstring(z);
break;
case '.':
nonzero();
startstring();
copystring(getline(*addr2, linebuf));
setstring(z);
break;
case '/':
nonzero();
compile('/');
if(execute(addr2)==0){
clearstring(z);
settruth(FALSE);
return;
}
q = loc1;
startstring();
while(q < loc2)
addstring(*q++);
setstring(z);
settruth(TRUE);
return;
case 's':
substitute(stackp!=&stack[0], z);
return;
case '+':
strinc(z, getsigned());
break;
case '-':
strinc(z, -getsigned());
break;
case 'n':
setcount(sp->len);
break;
case 'e':
startstring();
addstring(lasterr);
setstring(z);
break;
case '(':
n=getsigned();
if(abs(n) > sp->len)
error('[');
if(n>=0){
sp->str += n;
sp->len -= n;
}
else{
sp->str += sp->len+n;
sp->len = -n;
}
break;
case ')':
n=getsigned();
if(abs(n) > sp->len)
error('[');
if(n<0){
sp->str[sp->len+n]='\0';
sp->len += n;
} else if(n==0)
clearstring(z);
else {
sp->str[n]='\0';
sp->len=n;
}
break;
case '[':
cpstr(sp->str, linebuf);
loc2=0; /* Tell execute that it's already in linebuf */
compile(getchar());
if(execute(0)==0){
settruth(FALSE);
setcount(-1);
} else {
settruth(TRUE);
setcount(loc2-linebuf-1);
}
return;
case 'C':
startstring();
clean(z);
setstring(z);
break;
case '!':
if(posn(cond=getchar(), "=><")<0)
error('x');
negate=TRUE;
case '=':
case '<':
case '>':
settruth(FALSE);
q=sp->str;
for(;;){
c=getchar();
if(c=='\n' && *q==0){
if(cond == '=')
settruth(!negate);
return;
}
if(*q++!=c){
if(cond=='<')
settruth(negate ^ (*--q < c));
else if(cond=='>')
settruth(negate ^ (*--q > c));
while(c!='\n')
c=getchar();
return;
}
}
case '{':
q = genbuf;
while(posn(c=getchar(), "} \t\n")<0 && c!=EOF)
*q++ = c;
*q = '\0';
if((q=getenv(genbuf)) == 0)
clearstring(z);
else{
startstring();
copystring(q);
setstring(z);
}
break;
/* end of switch */
}
}
strinc(z, n)
{
register char *q;
q=string[z].str;
while(*q)
*q++ += n;
}
locn(ap, aq)
char *ap, *aq;
{
register char *p, *q, *lastq;
p=ap;
q=aq;
for(;;){
lastq=q;
while(*p==*q){
if(*p++==0 || *p==0)
return(lastq - aq);
q++;
}
if(*q==0)
return(-1);
p=ap;
q=lastq+1;
}
}
#define EMPTY (TRUE+1) /* ==> ignore this buf in G/V */
ncom(c)
{
register struct buffer *bufp;
struct buffer *stop;
register char *f, *lp;
int globflag;
setnoaddr();
syncbuf();
globflag = FALSE;
if(c == 'f')
stop = bufp = curbuf;
else{
bufp = buffer;
stop = buffer+NBUFS-1;
if(c=='G')
globflag = TRUE;
}
do{
lp = linebuf;
f = string[FILE(bufp-buffer)].str;
if(c=='N' && (!bufp->cflag || *f==0))
continue;
if(bufp->dol==bufp->zero && *f=='\0'){
if(globflag)
bufp->gmark = EMPTY;
if(globflag || bufp!=curbuf)
continue;
}
*lp++ = bname[bufp-buffer];
*lp++ = (bufp->cflag) ? '\'' : ' ';
*lp++ = (bufp==curbuf) ? '.' : ' ';
numset(FILEBUF, bufp->dol-bufp->zero);
cpstr(string[FILEBUF].str, lp);
lp += string[FILEBUF].len;
f = string[FILE(bufp-buffer)].str; /* in case strings got g.c.'d */
if(*f)
*lp++ = '\t';
if(globflag){
cpstr(f, lp);
loc2 = 0; /* ==> we are about to search for 1st time */
bufp->gmark = execute((int *)0);
} else {
*lp = '\0';
lp = linebuf;
while(*lp)
putchar(*lp++);
putl(f);
}
}while(bufp++!=stop);
}
allstrs()
{
register int i;
char *p;
setdot();
for(i=0; i<NBUFS; i++){
p=string[i].str;
if(*p!=0){
putct(bname[i]);
putl(p);
}
}
putct('P');
putl(string[SAVPAT].str);
putct('R');
putl(string[SAVRHS].str);
if(*string[BROWSE].str) {
putct('B');
putl(string[BROWSE].str);
}
}
/*
* clean (string) to support zaC
* strips leading and trailing white space from a string
* and replaces interior white space by single blanks
*/
clean(z) {
register char *s;
register char *d;
register char c;
d = genbuf;
for (s = string[z].str; (c = *s) == ' ' || c == '\t'; s++);
while (c = *s++) {
if (c == ' ' || c == '\t') {
*d++ = ' ';
while(*s == ' ' || *s == '\t')
s++;
} else {
*d++ = c;
}
}
while (d > genbuf && d[-1] == ' ')
--d;
*d = 0;
copystring(genbuf);
}

378
unix-1985/getchar.c Normal file
View File

@@ -0,0 +1,378 @@
/*% cc -c -O %
*/
#include "vars.h"
char digits[] = "0123456789"; /* getnum() & atoi() work even on non-ASCII systems */
getnum()
{
register n, i;
n=0;
while((i=posn(nextchar(), digits)) >= 0){
getchar();
n = n*10 + i;
}
return(n);
}
getsigned(){
register sign;
if(nextchar()=='-'){
getchar();
sign = -1;
}
else
sign = 1;
return(getnum()*sign);
}
atoi(s)
register char *s;
{
register n, i;
int sign;
n = 0;
sign = 1;
if(*s == '-'){
sign = -1;
s++;
}
while(*s){
i = posn(*s++, digits);
if(i < 0)
return(sign*n); /* error handling done elsewhere */
n = n*10 + i;
}
return(sign*n);
}
alldigs(s)
register char *s;
{
if(*s == '-')
s++;
while(*s)
if(posn(*s++, digits) < 0)
return(FALSE);
return(TRUE);
}
char bname[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~";
getname(e)
{
int getc();
return(getnm(e, getc));
}
getaz(e)
{
int getchar();
return(getnm(e, getchar));
}
getnm(e, f)
int (*f)();
{
register i;
i = posn((*f)(), bname);
if(i < 0)
error(e);
return(i);
}
char special[] = "xgBbBcfFlprzN\"\\'";
int qcount;
int afterq;
getchar()
{
register c;
register peek;
peek=peekc;
c=getc();
if(tflag && !peek && stackp!= &stack[0]){
if(c==EOF)
puts("[*EOF*]");
else
putchar(c);
}
return(c);
}
getc()
{
register c;
register struct buffer *bufp;
register struct stack *sp;
int *lp;
int numeric;
int delta;
int literal;
int i;
char *p;
static char bufbuf[LBSIZE];
if(c = peekc) /* assignment = */
peekc = 0;
else if(qcount) {
--qcount;
c = '\\';
} else if(c = afterq) /* assignment = */
afterq = 0;
else {
for(;;popinp()){
sp=stackp;
switch(sp->type){
case TTY:
case XTTY:
if(cprflag && sp == &stack[0] &&
lastttyc == '\n')
write(2, "*", 1);
c = ttyc();
if(sp != &stack[0] && c == '\n') {
if(stackp->type == TTY)
continue;
else /* XTTY */
popinp();
}
break;
case GLOB:
if ((c = *stackp->globp++) == 0){
popinp();
c = EOF;
}
break;
case STRING:
case BFILEN:
case PAT:
case RHS:
case BRWS:
case FILEN:
if(string[sp->strname].len < sp->charno){
c=EOF;
continue;
}
c=string[sp->strname].str[sp->charno++];
if(c==0)
continue;
break;
case BUF:
bufp=sp->bufptr;
if(bufp==curbuf)
syncbuf();
lp=bufp->zero+sp->lineno;
if(bbempty){
if(lp>bufp->dol)
continue;
p = getline(*lp, bufbuf);
bbempty = FALSE;
for(i=sp->charno; i-- && *p; p++)
;
}else
p = bufbuf+sp->charno;
sp->charno++;
if((c = *p) == '\0'){
/*
* Leave the last newline in the buffer out.
*/
bbempty = TRUE;
if(lp>=bufp->dol)
continue;
sp->lineno++;
sp->charno=0;
c='\n';
}
}
break;
}
literal = FALSE;
if(c == '\\' && !stackp->literal){
Getc:
c = getc();
i = posn(c, cspec);
switch(i) {
case LITERAL:
if(posn(peekc=getc(), "bfFlprz!") >= 0)
literal = TRUE;
goto Getc; /* business as usual... */
case QUOTE:
c = '\\';
break;
case NEWL:
c = '\n';
break;
case STRING:
delta = 0;
numeric = 0;
c = getc();
if(c == '#'){
numeric++;
c = getc();
}
if(c == '+' || c == '-'){
delta = 1;
if(c == '-')
delta = -delta;
c=getc();
}
ungetchar(c);
c = getname('z');
if(delta){
if(numeric){
if(!alldigs(string[c].str))
error('#');
numset(c, atoi(string[c].str)+delta);
} else
strinc(c, delta);
}
pushinp(i, c, literal);
literal = FALSE;
c=getc();
break;
case BUF:
case BFILEN:
c = getname(cspec[i]);
if(i == BUF)
bbempty = TRUE;
/* fall through */
case TTY:
case FILEN:
case PAT:
case RHS:
pushinp(i, c, literal);
literal = FALSE;
/* fall through */
case NOTHING:
c = getc();
break;
case CURBN:
c = bname[curbuf-buffer];
break;
case BACKSLASH:
qcount++;
break;
default:
afterq = c;
c = '\\';
break;
}
}
}
lastc = c;
return(c);
}
ttyc()
{
char c;
initflag = 0;
if(read(0, &c, 1) > 0)
lastttyc = c&0177;
else
lastttyc = EOF;
return(lastttyc);
}
posn(c, s)
register char c;
register char *s;
{
register char *is;
is = s;
while(*s)
if(c == *s++)
return(s - is - 1);
return(-1);
}
pushinp(type, arg, literal)
register arg;
{
register struct stack *s;
s = ++stackp;
if(s == stack+STACKSIZE)
error('l');
stackp->literal = literal;
if(tflag){
putchar('[');
if(literal)
putchar('\'');
putchar(cspec[type]);
}
s->type=type;
s->charno = 0;
switch(type){
case BFILEN:
s->strname = FILE(arg);
break;
case STRING:
s->strname = arg;
break;
case FILEN:
s->strname = savedfile;
break;
case PAT:
s->strname = SAVPAT;
break;
case RHS:
s->strname = SAVRHS;
break;
case BRWS:
s->strname = BROWSE;
break;
case BUF:
if((s->bufptr=buffer+arg) == curbuf && appflag)
error('\\');
s->lineno=1;
break;
case GLOB:
s->globp = (char *)arg;
break;
}
if(tflag){
if(type==BFILEN || type==STRING || type==BUF)
putchar(bname[arg]);
putchar('=');
}
}
popinp(){
if(stackp->type == BUF)
bbempty = TRUE;
if(tflag){
putchar(']');
flush();
}
--stackp;
}
gettty()
{
register c, gf;
register char *p;
p = linebuf;
gf = stackp->type;
while((c=getchar()) != '\n') {
if (c==EOF) {
if (gf == GLOB)
peekc=c;
return(c);
}
if (c == 0)
continue;
*p++ = c;
if (p >= &linebuf[LBSIZE-2])
error('l');
}
*p++ = 0;
if (!oneline && linebuf[0]=='.' && linebuf[1]==0)
return(EOF);
return(0);
}
getquote(p, f)
register char *p;
int (*f)();
{
register c;
c = (*f)();
if(c == '\\') {
if(peekc == 0)
nextchar(); /* prime peekc */
if(posn(peekc, p) >= 0) {
c = peekc | 0200;
(*f)(); /* clear peekc */
}
}
return(c);
}

259
unix-1985/getfile.c Normal file
View File

@@ -0,0 +1,259 @@
/*% cc -c -O %
*/
#include "vars.h"
char *nextip;
long count;
/*
* newfile: read a new file name (if given) from command line.
*
* nullerr: if true, error if file is null.
* savspec: decides if string[savedfile] is set.
* If savspec==SAVEIFFIRST, only save if deffile is null.
* deffile: default file name.
*
* return value: string[FILEBUF]!=deffile
* (unless SAVEIFFIRST && deffile null ==> return FALSE)
* side effects:
* can set string[savedfile]
* always sets string[FILEBUF]
* zeroes count
*/
newfile(nullerr, savspec, deffile)
char *deffile;
{
register char c;
count = 0L;
cpstr(deffile, genbuf); /* in case we strcompact() */
startstring();
c = getchar();
if(c == '\n')
copystring(genbuf);
else {
if(c != ' ')
error('f');
do c = getchar(); while(c == ' ');
while(posn(c, " \t\n") < 0){
if(c<' ' || c=='\177')
error('f');
addstring(c);
c = getchar();
}
}
setstring(FILEBUF);
if(nullerr && string[FILEBUF].str[0]=='\0')
error('f');
if(savspec==SAVEALWAYS || (savspec==SAVEIFFIRST && genbuf[0]=='\0')){
startstring();
dupstring(FILEBUF);
setstring(savedfile);
if(savspec==SAVEIFFIRST && genbuf[0]=='\0')
return(FALSE);
}
return(!eqstr(genbuf, string[FILEBUF].str));
}
exfile()
{
close(io);
io = -1;
if (vflag && initflag)
ncom('f');
else if (vflag) {
putlong(count);
putchar('\n');
}
setcount((int)count);
}
getfile()
{
register c;
register char *lp, *fp;
lp = linebuf;
fp = nextip;
do {
if (--ninbuf < 0) {
if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) {
if(ninbuf < -1)
error('r');
if(lp != linebuf)
error('N');
return(EOF);
}
fp = genbuf;
}
if (lp >= &linebuf[LBSIZE])
error('l');
if ((*lp++ = c = *fp++ ) == 0) {
lp--;
continue;
}
count++;
} while (c != '\n');
*--lp = 0;
nextip = fp;
return(0);
}
putfile()
{
int *a1;
register char *fp, *lp;
register nib;
nib = 512;
fp = genbuf;
a1 = addr1;
if(a1 == zero)
*a1++;
while(a1 <= addr2){
lp = getline(*a1++, linebuf);
for(;;){
if (--nib < 0) {
if(write(io, genbuf, fp-genbuf) < 0)
error('w');
nib = 511;
fp = genbuf;
}
count++;
if ((*fp++ = *lp++) == 0) {
fp[-1] = '\n';
break;
}
}
}
write(io, genbuf, fp-genbuf);
}
#define SIGHUP 1
#define SIGINTR 2
#define SIGQUIT 3
#define SIGBPIPE 13
int savint= -1; /* awful; this is known in error() */
Unix(type)
char type;
{
register pid, rpid;
register char *s;
int *a, c;
int getsvc();
int onbpipe;
int retcode;
char unixbuf[512];
int pipe1[2];
int pipe2[2];
int *a1, *a2, *ndot;
startstring(); /* for the \zU register */
if(type == '!')
setnoaddr();
else {
if(type == '>' || type == '|')
nonzero();
count = 0L;
if(pipe(pipe1) == -1){
lastc = '\n';
error('|');
}
}
/* Quick hack: if char is doubled, push \'zU */
if(nextchar()==type){
getchar(); /* throw it away */
pushinp(STRING, UNIX, TRUE);
}
/*
* Use c not *s as EOF and getchar() are int's
*/
for(s=unixbuf;(c=getquote("\n", getsvc))!='\n' && c!=EOF;*s++=(c&0177)){
if(s>=unixbuf+512)
error('l');
}
dropstring(); /* drop the newline */
setstring(UNIX);
*s='\0';
a1 = addr1;
a2 = addr2;
if ((pid = fork()) == 0) {
signal(SIGHUP, onhup);
signal(SIGINTR, onintr);
signal(SIGQUIT, onquit);
if(type=='<' || type=='|'){
close(1);
dup(pipe1[1]);
}else if(type == '>'){
close(0);
dup(pipe1[0]);
}
if (type != '!') {
close(pipe1[0]);
close(pipe1[1]);
}
if(type == '|'){
if(pipe(pipe2) == -1){
puts("?|");
exit(1);
}
if((pid=fork()) == 0){
close(1);
dup(pipe2[1]);
close(pipe2[0]);
close(pipe2[1]);
/*
* It's ok if we get SIGBPIPE here
*/
display('p');
exit(0);
}
if(pid == -1){
puts("Can't fork\n?!");
exit(1);
}
close(0);
dup(pipe2[0]);
close(pipe2[0]);
close(pipe2[1]);
}
execl("/bin/sh", "sh", "-c", unixbuf, 0);
exit(-1);
}
if(pid == -1){
puts("Can't fork");
error('!');
}
savint = signal(SIGINTR, 1);
if(type=='<' || type=='|') {
close(pipe1[1]);
io = pipe1[0];
ninbuf = 0;
append(getfile,addr2);
close(io);
io = -1;
ndot = dot;
} else if(type == '>') {
onbpipe = signal(SIGBPIPE, 1);
close(pipe1[0]);
a=addr1;
do{
s=getline(*a++, linebuf);
do; while(*s++);
*--s='\n';
if (write(pipe1[1],linebuf,s-(linebuf-1))<0){
puts("?o");
break;
}
}while (a<=addr2);
close(pipe1[1]);
signal(SIGBPIPE, onbpipe);
}
while ((rpid = wait(&retcode)) != pid && rpid != -1);
retcode = (retcode>>8)&0377;
settruth(retcode);
signal(SIGINTR, savint);
if(type == '|'){
if(retcode == 0){
addr1 = a1;
addr2 = a2;
delete();
dot = ndot - (a2-a1+1);
} else
error('0');
}
if(vflag)
puts("!");
}

113
unix-1985/glob.c Normal file
View File

@@ -0,0 +1,113 @@
/*% cc -c -O %
*/
#include "vars.h"
#define ALWAYS 2
#define GBSIZE 256
until(nfl, n)
{
register c, type;
char ubuf[GBSIZE];
c = getchar();
type=posn(c, "ft ");
if(type < 0){
if(nfl==0)
error('x');
ungetchar(c);
}
getglob(ubuf);
settruth(FALSE);
if(nfl && n<=0)
return; /* do it zero times */
do ; while (exglob(ubuf, ubuf) &&
!((nfl && --n==0) ||
(type != ALWAYS && type == truth())));
}
global(k)
{
register int *a1;
char globuf[GBSIZE];
struct buffer *startbuf;
if(gflag++)
error('g');
setall();
if(nextchar() == '\n')
error('x');
compile(getchar());
getglob(globuf);
for (a1=zero; ++a1<=dol;) {
*a1 &= ~01;
if (a1>=addr1 && a1<=addr2 && execute(a1)==k)
*a1 |= 01;
}
startbuf = curbuf;
for (a1=zero; ++a1<=dol; ) {
if (*a1 & 01) {
*a1 &= ~01;
dot = a1;
if (!exglob(globuf, "p"))
break;
chngbuf(startbuf-buffer);
a1 = zero;
}
}
chngbuf(startbuf-buffer);
gflag=FALSE;
}
globuf(k)
{
register struct buffer *bp;
char globbuf[GBSIZE];
if (biggflag++)
error('G');
if (nextchar() =='\n')
error('x');
compile(getchar());
getglob(globbuf);
for (bp=buffer; bp < &buffer[NBUFS]; bp++)
bp->gmark = FALSE;
ncom('G'); /* mark interesting buffers */
for (bp=buffer; bp < &buffer[NBUFS]; bp++)
if (bp->gmark == k) {
chngbuf(bp-buffer);
if (!exglob(globbuf, "f\n"))
break;
}
biggflag = FALSE;
}
getglob(globuf)
char globuf[];
{
register char *gp;
register c;
int getchar();
gp = globuf;
while ((c = getquote("\n", getchar)) != '\n') {
if (c==EOF)
error('x');
*gp++ = c & 0177;
if (gp >= &globuf[GBSIZE-2])
error('l');
}
*gp++ = '\n';
*gp++ = 0;
}
exglob(cmd, dflt)
char *cmd, *dflt;
{
register int nesting;
pushinp(GLOB, eqstr(cmd,"\n")? dflt : cmd, FALSE);
nesting = ++nestlevel;
commands();
if (nesting!=nestlevel)
return(FALSE);
nestlevel--;
return(TRUE);
}

15
unix-1985/grep.q Normal file
View File

@@ -0,0 +1,15 @@
" Grep for z| (possibly set by caller) in all buffers
z|=
yf'fi
""pattern:" z|:\l
"fi
G/^[a-zA-Z]/ g/\z|/ ""\cB:" P
grepf.q 430682255 0 1 100644 164 `
" Grep for z| (possibly set by caller) in all buffers
" Prints file name as well as buffer name
z|=
yf'fi
""pattern:" z|:\l
"fi
G/^[a-zA-Z]/ g/\z|/ ""\cB(\cf):" P

173
unix-1985/mail.q Normal file
View File

@@ -0,0 +1,173 @@
" bA contains mail file
" \Fa is uid
" zF is mail file
" zM is current message number
" zN is number of messages
" zX is modified if buffer has been modified
" zY is number of lines in original mail file
" zZ is number of characters in original mail file
zF:/usr/spool/mail/\Fa
bA E \zF
zZ'C
$zY#a
g/^From /zN#+1
zN#=0 yf'}
""No mail
Q
"}
" add an extra From line to make things easy
$a From
zM'N zM#-1
"Loop
""? "
bA
za:\'l
bZZ a \za
bA
za=
yf'Nope
zM#+1>\zN yf'Print
""at end of mailbox
zM:\zN
y`Loop
"Nope
za=d
yf'Nope
zx:0
g/^From /zx#+1=\zM yto
.,/^From /-d
zX:modified
zN#-1=0 yt'Quit
zM#>\zN yf zM'N
y`Loop
"Nope
za=h
yf'Nope
" h command: headers
zx:0
g/^From .+/ ""\cz#+x "p
y`Loop
"Nope
bZ zx/^m .+/ bA yf'Nope
bBZ bA
zx:0
g/^From /zx#+1=\zM yto
.,/^From /-tB0
0a Forwarded by \Fa
zas/m //
>mail \za
y`Loop
"Nope
za=p
yf'Nope
zM#>0 yt zM:1
yt'Print
"Nope
za=q
yf'Nope
"Quit
zX=modified
yt'}
" no changes; just quit
zx{HOME} !touch \zx/.../readmail
Q
"}
bA $d " remove that extra From
bBZ E \zF
zC#=\zZ yf'}
" nobody touched it; ok to put file back
"Write
bA w \zF
zx{HOME} !touch \zx/.../readmail
Q
"}
""new mail arrived
" if the file is shorter this will intentionally crap out and
" drop you into qed
\zY+1,$tA$
y`Write
"Nope
za=r
yf'Nope
zx:0
g/^From /zx#+1=\zM yto
za. zas/From \([^ ]*\) .*/\1/
bBZ
a To: \za
"{
zx:\'l
zx=.
yt'Sendit
zx=.e
yt'Editit
a \zx
y`{
"}
"Nope
za=R
yf'Nope
bBZ bA
zx:0
g/^From /zx#+1=\zM yto
.,/^From /-tB0
1" " za. zas/From \([^ ]*\) .*/\1/
1c To: \za
"Editit
zx#P
w /tmp/m\zx
!qed /tmp/m\zx
E /tmp/m\zx
!rm -f /tmp/m\zx
"Sendit
1" " za. d zas/To: // za=
yf'}
""reply aborted
y`Loop
"}
>mail \za
yf ""reply saved in bB
y`Loop
"Nope
bZ zx/^s.*/ bA yf'Nope
zxs/s \(.*\)/\1/ yt zx{HOME} zx:\zx/mbox
zy:0
g/^From /zy#+1=\zM yto
.,/^From /- W \zx
y`Loop
"Nope
za=x
yf'Nope
zx{HOME} !touch \zx/.../readmail
Q
"Nope
bZ zx/^[0-9]+/ bA yf'Nope
" message chosen by number
za#>\zN yf'}
""only \zN messages
y`Loop
"}
zM'a
y'Print
"Nope
bZ zx/^-[0-9]*/ bA yf'Nope
" back up some number of messages
za#:-\za=0 yf za:1
zx#:\zN-\za<1 yf'}
""beyond beginning of mailbox
y`Loop
"}
zM'x
y'Print
"Nope
bZ zx/^!.*/ bA yf'Nope
\za
y`Loop
"Nope
y`Loop
"Print
zx:0
g/^From /zx#+1=\zM yto
.,/^From /- > cat
y`Loop

676
unix-1985/main.c Normal file
View File

@@ -0,0 +1,676 @@
/*% cc -c -O %
*/
#include "vars.h"
#define SIGHUP 1
#define SIGINTR 2
#define SIGQUIT 3
#define UP 1
#define DOWN 0
char lchars[]="pPlL";
struct buffer *curbuf = buffer;
char *linp = line;
int appflag = 0;
int pagesize = PAGESIZE;
int prflag = 0; /* prflag==1 ==> much code to get it right. use the startup buffer */
int lastttyc = '\n';
int gflag = 0;
int tflag = 0;
int vflag = 0; /* initialization code turns it on */
int uflag = 's';
int dflag = 0;
int initflag = 1;
int *option[] = {
&cflag, &dflag, &eflag, &iflag, &prflag,&tflag, &vflag,
};
char opcs[] = "cdeipTv";
int tfile = -1;
struct sgttyb ttybuf = { 0, 0, '\b', '\b', /*0*/};
char QEDFILE[]="QEDFILE";
int (*pending)();
rescue()
{
/* Save in qed.hup:[ab]q on hangup */
signal(SIGHUP,1);
if (lock) {
pending = rescue;
return;
}
startstring();
copystring("qed.hup");
setstring(FILEBUF);
savall();
exit(SIGHUP);
}
char *filea()
{
register struct string *sp;
register int i, d;
char c;
sp = &string[FILEBUF];
startstring();
d = 0;
i = 0;
while((c=sp->str[i]) != '\0'){
addstring(c);
i++;
if(c == '/')
d = i;
}
if((i-d) > 12) /* file name is >= 13 characters long */
string[NSTRING].str -= (i-(d+12)); /* truncate string */
copystring(":aq");
setstring(FILEBUF);
return(sp->str);
}
char *fileb()
{
register struct string *sp;
sp = &string[FILEBUF];
sp->str[sp->len-2] = 'b';
return(sp->str);
}
savall()
{
register fi;
syncbuf();
addr1 = buffer[0].zero + 1;
addr2 = buffer[NBUFS-1].dol;
if(addr1 > addr2){
error('$');
return;
}
if((io = creat(filea(), 0644)) < 0)
error('o'|FILERR);
putfile();
exfile();
if((fi = creat(fileb(), 0644)) < 0)
error('o'|FILERR);
write(fi, (char *)buffer, sizeof buffer);
write(fi, strarea, sizeof strarea);
lock++;
shiftstring(DOWN);
write(fi, (char *)string, sizeof string);
shiftstring(UP);
unlock();
close(fi);
}
restor()
{
register i, t;
register struct buffer *b;
int fi;
int getfile();
curbuf = buffer;
i = (int)curbuf->zero;
if((t = open(filea(), 0)) < 0){
lastc = '\n';
error('o'|FILERR);
}
initio();
init();
io = t;
ninbuf = 0;
append(getfile, dol);
exfile();
if((fi = open(fileb(),0)) < 0)
error('o'|FILERR);
lock++;
if(read(fi,(char *)buffer,sizeof buffer) != sizeof buffer
|| read(fi, strarea, sizeof strarea) != sizeof strarea
|| read(fi, (char *)string, sizeof string) != sizeof string)
error('R');
close(fi);
shiftstring(UP);
/*
* This code is incredibly sleazy and machine dependent for the 11.
* Sorry. There is no good reason why we don't have a shiftbuf():
* feel free to write one (but lock before you call it!).
*/
t = (int)buffer[0].zero;
if(i != t){
i -= t;
i >>= 1;
for(b = buffer;b <= &buffer[NBUFS-1];b++){
b->zero += i;
b->dot += i;
b->dol += i;
}
}
newbuf(0);
error(0); /* ==> error, but don't print anything. calls unlock() */
}
/*
* On INTR, generate error '?'
*/
interrupt()
{
signal(SIGINTR, interrupt);
if (lock) {
pending = interrupt;
return;
}
if(iflag){
unlink(tfname);
exit(SIGINTR);
}
linp=line;
putchar('\n');
lastc = '\n';
error('?');
}
/*
* Unlock: exit a critical section, invoking any pending signal routines.
*/
unlock()
{
register (*p)();
p = pending;
pending = 0;
lock = 0;
if (p)
(*p)();
}
char cleanup[] = "ba z~:\n";
char setvflag[] = "ov?";
char boot1[] = "G/^[";
char boot2[] = "].+\t./r\n";
main(argc, argv)
char **argv;
{
register char *p1;
register i;
char buf;
int rvflag;
char *startup=(char *)0;
argv++;
onquit = signal(SIGQUIT, 1);
onhup = signal(SIGHUP, 1);
onintr = signal(SIGINTR, 1);
rvflag = 1;
for(i=0;i!=NSTRING;i++){
string[i].str = nullstr;
string[i].len=0;
}
/* initialize strfree */
string[NSTRING].str = strchars;
while(argc > 1 && **argv=='-'){
switch(argv[0][1]){
casedefault:
default:
rvflag = 0;
break;
case 'q':
/* allow debugging quits? */
signal(SIGQUIT, 0);
break;
case 'i':
/* allow interrupt quits? */
iflag++;
break;
case 'e':
/* Exit on error? */
eflag++;
break;
case 'x':
if(argc == 2)
goto casedefault;
startup = argv[1];
argv++;
--argc;
}
argv++;
--argc;
}
gtty(0,&ttybuf);
if(startup==0)
startup = getenv(QEDFILE);
fendcore = (int *)sbrk(0);
curbuf = &buffer[0];
init();
if (onhup != 1)
signal(SIGHUP, rescue);
if (onintr != 1)
signal(SIGINTR, interrupt);
/*
* Build the initialization code in register z~
*/
if(startup){
startstring();
copystring(startup);
setstring(FILE(NBUFS-1));
p1 = "b~ r\n\\b~\n";
} else
p1 = "";
startstring();
copystring(p1);
setvflag[2] = "rs"[rvflag];
copystring(setvflag);
/*
* z~ now has startup-buffer initialization; prepare the file list
* and generate a GLOBUF to read them in
*/
if(--argc > 0) {
if(argc >= 53) /* buffer names a-zA-Z */
puts("?i");
else {
copystring(boot1);
for(i=0; i<argc; i++) /* argument files only */
addstring(bname[i]);
copystring(boot2);
copystring(cleanup);
setstring(NBUFS-1);
buf = 0;
while(argc > 0) {
startstring();
copystring(*argv);
setstring(FILE(buf++));
--argc;
argv++;
}
}
}
else{
copystring(cleanup);
setstring(NBUFS-1);
}
pushinp(STRING, NBUFS-1, FALSE);
setexit();
lastttyc = '\n';
commands();
unlink(tfname);
exit(lasterr);
}
int noaddr;
commands()
{
register int *a;
register c, lastsep;
int getfile(), gettty();
int r;
int changed;
long locn, lseek();
int startline;
for (;;) {
startline = (lastttyc == '\n' && peekc == 0);
cprflag=prflag;
c = '\n';
for (addr1=0;;) {
lastsep = c;
a=address();
c=getchar();
if (c!=',' && c!=';')
break;
if (lastsep==',')
error('a');
if (a==0) {
a = zero+1;
if (a>dol)
--a;
}
addr1 = a;
if (c==';')
dot = a;
}
if (lastsep!='\n' && a==0)
a=dol;
if((addr2=a) == 0) {
addr2=dot;
noaddr = TRUE;
} else
noaddr = FALSE;
if(addr1 == 0)
addr1 = addr2;
cprflag=FALSE;
switch(c){
case 'a':
setdot();
setapp();
append(gettty, addr2);
continue;
case 'b':
if(posn((c=nextchar()), bname)<0){ /* browse command */
setdot();
nonzero();
bcom();
continue;
}
c = getaz('b');
setnoaddr();
chngbuf(c);
continue;
case 'c':
setdot();
nonzero();
setapp();
append(gettty, addr2);
a = dot-(addr2-addr1+1);
delete();
dot = a;
continue;
case 'd':
/* Dave Sherman mod, August 1983: allow '-' too */
if(posn(nextchar(),"\377\npPlL- \t") < 0)
error('x');
delete();
continue;
case 'E':
case 'e':
setnoaddr();
/* Dave Sherman mod, August 1983: only give error
* if the buffer is nonempty!
*/
if(c=='e' && !eok && cflag && dol>zero){
eok=TRUE;
error('e');
}
newfile(TRUE, SAVEALWAYS, "");
delall();
addr1 = zero;
addr2 = zero;
modified(); /* In case file open causes error */
goto caseread;
case 'f':
setnoaddr();
if((c = getchar()) != '\n'){
ungetchar(c);
if(newfile(FALSE, SAVEALWAYS, string[savedfile].str))
modified();
if(vflag)
ncom('f');
}
else
ncom('f');
continue;
case 'g':
global(TRUE);
continue;
case 'G':
globuf(TRUE);
continue;
case 'h':
setnoaddr();
if(nextchar()=='\n')
error('x');
if('0'<=peekc && peekc<='9')
until(TRUE, getnum());
else
until(FALSE, 0);
continue;
case 'i':
setdot();
nonzero();
setapp();
append(gettty, addr2-1);
continue;
case 'j':
setdot();
if (addr1 == addr2 && lastsep == '\n'){
addr1--;
if(addr1 <= zero)
error('$');
}
nonzero();
join();
continue;
case 'k':
c = getaz(c);
setdot();
nonzero();
names[c] = *addr2 | 01;
continue;
case 'm':
move(FALSE);
continue;
case 'n':
case 'N':
ncom(c);
continue;
case 'o':
setnoaddr();
c = getchar();
r=posn(c, opcs);
if(r >= 0)
setreset(option[r]);
else switch(c) {
case 'B':
if(nextchar() == '\n')
clearstring(BROWSE);
else {
startstring();
while((c=getchar()) != '\n')
addstring(c);
copystring("\\N");
setstring(BROWSE);
}
break;
case '?':
if ((r = posn(getchar(), opcs)) < 0)
error('O');
settruth(*option[r]);
break;
case 'q':
c = getchar();
if(c=='s' || c =='r')
signal(SIGQUIT, c=='r');
else
error('x');
break;
case 'u':
c = getchar();
if(c == 'r')
uflag = 0;
else if(posn(c, "slu") >= 0)
uflag = c;
else
error('x');
break;
case 'b':
if((r=getnum()) > 0)
pagesize = r;
if(posn(nextchar(), lchars) >=0)
bformat = getchar();
break;
default:
error('x');
}
continue;
case '\n':
if (a==0) {
if(stackp != &stack[0] || !startline)
continue;
if(*string[BROWSE].str){
pushinp(BRWS, 0, FALSE);
continue;
}
a = dot+1;
addr2 = a;
addr1 = a;
}
if (lastsep==';')
addr1 = a;
c = 'p'; /* fall through */
case 'L':
case 'l':
case 'p':
case 'P':
display(c);
continue;
case EOF:
return;
case 'Q':
case 'q':
setnoaddr();
if(c!=EOF && (!startline || getchar()!='\n'))
error('x');
if(c!='Q' && !qok){
register struct buffer *bp;
syncbuf();
qok=TRUE;
for(bp=buffer; bp<&buffer[NBUFS]; bp++)
if(bp->cflag && (bp->dol>bp->zero ||
string[FILE(bp-buffer)].str[0]))
error('q');
}
unlink(tfname);
/* Dave Sherman: exit code 0 if normal quit, not "lasterr"
* (modified September 12/83 - for readnews)
*/
exit(0);
case 'r':
newfile(TRUE, SAVEIFFIRST, string[savedfile].str);
caseread:
if((io = open(string[FILEBUF].str, 0)) < 0){
if(initflag){
putchar('?');
putchar('o');
putchar(' ');
puts(string[FILEBUF].str);
continue;
}
lastc = '\n';
error('o'|FILERR);
}
setall();
changed = (zero!=dol);
ninbuf = 0;
append(getfile, addr2);
if(eqstr(string[savedfile].str, string[FILEBUF].str))
if(cflag = changed) /* Assignment = */
modified();
/* else append got cflag right */
exfile();
continue;
case 'R':
setnoaddr();
newfile(TRUE, SAVENEVER, "q");
restor();
continue;
case 's':
setdot();
nonzero();
substitute(stackp != &stack[0], -1);
continue;
case 'S':
setnoaddr();
newfile(TRUE, SAVENEVER, "q");
savall();
continue;
case 't':
move(TRUE);
continue;
case 'u':
setnoaddr();
undo();
modified();
continue;
case 'v':
global(FALSE);
continue;
case 'V':
globuf(FALSE);
continue;
case 'W':
case 'w':
if(addr2==0 && dol==zero)
error('$');
setall();
if(newfile(TRUE, SAVEIFFIRST, string[savedfile].str))
changed = cflag;
else
changed = (addr1>(zero+1) || addr2!=dol);
if(c=='w' || (io=open(string[FILEBUF].str,1))==-1){
Create:
if ((io = creat(string[FILEBUF].str, 0666)) < 0)
error('o'|FILERR);
}else{
if((locn=lseek(io, 0L, 2)) == -1L)
goto Create;
if(locn != 0L) /* W on non-empty file */
changed = TRUE; /* PHEW! figured it out */
}
putfile();
if(cflag = changed) /* Assignment = */
modified();
exfile();
continue;
case 'x':
setdot();
nonzero();
xform();
continue;
case 'y':
jump();
continue;
case 'z':
strcom(getaz('z'));
continue;
case 'Z':
setnoaddr();
if((c=getchar())!=' ' && c!='\n')
error('x');
delall();
cflag=FALSE;
clearstring(savedfile);
continue;
case '"':
setdot();
dot=addr2;
comment();
continue;
case '=':
setall();
putdn((addr2-zero)&077777);
continue;
case '>':
case '<':
case '|':
setall();
case '!':
Unix(c);
continue;
case '#':
setnoaddr();
allnums();
continue;
case '%':
setnoaddr();
allstrs();
continue;
}
error('x');
}
}
setreset(opt)
register int *opt;
{
register c;
c = getchar();
if(c!='s' && c!= 'r')
error('x');
*opt = (c=='s');
}
delall(){
if(dol!=zero){
addr1=zero+1;
addr2=dol;
delete();
}
}

23
unix-1985/makefile Normal file
View File

@@ -0,0 +1,23 @@
# CFLAGS=-O -DPDP11
CFLAGS=-O
FILES=\
address.o\
blkio.o\
com.o\
getchar.o\
getfile.o\
glob.o\
main.o\
misc.o\
move.o\
pattern.o\
putchar.o\
setaddr.o\
string.o\
subs.o
a.out: $(FILES)
cc -n -s $(FILES)
$(FILES): vars.h
print:
@pr vars.h address.c blkio.c com.c getchar.c getfile.c glob.c main.c\
misc.c move.c pattern.c putchar.c setaddr.c string.c subs.c

14
unix-1985/man.q Normal file
View File

@@ -0,0 +1,14 @@
"" Arguments in [] will be prompted for if missing
"" man - print this listing
"" L - pad addressed lines with blanks to same length
"" R - pad addressed lines to same length with leading blanks
"" col - columnate addressed lines
"" grep [RE] - search buffers a-z and A-Z for regular expression
"" grepf [RE] - same as grep, but also gives file name in each buffer
""multiblanks - replace multiple blanks lines by single ones
"" nextfile - load bn with loop to loop through file list in bz
"" parens - show parenthesis nesting in addressed lines
"" pwd - put pwd output into zd
"" qfile - load your qfile into b~ (`qfile -' gets default)
"" split - split a line at a numbered blank
"" writelen - put length of quoted string into C write call

185
unix-1985/misc.c Normal file
View File

@@ -0,0 +1,185 @@
/*% cc -c -O %
*/
#include "vars.h"
#define SIGINT 2
bufinit(n)
int *n;
{
struct buffer *bufp;
register *fend;
fend=n;
for(bufp=buffer;bufp!=buffer+NBUFS;bufp++){
bufp->zero=fend;
bufp->dot=fend;
bufp->dol=fend;
bufp->cflag = FALSE;
}
}
chngbuf(bb)
int bb;
{
syncbuf();
newbuf(bb);
savedfile = FILE(curbuf-buffer);
}
newbuf(bb){
curbuf = buffer+bb;
zero=curbuf->zero;
dot=curbuf->dot;
dol=curbuf->dol;
cflag = curbuf->cflag;
}
fixbufs(n)
register n;
{
register struct buffer *bufp;
lock++;
for(bufp=curbuf+1;bufp!=buffer+NBUFS;bufp++){
bufp->zero+=n;
bufp->dot+=n;
bufp->dol+=n;
}
unlock();
}
syncbuf()
{
/* curbuf->zero = zero; /* we never assign to it, so needn't save */
curbuf->dot=dot;
curbuf->dol=dol;
curbuf->cflag = cflag!=FALSE; /* Normalize to fit in a char */
}
error(code)
{
extern savint; /* error during a ! > < | ?? */
unlock();
/* Dave Sherman mod, August 29/83: if ?q, beep to warn
* the user
*/
if(code == 'q')
putchar(7);
if(code){
for(;stackp != stack ;--stackp)
if(stackp->type == BUF || stackp->type == STRING){
putchar('?');
if(stackp->type == BUF){
putchar('b');
putchar(bname[stackp->bufptr - buffer]);
putlong((long)stackp->lineno);
putchar('.');
}else{
putchar('z');
putchar(bname[stackp->lineno]);
}
putlong((long)stackp->charno);
putchar(' ');
}
putchar('?');
putchar(lasterr=(code&~FILERR));
if(code&FILERR){
putchar(' ');
putl(string[FILEBUF].str);
} else
putchar('\n');
}
if(eflag && code)
exit(code);
nestlevel = 0;
listf = FALSE;
gflag = FALSE;
biggflag = FALSE;
stackp = stack;
peekc = 0;
if(code && code!='?'){ /* if '?', system cleared tty input buf */
while(lastttyc!='\n' && lastttyc!=EOF){
getchar();
}
}
lseek(0, 0L, 2);
if (io > 0) {
close(io);
io = -1;
cflag = TRUE; /* well, maybe not, but better be safe */
}
appflag=0;
if(savint>=0){
signal(SIGINT, savint);
savint= -1;
}
reset();
}
init()
{
register char *p;
register pid;
lock++;
close(tfile);
tfname = "/tmp/qxxxxx";
pid = getpid();
for (p = &tfname[11]; p > &tfname[6];) {
*--p = (pid%10) + '0';
pid /= 10;
}
close(creat(tfname, 0600));
tfile = open(tfname, 2);
ioctl(tfile, FIOCLEX, 0);
brk(fendcore);
bufinit(fendcore);
newbuf(0);
lastdol=dol;
endcore = fendcore - 2;
stackp=stack;
stackp->type=TTY;
unlock();
}
comment()
{
register c, mesg;
c = getchar();
mesg = 0;
if(c == '\"') {
mesg++;
c = getchar();
}
while(c != '\n' && c != '\"') {
if(mesg)
putchar(c);
c = getchar();
}
if(mesg) {
if(c == '\n')
putchar(c);
flush();
}
}
abs(n)
register n;
{
return(n<0?-n:n);
}
/*
* Slow, but avoids garbage collection
*/
settruth(t)
register t;
{
if(atoi(string[TRUTH].str) != t)
numset(TRUTH, t);
}
setcount(c)
register c;
{
if(atoi(string[COUNT].str) != c)
numset(COUNT, c);
}
truth(){
return(atoi(string[TRUTH].str) != FALSE);
}
modified(){
cflag=TRUE;
eok=FALSE;
qok=FALSE;
}

133
unix-1985/move.c Normal file
View File

@@ -0,0 +1,133 @@
/*% cc -c -O %
*/
#include "vars.h"
move(copyflag)
{
register int *adt, *ad1, *ad2;
int fb, tb;
int todot;
int tonewdot;
int totmved;
int temp;
int getcopy();
setdot();
nonzero();
fb = curbuf - buffer;
temp = getchar();
tb = posn(temp, bname);
if(tb >= 0)
chngbuf(tb);
else{
ungetchar(temp);
tb = fb;
}
if ((adt = address())==0){
chngbuf(fb);
error('x');
}
todot = adt - buffer[tb].zero; /* syncbuf not needed! */
chngbuf(fb);
ad1 = addr1;
ad2 = addr2;
totmved = ad2 - ad1 + 1;
lock++;
if (copyflag) {
tonewdot = addr2 - buffer[fb].zero;
/*
* NOTE: in the copy command
* copies of the lines are created using append
* and then moved to the target position.
* They are appended at the dollar of their
* original buffer. (guarenteed to be higher address)
* They are NOT appended at the target position
* since, if the target position was lower than their
* source position, getcopy would have to account
* for the shift of the addresses due to the insert
* of the copies.
*/
ad1 = dol;
temp = cflag;
append(getcopy, ad1++);
cflag = temp;
ad2 = dol;
} else
tonewdot = addr1 - buffer[fb].zero - 1;
ad2++;
adt = buffer[tb].zero + todot;
chngbuf(tb);
if (adt<ad1) {
if ((++adt)!=ad1){
reverse(adt, ad1);
reverse(ad1, ad2);
reverse(adt, ad2);
}
} else {
if (adt++ >= ad2) {
reverse(ad1, ad2);
reverse(ad2, adt);
reverse(ad1, adt);
} else {
if(ad2 != zero + 1){
error('m');
}
}
}
fixup(fb, tb, totmved);
buffer[fb].dot = buffer[fb].zero + tonewdot;
if(copyflag == 0 && fb == tb && todot >= tonewdot){
todot -= totmved;
}
if(!copyflag)
buffer[fb].cflag = TRUE;
modified();
dot = buffer[tb].dot = buffer[tb].zero + todot + totmved;
zero = buffer[tb].zero;
dol = buffer[tb].dol;
unlock();
}
fixup(from,to,tot) int from, to, tot;
{
register int b;
register int n;
register int lo;
int hi;
if(to == from){
return;
}
if(to < from){
n = tot;
lo = to;
hi = from;
} else {
n = -tot;
lo = from;
hi = to;
}
buffer[lo].dol += n;
for(b = lo;++b < hi;){
buffer[b].zero += n;
buffer[b].dot += n;
buffer[b].dol += n;
}
buffer[hi].zero += n;
}
reverse(a1, a2)
register int *a1, *a2;
{
register t;
for (;;) {
t = *--a2;
if (a2 <= a1)
return;
*a2 = *a1;
*a1++ = t;
}
}
getcopy()
{
if (addr1 > addr2)
return(EOF);
getline(*addr1++, linebuf);
return(0);
}

12
unix-1985/multiblanks.q Normal file
View File

@@ -0,0 +1,12 @@
" Multiblanks - convert multiple blank lines to single blank lines
" Address defaults to 1,$
zL#=\zM yf'fi
1,$zL#r
"fi
" By adding blank at end, get all trailing blank lines deleted!
\zMa
" Precompile the pattern for efficiency
/^$/"
\zL,\z#+M g// a \cN hf d zP//
zP)0 zL)0 zM)0

7
unix-1985/nextfile.q Normal file
View File

@@ -0,0 +1,7 @@
" Nextfile: simple little controller for sequencing through a list of file names
bnZ
a
ba o?c yf w
bz +;.zz.
bae \czz
f

37
unix-1985/nroff.q Normal file
View File

@@ -0,0 +1,37 @@

Date: 12 Jun 1984 16:25 (Tue)
From: dave@lsuc
To: arnold@GaTech
Via: akgua!utcsrgv; 12 Jun 84 21:47-EDT
""Q"
ops
zB:s/\cl/\ccfB&\ccfR/p
zF:s/\[[1457]m\(.*\)\[m/\ccfI\1\ccfR/p
zI:s/\cl/\ccfI&\ccfR/p
zb:/u/student/biblio/
zc:s@$@ /* \cl */@ p
zd:/u/student/descriptions/
zq:/u/student/quizzes/
zf:-/^[a-zA-Z_].*(/
zh:s/\cl/&/p
zs:s/\cl/&/p
zl:s/\cl/&/p
zp:/u/student/primary/
zr:/u/student/refresher/
zt:/u/student/taxcourse/
zu:us2//\c'r/p
zC:s/^/\/* /s/$/ *\//p
zk:s/^/\/* /s/$/ *\//p
zz:!calypso \cf
zN:>nroff -mbill|p
zn:>nroff|p
zL:/u/student/log/
zm: /u/student/monitor
zx:zX:\cl\cNbae /u/student/log/\czX\cNbbe /u/student/comment/\czX\cN
zw:?\.qu?,.
""ed


469
unix-1985/pattern.c Normal file
View File

@@ -0,0 +1,469 @@
/*% cc -c -O %
*/
#include "vars.h"
#define ESIZE 128 /* ESIZE-1 must fit in a signed byte */
char expbuf[ESIZE+4];
int expgood /*0*/; /* flag indicating if compiled exp is good */
#define CCHR 2
#define CDOT 4
#define CCL 6
#define NCCL 8
#define CFUNNY 10
#define CALT 12
#define CBACK 14
#define STAR 01
#define STARABLE CBACK
#define CKET 16
#define CDOL 17
#define CEOF 18
#define CBRA 19
#define CBOI 20
#define CEOI 21
#define CSPACE 22
int circfl;
char pmagic[] = "/.$^*+\\()<|>{}[!_123456789";
compile(eof)
char eof;
{
register c;
register char *ep, *penultep;
char *lastep, *bracketp, bracket[NBRA];
int getsvc();
int getchar();
struct{
char *althd; /* start of code for < ... > */
char *altlast; /* start of code for last < or | */
char *bpstart; /* bracketp at start of < and | */
char *bpend; /* bracketp at end of > or | */
int nbstart; /* nbra at start of < and | */
int nbend; /* nbra at end of > or | */
int firstalt; /* is this the first alternative? */
} *asp, altstk[NBRA];
if(eof == '\n')
error('x');
pmagic[0] = eof;
if ((c=nextchar()) == eof || c=='\n') {
if (!expgood)
goto cerror;
if(c!='\n')
getchar(); /* eat the eof character */
return;
}
expgood = FALSE;
ep = expbuf;
lastep = 0;
bracketp = bracket;
nbra = 0;
asp = &altstk[-1];
startstring(); /* for the saved pattern register */
circfl = 0;
if (c=='^') {
getsvc(); /* save the caret */
circfl++;
}
for (;;) {
c = getquote(pmagic, getsvc);
if (c==eof || c=='\n') {
if (bracketp!=bracket || asp>=altstk)
goto cerror;
*ep++ = CEOF;
expgood = TRUE;
dropstring(); /* lose the eof character */
setstring(SAVPAT);
if(c=='\n')
ungetchar(c);
return;
}
if (ep >= &expbuf[ESIZE-5])
goto cerror;
penultep = lastep;
lastep = ep;
if(c != (eof|0200)) switch (c) {
case '('|0200:
if (nbra >= NBRA)
goto cerror;
*bracketp++ = nbra;
*ep++ = CBRA;
*ep++ = nbra++;
continue;
case ')'|0200:
if (bracketp <= bracket)
goto cerror;
*ep++ = CKET;
*ep++ = *--bracketp;
continue;
case '{'|0200:
*ep++ = CBOI;
continue;
case '}'|0200:
*ep++ = CEOI;
continue;
case '_'|0200:
*ep++ = CSPACE;
continue;
case '!'|0200:
*ep++ = CFUNNY;
continue;
case '<':
if (++asp >= &altstk[NBRA])
goto cerror;
*ep++ = CALT;
asp->althd = ep;
ep++;
asp->bpstart = bracketp;
asp->nbstart = nbra;
asp->firstalt = TRUE;
asp->altlast = ep++;
lastep = 0;
continue;
case '|':
if (asp<altstk)
break;
if (asp->firstalt) {
asp->bpend = bracketp;
asp->nbend = nbra;
}
if (bracketp!=asp->bpend || nbra!=asp->nbend)
goto cerror;
*ep++ = CEOF;
asp->altlast[0] = ep-asp->altlast;
asp->firstalt = FALSE;
bracketp = asp->bpstart;
nbra = asp->nbstart;
asp->altlast = ep++;
lastep = 0;
continue;
case '>':
if (asp<altstk)
break;
if (!asp->firstalt &&
(bracketp!=asp->bpend || nbra!=asp->nbend))
goto cerror;
*ep++ = CEOF;
asp->altlast[0] = ep-asp->altlast;
lastep = asp->althd;
*lastep = ep-lastep;
lastep--;
if (bracketp!=asp->bpstart || nbra!=asp->nbstart)
lastep = 0;
asp--;
continue;
case '*':
case '+':
if (penultep==0){
*ep++ = CCHR;
*ep++ = c;
} else {
if(*penultep>STARABLE)
goto cerror;
if(c == '+'){
if((ep-penultep)+ep >= &expbuf[ESIZE-1])
goto cerror;
do
*ep++ = *penultep++;
while (penultep!=lastep);
}
*penultep |= STAR;
lastep = 0;
}
continue;
case '.':
*ep++ = CDOT;
continue;
case '[':
penultep = ep;
*ep++ = CCL;
*ep++ = 0;
if ((c=getsvc()) == '^') {
c = getsvc();
ep[-2] = NCCL;
}
do {
if (c == EOF || c == '\n')
goto cerror;
*ep++ = c;
if ((lastc=getsvc()) == '-') {
c=getsvc();
if (c == EOF || c == '\n' || c<=ep[-1])
goto cerror;
ep[-1] |= 0200;
*ep++ = c;
lastc = getsvc(); /* prime lastc */
} else if (dflag&&'a'<=(c|' ')&&(c|' ')<='z')
*ep++ = c^' ';
if (ep >= &expbuf[ESIZE-1])
goto cerror;
} while ((c=lastc) != ']');
penultep[1] = ep-penultep-1;
continue;
case '$':
if (nextchar() == eof || peekc=='\n') {
*ep++ = CDOL;
continue;
}
/* fall through */
default:
break;
}
/* if fell through switch, match literal character */
/* Goddamned sign extension! */
if ((c&0200) && (c&0177)>='1' && (c&0177)<='9') {
*ep++ = CBACK;
*ep++ = c-('1'|0200);
continue;
}
c &= ~0200;
if(dflag && c|' '>='a' && c|' '<='z'){
*ep++ = CCL;
*ep++ = 3;
*ep++ = c;
*ep++ = c^' ';
}
else{
*ep++ = CCHR;
*ep++ = c;
}
}
cerror:
error('p');
}
getsvc(){
register c;
addstring(c=getchar());
return(c);
}
int
execute(addr)
int *addr;
{
register char *p1, *p2;
if (addr==0) {
if((p1=loc2) == 0) /* G command */
p1 = linebuf;
else if (circfl) /* not first search in substitute */
return(FALSE);
} else {
if (addr==zero)
return(FALSE);
p1 = getline(*addr, linebuf);
}
p2 = expbuf;
if (circfl) {
loc1 = p1;
return(advance(p1, p2));
}
do {
if (*p2 != CCHR || p2[1] == *p1) {
if (advance(p1, p2)) {
loc1 = p1;
return(TRUE);
}
}
} while (*p1++);
return(FALSE);
}
int
advance(lp, ep)
register char *lp, *ep;
{
register char *curlp;
char *althd, *altend;
for (;;) {
curlp = lp;
switch (*ep++) {
case CCHR:
if (*ep++ == *lp++)
continue;
return(FALSE);
case CCHR|STAR:
do ; while (*lp++ == *ep);
ep++;
break;
case CDOT:
if (*lp++)
continue;
return(FALSE);
case CDOT|STAR:
do ; while (*lp++);
break;
case CCL:
case NCCL:
if (cclass(ep, *lp++, ep[-1]==CCL)) {
ep += *ep;
continue;
}
return(FALSE);
case CCL|STAR:
case NCCL|STAR:
do ; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
ep += *ep;
break;
case CFUNNY:
if (*lp>=' ' && *lp!='\177' || *lp=='\t' || *lp=='\0')
return(FALSE);
lp++;
continue;
case CFUNNY|STAR:
while (*lp<' ' && *lp && *lp!='\t' || *lp=='\177')
lp++;
lp++;
break;
case CBACK:
if (braelist[*ep]==0)
error('p');
if (backref(*ep++, lp)) {
lp += braelist[ep[-1]] - braslist[ep[-1]];
continue;
}
return(FALSE);
case CBACK|STAR:
if (braelist[*ep] == 0)
error('p');
curlp = lp;
while (backref(*ep, lp))
lp += braelist[*ep] - braslist[*ep];
while (lp >= curlp) {
if (advance(lp, ep+1))
return(TRUE);
lp -= braelist[*ep] - braslist[*ep];
}
ep++;
continue;
case CBRA:
braslist[*ep++] = lp;
continue;
case CKET:
braelist[*ep++] = lp;
continue;
case CDOL:
if (*lp==0)
continue;
return(FALSE);
case CEOF:
loc2 = lp;
return(TRUE);
case CBOI:
if (alfmatch(*lp,0)
&& (lp==linebuf || !alfmatch(lp[-1],1)))
continue;
return(FALSE);
case CEOI:
if (!alfmatch(*lp,1)
&& lp!=linebuf && alfmatch(lp[-1],1))
continue;
return(FALSE);
case CSPACE:
if (*lp==' ' || *lp=='\t') {
while (*lp == ' ' || *lp=='\t')
lp++;
continue;
}
return(FALSE);
case CALT:
althd = ep-1;
altend = ep + *ep;
for(ep++; ; ep+= *ep) {
if(ep == altend)
return(FALSE);
if(advance(lp,ep+1) && advance(loc2,altend))
return(TRUE);
}
case CALT|STAR:
althd = ep-1;
altend = ep + *ep;
for(ep++; ep!=altend; ep+= *ep){
if(advance(lp, ep+1)){
if(loc2 == lp)
break;
if(advance(loc2, althd))
return(TRUE);
}
}
/* return (advance(lp,altend)) */
continue;
default:
error('!');
}
/* star logic: executed by falling out of switch */
do {
lp--;
if (advance(lp, ep))
return(TRUE);
} while (lp > curlp);
return(FALSE);
}
}
backref(i, lp)
register i;
register char *lp;
{
register char *bp;
bp = braslist[i];
while (*bp++ == *lp++)
if (bp >= braelist[i])
return(TRUE);
return(FALSE);
}
int alfmatch(c,tail)
register char c;
{
return (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
(c == '_') ||
(tail && '0' <= c && c<= '9'));
}
cclass(set, c, f)
register char *set;
register c;
{
register n;
if (c == 0)
return(0);
n = *set++;
while (--n) {
if (*set&0200) {
if ((*set++ & 0177) <= c) {
if (c <= *set++)
return(f);
} else
set++;
--n;
} else if (*set++ == c)
return(f);
}
return(!f);
}

154
unix-1985/putchar.c Normal file
View File

@@ -0,0 +1,154 @@
/*% cc -c -O %
*/
#include "vars.h"
#ifdef PDP11
typedef long ulong;
#else
typedef unsigned long ulong;
#endif
int col;
putdn(i)
{
putlong((ulong)i);
putchar('\n');
}
#ifdef PDP11
/*
* In version 6, ldiv() is in the library. In version 7, it is separate:
.globl _ldiv, _ldivr
_ldiv:
mov 2(sp), r0
mov 4(sp), r1
div 6(sp), r0
mov r1,_ldivr
rts pc
.bss
_ldivr: .=.+2
*/
putlong(i)
long i;
{
register char r;
extern int ldiv(), ldivr;
/* the following pornography saves bundles of memory */
i = ldiv(i,10);
r = ldivr + '0';
if (i)
putlong(i);
putchar(r);
}
#endif
#ifndef PDP11
putlong(i)
ulong i;
{
register r;
r = i%10;
i /= 10;
if(i)
putlong(i);
putchar('0'+r);
}
#endif
putl(sp)
register char *sp;
{
listf++;
puts(sp);
listf = FALSE;
}
puts(sp)
register char *sp;
{
col = 0;
while (*sp)
putchar(*sp++);
putchar('\n');
}
display(lf)
{
register int *a1;
register int r;
register char *p;
register i;
int nf;
listf = (lf == 'l' || lf == 'L');
nf = (lf == 'P' || lf == 'L');
lf = listf;
setdot();
nonzero();
a1 = addr1;
r = (a1 - zero) & 077777;
do{
col = 0;
if(nf){
putlong((ulong)r++);
for(i=0; i<NBUFS; i++)
if((*a1|01) == names[i]){
putchar('\'');
putchar(bname[i]);
}
listf = 0;
putchar('\t');
col = 8;
listf = lf;
}
for(p = getline(*a1++,linebuf);*p;putchar(*p++));
putchar('\n');
}while (a1 <= addr2);
dot = addr2;
listf = FALSE;
}
putct(c){
putchar(c);
putchar('\t');
}
putchar(c)
register char c;
{
register char *lp;
lp = linp;
if (listf) {
if (c=='\n') {
if(linp!=line && linp[-1]==' ') {
*lp++ = '\\';
*lp++ = 'n';
}
} else {
if (col >= (72-4-2)) {
*lp++ = '\\';
*lp++ = '\n';
*lp++ = '\t';
col = 8;
}
col++;
if (c=='\b' || c=='\\' || c=='\t') {
*lp++ = '\\';
c = c=='\b'? 'b' : c=='\t'? 't' : '\\';
col++;
} else if ((c&0200) || c<' ' || c=='\177') {
*lp++ = '\\';
*lp++ = ((c>>6)&03)+'0';
*lp++ = ((c>>3)&07)+'0';
c = ( c &07)+'0';
col += 3;
}
}
}
*lp++ = c;
if(c == '\n' || lp >= &line[(sizeof line)-2-4]) {
linp = lp;
flush();
lp = linp;
}
linp = lp;
}
flush()
{
if(linp != line){
write(1, line, linp-line);
linp = line;
}
}

1617
unix-1985/qed.1 Normal file

File diff suppressed because it is too large Load Diff

33
unix-1985/setaddr.c Normal file
View File

@@ -0,0 +1,33 @@
/*% cc -c -O %
*/
#include "vars.h"
extern noaddr;
setdot()
{
if (addr2 == 0)
addr1 = addr2 = dot;
if (addr1 > addr2)
error('$');
}
setall()
{
if (noaddr) {
addr1 = zero+1;
addr2 = dol;
if (dol==zero)
addr1 = zero;
}
setdot();
}
setnoaddr()
{
extern noaddr;
if (noaddr == FALSE)
error('$');
}
nonzero()
{
if (addr1<=zero || addr2>dol)
error('$');
}

106
unix-1985/string.c Normal file
View File

@@ -0,0 +1,106 @@
/*% cc -c -O %
*/
#include "vars.h"
#define strfree string[NSTRING].str
char *strstart;
length(s)
register char *s;
{
register char *t;
if((t=s)==0)
return(0);
do;while(*t++);
return(t-s-1);
}
startstring(){
strstart=strfree;
}
addstring(c){
if(strfree==strchars+NSTRCHARS)
strcompact();
*strfree++ = c;
}
dropstring(){
--strfree;
}
cpstr(a, b)
register char *a, *b;
{
do;while (*b++ = *a++);
}
shiftstring(up){ /* A highly machine-dependent routine */
register struct string *sp;
for(sp=string; sp<=string+NSTRING; sp++)
if(up)
sp->str += (int)strarea;
else
sp->str -= (int)strarea;
}
clearstring(z){
string[z].len = 0;
string[z].str = nullstr;
}
copystring(s)
register char *s;
{
while(*s)
addstring(*s++);
}
eqstr(a, b)
register char *a, *b;
{
while(*a)
if(*a++ != *b++)
return(FALSE);
return(*b=='\0');
}
/*
* dupstring duplicates a string.
* Because we may strcompact(), we do it first if necessary.
*/
dupstring(z)
{
if(strfree+string[z].len > strchars+NSTRCHARS)
strcompact(); /* if insufficient, will get error when we copystring() */
copystring(string[z].str);
}
setstring(n){
addstring('\0');
if((string[n].len = length(strstart)) == 0)
string[n].str = nullstr;
else
string[n].str = strstart;
if(strfree >= strchars + NSTRCHARS)
strcompact();
}
strcompact(){
register struct string *cursor;
struct string *thisstr;
register char *s, *t;
lock++;
s=strchars;
for(;;){
t=strchars+NSTRCHARS;
for(cursor=string;cursor!=string+NSTRING;cursor++)
if(s<=cursor->str && cursor->str<t){
t = cursor->str;
thisstr = cursor;
}
if(t==strchars+NSTRCHARS)
break;
thisstr->str=s;
do;while(*s++ = *t++);
}
t=strstart;
strstart=s;
while(t!=strfree)
*s++ = *t++;
strfree=s;
if(s==strchars+NSTRCHARS){
strfree=strstart;
error('Z');
}
unlock();
}

416
unix-1985/subs.c Normal file
View File

@@ -0,0 +1,416 @@
/*% cc -c -O %
*/
#include "vars.h"
char *next_new;
char *next_old;
int new_line;
int old_line;
char rhsbuf[RHSIZE];
substitute(inglob, reg)
{
register int n, m;
register char *p;
char *q;
int *a1;
int gsubf;
extern int getsub();
int t, count, autop=0;
count=0;
t = FALSE;
n=getnum();
gsubf = compsub(TRUE, &autop);
if(reg!= -1){ /* Substitution in a register */
cpstr(string[reg].str, linebuf);
loc2=0; /* signal execute to take line from linebuf */
a1=0;
goto Do_it;
}
for (a1 = addr1; a1 <= addr2 && reg==-1; a1++) {
Do_it:
if (execute(a1)) {
next_old=linebuf;
next_new=genbuf;
m=n;
do {
if (--m <= 0) {
dosub();
t = TRUE;
count++;
if (!gsubf)
break;
}
/* can't find something at EOL twice */
if (*loc2=='\0')
break;
/* can't match same location twice */
if (loc1==loc2)
loc2++;
} while (execute((int *)0));
if (m<=0) {
inglob |= TRUE;
p=next_old;
do ; while (*p++);
place(next_old,p,0);
if(reg==-1){
p=linebuf;
q=genbuf;
do ; while (*p++ = *q++);
replace(a1,putline());
m=append(getsub,a1);
a1 += m;
addr2 += m;
}else{
startstring();
copystring(genbuf);
setstring(reg);
}
}
}
}
if (!inglob)
error('s');
settruth(t);
setcount(count);
if(autop)
if(reg>=0)
puts(string[reg].str);
else{
addr1=addr2=dot;
display('p');
}
}
compsub(subbing, autop)
int subbing;
int *autop;
{
register int seof, c;
char *rhsmagic;
register char *p;
int getsvc();
*autop=FALSE;
seof = getchar();
if(subbing) {
compile(seof);
rhsmagic = "/&^\n\\123456789";
}
else
rhsmagic = "/\\\n";
rhsmagic[0] = seof;
p = rhsbuf;
startstring();
for (;;) {
c = getquote(rhsmagic, getsvc);
if (c=='\n' || c==EOF){
*autop=TRUE;
ungetchar('\n');
break;
}
if (c==seof)
break;
*p++ = c;
if (p >= &rhsbuf[RHSIZE])
error('l');
}
*p = 0;
dropstring();
setstring(SAVRHS);
if (subbing && nextchar() == 'g') {
getchar(); /* clear 'g' */
return(1);
}
return(0);
}
int getsub()
{
register char *p1, *p2;
p1 = linebuf;
if ((p2 = linebp) == 0)
return(EOF);
do ; while (*p1++ = (*p2++ & 0177));
linebp = 0;
return(0);
}
dosub()
{
register int c;
register char *p;
place(next_old,loc1,0);
next_old=loc2;
p=rhsbuf;
while (c = *p++) {
if (c=='&' || (c == '^' && uflag))
place(loc1,loc2,c=='^');
else if ((c&0200) && (c &= 0177)>='1' && c<'1'+nbra)
place(braslist[c-'1'],braelist[c-'1'], 0);
else {
*next_new++ = c;
if (next_new >= genbuf+LBSIZE)
error('l');
}
}
}
place(l1, l2, ucase)
register char *l1;
char *l2;
{
register char *sp;
register c;
sp = next_new;
while (l1 < l2) {
*sp++ = (*l1++ & 0177);
if (sp >= &genbuf[LBSIZE])
error('l');
}
if(ucase){
for(l1 = next_new;l1 < sp;){
c = (*l1 & 0177);
if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
switch(uflag){
case 's':
*l1++ ^= 040;
break;
case 'u':
*l1++ &= ~040;
break;
case 'l':
*l1++ |= 040;
break;
default:
l1++;
}
}else{
l1++;
}
}
}
next_new = sp;
}
undo()
{
register int *l;
for (l=zero+1; l<=dol && (*l|01)!=new_line; l++)
;
if (l>dol)
error('u');
replace(l,old_line);
dot=l;
}
replace(line,ptr)
register int *line;
register int ptr;
{
register int *p;
*line |= 01;
for (p=names; p<names+NBUFS; p++)
if (*p == *line)
*p = ptr|01;
old_line = *line;
*line = ptr;
new_line = ptr | 01;
}
join()
{
register int *l;
register char *p, *q;
int rep;
int autop=FALSE;
rep=FALSE;
if(nextchar() == '/'){
compsub(FALSE, &autop);
rep=TRUE;
}
p = genbuf;
for (l=addr1; ;) {
q = getline(*l++, linebuf);
while (*q) {
*p++ = *q++;
if (p >= genbuf + sizeof genbuf)
error('l');
}
if(l > addr2)
break;
if(rep) {
q = string[SAVRHS].str;
while (*q) {
*p++ = *q++;
if (p >= genbuf + sizeof genbuf)
error('l');
}
}
}
*p = '\0';
linebp=p=linebuf;
q=genbuf;
do ; while (*p++ = *q++);
getsub();
*(l=addr1++)=putline();
/* if you want marks preserved for join, change the above line to
/* the one commented out here.
/* problem: undo then undoes the join, but gets it wrong. Your choice.
replace(l=addr1++, putline());
*/
if(l != addr2)
delete();
append(getsub, l);
if(autop){
addr1=addr2=dot;
display('p');
}
}
int next_col(col,cp,input)
register int col;
register char *cp;
int input;
{
register c;
c = *cp;
if (c=='\t')
col |= 07;
else if (c<' ' || c=='\177')
error('t'); /* invalid character in x data */
else
if (input && (c==ttybuf.sg_erase || c==ttybuf.sg_kill))
col++; /* One column for the backslash */
return (++col);
}
xform()
{
register char *i, *m, *o;
int *line, insert, change, ic, mc, c;
char *tf, *tl;
if(getchar() != '\n')
error('x');
for (line=addr1; line<=addr2; line++) {
getline(*line, linebuf);
change=FALSE;
dot=line;
for(;;){
puts(linebuf);
pushinp(XTTY, 0, FALSE);
m=rhsbuf;
while ((c = getchar())!='\n') {
if (c == EOF)
error('t'); /* unexpected EOF */
*m++ = c;
if (m==rhsbuf+RHSIZE-1)
error('l'); /* out of space */
}
*m='\0';
if (m==rhsbuf)
break;
change++;
i=linebuf;
o=genbuf;
do ; while (*o++ = *i++);
if (i+(m-rhsbuf) > linebuf+LBSIZE)
error('l'); /* out of space */
i=genbuf;
o=linebuf;
m=rhsbuf;
insert=FALSE;
ic=0;
mc=0;
while (*i && *m && !insert) {
if(*i=='\t' && *m!='#' && *m!='^' && *m!='$') {
ic=next_col(ic,i,FALSE);
tf=m;
tl=m;
do {
if (*m!=' ' && *m!='\t') {
if(*m=='%')
*m=' ';
tl=m+1;
}
mc=next_col(mc,m++,TRUE);
} while (ic>mc && *m && *m!='#' &&
*m!='^' && *m!='$');
if (ic>mc) {
ic=mc;
if (*m)
tl=m;
} else {
if (tl==m)
i++;
else
ic--;
}
while (tf!=tl)
*o++ = *tf++;
} else {
mc=next_col(mc,m,TRUE);
*o = *m;
switch (*m++) {
case ' ':
case '\t':
break;
case '^':
mc=ic;
insert++;
break;
case '$':
i="";
break;
case '#':
ic=next_col(ic,i++,FALSE);
while(*m=='#' && ic>mc)
mc=next_col(mc,m++,TRUE);
if (ic!=mc)
error('t');
break;
case '%':
*o = ' ';
/* fall through */
default:
o++;
ic=next_col(ic,i++,FALSE);
} /* switch */
} /* else */
for (;;) {
if (ic>mc && *m) {
if (*m!=' ' && *m!='\t')
error('t');
mc=next_col(mc,m++,TRUE);
} else if (mc>ic && *i) {
ic=next_col(ic,i,FALSE);
*o++ = *i++;
} else
break;
}
} /* while */
if (mc>ic && m[-1]=='\t')
*o++ = '\t';
if (insert && (*o++ = *m++) == '\0') {
replace(line,putline());
linebp=i;
append(getsub,line);
line++;
addr2++;
change = FALSE;
} else {
while (*m)
*o++ = *m++;
do ; while (*o++ = *i++);
}
}
if (change)
replace(line,putline());
} /* for */
}

184
unix-1985/vars.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* QED
*/
#ifdef VAX
#define BIGTMP LOTSOFBITS
#endif
/* Fake setexit & reset from v6 using setjmp and longjmp */
#include <setjmp.h>
jmp_buf env;
#define setexit() setjmp(env)
#define reset() longjmp(env, 0)
#define TRUE 1
#define FALSE 0
#define LBSIZE 512
#define RHSIZE (LBSIZE/4) /* ed says /2; but that's unreasonable! */
#define NBRA 9
#define EOF (-1)
#define FILERR 0200
#define SAVENEVER 0
#define SAVEIFFIRST 1
#define SAVEALWAYS 2
/*
* Stack types. Must appear in the order as in cspec[]/getchar.
* XTTY, GLOB and BRWS are special types with no corresponding special character.
* Special is never used directly - it is just used in tracing
* pushinp()/getchar.c can be called with a negative index for cspec[]
*/
char special[]; /* "xgBbBcfFlprzN\"\\'" */
#define cspec (special + 3)
#define XTTY 0175
#define GLOB 0176
#define BRWS 0177
#define BUF 0
#define CURBN 1
#define QUOTE 2
#define FILEN 3
#define BFILEN 4
#define TTY 5
#define PAT 6
#define RHS 7
#define STRING 8
#define NEWL 9
#define NOTHING 10
#define BACKSLASH 11
#define LITERAL 12
/*
* Getchar-linked macros
*/
#define ungetchar(c) (peekc = (c))
#define nextchar() (peekc = getchar())
#define NBUFS 56
/*
* The buffer structure. All info associated with each buffer stored here
*/
struct buffer{
int *zero;
int *dot;
int *dol;
char cflag;
char gmark;
}buffer[NBUFS];
struct buffer *curbuf;
/*
* The string structure
* The first NBUFS strings are the registers
* The next NBUFS are the file names
* The next two are the saved pattern and saved right hand side
* The next is the special register for browsing (the `ob' command)
* The next is a file buffer.
* Strings are stored in the `strarea' area and garbage collected
* when the area is full. The NSTRCHARS parameter can be increased
* if you've got lots of core.
* The first two characters of `strarea' form the null string.
* The third and subsequent characters are the storage for non null
* strings.
* The null string has to be stored in this area so that
* the R and S commands write out valid pointers to the null string.
* The last entry in the string structure is used to store the pointer
* to the next free position.
* In string.c strfree is defined as "string[NSTRING].str".
*/
#define NSTRING (NBUFS+NBUFS+4)
#define COUNT (26+'C'-'A')
#define TRUTH (26+'T'-'A')
#define UNIX (26+'U'-'A')
#define FILE(z) (NBUFS+(z))
#define SAVPAT (NBUFS+NBUFS)
#define SAVRHS (SAVPAT+1)
#define BROWSE (SAVRHS+1)
#define FILEBUF (BROWSE+1)
struct string{
int len;
char *str;
}string[NSTRING+1];
#define NSTRCHARS 1024
char strarea[NSTRCHARS + 2];
#define nullstr strarea
#define strchars (&strarea[2])
#define STACKSIZE 16
/*
* The getchar stack.
*/
struct stack{
char type;
char literal;
union{
struct buffer *u1bufptr;
char *u1globp;
}u1;
union{
int u2lineno;
int u2strname;
}u2;
int charno;
}stack[STACKSIZE];
#define bufptr u1.u1bufptr
#define globp u1.u1globp
#define lineno u2.u2lineno
#define strname u2.u2strname
struct stack *stackp;
int peekc;
int lastc;
char line[70];
char *linp;
int savedfile;
char linebuf[LBSIZE];
int *zero;
int *dot;
int *dol;
int *lastdol;
int *endcore;
int *fendcore;
int *addr1;
int *addr2;
char genbuf[LBSIZE];
char *linebp;
#include "sgtty.h"
struct sgttyb ttybuf;
int ninbuf;
int io;
int onhup;
int onquit;
int onintr;
char lasterr;
#define PAGESIZE 22
extern pagesize;
extern char bformat; /* = 'p' */
int appflag;
int cflag;
int cprflag;
int dflag;
int eflag;
int gflag;
int biggflag;
int iflag;
int prflag;
int tflag;
int uflag;
int vflag;
int qok;
int eok;
int initflag;
int nestlevel;
int lastttyc;
int listf;
int tfile;
char *tfname;
char *loc1;
char *loc2;
int names[NBUFS];
char *braslist[NBRA];
char *braelist[NBRA];
int nbra;
int oneline;
int lock;
char bname[]; /* ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~" */
char lchars[]; /* = "pPlL" */
int bbempty; /* whether getc's internal buffer buffer needs reloading */
char *getline();
int *address();
char *getenv();
long lseek();
char *sbrk();