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: }

Defined functions

address defined in line 358; used 3 times
advance defined in line 1385; used 5 times
append defined in line 712; used 6 times
backref defined in line 1492; used 2 times
blkio defined in line 905; used 3 times
callunix defined in line 745; used 1 times
cclass defined in line 1505; used 3 times
commands defined in line 149; used 2 times
compile defined in line 1205; used 3 times
compsub defined in line 1046; used 1 times
delete defined in line 774; used 2 times
dosub defined in line 1094; used 2 times
error defined in line 572; used 46 times
execute defined in line 1334; used 4 times
exfile defined in line 539; used 2 times
filename defined in line 502; used 4 times
gdelete defined in line 801; used 1 times
getblock defined in line 868; used 5 times
getchr defined in line 598; used 29 times
getcopy defined in line 1197; used 2 times
getfile defined in line 643; used 2 times
getline defined in line 822; used 6 times
getsub defined in line 1081; used 2 times
gettty defined in line 617; used 4 times
global defined in line 933; used 2 times
init defined in line 915; used 2 times
join defined in line 985; used 1 times
main defined in line 100; never used
move defined in line 1140; used 2 times
newline defined in line 486; used 12 times
nonzero defined in line 480; used 10 times
onhup defined in line 557; used 2 times
onintr defined in line 549; used 3 times
place defined in line 1127; used 3 times
putchr defined in line 1542; used 7 times
putd defined in line 1519; used 3 times
putfile defined in line 677; used 2 times
putline defined in line 840; used 3 times
puts defined in line 1530; used 6 times
quit defined in line 764; used 5 times
rdelete defined in line 782; used 2 times
reverse defined in line 1183; used 6 times
setall defined in line 463; used 4 times
setdot defined in line 455; used 10 times
setnoaddr defined in line 474; used 4 times
substitute defined in line 1007; used 1 times

Defined variables

Q defined in line 33; used 41 times
T defined in line 34; used 2 times
WRERR defined in line 79; used 2 times
addr1 defined in line 49; used 29 times
addr2 defined in line 50; used 40 times
anymarks defined in line 81; used 3 times
braelist defined in line 83; used 9 times
braslist defined in line 82; used 7 times
circfl defined in line 45; used 4 times
col defined in line 65; used 5 times
count defined in line 52; used 8 times
dol defined in line 48; used 29 times
dot defined in line 47; used 25 times
expbuf defined in line 44; used 6 times
fchange defined in line 87; used 13 times
file defined in line 41; used 8 times
genbuf defined in line 51; used 20 times
globp defined in line 66; used 11 times
iblock defined in line 74; used 4 times
ibuff defined in line 73; used 4 times
ichanged defined in line 77; used 4 times
io defined in line 56; used 14 times
lastc defined in line 39; used 15 times
line defined in line 1539; used 5 times
linebp defined in line 54; used 3 times
linebuf defined in line 42; used 16 times
linp defined in line 1540; used 3 times
listf defined in line 64; used 5 times
loc1 defined in line 70; used 5 times
loc2 defined in line 71; used 6 times
locs defined in line 72; used 3 times
names defined in line 80; used 6 times
nbra defined in line 84; used 6 times
nextip defined in line 53; used 2 times
ninbuf defined in line 55; used 4 times
nlall defined in line 89; used 4 times
nleft defined in line 78; used 5 times
oblock defined in line 76; used 5 times
obuff defined in line 75; used 3 times
peekc defined in line 38; used 10 times
pflag defined in line 57; used 4 times
rhsbuf defined in line 43; used 3 times
savedfile defined in line 40; used 5 times
savej defined in line 98; used 2 times
sccsid defined in line 2; never used
subnewa defined in line 85; used 5 times
subolda defined in line 86; used 2 times
tfile defined in line 67; used 4 times
tfname defined in line 69; used 4 times
tline defined in line 68; used 4 times
vflag defined in line 61; used 5 times
wrapp defined in line 88; used 4 times
zero defined in line 46; used 34 times

Defined macros

CBACK defined in line 29; used 2 times
CBRA defined in line 21; used 2 times
CCHR defined in line 22; used 4 times
CCL defined in line 24; used 3 times
CDOL defined in line 26; used 1 times
CDOT defined in line 23; used 2 times
CEOF defined in line 27; used 2 times
CKET defined in line 28; used 2 times
EOF defined in line 19; used 11 times
ESIZE defined in line 16; used 4 times
FNSIZE defined in line 14; used 2 times
GBSIZE defined in line 17; used 2 times
LBSIZE defined in line 15; used 11 times
NBRA defined in line 18; used 6 times
NCCL defined in line 25; used 2 times
NULL defined in line 13; used 1 times
READ defined in line 35; used 3 times
STAR defined in line 31; used 2 times
WRITE defined in line 36; used 2 times
Last modified: 1987-02-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 11791
Valid CSS Valid XHTML 1.0 Strict