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