/* $Header:output.c 12.0$ */
/* $ACIS:output.c 12.0$ */
/* $Source: /ibm/acis/usr/src/bin/adb_ca/RCS/output.c,v $ */

#ifndef lint
static char *rcsid = "$Header:output.c 12.0$";
#endif

/*
 *
 *      UNIX debugger
 *
 */
#include "defs.h"
#include <stdio.h>
INT             mkfault;
INT             infile;
INT             outfile = 1;
L_INT           maxpos;
L_INT           maxoff;
INT             radix = 16;
CHAR            printbuf[MAXLIN];
CHAR            *printptr = printbuf;
CHAR            *digitptr;
MSG             TOODEEP;
eqstr(s1, s2)
        REG STRING      s1, s2;
{
        REG STRING       es1;
        WHILE *s1++ == *s2
        DO IF *s2++ == 0
           THEN return(1);
           FI
        OD
        return(0);
}
length(s)
        REG STRING              s;
{
        INT             n = 0;
        WHILE *s++ DO n++; OD
        return(n);
}
printc(c)
        CHAR            c;
{
        CHAR            d;
        STRING          q;
        INT             posn, tabs, p;
        IF mkfault
        THEN    return;
        ELIF (*printptr=c)==EOR
        THEN tabs=0; posn=0; q=printbuf;
             FOR p=0; p<printptr-printbuf; p++
             DO d=printbuf[p];
                IF (p&7)==0 ANDF posn
                THEN tabs++; posn=0;
                FI
                IF d==SP
                THEN posn++;
                ELSE WHILE tabs>0 DO *q++=TB; tabs--; OD
                     WHILE posn>0 DO *q++=SP; posn--; OD
                     *q++=d;
                FI
             OD
             *q++=EOR;
#ifdef EDDT
	     printptr=printbuf; do putchar(*printptr++); while (printptr<q);
#else
             write(outfile,printbuf,q-printbuf);
#endif
             printptr=printbuf;
        ELIF c==TB
        THEN *printptr++=SP;
             WHILE (printptr-printbuf)&7 DO *printptr++=SP; OD
        ELIF c
        THEN printptr++;
        FI
        IF printptr >= &printbuf[MAXLIN-9] THEN
                write(outfile, printbuf, printptr - printbuf);
                printptr = printbuf;
        FI
}
charpos()
{       return(printptr-printbuf);
}
flushbuf()
{       IF printptr!=printbuf
        THEN printc(EOR);
        FI
}
printf(fmat,a1,a2,a3)
        STRING          fmat;
        STRING          *a1,*a2,*a3;
{
        STRING          fptr, s;
        L_INT           *dptr;
        L_REAL          *rptr;
        INT             width, prec;
        CHAR            c, adj;
        INT             x, decpt, n;
        L_INT           lx;
        CHAR            digits[64];
        fptr = fmat; dptr = (L_INT *)&a1;
        WHILE c = *fptr++
        DO  IF c!='%'
            THEN printc(c);
            ELSE IF *fptr=='-'
                 THEN adj='l'; fptr++;
                 ELSE adj='r';
                 FI
                 width=convert(&fptr);
                 IF *fptr=='.'
                 THEN fptr++; prec=convert(&fptr);
                 ELSE prec = -1;
                 FI
                 digitptr=digits;
                 rptr=(L_REAL *)dptr;
                 x = lx = (L_INT)*dptr++;
                 s=0;
                 switch (c = *fptr++) {
                    case 'd':
                    case 'u':
                        printnum(x,c,10); break;
                    case 'o':
			sprintf(s=digits, "%#o", lx); break;
                    case 'q':
                        lx=x; printoct(lx,-1); break;
                    case 'x':
			sprintf(s=digits, "%#06x", lx); break;
                    case 'r':
                        printdbl(lx=x,c,radix); break;
                    case 'R':
                        printdbl(lx,c,radix); break;
                    case 'Y':
                        printdate(lx); break;
                    case 'D':
			sprintf(s=digits, "%d", lx); break;
                    case 'U':
			sprintf(s=digits, "%u", lx); break;
                    case 'O':
                        printoct(lx,0); break;
                    case 'Q':
                        printoct(lx,-1); break;
                    case 'X':
			sprintf(s=digits, "%#10.8x", lx); break;
                    case 'c':
                        printc( (x>127 || x<32) ? '_' : x ); break;
                    case 's':
                        s=(STRING)lx; break;
                    case 'f':
                        dptr++;
                        sprintf(s=digits,"%.9g",*rptr);
                        prec= -1;
                        break;
                    case 'F':
                        dptr++;
                        sprintf(s=digits,"%.17g",*rptr);
                        prec= -1;
                        break;
                    case 'm':
                        break;
                    case 'M':
                        width=x; break;
                    case 'T':
                    case 't':
                        IF c=='T'
                        THEN width=x;
                        ELSE dptr--;
                        FI
                        IF width
                        THEN width -= charpos()%width;
                        FI
                        break;
                    default:
                        printc(c); dptr--;
                }
                IF s==0
                THEN *digitptr=0; s=digits;
                FI
                n=length(s);
                n=(prec<n ANDF prec>=0 ? prec : n);
                width -= n;
                IF adj=='r'
                THEN WHILE width-- > 0
                     DO printc(SP); OD
                FI
                WHILE n-- DO printc(*s++); OD
                WHILE width-- > 0 DO printc(SP); OD
                digitptr=digits;
            FI
        OD
}
 
printdate(tvec)
        L_INT           tvec;
{
        REG INT         i;
        REG STRING      timeptr;
#ifndef EDDT
        timeptr = ctime(&tvec);
#else
        timeptr="????????????????????????";
#endif
        FOR i=20; i<24; i++ DO *digitptr++ = *(timeptr+i); OD
        FOR i=3; i<19; i++ DO *digitptr++ = *(timeptr+i); OD
}
 
prints(s)
        char *s;
{
        printf("%s",s);
}
 
newline()
{
        printc(EOR);
}
 
convert(cp)
        REG STRING      *cp;
{
        REG CHAR        c;
        INT             n = 0;
 
        WHILE ((c = *(*cp)++)>='0') ANDF (c<='9') DO n=n*10+c-'0'; OD
        (*cp)--;
        return(n);
}
 
printnum(n,fmat,base)
        REG INT         n;
{
        REG CHAR        k;
        REG INT         *dptr;
        INT             digs[15];
 
        dptr=digs;
        IF n<0 ANDF fmat=='d' THEN n = -n; *digitptr++ = '-'; FI
        n &= 0xffff;
        WHILE n
        DO  *dptr++ = ((POS)(n&0xffff))%base;
            n=((POS)(n&0xffff))/base;
        OD
        IF dptr==digs THEN *dptr++=0; FI
        WHILE dptr!=digs
        DO  k = *--dptr;
            *digitptr++ = (k+(k<=9 ? '0' : 'a'-10));
        OD
}
 
printoct(o,s)
        L_INT           o;
        INT             s;
{
        INT             i;
        L_INT           po = o;
        CHAR            digs[12];
 
        IF s
        THEN IF po<0
             THEN po = -po; *digitptr++='-';
             ELSE IF s>0 THEN *digitptr++='+'; FI
             FI
        FI
        FOR i=0;i<=11;i++
        DO digs[i] = po&7; po >>= 3; OD
        digs[10] &= 03; digs[11]=0;
        FOR i=11;i>=0;i--
        DO IF digs[i] THEN break; FI OD
        FOR i++;i>=0;i--
        DO *digitptr++=digs[i]+'0'; OD
}
 
printdbl(lxy,fmat,base)
        L_INT lxy;
        char fmat;
        int base;
{
        int digs[20];
        int *dptr;
        char k;
 
        register char *cp1 = (char *) digs;
        if( (lxy&0xFFFF0000L) == 0xFFFF0000L ){
                *cp1++='-';
                lxy= -lxy;
        }
        sprintf( cp1, (base==16 ? "%#x" : "%D"), lxy );
        FOR cp1 = (char *)digs; *digitptr++ = *cp1++; DO OD
        --digitptr;
}
 
#define MAXIFD  5
struct {
        int     fd;
        int     r9;
} istack[MAXIFD];
int     ifiledepth;
 
iclose(stack, err)
{
        IF err
        THEN    IF infile
                THEN    close(infile); infile=0;
                FI
                WHILE --ifiledepth >= 0
                DO      IF istack[ifiledepth].fd
                        THEN    close(istack[ifiledepth].fd);
                        FI
                OD
                ifiledepth = 0;
        ELIF stack == 0
        THEN    IF infile
                THEN    close(infile); infile=0;
                FI
        ELIF stack > 0
        THEN    IF ifiledepth >= MAXIFD
                THEN    error(TOODEEP);
                FI
                istack[ifiledepth].fd = infile;
                istack[ifiledepth].r9 = var[9];
                ifiledepth++;
                infile = 0;
        ELSE    IF infile
                THEN    close(infile); infile=0;
                FI
                IF ifiledepth > 0
                THEN    infile = istack[--ifiledepth].fd;
                        var[9] = istack[ifiledepth].r9;
                FI
        FI
}
 
oclose()
{
        IF outfile!=1
        THEN    flushbuf(); close(outfile); outfile=1;
        FI
}
 
endline()
{
        if (maxpos <= charpos())
                printf("\n");
}
/* Convert 3-word integer array representing an 881 extended-precision no.
 * to decimal representation, and return the string.  L. M. Breed  10/87
 */
#include <math.h>
#include <ieee.h>

static int xd1[2] = {0x41300000,0};
static int xd2[2] = {0x3f300000,0};

static char xtod_result[30];

char *
xtod(unsigned int xw[3])
{
	unsigned int t[2];
	int b,n;
	double d1,d2;
	double g1,g2;
	double f;
	char * rp = xtod_result;

/*	if (xw[0]&0xffff) printf("Word 1 low 16 bits should be 0.\n"); */
	*rp++ = (xw[0]>>31) ? '-' : ' ';
	if ((xw[0]&0x7fff0000) == 0x7fff0000) {
	    if (xw[1]|xw[2]) strcpy(rp,"NaN()");
	    else strcpy(rp,"INF");
	    return xtod_result;
	}
	if (0 == (xw[1]|xw[2])) {
	    strcpy(rp,"0.0");
	    return xtod_result;
	}
	t[0]=xd1[0];
	t[1]=xw[1];
	d1 = *(double *)t - *(double *)xd1;
	t[0]=xd2[0];
	t[1]=xw[2];
	d2 = *(double *)t - *(double *)xd2;

	b = ((xw[0] >> 16) & 0x7fff) - 0x3ffe;
     /* All normal double numbers get converted right here
      * with no tumult or shouting. 
      */
	if (b>= -1023 && b<= 1024) {
	    g1 = scalb(d1,b) + scalb(d2,b);
	    if (g1 != g1+g1) {
			/* There's a slight chance that g1 might have
			 * overflowed to infinity or underflowed to 0;
			 */
		sprintf(rp,"%.17g",g1);
		return xtod_result;
	    }
	}
	n = rint(b/3.32192809488736234789);
	f = exp(0.69314718055994530941*drem((double)b,3.32192809488736234789));
	g1 = d1*f;
	g2 = d2*f;
	while (g1+g2<1.0) {
	    g1 *= 10;
	    g2 *= 10;
	    n--;
	}
	    /* Use g format here to get round to roundest; rely on
	       1<=x<10 to prevent g format from printing an exponent.
	    */
	sprintf(rp,"%.17ge+%d",g1+g2,n);
	return xtod_result;
}
