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