Subversion Repositories planix.SVN

Rev

Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed

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