|
|
1.1 ! root 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: #ifndef lint ! 8: static char *sccsid = "@(#)ex_cmds.c 7.10 (Berkeley) 6/7/85"; ! 9: #endif not lint ! 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 chage (: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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.