.Xr botch fix
[unix-history] / usr / src / old / adb / common_source / output.c
CommitLineData
f582ecdc
KB
1#ifndef lint
2static char sccsid[] = "@(#)output.c 5.1 (Berkeley) %G%";
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
14extern char TOODEEP[];
15
16int infile;
17int outfile = 1;
18
19char printbuf[LINELEN];
20char *printptr = printbuf;
21
22
23/*
24 * Print the string s.
25 */
26prints(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 */
38printc(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 */
66static
67sendout()
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
105charpos()
106{
107
108 return (printptr - printbuf);
109}
110
111endline()
112{
113
114 if (printptr - printbuf >= maxcol)
115 printc('\n');
116}
117
118flushbuf()
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 */
134struct 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 */
152adbprintf(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 */
193static
194dofmt(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;
207more:
208 c = *s++;
209sw:
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;
257rprint:
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 */
315static
316printdate(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 */
332static
333printradix(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
387struct {
388 int fd;
389 expr_t v9;
390} istack[MAXIFD];
391int ifiledepth;
392
393iclose(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
430oclose()
431{
432
433 if (outfile != 1) {
434 flushbuf();
435 (void) close(outfile);
436 outfile = 1;
437 }
438}