|
|
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.