static char rcsid[] = "$Header:misc.c 12.0$";
#include <ctype.h>
#include "defs"

char * copys(s)
register char *s;
{
register char *t;
char *k;
ptr calloc();

for(t=s; *t++ ; );
if( (k = (char *)calloc( t-s , sizeof(char))) == NULL)
	fatal("Cannot allocate memory");

for(t=k ; *t++ = *s++ ; );
return(k);
}



equals(a,b)
register char *a,*b;
{
if(a==b) return(YES);

while(*a == *b)
	if(*a == '\0') return(YES);
	else {++a; ++b;}

return(NO);
}


char *concat(a,b,c)   /* c = concatenation of a and b */
register char *a,*b;
char *c;
{
register char *t;
t = c;

while(*t = *a++) t++;
while(*t++ = *b++);
return(c);
}





ptr conrep(a,b)
char *a, *b;
{
char *s;

s = (char *)intalloc( strlen(a)+strlen(b)+1 );
concat(a,b,s);
cfree(a);
return((ptr)s);
}


eqcon(p,q)
register ptr p, q;
{
int pt, qt;

if(p==q) return(YES);
if(p==NULL || q==NULL) return(NO);
pt = ((struct headbits *)p)->tag;
qt = ((struct headbits *)q)->tag;
if(pt==TNEGOP && qt==TNEGOP)
	return( eqcon(((struct iostblock *)p)->leftp, ((struct iostblock *)q)->leftp) );
if(pt==TCONST && qt==TNEGOP)
	return(NO);
if(pt==TNEGOP && qt==TCONST)
	return(NO);
if(((struct headbits *)p)->tag==TCONST && ((struct headbits *)q)->tag==TCONST)
	return( equals(((struct iostblock *)p)->leftp,((struct iostblock *)q)->leftp) );

fatal("eqcon: nonconstant argument");
/* NOTREACHED */
}



char *convic(n)
register int n;
{
static char s[20];
register char *t;

s[19] = '\0';
t = s+19;

do	{
	*--t = '0' + n%10;
	n /= 10;
	} while(n > 0);

return(t);
}



conval(p)
register ptr p;
{
int val;
if(isicon(p, &val))
	return(val);
fatal("bad conval");
}



isicon(p, valp)
ptr p;
int *valp;
{
int val1;

if(p)
    switch(((struct headbits *)p)->tag)
	{
	case TNEGOP:
		if(isicon(((struct iostblock *)p)->leftp, &val1))
			{
			*valp = - val1;
			return(1);
			}
		break;

	case TCONST:
		if(((struct iostblock *)p)->vtype == TYINT)
			{
			*valp = convci(((struct iostblock *)p)->leftp);
			return(YES);
			}
	default:
		break;
	}
return(NO);
}



isconst(p)
ptr p;
{
return(((struct headbits *)p)->tag==TCONST  ||  (((struct headbits *)p)->tag==TNEGOP && isconst(((struct iostblock *)p)->leftp)) );
}



iszero(s)
register char *s;
{
if(s == NULL)
	return(YES);
while( *s=='+' || *s=='-' || *s==' ' )
	++s;
while( *s=='0' || *s=='.' )
	++s;
switch( *s )
	{
	case 'd':
	case 'e':
	case 'D':
	case 'E':
	case ' ':
	case '\0':
		return(YES);
	default:
		return(NO);
	}
}




convci(p)
register char *p;
{
register int n;
register int sgn;

n = 0;
sgn = 1;
for( ; *p ; ++p)
	if(*p == '-')
		sgn = -1;
	else if( isdigit(*p) )
		n = 10*n + (*p - '0');

return(sgn * n);
}



chainp hookup(x,y)
register chainp x, y;
{
register chainp p;

if(x == NULL)
	return(y);
for(p=x ; ((struct dimblock *)p)->nextp ; p = (chainp)((struct dimblock *)p)->nextp)
	;

((struct dimblock *)p)->nextp = (ptr)y;
return(x);
}


ptr cpexpr(p)
register ptr p;
{
register ptr e;
ptr q, q1;

if(p == NULL)
	return(NULL);

e = allexpblock();
cpblock(p, e, sizeof(struct exprblock));

switch(((struct headbits *)p)->tag)
	{
	case TAROP:
	case TRELOP:
	case TLOGOP:
	case TASGNOP:
	case TCALL:
		((struct exprblock *)e)->rightp = cpexpr(((struct exprblock *)p)->rightp);

	case TNOTOP:
	case TNEGOP:
		((struct exprblock *)e)->leftp = cpexpr(((struct exprblock *)p)->leftp);
		break;

	case TCONST:
		((struct exprblock *)e)->leftp = (ptr)copys(((struct exprblock *)p)->leftp);
		if(((struct exprblock *)p)->rightp)
			((struct exprblock *)e)->rightp = (ptr)copys(((struct exprblock *)p)->rightp);
		if(((struct exprblock *)p)->vtype == TYCHAR)
			((struct exprblock *)e)->vtypep = cpexpr(((struct exprblock *)p)->vtypep);
		break;

	case TLIST:
		q1 = (ptr)&(((struct exprblock *)e)->leftp);
		for(q = ((struct exprblock *)p)->leftp ; q ; q = ((struct dimblock *)q)->nextp)
			q1 = ((struct dimblock *)q1)->nextp = (ptr)mkchain( (((struct chain *)q)->datap), CHNULL);
		break;

	case TTEMP:
	case TNAME:
	case TFTNBLOCK:
		if(((struct varblock *)p)->vsubs)
			((struct varblock *)e)->vsubs = cpexpr(((struct varblock *)p)->vsubs);
		if(((struct varblock *)p)->voffset)
			((struct varblock *)e)->voffset = cpexpr(((struct varblock *)p)->voffset);
		break;

	case TERROR:
		break;

	default:
		badtag("cpexpr", ((struct headbits *)p)->tag);
	}
return(e);
}


mvexpr(p,q)
char *p, *q;
{
cpblock(p,q, sizeof(struct exprblock) );
frexpblock(p);
}


cpblock(p,q,n)
register char *p, *q;
int n;
{
register int i;

for(i=0; i<n; ++i)
	*q++ = *p++;
}



strlen(s)
register char *s;
{
register char *t;
for(t=s ; *t ; t++ ) ;
return(t-s);
}


char *procnm()	/* name of the current procedure */
{
return( procname ? ((struct stentry *)((struct typeblock *)procname)->sthead)->namep : "" );
}





ptr arg1(a)		/* make an argument list of one value */
ptr a;
{
return( mknode(TLIST,0, mkchain(a,CHNULL), PNULL) );
}



ptr arg2(a,b)	/* make an argumentlist (a,b) */
ptr a,b;
{
register ptr p;

p = (ptr)mkchain(a, mkchain(b,CHNULL) );
return( mknode(TLIST,0, p,0) );
}




ptr arg4(a,b)	/* make an argument list of  (a,len(a), b,len(b)) */
ptr a,b;
{
register ptr p;
p = (ptr)mkchain(b, mkchain(cpexpr(((struct varblock *)b)->vtypep), CHNULL));
p = (ptr)mkchain(a, mkchain(cpexpr(((struct varblock *)a)->vtypep), p));
return( mknode(TLIST,0,p,PNULL));
}



ptr builtin(type,s)
int type;
char *s;
{
register ptr p, q;
ptr mkvar(), mkname();

if(p = (ptr)name(s,1))
	{
	if(((struct headbits *)p)->blklevel>1 || (((struct headbits *)p)->tag!=TNAME && ((struct headbits *)p)->tag!=TKEYWORD) 
	    || (q=((struct stentry *)p)->varp)==0 || ((struct varblock *)q)->vext
	    || (((struct varblock *)q)->vtype!=type && ((struct varblock *)q)->vtype!=TYUNDEFINED) )
		{
		exprerr("error involving builtin %s", s);
		return(errnode());
		}
	if(((struct varblock *)q)->vtype!= TYUNDEFINED)
		return( cpexpr(q) );
	}
else	{
	q = mkvar( mkname(s) );
	if(blklevel > 1)
		{
		((struct headbits *)q)->blklevel = 1;
		((struct headbits *)((struct typeblock *)q)->sthead)->blklevel = 1;
		--ndecl[blklevel];
		++ndecl[1];
		}
	}

((struct varblock *)q)->vtype = type;
((struct varblock *)q)->vdclstart = 1;
mkftnp(q);
return( cpexpr(q) );
}



ptr errnode()
{
register struct exprblock * p;

p = (struct exprblock *)allexpblock();
((struct headbits *)p)->tag = TERROR;
((struct varblock *)p)->vtype = TYINT;
return((ptr)p);
}



min(a,b)
int a,b;
{
return( a<b ? a : b);
}



setvproc(p, v)
register ptr p;
register int v;
{
ptr q;
register int k;

q = ((struct stentry *)((struct typeblock *)p)->sthead)->varp;
k = ((struct varblock *)q)->vproc;
/*debug printf("setvproc(%s ,%d)\n", (((struct stentry *)(struct varblock *)q)->sthead)->namep, v); */
if(p != q)
	((struct varblock *)p)->vproc = k;
if(k == v)
	return;

if(k==PROCUNKNOWN || (k==PROCYES && v==PROCINTRINSIC) )
	((struct varblock *)p)->vproc = ((struct varblock *)q)->vproc = v;
else if( !(k==PROCINTRINSIC && v==PROCYES)  && ((struct stentry *)((struct typeblock *)p)->sthead)->varp!=procname)
	execerr("attempt to use %s as variable and procedure",
		((struct stentry *)((struct typeblock *)p)->sthead)->namep);
}
