V8/usr/src/libI77/wrtfmt.c
/* @(#)wrtfmt.c 1.3 */
/* 3.0 SID # 1.2 */
#include "fio.h"
#include "fmt.h"
extern int cursor;
extern char *icvt(), *ecvt();
int hiwater;
icilist *svic;
char *icptr;
mv_cur() /* shouldn't use fseek because it insists on calling fflush */
/* instead we know too much about stdio */
{
if(external == 0) {
if(cursor < 0) {
if(hiwater < recpos)
hiwater = recpos;
recpos += cursor;
icptr += cursor;
cursor = 0;
if(recpos < 0)
err(elist->cierr, 110, "left off");
}
else if(cursor > 0) {
if(recpos + cursor >= svic->icirlen)
err(elist->cierr, 110, "recend");
if(hiwater <= recpos)
for(; cursor > 0; cursor--)
(*putn)(' ');
else if(hiwater <= recpos + cursor) {
cursor -= hiwater - recpos;
icptr += hiwater - recpos;
recpos = hiwater;
for(; cursor > 0; cursor--)
(*putn)(' ');
}
else {
icptr += cursor;
recpos += cursor;
}
cursor = 0;
}
return(0);
}
if(cursor > 0) {
if(hiwater <= recpos)
for(;cursor>0;cursor--) (*putn)(' ');
else if(hiwater <= recpos + cursor) {
if(cf->_ptr + hiwater - recpos < _bufend(cf))
cf->_ptr += hiwater - recpos;
else
(void) fseek(cf, (long) (hiwater - recpos), 1);
cursor -= hiwater - recpos;
recpos = hiwater;
for(; cursor > 0; cursor--)
(*putn)(' ');
}
else {
if(cf->_ptr + cursor < _bufend(cf))
cf->_ptr += cursor;
else
(void) fseek(cf, (long)cursor, 1);
recpos += cursor;
}
}
if(cursor<0)
{
if(cursor+recpos<0) err(elist->cierr,110,"left off");
if(cf->_ptr + cursor >= cf->_base)
cf->_ptr += cursor;
else if(curunit->useek) (void) fseek(cf,(long)cursor,1);
else err(elist->cierr,106,"fmt");
if(hiwater < recpos)
hiwater = recpos;
recpos += cursor;
cursor=0;
}
return(0);
}
w_ed(p,ptr,len) char *ptr; struct syl *p; ftnlen len;
{
if(cursor && mv_cur()) return(mv_cur());
switch(p->op)
{
default:
fprintf(stderr,"w_ed, unexpected code: %d\n%s\n",
p->op,fmtbuf);
abort();
case I: return(wrt_I((uint *)ptr,p->p1,len, 10));
case IM:
return(wrt_IM((uint *)ptr,p->p1,p->p2,len));
case O: return(wrt_I((uint *)ptr, p->p1, len, 8));
case L: return(wrt_L((uint *)ptr,p->p1, len));
case A: return(wrt_A(ptr,len));
case AW:
return(wrt_AW(ptr,p->p1,len));
case D:
case E:
case EE:
return(wrt_E((ufloat *)ptr,p->p1,p->p2,p->p3,len));
case G:
case GE:
return(wrt_G((ufloat *)ptr,p->p1,p->p2,p->p3,len));
case F: return(wrt_F((ufloat *)ptr,p->p1,p->p2,len));
}
}
w_ned(p) struct syl *p;
{
switch(p->op)
{
default: fprintf(stderr,"w_ned, unexpected code: %d\n%s\n",
p->op,fmtbuf);
abort();
case SLASH:
return((*donewrec)());
case T: cursor = p->p1-recpos - 1;
return(1);
case TL: cursor -= p->p1;
if(cursor < -recpos) /* TL1000, 1X */
cursor = -recpos;
return(1);
case TR:
case X:
cursor += p->p1;
return(1);
case APOS:
return(wrt_AP(p->p1));
case H:
return(wrt_H(p->p1,p->p2));
}
}
wrt_I(n,w,len, base) uint *n; ftnlen len; register int base;
{ int ndigit,sign,spare,i;
long x;
char *ans;
if(len==sizeof(short)) x=n->is;
else if(len == sizeof(char)) x = n->ic;
else x=n->il;
ans=icvt(x,&ndigit,&sign, base);
spare=w-ndigit;
if(sign || cplus) spare--;
if(spare<0)
for(i=0;i<w;i++) (*putn)('*');
else
{ for(i=0;i<spare;i++) (*putn)(' ');
if(sign) (*putn)('-');
else if(cplus) (*putn)('+');
for(i=0;i<ndigit;i++) (*putn)(*ans++);
}
return(0);
}
wrt_IM(n,w,m,len) uint *n; ftnlen len;
{ int ndigit,sign,spare,i,xsign;
long x;
char *ans;
if(sizeof(short)==len) x=n->is;
else if(len == sizeof(char)) x = n->ic;
else x=n->il;
ans=icvt(x,&ndigit,&sign, 10);
if(sign || cplus) xsign=1;
else xsign=0;
if(ndigit+xsign>w || m+xsign>w)
{ for(i=0;i<w;i++) (*putn)('*');
return(0);
}
if(x==0 && m==0)
{ for(i=0;i<w;i++) (*putn)(' ');
return(0);
}
if(ndigit>=m)
spare=w-ndigit-xsign;
else
spare=w-m-xsign;
for(i=0;i<spare;i++) (*putn)(' ');
if(sign) (*putn)('-');
else if(cplus) (*putn)('+');
for(i=0;i<m-ndigit;i++) (*putn)('0');
for(i=0;i<ndigit;i++) (*putn)(*ans++);
return(0);
}
wrt_AP(n)
{ char *s,quote;
if(cursor && mv_cur()) return(mv_cur());
s=(char *)n;
quote = *s++;
for(;*s;s++)
{ if(*s!=quote) (*putn)(*s);
else if(*++s==quote) (*putn)(*s);
else return(1);
}
return(1);
}
wrt_H(a,b)
{ char *s=(char *)b;
if(cursor && mv_cur()) return(mv_cur());
while(a--) (*putn)(*s++);
return(1);
}
wrt_L(n,len, sz) uint *n; ftnlen sz;
{ int i;
long x;
if(sizeof(short)==sz) x=n->is;
else if(sz == sizeof(char)) x = n->ic;
else x=n->il;
for(i=0;i<len-1;i++)
(*putn)(' ');
if(x) (*putn)('t');
else (*putn)('f');
return(0);
}
wrt_A(p,len) char *p; ftnlen len;
{
while(len-- > 0) (*putn)(*p++);
return(0);
}
wrt_AW(p,w,len) char * p; ftnlen len;
{
while(w>len)
{ w--;
(*putn)(' ');
}
while(w-- > 0)
(*putn)(*p++);
return(0);
}
wrt_E(p,w,d,e,len) ufloat *p; ftnlen len;
{ char *s;
int dp,sign,i, delta;
char *ecvt();
double dd;
if(e == 0)
e = 2;
if(scale) {
if(scale >= d + 2 || scale <= -d)
goto nogood;
if(scale > 0)
d++;
}
if (len == sizeof(float))
dd = p->pf;
else
dd = p->pd;
s=ecvt( dd ,d,&dp,&sign);
delta = 1 /* for the . */ + 2 /* for the E+ */ + (sign || cplus);
if(w < d + e + delta) {
nogood:
for(i=0;i<w;i++) (*putn)('*');
return(0);
}
if(p->pf != 0) dp -= scale;
else dp = 0;
switch(e) { /* grumph */
case 1:
if(dp <= -10 || dp >= 10)
goto nogood;
break;
case 2:
if(dp <= -100 || dp >= 100)
goto nogood;
break;
case 3:
if(dp <= -1000 || dp >= 1000)
goto nogood;
break;
default:
/* probably ok */
break;
}
for(i=0;i<w-(delta+d+e);i++) (*putn)(' ');
if(sign) (*putn)('-');
else if(cplus) (*putn)('+');
if(scale<0)
{
(*putn)('.');
for(i=0;i<-scale;i++)
(*putn)('0');
for(i=0;i<d+scale;i++)
(*putn)(*s++);
}
else if(scale>0 && scale<d+2)
{ for(i=0;i<scale;i++)
(*putn)(*s++);
(*putn)('.');
for(i=0;i<d-scale;i++)
(*putn)(*s++);
}
else
{ (*putn)('.');
for(i=0;i<d;i++) (*putn)(*s++);
}
if(dp < 100 && dp > -100) (*putn)('e');
if(dp<0)
{ (*putn)('-');
dp = -dp;
}
else (*putn)('+');
for(; e >= 4; e--)
(*putn)('0');
if(e>=3 || dp >= 100)
{ (*putn)(dp/100 + '0');
dp = dp % 100;
}
if(e!=1) (*putn)(dp/10+'0');
(*putn)(dp%10+'0');
return(0);
}
wrt_G(p,w,d,e,len) ufloat *p; ftnlen len;
{ double up = 1,x;
int i,oldscale=scale,n,j;
x= len==sizeof(float)?p->pf:p->pd;
if(x < 0 ) x = -x;
if(x<.1) return(wrt_E(p,w,d,e,len));
for(i=0;i<=d;i++,up*=10)
{ if(x>=up) continue;
scale=0;
if(e==0) n=4;
else n=e+2;
i=wrt_F(p,w-n,d-i,len);
for(j=0;j<n;j++) (*putn)(' ');
scale=oldscale;
return(i);
}
return(wrt_E((ufloat *)p,w,d,e,len));
}
wrt_F(p,w,d,len) ufloat *p; ftnlen len;
{ int i,delta,dp,sign,n;
double x;
char *s,*fcvt();
x= (len==sizeof(float)?p->pf:p->pd);
if(scale)
{ if(scale>0)
for(i=0;i<scale;i++) x*=10;
else for(i=0;i<-scale;i++) x/=10;
}
s=fcvt(x,d,&dp,&sign);
if(-dp>=d) sign=0;
if(sign || cplus) delta=2;
else delta=1;
n= w - (d+delta+(dp>0?dp:0));
if(n<0)
{
for(i=0;i<w;i++) PUT('*');
return(0);
}
for(i=0;i<n;i++) PUT(' ');
if(sign) PUT('-');
else if(cplus) PUT('+');
for(i=0;i<dp;i++) PUT(*s++);
PUT('.');
for(i=0;i< -dp && i<d;i++) PUT('0');
for(;i<d;i++)
{ if(*s) PUT(*s++);
else PUT('0');
}
return(0);
}