|
|
1.1 root 1: /*% cc -c -O %
2: */
3: #include "vars.h"
4: #define UP 1
5: #define DOWN 0
6: char lchars[]="pPlL";
7: struct buffer *curbuf = buffer;
8: char *linp = line;
9: int appflag = 0;
10: int pagesize = PAGESIZE;
11: int prflag = 0; /* prflag==1 ==> much code to get it right. use the startup buffer */
12: int lastttyc = '\n';
13: int gflag = 0;
14: int tflag = 0;
15: int vflag = 0; /* initialization code turns it on */
16: int uflag = 's';
17: int dflag = 0;
18: int initflag = 1;
19: int *option[] = {
20: &cflag, &dflag, &eflag, &iflag, &prflag,&tflag, &vflag,
21: };
22: char opcs[] = "cdeipTv";
23: int tfile = -1;
24: struct sgttyb ttybuf = { 0, 0, '\b', '\b', /*0*/};
25: char QEDFILE[]="QEDFILE";
26: int (*pending)();
27:
28: rescue()
29: {
30: /* Save in qed.hup:[ab]q on hangup */
31: signal(SIGHUP,1);
32: if (lock) {
33: pending = rescue;
34: return;
35: }
36: startstring();
37: copystring("qed.hup");
38: setstring(FILEBUF);
39: savall();
40: exit(SIGHUP);
41: }
42: char *filea()
43: {
44: register struct string *sp;
45: register int i, d;
46: char c;
47:
48: sp = &string[FILEBUF];
49: startstring();
50: d = 0;
51: i = 0;
52: while((c=sp->str[i]) != '\0'){
53: addstring(c);
54: i++;
55: if(c == '/')
56: d = i;
57: }
58: if((i-d) > 12) /* file name is >= 13 characters long */
59: string[NSTRING].str -= (i-(d+12)); /* truncate string */
60: copystring(":aq");
61: setstring(FILEBUF);
62: return(sp->str);
63: }
64:
65: char *fileb()
66: {
67: register struct string *sp;
68:
69: sp = &string[FILEBUF];
70: sp->str[sp->len-2] = 'b';
71: return(sp->str);
72: }
73: savall()
74: {
75: register fi;
76:
77: syncbuf();
78: addr1 = buffer[0].zero + 1;
79: addr2 = buffer[NBUFS-1].dol;
80: if(addr1 > addr2){
81: error('$');
82: return;
83: }
84: if((io = creat(filea(), 0644)) < 0)
85: error('o'|FILERR);
86: putfile();
87: exfile();
88: if((fi = creat(fileb(), 0644)) < 0)
89: error('o'|FILERR);
90: write(fi, (char *)buffer, sizeof buffer);
91: write(fi, strarea, sizeof strarea);
92: lock++;
93: shiftstring(DOWN);
94: write(fi, (char *)string, sizeof string);
95: shiftstring(UP);
96: unlock();
97: close(fi);
98: }
99: restor()
100: {
101: register i, t;
102: register struct buffer *b;
103: int fi;
104: int getfile();
105: curbuf = buffer;
106: i = (int)curbuf->zero;
107: if((t = open(filea(), 0)) < 0){
108: lastc = '\n';
109: error('o'|FILERR);
110: }
111: initio();
112: init();
113: io = t;
114: ninbuf = 0;
115: append(getfile, dol);
116: exfile();
117: if((fi = open(fileb(),0)) < 0)
118: error('o'|FILERR);
119: lock++;
120: if(read(fi,(char *)buffer,sizeof buffer) != sizeof buffer
121: || read(fi, strarea, sizeof strarea) != sizeof strarea
122: || read(fi, (char *)string, sizeof string) != sizeof string)
123: error('R');
124: close(fi);
125: shiftstring(UP);
126: /*
127: * This code is incredibly sleazy and machine dependent for the 11.
128: * Sorry. There is no good reason why we don't have a shiftbuf():
129: * feel free to write one (but lock before you call it!).
130: */
131: t = (int)buffer[0].zero;
132: if(i != t){
133: i -= t;
134: i >>= 1;
135: for(b = buffer;b <= &buffer[NBUFS-1];b++){
136: b->zero += i;
137: b->dot += i;
138: b->dol += i;
139: }
140: }
141: newbuf(0);
142: error(0); /* ==> error, but don't print anything. calls unlock() */
143: }
144:
145: /*
146: * On INTR, generate error '?'
147: */
148:
149: interrupt()
150: {
151: signal(SIGINT, interrupt);
152: if (lock) {
153: pending = interrupt;
154: return;
155: }
156: if(iflag){
157: unlink(tfname);
158: exit(SIGINT);
159: }
160: linp=line;
161: putchar('\n');
162: lastc = '\n';
163: error('?');
164: }
165:
166: /*
167: * Unlock: exit a critical section, invoking any pending signal routines.
168: */
169:
170: unlock()
171: {
172: register (*p)();
173:
174: p = pending;
175: pending = 0;
176: lock = 0;
177: if (p)
178: (*p)();
179: }
180:
181: char cleanup[] = "ba z~:\n";
182: char setvflag[] = "ov?";
183: char boot1[] = "G/^[";
184: char boot2[] = "].+\t./r\n";
185:
186: main(argc, argv)
187: char **argv;
188: {
189: register char *p1;
190: register i;
191: char buf;
192: int rvflag;
193: char *startup=(char *)0;
194:
195: argv++;
196: onquit = signal(SIGQUIT, 1);
197: onhup = signal(SIGHUP, 1);
198: onintr = signal(SIGINT, 1);
199: rvflag = 1;
200: for(i=0;i!=NSTRING;i++){
201: string[i].str = nullstr;
202: string[i].len=0;
203: }
204: /* initialize strfree */
205: string[NSTRING].str = strchars;
206: while(argc > 1 && **argv=='-'){
207: switch(argv[0][1]){
208: casedefault:
209: default:
210: rvflag = 0;
211: break;
212: case 'q':
213: /* allow debugging quits? */
214: signal(SIGQUIT, 0);
215: break;
216: case 'i':
217: /* allow interrupt quits? */
218: iflag++;
219: break;
220: case 'e':
221: /* Exit on error? */
222: eflag++;
223: break;
224: case 'x':
225: if(argc == 2)
226: goto casedefault;
227: startup = argv[1];
228: argv++;
229: --argc;
230: }
231: argv++;
232: --argc;
233: }
234: gtty(0,&ttybuf);
235: if(startup==0)
236: startup = getenv(QEDFILE);
237: fendcore = (int *)sbrk(0);
238: curbuf = &buffer[0];
239: init();
240: if (onhup != 1)
241: signal(SIGHUP, rescue);
242: if (onintr != 1)
243: signal(SIGINT, interrupt);
244: /*
245: * Build the initialization code in register z~
246: */
247: if(startup){
248: startstring();
249: copystring(startup);
250: setstring(FILE(NBUFS-1));
251: p1 = "b~ r\n\\b~\n";
252: } else
253: p1 = "";
254: startstring();
255: copystring(p1);
256: setvflag[2] = "rs"[rvflag];
257: copystring(setvflag);
258: /*
259: * z~ now has startup-buffer initialization; prepare the file list
260: * and generate a GLOBUF to read them in
261: */
262: if(--argc > 0) {
263: if(argc >= 53) /* buffer names a-zA-Z */
264: puts("?i");
265: else {
266: copystring(boot1);
267: for(i=0; i<argc; i++) /* argument files only */
268: addstring(bname[i]);
269: copystring(boot2);
270: copystring(cleanup);
271: setstring(NBUFS-1);
272: buf = 0;
273: while(argc > 0) {
274: startstring();
275: copystring(*argv);
276: setstring(FILE(buf++));
277: --argc;
278: argv++;
279: }
280: }
281: }
282: else{
283: copystring(cleanup);
284: setstring(NBUFS-1);
285: }
286: pushinp(STRING, NBUFS-1, FALSE);
287: setexit();
288: lastttyc = '\n';
289: commands();
290: unlink(tfname);
291: exit(lasterr);
292: }
293:
294: int noaddr;
295: commands()
296: {
297: register int *a;
298: register c, lastsep;
299: int getfile(), gettty();
300: int r;
301: int changed;
302: long locn, lseek();
303: int startline;
304:
305: for (;;) {
306: startline = (lastttyc == '\n' && peekc == 0);
307: cprflag=prflag;
308: c = '\n';
309: for (addr1=0;;) {
310: lastsep = c;
311: a=address();
312: c=getchar();
313: if (c!=',' && c!=';')
314: break;
315: if (lastsep==',')
316: error('a');
317: if (a==0) {
318: a = zero+1;
319: if (a>dol)
320: --a;
321: }
322: addr1 = a;
323: if (c==';')
324: dot = a;
325: }
326: if (lastsep!='\n' && a==0)
327: a=dol;
328: if((addr2=a) == 0) {
329: addr2=dot;
330: noaddr = TRUE;
331: } else
332: noaddr = FALSE;
333:
334: if(addr1 == 0)
335: addr1 = addr2;
336:
337: cprflag=FALSE;
338: switch(c){
339: case 'a':
340: setdot();
341: setapp();
342: append(gettty, addr2);
343: continue;
344: case 'b':
345: if(posn((c=nextchar()), bname)<0){ /* browse command */
346: setdot();
347: nonzero();
348: bcom();
349: continue;
350: }
351: c = getaz('b');
352: setnoaddr();
353: chngbuf(c);
354: continue;
355: case 'c':
356: setdot();
357: nonzero();
358: setapp();
359: append(gettty, addr2);
360: a = dot-(addr2-addr1+1);
361: delete();
362: dot = a;
363: continue;
364: case 'd':
365: if(posn(nextchar(),"\377\npPlL \t") < 0)
366: error('x');
367: delete();
368: continue;
369: case 'E':
370: case 'e':
371: setnoaddr();
372: if(c=='e' && !eok && cflag){
373: eok=TRUE;
374: error('e');
375: }
376: newfile(TRUE, SAVEALWAYS, "");
377: delall();
378: addr1 = zero;
379: addr2 = zero;
380: modified(); /* In case file open causes error */
381: goto caseread;
382: case 'f':
383: setnoaddr();
384: if((c = getchar()) != '\n'){
385: ungetchar(c);
386: if(newfile(FALSE, SAVEALWAYS, string[savedfile].str))
387: modified();
388: if(vflag)
389: ncom('f');
390: }
391: else
392: ncom('f');
393: continue;
394: case 'g':
395: global(TRUE);
396: continue;
397: case 'G':
398: globuf(TRUE);
399: continue;
400: case 'h':
401: setnoaddr();
402: if(nextchar()=='\n')
403: error('x');
404: if('0'<=peekc && peekc<='9')
405: until(TRUE, getnum());
406: else
407: until(FALSE, 0);
408: continue;
409: case 'i':
410: setdot();
411: nonzero();
412: setapp();
413: append(gettty, addr2-1);
414: continue;
415: case 'j':
416: setdot();
417: if (addr1 == addr2 && lastsep == '\n'){
418: addr1--;
419: if(addr1 <= zero)
420: error('$');
421: }
422: nonzero();
423: join();
424: continue;
425: case 'k':
426: c = getaz(c);
427: setdot();
428: nonzero();
429: names[c] = *addr2 | 01;
430: continue;
431: case 'm':
432: move(FALSE);
433: continue;
434: case 'n':
435: case 'N':
436: ncom(c);
437: continue;
438: case 'o':
439: setnoaddr();
440: c = getchar();
441: r=posn(c, opcs);
442: if(r >= 0)
443: setreset(option[r]);
444: else switch(c) {
445: case 'B':
446: if(nextchar() == '\n')
447: clearstring(BROWSE);
448: else {
449: startstring();
450: while((c=getchar()) != '\n')
451: addstring(c);
452: copystring("\\N");
453: setstring(BROWSE);
454: }
455: break;
456: case '?':
457: if ((r = posn(getchar(), opcs)) < 0)
458: error('O');
459: settruth(*option[r]);
460: break;
461: case 'q':
462: c = getchar();
463: if(c=='s' || c =='r')
464: signal(SIGQUIT, c=='r');
465: else
466: error('x');
467: break;
468: case 'u':
469: c = getchar();
470: if(c == 'r')
471: uflag = 0;
472: else if(posn(c, "slu") >= 0)
473: uflag = c;
474: else
475: error('x');
476: break;
477: case 'b':
478: if((r=getnum()) > 0)
479: pagesize = r;
480: if(posn(nextchar(), lchars) >=0)
481: bformat = getchar();
482: break;
483: default:
484: error('x');
485: }
486: continue;
487: case '\n':
488: if (a==0) {
489: if(stackp != &stack[0] || !startline)
490: continue;
491: if(*string[BROWSE].str){
492: pushinp(BRWS, 0, FALSE);
493: continue;
494: }
495: a = dot+1;
496: addr2 = a;
497: addr1 = a;
498: }
499: if (lastsep==';')
500: addr1 = a;
501: c = 'p'; /* fall through */
502: case 'L':
503: case 'l':
504: case 'p':
505: case 'P':
506: display(c);
507: continue;
508: case EOF:
509: return;
510: case 'Q':
511: case 'q':
512: setnoaddr();
513: if(c!=EOF && (!startline || getchar()!='\n'))
514: error('x');
515: if(c!='Q' && !qok){
516: register struct buffer *bp;
517: syncbuf();
518: qok=TRUE;
519: for(bp=buffer; bp<&buffer[NBUFS]; bp++)
520: if(bp->cflag && (bp->dol>bp->zero ||
521: string[FILE(bp-buffer)].str[0]))
522: error('q');
523: }
524: unlink(tfname);
525: exit(lasterr);
526: case 'r':
527: newfile(TRUE, SAVEIFFIRST, string[savedfile].str);
528: caseread:
529: if((io = open(string[FILEBUF].str, 0)) < 0){
530: if(initflag){
531: putchar('?');
532: putchar('o');
533: putchar(' ');
534: puts(string[FILEBUF].str);
535: continue;
536: }
537: lastc = '\n';
538: error('o'|FILERR);
539: }
540: setall();
541: changed = (zero!=dol);
542: ninbuf = 0;
543: append(getfile, addr2);
544: if(eqstr(string[savedfile].str, string[FILEBUF].str))
545: if(cflag = changed) /* Assignment = */
546: modified();
547: /* else append got cflag right */
548: exfile();
549: continue;
550: case 'R':
551: setnoaddr();
552: newfile(TRUE, SAVENEVER, "q");
553: restor();
554: continue;
555: case 's':
556: setdot();
557: nonzero();
558: substitute(stackp != &stack[0], -1);
559: continue;
560: case 'S':
561: setnoaddr();
562: newfile(TRUE, SAVENEVER, "q");
563: savall();
564: continue;
565: case 't':
566: move(TRUE);
567: continue;
568: case 'u':
569: setnoaddr();
570: undo();
571: modified();
572: continue;
573: case 'v':
574: global(FALSE);
575: continue;
576: case 'V':
577: globuf(FALSE);
578: continue;
579: case 'W':
580: case 'w':
581: if(addr2==0 && dol==zero)
582: error('$');
583: setall();
584: if(newfile(TRUE, SAVEIFFIRST, string[savedfile].str))
585: changed = cflag;
586: else
587: changed = (addr1>(zero+1) || addr2!=dol);
588: if(c=='w' || (io=open(string[FILEBUF].str,1))==-1){
589: Create:
590: if ((io = creat(string[FILEBUF].str, 0666)) < 0)
591: error('o'|FILERR);
592: }else{
593: if((locn=lseek(io, 0L, 2)) == -1L)
594: goto Create;
595: if(locn != 0L) /* W on non-empty file */
596: changed = TRUE; /* PHEW! figured it out */
597: }
598: putfile();
599: if(cflag = changed) /* Assignment = */
600: modified();
601: exfile();
602: continue;
603: case 'x':
604: setdot();
605: nonzero();
606: xform();
607: continue;
608: case 'y':
609: jump();
610: continue;
611: case 'z':
612: strcom(getaz('z'));
613: continue;
614: case 'Z':
615: setnoaddr();
616: if((c=getchar())!=' ' && c!='\n')
617: error('x');
618: delall();
619: cflag=FALSE;
620: clearstring(savedfile);
621: continue;
622: case '"':
623: setdot();
624: dot=addr2;
625: comment();
626: continue;
627: case '=':
628: setall();
629: putdn((addr2-zero)&077777);
630: continue;
631: case '>':
632: case '<':
633: case '|':
634: setall();
635: case '!':
636: Unix(c);
637: continue;
638: case '#':
639: setnoaddr();
640: allnums();
641: continue;
642: case '%':
643: setnoaddr();
644: allstrs();
645: continue;
646: }
647: error('x');
648: }
649: }
650: setreset(opt)
651: register int *opt;
652: {
653: register c;
654:
655: c = getchar();
656: if(c!='s' && c!= 'r')
657: error('x');
658: *opt = (c=='s');
659: }
660: delall(){
661: if(dol!=zero){
662: addr1=zero+1;
663: addr2=dol;
664: delete();
665: }
666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.