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

Defined functions

Defined variables

nflag defined in line 9; used 3 times
pflag defined in line 9; used 11 times
poffset defined in line 10; used 4 times
sccsid defined in line 2; never used

Defined macros

nochng defined in line 12; used 16 times
Last modified: 1982-01-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2110
Valid CSS Valid XHTML 1.0 Strict