1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char *sccsid = "@(#)ex_cmds.c	7.10.1 (2.11BSD) 1996/11/19";
   9: #endif
  10: 
  11: #include "ex.h"
  12: #include "ex_argv.h"
  13: #include "ex_temp.h"
  14: #include "ex_tty.h"
  15: #include "ex_vis.h"
  16: 
  17: bool    pflag, nflag;
  18: int poffset;
  19: 
  20: #define nochng()    lchng = chng
  21: 
  22: /*
  23:  * Main loop for command mode command decoding.
  24:  * A few commands are executed here, but main function
  25:  * is to strip command addresses, do a little address oriented
  26:  * processing and call command routines to do the real work.
  27:  */
  28: commands(noprompt, exitoneof)
  29:     bool noprompt, exitoneof;
  30: {
  31:     register line *addr;
  32:     register int c;
  33:     register int lchng;
  34:     int given;
  35:     int seensemi;
  36:     int cnt;
  37:     bool hadpr;
  38: 
  39:     resetflav();
  40:     nochng();
  41:     for (;;) {
  42:         /*
  43: 		 * If dot at last command
  44: 		 * ended up at zero, advance to one if there is a such.
  45: 		 */
  46:         if (dot <= zero) {
  47:             dot = zero;
  48:             if (dol > zero)
  49:                 dot = one;
  50:         }
  51:         shudclob = 0;
  52: 
  53:         /*
  54: 		 * If autoprint or trailing print flags,
  55: 		 * print the line at the specified offset
  56: 		 * before the next command.
  57: 		 */
  58:         if (pflag ||
  59:             lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
  60:             pflag = 0;
  61:             nochng();
  62:             if (dol != zero) {
  63:                 addr1 = addr2 = dot + poffset;
  64:                 if (addr1 < one || addr1 > dol)
  65: error("Offset out-of-bounds|Offset after command too large");
  66:                 setdot1();
  67:                 goto print;
  68:             }
  69:         }
  70:         nochng();
  71: 
  72:         /*
  73: 		 * Print prompt if appropriate.
  74: 		 * If not in global flush output first to prevent
  75: 		 * going into pfast mode unreasonably.
  76: 		 */
  77:         if (inglobal == 0) {
  78:             flush();
  79:             if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
  80:                 putchar(':');
  81:                 hadpr = 1;
  82:             }
  83:             TSYNC();
  84:         }
  85: 
  86:         /*
  87: 		 * Gobble up the address.
  88: 		 * Degenerate addresses yield ".".
  89: 		 */
  90:         addr2 = 0;
  91:         given = seensemi = 0;
  92:         do {
  93:             addr1 = addr2;
  94:             addr = address(0);
  95:             c = getcd();
  96:             if (addr == 0)
  97:                 if (c == ',')
  98:                     addr = dot;
  99:                 else if (addr1 != 0) {
 100:                     addr2 = dot;
 101:                     break;
 102:                 } else
 103:                     break;
 104:             addr2 = addr;
 105:             given++;
 106:             if (c == ';') {
 107:                 c = ',';
 108:                 dot = addr;
 109:                 seensemi = 1;
 110:             }
 111:         } while (c == ',');
 112:         if (c == '%') {
 113:             /* %: same as 1,$ */
 114:             addr1 = one;
 115:             addr2 = dol;
 116:             given = 2;
 117:             c = getchar();
 118:         }
 119:         if (addr1 == 0)
 120:             addr1 = addr2;
 121:         if (c == ':')
 122:             c = getchar();
 123: 
 124:         /*
 125: 		 * Set command name for special character commands.
 126: 		 */
 127:         tailspec(c);
 128: 
 129:         /*
 130: 		 * If called via : escape from open or visual, limit
 131: 		 * the set of available commands here to save work below.
 132: 		 */
 133:         if (inopen) {
 134:             if (c=='\n' || c=='\r' || c==CTRL(d) || c==EOF) {
 135:                 if (addr2)
 136:                     dot = addr2;
 137:                 if (c == EOF)
 138:                     return;
 139:                 continue;
 140:             }
 141:             if (any(c, "o"))
 142: notinvis:
 143:                 tailprim(Command, 1, 1);
 144:         }
 145: choice:
 146:         switch (c) {
 147: 
 148:         case 'a':
 149: 
 150:             switch(peekchar()) {
 151:             case 'b':
 152: /* abbreviate */
 153:                 tail("abbreviate");
 154:                 setnoaddr();
 155:                 mapcmd(0, 1);
 156:                 anyabbrs = 1;
 157:                 continue;
 158:             case 'r':
 159: /* args */
 160:                 tail("args");
 161:                 setnoaddr();
 162:                 eol();
 163:                 pargs();
 164:                 continue;
 165:             }
 166: 
 167: /* append */
 168:             if (inopen)
 169:                 goto notinvis;
 170:             tail("append");
 171:             setdot();
 172:             aiflag = exclam();
 173:             newline();
 174:             vmacchng(0);
 175:             deletenone();
 176:             setin(addr2);
 177:             inappend = 1;
 178:             ignore(append(gettty, addr2));
 179:             inappend = 0;
 180:             nochng();
 181:             continue;
 182: 
 183:         case 'c':
 184:             switch (peekchar()) {
 185: 
 186: /* copy */
 187:             case 'o':
 188:                 tail("copy");
 189:                 vmacchng(0);
 190:                 move();
 191:                 continue;
 192: 
 193: #ifdef CHDIR
 194: /* cd */
 195:             case 'd':
 196:                 tail("cd");
 197:                 goto changdir;
 198: 
 199: /* chdir */
 200:             case 'h':
 201:                 ignchar();
 202:                 if (peekchar() == 'd') {
 203:                     register char *p;
 204:                     tail2of("chdir");
 205: changdir:
 206:                     if (savedfile[0] == '/' || !value(WARN))
 207:                         ignore(exclam());
 208:                     else
 209:                         ignore(quickly());
 210:                     if (skipend()) {
 211:                         p = getenv("HOME");
 212:                         if (p == NULL)
 213:                             error("Home directory unknown");
 214:                     } else
 215:                         getone(), p = file;
 216:                     eol();
 217:                     if (chdir(p) < 0)
 218:                         filioerr(p);
 219:                     if (savedfile[0] != '/')
 220:                         edited = 0;
 221:                     continue;
 222:                 }
 223:                 if (inopen)
 224:                     tailprim("change", 2, 1);
 225:                 tail2of("change");
 226:                 break;
 227: 
 228: #endif
 229:             default:
 230:                 if (inopen)
 231:                     goto notinvis;
 232:                 tail("change");
 233:                 break;
 234:             }
 235: /* change */
 236:             aiflag = exclam();
 237:             setCNL();
 238:             vmacchng(0);
 239:             setin(addr1);
 240:             delete(0);
 241:             inappend = 1;
 242:             ignore(append(gettty, addr1 - 1));
 243:             inappend = 0;
 244:             nochng();
 245:             continue;
 246: 
 247: /* delete */
 248:         case 'd':
 249:             /*
 250: 			 * Caution: dp and dl have special meaning already.
 251: 			 */
 252:             tail("delete");
 253:             c = cmdreg();
 254:             setCNL();
 255:             vmacchng(0);
 256:             if (c)
 257:                 YANKreg(c);
 258:             delete(0);
 259:             appendnone();
 260:             continue;
 261: 
 262: /* edit */
 263: /* ex */
 264:         case 'e':
 265:             tail(peekchar() == 'x' ? "ex" : "edit");
 266: editcmd:
 267:             if (!exclam() && chng)
 268:                 c = 'E';
 269:             filename(c);
 270:             if (c == 'E') {
 271:                 ungetchar(lastchar());
 272:                 ignore(quickly());
 273:             }
 274:             setnoaddr();
 275: doecmd:
 276:             init();
 277:             addr2 = zero;
 278:             laste++;
 279:             sync();
 280:             rop(c);
 281: #ifdef VMUNIX
 282:             tlaste();
 283: #endif
 284:             laste = 0;
 285:             sync();
 286:             nochng();
 287:             continue;
 288: 
 289: /* file */
 290:         case 'f':
 291:             tail("file");
 292:             setnoaddr();
 293:             filename(c);
 294:             noonl();
 295: /*
 296: 			synctmp();
 297: */
 298:             continue;
 299: 
 300: /* global */
 301:         case 'g':
 302:             tail("global");
 303:             global(!exclam());
 304:             nochng();
 305:             continue;
 306: 
 307: /* insert */
 308:         case 'i':
 309:             if (inopen)
 310:                 goto notinvis;
 311:             tail("insert");
 312:             setdot();
 313:             nonzero();
 314:             aiflag = exclam();
 315:             newline();
 316:             vmacchng(0);
 317:             deletenone();
 318:             setin(addr2);
 319:             inappend = 1;
 320:             ignore(append(gettty, addr2 - 1));
 321:             inappend = 0;
 322:             if (dot == zero && dol > zero)
 323:                 dot = one;
 324:             nochng();
 325:             continue;
 326: 
 327: /* join */
 328:         case 'j':
 329:             tail("join");
 330:             c = exclam();
 331:             setcount();
 332:             nonzero();
 333:             newline();
 334:             vmacchng(0);
 335:             if (given < 2 && addr2 != dol)
 336:                 addr2++;
 337:             join(c);
 338:             continue;
 339: 
 340: /* k */
 341:         case 'k':
 342: casek:
 343:             pastwh();
 344:             c = getchar();
 345:             if (endcmd(c))
 346:                 serror("Mark what?|%s requires following letter", Command);
 347:             newline();
 348:             if (!islower(c))
 349:                 error("Bad mark|Mark must specify a letter");
 350:             setdot();
 351:             nonzero();
 352:             names[c - 'a'] = *addr2 &~ 01;
 353:             anymarks = 1;
 354:             continue;
 355: 
 356: /* list */
 357:         case 'l':
 358:             tail("list");
 359:             setCNL();
 360:             ignorf(setlist(1));
 361:             pflag = 0;
 362:             goto print;
 363: 
 364:         case 'm':
 365:             if (peekchar() == 'a') {
 366:                 ignchar();
 367:                 if (peekchar() == 'p') {
 368: /* map */
 369:                     tail2of("map");
 370:                     setnoaddr();
 371:                     mapcmd(0, 0);
 372:                     continue;
 373:                 }
 374: /* mark */
 375:                 tail2of("mark");
 376:                 goto casek;
 377:             }
 378: /* move */
 379:             tail("move");
 380:             vmacchng(0);
 381:             move();
 382:             continue;
 383: 
 384:         case 'n':
 385:             if (peekchar() == 'u') {
 386:                 tail("number");
 387:                 goto numberit;
 388:             }
 389: /* next */
 390:             tail("next");
 391:             setnoaddr();
 392:             ckaw();
 393:             ignore(quickly());
 394:             if (getargs())
 395:                 makargs();
 396:             next();
 397:             c = 'e';
 398:             filename(c);
 399:             goto doecmd;
 400: 
 401: /* open */
 402:         case 'o':
 403:             tail("open");
 404:             oop();
 405:             pflag = 0;
 406:             nochng();
 407:             continue;
 408: 
 409:         case 'p':
 410:         case 'P':
 411:             switch (peekchar()) {
 412: 
 413: /* put */
 414:             case 'u':
 415:                 tail("put");
 416:                 setdot();
 417:                 c = cmdreg();
 418:                 eol();
 419:                 vmacchng(0);
 420:                 if (c)
 421:                     putreg(c);
 422:                 else
 423:                     put();
 424:                 continue;
 425: 
 426:             case 'r':
 427:                 ignchar();
 428:                 if (peekchar() == 'e') {
 429: /* preserve */
 430:                     tail2of("preserve");
 431:                     eol();
 432:                     if (preserve() == 0)
 433:                         error("Preserve failed!");
 434:                     else
 435:                         error("File preserved.");
 436:                 }
 437:                 tail2of("print");
 438:                 break;
 439: 
 440:             default:
 441:                 tail("print");
 442:                 break;
 443:             }
 444: /* print */
 445:             setCNL();
 446:             pflag = 0;
 447: print:
 448:             nonzero();
 449:             if (CL && span() > LINES) {
 450:                 flush1();
 451:                 vclear();
 452:             }
 453:             plines(addr1, addr2, 1);
 454:             continue;
 455: 
 456: /* quit */
 457:         case 'q':
 458:             tail("quit");
 459:             setnoaddr();
 460:             c = quickly();
 461:             eol();
 462:             if (!c)
 463: quit:
 464:                 nomore();
 465:             if (inopen) {
 466:                 vgoto(WECHO, 0);
 467:                 if (!ateopr())
 468:                     vnfl();
 469:                 else {
 470:                     tostop();
 471:                 }
 472:                 flush();
 473:                 setty(normf);
 474:             }
 475:             cleanup(1);
 476:             exit(0);
 477: 
 478:         case 'r':
 479:             if (peekchar() == 'e') {
 480:                 ignchar();
 481:                 switch (peekchar()) {
 482: 
 483: /* rewind */
 484:                 case 'w':
 485:                     tail2of("rewind");
 486:                     setnoaddr();
 487:                     if (!exclam()) {
 488:                         ckaw();
 489:                         if (chng && dol > zero)
 490:                             error("No write@since last change (:rewind! overrides)");
 491:                     }
 492:                     eol();
 493:                     erewind();
 494:                     next();
 495:                     c = 'e';
 496:                     ungetchar(lastchar());
 497:                     filename(c);
 498:                     goto doecmd;
 499: 
 500: /* recover */
 501:                 case 'c':
 502:                     tail2of("recover");
 503:                     setnoaddr();
 504:                     c = 'e';
 505:                     if (!exclam() && chng)
 506:                         c = 'E';
 507:                     filename(c);
 508:                     if (c == 'E') {
 509:                         ungetchar(lastchar());
 510:                         ignore(quickly());
 511:                     }
 512:                     init();
 513:                     addr2 = zero;
 514:                     laste++;
 515:                     sync();
 516:                     recover();
 517:                     rop2();
 518:                     revocer();
 519:                     if (status == 0)
 520:                         rop3(c);
 521:                     if (dol != zero)
 522:                         change();
 523: #ifdef VMUNIX
 524:                     tlaste();
 525: #endif
 526:                     laste = 0;
 527:                     nochng();
 528:                     continue;
 529:                 }
 530:                 tail2of("read");
 531:             } else
 532:                 tail("read");
 533: /* read */
 534:             if (savedfile[0] == 0 && dol == zero)
 535:                 c = 'e';
 536:             pastwh();
 537:             vmacchng(0);
 538:             if (peekchar() == '!') {
 539:                 setdot();
 540:                 ignchar();
 541:                 unix0(0);
 542:                 filter(0);
 543:                 continue;
 544:             }
 545:             filename(c);
 546:             rop(c);
 547:             nochng();
 548:             if (inopen && endline && addr1 > zero && addr1 < dol)
 549:                 dot = addr1 + 1;
 550:             continue;
 551: 
 552:         case 's':
 553:             switch (peekchar()) {
 554:             /*
 555: 			 * Caution: 2nd char cannot be c, g, or r
 556: 			 * because these have meaning to substitute.
 557: 			 */
 558: 
 559: /* set */
 560:             case 'e':
 561:                 tail("set");
 562:                 setnoaddr();
 563:                 set();
 564:                 continue;
 565: 
 566: /* shell */
 567:             case 'h':
 568:                 tail("shell");
 569:                 setNAEOL();
 570:                 vnfl();
 571:                 putpad(TE);
 572:                 flush();
 573:                 unixwt(1, unixex("-i", (char *) 0, 0, 0));
 574:                 vcontin(0);
 575:                 continue;
 576: 
 577: /* source */
 578:             case 'o':
 579: #ifdef notdef
 580:                 if (inopen)
 581:                     goto notinvis;
 582: #endif
 583:                 tail("source");
 584:                 setnoaddr();
 585:                 getone();
 586:                 eol();
 587:                 source(file, 0);
 588:                 continue;
 589: #ifdef SIGTSTP
 590: /* stop, suspend */
 591:             case 't':
 592:                 tail("stop");
 593:                 goto suspend;
 594:             case 'u':
 595:                 tail("suspend");
 596: suspend:
 597:                 if (!ldisc)
 598:                     error("Old tty driver|Not using new tty driver/shell");
 599:                 c = exclam();
 600:                 eol();
 601:                 if (!c)
 602:                     ckaw();
 603:                 onsusp();
 604:                 continue;
 605: #endif
 606: 
 607:             }
 608:             /* fall into ... */
 609: 
 610: /* & */
 611: /* ~ */
 612: /* substitute */
 613:         case '&':
 614:         case '~':
 615:             Command = "substitute";
 616:             if (c == 's')
 617:                 tail(Command);
 618:             vmacchng(0);
 619:             if (!substitute(c))
 620:                 pflag = 0;
 621:             continue;
 622: 
 623: /* t */
 624:         case 't':
 625:             if (peekchar() == 'a') {
 626:                 tail("tag");
 627:                 tagfind(exclam());
 628:                 if (!inopen)
 629:                     lchng = chng - 1;
 630:                 else
 631:                     nochng();
 632:                 continue;
 633:             }
 634:             tail("t");
 635:             vmacchng(0);
 636:             move();
 637:             continue;
 638: 
 639:         case 'u':
 640:             if (peekchar() == 'n') {
 641:                 ignchar();
 642:                 switch(peekchar()) {
 643: /* unmap */
 644:                 case 'm':
 645:                     tail2of("unmap");
 646:                     setnoaddr();
 647:                     mapcmd(1, 0);
 648:                     continue;
 649: /* unabbreviate */
 650:                 case 'a':
 651:                     tail2of("unabbreviate");
 652:                     setnoaddr();
 653:                     mapcmd(1, 1);
 654:                     anyabbrs = 1;
 655:                     continue;
 656:                 }
 657: /* undo */
 658:                 tail2of("undo");
 659:             } else
 660:                 tail("undo");
 661:             setnoaddr();
 662:             markDOT();
 663:             c = exclam();
 664:             newline();
 665:             undo(c);
 666:             continue;
 667: 
 668:         case 'v':
 669:             switch (peekchar()) {
 670: 
 671:             case 'e':
 672: /* version */
 673:                 tail("version");
 674:                 setNAEOL();
 675:                 printf("@(#) Version 3.7, 6/7/85."+5);
 676:                 noonl();
 677:                 continue;
 678: 
 679: /* visual */
 680:             case 'i':
 681:                 tail("visual");
 682:                 if (inopen) {
 683:                     c = 'e';
 684:                     goto editcmd;
 685:                 }
 686:                 vop();
 687:                 pflag = 0;
 688:                 nochng();
 689:                 continue;
 690:             }
 691: /* v */
 692:             tail("v");
 693:             global(0);
 694:             nochng();
 695:             continue;
 696: 
 697: /* write */
 698:         case 'w':
 699:             c = peekchar();
 700:             tail(c == 'q' ? "wq" : "write");
 701: wq:
 702:             if (skipwh() && peekchar() == '!') {
 703:                 pofix();
 704:                 ignchar();
 705:                 setall();
 706:                 unix0(0);
 707:                 filter(1);
 708:             } else {
 709:                 setall();
 710:                 wop(1);
 711:                 nochng();
 712:             }
 713:             if (c == 'q')
 714:                 goto quit;
 715:             continue;
 716: 
 717: /* xit */
 718:         case 'x':
 719:             tail("xit");
 720:             if (!chng)
 721:                 goto quit;
 722:             c = 'q';
 723:             goto wq;
 724: 
 725: /* yank */
 726:         case 'y':
 727:             tail("yank");
 728:             c = cmdreg();
 729:             setcount();
 730:             eol();
 731:             vmacchng(0);
 732:             if (c)
 733:                 YANKreg(c);
 734:             else
 735:                 yank();
 736:             continue;
 737: 
 738: /* z */
 739:         case 'z':
 740:             zop(0);
 741:             pflag = 0;
 742:             continue;
 743: 
 744: /* * */
 745: /* @ */
 746:         case '*':
 747:         case '@':
 748:             c = getchar();
 749:             if (c=='\n' || c=='\r')
 750:                 ungetchar(c);
 751:             if (any(c, "@*\n\r"))
 752:                 c = lastmac;
 753:             if (isupper(c))
 754:                 c = tolower(c);
 755:             if (!islower(c))
 756:                 error("Bad register");
 757:             newline();
 758:             setdot();
 759:             cmdmac(c);
 760:             continue;
 761: 
 762: /* | */
 763:         case '|':
 764:             endline = 0;
 765:             goto caseline;
 766: 
 767: /* \n */
 768:         case '\n':
 769:             endline = 1;
 770: caseline:
 771:             notempty();
 772:             if (addr2 == 0) {
 773:                 if (UP != NOSTR && c == '\n' && !inglobal)
 774:                     c = CTRL(k);
 775:                 if (inglobal)
 776:                     addr1 = addr2 = dot;
 777:                 else {
 778:                     if (dot == dol)
 779:                         error("At EOF|At end-of-file");
 780:                     addr1 = addr2 = dot + 1;
 781:                 }
 782:             }
 783:             setdot();
 784:             nonzero();
 785:             if (seensemi)
 786:                 addr1 = addr2;
 787:             getline(*addr1);
 788:             if (c == CTRL(k)) {
 789:                 flush1();
 790:                 destline--;
 791:                 if (hadpr)
 792:                     shudclob = 1;
 793:             }
 794:             plines(addr1, addr2, 1);
 795:             continue;
 796: 
 797: /* " */
 798:         case '"':
 799:             comment();
 800:             continue;
 801: 
 802: /* # */
 803:         case '#':
 804: numberit:
 805:             setCNL();
 806:             ignorf(setnumb(1));
 807:             pflag = 0;
 808:             goto print;
 809: 
 810: /* = */
 811:         case '=':
 812:             newline();
 813:             setall();
 814:             if (inglobal == 2)
 815:                 pofix();
 816:             printf("%d", lineno(addr2));
 817:             noonl();
 818:             continue;
 819: 
 820: /* ! */
 821:         case '!':
 822:             if (addr2 != 0) {
 823:                 vmacchng(0);
 824:                 unix0(0);
 825:                 setdot();
 826:                 filter(2);
 827:             } else {
 828:                 unix0(1);
 829:                 pofix();
 830:                 putpad(TE);
 831:                 flush();
 832:                 unixwt(1, unixex("-c", uxb, 0, 0));
 833:                 vclrech(1); /* vcontin(0); */
 834:                 nochng();
 835:             }
 836:             continue;
 837: 
 838: /* < */
 839: /* > */
 840:         case '<':
 841:         case '>':
 842:             for (cnt = 1; peekchar() == c; cnt++)
 843:                 ignchar();
 844:             setCNL();
 845:             vmacchng(0);
 846:             shift(c, cnt);
 847:             continue;
 848: 
 849: /* ^D */
 850: /* EOF */
 851:         case CTRL(d):
 852:         case EOF:
 853:             if (exitoneof) {
 854:                 if (addr2 != 0)
 855:                     dot = addr2;
 856:                 return;
 857:             }
 858:             if (!isatty(0)) {
 859:                 if (intty)
 860:                     /*
 861: 					 * Chtty sys call at UCB may cause a
 862: 					 * input which was a tty to suddenly be
 863: 					 * turned into /dev/null.
 864: 					 */
 865:                     onhup();
 866:                 return;
 867:             }
 868:             if (addr2 != 0) {
 869:                 setlastchar('\n');
 870:                 putnl();
 871:             }
 872:             if (dol == zero) {
 873:                 if (addr2 == 0)
 874:                     putnl();
 875:                 notempty();
 876:             }
 877:             ungetchar(EOF);
 878:             zop(hadpr);
 879:             continue;
 880: 
 881:         default:
 882:             if (!isalpha(c))
 883:                 break;
 884:             ungetchar(c);
 885:             tailprim("", 0, 0);
 886:         }
 887:         error("What?|Unknown command character '%c'", c);
 888:     }
 889: }

Defined functions

Defined variables

nflag defined in line 17; used 3 times
pflag defined in line 17; used 11 times
poffset defined in line 18; used 4 times
sccsid defined in line 8; never used

Defined macros

nochng defined in line 20; used 16 times
Last modified: 1996-11-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2619
Valid CSS Valid XHTML 1.0 Strict