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