|
|
1.1 ! root 1: /* Copyright (c) 1981 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_cmds.c 7.6 10/31/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) ! 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/31/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.