1
0
mirror of synced 2026-02-26 16:23:33 +00:00
Files
1985-04-16 21:25:23 +00:00

677 lines
12 KiB
C

/*% 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();
}
}