|
|
1.1 ! root 1: /* ! 2: * Editor ! 3: */ ! 4: ! 5: #include <signal.h> ! 6: #include <setjmp.h> ! 7: ! 8: #define BLKSIZE 512 ! 9: #define NBLK 2047 ! 10: ! 11: #define NULL 0 ! 12: #define FNSIZE 128 ! 13: #define LBSIZE 512 ! 14: #define ESIZE 256 ! 15: #define GBSIZE 256 ! 16: #define NBRA 5 ! 17: #define EOF -1 ! 18: #define KSIZE 9 ! 19: ! 20: #define CBRA 1 ! 21: #define CCHR 2 ! 22: #define CDOT 4 ! 23: #define CCL 6 ! 24: #define NCCL 8 ! 25: #define CDOL 10 ! 26: #define CEOF 11 ! 27: #define CKET 12 ! 28: #define CBACK 14 ! 29: ! 30: #define STAR 01 ! 31: ! 32: char Q[] = ""; ! 33: char T[] = "TMP"; ! 34: #define READ 0 ! 35: #define WRITE 1 ! 36: ! 37: int peekc; ! 38: int lastc; ! 39: char savedfile[FNSIZE]; ! 40: char file[FNSIZE]; ! 41: char linebuf[LBSIZE]; ! 42: char rhsbuf[LBSIZE/2]; ! 43: char expbuf[ESIZE+4]; ! 44: int circfl; ! 45: int *zero; ! 46: int *dot; ! 47: int *dol; ! 48: int given; ! 49: int *addr1; ! 50: int *addr2; ! 51: char genbuf[LBSIZE]; ! 52: long count; ! 53: char *nextip; ! 54: char *linebp; ! 55: int ninbuf; ! 56: int io; ! 57: int pflag; ! 58: long lseek(); ! 59: int (*oldhup)(); ! 60: int (*oldquit)(); ! 61: int vflag = 1; ! 62: int oflag; ! 63: int listf; ! 64: int listn; ! 65: int col; ! 66: char *globp; ! 67: int tfile = -1; ! 68: int tline; ! 69: char *tfname; ! 70: char *loc1; ! 71: char *loc2; ! 72: char *locs; ! 73: char ibuff[512]; ! 74: int iblock = -1; ! 75: char obuff[512]; ! 76: int oblock = -1; ! 77: int ichanged; ! 78: int nleft; ! 79: char WRERR[] = "WRITE ERROR"; ! 80: int names[26]; ! 81: int anymarks; ! 82: char *braslist[NBRA]; ! 83: char *braelist[NBRA]; ! 84: int nbra; ! 85: int subnewa; ! 86: int subolda; ! 87: int fchange; ! 88: int wrapp; ! 89: int bpagesize = 20; ! 90: unsigned nlall = 128; ! 91: ! 92: int *address(); ! 93: char *getline(); ! 94: char *getblock(); ! 95: char *place(); ! 96: char *mktemp(); ! 97: char *malloc(); ! 98: char *realloc(); ! 99: jmp_buf savej; ! 100: ! 101: main(argc, argv) ! 102: char **argv; ! 103: { ! 104: register char *p1, *p2; ! 105: extern int onintr(), quit(), onhup(); ! 106: int (*oldintr)(); ! 107: ! 108: oldquit = signal(SIGQUIT, SIG_IGN); ! 109: oldhup = signal(SIGHUP, SIG_IGN); ! 110: oldintr = signal(SIGINT, SIG_IGN); ! 111: if ((int)signal(SIGTERM, SIG_IGN) == 0) ! 112: signal(SIGTERM, quit); ! 113: argv++; ! 114: while (argc > 1 && **argv=='-') { ! 115: switch((*argv)[1]) { ! 116: ! 117: case '\0': ! 118: vflag = 0; ! 119: break; ! 120: ! 121: case 'q': ! 122: signal(SIGQUIT, SIG_DFL); ! 123: vflag = 1; ! 124: break; ! 125: ! 126: case 'o': ! 127: oflag = 1; ! 128: break; ! 129: } ! 130: argv++; ! 131: argc--; ! 132: } ! 133: if (oflag) { ! 134: p1 = "/dev/stdout"; ! 135: p2 = savedfile; ! 136: while (*p2++ = *p1++) ! 137: ; ! 138: } ! 139: if (argc>1) { ! 140: p1 = *argv; ! 141: p2 = savedfile; ! 142: while (*p2++ = *p1++) ! 143: if (p2 >= &savedfile[sizeof(savedfile)]) ! 144: p2--; ! 145: globp = "r"; ! 146: } ! 147: zero = (int *)malloc(nlall*sizeof(int)); ! 148: tfname = mktemp("/tmp/eXXXXX"); ! 149: init(); ! 150: if (((int)oldintr&01) == 0) ! 151: signal(SIGINT, onintr); ! 152: if (((int)oldhup&01) == 0) ! 153: signal(SIGHUP, onhup); ! 154: setjmp(savej); ! 155: commands(); ! 156: quit(); ! 157: } ! 158: ! 159: commands() ! 160: { ! 161: int getfile(), gettty(); ! 162: register *a1, c; ! 163: register int temp; ! 164: char lastsep; ! 165: ! 166: for (;;) { ! 167: if (pflag) { ! 168: pflag = 0; ! 169: addr1 = addr2 = dot; ! 170: print(); ! 171: } ! 172: c = '\n'; ! 173: for (addr1 = 0;;) { ! 174: lastsep = c; ! 175: a1 = address(); ! 176: c = getchr(); ! 177: if (c!=',' && c!=';') ! 178: break; ! 179: if (lastsep==',') ! 180: error(Q); ! 181: if (a1==0) { ! 182: a1 = zero+1; ! 183: if (a1>dol) ! 184: a1--; ! 185: } ! 186: addr1 = a1; ! 187: if (c==';') ! 188: dot = a1; ! 189: } ! 190: if (lastsep!='\n' && a1==0) ! 191: a1 = dol; ! 192: if ((addr2=a1)==0) { ! 193: given = 0; ! 194: addr2 = dot; ! 195: } ! 196: else ! 197: given = 1; ! 198: if (addr1==0) ! 199: addr1 = addr2; ! 200: switch(c) { ! 201: ! 202: case 'a': ! 203: add(0); ! 204: continue; ! 205: ! 206: case 'b': ! 207: nonzero(); ! 208: browse(); ! 209: continue; ! 210: ! 211: case 'c': ! 212: nonzero(); ! 213: newline(); ! 214: rdelete(addr1, addr2); ! 215: append(gettty, addr1-1); ! 216: continue; ! 217: ! 218: case 'd': ! 219: nonzero(); ! 220: newline(); ! 221: rdelete(addr1, addr2); ! 222: continue; ! 223: ! 224: case 'E': ! 225: fchange = 0; ! 226: c = 'e'; ! 227: case 'e': ! 228: setnoaddr(); ! 229: if (vflag && fchange) { ! 230: fchange = 0; ! 231: error(Q); ! 232: } ! 233: filename(c); ! 234: init(); ! 235: addr2 = zero; ! 236: goto caseread; ! 237: ! 238: case 'f': ! 239: setnoaddr(); ! 240: filename(c); ! 241: puts(savedfile); ! 242: continue; ! 243: ! 244: case 'g': ! 245: global(1); ! 246: continue; ! 247: ! 248: case 'i': ! 249: add(-1); ! 250: continue; ! 251: ! 252: ! 253: case 'j': ! 254: if (!given) ! 255: addr2++; ! 256: newline(); ! 257: join(); ! 258: continue; ! 259: ! 260: case 'k': ! 261: nonzero(); ! 262: if ((c = getchr()) < 'a' || c > 'z') ! 263: error(Q); ! 264: newline(); ! 265: names[c-'a'] = *addr2 & ~01; ! 266: anymarks |= 01; ! 267: continue; ! 268: ! 269: case 'm': ! 270: move(0); ! 271: continue; ! 272: ! 273: case 'n': ! 274: listn++; ! 275: newline(); ! 276: print(); ! 277: continue; ! 278: ! 279: case '\n': ! 280: if (a1==0) { ! 281: a1 = dot+1; ! 282: addr2 = a1; ! 283: addr1 = a1; ! 284: } ! 285: if (lastsep==';') ! 286: addr1 = a1; ! 287: print(); ! 288: continue; ! 289: ! 290: case 'l': ! 291: listf++; ! 292: case 'p': ! 293: case 'P': ! 294: newline(); ! 295: print(); ! 296: continue; ! 297: ! 298: case 'Q': ! 299: fchange = 0; ! 300: case 'q': ! 301: setnoaddr(); ! 302: newline(); ! 303: quit(); ! 304: ! 305: case 'r': ! 306: filename(c); ! 307: caseread: ! 308: if ((io = open(file, 0)) < 0) { ! 309: lastc = '\n'; ! 310: error(file); ! 311: } ! 312: setwide(); ! 313: squeeze(0); ! 314: ninbuf = 0; ! 315: c = zero != dol; ! 316: append(getfile, addr2); ! 317: exfile(); ! 318: fchange = c; ! 319: continue; ! 320: ! 321: case 's': ! 322: nonzero(); ! 323: substitute(globp!=0); ! 324: continue; ! 325: ! 326: case 't': ! 327: move(1); ! 328: continue; ! 329: ! 330: case 'u': ! 331: nonzero(); ! 332: newline(); ! 333: if ((*addr2&~01) != subnewa) ! 334: error(Q); ! 335: *addr2 = subolda; ! 336: dot = addr2; ! 337: continue; ! 338: ! 339: case 'v': ! 340: global(0); ! 341: continue; ! 342: ! 343: case 'W': ! 344: wrapp++; ! 345: case 'w': ! 346: setwide(); ! 347: squeeze(dol>zero); ! 348: if ((temp = getchr()) != 'q' && temp != 'Q') { ! 349: peekc = temp; ! 350: temp = 0; ! 351: } ! 352: filename(c); ! 353: if(!wrapp || ! 354: ((io = open(file,1)) == -1) || ! 355: ((lseek(io, 0L, 2)) == -1)) ! 356: if ((io = creat(file, 0666)) < 0) ! 357: error(file); ! 358: wrapp = 0; ! 359: if (dol > zero) ! 360: putfile(); ! 361: exfile(); ! 362: if (addr1<=zero+1 && addr2==dol) ! 363: fchange = 0; ! 364: if (temp == 'Q') ! 365: fchange = 0; ! 366: if (temp) ! 367: quit(); ! 368: continue; ! 369: ! 370: case '=': ! 371: setwide(); ! 372: squeeze(0); ! 373: newline(); ! 374: count = addr2 - zero; ! 375: putd(); ! 376: putchr('\n'); ! 377: continue; ! 378: ! 379: case '!': ! 380: callunix(); ! 381: continue; ! 382: ! 383: case EOF: ! 384: return; ! 385: ! 386: } ! 387: error(Q); ! 388: } ! 389: } ! 390: ! 391: print(){ ! 392: register int *a1; ! 393: nonzero(); ! 394: a1 = addr1; ! 395: do { ! 396: if (listn) { ! 397: count = a1-zero; ! 398: putd(); ! 399: putchr('\t'); ! 400: } ! 401: puts(getline(*a1++)); ! 402: } while (a1 <= addr2); ! 403: dot = addr2; ! 404: listf = 0; ! 405: listn = 0; ! 406: pflag = 0; ! 407: } ! 408: ! 409: int * ! 410: address() ! 411: { ! 412: register int sign, *a; ! 413: int opcnt, nextopand, *b; ! 414: register int c; ! 415: ! 416: nextopand = -1; ! 417: sign = 1; ! 418: opcnt = 0; ! 419: a = dot; ! 420: do { ! 421: do c = getchr(); while (c==' ' || c=='\t'); ! 422: if ('0'<=c && c<='9') { ! 423: peekc = c; ! 424: if (!opcnt) ! 425: a = zero; ! 426: a += sign*getnum(); ! 427: } else switch (c) { ! 428: case '$': ! 429: a = dol; ! 430: /* fall through */ ! 431: case '.': ! 432: if (opcnt) ! 433: error(Q); ! 434: break; ! 435: case '\'': ! 436: c = getchr(); ! 437: if (opcnt || c<'a' || 'z'<c) ! 438: error(Q); ! 439: a = zero; ! 440: do a++; while (a<=dol && names[c-'a']!=(*a&~01)); ! 441: break; ! 442: case '?': ! 443: sign = -sign; ! 444: /* fall through */ ! 445: case '/': ! 446: compile(c); ! 447: b = a; ! 448: for (;;) { ! 449: a += sign; ! 450: if (a<zero) ! 451: a = dol; ! 452: if (a>dol) ! 453: a = zero; ! 454: if (execute(a)) ! 455: break; ! 456: if (a==b) ! 457: error(Q); ! 458: } ! 459: break; ! 460: default: ! 461: if (nextopand == opcnt) { ! 462: a += sign; ! 463: if (a<zero || dol<a) ! 464: continue; /* error(Q); */ ! 465: } ! 466: if (c!='+' && c!='-' && c!='^') { ! 467: peekc = c; ! 468: if (opcnt==0) ! 469: a = 0; ! 470: return (a); ! 471: } ! 472: sign = 1; ! 473: if (c!='+') ! 474: sign = -sign; ! 475: nextopand = ++opcnt; ! 476: continue; ! 477: } ! 478: sign = 1; ! 479: opcnt++; ! 480: } while (zero<=a && a<=dol); ! 481: error(Q); ! 482: /*NOTREACHED*/ ! 483: } ! 484: int getnum() ! 485: { ! 486: register int r, c; ! 487: ! 488: r = 0; ! 489: while ((c=getchr())>='0' && c<='9') ! 490: r = r*10 + c - '0'; ! 491: peekc = c; ! 492: return (r); ! 493: } ! 494: ! 495: setwide() ! 496: { ! 497: if (!given) { ! 498: addr1 = zero + (dol>zero); ! 499: addr2 = dol; ! 500: } ! 501: } ! 502: ! 503: setnoaddr() ! 504: { ! 505: if (given) ! 506: error(Q); ! 507: } ! 508: ! 509: nonzero() ! 510: { ! 511: squeeze(1); ! 512: } ! 513: ! 514: squeeze(i) ! 515: int i; ! 516: { ! 517: if (addr1<zero+i || addr2>dol || addr1>addr2) ! 518: error(Q); ! 519: } ! 520: ! 521: newline() ! 522: { ! 523: register c; ! 524: ! 525: if ((c = getchr()) == '\n' || c == EOF) ! 526: return; ! 527: if (c=='p' || c=='l' || c=='n') { ! 528: pflag++; ! 529: if (c=='l') ! 530: listf++; ! 531: else if (c=='n') ! 532: listn++; ! 533: if ((c=getchr())=='\n') ! 534: return; ! 535: } ! 536: error(Q); ! 537: } ! 538: ! 539: filename(comm) ! 540: { ! 541: register char *p1, *p2; ! 542: register c; ! 543: ! 544: count = 0; ! 545: c = getchr(); ! 546: if (c=='\n' || c==EOF) { ! 547: p1 = savedfile; ! 548: if (*p1==0 && comm!='f') ! 549: error(Q); ! 550: p2 = file; ! 551: while (*p2++ = *p1++) ! 552: ; ! 553: return; ! 554: } ! 555: if (c!=' ') ! 556: error(Q); ! 557: while ((c = getchr()) == ' ') ! 558: ; ! 559: if (c=='\n') ! 560: error(Q); ! 561: p1 = file; ! 562: do { ! 563: if (p1 >= &file[sizeof(file)-1] || c==' ' || c==EOF) ! 564: error(Q); ! 565: *p1++ = c; ! 566: } while ((c = getchr()) != '\n'); ! 567: *p1++ = 0; ! 568: if (savedfile[0]==0 || comm=='e' || comm=='f') { ! 569: p1 = savedfile; ! 570: p2 = file; ! 571: while (*p1++ = *p2++) ! 572: ; ! 573: } ! 574: } ! 575: ! 576: exfile() ! 577: { ! 578: close(io); ! 579: io = -1; ! 580: if (vflag) { ! 581: putd(); ! 582: putchr('\n'); ! 583: } ! 584: } ! 585: ! 586: onintr() ! 587: { ! 588: signal(SIGINT, onintr); ! 589: putchr('\n'); ! 590: lastc = '\n'; ! 591: error(Q); ! 592: } ! 593: ! 594: onhup() ! 595: { ! 596: signal(SIGINT, SIG_IGN); ! 597: signal(SIGHUP, SIG_IGN); ! 598: if (dol > zero) { ! 599: addr1 = zero+1; ! 600: addr2 = dol; ! 601: io = creat("ed.hup", 0666); ! 602: if (io > 0) ! 603: putfile(); ! 604: } ! 605: fchange = 0; ! 606: quit(); ! 607: } ! 608: ! 609: error(s) ! 610: char *s; ! 611: { ! 612: register c; ! 613: ! 614: wrapp = 0; ! 615: listf = 0; ! 616: listn = 0; ! 617: putchr('?'); ! 618: puts(s); ! 619: count = 0; ! 620: lseek(0, (long)0, 2); ! 621: pflag = 0; ! 622: if (globp) ! 623: lastc = '\n'; ! 624: globp = 0; ! 625: peekc = lastc; ! 626: if(lastc) ! 627: while ((c = getchr()) != '\n' && c != EOF) ! 628: ; ! 629: if (io > 0) { ! 630: close(io); ! 631: io = -1; ! 632: } ! 633: longjmp(savej, 1); ! 634: } ! 635: ! 636: getchr() ! 637: { ! 638: char c; ! 639: if (lastc=peekc) { ! 640: peekc = 0; ! 641: return(lastc); ! 642: } ! 643: if (globp) { ! 644: if ((lastc = *globp++) != 0) ! 645: return(lastc); ! 646: globp = 0; ! 647: return(EOF); ! 648: } ! 649: if (read(0, &c, 1) <= 0) ! 650: return(lastc = EOF); ! 651: lastc = c&0177; ! 652: return(lastc); ! 653: } ! 654: ! 655: gettty() ! 656: { ! 657: register int rc; ! 658: ! 659: if (rc = gety()) ! 660: return(rc); ! 661: if (linebuf[0]=='.' && linebuf[1]==0) ! 662: return(EOF); ! 663: return(0); ! 664: } ! 665: ! 666: gety() ! 667: { ! 668: register int c; ! 669: register char *gf; ! 670: register char *p; ! 671: ! 672: p = linebuf; ! 673: gf = globp; ! 674: while ((c = getchr()) != '\n') { ! 675: if (c==EOF) { ! 676: if (gf) ! 677: peekc = c; ! 678: return(c); ! 679: } ! 680: if ((c &= 0177) == 0) ! 681: continue; ! 682: *p++ = c; ! 683: if (p >= &linebuf[LBSIZE-2]) ! 684: error(Q); ! 685: } ! 686: ! 687: *p++ = 0; ! 688: return(0); ! 689: } ! 690: ! 691: getfile() ! 692: { ! 693: register c; ! 694: register char *lp, *fp; ! 695: ! 696: lp = linebuf; ! 697: fp = nextip; ! 698: do { ! 699: if (--ninbuf < 0) { ! 700: if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) ! 701: if (lp>linebuf) { ! 702: puts("'\\n' appended"); ! 703: *genbuf = '\n'; ! 704: } ! 705: else return(EOF); ! 706: fp = genbuf; ! 707: while(fp < &genbuf[ninbuf]) { ! 708: if (*fp++ & 0200) ! 709: break; ! 710: } ! 711: fp = genbuf; ! 712: } ! 713: c = *fp++; ! 714: if (c=='\0') ! 715: continue; ! 716: if (c&0200 || lp >= &linebuf[LBSIZE]) { ! 717: lastc = '\n'; ! 718: error(Q); ! 719: } ! 720: *lp++ = c; ! 721: count++; ! 722: } while (c != '\n'); ! 723: *--lp = 0; ! 724: nextip = fp; ! 725: return(0); ! 726: } ! 727: ! 728: putfile() ! 729: { ! 730: int *a1, n; ! 731: register char *fp, *lp; ! 732: register nib; ! 733: ! 734: nib = BLKSIZE; ! 735: fp = genbuf; ! 736: a1 = addr1; ! 737: do { ! 738: lp = getline(*a1++); ! 739: for (;;) { ! 740: if (--nib < 0) { ! 741: n = fp-genbuf; ! 742: if(write(io, genbuf, n) != n) { ! 743: puts(WRERR); ! 744: error(Q); ! 745: } ! 746: nib = BLKSIZE-1; ! 747: fp = genbuf; ! 748: } ! 749: count++; ! 750: if ((*fp++ = *lp++) == 0) { ! 751: fp[-1] = '\n'; ! 752: break; ! 753: } ! 754: } ! 755: } while (a1 <= addr2); ! 756: n = fp-genbuf; ! 757: if(write(io, genbuf, n) != n) { ! 758: puts(WRERR); ! 759: error(Q); ! 760: } ! 761: } ! 762: ! 763: append(f, a) ! 764: int *a; ! 765: int (*f)(); ! 766: { ! 767: register *a1, *a2, *rdot; ! 768: int nline, tl; ! 769: ! 770: nline = 0; ! 771: dot = a; ! 772: while ((*f)() == 0) { ! 773: if ((dol-zero)+1 >= nlall) { ! 774: int *ozero = zero; ! 775: nlall += 1024; ! 776: if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) { ! 777: error("MEM?"); ! 778: onhup(); ! 779: } ! 780: dot += zero - ozero; ! 781: dol += zero - ozero; ! 782: } ! 783: tl = putline(); ! 784: nline++; ! 785: a1 = ++dol; ! 786: a2 = a1+1; ! 787: rdot = ++dot; ! 788: while (a1 > rdot) ! 789: *--a2 = *--a1; ! 790: *rdot = tl; ! 791: } ! 792: return(nline); ! 793: } ! 794: ! 795: add(i) ! 796: int i; ! 797: { ! 798: if (i && (given || dol>zero)) { ! 799: addr1--; ! 800: addr2--; ! 801: } ! 802: squeeze(0); ! 803: newline(); ! 804: append(gettty, addr2); ! 805: } ! 806: ! 807: browse() ! 808: { ! 809: register forward, n; ! 810: static bformat; /*0*/ ! 811: static bnum; /*0*/ ! 812: forward=1; ! 813: if((peekc=getchr())!='\n'){ ! 814: if (peekc=='-' || peekc=='+') { ! 815: if(peekc=='-') ! 816: forward=0; ! 817: getchr(); ! 818: } ! 819: if((n=getnum())>0) ! 820: bpagesize=n; ! 821: } ! 822: newline(); ! 823: if (pflag) { ! 824: bformat=listf; ! 825: bnum=listn; ! 826: } else { ! 827: listf=bformat; ! 828: listn=bnum; ! 829: } ! 830: if (forward) { ! 831: addr1=addr2; ! 832: if((addr2+=bpagesize)>dol) ! 833: addr2=dol; ! 834: } else { ! 835: if((addr1=addr2-bpagesize)<=zero) ! 836: addr1=zero+1; ! 837: } ! 838: print(); ! 839: } ! 840: ! 841: callunix() ! 842: { ! 843: register (*savint)(), pid, rpid; ! 844: int retcode; ! 845: ! 846: setnoaddr(); ! 847: if ((pid = fork()) == 0) { ! 848: signal(SIGHUP, oldhup); ! 849: signal(SIGQUIT, oldquit); ! 850: execl("/bin/sh", "sh", "-t", 0); ! 851: exit(0100); ! 852: } ! 853: savint = signal(SIGINT, SIG_IGN); ! 854: while ((rpid = wait(&retcode)) != pid && rpid != -1) ! 855: ; ! 856: signal(SIGINT, savint); ! 857: if (vflag) { ! 858: puts("!"); ! 859: } ! 860: } ! 861: ! 862: quit() ! 863: { ! 864: if (vflag && fchange && dol!=zero) { ! 865: fchange = 0; ! 866: error(Q); ! 867: } ! 868: unlink(tfname); ! 869: exit(0); ! 870: } ! 871: ! 872: rdelete(ad1, ad2) ! 873: int *ad1, *ad2; ! 874: { ! 875: register *a1, *a2, *a3; ! 876: ! 877: a1 = ad1; ! 878: a2 = ad2+1; ! 879: a3 = dol; ! 880: dol -= a2 - a1; ! 881: do { ! 882: *a1++ = *a2++; ! 883: } while (a2 <= a3); ! 884: a1 = ad1; ! 885: if (a1 > dol) ! 886: a1 = dol; ! 887: dot = a1; ! 888: fchange = 1; ! 889: } ! 890: ! 891: gdelete() ! 892: { ! 893: register *a1, *a2, *a3; ! 894: ! 895: a3 = dol; ! 896: for (a1=zero; (*a1&01)==0; a1++) ! 897: if (a1>=a3) ! 898: return; ! 899: for (a2=a1+1; a2<=a3;) { ! 900: if (*a2&01) { ! 901: a2++; ! 902: dot = a1; ! 903: } else ! 904: *a1++ = *a2++; ! 905: } ! 906: dol = a1-1; ! 907: if (dot>dol) ! 908: dot = dol; ! 909: fchange = 1; ! 910: } ! 911: ! 912: char * ! 913: getline(tl) ! 914: { ! 915: register char *bp, *lp; ! 916: register nl; ! 917: ! 918: lp = linebuf; ! 919: bp = getblock(tl, READ); ! 920: nl = nleft; ! 921: tl &= ~((BLKSIZE/2)-1); ! 922: while (*lp++ = *bp++) ! 923: if (--nl == 0) { ! 924: bp = getblock(tl+=(BLKSIZE/2), READ); ! 925: nl = nleft; ! 926: } ! 927: return(linebuf); ! 928: } ! 929: ! 930: putline() ! 931: { ! 932: register char *bp, *lp; ! 933: register nl; ! 934: int tl; ! 935: ! 936: fchange = 1; ! 937: lp = linebuf; ! 938: tl = tline; ! 939: bp = getblock(tl, WRITE); ! 940: nl = nleft; ! 941: tl &= ~((BLKSIZE/2)-1); ! 942: while (*bp = *lp++) { ! 943: if (*bp++ == '\n') { ! 944: *--bp = 0; ! 945: linebp = lp; ! 946: break; ! 947: } ! 948: if (--nl == 0) { ! 949: bp = getblock(tl+=(BLKSIZE/2), WRITE); ! 950: nl = nleft; ! 951: } ! 952: } ! 953: nl = tline; ! 954: tline += (((lp-linebuf)+03)>>1)&077776; ! 955: return(nl); ! 956: } ! 957: ! 958: char * ! 959: getblock(atl, iof) ! 960: unsigned atl; ! 961: { ! 962: extern read(), write(); ! 963: register bno, off; ! 964: register char *p1, *p2; ! 965: register int n; ! 966: ! 967: bno = (atl/(BLKSIZE/2)); ! 968: off = (atl<<1) & (BLKSIZE-1) & ~03; ! 969: if (bno >= NBLK) { ! 970: lastc = '\n'; ! 971: error(T); ! 972: } ! 973: nleft = BLKSIZE - off; ! 974: if (bno==iblock) { ! 975: ichanged |= iof; ! 976: return(ibuff+off); ! 977: } ! 978: if (bno==oblock) ! 979: return(obuff+off); ! 980: if (iof==READ) { ! 981: if (ichanged) ! 982: blkio(iblock, ibuff, write); ! 983: ichanged = 0; ! 984: iblock = bno; ! 985: blkio(bno, ibuff, read); ! 986: return(ibuff+off); ! 987: } ! 988: if (oblock>=0) ! 989: blkio(oblock, obuff, write); ! 990: oblock = bno; ! 991: return(obuff+off); ! 992: } ! 993: ! 994: blkio(b, buf, iofcn) ! 995: char *buf; ! 996: int (*iofcn)(); ! 997: { ! 998: lseek(tfile, (long)b*BLKSIZE, 0); ! 999: if ((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) { ! 1000: error(T); ! 1001: } ! 1002: } ! 1003: ! 1004: init() ! 1005: { ! 1006: register *markp; ! 1007: ! 1008: close(tfile); ! 1009: tline = 2; ! 1010: for (markp = names; markp < &names[26]; ) ! 1011: *markp++ = 0; ! 1012: subnewa = 0; ! 1013: anymarks = 0; ! 1014: iblock = -1; ! 1015: oblock = -1; ! 1016: ichanged = 0; ! 1017: close(creat(tfname, 0600)); ! 1018: tfile = open(tfname, 2); ! 1019: dot = dol = zero; ! 1020: } ! 1021: ! 1022: global(k) ! 1023: { ! 1024: register char *gp; ! 1025: register c; ! 1026: register int *a1; ! 1027: char globuf[GBSIZE]; ! 1028: ! 1029: if (globp) ! 1030: error(Q); ! 1031: setwide(); ! 1032: squeeze(dol>zero); ! 1033: if ((c=getchr())=='\n') ! 1034: error(Q); ! 1035: compile(c); ! 1036: gp = globuf; ! 1037: while ((c = getchr()) != '\n') { ! 1038: if (c==EOF) ! 1039: error(Q); ! 1040: if (c=='\\') { ! 1041: c = getchr(); ! 1042: if (c!='\n') ! 1043: *gp++ = '\\'; ! 1044: } ! 1045: *gp++ = c; ! 1046: if (gp >= &globuf[GBSIZE-2]) ! 1047: error(Q); ! 1048: } ! 1049: if (gp == globuf) ! 1050: *gp++ = 'p'; ! 1051: *gp++ = '\n'; ! 1052: *gp++ = 0; ! 1053: for (a1=zero; a1<=dol; a1++) { ! 1054: *a1 &= ~01; ! 1055: if (a1>=addr1 && a1<=addr2 && execute(a1)==k) ! 1056: *a1 |= 01; ! 1057: } ! 1058: /* ! 1059: * Special case: g/.../d (avoid n^2 algorithm) ! 1060: */ ! 1061: if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') { ! 1062: gdelete(); ! 1063: return; ! 1064: } ! 1065: for (a1=zero; a1<=dol; a1++) { ! 1066: if (*a1 & 01) { ! 1067: *a1 &= ~01; ! 1068: dot = a1; ! 1069: globp = globuf; ! 1070: commands(); ! 1071: a1 = zero; ! 1072: } ! 1073: } ! 1074: } ! 1075: ! 1076: join() ! 1077: { ! 1078: register char *gp, *lp; ! 1079: register *a1; ! 1080: ! 1081: nonzero(); ! 1082: gp = genbuf; ! 1083: for (a1=addr1; a1<=addr2; a1++) { ! 1084: lp = getline(*a1); ! 1085: while (*gp = *lp++) ! 1086: if (gp++ >= &genbuf[LBSIZE-2]) ! 1087: error(Q); ! 1088: } ! 1089: lp = linebuf; ! 1090: gp = genbuf; ! 1091: while (*lp++ = *gp++) ! 1092: ; ! 1093: *addr1 = putline(); ! 1094: if (addr1<addr2) ! 1095: rdelete(addr1+1, addr2); ! 1096: dot = addr1; ! 1097: } ! 1098: ! 1099: substitute(inglob) ! 1100: { ! 1101: register *markp, *a1, nl; ! 1102: int gsubf; ! 1103: int getsub(); ! 1104: int n, m; ! 1105: ! 1106: n = getnum(); /* OK even if n==0 */ ! 1107: gsubf = compsub(); ! 1108: for (a1 = addr1; a1 <= addr2; a1++) { ! 1109: if (execute(a1)){ ! 1110: int *ozero; ! 1111: m = n; ! 1112: do { ! 1113: if (--m <= 0) { ! 1114: dosub(); ! 1115: if (!gsubf) ! 1116: break; ! 1117: } ! 1118: } while (execute((int *)0)); ! 1119: if (m <= 0) { ! 1120: inglob |= 01; ! 1121: subnewa = putline(); ! 1122: *a1 &= ~01; ! 1123: if (anymarks) { ! 1124: for (markp = names; markp < &names[26]; markp++) ! 1125: if (*markp == *a1) ! 1126: *markp = subnewa; ! 1127: } ! 1128: subolda = *a1; ! 1129: *a1 = subnewa; ! 1130: ozero = zero; ! 1131: nl = append(getsub, a1); ! 1132: nl += zero-ozero; ! 1133: a1 += nl; ! 1134: addr2 += nl; ! 1135: } ! 1136: } ! 1137: } ! 1138: if (inglob==0) ! 1139: error(Q); ! 1140: } ! 1141: ! 1142: compsub() ! 1143: { ! 1144: register seof, c; ! 1145: register char *p; ! 1146: ! 1147: if ((seof = getchr()) == '\n' || seof == ' ') ! 1148: error(Q); ! 1149: compile(seof); ! 1150: p = rhsbuf; ! 1151: for (;;) { ! 1152: c = getchr(); ! 1153: if (c=='\\') ! 1154: c = getchr() | 0200; ! 1155: if (c=='\n') { ! 1156: if (globp && globp[0]) /* last '\n' does not count */ ! 1157: c |= 0200; ! 1158: else { ! 1159: peekc = c; ! 1160: pflag++; ! 1161: break; ! 1162: } ! 1163: } ! 1164: if (c==seof) ! 1165: break; ! 1166: *p++ = c; ! 1167: if (p >= &rhsbuf[LBSIZE/2]) ! 1168: error(Q); ! 1169: } ! 1170: *p++ = 0; ! 1171: if ((peekc = getchr()) == 'g') { ! 1172: peekc = 0; ! 1173: newline(); ! 1174: return(1); ! 1175: } ! 1176: newline(); ! 1177: return(0); ! 1178: } ! 1179: ! 1180: getsub() ! 1181: { ! 1182: register char *p1, *p2; ! 1183: ! 1184: p1 = linebuf; ! 1185: if ((p2 = linebp) == 0) ! 1186: return(EOF); ! 1187: while (*p1++ = *p2++) ! 1188: ; ! 1189: linebp = 0; ! 1190: return(0); ! 1191: } ! 1192: ! 1193: dosub() ! 1194: { ! 1195: register char *lp, *sp, *rp; ! 1196: int c; ! 1197: ! 1198: lp = linebuf; ! 1199: sp = genbuf; ! 1200: rp = rhsbuf; ! 1201: while (lp < loc1) ! 1202: *sp++ = *lp++; ! 1203: while (c = *rp++&0377) { ! 1204: if (c=='&') { ! 1205: sp = place(sp, loc1, loc2); ! 1206: continue; ! 1207: } else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') { ! 1208: sp = place(sp, braslist[c-'1'], braelist[c-'1']); ! 1209: continue; ! 1210: } ! 1211: *sp++ = c&0177; ! 1212: if (sp >= &genbuf[LBSIZE]) ! 1213: error(Q); ! 1214: } ! 1215: lp = loc2; ! 1216: loc2 = sp - genbuf + linebuf; ! 1217: while (*sp++ = *lp++) ! 1218: if (sp >= &genbuf[LBSIZE]) ! 1219: error(Q); ! 1220: lp = linebuf; ! 1221: sp = genbuf; ! 1222: while (*lp++ = *sp++) ! 1223: ; ! 1224: } ! 1225: ! 1226: char * ! 1227: place(sp, l1, l2) ! 1228: register char *sp, *l1, *l2; ! 1229: { ! 1230: ! 1231: while (l1 < l2) { ! 1232: *sp++ = *l1++; ! 1233: if (sp >= &genbuf[LBSIZE]) ! 1234: error(Q); ! 1235: } ! 1236: return(sp); ! 1237: } ! 1238: ! 1239: move(cflag) ! 1240: { ! 1241: register int *adt, *ad1, *ad2; ! 1242: int getcopy(); ! 1243: ! 1244: nonzero(); ! 1245: if ((adt = address())==0) /* address() guarantees addr is in range */ ! 1246: error(Q); ! 1247: newline(); ! 1248: if (cflag) { ! 1249: int *ozero, delta; ! 1250: ad1 = dol; ! 1251: ozero = zero; ! 1252: append(getcopy, ad1++); ! 1253: ad2 = dol; ! 1254: delta = zero - ozero; ! 1255: ad1 += delta; ! 1256: adt += delta; ! 1257: } else { ! 1258: ad2 = addr2; ! 1259: for (ad1 = addr1; ad1 <= ad2;) ! 1260: *ad1++ &= ~01; ! 1261: ad1 = addr1; ! 1262: } ! 1263: ad2++; ! 1264: if (adt<ad1) { ! 1265: dot = adt + (ad2-ad1); ! 1266: if ((++adt)==ad1) ! 1267: return; ! 1268: reverse(adt, ad1); ! 1269: reverse(ad1, ad2); ! 1270: reverse(adt, ad2); ! 1271: } else if (adt >= ad2) { ! 1272: dot = adt++; ! 1273: reverse(ad1, ad2); ! 1274: reverse(ad2, adt); ! 1275: reverse(ad1, adt); ! 1276: } else ! 1277: error(Q); ! 1278: fchange = 1; ! 1279: } ! 1280: ! 1281: reverse(a1, a2) ! 1282: register int *a1, *a2; ! 1283: { ! 1284: register int t; ! 1285: ! 1286: for (;;) { ! 1287: t = *--a2; ! 1288: if (a2 <= a1) ! 1289: return; ! 1290: *a2 = *a1; ! 1291: *a1++ = t; ! 1292: } ! 1293: } ! 1294: ! 1295: getcopy() ! 1296: { ! 1297: if (addr1 > addr2) ! 1298: return(EOF); ! 1299: getline(*addr1++); ! 1300: return(0); ! 1301: } ! 1302: ! 1303: compile(aeof) ! 1304: { ! 1305: register eof, c; ! 1306: register char *ep; ! 1307: char *lastep; ! 1308: char bracket[NBRA], *bracketp; ! 1309: int cclcnt; ! 1310: ! 1311: ep = expbuf; ! 1312: eof = aeof; ! 1313: bracketp = bracket; ! 1314: if ((c = getchr()) == '\n') { ! 1315: peekc = c; ! 1316: c = eof; ! 1317: } ! 1318: if (c == eof) { ! 1319: if (*ep==0) ! 1320: error(Q); ! 1321: return; ! 1322: } ! 1323: circfl = 0; ! 1324: nbra = 0; ! 1325: if (c=='^') { ! 1326: c = getchr(); ! 1327: circfl++; ! 1328: } ! 1329: peekc = c; ! 1330: lastep = 0; ! 1331: for (;;) { ! 1332: if (ep >= &expbuf[ESIZE]) ! 1333: goto cerror; ! 1334: c = getchr(); ! 1335: if (c == '\n') { ! 1336: peekc = c; ! 1337: c = eof; ! 1338: } ! 1339: if (c==eof) { ! 1340: if (bracketp != bracket) ! 1341: goto cerror; ! 1342: *ep++ = CEOF; ! 1343: return; ! 1344: } ! 1345: if (c!='*') ! 1346: lastep = ep; ! 1347: switch (c) { ! 1348: ! 1349: case '\\': ! 1350: if ((c = getchr())=='(') { ! 1351: if (nbra >= NBRA) ! 1352: goto cerror; ! 1353: *bracketp++ = nbra; ! 1354: *ep++ = CBRA; ! 1355: *ep++ = nbra++; ! 1356: continue; ! 1357: } ! 1358: if (c == ')') { ! 1359: if (bracketp <= bracket) ! 1360: goto cerror; ! 1361: *ep++ = CKET; ! 1362: *ep++ = *--bracketp; ! 1363: continue; ! 1364: } ! 1365: if (c>='1' && c<'1'+NBRA) { ! 1366: *ep++ = CBACK; ! 1367: *ep++ = c-'1'; ! 1368: continue; ! 1369: } ! 1370: *ep++ = CCHR; ! 1371: if (c=='\n') ! 1372: goto cerror; ! 1373: *ep++ = c; ! 1374: continue; ! 1375: ! 1376: case '.': ! 1377: *ep++ = CDOT; ! 1378: continue; ! 1379: ! 1380: case '\n': ! 1381: goto cerror; ! 1382: ! 1383: case '*': ! 1384: if (lastep==0 || *lastep==CBRA || *lastep==CKET) ! 1385: goto defchar; ! 1386: *lastep |= STAR; ! 1387: continue; ! 1388: ! 1389: case '$': ! 1390: if ((peekc=getchr()) != eof && peekc!='\n') ! 1391: goto defchar; ! 1392: *ep++ = CDOL; ! 1393: continue; ! 1394: ! 1395: case '[': ! 1396: *ep++ = CCL; ! 1397: *ep++ = 0; ! 1398: cclcnt = 1; ! 1399: if ((c=getchr()) == '^') { ! 1400: c = getchr(); ! 1401: ep[-2] = NCCL; ! 1402: } ! 1403: do { ! 1404: if (c=='\n') ! 1405: goto cerror; ! 1406: if (c=='-' && ep[-1]!=0) { ! 1407: if ((c=getchr())==']') { ! 1408: *ep++ = '-'; ! 1409: cclcnt++; ! 1410: break; ! 1411: } ! 1412: while (ep[-1]<c) { ! 1413: *ep = ep[-1]+1; ! 1414: ep++; ! 1415: cclcnt++; ! 1416: if (ep>=&expbuf[ESIZE]) ! 1417: goto cerror; ! 1418: } ! 1419: } ! 1420: *ep++ = c; ! 1421: cclcnt++; ! 1422: if (ep >= &expbuf[ESIZE]) ! 1423: goto cerror; ! 1424: } while ((c = getchr()) != ']'); ! 1425: lastep[1] = cclcnt; ! 1426: continue; ! 1427: ! 1428: defchar: ! 1429: default: ! 1430: *ep++ = CCHR; ! 1431: *ep++ = c; ! 1432: } ! 1433: } ! 1434: cerror: ! 1435: expbuf[0] = 0; ! 1436: nbra = 0; ! 1437: error(Q); ! 1438: } ! 1439: ! 1440: execute(addr) ! 1441: int *addr; ! 1442: { ! 1443: register char *p1, *p2; ! 1444: register c; ! 1445: ! 1446: for (c=0; c<NBRA; c++) { ! 1447: braslist[c] = 0; ! 1448: braelist[c] = 0; ! 1449: } ! 1450: if (addr == (int *)0) { ! 1451: if (circfl) ! 1452: return(0); ! 1453: locs = p1 = loc2; ! 1454: } else { ! 1455: if (addr==zero) ! 1456: return(0); ! 1457: p1 = getline(*addr); ! 1458: locs = 0; ! 1459: } ! 1460: p2 = expbuf; ! 1461: if (circfl) { ! 1462: loc1 = p1; ! 1463: return(advance(p1, p2)); ! 1464: } ! 1465: /* fast check for first character */ ! 1466: if (*p2==CCHR) { ! 1467: c = p2[1]; ! 1468: do { ! 1469: if (*p1!=c) ! 1470: continue; ! 1471: if (advance(p1, p2)) { ! 1472: loc1 = p1; ! 1473: return(1); ! 1474: } ! 1475: } while (*p1++); ! 1476: return(0); ! 1477: } ! 1478: /* regular algorithm */ ! 1479: do { ! 1480: if (advance(p1, p2)) { ! 1481: loc1 = p1; ! 1482: return(1); ! 1483: } ! 1484: } while (*p1++); ! 1485: return(0); ! 1486: } ! 1487: ! 1488: advance(lp, ep) ! 1489: register char *ep, *lp; ! 1490: { ! 1491: register char *curlp; ! 1492: int i; ! 1493: ! 1494: for (;;) switch (*ep++) { ! 1495: ! 1496: case CCHR: ! 1497: if (*ep++ == *lp++) ! 1498: continue; ! 1499: return(0); ! 1500: ! 1501: case CDOT: ! 1502: if (*lp++) ! 1503: continue; ! 1504: return(0); ! 1505: ! 1506: case CDOL: ! 1507: if (*lp==0) ! 1508: continue; ! 1509: return(0); ! 1510: ! 1511: case CEOF: ! 1512: loc2 = lp; ! 1513: return(1); ! 1514: ! 1515: case CCL: ! 1516: if (cclass(ep, *lp++, 1)) { ! 1517: ep += *ep; ! 1518: continue; ! 1519: } ! 1520: return(0); ! 1521: ! 1522: case NCCL: ! 1523: if (cclass(ep, *lp++, 0)) { ! 1524: ep += *ep; ! 1525: continue; ! 1526: } ! 1527: return(0); ! 1528: ! 1529: case CBRA: ! 1530: braslist[*ep++] = lp; ! 1531: continue; ! 1532: ! 1533: case CKET: ! 1534: braelist[*ep++] = lp; ! 1535: continue; ! 1536: ! 1537: case CBACK: ! 1538: if (braelist[i = *ep++]==0) ! 1539: error(Q); ! 1540: if (backref(i, lp)) { ! 1541: lp += braelist[i] - braslist[i]; ! 1542: continue; ! 1543: } ! 1544: return(0); ! 1545: ! 1546: case CBACK|STAR: ! 1547: if (braelist[i = *ep++] == 0) ! 1548: error(Q); ! 1549: curlp = lp; ! 1550: while (backref(i, lp)) ! 1551: lp += braelist[i] - braslist[i]; ! 1552: while (lp >= curlp) { ! 1553: if (advance(lp, ep)) ! 1554: return(1); ! 1555: lp -= braelist[i] - braslist[i]; ! 1556: } ! 1557: continue; ! 1558: ! 1559: case CDOT|STAR: ! 1560: curlp = lp; ! 1561: while (*lp++) ! 1562: ; ! 1563: goto star; ! 1564: ! 1565: case CCHR|STAR: ! 1566: curlp = lp; ! 1567: while (*lp++ == *ep) ! 1568: ; ! 1569: ep++; ! 1570: goto star; ! 1571: ! 1572: case CCL|STAR: ! 1573: case NCCL|STAR: ! 1574: curlp = lp; ! 1575: while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))) ! 1576: ; ! 1577: ep += *ep; ! 1578: goto star; ! 1579: ! 1580: star: ! 1581: do { ! 1582: lp--; ! 1583: if (lp==locs) ! 1584: break; ! 1585: if (advance(lp, ep)) ! 1586: return(1); ! 1587: } while (lp > curlp); ! 1588: return(0); ! 1589: ! 1590: default: ! 1591: error(Q); ! 1592: } ! 1593: } ! 1594: ! 1595: backref(i, lp) ! 1596: register i; ! 1597: register char *lp; ! 1598: { ! 1599: register char *bp; ! 1600: ! 1601: bp = braslist[i]; ! 1602: while (*bp++ == *lp++) ! 1603: if (bp >= braelist[i]) ! 1604: return(1); ! 1605: return(0); ! 1606: } ! 1607: ! 1608: cclass(set, c, af) ! 1609: register char *set; ! 1610: register c; ! 1611: { ! 1612: register n; ! 1613: ! 1614: if (c==0) ! 1615: return(0); ! 1616: n = *set++; ! 1617: while (--n) ! 1618: if (*set++ == c) ! 1619: return(af); ! 1620: return(!af); ! 1621: } ! 1622: ! 1623: putd() ! 1624: { ! 1625: register r; ! 1626: ! 1627: r = count%10; ! 1628: count /= 10; ! 1629: if (count) ! 1630: putd(); ! 1631: putchr(r + '0'); ! 1632: } ! 1633: ! 1634: puts(sp) ! 1635: register char *sp; ! 1636: { ! 1637: col = 0; ! 1638: while (*sp) ! 1639: putchr(*sp++); ! 1640: putchr('\n'); ! 1641: } ! 1642: ! 1643: char line[70]; ! 1644: char *linp = line; ! 1645: ! 1646: putchr(ac) ! 1647: { ! 1648: register char *lp; ! 1649: register c; ! 1650: ! 1651: lp = linp; ! 1652: c = ac; ! 1653: if (listf) { ! 1654: if (c=='\n') { ! 1655: if (linp!=line && linp[-1]==' ') { ! 1656: *lp++ = '\\'; ! 1657: *lp++ = 'n'; ! 1658: } ! 1659: } else { ! 1660: if (col > (72-4-2)) { ! 1661: col = 8; ! 1662: *lp++ = '\\'; ! 1663: *lp++ = '\n'; ! 1664: *lp++ = '\t'; ! 1665: } ! 1666: col++; ! 1667: if (c=='\b' || c=='\t' || c=='\\') { ! 1668: *lp++ = '\\'; ! 1669: if (c=='\b') ! 1670: c = 'b'; ! 1671: else if (c=='\t') ! 1672: c = 't'; ! 1673: col++; ! 1674: } else if (c<' ' || c=='\177') { ! 1675: *lp++ = '\\'; ! 1676: *lp++ = (c>>6) +'0'; ! 1677: *lp++ = ((c>>3)&07)+'0'; ! 1678: c = ( c &07)+'0'; ! 1679: col += 3; ! 1680: } ! 1681: } ! 1682: } ! 1683: *lp++ = c; ! 1684: if(c == '\n' || lp >= &line[64]) { ! 1685: linp = line; ! 1686: write(oflag?2:1, line, lp-line); ! 1687: return; ! 1688: } ! 1689: linp = lp; ! 1690: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.