xref: /original-bsd/old/adb/common_source/output.c (revision 7bad34b3)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)output.c	5.2 (Berkeley) 04/04/91";
10 #endif /* not lint */
11 
12 /*
13  * adb - output
14  */
15 
16 #include "defs.h"
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <varargs.h>
20 
21 extern char TOODEEP[];
22 
23 int	infile;
24 int	outfile = 1;
25 
26 char	printbuf[LINELEN];
27 char	*printptr = printbuf;
28 
29 
30 /*
31  * Print the string s.
32  */
33 prints(s)
34 	register char *s;
35 {
36 	register int c;
37 
38 	while ((c = *s++) != '\0')
39 		printc(c);
40 }
41 
42 /*
43  * Print the character c.
44  */
45 printc(c)
46 	int c;
47 {
48 
49 	if (mkfault)
50 		return;
51 	switch (c) {
52 
53 	case 0:
54 		return;
55 
56 	case '\n':
57 		sendout();
58 		return;
59 
60 	default:
61 		if (isprint(c))
62 			*printptr++ = c;
63 		break;
64 	}
65 	if (printptr >= &printbuf[LINELEN - 1])	/* 1 == space for \n */
66 		sendout();
67 }
68 
69 /*
70  * Send (write) out the contents of the print buffer, compressing
71  * spaces into tabs.
72  */
73 static
74 sendout()
75 {
76 	register char *p, *q;
77 	register int c, off = 0, spaces = 0, s;
78 #define	tabsize(x) (8 - ((x) & 7))
79 
80 	for (q = p = printbuf; p < printptr;) {
81 		c = *p++;
82 		switch (c) {
83 
84 		case ' ':
85 			spaces++;
86 			break;
87 
88 		case '\t':
89 			spaces += tabsize(off + spaces);
90 			break;
91 
92 		default:
93 			s = tabsize(off);
94 			off += spaces + 1;
95 			while (spaces >= s) {
96 				*q++ = '\t';
97 				spaces -= s;
98 				s = 8;
99 			}
100 			while (--spaces >= 0)
101 				*q++ = ' ';
102 			spaces = 0;
103 			*q++ = c;
104 		}
105 	}
106 	*q++ = '\n';
107 	(void) write(outfile, printbuf, q - printbuf);
108 	printptr = printbuf;
109 #undef tabsize
110 }
111 
112 charpos()
113 {
114 
115 	return (printptr - printbuf);
116 }
117 
118 endline()
119 {
120 
121 	if (printptr - printbuf >= maxcol)
122 		printc('\n');
123 }
124 
125 flushbuf()
126 {
127 
128 	if (printptr != printbuf)
129 		sendout();
130 }
131 
132 /* this should not be necessary! */
133 #ifdef lint
134 #undef va_arg
135 #define va_arg(ap, type) (ap = ap, (type)0)
136 #endif
137 
138 /*
139  * Context passed between adbprintf and decodefmt.
140  */
141 struct prf {
142 	char	*fmt;		/* format pointer */
143 	va_list	ap;		/* argument pointer */
144 	char	*buf;		/* digit buffer, or %s string */
145 	int	adj;		/* 'l'eft (-) or 'r'ight adjustment */
146 	int	width;		/* width from format */
147 	int	prec;		/* precision from format */
148 };
149 
150 /*
151  * adb's very own version of printf() ... of course, all the format
152  * escapes are different.  Noteworthy are the %<width>m and %<tabstop>t
153  * formats, which move the given width, or to the given tabstop, and
154  * the %?a format, which evaluates one argument, and if not zero, prints
155  * according to format a.  (Note that any modifiers must appear in the
156  * `a' part, not in the %? part.)
157  */
158 /* VARARGS1 */
159 adbprintf(fmt, va_alist)
160 	char *fmt;
161 	va_dcl
162 {
163 	register char *s;
164 	register int n, c;
165 	struct prf prf;
166 	char digits[130];	/* good to at least 128 bit expr_t */
167 
168 	/* set up the fields adbprf needs */
169 	prf.fmt = fmt;
170 	va_start(prf.ap);
171 	for (;;) {
172 		/* look for % conversions */
173 		s = prf.fmt;
174 		while ((c = *s++) != '%') {
175 			if (c == 0)
176 				return;
177 			printc(c);
178 		}
179 		prf.fmt = s;
180 		prf.buf = digits;
181 		dofmt(&prf);		/* format one format */
182 		n = strlen(s = prf.buf);
183 		if (prf.prec >= 0 && n > prf.prec)
184 			n = prf.prec;
185 		c = prf.width - n;
186 		if (prf.adj == 'r')
187 			while (--c >= 0)
188 				printc(' ');
189 		while (--n >= 0)
190 			printc(*s++);
191 		while (--c >= 0)
192 			printc(' ');
193 	}
194 	va_end(prf.ap);
195 }
196 
197 /*
198  * Do a single format.
199  */
200 static
201 dofmt(prf)
202 	register struct prf *prf;
203 {
204 	register char *s = prf->fmt;
205 	register va_list ap = prf->ap;
206 	register int c, n;
207 	expr_t v;
208 	int pluspref = 0;
209 	static char null[] = "";
210 
211 	prf->adj = 'r';
212 	prf->width = 0;
213 	prf->prec = -1;
214 more:
215 	c = *s++;
216 sw:
217 	switch (c) {
218 
219 	case '-':
220 		prf->adj = 'l';
221 		goto more;
222 
223 	case '+':
224 		pluspref = 1;
225 		goto more;
226 
227 	case '*':
228 		prf->width = va_arg(ap, int);
229 		goto more;
230 
231 	case '0': case '1': case '2': case '3': case '4':
232 	case '5': case '6': case '7': case '8': case '9':
233 		for (n = c - '0'; isdigit(c = *s++);)
234 			n = 10 * n + c - '0';
235 		prf->width = n;
236 		goto sw;
237 
238 	case '.':
239 		c = *s++;
240 		if (c == '*') {
241 			prf->prec = va_arg(ap, int);
242 			goto more;
243 		}
244 		for (n = 0; isdigit(c); c = *s++)
245 			n = 10 * n + c - '0';
246 		prf->prec = n;
247 		goto sw;
248 
249 	case 'v': case 'V':
250 		/* print in signed version of current radix */
251 		if ((n = radix) > 0)
252 			n = -n;
253 		goto rprint;
254 
255 	case 'q': case 'Q': n =  -8; goto rprint; /* octal */
256 	case 'd': case 'D': n = -10; goto rprint; /* decimal */
257 	case 'z': case 'Z': n = -16; goto rprint; /* hex */
258 	case 'o': case 'O': n =   8; goto rprint; /* and */
259 	case 'u': case 'U': n =  10; goto rprint; /* unsigned */
260 	case 'x': case 'X': n =  16; goto rprint; /* versions */
261 
262 	case 'r': case 'R':
263 		n = radix;
264 rprint:
265 		if (isupper(c))
266 			v = n < 0 ? SF_ARG : UF_ARG;
267 		else
268 			v = n < 0 ? SH_ARG : UH_ARG;
269 		printradix(prf->buf, v, n, pluspref);
270 		break;
271 
272 	case 'Y':
273 		printdate(prf->buf, va_arg(ap, time_t));
274 		break;
275 
276 	case 'c':
277 		*prf->buf = va_arg(ap, int);
278 		prf->buf[1] = 0;
279 		break;
280 
281 	case 's':
282 		prf->buf = va_arg(ap, char *);
283 		break;
284 
285 	case 'f':
286 		/* here comes stdio ... sigh */
287 		(void) sprintf(prf->buf, "%+*.*e", prf->width,
288 		    prf->prec >= 0 ? prf->prec : 16, va_arg(ap, double));
289 		prf->prec = -1;
290 		break;
291 
292 	case 'm':
293 		prf->buf = null;
294 		break;
295 
296 	case 't':
297 		if (prf->width)
298 			prf->width -= charpos() % prf->width;
299 		prf->buf = null;
300 		break;
301 
302 	case '?':
303 		c = va_arg(ap, int);
304 		prf->fmt = s;
305 		prf->ap = ap;
306 		dofmt(prf);
307 		if (c == 0)
308 			prf->buf = null;
309 		return;
310 
311 	default:
312 		panic("dofmt");
313 		/* NOTREACHED */
314 	}
315 	prf->fmt = s;
316 	prf->ap = ap;
317 }
318 
319 /*
320  * Print the date into the buffer at `p'.
321  */
322 static
323 printdate(p, tm)
324 	register char *p;
325 	time_t tm;
326 {
327 	char *asc = ctime(&tm);
328 	char *strncpy();
329 
330 	(void) strncpy(p, asc + 20, 4);		/* "1988" */
331 	(void) strncpy(p + 4, asc + 3, 16);	/* " Aug 18 03:04:49" */
332 	p[20] = 0;
333 }
334 
335 /*
336  * Print the value `val' in base `base' into the buffer at `p'.
337  * If base is negative, assume the number is signed.
338  */
339 static
340 printradix(p, val, base, pluspref)
341 	register char *p;
342 	register expr_t val;
343 	register int base;
344 	int pluspref;
345 {
346 	register char *d;
347 	register expr_t high;
348 	char digs[128];		/* good to 128 bits minimum */
349 
350 	if (base < 0) {
351 		base = -base;
352 		if ((sexpr_t)val < 0) {
353 			val = -val;
354 			*p++ = '-';
355 		} else if (pluspref)
356 			*p++ = '+';
357 	} else if (pluspref)
358 		*p++ = '+';
359 
360 	d = digs;
361 	switch (base) {
362 
363 	case 8:
364 		while (val != 0) {
365 			*d++ = val & 7;
366 			val >>= 3;
367 		}
368 		*d++ = 0;
369 		break;
370 
371 	case 16:
372 		do {
373 			*d++ = val & 15;
374 		} while ((val >>= 4) != 0);
375 		break;
376 
377 	default:
378 		do {
379 			high = val / base;
380 			*d++ = val - (high * base);
381 		} while ((val = high) != 0);
382 		break;
383 	}
384 	while (d > digs)
385 		*p++ = "0123456789abcdef"[*--d];
386 	*p = 0;
387 }
388 
389 /*
390  * BEGIN XXX
391  * THIS BELONGS ELSEWHERE
392  */
393 #define	MAXIFD	5
394 struct {
395 	int fd;
396 	expr_t v9;
397 } istack[MAXIFD];
398 int ifiledepth;
399 
400 iclose(stack, err)
401 	int stack, err;
402 {
403 
404 	if (err) {
405 		if (infile) {
406 			(void) close(infile);
407 			infile = 0;
408 		}
409 		while (--ifiledepth >= 0)
410 			if (istack[ifiledepth].fd)
411 				(void) close(istack[ifiledepth].fd);
412 		ifiledepth = 0;
413 	} else if (stack == 0) {
414 		if (infile) {
415 			(void) close(infile);
416 			infile = 0;
417 		}
418 	} else if (stack > 0) {
419 		if (ifiledepth >= MAXIFD)
420 			error(TOODEEP);
421 		istack[ifiledepth].fd = infile;
422 		istack[ifiledepth].v9 = var[9];
423 		ifiledepth++;
424 		infile = 0;
425 	} else {
426 		if (infile) {
427 			(void) close(infile);
428 			infile = 0;
429 		}
430 		if (ifiledepth > 0) {
431 			infile = istack[--ifiledepth].fd;
432 			var[9] = istack[ifiledepth].v9;
433 		}
434 	}
435 }
436 
437 oclose()
438 {
439 
440 	if (outfile != 1) {
441 		flushbuf();
442 		(void) close(outfile);
443 		outfile = 1;
444 	}
445 }
446