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

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

/*
 *
 *      UNIX debugger
 *
 */
#include "defs.h"
MSG             BADMOD;
MSG             NOFORK;
MSG             ADWRAP;
INT             mkfault;
CHAR            *lp;
L_INT           maxoff;
ADDR            sigint;
ADDR            sigqit;
STRING          errflg;
CHAR            lastc,peekc;
L_INT           dot;
INT             dotinc;
L_INT           expv;
L_INT           var[];
STRING          fphack;
rdfp()
{
        return(lastc= *fphack++);
}
scanform(icount,ifp,itype,ptype)
L_INT           icount;
STRING          ifp;
{
        STRING          fp;
        CHAR            modifier;
        INT             fcount, init=1;
        L_INT           savdot;
        BOOL exact;
        BOOL doit = 1;
        WHILE icount
        DO  fp=ifp;
            savdot=dot; init=0;
            /*now loop over format*/
            WHILE *fp ANDF errflg==0
            DO  IF digit(modifier = *fp)
                THEN fcount = 0;
                        WHILE digit(modifier = *fp++)
                        DO fcount *= 10;
                           fcount += modifier-'0';
                        OD
                        fp--;
                ELSE fcount = 1;
                FI
                IF *fp==0 THEN break; FI
                fp=exform(fcount,fp,itype,ptype);
            OD
            dotinc=dot-savdot;
            dot=savdot;
            IF errflg
            THEN IF icount<0
                 THEN errflg=0; break;
                 ELSE error(errflg);
                 FI
            FI
            IF --icount
            THEN dot=inkdot(dotinc);
            FI
            IF mkfault THEN error(0); FI
        OD
}
STRING
exform(fcount,ifp,itype,ptype)
INT             fcount;
STRING          ifp;
{
        /* execute single format item `fcount' times
         * sets `dotinc' and moves `dot'
         * returns address of next format item
         */
        POS             w;
        L_INT           savdot, wx;
        STRING          fp;
        CHAR            c, modifier, longpr, wb;
 
        union{  /* changed for clean compile JEC */
                L_REAL  u_fw;
                struct{
                        L_INT   sa;
                        INT     sb, sc;
                } u_s;
        } u_lreal;
#define fw u_lreal.u_fw
#define fw_sa u_lreal.u_s.sa
#define fw_sb u_lreal.u_s.sb
#define fw_sc u_lreal.u_s.sc
 
	if(ifp[0] == 'i' && ifp[1] == 'a' && ifp[2] == '\0') { /* XXX */
		ifp[0] = 'a';	/* Force similar output for ?ai and ?ia */
		ifp[1] = 'i';
	}
        WHILE fcount>0
        DO      fp = ifp; c = *fp;
                longpr=(c>='A')&(c<='Z')|(c=='f')|(c=='4')|(c=='p');
                IF itype==NSP ORF *fp=='a'
                THEN wb = w = wx = dot;
                ELSE wx = get(dot,itype);
                     w  = ((unsigned) wx) >> 16;
                     wb = ((unsigned) wx) >> 24;
                FI
                IF c=='F'
                THEN fw_sb=get(inkdot(4),itype);
		     fw_sc = get(inkdot(4), itype);
                FI
                IF errflg THEN return(fp); FI
                IF mkfault THEN error(0); FI
                var[0]=wx;
                modifier = *fp++;
                dotinc=(longpr?4:2);;
                IF charpos()==0 ANDF modifier!='a' ANDF modifier!='i' THEN printf("%16m"); FI
                switch(modifier) {
                    case SP: case TB:
                        break;
                    case 't': case 'T':
                        printf("%T",fcount); return(fp);
                    case 'r': case 'R':
                        printf("%M",fcount); return(fp);
                    case 'a':
                        psymoff(dot,ptype,":%16t"); dotinc=0; break;
                    case 'p':
                        psymoff(var[0],ptype,"%16t"); break;
                    case 'u':
                        printf("%-16u",w); break;
                    case 'U':
                        printf("%-16U",wx); break;
                    case 'c':
                        printc( (wb>127 || wb<32) ? '_' : wb );
                        dotinc=1; break;
                    case 'C':
                        printesc(wb); dotinc=1; break;
                    case 'b': case 'B':
                        printf( "%-8o", wb ); dotinc=1; break;
                    case '1':
                        printf("%-8r", wb ); dotinc=1; break;
                    case '2':
                    case 'w':
                        printf("%-16r", w); break;
                    case '4':
                    case 'W':
                        printf("%-16R", wx); break;
                    case 's': case 'S':
                        savdot=dot; dotinc=1;
                        WHILE (c=ONEBYTE(get(dot,itype))) ANDF errflg==0
                        DO dot=inkdot(1);
                           IF modifier == 'S'
                           THEN printesc(c);
                           ELSE printc(c);
                           FI
                           endline();
                        OD
                        dotinc=dot-savdot+1; dot=savdot; break;
                    case 'x':
                        printf("%-16x", w); break;
                    case 'X':
                        printf("%-16X", wx); break;
                    case 'Y':
                        printf("%-24Y", wx); break;
                    case 'q':
                        printf("%-16q", w); break;
                    case 'Q':
                        printf("%-16Q", wx); break;
                    case 'o':
                        printf("%-16o", w); break;
                    case 'O':
                        printf("%-16O", wx); break;
                    case 'i':
                        printins(dot,wx); printc(EOR); break;
                    case 'd':
                        printf("%-16d", w); break;
                    case 'D':
                        printf("%-16D", wx); break;
                    case 'f':
			{
			float x;
                        x = *((float *) &wx);
                        printf("%-32.18F", x);
                        dotinc=4; break;
			}
                    case 'F':
                        fw_sa = wx;
                        printf("%-32.18F", fw);
                        dotinc=8; break;
                    case 'n': case 'N':
                        printc('\n'); dotinc=0; break;
                    case '"':
                        dotinc=0;
                        WHILE *fp != '"' ANDF *fp
                        DO printc(*fp++); OD
                        IF *fp THEN fp++; FI
                        break;
                    case '^':
                        dot=inkdot(-dotinc*fcount); return(fp);
                    case '+':
                        dot=inkdot(fcount); return(fp);
                    case '-':
                        dot=inkdot(-fcount); return(fp);
                    default: error(BADMOD);
                }
                IF itype!=NSP
                THEN    dot=inkdot(dotinc);
                FI
                fcount--; endline();
        OD
        return(fp);
}
shell()
{
#ifndef EDDT
        INT             rc, status, unixpid;
        STRING          argp = lp;
        STRING          getenv(), shell = getenv("SHELL");
#ifdef VFORK
        char            oldstlp;
#endif
        if (shell == 0)
                shell = "/bin/sh";
        WHILE lastc!=EOR DO rdc(); OD
#ifndef VFORK
        IF (unixpid=fork())==0
#else
        oldstlp = *lp;
        IF (unixpid=vfork())==0
#endif
        THEN    signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
                *lp=0; execl(shell, "sh", "-c", argp, 0);
                _exit(16);
#ifndef VFORK
        ELIF unixpid == -1
#else
        ELIF *lp = oldstlp, unixpid == -1
#endif
        THEN    error(NOFORK);
        ELSE    signal(SIGINT,1);
                WHILE (rc = wait(&status)) != unixpid ANDF rc != -1 DONE
                signal(SIGINT,sigint);
                prints("!"); lp--;
        FI
#endif
}
printesc(c)
{
        c &= STRIP;
        IF c==0177 THEN printf("~?");
        ELIF c<SP
        THEN printf("~%c", c + '@');
        ELSE printc(c);
        FI
}
L_INT   inkdot(incr)
{
        L_INT           newdot;
        newdot = dot + incr;
        IF (dot NEQ newdot) >> 24 THEN error(ADWRAP); FI
        return(newdot);
}
digit(c)
{
        return c >= '0' && c <= '9';
}
