|
|
1.1 ! root 1: /* Copyright (c) 1981 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_cmds.c 7.7 6/10/83"; ! 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: #ifdef VMUNIX ! 274: tlaste(); ! 275: #endif ! 276: laste = 0; ! 277: sync(); ! 278: nochng(); ! 279: continue; ! 280: ! 281: /* file */ ! 282: case 'f': ! 283: tail("file"); ! 284: setnoaddr(); ! 285: filename(c); ! 286: noonl(); ! 287: /* ! 288: synctmp(); ! 289: */ ! 290: continue; ! 291: ! 292: /* global */ ! 293: case 'g': ! 294: tail("global"); ! 295: global(!exclam()); ! 296: nochng(); ! 297: continue; ! 298: ! 299: /* insert */ ! 300: case 'i': ! 301: if (inopen) ! 302: goto notinvis; ! 303: tail("insert"); ! 304: setdot(); ! 305: nonzero(); ! 306: aiflag = exclam(); ! 307: newline(); ! 308: vmacchng(0); ! 309: deletenone(); ! 310: setin(addr2); ! 311: inappend = 1; ! 312: ignore(append(gettty, addr2 - 1)); ! 313: inappend = 0; ! 314: if (dot == zero && dol > zero) ! 315: dot = one; ! 316: nochng(); ! 317: continue; ! 318: ! 319: /* join */ ! 320: case 'j': ! 321: tail("join"); ! 322: c = exclam(); ! 323: setcount(); ! 324: nonzero(); ! 325: newline(); ! 326: vmacchng(0); ! 327: if (given < 2 && addr2 != dol) ! 328: addr2++; ! 329: join(c); ! 330: continue; ! 331: ! 332: /* k */ ! 333: case 'k': ! 334: casek: ! 335: pastwh(); ! 336: c = getchar(); ! 337: if (endcmd(c)) ! 338: serror("Mark what?|%s requires following letter", Command); ! 339: newline(); ! 340: if (!islower(c)) ! 341: error("Bad mark|Mark must specify a letter"); ! 342: setdot(); ! 343: nonzero(); ! 344: names[c - 'a'] = *addr2 &~ 01; ! 345: anymarks = 1; ! 346: continue; ! 347: ! 348: /* list */ ! 349: case 'l': ! 350: tail("list"); ! 351: setCNL(); ! 352: ignorf(setlist(1)); ! 353: pflag = 0; ! 354: goto print; ! 355: ! 356: case 'm': ! 357: if (peekchar() == 'a') { ! 358: ignchar(); ! 359: if (peekchar() == 'p') { ! 360: /* map */ ! 361: tail2of("map"); ! 362: setnoaddr(); ! 363: mapcmd(0, 0); ! 364: continue; ! 365: } ! 366: /* mark */ ! 367: tail2of("mark"); ! 368: goto casek; ! 369: } ! 370: /* move */ ! 371: tail("move"); ! 372: vmacchng(0); ! 373: move(); ! 374: continue; ! 375: ! 376: case 'n': ! 377: if (peekchar() == 'u') { ! 378: tail("number"); ! 379: goto numberit; ! 380: } ! 381: /* next */ ! 382: tail("next"); ! 383: setnoaddr(); ! 384: ckaw(); ! 385: ignore(quickly()); ! 386: if (getargs()) ! 387: makargs(); ! 388: next(); ! 389: c = 'e'; ! 390: filename(c); ! 391: goto doecmd; ! 392: ! 393: /* open */ ! 394: case 'o': ! 395: tail("open"); ! 396: oop(); ! 397: pflag = 0; ! 398: nochng(); ! 399: continue; ! 400: ! 401: case 'p': ! 402: case 'P': ! 403: switch (peekchar()) { ! 404: ! 405: /* put */ ! 406: case 'u': ! 407: tail("put"); ! 408: setdot(); ! 409: c = cmdreg(); ! 410: eol(); ! 411: vmacchng(0); ! 412: if (c) ! 413: putreg(c); ! 414: else ! 415: put(); ! 416: continue; ! 417: ! 418: case 'r': ! 419: ignchar(); ! 420: if (peekchar() == 'e') { ! 421: /* preserve */ ! 422: tail2of("preserve"); ! 423: eol(); ! 424: if (preserve() == 0) ! 425: error("Preserve failed!"); ! 426: else ! 427: error("File preserved."); ! 428: } ! 429: tail2of("print"); ! 430: break; ! 431: ! 432: default: ! 433: tail("print"); ! 434: break; ! 435: } ! 436: /* print */ ! 437: setCNL(); ! 438: pflag = 0; ! 439: print: ! 440: nonzero(); ! 441: if (CL && span() > LINES) { ! 442: flush1(); ! 443: vclear(); ! 444: } ! 445: plines(addr1, addr2, 1); ! 446: continue; ! 447: ! 448: /* quit */ ! 449: case 'q': ! 450: tail("quit"); ! 451: setnoaddr(); ! 452: c = quickly(); ! 453: eol(); ! 454: if (!c) ! 455: quit: ! 456: nomore(); ! 457: if (inopen) { ! 458: vgoto(WECHO, 0); ! 459: if (!ateopr()) ! 460: vnfl(); ! 461: else { ! 462: tostop(); ! 463: } ! 464: flush(); ! 465: setty(normf); ! 466: } ! 467: cleanup(1); ! 468: exit(0); ! 469: ! 470: case 'r': ! 471: if (peekchar() == 'e') { ! 472: ignchar(); ! 473: switch (peekchar()) { ! 474: ! 475: /* rewind */ ! 476: case 'w': ! 477: tail2of("rewind"); ! 478: setnoaddr(); ! 479: if (!exclam()) { ! 480: ckaw(); ! 481: if (chng && dol > zero) ! 482: error("No write@since last chage (:rewind! overrides)"); ! 483: } ! 484: eol(); ! 485: erewind(); ! 486: next(); ! 487: c = 'e'; ! 488: ungetchar(lastchar()); ! 489: filename(c); ! 490: goto doecmd; ! 491: ! 492: /* recover */ ! 493: case 'c': ! 494: tail2of("recover"); ! 495: setnoaddr(); ! 496: c = 'e'; ! 497: if (!exclam() && chng) ! 498: c = 'E'; ! 499: filename(c); ! 500: if (c == 'E') { ! 501: ungetchar(lastchar()); ! 502: ignore(quickly()); ! 503: } ! 504: init(); ! 505: addr2 = zero; ! 506: laste++; ! 507: sync(); ! 508: recover(); ! 509: rop2(); ! 510: revocer(); ! 511: if (status == 0) ! 512: rop3(c); ! 513: if (dol != zero) ! 514: change(); ! 515: #ifdef VMUNIX ! 516: tlaste(); ! 517: #endif ! 518: laste = 0; ! 519: sync(); ! 520: nochng(); ! 521: continue; ! 522: } ! 523: tail2of("read"); ! 524: } else ! 525: tail("read"); ! 526: /* read */ ! 527: if (savedfile[0] == 0 && dol == zero) ! 528: c = 'e'; ! 529: pastwh(); ! 530: vmacchng(0); ! 531: if (peekchar() == '!') { ! 532: setdot(); ! 533: ignchar(); ! 534: unix0(0); ! 535: filter(0); ! 536: continue; ! 537: } ! 538: filename(c); ! 539: rop(c); ! 540: nochng(); ! 541: if (inopen && endline && addr1 > zero && addr1 < dol) ! 542: dot = addr1 + 1; ! 543: continue; ! 544: ! 545: case 's': ! 546: switch (peekchar()) { ! 547: /* ! 548: * Caution: 2nd char cannot be c, g, or r ! 549: * because these have meaning to substitute. ! 550: */ ! 551: ! 552: /* set */ ! 553: case 'e': ! 554: tail("set"); ! 555: setnoaddr(); ! 556: set(); ! 557: continue; ! 558: ! 559: /* shell */ ! 560: case 'h': ! 561: tail("shell"); ! 562: setNAEOL(); ! 563: vnfl(); ! 564: putpad(TE); ! 565: flush(); ! 566: unixwt(1, unixex("-i", (char *) 0, 0, 0)); ! 567: vcontin(0); ! 568: continue; ! 569: ! 570: /* source */ ! 571: case 'o': ! 572: #ifdef notdef ! 573: if (inopen) ! 574: goto notinvis; ! 575: #endif ! 576: tail("source"); ! 577: setnoaddr(); ! 578: getone(); ! 579: eol(); ! 580: source(file, 0); ! 581: continue; ! 582: #ifdef SIGTSTP ! 583: /* stop, suspend */ ! 584: case 't': ! 585: tail("stop"); ! 586: goto suspend; ! 587: case 'u': ! 588: tail("suspend"); ! 589: suspend: ! 590: if (!ldisc) ! 591: error("Old tty driver|Not using new tty driver/shell"); ! 592: c = exclam(); ! 593: eol(); ! 594: if (!c) ! 595: ckaw(); ! 596: onsusp(); ! 597: continue; ! 598: #endif ! 599: ! 600: } ! 601: /* fall into ... */ ! 602: ! 603: /* & */ ! 604: /* ~ */ ! 605: /* substitute */ ! 606: case '&': ! 607: case '~': ! 608: Command = "substitute"; ! 609: if (c == 's') ! 610: tail(Command); ! 611: vmacchng(0); ! 612: if (!substitute(c)) ! 613: pflag = 0; ! 614: continue; ! 615: ! 616: /* t */ ! 617: case 't': ! 618: if (peekchar() == 'a') { ! 619: tail("tag"); ! 620: tagfind(exclam()); ! 621: if (!inopen) ! 622: lchng = chng - 1; ! 623: else ! 624: nochng(); ! 625: continue; ! 626: } ! 627: tail("t"); ! 628: vmacchng(0); ! 629: move(); ! 630: continue; ! 631: ! 632: case 'u': ! 633: if (peekchar() == 'n') { ! 634: ignchar(); ! 635: switch(peekchar()) { ! 636: /* unmap */ ! 637: case 'm': ! 638: tail2of("unmap"); ! 639: setnoaddr(); ! 640: mapcmd(1, 0); ! 641: continue; ! 642: /* unabbreviate */ ! 643: case 'a': ! 644: tail2of("unabbreviate"); ! 645: setnoaddr(); ! 646: mapcmd(1, 1); ! 647: anyabbrs = 1; ! 648: continue; ! 649: } ! 650: /* undo */ ! 651: tail2of("undo"); ! 652: } else ! 653: tail("undo"); ! 654: setnoaddr(); ! 655: markDOT(); ! 656: c = exclam(); ! 657: newline(); ! 658: undo(c); ! 659: continue; ! 660: ! 661: case 'v': ! 662: switch (peekchar()) { ! 663: ! 664: case 'e': ! 665: /* version */ ! 666: tail("version"); ! 667: setNAEOL(); ! 668: printf("@(#) Version 3.7, 6/10/83."+5); ! 669: noonl(); ! 670: continue; ! 671: ! 672: /* visual */ ! 673: case 'i': ! 674: tail("visual"); ! 675: if (inopen) { ! 676: c = 'e'; ! 677: goto editcmd; ! 678: } ! 679: vop(); ! 680: pflag = 0; ! 681: nochng(); ! 682: continue; ! 683: } ! 684: /* v */ ! 685: tail("v"); ! 686: global(0); ! 687: nochng(); ! 688: continue; ! 689: ! 690: /* write */ ! 691: case 'w': ! 692: c = peekchar(); ! 693: tail(c == 'q' ? "wq" : "write"); ! 694: wq: ! 695: if (skipwh() && peekchar() == '!') { ! 696: pofix(); ! 697: ignchar(); ! 698: setall(); ! 699: unix0(0); ! 700: filter(1); ! 701: } else { ! 702: setall(); ! 703: wop(1); ! 704: nochng(); ! 705: } ! 706: if (c == 'q') ! 707: goto quit; ! 708: continue; ! 709: ! 710: /* xit */ ! 711: case 'x': ! 712: tail("xit"); ! 713: if (!chng) ! 714: goto quit; ! 715: c = 'q'; ! 716: goto wq; ! 717: ! 718: /* yank */ ! 719: case 'y': ! 720: tail("yank"); ! 721: c = cmdreg(); ! 722: setcount(); ! 723: eol(); ! 724: vmacchng(0); ! 725: if (c) ! 726: YANKreg(c); ! 727: else ! 728: yank(); ! 729: continue; ! 730: ! 731: /* z */ ! 732: case 'z': ! 733: zop(0); ! 734: pflag = 0; ! 735: continue; ! 736: ! 737: /* * */ ! 738: /* @ */ ! 739: case '*': ! 740: case '@': ! 741: c = getchar(); ! 742: if (c=='\n' || c=='\r') ! 743: ungetchar(c); ! 744: if (any(c, "@*\n\r")) ! 745: c = lastmac; ! 746: if (isupper(c)) ! 747: c = tolower(c); ! 748: if (!islower(c)) ! 749: error("Bad register"); ! 750: newline(); ! 751: setdot(); ! 752: cmdmac(c); ! 753: continue; ! 754: ! 755: /* | */ ! 756: case '|': ! 757: endline = 0; ! 758: goto caseline; ! 759: ! 760: /* \n */ ! 761: case '\n': ! 762: endline = 1; ! 763: caseline: ! 764: notempty(); ! 765: if (addr2 == 0) { ! 766: if (UP != NOSTR && c == '\n' && !inglobal) ! 767: c = CTRL(k); ! 768: if (inglobal) ! 769: addr1 = addr2 = dot; ! 770: else { ! 771: if (dot == dol) ! 772: error("At EOF|At end-of-file"); ! 773: addr1 = addr2 = dot + 1; ! 774: } ! 775: } ! 776: setdot(); ! 777: nonzero(); ! 778: if (seensemi) ! 779: addr1 = addr2; ! 780: getline(*addr1); ! 781: if (c == CTRL(k)) { ! 782: flush1(); ! 783: destline--; ! 784: if (hadpr) ! 785: shudclob = 1; ! 786: } ! 787: plines(addr1, addr2, 1); ! 788: continue; ! 789: ! 790: /* " */ ! 791: case '"': ! 792: comment(); ! 793: continue; ! 794: ! 795: /* # */ ! 796: case '#': ! 797: numberit: ! 798: setCNL(); ! 799: ignorf(setnumb(1)); ! 800: pflag = 0; ! 801: goto print; ! 802: ! 803: /* = */ ! 804: case '=': ! 805: newline(); ! 806: setall(); ! 807: if (inglobal == 2) ! 808: pofix(); ! 809: printf("%d", lineno(addr2)); ! 810: noonl(); ! 811: continue; ! 812: ! 813: /* ! */ ! 814: case '!': ! 815: if (addr2 != 0) { ! 816: vmacchng(0); ! 817: unix0(0); ! 818: setdot(); ! 819: filter(2); ! 820: } else { ! 821: unix0(1); ! 822: pofix(); ! 823: putpad(TE); ! 824: flush(); ! 825: unixwt(1, unixex("-c", uxb, 0, 0)); ! 826: vclrech(1); /* vcontin(0); */ ! 827: nochng(); ! 828: } ! 829: continue; ! 830: ! 831: /* < */ ! 832: /* > */ ! 833: case '<': ! 834: case '>': ! 835: for (cnt = 1; peekchar() == c; cnt++) ! 836: ignchar(); ! 837: setCNL(); ! 838: vmacchng(0); ! 839: shift(c, cnt); ! 840: continue; ! 841: ! 842: /* ^D */ ! 843: /* EOF */ ! 844: case CTRL(d): ! 845: case EOF: ! 846: if (exitoneof) { ! 847: if (addr2 != 0) ! 848: dot = addr2; ! 849: return; ! 850: } ! 851: if (!isatty(0)) { ! 852: if (intty) ! 853: /* ! 854: * Chtty sys call at UCB may cause a ! 855: * input which was a tty to suddenly be ! 856: * turned into /dev/null. ! 857: */ ! 858: onhup(); ! 859: return; ! 860: } ! 861: if (addr2 != 0) { ! 862: setlastchar('\n'); ! 863: putnl(); ! 864: } ! 865: if (dol == zero) { ! 866: if (addr2 == 0) ! 867: putnl(); ! 868: notempty(); ! 869: } ! 870: ungetchar(EOF); ! 871: zop(hadpr); ! 872: continue; ! 873: ! 874: default: ! 875: if (!isalpha(c)) ! 876: break; ! 877: ungetchar(c); ! 878: tailprim("", 0, 0); ! 879: } ! 880: error("What?|Unknown command character '%c'", c); ! 881: } ! 882: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.