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