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