date and time created 94/04/13 10:27:13 by eric
[unix-history] / usr / src / usr.bin / ex / ex_cmds.c
CommitLineData
2791ff57 1/*-
799abc32
KB
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
2791ff57
KB
4 *
5 * %sccs.include.proprietary.c%
19d73a0e
DF
6 */
7
8#ifndef lint
799abc32 9static char sccsid[] = "@(#)ex_cmds.c 8.1 (Berkeley) %G%";
2791ff57 10#endif /* not lint */
19d73a0e 11
d9fbdd64
MH
12#include "ex.h"
13#include "ex_argv.h"
14#include "ex_temp.h"
15#include "ex_tty.h"
714bf4c2 16#include "ex_vis.h"
d9fbdd64
MH
17
18bool pflag, nflag;
19int poffset;
20
21#define nochng() lchng = chng
22
23/*
24 * Main loop for command mode command decoding.
25 * A few commands are executed here, but main function
26 * is to strip command addresses, do a little address oriented
27 * processing and call command routines to do the real work.
28 */
29commands(noprompt, exitoneof)
30 bool noprompt, exitoneof;
31{
32 register line *addr;
33 register int c;
34 register int lchng;
35 int given;
36 int seensemi;
37 int cnt;
38 bool hadpr;
39
40 resetflav();
41 nochng();
42 for (;;) {
43 /*
44 * If dot at last command
45 * ended up at zero, advance to one if there is a such.
46 */
47 if (dot <= zero) {
48 dot = zero;
49 if (dol > zero)
50 dot = one;
51 }
52 shudclob = 0;
53
54 /*
55 * If autoprint or trailing print flags,
56 * print the line at the specified offset
57 * before the next command.
58 */
59 if (pflag ||
60 lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
61 pflag = 0;
62 nochng();
63 if (dol != zero) {
64 addr1 = addr2 = dot + poffset;
65 if (addr1 < one || addr1 > dol)
66error("Offset out-of-bounds|Offset after command too large");
67 setdot1();
68 goto print;
69 }
70 }
71 nochng();
72
73 /*
74 * Print prompt if appropriate.
75 * If not in global flush output first to prevent
76 * going into pfast mode unreasonably.
77 */
78 if (inglobal == 0) {
79 flush();
80 if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
5a6c967e 81 ex_putchar(':');
d9fbdd64
MH
82 hadpr = 1;
83 }
84 TSYNC();
85 }
86
87 /*
88 * Gobble up the address.
89 * Degenerate addresses yield ".".
90 */
91 addr2 = 0;
92 given = seensemi = 0;
93 do {
94 addr1 = addr2;
5a6c967e 95 addr = address((char *) 0);
d9fbdd64
MH
96 c = getcd();
97 if (addr == 0)
98 if (c == ',')
99 addr = dot;
100 else if (addr1 != 0) {
101 addr2 = dot;
102 break;
103 } else
104 break;
105 addr2 = addr;
106 given++;
107 if (c == ';') {
108 c = ',';
109 dot = addr;
110 seensemi = 1;
111 }
112 } while (c == ',');
113 if (c == '%') {
114 /* %: same as 1,$ */
115 addr1 = one;
116 addr2 = dol;
117 given = 2;
5a6c967e 118 c = ex_getchar();
d9fbdd64
MH
119 }
120 if (addr1 == 0)
121 addr1 = addr2;
122 if (c == ':')
5a6c967e 123 c = ex_getchar();
d9fbdd64
MH
124
125 /*
126 * Set command name for special character commands.
127 */
128 tailspec(c);
129
130 /*
131 * If called via : escape from open or visual, limit
132 * the set of available commands here to save work below.
133 */
134 if (inopen) {
65bacefd 135 if (c=='\n' || c=='\r' || c==CTRL('d') || c==EOF) {
d9fbdd64
MH
136 if (addr2)
137 dot = addr2;
138 if (c == EOF)
139 return;
140 continue;
141 }
142 if (any(c, "o"))
143notinvis:
144 tailprim(Command, 1, 1);
145 }
d9fbdd64
MH
146 switch (c) {
147
148 case 'a':
149
d266c416
MH
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':
d9fbdd64
MH
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();
d266c416 174 vmacchng(0);
d9fbdd64
MH
175 deletenone();
176 setin(addr2);
d266c416 177 inappend = 1;
d9fbdd64 178 ignore(append(gettty, addr2));
d266c416 179 inappend = 0;
d9fbdd64
MH
180 nochng();
181 continue;
182
183 case 'c':
184 switch (peekchar()) {
185
186/* copy */
187 case 'o':
188 tail("copy");
d266c416 189 vmacchng(0);
d9fbdd64
MH
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");
205changdir:
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();
d266c416 238 vmacchng(0);
d9fbdd64 239 setin(addr1);
5a6c967e 240 ex_delete(0);
d266c416 241 inappend = 1;
d9fbdd64 242 ignore(append(gettty, addr1 - 1));
d266c416 243 inappend = 0;
d9fbdd64
MH
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();
d266c416 255 vmacchng(0);
d9fbdd64
MH
256 if (c)
257 YANKreg(c);
5a6c967e 258 ex_delete(0);
d9fbdd64
MH
259 appendnone();
260 continue;
261
262/* edit */
263/* ex */
264 case 'e':
265 tail(peekchar() == 'x' ? "ex" : "edit");
d266c416 266editcmd:
d9fbdd64
MH
267 if (!exclam() && chng)
268 c = 'E';
269 filename(c);
270 if (c == 'E') {
271 ungetchar(lastchar());
272 ignore(quickly());
273 }
274 setnoaddr();
275doecmd:
276 init();
277 addr2 = zero;
278 laste++;
5a6c967e 279 ex_sync();
d9fbdd64 280 rop(c);
79086561
RC
281#ifdef VMUNIX
282 tlaste();
283#endif
284 laste = 0;
5a6c967e 285 ex_sync();
d9fbdd64
MH
286 nochng();
287 continue;
288
289/* file */
290 case 'f':
291 tail("file");
292 setnoaddr();
293 filename(c);
294 noonl();
44232d5b 295/*
d9fbdd64 296 synctmp();
44232d5b 297*/
d9fbdd64
MH
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();
d266c416 316 vmacchng(0);
d9fbdd64
MH
317 deletenone();
318 setin(addr2);
d266c416 319 inappend = 1;
d9fbdd64 320 ignore(append(gettty, addr2 - 1));
d266c416 321 inappend = 0;
d9fbdd64
MH
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();
d266c416 334 vmacchng(0);
d9fbdd64
MH
335 if (given < 2 && addr2 != dol)
336 addr2++;
337 join(c);
338 continue;
339
340/* k */
341 case 'k':
342casek:
343 pastwh();
5a6c967e 344 c = ex_getchar();
d9fbdd64
MH
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();
d266c416 371 mapcmd(0, 0);
d9fbdd64
MH
372 continue;
373 }
374/* mark */
375 tail2of("mark");
376 goto casek;
377 }
378/* move */
379 tail("move");
d266c416 380 vmacchng(0);
d9fbdd64
MH
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();
d266c416 419 vmacchng(0);
d9fbdd64
MH
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;
447print:
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)
463quit:
464 nomore();
465 if (inopen) {
466 vgoto(WECHO, 0);
467 if (!ateopr())
468 vnfl();
469 else {
d266c416 470 tostop();
d9fbdd64
MH
471 }
472 flush();
5a6c967e 473 ignore(setty(normf));
d9fbdd64
MH
474 }
475 cleanup(1);
5a6c967e 476 ex_exit(0);
d9fbdd64
MH
477
478 case 'r':
479 if (peekchar() == 'e') {
480 ignchar();
481 switch (peekchar()) {
482
483/* rewind */
484 case 'w':
485 tail2of("rewind");
486 setnoaddr();
10499a70
MH
487 if (!exclam()) {
488 ckaw();
489 if (chng && dol > zero)
490 error("No write@since last chage (:rewind! overrides)");
491 }
d9fbdd64
MH
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++;
5a6c967e 515 ex_sync();
d9fbdd64
MH
516 recover();
517 rop2();
518 revocer();
519 if (status == 0)
520 rop3(c);
521 if (dol != zero)
522 change();
79086561
RC
523#ifdef VMUNIX
524 tlaste();
525#endif
526 laste = 0;
d9fbdd64
MH
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();
d266c416 537 vmacchng(0);
d9fbdd64
MH
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);
d9fbdd64
MH
575 continue;
576
577/* source */
578 case 'o':
04379bab 579#ifdef notdef
d9fbdd64
MH
580 if (inopen)
581 goto notinvis;
04379bab 582#endif
d9fbdd64
MH
583 tail("source");
584 setnoaddr();
585 getone();
586 eol();
587 source(file, 0);
588 continue;
bdbbb330 589#ifdef SIGTSTP
04379bab 590/* stop, suspend */
d266c416
MH
591 case 't':
592 tail("stop");
04379bab
MH
593 goto suspend;
594 case 'u':
595 tail("suspend");
596suspend:
d266c416
MH
597 c = exclam();
598 eol();
599 if (!c)
600 ckaw();
d266c416
MH
601 onsusp();
602 continue;
603#endif
604
d9fbdd64
MH
605 }
606 /* fall into ... */
607
608/* & */
609/* ~ */
610/* substitute */
611 case '&':
612 case '~':
613 Command = "substitute";
614 if (c == 's')
615 tail(Command);
d266c416 616 vmacchng(0);
d9fbdd64
MH
617 if (!substitute(c))
618 pflag = 0;
619 continue;
620
621/* t */
622 case 't':
623 if (peekchar() == 'a') {
624 tail("tag");
625 tagfind(exclam());
626 if (!inopen)
627 lchng = chng - 1;
628 else
629 nochng();
630 continue;
631 }
632 tail("t");
d266c416 633 vmacchng(0);
d9fbdd64
MH
634 move();
635 continue;
636
637 case 'u':
638 if (peekchar() == 'n') {
d9fbdd64 639 ignchar();
d266c416
MH
640 switch(peekchar()) {
641/* unmap */
642 case 'm':
d9fbdd64
MH
643 tail2of("unmap");
644 setnoaddr();
d266c416
MH
645 mapcmd(1, 0);
646 continue;
647/* unabbreviate */
648 case 'a':
649 tail2of("unabbreviate");
650 setnoaddr();
651 mapcmd(1, 1);
652 anyabbrs = 1;
d9fbdd64
MH
653 continue;
654 }
655/* undo */
656 tail2of("undo");
657 } else
658 tail("undo");
659 setnoaddr();
660 markDOT();
661 c = exclam();
662 newline();
663 undo(c);
664 continue;
665
666 case 'v':
667 switch (peekchar()) {
668
669 case 'e':
670/* version */
671 tail("version");
672 setNAEOL();
5a6c967e 673 ex_printf("@(#) Version 3.7, 6/7/85."+5);
d9fbdd64
MH
674 noonl();
675 continue;
676
677/* visual */
678 case 'i':
679 tail("visual");
d266c416
MH
680 if (inopen) {
681 c = 'e';
682 goto editcmd;
683 }
d9fbdd64
MH
684 vop();
685 pflag = 0;
686 nochng();
687 continue;
688 }
689/* v */
690 tail("v");
691 global(0);
692 nochng();
693 continue;
694
695/* write */
696 case 'w':
697 c = peekchar();
698 tail(c == 'q' ? "wq" : "write");
887e3e0d 699wq:
d9fbdd64 700 if (skipwh() && peekchar() == '!') {
887e3e0d 701 pofix();
d9fbdd64
MH
702 ignchar();
703 setall();
704 unix0(0);
705 filter(1);
706 } else {
707 setall();
708 wop(1);
709 nochng();
710 }
711 if (c == 'q')
712 goto quit;
713 continue;
714
887e3e0d
MH
715/* xit */
716 case 'x':
717 tail("xit");
718 if (!chng)
719 goto quit;
720 c = 'q';
721 goto wq;
722
d9fbdd64
MH
723/* yank */
724 case 'y':
725 tail("yank");
726 c = cmdreg();
727 setcount();
728 eol();
d266c416 729 vmacchng(0);
d9fbdd64
MH
730 if (c)
731 YANKreg(c);
732 else
733 yank();
734 continue;
735
736/* z */
737 case 'z':
738 zop(0);
739 pflag = 0;
740 continue;
741
742/* * */
743/* @ */
744 case '*':
745 case '@':
5a6c967e 746 c = ex_getchar();
d9fbdd64
MH
747 if (c=='\n' || c=='\r')
748 ungetchar(c);
749 if (any(c, "@*\n\r"))
750 c = lastmac;
751 if (isupper(c))
752 c = tolower(c);
753 if (!islower(c))
754 error("Bad register");
755 newline();
756 setdot();
757 cmdmac(c);
758 continue;
759
760/* | */
761 case '|':
762 endline = 0;
763 goto caseline;
764
765/* \n */
766 case '\n':
767 endline = 1;
768caseline:
769 notempty();
770 if (addr2 == 0) {
d9fbdd64 771 if (UP != NOSTR && c == '\n' && !inglobal)
65bacefd 772 c = CTRL('k');
d9fbdd64
MH
773 if (inglobal)
774 addr1 = addr2 = dot;
887e3e0d
MH
775 else {
776 if (dot == dol)
777 error("At EOF|At end-of-file");
d9fbdd64 778 addr1 = addr2 = dot + 1;
887e3e0d 779 }
d9fbdd64
MH
780 }
781 setdot();
782 nonzero();
783 if (seensemi)
784 addr1 = addr2;
785 getline(*addr1);
65bacefd 786 if (c == CTRL('k')) {
d9fbdd64
MH
787 flush1();
788 destline--;
789 if (hadpr)
790 shudclob = 1;
791 }
792 plines(addr1, addr2, 1);
793 continue;
794
d266c416
MH
795/* " */
796 case '"':
797 comment();
798 continue;
799
d9fbdd64
MH
800/* # */
801 case '#':
802numberit:
803 setCNL();
804 ignorf(setnumb(1));
805 pflag = 0;
806 goto print;
807
808/* = */
809 case '=':
810 newline();
811 setall();
887e3e0d
MH
812 if (inglobal == 2)
813 pofix();
5a6c967e 814 ex_printf("%d", lineno(addr2));
d9fbdd64
MH
815 noonl();
816 continue;
817
818/* ! */
819 case '!':
820 if (addr2 != 0) {
d266c416 821 vmacchng(0);
d9fbdd64
MH
822 unix0(0);
823 setdot();
824 filter(2);
825 } else {
826 unix0(1);
887e3e0d 827 pofix();
d9fbdd64
MH
828 putpad(TE);
829 flush();
830 unixwt(1, unixex("-c", uxb, 0, 0));
d266c416 831 vclrech(1); /* vcontin(0); */
d9fbdd64
MH
832 nochng();
833 }
834 continue;
835
836/* < */
837/* > */
838 case '<':
839 case '>':
840 for (cnt = 1; peekchar() == c; cnt++)
841 ignchar();
842 setCNL();
d266c416 843 vmacchng(0);
d9fbdd64
MH
844 shift(c, cnt);
845 continue;
846
847/* ^D */
848/* EOF */
65bacefd 849 case CTRL('d'):
d9fbdd64
MH
850 case EOF:
851 if (exitoneof) {
852 if (addr2 != 0)
853 dot = addr2;
854 return;
855 }
856 if (!isatty(0)) {
857 if (intty)
858 /*
859 * Chtty sys call at UCB may cause a
860 * input which was a tty to suddenly be
861 * turned into /dev/null.
862 */
863 onhup();
864 return;
865 }
866 if (addr2 != 0) {
867 setlastchar('\n');
868 putnl();
869 }
870 if (dol == zero) {
871 if (addr2 == 0)
872 putnl();
873 notempty();
874 }
875 ungetchar(EOF);
876 zop(hadpr);
877 continue;
878
879 default:
880 if (!isalpha(c))
881 break;
882 ungetchar(c);
883 tailprim("", 0, 0);
884 }
885 error("What?|Unknown command character '%c'", c);
886 }
887}