|
|
1.1 root 1: /* Copyright (c) 1981 Regents of the University of California */
2: static char *sccsid = "@(#)ex_cmds.c 7.6 10/31/81";
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: nochng();
274: continue;
275:
276: /* file */
277: case 'f':
278: tail("file");
279: setnoaddr();
280: filename(c);
281: noonl();
282: /*
283: synctmp();
284: */
285: continue;
286:
287: /* global */
288: case 'g':
289: tail("global");
290: global(!exclam());
291: nochng();
292: continue;
293:
294: /* insert */
295: case 'i':
296: if (inopen)
297: goto notinvis;
298: tail("insert");
299: setdot();
300: nonzero();
301: aiflag = exclam();
302: newline();
303: vmacchng(0);
304: deletenone();
305: setin(addr2);
306: inappend = 1;
307: ignore(append(gettty, addr2 - 1));
308: inappend = 0;
309: if (dot == zero && dol > zero)
310: dot = one;
311: nochng();
312: continue;
313:
314: /* join */
315: case 'j':
316: tail("join");
317: c = exclam();
318: setcount();
319: nonzero();
320: newline();
321: vmacchng(0);
322: if (given < 2 && addr2 != dol)
323: addr2++;
324: join(c);
325: continue;
326:
327: /* k */
328: case 'k':
329: casek:
330: pastwh();
331: c = getchar();
332: if (endcmd(c))
333: serror("Mark what?|%s requires following letter", Command);
334: newline();
335: if (!islower(c))
336: error("Bad mark|Mark must specify a letter");
337: setdot();
338: nonzero();
339: names[c - 'a'] = *addr2 &~ 01;
340: anymarks = 1;
341: continue;
342:
343: /* list */
344: case 'l':
345: tail("list");
346: setCNL();
347: ignorf(setlist(1));
348: pflag = 0;
349: goto print;
350:
351: case 'm':
352: if (peekchar() == 'a') {
353: ignchar();
354: if (peekchar() == 'p') {
355: /* map */
356: tail2of("map");
357: setnoaddr();
358: mapcmd(0, 0);
359: continue;
360: }
361: /* mark */
362: tail2of("mark");
363: goto casek;
364: }
365: /* move */
366: tail("move");
367: vmacchng(0);
368: move();
369: continue;
370:
371: case 'n':
372: if (peekchar() == 'u') {
373: tail("number");
374: goto numberit;
375: }
376: /* next */
377: tail("next");
378: setnoaddr();
379: ckaw();
380: ignore(quickly());
381: if (getargs())
382: makargs();
383: next();
384: c = 'e';
385: filename(c);
386: goto doecmd;
387:
388: /* open */
389: case 'o':
390: tail("open");
391: oop();
392: pflag = 0;
393: nochng();
394: continue;
395:
396: case 'p':
397: case 'P':
398: switch (peekchar()) {
399:
400: /* put */
401: case 'u':
402: tail("put");
403: setdot();
404: c = cmdreg();
405: eol();
406: vmacchng(0);
407: if (c)
408: putreg(c);
409: else
410: put();
411: continue;
412:
413: case 'r':
414: ignchar();
415: if (peekchar() == 'e') {
416: /* preserve */
417: tail2of("preserve");
418: eol();
419: if (preserve() == 0)
420: error("Preserve failed!");
421: else
422: error("File preserved.");
423: }
424: tail2of("print");
425: break;
426:
427: default:
428: tail("print");
429: break;
430: }
431: /* print */
432: setCNL();
433: pflag = 0;
434: print:
435: nonzero();
436: if (CL && span() > LINES) {
437: flush1();
438: vclear();
439: }
440: plines(addr1, addr2, 1);
441: continue;
442:
443: /* quit */
444: case 'q':
445: tail("quit");
446: setnoaddr();
447: c = quickly();
448: eol();
449: if (!c)
450: quit:
451: nomore();
452: if (inopen) {
453: vgoto(WECHO, 0);
454: if (!ateopr())
455: vnfl();
456: else {
457: tostop();
458: }
459: flush();
460: setty(normf);
461: }
462: cleanup(1);
463: exit(0);
464:
465: case 'r':
466: if (peekchar() == 'e') {
467: ignchar();
468: switch (peekchar()) {
469:
470: /* rewind */
471: case 'w':
472: tail2of("rewind");
473: setnoaddr();
474: if (!exclam()) {
475: ckaw();
476: if (chng && dol > zero)
477: error("No write@since last chage (:rewind! overrides)");
478: }
479: eol();
480: erewind();
481: next();
482: c = 'e';
483: ungetchar(lastchar());
484: filename(c);
485: goto doecmd;
486:
487: /* recover */
488: case 'c':
489: tail2of("recover");
490: setnoaddr();
491: c = 'e';
492: if (!exclam() && chng)
493: c = 'E';
494: filename(c);
495: if (c == 'E') {
496: ungetchar(lastchar());
497: ignore(quickly());
498: }
499: init();
500: addr2 = zero;
501: laste++;
502: sync();
503: recover();
504: rop2();
505: revocer();
506: if (status == 0)
507: rop3(c);
508: if (dol != zero)
509: change();
510: nochng();
511: continue;
512: }
513: tail2of("read");
514: } else
515: tail("read");
516: /* read */
517: if (savedfile[0] == 0 && dol == zero)
518: c = 'e';
519: pastwh();
520: vmacchng(0);
521: if (peekchar() == '!') {
522: setdot();
523: ignchar();
524: unix0(0);
525: filter(0);
526: continue;
527: }
528: filename(c);
529: rop(c);
530: nochng();
531: if (inopen && endline && addr1 > zero && addr1 < dol)
532: dot = addr1 + 1;
533: continue;
534:
535: case 's':
536: switch (peekchar()) {
537: /*
538: * Caution: 2nd char cannot be c, g, or r
539: * because these have meaning to substitute.
540: */
541:
542: /* set */
543: case 'e':
544: tail("set");
545: setnoaddr();
546: set();
547: continue;
548:
549: /* shell */
550: case 'h':
551: tail("shell");
552: setNAEOL();
553: vnfl();
554: putpad(TE);
555: flush();
556: unixwt(1, unixex("-i", (char *) 0, 0, 0));
557: vcontin(0);
558: continue;
559:
560: /* source */
561: case 'o':
562: #ifdef notdef
563: if (inopen)
564: goto notinvis;
565: #endif
566: tail("source");
567: setnoaddr();
568: getone();
569: eol();
570: source(file, 0);
571: continue;
572: #ifdef SIGTSTP
573: /* stop, suspend */
574: case 't':
575: tail("stop");
576: goto suspend;
577: case 'u':
578: tail("suspend");
579: suspend:
580: if (!ldisc)
581: error("Old tty driver|Not using new tty driver/shell");
582: c = exclam();
583: eol();
584: if (!c)
585: ckaw();
586: onsusp();
587: continue;
588: #endif
589:
590: }
591: /* fall into ... */
592:
593: /* & */
594: /* ~ */
595: /* substitute */
596: case '&':
597: case '~':
598: Command = "substitute";
599: if (c == 's')
600: tail(Command);
601: vmacchng(0);
602: if (!substitute(c))
603: pflag = 0;
604: continue;
605:
606: /* t */
607: case 't':
608: if (peekchar() == 'a') {
609: tail("tag");
610: tagfind(exclam());
611: if (!inopen)
612: lchng = chng - 1;
613: else
614: nochng();
615: continue;
616: }
617: tail("t");
618: vmacchng(0);
619: move();
620: continue;
621:
622: case 'u':
623: if (peekchar() == 'n') {
624: ignchar();
625: switch(peekchar()) {
626: /* unmap */
627: case 'm':
628: tail2of("unmap");
629: setnoaddr();
630: mapcmd(1, 0);
631: continue;
632: /* unabbreviate */
633: case 'a':
634: tail2of("unabbreviate");
635: setnoaddr();
636: mapcmd(1, 1);
637: anyabbrs = 1;
638: continue;
639: }
640: /* undo */
641: tail2of("undo");
642: } else
643: tail("undo");
644: setnoaddr();
645: markDOT();
646: c = exclam();
647: newline();
648: undo(c);
649: continue;
650:
651: case 'v':
652: switch (peekchar()) {
653:
654: case 'e':
655: /* version */
656: tail("version");
657: setNAEOL();
658: printf("@(#) Version 3.7, 10/31/81."+5);
659: noonl();
660: continue;
661:
662: /* visual */
663: case 'i':
664: tail("visual");
665: if (inopen) {
666: c = 'e';
667: goto editcmd;
668: }
669: vop();
670: pflag = 0;
671: nochng();
672: continue;
673: }
674: /* v */
675: tail("v");
676: global(0);
677: nochng();
678: continue;
679:
680: /* write */
681: case 'w':
682: c = peekchar();
683: tail(c == 'q' ? "wq" : "write");
684: wq:
685: if (skipwh() && peekchar() == '!') {
686: pofix();
687: ignchar();
688: setall();
689: unix0(0);
690: filter(1);
691: } else {
692: setall();
693: wop(1);
694: nochng();
695: }
696: if (c == 'q')
697: goto quit;
698: continue;
699:
700: /* xit */
701: case 'x':
702: tail("xit");
703: if (!chng)
704: goto quit;
705: c = 'q';
706: goto wq;
707:
708: /* yank */
709: case 'y':
710: tail("yank");
711: c = cmdreg();
712: setcount();
713: eol();
714: vmacchng(0);
715: if (c)
716: YANKreg(c);
717: else
718: yank();
719: continue;
720:
721: /* z */
722: case 'z':
723: zop(0);
724: pflag = 0;
725: continue;
726:
727: /* * */
728: /* @ */
729: case '*':
730: case '@':
731: c = getchar();
732: if (c=='\n' || c=='\r')
733: ungetchar(c);
734: if (any(c, "@*\n\r"))
735: c = lastmac;
736: if (isupper(c))
737: c = tolower(c);
738: if (!islower(c))
739: error("Bad register");
740: newline();
741: setdot();
742: cmdmac(c);
743: continue;
744:
745: /* | */
746: case '|':
747: endline = 0;
748: goto caseline;
749:
750: /* \n */
751: case '\n':
752: endline = 1;
753: caseline:
754: notempty();
755: if (addr2 == 0) {
756: if (UP != NOSTR && c == '\n' && !inglobal)
757: c = CTRL(k);
758: if (inglobal)
759: addr1 = addr2 = dot;
760: else {
761: if (dot == dol)
762: error("At EOF|At end-of-file");
763: addr1 = addr2 = dot + 1;
764: }
765: }
766: setdot();
767: nonzero();
768: if (seensemi)
769: addr1 = addr2;
770: getline(*addr1);
771: if (c == CTRL(k)) {
772: flush1();
773: destline--;
774: if (hadpr)
775: shudclob = 1;
776: }
777: plines(addr1, addr2, 1);
778: continue;
779:
780: /* " */
781: case '"':
782: comment();
783: continue;
784:
785: /* # */
786: case '#':
787: numberit:
788: setCNL();
789: ignorf(setnumb(1));
790: pflag = 0;
791: goto print;
792:
793: /* = */
794: case '=':
795: newline();
796: setall();
797: if (inglobal == 2)
798: pofix();
799: printf("%d", lineno(addr2));
800: noonl();
801: continue;
802:
803: /* ! */
804: case '!':
805: if (addr2 != 0) {
806: vmacchng(0);
807: unix0(0);
808: setdot();
809: filter(2);
810: } else {
811: unix0(1);
812: pofix();
813: putpad(TE);
814: flush();
815: unixwt(1, unixex("-c", uxb, 0, 0));
816: vclrech(1); /* vcontin(0); */
817: nochng();
818: }
819: continue;
820:
821: /* < */
822: /* > */
823: case '<':
824: case '>':
825: for (cnt = 1; peekchar() == c; cnt++)
826: ignchar();
827: setCNL();
828: vmacchng(0);
829: shift(c, cnt);
830: continue;
831:
832: /* ^D */
833: /* EOF */
834: case CTRL(d):
835: case EOF:
836: if (exitoneof) {
837: if (addr2 != 0)
838: dot = addr2;
839: return;
840: }
841: if (!isatty(0)) {
842: if (intty)
843: /*
844: * Chtty sys call at UCB may cause a
845: * input which was a tty to suddenly be
846: * turned into /dev/null.
847: */
848: onhup();
849: return;
850: }
851: if (addr2 != 0) {
852: setlastchar('\n');
853: putnl();
854: }
855: if (dol == zero) {
856: if (addr2 == 0)
857: putnl();
858: notempty();
859: }
860: ungetchar(EOF);
861: zop(hadpr);
862: continue;
863:
864: default:
865: if (!isalpha(c))
866: break;
867: ungetchar(c);
868: tailprim("", 0, 0);
869: }
870: error("What?|Unknown command character '%c'", c);
871: }
872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.