|
|
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.