#include "all.h"
int var_alloc_local(void);
int var_free_local(void);
extern long *(*gpcode)[];   /* gpcode is a pointer to an array of poiter to long */
extern long (*gplen)[];   /* gpcode is a pointer to an array of long */
extern int ngpcode;
extern int gle_debug;
#define dbg if ((gle_debug & 128)>0)

struct sub_st {char name[40];int typ; int np
		; int ptyp[20]; char *pname[20]; int start; int end ; }  ;
struct sub_st *sb[100];
int nsb;
double return_value=0;
char return_string[80];
int return_type;


sub_param(int idx,char *s)
{
	int vi,vt;
	mystrcpy(&( sb[idx]->pname[ ++(sb[idx]->np) ] ) ,s);
	/* should be set ptype according to num/string variable */
	var_add(s,&vi,&vt);
	sb[idx]->ptyp[ (sb[idx]->np) ] = vt;
}
sub_find(char *s,int *idx,int *zret, int *np, int **plist)
{
	int i;
	for (i=1;i<=nsb;i++) {
		if (strcmp(sb[i]->name,s)==0) {
			*idx = i;
			*zret = sb[i]->typ;
			*np = sb[i]->np;
			*plist = &(sb[i]->ptyp[1]);
			return i;
		}
	}
	return 0;
}
sub_clear()
{
	int i,j;
	for (i=1;i<=nsb;i++) {
	  if (sb[i] != NULL) {
		for (j=1; j<= sb[i]->np; j++) {
			if (sb[i]->pname[j] != NULL) myfree(sb[i]->pname[j]);
		}
	  }
	  myfree(sb[i]);
	  sb[i] = NULL;
	}
	nsb = 0;
}
int sub_def(char *s)
{
	int i;
	for (i=1;i<=nsb;i++) {
		if (strcmp(sb[i]->name,s)==0) {
			strcpy(sb[i]->name,"^");
		}
	}
	if (i>nsb) {
		nsb = i;
		sb[i] = myallocz(sizeof(*sb[0]));
		strcpy(sb[i]->name,s);
	}
	sb[i]->np = 0;
	return i;
}
sub_set_startend(int idx, int ss, int ee)
{
	if (idx<0 || idx>1000) {
		gprint("idx is out of range \n");
		return;
	}
	sb[idx]->start = ss;
	sb[idx]->end = ee;
}
sub_get_startend(int idx, int *ss, int *ee)
{
	*ss = sb[idx]->start;
	*ee = sb[idx]->end;
}

/*--------------------------------------------------------------------------*/
/* 	Run a user defined function  */
sub_call(int idx,double *pval,char **pstr,int *npm)
{
	int i;
	int endp;
	double save_return_value;

    	save_return_value = return_value;
	var_alloc_local();
	dbg for (i=0;i<4;i++) gprint("STACK IN SUBCALL, (%d) = %f \n",i,*(pval+i));
	if (*npm<sb[idx]->np) gprint("parameters in sub_call, not enough **\n");
	for (i = sb[idx]->np;i>=1;i--) {
		if (sb[idx]->ptyp[i] == 1)  {
			var_set(200 + i-1,*(pval+(*npm)--));
		} else	{
			var_setstr(200 + i-1,*(pstr+(*npm)--));
		}
	}

	dbg gprint("SUB CALL ----- startline %d   end %d \n",
		sb[idx]->start,sb[idx]->end);

	for (i = sb[idx]->start + 1;i< (sb[idx]->end);i++) {
		dbg gprint("=Call do pcode, line %d ",i);
		do_pcode(&i,(*gpcode)[i],(*gplen)[i],&endp);
		dbg gprint("AFTER DO_PCODE I = %d \n",i);
	}
	dbg gprint("FINISHED CALL ------\n");
	*(pval + ++(*npm)) = return_value;
	return_value = save_return_value;
	var_free_local();
	dbg for (i=0;i<=*npm;i++) gprint("STACK IN SUBCALL, (%d) = %f \n",i,*(pval+i));
}
sub_set_return(double d)
{
	return_value = d;
}

