xref: /csrg-svn/usr.bin/ex/ex_cmds.c (revision 30596)
121655Sdist /*
221655Sdist  * Copyright (c) 1980 Regents of the University of California.
321655Sdist  * All rights reserved.  The Berkeley software License Agreement
421655Sdist  * specifies the terms and conditions for redistribution.
521655Sdist  */
621655Sdist 
721655Sdist #ifndef lint
8*30596Sconrad static char *sccsid = "@(#)ex_cmds.c	7.11 (Berkeley) 03/09/87";
921655Sdist #endif not lint
1021655Sdist 
11431Smark #include "ex.h"
12431Smark #include "ex_argv.h"
13431Smark #include "ex_temp.h"
14431Smark #include "ex_tty.h"
1521680Sdist #include "ex_vis.h"
16431Smark 
17431Smark bool	pflag, nflag;
18431Smark int	poffset;
19431Smark 
20431Smark #define	nochng()	lchng = chng
21431Smark 
22431Smark /*
23431Smark  * Main loop for command mode command decoding.
24431Smark  * A few commands are executed here, but main function
25431Smark  * is to strip command addresses, do a little address oriented
26431Smark  * processing and call command routines to do the real work.
27431Smark  */
28431Smark commands(noprompt, exitoneof)
29431Smark 	bool noprompt, exitoneof;
30431Smark {
31431Smark 	register line *addr;
32431Smark 	register int c;
33431Smark 	register int lchng;
34431Smark 	int given;
35431Smark 	int seensemi;
36431Smark 	int cnt;
37431Smark 	bool hadpr;
38431Smark 
39431Smark 	resetflav();
40431Smark 	nochng();
41431Smark 	for (;;) {
42431Smark 		/*
43431Smark 		 * If dot at last command
44431Smark 		 * ended up at zero, advance to one if there is a such.
45431Smark 		 */
46431Smark 		if (dot <= zero) {
47431Smark 			dot = zero;
48431Smark 			if (dol > zero)
49431Smark 				dot = one;
50431Smark 		}
51431Smark 		shudclob = 0;
52431Smark 
53431Smark 		/*
54431Smark 		 * If autoprint or trailing print flags,
55431Smark 		 * print the line at the specified offset
56431Smark 		 * before the next command.
57431Smark 		 */
58431Smark 		if (pflag ||
59431Smark 		    lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
60431Smark 			pflag = 0;
61431Smark 			nochng();
62431Smark 			if (dol != zero) {
63431Smark 				addr1 = addr2 = dot + poffset;
64431Smark 				if (addr1 < one || addr1 > dol)
65431Smark error("Offset out-of-bounds|Offset after command too large");
66431Smark 				setdot1();
67431Smark 				goto print;
68431Smark 			}
69431Smark 		}
70431Smark 		nochng();
71431Smark 
72431Smark 		/*
73431Smark 		 * Print prompt if appropriate.
74431Smark 		 * If not in global flush output first to prevent
75431Smark 		 * going into pfast mode unreasonably.
76431Smark 		 */
77431Smark 		if (inglobal == 0) {
78431Smark 			flush();
79431Smark 			if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
80*30596Sconrad 				ex_putchar(':');
81431Smark 				hadpr = 1;
82431Smark 			}
83431Smark 			TSYNC();
84431Smark 		}
85431Smark 
86431Smark 		/*
87431Smark 		 * Gobble up the address.
88431Smark 		 * Degenerate addresses yield ".".
89431Smark 		 */
90431Smark 		addr2 = 0;
91431Smark 		given = seensemi = 0;
92431Smark 		do {
93431Smark 			addr1 = addr2;
94*30596Sconrad 			addr = address((char *) 0);
95431Smark 			c = getcd();
96431Smark 			if (addr == 0)
97431Smark 				if (c == ',')
98431Smark 					addr = dot;
99431Smark 				else if (addr1 != 0) {
100431Smark 					addr2 = dot;
101431Smark 					break;
102431Smark 				} else
103431Smark 					break;
104431Smark 			addr2 = addr;
105431Smark 			given++;
106431Smark 			if (c == ';') {
107431Smark 				c = ',';
108431Smark 				dot = addr;
109431Smark 				seensemi = 1;
110431Smark 			}
111431Smark 		} while (c == ',');
112431Smark 		if (c == '%') {
113431Smark 			/* %: same as 1,$ */
114431Smark 			addr1 = one;
115431Smark 			addr2 = dol;
116431Smark 			given = 2;
117*30596Sconrad 			c = ex_getchar();
118431Smark 		}
119431Smark 		if (addr1 == 0)
120431Smark 			addr1 = addr2;
121431Smark 		if (c == ':')
122*30596Sconrad 			c = ex_getchar();
123431Smark 
124431Smark 		/*
125431Smark 		 * Set command name for special character commands.
126431Smark 		 */
127431Smark 		tailspec(c);
128431Smark 
129431Smark 		/*
130431Smark 		 * If called via : escape from open or visual, limit
131431Smark 		 * the set of available commands here to save work below.
132431Smark 		 */
133431Smark 		if (inopen) {
134431Smark 			if (c=='\n' || c=='\r' || c==CTRL(d) || c==EOF) {
135431Smark 				if (addr2)
136431Smark 					dot = addr2;
137431Smark 				if (c == EOF)
138431Smark 					return;
139431Smark 				continue;
140431Smark 			}
141431Smark 			if (any(c, "o"))
142431Smark notinvis:
143431Smark 				tailprim(Command, 1, 1);
144431Smark 		}
145431Smark 		switch (c) {
146431Smark 
147431Smark 		case 'a':
148431Smark 
149512Smark 			switch(peekchar()) {
150512Smark 			case 'b':
151512Smark /* abbreviate */
152512Smark 				tail("abbreviate");
153512Smark 				setnoaddr();
154512Smark 				mapcmd(0, 1);
155512Smark 				anyabbrs = 1;
156512Smark 				continue;
157512Smark 			case 'r':
158431Smark /* args */
159431Smark 				tail("args");
160431Smark 				setnoaddr();
161431Smark 				eol();
162431Smark 				pargs();
163431Smark 				continue;
164431Smark 			}
165431Smark 
166431Smark /* append */
167431Smark 			if (inopen)
168431Smark 				goto notinvis;
169431Smark 			tail("append");
170431Smark 			setdot();
171431Smark 			aiflag = exclam();
172431Smark 			newline();
173512Smark 			vmacchng(0);
174431Smark 			deletenone();
175431Smark 			setin(addr2);
176512Smark 			inappend = 1;
177431Smark 			ignore(append(gettty, addr2));
178512Smark 			inappend = 0;
179431Smark 			nochng();
180431Smark 			continue;
181431Smark 
182431Smark 		case 'c':
183431Smark 			switch (peekchar()) {
184431Smark 
185431Smark /* copy */
186431Smark 			case 'o':
187431Smark 				tail("copy");
188512Smark 				vmacchng(0);
189431Smark 				move();
190431Smark 				continue;
191431Smark 
192431Smark #ifdef CHDIR
193431Smark /* cd */
194431Smark 			case 'd':
195431Smark 				tail("cd");
196431Smark 				goto changdir;
197431Smark 
198431Smark /* chdir */
199431Smark 			case 'h':
200431Smark 				ignchar();
201431Smark 				if (peekchar() == 'd') {
202431Smark 					register char *p;
203431Smark 					tail2of("chdir");
204431Smark changdir:
205431Smark 					if (savedfile[0] == '/' || !value(WARN))
206431Smark 						ignore(exclam());
207431Smark 					else
208431Smark 						ignore(quickly());
209431Smark 					if (skipend()) {
210431Smark 						p = getenv("HOME");
211431Smark 						if (p == NULL)
212431Smark 							error("Home directory unknown");
213431Smark 					} else
214431Smark 						getone(), p = file;
215431Smark 					eol();
216431Smark 					if (chdir(p) < 0)
217431Smark 						filioerr(p);
218431Smark 					if (savedfile[0] != '/')
219431Smark 						edited = 0;
220431Smark 					continue;
221431Smark 				}
222431Smark 				if (inopen)
223431Smark 					tailprim("change", 2, 1);
224431Smark 				tail2of("change");
225431Smark 				break;
226431Smark 
227431Smark #endif
228431Smark 			default:
229431Smark 				if (inopen)
230431Smark 					goto notinvis;
231431Smark 				tail("change");
232431Smark 				break;
233431Smark 			}
234431Smark /* change */
235431Smark 			aiflag = exclam();
236431Smark 			setCNL();
237512Smark 			vmacchng(0);
238431Smark 			setin(addr1);
239*30596Sconrad 			ex_delete(0);
240512Smark 			inappend = 1;
241431Smark 			ignore(append(gettty, addr1 - 1));
242512Smark 			inappend = 0;
243431Smark 			nochng();
244431Smark 			continue;
245431Smark 
246431Smark /* delete */
247431Smark 		case 'd':
248431Smark 			/*
249431Smark 			 * Caution: dp and dl have special meaning already.
250431Smark 			 */
251431Smark 			tail("delete");
252431Smark 			c = cmdreg();
253431Smark 			setCNL();
254512Smark 			vmacchng(0);
255431Smark 			if (c)
256431Smark 				YANKreg(c);
257*30596Sconrad 			ex_delete(0);
258431Smark 			appendnone();
259431Smark 			continue;
260431Smark 
261431Smark /* edit */
262431Smark /* ex */
263431Smark 		case 'e':
264431Smark 			tail(peekchar() == 'x' ? "ex" : "edit");
265512Smark editcmd:
266431Smark 			if (!exclam() && chng)
267431Smark 				c = 'E';
268431Smark 			filename(c);
269431Smark 			if (c == 'E') {
270431Smark 				ungetchar(lastchar());
271431Smark 				ignore(quickly());
272431Smark 			}
273431Smark 			setnoaddr();
274431Smark doecmd:
275431Smark 			init();
276431Smark 			addr2 = zero;
277431Smark 			laste++;
278*30596Sconrad 			ex_sync();
279431Smark 			rop(c);
28021680Sdist #ifdef VMUNIX
28121680Sdist 			tlaste();
28221680Sdist #endif
28321680Sdist 			laste = 0;
284*30596Sconrad 			ex_sync();
285431Smark 			nochng();
286431Smark 			continue;
287431Smark 
288431Smark /* file */
289431Smark 		case 'f':
290431Smark 			tail("file");
291431Smark 			setnoaddr();
292431Smark 			filename(c);
293431Smark 			noonl();
294469Smark /*
295431Smark 			synctmp();
296469Smark */
297431Smark 			continue;
298431Smark 
299431Smark /* global */
300431Smark 		case 'g':
301431Smark 			tail("global");
302431Smark 			global(!exclam());
303431Smark 			nochng();
304431Smark 			continue;
305431Smark 
306431Smark /* insert */
307431Smark 		case 'i':
308431Smark 			if (inopen)
309431Smark 				goto notinvis;
310431Smark 			tail("insert");
311431Smark 			setdot();
312431Smark 			nonzero();
313431Smark 			aiflag = exclam();
314431Smark 			newline();
315512Smark 			vmacchng(0);
316431Smark 			deletenone();
317431Smark 			setin(addr2);
318512Smark 			inappend = 1;
319431Smark 			ignore(append(gettty, addr2 - 1));
320512Smark 			inappend = 0;
321431Smark 			if (dot == zero && dol > zero)
322431Smark 				dot = one;
323431Smark 			nochng();
324431Smark 			continue;
325431Smark 
326431Smark /* join */
327431Smark 		case 'j':
328431Smark 			tail("join");
329431Smark 			c = exclam();
330431Smark 			setcount();
331431Smark 			nonzero();
332431Smark 			newline();
333512Smark 			vmacchng(0);
334431Smark 			if (given < 2 && addr2 != dol)
335431Smark 				addr2++;
336431Smark 			join(c);
337431Smark 			continue;
338431Smark 
339431Smark /* k */
340431Smark 		case 'k':
341431Smark casek:
342431Smark 			pastwh();
343*30596Sconrad 			c = ex_getchar();
344431Smark 			if (endcmd(c))
345431Smark 				serror("Mark what?|%s requires following letter", Command);
346431Smark 			newline();
347431Smark 			if (!islower(c))
348431Smark 				error("Bad mark|Mark must specify a letter");
349431Smark 			setdot();
350431Smark 			nonzero();
351431Smark 			names[c - 'a'] = *addr2 &~ 01;
352431Smark 			anymarks = 1;
353431Smark 			continue;
354431Smark 
355431Smark /* list */
356431Smark 		case 'l':
357431Smark 			tail("list");
358431Smark 			setCNL();
359431Smark 			ignorf(setlist(1));
360431Smark 			pflag = 0;
361431Smark 			goto print;
362431Smark 
363431Smark 		case 'm':
364431Smark 			if (peekchar() == 'a') {
365431Smark 				ignchar();
366431Smark 				if (peekchar() == 'p') {
367431Smark /* map */
368431Smark 					tail2of("map");
369431Smark 					setnoaddr();
370512Smark 					mapcmd(0, 0);
371431Smark 					continue;
372431Smark 				}
373431Smark /* mark */
374431Smark 				tail2of("mark");
375431Smark 				goto casek;
376431Smark 			}
377431Smark /* move */
378431Smark 			tail("move");
379512Smark 			vmacchng(0);
380431Smark 			move();
381431Smark 			continue;
382431Smark 
383431Smark 		case 'n':
384431Smark 			if (peekchar() == 'u') {
385431Smark 				tail("number");
386431Smark 				goto numberit;
387431Smark 			}
388431Smark /* next */
389431Smark 			tail("next");
390431Smark 			setnoaddr();
391431Smark 			ckaw();
392431Smark 			ignore(quickly());
393431Smark 			if (getargs())
394431Smark 				makargs();
395431Smark 			next();
396431Smark 			c = 'e';
397431Smark 			filename(c);
398431Smark 			goto doecmd;
399431Smark 
400431Smark /* open */
401431Smark 		case 'o':
402431Smark 			tail("open");
403431Smark 			oop();
404431Smark 			pflag = 0;
405431Smark 			nochng();
406431Smark 			continue;
407431Smark 
408431Smark 		case 'p':
409431Smark 		case 'P':
410431Smark 			switch (peekchar()) {
411431Smark 
412431Smark /* put */
413431Smark 			case 'u':
414431Smark 				tail("put");
415431Smark 				setdot();
416431Smark 				c = cmdreg();
417431Smark 				eol();
418512Smark 				vmacchng(0);
419431Smark 				if (c)
420431Smark 					putreg(c);
421431Smark 				else
422431Smark 					put();
423431Smark 				continue;
424431Smark 
425431Smark 			case 'r':
426431Smark 				ignchar();
427431Smark 				if (peekchar() == 'e') {
428431Smark /* preserve */
429431Smark 					tail2of("preserve");
430431Smark 					eol();
431431Smark 					if (preserve() == 0)
432431Smark 						error("Preserve failed!");
433431Smark 					else
434431Smark 						error("File preserved.");
435431Smark 				}
436431Smark 				tail2of("print");
437431Smark 				break;
438431Smark 
439431Smark 			default:
440431Smark 				tail("print");
441431Smark 				break;
442431Smark 			}
443431Smark /* print */
444431Smark 			setCNL();
445431Smark 			pflag = 0;
446431Smark print:
447431Smark 			nonzero();
448431Smark 			if (CL && span() > LINES) {
449431Smark 				flush1();
450431Smark 				vclear();
451431Smark 			}
452431Smark 			plines(addr1, addr2, 1);
453431Smark 			continue;
454431Smark 
455431Smark /* quit */
456431Smark 		case 'q':
457431Smark 			tail("quit");
458431Smark 			setnoaddr();
459431Smark 			c = quickly();
460431Smark 			eol();
461431Smark 			if (!c)
462431Smark quit:
463431Smark 				nomore();
464431Smark 			if (inopen) {
465431Smark 				vgoto(WECHO, 0);
466431Smark 				if (!ateopr())
467431Smark 					vnfl();
468431Smark 				else {
469512Smark 					tostop();
470431Smark 				}
471431Smark 				flush();
472*30596Sconrad 				ignore(setty(normf));
473431Smark 			}
474431Smark 			cleanup(1);
475*30596Sconrad 			ex_exit(0);
476431Smark 
477431Smark 		case 'r':
478431Smark 			if (peekchar() == 'e') {
479431Smark 				ignchar();
480431Smark 				switch (peekchar()) {
481431Smark 
482431Smark /* rewind */
483431Smark 				case 'w':
484431Smark 					tail2of("rewind");
485431Smark 					setnoaddr();
486811Smark 					if (!exclam()) {
487811Smark 						ckaw();
488811Smark 						if (chng && dol > zero)
489811Smark 							error("No write@since last chage (:rewind! overrides)");
490811Smark 					}
491512Smark 					eol();
492431Smark 					erewind();
493431Smark 					next();
494431Smark 					c = 'e';
495431Smark 					ungetchar(lastchar());
496431Smark 					filename(c);
497431Smark 					goto doecmd;
498431Smark 
499431Smark /* recover */
500431Smark 				case 'c':
501431Smark 					tail2of("recover");
502431Smark 					setnoaddr();
503431Smark 					c = 'e';
504431Smark 					if (!exclam() && chng)
505431Smark 						c = 'E';
506431Smark 					filename(c);
507431Smark 					if (c == 'E') {
508431Smark 						ungetchar(lastchar());
509431Smark 						ignore(quickly());
510431Smark 					}
511431Smark 					init();
512431Smark 					addr2 = zero;
513431Smark 					laste++;
514*30596Sconrad 					ex_sync();
515431Smark 					recover();
516431Smark 					rop2();
517431Smark 					revocer();
518431Smark 					if (status == 0)
519431Smark 						rop3(c);
520431Smark 					if (dol != zero)
521431Smark 						change();
52221680Sdist #ifdef VMUNIX
52321680Sdist 					tlaste();
52421680Sdist #endif
52521680Sdist 					laste = 0;
526431Smark 					nochng();
527431Smark 					continue;
528431Smark 				}
529431Smark 				tail2of("read");
530431Smark 			} else
531431Smark 				tail("read");
532431Smark /* read */
533431Smark 			if (savedfile[0] == 0 && dol == zero)
534431Smark 				c = 'e';
535431Smark 			pastwh();
536512Smark 			vmacchng(0);
537431Smark 			if (peekchar() == '!') {
538431Smark 				setdot();
539431Smark 				ignchar();
540431Smark 				unix0(0);
541431Smark 				filter(0);
542431Smark 				continue;
543431Smark 			}
544431Smark 			filename(c);
545431Smark 			rop(c);
546431Smark 			nochng();
547431Smark 			if (inopen && endline && addr1 > zero && addr1 < dol)
548431Smark 				dot = addr1 + 1;
549431Smark 			continue;
550431Smark 
551431Smark 		case 's':
552431Smark 			switch (peekchar()) {
553431Smark 			/*
554431Smark 			 * Caution: 2nd char cannot be c, g, or r
555431Smark 			 * because these have meaning to substitute.
556431Smark 			 */
557431Smark 
558431Smark /* set */
559431Smark 			case 'e':
560431Smark 				tail("set");
561431Smark 				setnoaddr();
562431Smark 				set();
563431Smark 				continue;
564431Smark 
565431Smark /* shell */
566431Smark 			case 'h':
567431Smark 				tail("shell");
568431Smark 				setNAEOL();
569431Smark 				vnfl();
570431Smark 				putpad(TE);
571431Smark 				flush();
572431Smark 				unixwt(1, unixex("-i", (char *) 0, 0, 0));
573431Smark 				vcontin(0);
574431Smark 				continue;
575431Smark 
576431Smark /* source */
577431Smark 			case 'o':
57821680Sdist #ifdef notdef
579431Smark 				if (inopen)
580431Smark 					goto notinvis;
58121680Sdist #endif
582431Smark 				tail("source");
583431Smark 				setnoaddr();
584431Smark 				getone();
585431Smark 				eol();
586431Smark 				source(file, 0);
587431Smark 				continue;
588865Smark #ifdef SIGTSTP
58921680Sdist /* stop, suspend */
590512Smark 			case 't':
591512Smark 				tail("stop");
59221680Sdist 				goto suspend;
59321680Sdist 			case 'u':
59421680Sdist 				tail("suspend");
59521680Sdist suspend:
596512Smark 				if (!ldisc)
597512Smark 					error("Old tty driver|Not using new tty driver/shell");
598512Smark 				c = exclam();
599512Smark 				eol();
600512Smark 				if (!c)
601512Smark 					ckaw();
602512Smark 				onsusp();
603512Smark 				continue;
604512Smark #endif
605512Smark 
606431Smark 			}
607431Smark 			/* fall into ... */
608431Smark 
609431Smark /* & */
610431Smark /* ~ */
611431Smark /* substitute */
612431Smark 		case '&':
613431Smark 		case '~':
614431Smark 			Command = "substitute";
615431Smark 			if (c == 's')
616431Smark 				tail(Command);
617512Smark 			vmacchng(0);
618431Smark 			if (!substitute(c))
619431Smark 				pflag = 0;
620431Smark 			continue;
621431Smark 
622431Smark /* t */
623431Smark 		case 't':
624431Smark 			if (peekchar() == 'a') {
625431Smark 				tail("tag");
626431Smark 				tagfind(exclam());
627431Smark 				if (!inopen)
628431Smark 					lchng = chng - 1;
629431Smark 				else
630431Smark 					nochng();
631431Smark 				continue;
632431Smark 			}
633431Smark 			tail("t");
634512Smark 			vmacchng(0);
635431Smark 			move();
636431Smark 			continue;
637431Smark 
638431Smark 		case 'u':
639431Smark 			if (peekchar() == 'n') {
640512Smark 				ignchar();
641512Smark 				switch(peekchar()) {
642431Smark /* unmap */
643512Smark 				case 'm':
644431Smark 					tail2of("unmap");
645431Smark 					setnoaddr();
646512Smark 					mapcmd(1, 0);
647431Smark 					continue;
648512Smark /* unabbreviate */
649512Smark 				case 'a':
650512Smark 					tail2of("unabbreviate");
651512Smark 					setnoaddr();
652512Smark 					mapcmd(1, 1);
653512Smark 					anyabbrs = 1;
654512Smark 					continue;
655431Smark 				}
656431Smark /* undo */
657431Smark 				tail2of("undo");
658431Smark 			} else
659431Smark 				tail("undo");
660431Smark 			setnoaddr();
661431Smark 			markDOT();
662431Smark 			c = exclam();
663431Smark 			newline();
664431Smark 			undo(c);
665431Smark 			continue;
666431Smark 
667431Smark 		case 'v':
668431Smark 			switch (peekchar()) {
669431Smark 
670431Smark 			case 'e':
671431Smark /* version */
672431Smark 				tail("version");
673431Smark 				setNAEOL();
674*30596Sconrad 				ex_printf("@(#) Version 3.7, 6/7/85."+5);
675431Smark 				noonl();
676431Smark 				continue;
677431Smark 
678431Smark /* visual */
679431Smark 			case 'i':
680431Smark 				tail("visual");
681512Smark 				if (inopen) {
682512Smark 					c = 'e';
683512Smark 					goto editcmd;
684512Smark 				}
685431Smark 				vop();
686431Smark 				pflag = 0;
687431Smark 				nochng();
688431Smark 				continue;
689431Smark 			}
690431Smark /* v */
691431Smark 			tail("v");
692431Smark 			global(0);
693431Smark 			nochng();
694431Smark 			continue;
695431Smark 
696431Smark /* write */
697431Smark 		case 'w':
698431Smark 			c = peekchar();
699431Smark 			tail(c == 'q' ? "wq" : "write");
700487Smark wq:
701431Smark 			if (skipwh() && peekchar() == '!') {
702487Smark 				pofix();
703431Smark 				ignchar();
704431Smark 				setall();
705431Smark 				unix0(0);
706431Smark 				filter(1);
707431Smark 			} else {
708431Smark 				setall();
709431Smark 				wop(1);
710431Smark 				nochng();
711431Smark 			}
712431Smark 			if (c == 'q')
713431Smark 				goto quit;
714431Smark 			continue;
715431Smark 
716487Smark /* xit */
717487Smark 		case 'x':
718487Smark 			tail("xit");
719487Smark 			if (!chng)
720487Smark 				goto quit;
721487Smark 			c = 'q';
722487Smark 			goto wq;
723487Smark 
724431Smark /* yank */
725431Smark 		case 'y':
726431Smark 			tail("yank");
727431Smark 			c = cmdreg();
728431Smark 			setcount();
729431Smark 			eol();
730512Smark 			vmacchng(0);
731431Smark 			if (c)
732431Smark 				YANKreg(c);
733431Smark 			else
734431Smark 				yank();
735431Smark 			continue;
736431Smark 
737431Smark /* z */
738431Smark 		case 'z':
739431Smark 			zop(0);
740431Smark 			pflag = 0;
741431Smark 			continue;
742431Smark 
743431Smark /* * */
744431Smark /* @ */
745431Smark 		case '*':
746431Smark 		case '@':
747*30596Sconrad 			c = ex_getchar();
748431Smark 			if (c=='\n' || c=='\r')
749431Smark 				ungetchar(c);
750431Smark 			if (any(c, "@*\n\r"))
751431Smark 				c = lastmac;
752431Smark 			if (isupper(c))
753431Smark 				c = tolower(c);
754431Smark 			if (!islower(c))
755431Smark 				error("Bad register");
756431Smark 			newline();
757431Smark 			setdot();
758431Smark 			cmdmac(c);
759431Smark 			continue;
760431Smark 
761431Smark /* | */
762431Smark 		case '|':
763431Smark 			endline = 0;
764431Smark 			goto caseline;
765431Smark 
766431Smark /* \n */
767431Smark 		case '\n':
768431Smark 			endline = 1;
769431Smark caseline:
770431Smark 			notempty();
771431Smark 			if (addr2 == 0) {
772431Smark 				if (UP != NOSTR && c == '\n' && !inglobal)
773431Smark 					c = CTRL(k);
774431Smark 				if (inglobal)
775431Smark 					addr1 = addr2 = dot;
776487Smark 				else {
777487Smark 					if (dot == dol)
778487Smark 						error("At EOF|At end-of-file");
779431Smark 					addr1 = addr2 = dot + 1;
780487Smark 				}
781431Smark 			}
782431Smark 			setdot();
783431Smark 			nonzero();
784431Smark 			if (seensemi)
785431Smark 				addr1 = addr2;
786431Smark 			getline(*addr1);
787431Smark 			if (c == CTRL(k)) {
788431Smark 				flush1();
789431Smark 				destline--;
790431Smark 				if (hadpr)
791431Smark 					shudclob = 1;
792431Smark 			}
793431Smark 			plines(addr1, addr2, 1);
794431Smark 			continue;
795431Smark 
796512Smark /* " */
797512Smark 		case '"':
798512Smark 			comment();
799512Smark 			continue;
800512Smark 
801431Smark /* # */
802431Smark 		case '#':
803431Smark numberit:
804431Smark 			setCNL();
805431Smark 			ignorf(setnumb(1));
806431Smark 			pflag = 0;
807431Smark 			goto print;
808431Smark 
809431Smark /* = */
810431Smark 		case '=':
811431Smark 			newline();
812431Smark 			setall();
813487Smark 			if (inglobal == 2)
814487Smark 				pofix();
815*30596Sconrad 			ex_printf("%d", lineno(addr2));
816431Smark 			noonl();
817431Smark 			continue;
818431Smark 
819431Smark /* ! */
820431Smark 		case '!':
821431Smark 			if (addr2 != 0) {
822512Smark 				vmacchng(0);
823431Smark 				unix0(0);
824431Smark 				setdot();
825431Smark 				filter(2);
826431Smark 			} else {
827431Smark 				unix0(1);
828487Smark 				pofix();
829431Smark 				putpad(TE);
830431Smark 				flush();
831431Smark 				unixwt(1, unixex("-c", uxb, 0, 0));
832512Smark 				vclrech(1);	/* vcontin(0); */
833431Smark 				nochng();
834431Smark 			}
835431Smark 			continue;
836431Smark 
837431Smark /* < */
838431Smark /* > */
839431Smark 		case '<':
840431Smark 		case '>':
841431Smark 			for (cnt = 1; peekchar() == c; cnt++)
842431Smark 				ignchar();
843431Smark 			setCNL();
844512Smark 			vmacchng(0);
845431Smark 			shift(c, cnt);
846431Smark 			continue;
847431Smark 
848431Smark /* ^D */
849431Smark /* EOF */
850431Smark 		case CTRL(d):
851431Smark 		case EOF:
852431Smark 			if (exitoneof) {
853431Smark 				if (addr2 != 0)
854431Smark 					dot = addr2;
855431Smark 				return;
856431Smark 			}
857431Smark 			if (!isatty(0)) {
858431Smark 				if (intty)
859431Smark 					/*
860431Smark 					 * Chtty sys call at UCB may cause a
861431Smark 					 * input which was a tty to suddenly be
862431Smark 					 * turned into /dev/null.
863431Smark 					 */
864431Smark 					onhup();
865431Smark 				return;
866431Smark 			}
867431Smark 			if (addr2 != 0) {
868431Smark 				setlastchar('\n');
869431Smark 				putnl();
870431Smark 			}
871431Smark 			if (dol == zero) {
872431Smark 				if (addr2 == 0)
873431Smark 					putnl();
874431Smark 				notempty();
875431Smark 			}
876431Smark 			ungetchar(EOF);
877431Smark 			zop(hadpr);
878431Smark 			continue;
879431Smark 
880431Smark 		default:
881431Smark 			if (!isalpha(c))
882431Smark 				break;
883431Smark 			ungetchar(c);
884431Smark 			tailprim("", 0, 0);
885431Smark 		}
886431Smark 		error("What?|Unknown command character '%c'", c);
887431Smark 	}
888431Smark }
889