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