|
|
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.12 (Berkeley) 1/2/88";
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: if (!ldisc)
597: error("Old tty driver|Not using new tty driver/shell");
598: c = exclam();
599: eol();
600: if (!c)
601: ckaw();
602: onsusp();
603: continue;
604: #endif
605:
606: }
607: /* fall into ... */
608:
609: /* & */
610: /* ~ */
611: /* substitute */
612: case '&':
613: case '~':
614: Command = "substitute";
615: if (c == 's')
616: tail(Command);
617: vmacchng(0);
618: if (!substitute(c))
619: pflag = 0;
620: continue;
621:
622: /* t */
623: case 't':
624: if (peekchar() == 'a') {
625: tail("tag");
626: tagfind(exclam());
627: if (!inopen)
628: lchng = chng - 1;
629: else
630: nochng();
631: continue;
632: }
633: tail("t");
634: vmacchng(0);
635: move();
636: continue;
637:
638: case 'u':
639: if (peekchar() == 'n') {
640: ignchar();
641: switch(peekchar()) {
642: /* unmap */
643: case 'm':
644: tail2of("unmap");
645: setnoaddr();
646: mapcmd(1, 0);
647: continue;
648: /* unabbreviate */
649: case 'a':
650: tail2of("unabbreviate");
651: setnoaddr();
652: mapcmd(1, 1);
653: anyabbrs = 1;
654: continue;
655: }
656: /* undo */
657: tail2of("undo");
658: } else
659: tail("undo");
660: setnoaddr();
661: markDOT();
662: c = exclam();
663: newline();
664: undo(c);
665: continue;
666:
667: case 'v':
668: switch (peekchar()) {
669:
670: case 'e':
671: /* version */
672: tail("version");
673: setNAEOL();
674: ex_printf("@(#) Version 3.7, 6/7/85."+5);
675: noonl();
676: continue;
677:
678: /* visual */
679: case 'i':
680: tail("visual");
681: if (inopen) {
682: c = 'e';
683: goto editcmd;
684: }
685: vop();
686: pflag = 0;
687: nochng();
688: continue;
689: }
690: /* v */
691: tail("v");
692: global(0);
693: nochng();
694: continue;
695:
696: /* write */
697: case 'w':
698: c = peekchar();
699: tail(c == 'q' ? "wq" : "write");
700: wq:
701: if (skipwh() && peekchar() == '!') {
702: pofix();
703: ignchar();
704: setall();
705: unix0(0);
706: filter(1);
707: } else {
708: setall();
709: wop(1);
710: nochng();
711: }
712: if (c == 'q')
713: goto quit;
714: continue;
715:
716: /* xit */
717: case 'x':
718: tail("xit");
719: if (!chng)
720: goto quit;
721: c = 'q';
722: goto wq;
723:
724: /* yank */
725: case 'y':
726: tail("yank");
727: c = cmdreg();
728: setcount();
729: eol();
730: vmacchng(0);
731: if (c)
732: YANKreg(c);
733: else
734: yank();
735: continue;
736:
737: /* z */
738: case 'z':
739: zop(0);
740: pflag = 0;
741: continue;
742:
743: /* * */
744: /* @ */
745: case '*':
746: case '@':
747: c = ex_getchar();
748: if (c=='\n' || c=='\r')
749: ungetchar(c);
750: if (any(c, "@*\n\r"))
751: c = lastmac;
752: if (isupper(c))
753: c = tolower(c);
754: if (!islower(c))
755: error("Bad register");
756: newline();
757: setdot();
758: cmdmac(c);
759: continue;
760:
761: /* | */
762: case '|':
763: endline = 0;
764: goto caseline;
765:
766: /* \n */
767: case '\n':
768: endline = 1;
769: caseline:
770: notempty();
771: if (addr2 == 0) {
772: if (UP != NOSTR && c == '\n' && !inglobal)
773: c = CTRL('k');
774: if (inglobal)
775: addr1 = addr2 = dot;
776: else {
777: if (dot == dol)
778: error("At EOF|At end-of-file");
779: addr1 = addr2 = dot + 1;
780: }
781: }
782: setdot();
783: nonzero();
784: if (seensemi)
785: addr1 = addr2;
786: getline(*addr1);
787: if (c == CTRL('k')) {
788: flush1();
789: destline--;
790: if (hadpr)
791: shudclob = 1;
792: }
793: plines(addr1, addr2, 1);
794: continue;
795:
796: /* " */
797: case '"':
798: comment();
799: continue;
800:
801: /* # */
802: case '#':
803: numberit:
804: setCNL();
805: ignorf(setnumb(1));
806: pflag = 0;
807: goto print;
808:
809: /* = */
810: case '=':
811: newline();
812: setall();
813: if (inglobal == 2)
814: pofix();
815: ex_printf("%d", lineno(addr2));
816: noonl();
817: continue;
818:
819: /* ! */
820: case '!':
821: if (addr2 != 0) {
822: vmacchng(0);
823: unix0(0);
824: setdot();
825: filter(2);
826: } else {
827: unix0(1);
828: pofix();
829: putpad(TE);
830: flush();
831: unixwt(1, unixex("-c", uxb, 0, 0));
832: vclrech(1); /* vcontin(0); */
833: nochng();
834: }
835: continue;
836:
837: /* < */
838: /* > */
839: case '<':
840: case '>':
841: for (cnt = 1; peekchar() == c; cnt++)
842: ignchar();
843: setCNL();
844: vmacchng(0);
845: shift(c, cnt);
846: continue;
847:
848: /* ^D */
849: /* EOF */
850: case CTRL('d'):
851: case EOF:
852: if (exitoneof) {
853: if (addr2 != 0)
854: dot = addr2;
855: return;
856: }
857: if (!isatty(0)) {
858: if (intty)
859: /*
860: * Chtty sys call at UCB may cause a
861: * input which was a tty to suddenly be
862: * turned into /dev/null.
863: */
864: onhup();
865: return;
866: }
867: if (addr2 != 0) {
868: setlastchar('\n');
869: putnl();
870: }
871: if (dol == zero) {
872: if (addr2 == 0)
873: putnl();
874: notempty();
875: }
876: ungetchar(EOF);
877: zop(hadpr);
878: continue;
879:
880: default:
881: if (!isalpha(c))
882: break;
883: ungetchar(c);
884: tailprim("", 0, 0);
885: }
886: error("What?|Unknown command character '%c'", c);
887: }
888: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.