/*  helpers.c -- native runtime helpers called from generated code  */

#include "toba.h"
#include "runtime.h"
#include "java_lang_NullPointerException.h"

#include <stdlib.h>
#include <math.h>

char * npe_file_name = NULL;    /* Name of file throwing NPE */
int npe_file_line = -1;         /* Line where threw NPE */

/*  findhandler(table, size, exceptn, oldpc) -- search table to find handler  */

int findhandler(struct handler *h, int tsize, Object exception, int oldpc)
{
    while (tsize-- > 0) {
	if ((unsigned)oldpc >= h->start_pc
	&&  (unsigned)oldpc <  h->end_pc
	&& (h->class == 0 || instanceof(exception, h->class, 0)))
	    return h->handler_pc;
	h++;
    }
    return -1;
}



/*  findinterface(o, n) -- find interface method for "invokeinterface"  */

struct mt_generic *
findinterface(Object o, int signaturehash)
{
    Class c = ((struct in_generic *)o)->class;
    struct ihash *p = (struct ihash *)c->htable + (signaturehash & c->hashmask);

    for (;;) {
	if (p->n == signaturehash)
	    return (struct mt_generic *)p->mt;
	else if (p->mt != 0)
	    p++;
	else
	    throwIncompatibleClassChangeError(o);
    }
}


/* interfinstance(cl, interf) -- does cl implement the interface interf? */

static int interfinstance(Class cl, Class interf)
{
    int i;

    for (i = 0; i < cl->ninters; i++) {
        if (cl->inters[i] == interf)
 	    return 1;
        if(interfinstance(cl->inters[i], interf))
            return 1;
    }
    return 0;
}


/* 
 *  instanceof(o, c, n) -- is o an instance of an array of n dims of class c?
 *
 *  o is any object, but not null.
 *  c is any class
 *
 *  o is checked for assignability to an n-dimensional array of c.
 *  If n is zero, o is checked for assignability to an object of type c.
 */ 
int instanceof(Object o, Class c, int ndim)
{
    int dim;
    Class oc = ((struct in_generic *)o)->class;

    dim = ndim;
    while (c->flags & IS_ARRAY) {	/* find underlying target class */
        c = c->elemclass;
        dim++;
    }
 
    while (dim > 0) {
	oc = oc->elemclass;		/* find underlying element classes */
	if (!oc)
	    return 0;			/* dimension mismatch */
	dim--;
    }

    if (oc == c)			/* quick check for exact match */
	return 1;

    if ((oc->flags | c->flags) & IS_PRIMITIVE)
	return 0;			/* if primitive, must be identical */

    if (c->flags & IS_INTERFACE)	/* if an interface, check specially */
        return interfinstance(oc, c);

    /* at this point c is a simple class although oc may be an array; */
    /* an array matches only java.lang.Object */
    return oc->nsupers >= c->nsupers && oc->supers[oc->nsupers-c->nsupers] == c;
}



/*
 *  dtoi(d) -- convert double (or float) to int.
 */
Int dtoi(Double d)
{
    if (d != d)		/* if NaN */
    	return 0;
    else if (d >= MAX_JAVA_INT)
        return MAX_JAVA_INT;
    else if (d <= MIN_JAVA_INT)
        return MIN_JAVA_INT;
    else
    	return (Int)d;
}

/*
 *  dtol(d) -- convert double (or float) to long.
 */
Long dtol(Double d)
{
    if (d != d)		/* if NaN */
    	return 0;
    else if (d >= MAX_JAVA_LONG)
        return MAX_JAVA_LONG;
    else if (d <= MIN_JAVA_LONG)
        return MIN_JAVA_LONG;
    else
    	return (Long)d;
}

/*
 *  remdr(a,b) -- compute a % b.
 */
Double remdr(Double a, Double b)
{
    if (a != a || b != b || b == 0)
    	return 0.0 / 0.0;	/* NaN */
    else
    	return fmod(a, b);
}
