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