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