xref: /csrg-svn/usr.bin/ex/ex_subr.c (revision 493)
1441Smark /* Copyright (c) 1979 Regents of the University of California */
2441Smark #include "ex.h"
3441Smark #include "ex_re.h"
4441Smark #include "ex_tty.h"
5441Smark #include "ex_vis.h"
6441Smark 
7441Smark /*
8441Smark  * Random routines, in alphabetical order.
9441Smark  */
10441Smark 
11441Smark any(c, s)
12441Smark 	int c;
13441Smark 	register char *s;
14441Smark {
15441Smark 	register int x;
16441Smark 
17441Smark 	while (x = *s++)
18441Smark 		if (x == c)
19441Smark 			return (1);
20441Smark 	return (0);
21441Smark }
22441Smark 
23441Smark backtab(i)
24441Smark 	register int i;
25441Smark {
26441Smark 	register int j;
27441Smark 
28441Smark 	j = i % value(SHIFTWIDTH);
29441Smark 	if (j == 0)
30441Smark 		j = value(SHIFTWIDTH);
31441Smark 	i -= j;
32441Smark 	if (i < 0)
33441Smark 		i = 0;
34441Smark 	return (i);
35441Smark }
36441Smark 
37441Smark change()
38441Smark {
39441Smark 
40441Smark 	tchng++;
41441Smark 	chng = tchng;
42441Smark }
43441Smark 
44441Smark /*
45441Smark  * Column returns the number of
46441Smark  * columns occupied by printing the
47441Smark  * characters through position cp of the
48441Smark  * current line.
49441Smark  */
50441Smark column(cp)
51441Smark 	register char *cp;
52441Smark {
53441Smark 
54441Smark 	if (cp == 0)
55441Smark 		cp = &linebuf[LBSIZE - 2];
56441Smark 	return (qcolumn(cp, (char *) 0));
57441Smark }
58441Smark 
59441Smark Copy(to, from, size)
60441Smark 	register char *from, *to;
61441Smark 	register int size;
62441Smark {
63441Smark 
64441Smark 	if (size > 0)
65441Smark 		do
66441Smark 			*to++ = *from++;
67441Smark 		while (--size > 0);
68441Smark }
69441Smark 
70441Smark copyw(to, from, size)
71441Smark 	register line *from, *to;
72441Smark 	register int size;
73441Smark {
74441Smark 
75441Smark 	if (size > 0)
76441Smark 		do
77441Smark 			*to++ = *from++;
78441Smark 		while (--size > 0);
79441Smark }
80441Smark 
81441Smark copywR(to, from, size)
82441Smark 	register line *from, *to;
83441Smark 	register int size;
84441Smark {
85441Smark 
86441Smark 	while (--size >= 0)
87441Smark 		to[size] = from[size];
88441Smark }
89441Smark 
90441Smark ctlof(c)
91441Smark 	int c;
92441Smark {
93441Smark 
94441Smark 	return (c == TRIM ? '?' : c | ('A' - 1));
95441Smark }
96441Smark 
97441Smark dingdong()
98441Smark {
99441Smark 
100441Smark 	if (VB)
101441Smark 		putpad(VB);
102441Smark 	else if (value(ERRORBELLS))
103441Smark 		putch('\207');
104441Smark }
105441Smark 
106441Smark fixindent(indent)
107441Smark 	int indent;
108441Smark {
109441Smark 	register int i;
110441Smark 	register char *cp;
111441Smark 
112441Smark 	i = whitecnt(genbuf);
113441Smark 	cp = vpastwh(genbuf);
114441Smark 	if (*cp == 0 && i == indent && linebuf[0] == 0) {
115441Smark 		genbuf[0] = 0;
116441Smark 		return (i);
117441Smark 	}
118441Smark 	CP(genindent(i), cp);
119441Smark 	return (i);
120441Smark }
121441Smark 
122441Smark filioerr(cp)
123441Smark 	char *cp;
124441Smark {
125441Smark 	register int oerrno = errno;
126441Smark 
127441Smark 	lprintf("\"%s\"", cp);
128441Smark 	errno = oerrno;
129441Smark 	syserror();
130441Smark }
131441Smark 
132441Smark char *
133441Smark genindent(indent)
134441Smark 	register int indent;
135441Smark {
136441Smark 	register char *cp;
137441Smark 
138441Smark 	for (cp = genbuf; indent >= value(TABSTOP); indent -= value(TABSTOP))
139441Smark 		*cp++ = '\t';
140441Smark 	for (; indent > 0; indent--)
141441Smark 		*cp++ = ' ';
142441Smark 	return (cp);
143441Smark }
144441Smark 
145441Smark getDOT()
146441Smark {
147441Smark 
148441Smark 	getline(*dot);
149441Smark }
150441Smark 
151441Smark line *
152441Smark getmark(c)
153441Smark 	register int c;
154441Smark {
155441Smark 	register line *addr;
156441Smark 
157441Smark 	for (addr = one; addr <= dol; addr++)
158441Smark 		if (names[c - 'a'] == (*addr &~ 01)) {
159441Smark 			return (addr);
160441Smark 		}
161441Smark 	return (0);
162441Smark }
163441Smark 
164441Smark getn(cp)
165441Smark 	register char *cp;
166441Smark {
167441Smark 	register int i = 0;
168441Smark 
169441Smark 	while (isdigit(*cp))
170441Smark 		i = i * 10 + *cp++ - '0';
171441Smark 	if (*cp)
172441Smark 		return (0);
173441Smark 	return (i);
174441Smark }
175441Smark 
176441Smark ignnEOF()
177441Smark {
178441Smark 	register int c = getchar();
179441Smark 
180441Smark 	if (c == EOF)
181441Smark 		ungetchar(c);
182441Smark }
183441Smark 
184441Smark iswhite(c)
185441Smark 	int c;
186441Smark {
187441Smark 
188441Smark 	return (c == ' ' || c == '\t');
189441Smark }
190441Smark 
191441Smark junk(c)
192441Smark 	register int c;
193441Smark {
194441Smark 
195441Smark 	if (c && !value(BEAUTIFY))
196441Smark 		return (0);
197441Smark 	if (c >= ' ' && c != TRIM)
198441Smark 		return (0);
199441Smark 	switch (c) {
200441Smark 
201441Smark 	case '\t':
202441Smark 	case '\n':
203441Smark 	case '\f':
204441Smark 		return (0);
205441Smark 
206441Smark 	default:
207441Smark 		return (1);
208441Smark 	}
209441Smark }
210441Smark 
211441Smark killed()
212441Smark {
213441Smark 
214441Smark 	killcnt(addr2 - addr1 + 1);
215441Smark }
216441Smark 
217441Smark killcnt(cnt)
218441Smark 	register int cnt;
219441Smark {
220441Smark 
221441Smark 	if (inopen) {
222441Smark 		notecnt = cnt;
223441Smark 		notenam = notesgn = "";
224441Smark 		return;
225441Smark 	}
226441Smark 	if (!notable(cnt))
227441Smark 		return;
228441Smark 	printf("%d lines", cnt);
229441Smark 	if (value(TERSE) == 0) {
230441Smark 		printf(" %c%s", Command[0] | ' ', Command + 1);
231441Smark 		if (Command[strlen(Command) - 1] != 'e')
232441Smark 			putchar('e');
233441Smark 		putchar('d');
234441Smark 	}
235441Smark 	putNFL();
236441Smark }
237441Smark 
238441Smark lineno(a)
239441Smark 	line *a;
240441Smark {
241441Smark 
242441Smark 	return (a - zero);
243441Smark }
244441Smark 
245441Smark lineDOL()
246441Smark {
247441Smark 
248441Smark 	return (lineno(dol));
249441Smark }
250441Smark 
251441Smark lineDOT()
252441Smark {
253441Smark 
254441Smark 	return (lineno(dot));
255441Smark }
256441Smark 
257441Smark markDOT()
258441Smark {
259441Smark 
260441Smark 	markpr(dot);
261441Smark }
262441Smark 
263441Smark markpr(which)
264441Smark 	line *which;
265441Smark {
266441Smark 
267441Smark 	if ((inglobal == 0 || inopen) && which <= endcore) {
268441Smark 		names['z'-'a'+1] = *which & ~01;
269441Smark 		if (inopen)
270441Smark 			ncols['z'-'a'+1] = cursor;
271441Smark 	}
272441Smark }
273441Smark 
274441Smark markreg(c)
275441Smark 	register int c;
276441Smark {
277441Smark 
278441Smark 	if (c == '\'' || c == '`')
279441Smark 		return ('z' + 1);
280441Smark 	if (c >= 'a' && c <= 'z')
281441Smark 		return (c);
282441Smark 	return (0);
283441Smark }
284441Smark 
285441Smark /*
286441Smark  * Mesg decodes the terse/verbose strings. Thus
287441Smark  *	'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
288441Smark  *	'xxx|yyy' -> 'xxx' if terse, else 'yyy'
289441Smark  * All others map to themselves.
290441Smark  */
291441Smark char *
292441Smark mesg(str)
293441Smark 	register char *str;
294441Smark {
295441Smark 	register char *cp;
296441Smark 
297441Smark 	str = strcpy(genbuf, str);
298441Smark 	for (cp = str; *cp; cp++)
299441Smark 		switch (*cp) {
300441Smark 
301441Smark 		case '@':
302441Smark 			if (value(TERSE))
303441Smark 				*cp = 0;
304441Smark 			else
305441Smark 				*cp = ' ';
306441Smark 			break;
307441Smark 
308441Smark 		case '|':
309441Smark 			if (value(TERSE) == 0)
310441Smark 				return (cp + 1);
311441Smark 			*cp = 0;
312441Smark 			break;
313441Smark 		}
314441Smark 	return (str);
315441Smark }
316441Smark 
317441Smark /*VARARGS2*/
318441Smark merror(seekpt, i)
319474Smark #ifdef VMUNIX
320441Smark 	char *seekpt;
321441Smark #else
322474Smark # ifdef lint
323474Smark 	char *seekpt;
324474Smark # else
325441Smark 	int seekpt;
326474Smark # endif
327441Smark #endif
328441Smark 	int i;
329441Smark {
330441Smark 	register char *cp = linebuf;
331441Smark 
332441Smark 	if (seekpt == 0)
333441Smark 		return;
334441Smark 	merror1(seekpt);
335441Smark 	if (*cp == '\n')
336441Smark 		putnl(), cp++;
337441Smark 	if (inopen && CE)
338441Smark 		vclreol();
339441Smark 	if (SO && SE)
340441Smark 		putpad(SO);
341441Smark 	printf(mesg(cp), i);
342441Smark 	if (SO && SE)
343441Smark 		putpad(SE);
344441Smark }
345441Smark 
346441Smark merror1(seekpt)
347474Smark #ifdef VMUNIX
348441Smark 	char *seekpt;
349441Smark #else
350474Smark # ifdef lint
351474Smark 	char *seekpt;
352474Smark # else
353441Smark 	int seekpt;
354474Smark # endif
355441Smark #endif
356441Smark {
357441Smark 
358474Smark #ifdef VMUNIX
359474Smark 	strcpy(linebuf, seekpt);
360474Smark #else
361441Smark 	lseek(erfile, (long) seekpt, 0);
362441Smark 	if (read(erfile, linebuf, 128) < 2)
363441Smark 		CP(linebuf, "ERROR");
364474Smark #endif
365441Smark }
366441Smark 
367441Smark morelines()
368441Smark {
369441Smark 
370441Smark 	if ((int) sbrk(1024 * sizeof (line)) == -1)
371441Smark 		return (-1);
372441Smark 	endcore += 1024;
373441Smark 	return (0);
374441Smark }
375441Smark 
376441Smark nonzero()
377441Smark {
378441Smark 
379441Smark 	if (addr1 == zero) {
380441Smark 		notempty();
381441Smark 		error("Nonzero address required@on this command");
382441Smark 	}
383441Smark }
384441Smark 
385441Smark notable(i)
386441Smark 	int i;
387441Smark {
388441Smark 
389441Smark 	return (hush == 0 && !inglobal && i > value(REPORT));
390441Smark }
391441Smark 
392441Smark 
393441Smark notempty()
394441Smark {
395441Smark 
396441Smark 	if (dol == zero)
397441Smark 		error("No lines@in the buffer");
398441Smark }
399441Smark 
400441Smark 
401441Smark netchHAD(cnt)
402441Smark 	int cnt;
403441Smark {
404441Smark 
405441Smark 	netchange(lineDOL() - cnt);
406441Smark }
407441Smark 
408441Smark netchange(i)
409441Smark 	register int i;
410441Smark {
411441Smark 	register char *cp;
412441Smark 
413441Smark 	if (i > 0)
414441Smark 		notesgn = cp = "more ";
415441Smark 	else
416441Smark 		notesgn = cp = "fewer ", i = -i;
417441Smark 	if (inopen) {
418441Smark 		notecnt = i;
419441Smark 		notenam = "";
420441Smark 		return;
421441Smark 	}
422441Smark 	if (!notable(i))
423441Smark 		return;
424441Smark 	printf(mesg("%d %slines@in file after %s"), i, cp, Command);
425441Smark 	putNFL();
426441Smark }
427441Smark 
428441Smark putmark(addr)
429441Smark 	line *addr;
430441Smark {
431441Smark 
432441Smark 	putmk1(addr, putline());
433441Smark }
434441Smark 
435441Smark putmk1(addr, n)
436441Smark 	register line *addr;
437441Smark 	int n;
438441Smark {
439441Smark 	register line *markp;
440441Smark 
441441Smark 	*addr &= ~1;
442441Smark 	for (markp = (anymarks ? names : &names['z'-'a'+1]);
443441Smark 	  markp <= &names['z'-'a'+1]; markp++)
444441Smark 		if (*markp == *addr)
445441Smark 			*markp = n;
446441Smark 	*addr = n;
447441Smark }
448441Smark 
449441Smark char *
450441Smark plural(i)
451441Smark 	long i;
452441Smark {
453441Smark 
454441Smark 	return (i == 1 ? "" : "s");
455441Smark }
456441Smark 
457441Smark int	qcount();
458441Smark short	vcntcol;
459441Smark 
460441Smark qcolumn(lim, gp)
461441Smark 	register char *lim, *gp;
462441Smark {
463441Smark 	register int x;
464441Smark 	int (*OO)();
465441Smark 
466441Smark 	OO = Outchar;
467441Smark 	Outchar = qcount;
468441Smark 	vcntcol = 0;
469441Smark 	if (lim != NULL)
470441Smark 		x = lim[1], lim[1] = 0;
471441Smark 	pline(0);
472441Smark 	if (lim != NULL)
473441Smark 		lim[1] = x;
474441Smark 	if (gp)
475441Smark 		while (*gp)
476441Smark 			putchar(*gp++);
477441Smark 	Outchar = OO;
478441Smark 	return (vcntcol);
479441Smark }
480441Smark 
481441Smark int
482441Smark qcount(c)
483441Smark 	int c;
484441Smark {
485441Smark 
486441Smark 	if (c == '\t') {
487441Smark 		vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
488441Smark 		return;
489441Smark 	}
490441Smark 	vcntcol++;
491441Smark }
492441Smark 
493441Smark reverse(a1, a2)
494441Smark 	register line *a1, *a2;
495441Smark {
496441Smark 	register line t;
497441Smark 
498441Smark 	for (;;) {
499441Smark 		t = *--a2;
500441Smark 		if (a2 <= a1)
501441Smark 			return;
502441Smark 		*a2 = *a1;
503441Smark 		*a1++ = t;
504441Smark 	}
505441Smark }
506441Smark 
507441Smark save(a1, a2)
508441Smark 	line *a1;
509441Smark 	register line *a2;
510441Smark {
511441Smark 	register int more;
512441Smark 
513*493Smark 	if (!FIXUNDO)
514*493Smark 		return;
515*493Smark #ifdef TRACE
516*493Smark 	if (trace)
517*493Smark 		vudump("before save");
518*493Smark #endif
519441Smark 	undkind = UNDNONE;
520441Smark 	undadot = dot;
521441Smark 	more = (a2 - a1 + 1) - (unddol - dol);
522441Smark 	while (more > (endcore - truedol))
523441Smark 		if (morelines() < 0)
524441Smark 			error("Out of memory@saving lines for undo - try using ed or re");
525441Smark 	if (more)
526441Smark 		(*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
527441Smark 		    (truedol - unddol));
528441Smark 	unddol += more;
529441Smark 	truedol += more;
530441Smark 	copyw(dol + 1, a1, a2 - a1 + 1);
531441Smark 	undkind = UNDALL;
532441Smark 	unddel = a1 - 1;
533441Smark 	undap1 = a1;
534441Smark 	undap2 = a2 + 1;
535*493Smark #ifdef TRACE
536*493Smark 	if (trace)
537*493Smark 		vudump("after save");
538*493Smark #endif
539441Smark }
540441Smark 
541441Smark save12()
542441Smark {
543441Smark 
544441Smark 	save(addr1, addr2);
545441Smark }
546441Smark 
547441Smark saveall()
548441Smark {
549441Smark 
550441Smark 	save(one, dol);
551441Smark }
552441Smark 
553441Smark span()
554441Smark {
555441Smark 
556441Smark 	return (addr2 - addr1 + 1);
557441Smark }
558441Smark 
559441Smark sync()
560441Smark {
561441Smark 
562441Smark 	chng = 0;
563441Smark 	tchng = 0;
564441Smark 	xchng = 0;
565441Smark }
566441Smark 
567441Smark 
568441Smark skipwh()
569441Smark {
570441Smark 	register int wh;
571441Smark 
572441Smark 	wh = 0;
573441Smark 	while (iswhite(peekchar())) {
574441Smark 		wh++;
575441Smark 		ignchar();
576441Smark 	}
577441Smark 	return (wh);
578441Smark }
579441Smark 
580441Smark /*VARARGS2*/
581441Smark smerror(seekpt, cp)
582441Smark #ifdef lint
583441Smark 	char *seekpt;
584441Smark #else
585441Smark 	int seekpt;
586441Smark #endif
587441Smark 	char *cp;
588441Smark {
589441Smark 
590441Smark 	if (seekpt == 0)
591441Smark 		return;
592441Smark 	merror1(seekpt);
593441Smark 	if (inopen && CE)
594441Smark 		vclreol();
595441Smark 	if (SO && SE)
596441Smark 		putpad(SO);
597441Smark 	lprintf(mesg(linebuf), cp);
598441Smark 	if (SO && SE)
599441Smark 		putpad(SE);
600441Smark }
601441Smark 
602441Smark #define	std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
603441Smark 
604441Smark #define	error(i)	i
605441Smark 
606441Smark #ifdef lint
607441Smark char	*std_errlist[] = {
608441Smark #else
609*493Smark # ifdef VMUNIX
610474Smark char	*std_errlist[] = {
611*493Smark # else
612441Smark short	std_errlist[] = {
613*493Smark # endif
614441Smark #endif
615441Smark 	error("Error 0"),
616441Smark 	error("Not super-user"),
617441Smark 	error("No such file or directory"),
618441Smark 	error("No such process"),
619441Smark 	error("Interrupted system call"),
620441Smark 	error("Physical I/O error"),
621441Smark 	error("No such device or address"),
622441Smark 	error("Argument list too long"),
623441Smark 	error("Exec format error"),
624441Smark 	error("Bad file number"),
625441Smark 	error("No children"),
626441Smark 	error("No more processes"),
627441Smark 	error("Not enough core"),
628441Smark 	error("Permission denied"),
629441Smark 	error("Bad address"),
630441Smark 	error("Block device required"),
631441Smark 	error("Mount device busy"),
632441Smark 	error("File exists"),
633441Smark 	error("Cross-device link"),
634441Smark 	error("No such device"),
635441Smark 	error("Not a directory"),
636441Smark 	error("Is a directory"),
637441Smark 	error("Invalid argument"),
638441Smark 	error("File table overflow"),
639441Smark 	error("Too many open files"),
640441Smark 	error("Not a typewriter"),
641441Smark 	error("Text file busy"),
642441Smark 	error("File too large"),
643441Smark 	error("No space left on device"),
644441Smark 	error("Illegal seek"),
645441Smark 	error("Read-only file system"),
646441Smark 	error("Too many links"),
647441Smark 	error("Broken pipe")
648441Smark #ifndef QUOTA
649441Smark 	, error("Math argument")
650441Smark 	, error("Result too large")
651441Smark #else
652441Smark 	, error("Quota exceeded")
653441Smark #endif
654441Smark };
655441Smark 
656441Smark #undef	error
657441Smark 
658441Smark char *
659441Smark strend(cp)
660441Smark 	register char *cp;
661441Smark {
662441Smark 
663441Smark 	while (*cp)
664441Smark 		cp++;
665441Smark 	return (cp);
666441Smark }
667441Smark 
668441Smark strcLIN(dp)
669441Smark 	char *dp;
670441Smark {
671441Smark 
672441Smark 	CP(linebuf, dp);
673441Smark }
674441Smark 
675441Smark syserror()
676441Smark {
677441Smark 	register int e = errno;
678441Smark 
679441Smark 	dirtcnt = 0;
680441Smark 	putchar(' ');
681441Smark 	if (e >= 0 && errno <= std_nerrs)
682441Smark 		error(std_errlist[e]);
683441Smark 	else
684441Smark 		error("System error %d", e);
685441Smark }
686441Smark 
687441Smark char *
688441Smark vfindcol(i)
689441Smark 	int i;
690441Smark {
691441Smark 	register char *cp;
692441Smark 	register int (*OO)() = Outchar;
693441Smark 
694441Smark 	Outchar = qcount;
695441Smark 	ignore(qcolumn(linebuf - 1, NOSTR));
696441Smark 	for (cp = linebuf; *cp && vcntcol < i; cp++)
697441Smark 		putchar(*cp);
698441Smark 	if (cp != linebuf)
699441Smark 		cp--;
700441Smark 	Outchar = OO;
701441Smark 	return (cp);
702441Smark }
703441Smark 
704441Smark char *
705441Smark vskipwh(cp)
706441Smark 	register char *cp;
707441Smark {
708441Smark 
709441Smark 	while (iswhite(*cp) && cp[1])
710441Smark 		cp++;
711441Smark 	return (cp);
712441Smark }
713441Smark 
714441Smark 
715441Smark char *
716441Smark vpastwh(cp)
717441Smark 	register char *cp;
718441Smark {
719441Smark 
720441Smark 	while (iswhite(*cp))
721441Smark 		cp++;
722441Smark 	return (cp);
723441Smark }
724441Smark 
725441Smark whitecnt(cp)
726441Smark 	register char *cp;
727441Smark {
728441Smark 	register int i;
729441Smark 
730441Smark 	i = 0;
731441Smark 	for (;;)
732441Smark 		switch (*cp++) {
733441Smark 
734441Smark 		case '\t':
735441Smark 			i += value(TABSTOP) - i % value(TABSTOP);
736441Smark 			break;
737441Smark 
738441Smark 		case ' ':
739441Smark 			i++;
740441Smark 			break;
741441Smark 
742441Smark 		default:
743441Smark 			return (i);
744441Smark 		}
745441Smark }
746441Smark 
747441Smark #ifdef lint
748441Smark Ignore(a)
749441Smark 	char *a;
750441Smark {
751441Smark 
752441Smark 	a = a;
753441Smark }
754441Smark 
755441Smark Ignorf(a)
756441Smark 	int (*a)();
757441Smark {
758441Smark 
759441Smark 	a = a;
760441Smark }
761441Smark #endif
762441Smark 
763441Smark markit(addr)
764441Smark 	line *addr;
765441Smark {
766441Smark 
767441Smark 	if (addr != dot && addr >= one && addr <= dol)
768441Smark 		markDOT();
769441Smark }
770441Smark 
771