xref: /csrg-svn/usr.bin/ex/ex_cmds.c (revision 63046)
148255Sbostic /*-
2*63046Sbostic  * Copyright (c) 1980, 1993
3*63046Sbostic  *	The Regents of the University of California.  All rights reserved.
448255Sbostic  *
548255Sbostic  * %sccs.include.proprietary.c%
621655Sdist  */
721655Sdist 
821655Sdist #ifndef lint
9*63046Sbostic static char sccsid[] = "@(#)ex_cmds.c	8.1 (Berkeley) 06/09/93";
1048255Sbostic #endif /* not lint */
1121655Sdist 
12431Smark #include "ex.h"
13431Smark #include "ex_argv.h"
14431Smark #include "ex_temp.h"
15431Smark #include "ex_tty.h"
1621680Sdist #include "ex_vis.h"
17431Smark 
18431Smark bool	pflag, nflag;
19431Smark int	poffset;
20431Smark 
21431Smark #define	nochng()	lchng = chng
22431Smark 
23431Smark /*
24431Smark  * Main loop for command mode command decoding.
25431Smark  * A few commands are executed here, but main function
26431Smark  * is to strip command addresses, do a little address oriented
27431Smark  * processing and call command routines to do the real work.
28431Smark  */
commands(noprompt,exitoneof)29431Smark commands(noprompt, exitoneof)
30431Smark 	bool noprompt, exitoneof;
31431Smark {
32431Smark 	register line *addr;
33431Smark 	register int c;
34431Smark 	register int lchng;
35431Smark 	int given;
36431Smark 	int seensemi;
37431Smark 	int cnt;
38431Smark 	bool hadpr;
39431Smark 
40431Smark 	resetflav();
41431Smark 	nochng();
42431Smark 	for (;;) {
43431Smark 		/*
44431Smark 		 * If dot at last command
45431Smark 		 * ended up at zero, advance to one if there is a such.
46431Smark 		 */
47431Smark 		if (dot <= zero) {
48431Smark 			dot = zero;
49431Smark 			if (dol > zero)
50431Smark 				dot = one;
51431Smark 		}
52431Smark 		shudclob = 0;
53431Smark 
54431Smark 		/*
55431Smark 		 * If autoprint or trailing print flags,
56431Smark 		 * print the line at the specified offset
57431Smark 		 * before the next command.
58431Smark 		 */
59431Smark 		if (pflag ||
60431Smark 		    lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
61431Smark 			pflag = 0;
62431Smark 			nochng();
63431Smark 			if (dol != zero) {
64431Smark 				addr1 = addr2 = dot + poffset;
65431Smark 				if (addr1 < one || addr1 > dol)
66431Smark error("Offset out-of-bounds|Offset after command too large");
67431Smark 				setdot1();
68431Smark 				goto print;
69431Smark 			}
70431Smark 		}
71431Smark 		nochng();
72431Smark 
73431Smark 		/*
74431Smark 		 * Print prompt if appropriate.
75431Smark 		 * If not in global flush output first to prevent
76431Smark 		 * going into pfast mode unreasonably.
77431Smark 		 */
78431Smark 		if (inglobal == 0) {
79431Smark 			flush();
80431Smark 			if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
8130596Sconrad 				ex_putchar(':');
82431Smark 				hadpr = 1;
83431Smark 			}
84431Smark 			TSYNC();
85431Smark 		}
86431Smark 
87431Smark 		/*
88431Smark 		 * Gobble up the address.
89431Smark 		 * Degenerate addresses yield ".".
90431Smark 		 */
91431Smark 		addr2 = 0;
92431Smark 		given = seensemi = 0;
93431Smark 		do {
94431Smark 			addr1 = addr2;
9530596Sconrad 			addr = address((char *) 0);
96431Smark 			c = getcd();
97431Smark 			if (addr == 0)
98431Smark 				if (c == ',')
99431Smark 					addr = dot;
100431Smark 				else if (addr1 != 0) {
101431Smark 					addr2 = dot;
102431Smark 					break;
103431Smark 				} else
104431Smark 					break;
105431Smark 			addr2 = addr;
106431Smark 			given++;
107431Smark 			if (c == ';') {
108431Smark 				c = ',';
109431Smark 				dot = addr;
110431Smark 				seensemi = 1;
111431Smark 			}
112431Smark 		} while (c == ',');
113431Smark 		if (c == '%') {
114431Smark 			/* %: same as 1,$ */
115431Smark 			addr1 = one;
116431Smark 			addr2 = dol;
117431Smark 			given = 2;
11830596Sconrad 			c = ex_getchar();
119431Smark 		}
120431Smark 		if (addr1 == 0)
121431Smark 			addr1 = addr2;
122431Smark 		if (c == ':')
12330596Sconrad 			c = ex_getchar();
124431Smark 
125431Smark 		/*
126431Smark 		 * Set command name for special character commands.
127431Smark 		 */
128431Smark 		tailspec(c);
129431Smark 
130431Smark 		/*
131431Smark 		 * If called via : escape from open or visual, limit
132431Smark 		 * the set of available commands here to save work below.
133431Smark 		 */
134431Smark 		if (inopen) {
13533222Sbostic 			if (c=='\n' || c=='\r' || c==CTRL('d') || c==EOF) {
136431Smark 				if (addr2)
137431Smark 					dot = addr2;
138431Smark 				if (c == EOF)
139431Smark 					return;
140431Smark 				continue;
141431Smark 			}
142431Smark 			if (any(c, "o"))
143431Smark notinvis:
144431Smark 				tailprim(Command, 1, 1);
145431Smark 		}
146431Smark 		switch (c) {
147431Smark 
148431Smark 		case 'a':
149431Smark 
150512Smark 			switch(peekchar()) {
151512Smark 			case 'b':
152512Smark /* abbreviate */
153512Smark 				tail("abbreviate");
154512Smark 				setnoaddr();
155512Smark 				mapcmd(0, 1);
156512Smark 				anyabbrs = 1;
157512Smark 				continue;
158512Smark 			case 'r':
159431Smark /* args */
160431Smark 				tail("args");
161431Smark 				setnoaddr();
162431Smark 				eol();
163431Smark 				pargs();
164431Smark 				continue;
165431Smark 			}
166431Smark 
167431Smark /* append */
168431Smark 			if (inopen)
169431Smark 				goto notinvis;
170431Smark 			tail("append");
171431Smark 			setdot();
172431Smark 			aiflag = exclam();
173431Smark 			newline();
174512Smark 			vmacchng(0);
175431Smark 			deletenone();
176431Smark 			setin(addr2);
177512Smark 			inappend = 1;
178431Smark 			ignore(append(gettty, addr2));
179512Smark 			inappend = 0;
180431Smark 			nochng();
181431Smark 			continue;
182431Smark 
183431Smark 		case 'c':
184431Smark 			switch (peekchar()) {
185431Smark 
186431Smark /* copy */
187431Smark 			case 'o':
188431Smark 				tail("copy");
189512Smark 				vmacchng(0);
190431Smark 				move();
191431Smark 				continue;
192431Smark 
193431Smark #ifdef CHDIR
194431Smark /* cd */
195431Smark 			case 'd':
196431Smark 				tail("cd");
197431Smark 				goto changdir;
198431Smark 
199431Smark /* chdir */
200431Smark 			case 'h':
201431Smark 				ignchar();
202431Smark 				if (peekchar() == 'd') {
203431Smark 					register char *p;
204431Smark 					tail2of("chdir");
205431Smark changdir:
206431Smark 					if (savedfile[0] == '/' || !value(WARN))
207431Smark 						ignore(exclam());
208431Smark 					else
209431Smark 						ignore(quickly());
210431Smark 					if (skipend()) {
211431Smark 						p = getenv("HOME");
212431Smark 						if (p == NULL)
213431Smark 							error("Home directory unknown");
214431Smark 					} else
215431Smark 						getone(), p = file;
216431Smark 					eol();
217431Smark 					if (chdir(p) < 0)
218431Smark 						filioerr(p);
219431Smark 					if (savedfile[0] != '/')
220431Smark 						edited = 0;
221431Smark 					continue;
222431Smark 				}
223431Smark 				if (inopen)
224431Smark 					tailprim("change", 2, 1);
225431Smark 				tail2of("change");
226431Smark 				break;
227431Smark 
228431Smark #endif
229431Smark 			default:
230431Smark 				if (inopen)
231431Smark 					goto notinvis;
232431Smark 				tail("change");
233431Smark 				break;
234431Smark 			}
235431Smark /* change */
236431Smark 			aiflag = exclam();
237431Smark 			setCNL();
238512Smark 			vmacchng(0);
239431Smark 			setin(addr1);
24030596Sconrad 			ex_delete(0);
241512Smark 			inappend = 1;
242431Smark 			ignore(append(gettty, addr1 - 1));
243512Smark 			inappend = 0;
244431Smark 			nochng();
245431Smark 			continue;
246431Smark 
247431Smark /* delete */
248431Smark 		case 'd':
249431Smark 			/*
250431Smark 			 * Caution: dp and dl have special meaning already.
251431Smark 			 */
252431Smark 			tail("delete");
253431Smark 			c = cmdreg();
254431Smark 			setCNL();
255512Smark 			vmacchng(0);
256431Smark 			if (c)
257431Smark 				YANKreg(c);
25830596Sconrad 			ex_delete(0);
259431Smark 			appendnone();
260431Smark 			continue;
261431Smark 
262431Smark /* edit */
263431Smark /* ex */
264431Smark 		case 'e':
265431Smark 			tail(peekchar() == 'x' ? "ex" : "edit");
266512Smark editcmd:
267431Smark 			if (!exclam() && chng)
268431Smark 				c = 'E';
269431Smark 			filename(c);
270431Smark 			if (c == 'E') {
271431Smark 				ungetchar(lastchar());
272431Smark 				ignore(quickly());
273431Smark 			}
274431Smark 			setnoaddr();
275431Smark doecmd:
276431Smark 			init();
277431Smark 			addr2 = zero;
278431Smark 			laste++;
27930596Sconrad 			ex_sync();
280431Smark 			rop(c);
28121680Sdist #ifdef VMUNIX
28221680Sdist 			tlaste();
28321680Sdist #endif
28421680Sdist 			laste = 0;
28530596Sconrad 			ex_sync();
286431Smark 			nochng();
287431Smark 			continue;
288431Smark 
289431Smark /* file */
290431Smark 		case 'f':
291431Smark 			tail("file");
292431Smark 			setnoaddr();
293431Smark 			filename(c);
294431Smark 			noonl();
295469Smark /*
296431Smark 			synctmp();
297469Smark */
298431Smark 			continue;
299431Smark 
300431Smark /* global */
301431Smark 		case 'g':
302431Smark 			tail("global");
303431Smark 			global(!exclam());
304431Smark 			nochng();
305431Smark 			continue;
306431Smark 
307431Smark /* insert */
308431Smark 		case 'i':
309431Smark 			if (inopen)
310431Smark 				goto notinvis;
311431Smark 			tail("insert");
312431Smark 			setdot();
313431Smark 			nonzero();
314431Smark 			aiflag = exclam();
315431Smark 			newline();
316512Smark 			vmacchng(0);
317431Smark 			deletenone();
318431Smark 			setin(addr2);
319512Smark 			inappend = 1;
320431Smark 			ignore(append(gettty, addr2 - 1));
321512Smark 			inappend = 0;
322431Smark 			if (dot == zero && dol > zero)
323431Smark 				dot = one;
324431Smark 			nochng();
325431Smark 			continue;
326431Smark 
327431Smark /* join */
328431Smark 		case 'j':
329431Smark 			tail("join");
330431Smark 			c = exclam();
331431Smark 			setcount();
332431Smark 			nonzero();
333431Smark 			newline();
334512Smark 			vmacchng(0);
335431Smark 			if (given < 2 && addr2 != dol)
336431Smark 				addr2++;
337431Smark 			join(c);
338431Smark 			continue;
339431Smark 
340431Smark /* k */
341431Smark 		case 'k':
342431Smark casek:
343431Smark 			pastwh();
34430596Sconrad 			c = ex_getchar();
345431Smark 			if (endcmd(c))
346431Smark 				serror("Mark what?|%s requires following letter", Command);
347431Smark 			newline();
348431Smark 			if (!islower(c))
349431Smark 				error("Bad mark|Mark must specify a letter");
350431Smark 			setdot();
351431Smark 			nonzero();
352431Smark 			names[c - 'a'] = *addr2 &~ 01;
353431Smark 			anymarks = 1;
354431Smark 			continue;
355431Smark 
356431Smark /* list */
357431Smark 		case 'l':
358431Smark 			tail("list");
359431Smark 			setCNL();
360431Smark 			ignorf(setlist(1));
361431Smark 			pflag = 0;
362431Smark 			goto print;
363431Smark 
364431Smark 		case 'm':
365431Smark 			if (peekchar() == 'a') {
366431Smark 				ignchar();
367431Smark 				if (peekchar() == 'p') {
368431Smark /* map */
369431Smark 					tail2of("map");
370431Smark 					setnoaddr();
371512Smark 					mapcmd(0, 0);
372431Smark 					continue;
373431Smark 				}
374431Smark /* mark */
375431Smark 				tail2of("mark");
376431Smark 				goto casek;
377431Smark 			}
378431Smark /* move */
379431Smark 			tail("move");
380512Smark 			vmacchng(0);
381431Smark 			move();
382431Smark 			continue;
383431Smark 
384431Smark 		case 'n':
385431Smark 			if (peekchar() == 'u') {
386431Smark 				tail("number");
387431Smark 				goto numberit;
388431Smark 			}
389431Smark /* next */
390431Smark 			tail("next");
391431Smark 			setnoaddr();
392431Smark 			ckaw();
393431Smark 			ignore(quickly());
394431Smark 			if (getargs())
395431Smark 				makargs();
396431Smark 			next();
397431Smark 			c = 'e';
398431Smark 			filename(c);
399431Smark 			goto doecmd;
400431Smark 
401431Smark /* open */
402431Smark 		case 'o':
403431Smark 			tail("open");
404431Smark 			oop();
405431Smark 			pflag = 0;
406431Smark 			nochng();
407431Smark 			continue;
408431Smark 
409431Smark 		case 'p':
410431Smark 		case 'P':
411431Smark 			switch (peekchar()) {
412431Smark 
413431Smark /* put */
414431Smark 			case 'u':
415431Smark 				tail("put");
416431Smark 				setdot();
417431Smark 				c = cmdreg();
418431Smark 				eol();
419512Smark 				vmacchng(0);
420431Smark 				if (c)
421431Smark 					putreg(c);
422431Smark 				else
423431Smark 					put();
424431Smark 				continue;
425431Smark 
426431Smark 			case 'r':
427431Smark 				ignchar();
428431Smark 				if (peekchar() == 'e') {
429431Smark /* preserve */
430431Smark 					tail2of("preserve");
431431Smark 					eol();
432431Smark 					if (preserve() == 0)
433431Smark 						error("Preserve failed!");
434431Smark 					else
435431Smark 						error("File preserved.");
436431Smark 				}
437431Smark 				tail2of("print");
438431Smark 				break;
439431Smark 
440431Smark 			default:
441431Smark 				tail("print");
442431Smark 				break;
443431Smark 			}
444431Smark /* print */
445431Smark 			setCNL();
446431Smark 			pflag = 0;
447431Smark print:
448431Smark 			nonzero();
449431Smark 			if (CL && span() > LINES) {
450431Smark 				flush1();
451431Smark 				vclear();
452431Smark 			}
453431Smark 			plines(addr1, addr2, 1);
454431Smark 			continue;
455431Smark 
456431Smark /* quit */
457431Smark 		case 'q':
458431Smark 			tail("quit");
459431Smark 			setnoaddr();
460431Smark 			c = quickly();
461431Smark 			eol();
462431Smark 			if (!c)
463431Smark quit:
464431Smark 				nomore();
465431Smark 			if (inopen) {
466431Smark 				vgoto(WECHO, 0);
467431Smark 				if (!ateopr())
468431Smark 					vnfl();
469431Smark 				else {
470512Smark 					tostop();
471431Smark 				}
472431Smark 				flush();
47330596Sconrad 				ignore(setty(normf));
474431Smark 			}
475431Smark 			cleanup(1);
47630596Sconrad 			ex_exit(0);
477431Smark 
478431Smark 		case 'r':
479431Smark 			if (peekchar() == 'e') {
480431Smark 				ignchar();
481431Smark 				switch (peekchar()) {
482431Smark 
483431Smark /* rewind */
484431Smark 				case 'w':
485431Smark 					tail2of("rewind");
486431Smark 					setnoaddr();
487811Smark 					if (!exclam()) {
488811Smark 						ckaw();
489811Smark 						if (chng && dol > zero)
490811Smark 							error("No write@since last chage (:rewind! overrides)");
491811Smark 					}
492512Smark 					eol();
493431Smark 					erewind();
494431Smark 					next();
495431Smark 					c = 'e';
496431Smark 					ungetchar(lastchar());
497431Smark 					filename(c);
498431Smark 					goto doecmd;
499431Smark 
500431Smark /* recover */
501431Smark 				case 'c':
502431Smark 					tail2of("recover");
503431Smark 					setnoaddr();
504431Smark 					c = 'e';
505431Smark 					if (!exclam() && chng)
506431Smark 						c = 'E';
507431Smark 					filename(c);
508431Smark 					if (c == 'E') {
509431Smark 						ungetchar(lastchar());
510431Smark 						ignore(quickly());
511431Smark 					}
512431Smark 					init();
513431Smark 					addr2 = zero;
514431Smark 					laste++;
51530596Sconrad 					ex_sync();
516431Smark 					recover();
517431Smark 					rop2();
518431Smark 					revocer();
519431Smark 					if (status == 0)
520431Smark 						rop3(c);
521431Smark 					if (dol != zero)
522431Smark 						change();
52321680Sdist #ifdef VMUNIX
52421680Sdist 					tlaste();
52521680Sdist #endif
52621680Sdist 					laste = 0;
527431Smark 					nochng();
528431Smark 					continue;
529431Smark 				}
530431Smark 				tail2of("read");
531431Smark 			} else
532431Smark 				tail("read");
533431Smark /* read */
534431Smark 			if (savedfile[0] == 0 && dol == zero)
535431Smark 				c = 'e';
536431Smark 			pastwh();
537512Smark 			vmacchng(0);
538431Smark 			if (peekchar() == '!') {
539431Smark 				setdot();
540431Smark 				ignchar();
541431Smark 				unix0(0);
542431Smark 				filter(0);
543431Smark 				continue;
544431Smark 			}
545431Smark 			filename(c);
546431Smark 			rop(c);
547431Smark 			nochng();
548431Smark 			if (inopen && endline && addr1 > zero && addr1 < dol)
549431Smark 				dot = addr1 + 1;
550431Smark 			continue;
551431Smark 
552431Smark 		case 's':
553431Smark 			switch (peekchar()) {
554431Smark 			/*
555431Smark 			 * Caution: 2nd char cannot be c, g, or r
556431Smark 			 * because these have meaning to substitute.
557431Smark 			 */
558431Smark 
559431Smark /* set */
560431Smark 			case 'e':
561431Smark 				tail("set");
562431Smark 				setnoaddr();
563431Smark 				set();
564431Smark 				continue;
565431Smark 
566431Smark /* shell */
567431Smark 			case 'h':
568431Smark 				tail("shell");
569431Smark 				setNAEOL();
570431Smark 				vnfl();
571431Smark 				putpad(TE);
572431Smark 				flush();
573431Smark 				unixwt(1, unixex("-i", (char *) 0, 0, 0));
574431Smark 				vcontin(0);
575431Smark 				continue;
576431Smark 
577431Smark /* source */
578431Smark 			case 'o':
57921680Sdist #ifdef notdef
580431Smark 				if (inopen)
581431Smark 					goto notinvis;
58221680Sdist #endif
583431Smark 				tail("source");
584431Smark 				setnoaddr();
585431Smark 				getone();
586431Smark 				eol();
587431Smark 				source(file, 0);
588431Smark 				continue;
589865Smark #ifdef SIGTSTP
59021680Sdist /* stop, suspend */
591512Smark 			case 't':
592512Smark 				tail("stop");
59321680Sdist 				goto suspend;
59421680Sdist 			case 'u':
59521680Sdist 				tail("suspend");
59621680Sdist suspend:
597512Smark 				c = exclam();
598512Smark 				eol();
599512Smark 				if (!c)
600512Smark 					ckaw();
601512Smark 				onsusp();
602512Smark 				continue;
603512Smark #endif
604512Smark 
605431Smark 			}
606431Smark 			/* fall into ... */
607431Smark 
608431Smark /* & */
609431Smark /* ~ */
610431Smark /* substitute */
611431Smark 		case '&':
612431Smark 		case '~':
613431Smark 			Command = "substitute";
614431Smark 			if (c == 's')
615431Smark 				tail(Command);
616512Smark 			vmacchng(0);
617431Smark 			if (!substitute(c))
618431Smark 				pflag = 0;
619431Smark 			continue;
620431Smark 
621431Smark /* t */
622431Smark 		case 't':
623431Smark 			if (peekchar() == 'a') {
624431Smark 				tail("tag");
625431Smark 				tagfind(exclam());
626431Smark 				if (!inopen)
627431Smark 					lchng = chng - 1;
628431Smark 				else
629431Smark 					nochng();
630431Smark 				continue;
631431Smark 			}
632431Smark 			tail("t");
633512Smark 			vmacchng(0);
634431Smark 			move();
635431Smark 			continue;
636431Smark 
637431Smark 		case 'u':
638431Smark 			if (peekchar() == 'n') {
639512Smark 				ignchar();
640512Smark 				switch(peekchar()) {
641431Smark /* unmap */
642512Smark 				case 'm':
643431Smark 					tail2of("unmap");
644431Smark 					setnoaddr();
645512Smark 					mapcmd(1, 0);
646431Smark 					continue;
647512Smark /* unabbreviate */
648512Smark 				case 'a':
649512Smark 					tail2of("unabbreviate");
650512Smark 					setnoaddr();
651512Smark 					mapcmd(1, 1);
652512Smark 					anyabbrs = 1;
653512Smark 					continue;
654431Smark 				}
655431Smark /* undo */
656431Smark 				tail2of("undo");
657431Smark 			} else
658431Smark 				tail("undo");
659431Smark 			setnoaddr();
660431Smark 			markDOT();
661431Smark 			c = exclam();
662431Smark 			newline();
663431Smark 			undo(c);
664431Smark 			continue;
665431Smark 
666431Smark 		case 'v':
667431Smark 			switch (peekchar()) {
668431Smark 
669431Smark 			case 'e':
670431Smark /* version */
671431Smark 				tail("version");
672431Smark 				setNAEOL();
67330596Sconrad 				ex_printf("@(#) Version 3.7, 6/7/85."+5);
674431Smark 				noonl();
675431Smark 				continue;
676431Smark 
677431Smark /* visual */
678431Smark 			case 'i':
679431Smark 				tail("visual");
680512Smark 				if (inopen) {
681512Smark 					c = 'e';
682512Smark 					goto editcmd;
683512Smark 				}
684431Smark 				vop();
685431Smark 				pflag = 0;
686431Smark 				nochng();
687431Smark 				continue;
688431Smark 			}
689431Smark /* v */
690431Smark 			tail("v");
691431Smark 			global(0);
692431Smark 			nochng();
693431Smark 			continue;
694431Smark 
695431Smark /* write */
696431Smark 		case 'w':
697431Smark 			c = peekchar();
698431Smark 			tail(c == 'q' ? "wq" : "write");
699487Smark wq:
700431Smark 			if (skipwh() && peekchar() == '!') {
701487Smark 				pofix();
702431Smark 				ignchar();
703431Smark 				setall();
704431Smark 				unix0(0);
705431Smark 				filter(1);
706431Smark 			} else {
707431Smark 				setall();
708431Smark 				wop(1);
709431Smark 				nochng();
710431Smark 			}
711431Smark 			if (c == 'q')
712431Smark 				goto quit;
713431Smark 			continue;
714431Smark 
715487Smark /* xit */
716487Smark 		case 'x':
717487Smark 			tail("xit");
718487Smark 			if (!chng)
719487Smark 				goto quit;
720487Smark 			c = 'q';
721487Smark 			goto wq;
722487Smark 
723431Smark /* yank */
724431Smark 		case 'y':
725431Smark 			tail("yank");
726431Smark 			c = cmdreg();
727431Smark 			setcount();
728431Smark 			eol();
729512Smark 			vmacchng(0);
730431Smark 			if (c)
731431Smark 				YANKreg(c);
732431Smark 			else
733431Smark 				yank();
734431Smark 			continue;
735431Smark 
736431Smark /* z */
737431Smark 		case 'z':
738431Smark 			zop(0);
739431Smark 			pflag = 0;
740431Smark 			continue;
741431Smark 
742431Smark /* * */
743431Smark /* @ */
744431Smark 		case '*':
745431Smark 		case '@':
74630596Sconrad 			c = ex_getchar();
747431Smark 			if (c=='\n' || c=='\r')
748431Smark 				ungetchar(c);
749431Smark 			if (any(c, "@*\n\r"))
750431Smark 				c = lastmac;
751431Smark 			if (isupper(c))
752431Smark 				c = tolower(c);
753431Smark 			if (!islower(c))
754431Smark 				error("Bad register");
755431Smark 			newline();
756431Smark 			setdot();
757431Smark 			cmdmac(c);
758431Smark 			continue;
759431Smark 
760431Smark /* | */
761431Smark 		case '|':
762431Smark 			endline = 0;
763431Smark 			goto caseline;
764431Smark 
765431Smark /* \n */
766431Smark 		case '\n':
767431Smark 			endline = 1;
768431Smark caseline:
769431Smark 			notempty();
770431Smark 			if (addr2 == 0) {
771431Smark 				if (UP != NOSTR && c == '\n' && !inglobal)
77233222Sbostic 					c = CTRL('k');
773431Smark 				if (inglobal)
774431Smark 					addr1 = addr2 = dot;
775487Smark 				else {
776487Smark 					if (dot == dol)
777487Smark 						error("At EOF|At end-of-file");
778431Smark 					addr1 = addr2 = dot + 1;
779487Smark 				}
780431Smark 			}
781431Smark 			setdot();
782431Smark 			nonzero();
783431Smark 			if (seensemi)
784431Smark 				addr1 = addr2;
785431Smark 			getline(*addr1);
78633222Sbostic 			if (c == CTRL('k')) {
787431Smark 				flush1();
788431Smark 				destline--;
789431Smark 				if (hadpr)
790431Smark 					shudclob = 1;
791431Smark 			}
792431Smark 			plines(addr1, addr2, 1);
793431Smark 			continue;
794431Smark 
795512Smark /* " */
796512Smark 		case '"':
797512Smark 			comment();
798512Smark 			continue;
799512Smark 
800431Smark /* # */
801431Smark 		case '#':
802431Smark numberit:
803431Smark 			setCNL();
804431Smark 			ignorf(setnumb(1));
805431Smark 			pflag = 0;
806431Smark 			goto print;
807431Smark 
808431Smark /* = */
809431Smark 		case '=':
810431Smark 			newline();
811431Smark 			setall();
812487Smark 			if (inglobal == 2)
813487Smark 				pofix();
81430596Sconrad 			ex_printf("%d", lineno(addr2));
815431Smark 			noonl();
816431Smark 			continue;
817431Smark 
818431Smark /* ! */
819431Smark 		case '!':
820431Smark 			if (addr2 != 0) {
821512Smark 				vmacchng(0);
822431Smark 				unix0(0);
823431Smark 				setdot();
824431Smark 				filter(2);
825431Smark 			} else {
826431Smark 				unix0(1);
827487Smark 				pofix();
828431Smark 				putpad(TE);
829431Smark 				flush();
830431Smark 				unixwt(1, unixex("-c", uxb, 0, 0));
831512Smark 				vclrech(1);	/* vcontin(0); */
832431Smark 				nochng();
833431Smark 			}
834431Smark 			continue;
835431Smark 
836431Smark /* < */
837431Smark /* > */
838431Smark 		case '<':
839431Smark 		case '>':
840431Smark 			for (cnt = 1; peekchar() == c; cnt++)
841431Smark 				ignchar();
842431Smark 			setCNL();
843512Smark 			vmacchng(0);
844431Smark 			shift(c, cnt);
845431Smark 			continue;
846431Smark 
847431Smark /* ^D */
848431Smark /* EOF */
84933222Sbostic 		case CTRL('d'):
850431Smark 		case EOF:
851431Smark 			if (exitoneof) {
852431Smark 				if (addr2 != 0)
853431Smark 					dot = addr2;
854431Smark 				return;
855431Smark 			}
856431Smark 			if (!isatty(0)) {
857431Smark 				if (intty)
858431Smark 					/*
859431Smark 					 * Chtty sys call at UCB may cause a
860431Smark 					 * input which was a tty to suddenly be
861431Smark 					 * turned into /dev/null.
862431Smark 					 */
863431Smark 					onhup();
864431Smark 				return;
865431Smark 			}
866431Smark 			if (addr2 != 0) {
867431Smark 				setlastchar('\n');
868431Smark 				putnl();
869431Smark 			}
870431Smark 			if (dol == zero) {
871431Smark 				if (addr2 == 0)
872431Smark 					putnl();
873431Smark 				notempty();
874431Smark 			}
875431Smark 			ungetchar(EOF);
876431Smark 			zop(hadpr);
877431Smark 			continue;
878431Smark 
879431Smark 		default:
880431Smark 			if (!isalpha(c))
881431Smark 				break;
882431Smark 			ungetchar(c);
883431Smark 			tailprim("", 0, 0);
884431Smark 		}
885431Smark 		error("What?|Unknown command character '%c'", c);
886431Smark 	}
887431Smark }
888