#include "include/glbtypes.h"
#include "include/glbproto.h"
#include "include/globvars.h"


void warning(int code,char * msg)
{
fprintf(stderr,"Warning %d: %s\n",code,msg);
};


int typesizeprint(struct typerec type)
{
printf("Type %s : \nSize = %d\nKind = ",type.name,type.size);

switch(type.typekind)
	{
	case BUILT_IN:  printf("Built-in type\n");
			printf("Built-in specification details:");
			switch(type.typebody.built_in)
				{
				case __int___  : printf("Integer number\n");
						 break;
				case __char__  : printf("Character\n");
						 break;
				case __list__  : printf("List\n");
						 break;
				case __str__   : printf("String\n");
						 break;
				case __long__  : printf("Long integer number\n");
						 break;
				case __double__: printf("Double integer number\n");
						 break;
				default        : printf("\n\nCritical: unknown built-in type !\n");
						break;
				};
			break;
	case STRUCT:    printf("Structure type\n");break;
	case UNION:     printf("Union type\n");break;
	case ENUM:      printf("Enumeration type\n");break;
	default: printf("\n\nError !!!\n\n");break;
	};
return type.size;
};

int functionprint(struct fundef x)
{
struct vardecl_list PTR args;
int i;
printf("Function %s : the type is\n",x.name);
typesizeprint(*x.res_type);
for(i=1,args=x.args;args!=NULL;args=args->next)
	{
	printf("Argument #%d:\n",i);
	typesizeprint(*args->var->type);
	};
return x.res_type->size;
};



int print_var(struct var_decl var,int tab)
{
char PTR varname=var.name;
/*struct field_def PTR field;*/
struct vardecl_list PTR field;
printf("%*s %s : size %d\n",tab,var.type->name,varname,var.type->size);
if (var.type->typekind==STRUCT)
{
	field=var.type->typebody.struct_def->fields;
	while (field!=NULL)
		{
		printf("%*s %s.%s : size %d\n",tab+1,field->var->type->name,varname,field->var->name,field->var->type->size);
		field=field->next;
		};
};

return var.type->size;
};

int type_cmp(struct typerec PTR t1,struct typerec PTR t2)
	{
	if((t1==NULL)||(t2==NULL))
		return 0;
	if(t1==t2)
		return 1; /* a shortcut */
	if(Strcmp(t1->name,t2->name))
		return 0; /* different names -> no match */
	if(t1->typemodf==t2->typemodf)
		{
		if((t1->typemodf==POINTER)
		||(t1->typemodf==REFERENCE)
		||(t1->typemodf==INDEX))
			return type_cmp(t1->typebody.pointer_to,t2->typebody.pointer_to);
		else /* if not pointer */
			return 1; /* then true */
		}
	else
		return 0; /* different modifiers -> no match */
	
	};


struct typerec PTR mk_ref_type_from_type(struct typerec PTR type,enum typemodf tm, struct type_listoflist PTR tll,int force_new_flag)
{
/* force_new_flag is used to FORCE creation of new type even if there already is one */
struct type_list PTR tl;

if((tm!=POINTER)&(tm!=REFERENCE)&(tm!=INDEX))
	return type;
if(tll->tlist==NULL)
  {
    tll->tlist=my_malloc(sizeof(struct type_list));
    tll->tlist->next=NULL;
    tll->tlist->convert_lock=OFF;
    tll->tlist->type=my_malloc(sizeof(struct typerec));
    set_typerec(tll->tlist->type,4,Strdup(type->name),TYPEREFR,tm,__void__,NULL);
    global_type_id_count++;
    tl=tll->tlist;
    tl->type->typeid=global_type_id_count;
  }
else
  {
    struct type_listoflist PTR tll_ind;
    int type_redef_flag=0;
    for(tll_ind=tll;(!force_new_flag)&(tll_ind!=NULL)&(!type_redef_flag);tll_ind=tll_ind->next)
/* this does check upper level types until type is redeclared - after that it's dangerous  to use ref types */
      {
	for(tl=tll->tlist;tl!=NULL;tl=tl->next) /* maybe we already have ref type ? */
	  {
	     if(tl->type!=NULL)
		{	
		    if(!strcmp(type->name,tl->type->name))
		      {
			if((tm==tl->type->typemodf)&(type_cmp(tl->type->typebody.pointer_to,type)))
			/* if type is the same, i.e. if we already have that pointer */
		          {
			    return tl->type; /* we already have that pointer */
	        	  }
	     	   else
			  type_redef_flag=1; /* it's not a pointer, but that type was redefined - we must stop going up levels */
		};
	      };
	  };
      };
    tl=install_type(tll->tlist,4,Strdup(type->name),TYPEREFR,tm,__void__,NULL);
  };
tl->type->typebody.pointer_to=type;
return tl->type;
};

struct typerec PTR mk_subtype_by_type(struct typerec PTR type1,struct typerec PTR type2, struct type_listoflist PTR tll,int mode)
/* mode: 0 - ADD to temporary types, 1 - create new types even if type1 is temporary */
{
struct type_list PTR tl,PTR tl1;
char local_buf[32];

if (type1==NULL)
	return type2;

if(type2==NULL)
	return type1;

if((mode==0)&(*type1->name==4)&(type1->typekind==CLASS)) 
	{
	/* add to type */
	struct type_list PTR tmptlist=NULL;
	tmptlist=type1->typebody.class_def->top_class;
	type1->typebody.class_def->top_class=my_malloc(sizeof(struct type_list));
	type1->typebody.class_def->top_class->next=tmptlist;
	type1->typebody.class_def->top_class->type=type2;
	return type1;
	};

sprintf(local_buf,"\4tmptype%lx",global_tmp_type++);

if(tll->tlist==NULL)
{
  tll->tlist=my_malloc(sizeof(struct type_list));
  tll->tlist->next=NULL;
  tll->tlist->convert_lock=OFF;
  tll->tlist->type=my_malloc(sizeof(struct typerec));
  set_typerec(tll->tlist->type,type1->size+type2->size,Strdup(local_buf),CLASS,NONE,__void__,NULL);
  global_type_id_count++;
  tll->tlist->type->typeid=global_type_id_count;
  tl1=tll->tlist;
}
else
  tl1=install_type(tll->tlist,type1->size+type2->size,Strdup(local_buf),CLASS,NONE,__void__,NULL);

tl1->type->typebody.class_def=my_malloc(sizeof(struct class_def));
tl1->type->typebody.class_def->name=Strdup(local_buf);
tl1->type->typebody.class_def->constructors=NULL;
tl1->type->typebody.class_def->destructors=NULL;
/*tl1->type->typebody.class_def->modif_lst=NULL;*/
tl1->type->typebody.class_def->funcs=NULL;
tl1->type->typebody.class_def->vars=NULL;
tl1->type->typebody.class_def->top_class=my_malloc(sizeof(struct type_list));
tl1->type->typebody.class_def->top_class->next=my_malloc(sizeof(struct type_list));
tl1->type->typebody.class_def->top_class->next->next=NULL;

tl1->type->typebody.class_def->top_class->type=type1;
tl1->type->typebody.class_def->top_class->next->type=type2;

return tl1->type;
};

struct typerec PTR mk_subtype_by_name(struct typerec PTR type,char PTR name,enum typemodf tm, struct type_listoflist PTR tll)
{
struct type_list PTR tl,PTR tl1;
char local_buf[32];

while(tll!=NULL)
	{
	tl=tll->tlist;
	while(tl!=NULL)
		{
		if((!Strcmp(name,tl->type->name))&(tl->type->typemodf==tm))
				break;
		tl=tl->next;
		};
	if(tl!=NULL)
		break;
	tll=tll->next;
	};

if (tl==NULL)
	return NULL;

return mk_subtype_by_type(type,tl->type,tll,0);

};

struct typerec PTR eval_type_refr(struct typerec PTR type,listnode fnlist,struct vardecl_listoflist PTR vars,struct type_listoflist PTR types,listnode labels,int bind)
{
struct vardecl_list PTR vl=NULL;
struct typerec PTR type1=NULL;
char local_buf[34];

/* "bind" selects the binding mode for "typeof"
// 0 - just get type, 1 - bind, 2 - make copy and bind it */

if(type==NULL)
	return NULL;

while((type!=NULL)&(type->typekind==TYPEREFR)&(type->typemodf==NONE))
	type=type->typebody.pointer_to;

if((type->typekind!=ISTYPEOF)&(type->typekind!=SYMBREFR))
	return type;

if(type->typekind==SYMBREFR)
	{
	type1=get_type_by_name(type->typebody.symbrefr,NONE,types);

	if(type1==NULL)
		return type; /* cant resolve by now ... */

	type->typekind=TYPEREFR;

	type->typebody.pointer_to=eval_type_refr(type1,fnlist,vars,types,labels,bind);

	return type->typebody.pointer_to;
	};

if((type->typebody.typeof->attr==VARIABLE)&(type->typebody.typeof->next==NULL))
	{
	vl=global_find_var_decl(type->typebody.typeof->data,vars);
	if(vl==NULL)
		return NULL;

	type1=vl->var->type;

	}
else
	{
	type1=validate_function(type->typebody.typeof,fnlist,vars,types,labels,0);
	if(type1==NULL)
		return NULL;
	};

if(bind==0)
	return eval_type_refr(type,fnlist,vars,types,labels,0);/* bind==0 */

if(bind==1)
	{
	rm_lnd_all(type->typebody.typeof);

	type->typekind=TYPEREFR; /* bind the type now ! */
	type->typebody.pointer_to=type1;

	return type;
	};

memset(local_buf,0,34);
sprintf(local_buf,"\4tmptypel%x",global_tmp_type);

if(types->tlist==NULL)
	{
	types->tlist=my_malloc(sizeof(struct type_list));
	types->tlist->next=NULL;
	types->tlist->convert_lock=OFF;
	types->tlist->type=my_malloc(sizeof(struct typerec));
	type=set_typerec(types->tlist->type,type->size,Strdup(local_buf),TYPEREFR,type->typemodf,__void__,NULL);
	}
else
	type=install_type(types->tlist,type->size,Strdup(local_buf),TYPEREFR,type->typemodf,__void__,NULL)->type;

type->typebody.pointer_to=type1;
return type;
};


listnode convert_type_special(struct typerec PTR type1,struct typerec PTR type2)
{
if(!Strcmp(type1->name,type2->name))
	{
	if((type1->typemodf==NONE)
	&(type2->typemodf==REFERENCE))
		{
		printf("# Converting type %s to reference to type %s\n",type1->name,type2->name);
		return mk_set_lnd(NULL,"\4_Bstdrefconv",FUNCTION);
		};

	if((type1->typemodf==REFERENCE)
	&(type2->typemodf==NONE))
		{
		printf("# Converting reference to type %s to type %s\n",type1->name,type2->name);
		return mk_set_lnd(NULL,"\4_Bstdrefconv",FUNCTION);
		};

	if((type1->typemodf==POINTER)
	&(type2->typemodf==INDEX))
		{
		printf("# Converting pointer to type %s to index of type %s\n",type1->name,type2->name);
		return mk_set_lnd(NULL,"\4_Bstdptr2indconv",FUNCTION);
		};

	if((type1->typemodf==INDEX)
	&(type2->typemodf==POINTER))
		{
		printf("# Converting index of type %s to pointer to type %s\n",type1->name,type2->name);
		return mk_set_lnd(NULL,"\4_Bstdind2ptrconv",FUNCTION);
		};
	return 0;
	}    /* if !strcmp(type1->name,type2->name) */
else
	if((type1->typemodf==POINTER) & (type2->typemodf==POINTER))
		{
		if((type1->typekind==BUILT_IN)&(type1->typebody.built_in==__void__))
			{
			printf("# Representing void * as %s * \n",type2->name);
			return mk_set_lnd(NULL,"\4_Bstdvoidconv",FUNCTION);
			};
		if((type2->typekind==BUILT_IN)&(type2->typebody.built_in==__void__))
			{
			printf("# Representing %s * as void * \n",type1->name);
			return mk_set_lnd(NULL,"\4_Bstdvoidconv",FUNCTION);
			};
		};
return NULL;
};

listnode convert_type_self_daemon(
struct typerec PTR type,
listnode convlist,
int direction)
{
struct fundef_list PTR convind;

if(type==NULL)
	return convlist;

for(convind=type->typeconv;convind!=NULL;convind=convind->next)
  {
    if(convind->fundef==NULL)
	continue;
    if(convind->fundef->res_type==NULL)
	continue;
    if((!Strcmp(type->name,convind->fundef->res_type->name))
       & (type->typemodf==convind->fundef->res_type->typemodf))
      {
	if((convind->fundef->args==NULL)&(direction==1)) /* self - out */
	  {
	    return mk_head_lnd(convlist,convind->fundef,FUNDEFNL);
	  };
	if((convind->fundef->args->var!=NULL)&(convind->fundef->args->next==NULL))
	  {
	    if(convind->fundef->args->var->type==NULL)
	      continue; /* no type - no match */
	    if((type_cmp(type,convind->fundef->args->var->type))
	       & (!direction)) /* self - in */
	      {
		return mk_head_lnd(convlist,convind->fundef,FUNDEFNL);
	      };
	  };
      };
  };
return convlist;
};

listnode convert_type(
struct type_listoflist PTR typelist,/* Main list of types */
struct typerec 	 PTR type1, /* FROM type1 */
struct typerec 	 PTR type2, /* TO type2 */
listnode convlist)
{
struct fundef_list PTR convind;
struct type_list PTR tl;
struct type_listoflist PTR tll;
listnode use_fun=NULL;
int was_rec_flag=0; 
listnode clst=NULL;
/* 0 - no recursive conv, 1 - was recursive conv, 2 - recursively found
dynamic type */

if((type1==NULL)||(type2==NULL)) return NULL;

while((type1->typekind==TYPEREFR)&(type1->typemodf==NONE))
	type1=type1->typebody.pointer_to;
while((type2->typekind==TYPEREFR)&(type2->typemodf==NONE))
	type2=type2->typebody.pointer_to;

tll=typelist;

while(tll!=NULL)
	{
	tl=tll->tlist;
	while(tl!=NULL)
		{
		if((type_cmp(type2,tl->type))
		& (tl->convert_lock==OFF))
			break;
		tl=tl->next;
		};
	if(tl!=NULL)
		break;
	tll=tll->next;
	};


if(type2->typekind==VAR_TYPE)
	{
	if(type1->typemodf==VAR_TYPE)
		  return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,VARTYPEL),type1,VARTYPEL),VARTYPEL);
	else
		  return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,TYPEDEFN),type1,VARTYPEL),VARTYPEL);
	};
if(type1->typekind==VAR_TYPE)
	  return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,VARTYPEL),type1,TYPEDEFN),VARTYPEL);


if(tl==NULL)
	/* Direct convertion ... */
	/*  return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,TYPEDEFN),type1,TYPEDEFN),TWOLISTS);*/
	{
	if((clst=convert_type_special(type1,type2))!=NULL)
		{
		lnd_rapnde(clst,convlist);
		return clst;
		};
	};
if (tll==NULL) /* Trying to work with moditiers ... */
	{
	tll=typelist;

	while(tll!=NULL)
		{
		tl=tll->tlist;

		while(tl!=NULL)
			{
			if((tl->convert_lock==OFF)
			&((clst=convert_type_special(type2,tl->type))!=NULL))
				break;
			tl=tl->next;
			};
		if(tl!=NULL)
			break;
		tll=tll->next;
		};
	if(tl!=NULL)
		{
		lnd_rapnde(clst,convlist);
		convlist=clst;clst=NULL;
		};
	};
if(tl==NULL)
	{
	printf("Type %s not found !!!\n",type2->name);
	return NULL;
	};

for(convind=tl->type->typeconv;convind!=NULL;convind=convind->next)
  {
    if(convind->fundef->args!=NULL)
      {
	if((type_cmp(type1,convind->fundef->args->var->type)) &
	(convind->fundef->args->next==NULL))
		{
		convind=(struct fundef_list PTR)convind->fundef;
		break;
		};
      };
  };
if (convind==NULL)
	{
	for(convind=tl->type->typeconv;convind!=NULL;convind=convind->next)

		if(convind->fundef->args->next==NULL)
			{
			if((clst=convert_type_special(type1,convind->fundef->args->var->type))!=NULL)
				{
				convind=(struct fundef_list PTR)convind->fundef;
				if(clst!=NULL)
					{
					lnd_rapnde(clst,convlist);
					convlist=clst;clst=NULL;
					};
				break;
				};
			};
	};

if ((convind==NULL)&(type2->typekind==CLASS))
  {
    for(convind=type2->typebody.class_def->constructors;convind!=NULL;convind=convind->next)
      {
	if(convind->fundef->args!=NULL)
	  {
	    if((type_cmp(type1,convind->fundef->args->var->type)) &
	       (convind->fundef->args->next==NULL))
	      {
		convind=(struct fundef_list PTR)convind->fundef;
		break;
	      };
	  };
      };
  };

if((convind==NULL)&(type1->typekind==CLASS))
/* Maybe base classes of this class have methods of converting ... */
	{
	printf("## Using base classes of class %s ...\n",type1->name);
	convind=NULL;

	for(tl=type1->typebody.class_def->top_class;tl!=NULL;tl=tl->next)
		if (tl->type==type2)
			{
			printf("## %s has a base class %s was used.\n",type2->name,type1->name);
			return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,TYPEDEFN),type1,TYPEDEFN),TWOLISTS);
			};
	};

if((convind==NULL)&(type2->typekind==CLASS))
/* Maybe base classes of this class have methods of converting ... */
	{
	printf("## Using base classes of class %s ...\n",type1->name);
	convind=NULL;

	for(tl=type2->typebody.class_def->top_class;tl!=NULL;tl=tl->next)
		if (type_cmp(tl->type,type1))
			{
			printf("## %s has a base class %s was used.\n",type1->name,type2->name);
			return mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type2,TYPEDEFN),type1,TYPEDEFN),TWOLISTS);
			};

	for(tl=type2->typebody.class_def->top_class;tl!=NULL;tl=tl->next)
		{
		listnode ltmp=NULL;
		printf("## Trying to use base class %s ...\n",tl->type->name);

		ltmp=convert_type(typelist,type1,tl->type,convlist);
		if (ltmp!=NULL)
			{
			printf("## Base class %s of %s was used.\n",tl->type->name,type2->name);
			if((ltmp->attr==VARTYPEL)||(ltmp->attr==TYPEVARL))
				{
				printf("## Type is dynamic, looking for static alternative ...\n");
				if(clst==NULL)
					clst=ltmp;
				else
					lnd_rapnde(clst,ltmp);
				was_rec_flag=2; /* dynamic recursive conv */
				}
			else
				{
				if(clst!=NULL)
				/* if we have static types we don't need any dynamic */
					rm_lnd_all(clst); 
		
				clst=ltmp;
				was_rec_flag=1; /* recursive conv occured */
				break;
				};
			};
		};
	};

if (((convind==NULL)&(clst==NULL))||(was_rec_flag==2))
	{
	printf("## Trying to convert type %s to type %s in several steps\n",type1->name,type2->name);
	tl->convert_lock=ON;
	for(convind=tl->type->typeconv;(convind!=NULL)&(was_rec_flag!=1);convind=convind->next)
		{
		if((use_fun=convert_type(typelist,type1,convind->fundef->args->var->type,convlist))!=NULL)
			if((use_fun->attr==TYPEVARL)||(use_fun->attr==VARTYPEL))
				{
				if(clst==NULL)
					clst=use_fun;
				else
					lnd_rapnde(clst,use_fun);
				was_rec_flag=2; /* dynamic recursive conv */
				use_fun=NULL; /* to continue work */
				}
			else
				{
				if(clst!=NULL)
				/* if we have static types we don't need any dynamic */
					rm_lnd_all(clst); 
		
				clst=use_fun;
				was_rec_flag=1; /* recursive conv occured */
				break;
				}
		if(((use_fun=convert_type_special(type1,convind->fundef->args->var->type))!=NULL))
			{
			lnd_rapnde(use_fun,convlist);
			convlist=use_fun;use_fun=NULL;

			if(clst!=NULL)
			/* if we have static types we don't need any dynamic */
				rm_lnd_all(clst); 
		
			clst=NULL;
			was_rec_flag=1; /* recursive conv occured */
			break;
			};
		};
	tl->convert_lock=OFF;
	if(convind!=NULL)
		{
		if(use_fun!=NULL)
			convlist=use_fun; /* Functional converter */
/* new built-in handle		else*/	/* Built-in */
		/*	convlist=mk_head_lnd(convlist,mk_head_lnd(mk_head_lnd(NULL,type1,TYPEDEFN),convind->fundef->args->var->type,TYPEDEFN),TWOLISTS);*/

		printf("## Used step-type %s\n",convind->fundef->args->var->type->name);
		convind=(struct fundef_list PTR)convind->fundef;
		};
	};


if (((convind==NULL)&(clst==NULL))||(was_rec_flag==2))
/* Trying to work with special moditiers in several steps ... */
	{
	tll=typelist;

	while(tll!=NULL)
		{
		tl=tll->tlist;

		while(tl!=NULL)
			{
			if(tl->convert_lock==OFF)
			/* Try the last posibility - special modifiers ... */
				{
				if((clst=convert_type_special(tl->type,type2))!=NULL)
					{
					lnd_rapnde(clst,convlist);
					convlist=clst;clst=NULL;
					if(type_cmp(tl->type,type1)) 
					/* if this is waht we want - well,
it IS dumb, but we need all this convertion stuff in case someone reloads one
of the default conversions */
						use_fun=convlist;
					else
						{
						tl->convert_lock=ON;
						use_fun=convert_type(typelist,type1,tl->type,convlist);
						tl->convert_lock=OFF;
						};
					};
				};
			if(use_fun!=NULL)
				{
				if((use_fun->attr==TYPEVARL)||(use_fun->attr==VARTYPEL))
					{
					if(clst==NULL)
						clst=use_fun;
					else
						lnd_rapnde(clst,use_fun);
					was_rec_flag=2; /* dynamic recursive conv */
					use_fun=NULL; /* to continue work */
					}
				else
					{
					if(clst!=NULL)
					/* if we have static types we don't need any dynamic */
						rm_lnd_all(clst); 
		
					clst=use_fun;
					was_rec_flag=1; /* recursive conv occured */
					break;
					};
				}
			tl=tl->next;
			};
		if(tl!=NULL)
			break;
		tll=tll->next;
		};
	};
if((convind==NULL)&(clst==NULL))
	return NULL;
if((convlist==use_fun)&(was_rec_flag==1))
	{/* do nothing at all */}
else if((convind!=NULL)&(clst==NULL)&(was_rec_flag!=2))
	convlist=mk_head_lnd(convlist,convind,FUNDEFNL);
else if((clst!=NULL)&(was_rec_flag==2))
	convlist=mk_head_lnd(convlist,clst,TYPEVARL);
else
	printf("# convert_type(): strange: convind==%lx,clst=%lx,was_rec_flag=%d\n",convind,clst,was_rec_flag);
convlist=convert_type_self_daemon(type2,convlist,1); /* OUT "daemon" convertion for type2 */
return convert_type_self_daemon(type1,convlist,0); /* IN "daemon" convertion for type1 */
};


listnode convlist_to_funcall(listnode convlist,listnode fn)
{
listnode l1,lptr;
char local_buf[34];

if(convlist==NULL)
  return fn;

memset(local_buf,0,33);
l1=mk_set_lnd(NULL,NULL,TWOLISTS);
lptr=l1;
while(convlist!=NULL)
  {
   if((convlist->attr!=TWOLISTS)&(convlist->attr!=VARTYPEL)&(convlist->attr!=TYPEVARL))
      {
	if(convlist->attr==FUNDEFNL) /* pointer to func defn */
		{
		lptr->data=(char PTR)mk_set_lnd(NULL,my_malloc(2+Strlen(((struct fundef PTR)convlist->data)->def_to_use.name_in_code)),FUNCTION);
		sprintf(local_buf,"\4_%s",((struct fundef PTR)convlist->data)->def_to_use.name_in_code);
		}
	else if(convlist->attr==FUNCTION) /* just function's NAME */
		lptr->data=(char PTR)mk_set_lnd(NULL,Strdup(convlist->data),FUNCTION);
	else
		fprintf(stderr,"convlist_to_funcall: some weird attr %d at convlist\n",convlist->attr);
	lptr=(listnode)lptr->data;
	if(convlist->attr==FUNDEFNL) 
		Strcpy(lptr->data,local_buf);
	lptr=mk_set_lnd(lptr,NULL,FUNCTION);
      }
    else if(convlist->attr==TWOLISTS)
      {
	lptr->data=(char PTR)mk_set_lnd(NULL,my_malloc(11),FUNCTION);
	lptr=(listnode)lptr->data;
	Strcpy(lptr->data,"\4_Bdef_conv");
	lptr=mk_set_lnd(lptr,NULL,FUNCTION);
      }
    else if(convlist->attr==TYPEVARL)
	{
	if(((listnode)convlist->data)->attr==TYPEVARL)
		{
		lptr->data=(char PTR)mk_set_lnd(NULL,NULL,FUNCTION);
		lptr=(listnode)lptr->data;
		lptr->data=Strdup("\4vartypeif");
		mk_set_lnd(lptr,(listnode)convlist->data,TYPEVARL);
		lptr=mk_set_lnd(lptr,NULL,FUNCTION);
		}
	else
		printf("# convlist_to_funcall():strange: strange attr %d at sublist of list with TYPEVARL(%d) attr\n",((listnode)convlist->data)->attr,TYPEVARL);
	} 
   else
      {
	lptr->data=(char PTR)mk_set_lnd(NULL,NULL,FUNCTION);
	lptr=(listnode)lptr->data;
	if(((listnode)convlist->data)->attr==VARTYPEL)
		{
		if(((listnode)convlist->data)->next->attr==VARTYPEL)
			lptr->data=Strdup("\4vartypevv");
		else
			lptr->data=Strdup("\4vartypetv");
		}
	else
		lptr->data=Strdup("\4vartypevt");
	lptr=mk_set_lnd(lptr,((listnode)convlist->data)->data,TYPEDEFN);
	lptr=mk_set_lnd(lptr,((listnode)convlist->data)->next->data,TYPEDEFN);
	lptr=mk_set_lnd(lptr,NULL,FUNCTION);
	convlist->data=NULL;
      };

    convlist=rm_cdr_next(convlist);
  };
lptr->data=fn->data;
lptr->attr=fn->attr;
fn->attr=TWOLISTS;
fn->data=l1->data;
Free(l1);
return fn;
};



struct vardecl_list PTR lookup_var_decl(char PTR name,struct vardecl_list PTR lst)
{
while(lst!=NULL)
	{
	if(lst->var!=NULL)
		if (!Strcmp(lst->var->name,name))
			break;
	lst=lst->next;
	};
return lst;
};

struct vardecl_list PTR global_find_var_decl(char PTR name, struct vardecl_listoflist PTR vars)
{
struct vardecl_list PTR l;
if(vars==NULL)
	return NULL;
for(l=lookup_var_decl(name,vars->vlist);(l==NULL)&(vars!=NULL);vars=vars->next)
	l=lookup_var_decl(name,vars->vlist);
return l;
};



struct vardecl_list PTR lookup_var_decl_attr(enum var_attr attr,struct vardecl_list PTR lst)
{
while(lst!=NULL)
	{
	if (lst->var->attr==attr)
		break;
	lst=lst->next;
	};
return lst;
};

struct vardecl_list PTR global_find_var_decl_attr(enum var_attr attr, struct vardecl_listoflist PTR vars)
{
struct vardecl_list PTR l;
for(l=lookup_var_decl_attr(attr,vars->vlist);(l==NULL)&(vars!=NULL);vars=vars->next)
	l=lookup_var_decl_attr(attr,vars->vlist);
return l;
};



struct vardecl_list PTR insert_var_decl(
struct vardecl_list PTR list,
char PTR name,
struct typerec PTR type,
void * defvalue,
int replace)
{
struct vardecl_list PTR l;
l=lookup_var_decl(name,list);
if(l!=NULL)
	if(replace)
		{
		l->var->type=type;
		l->var->defvalue=defvalue;
		return l;
		}
	else
		return NULL;
else
	{
	if(list!=NULL)
		{
		l=list->next;
		list->next=my_malloc(sizeof(struct vardecl_list));
		list->next->var=my_malloc(sizeof(struct var_decl));
		list->next->next=l;
		list=list->next;
		}
	else
		{
		list=my_malloc(sizeof(struct vardecl_list));
		list->var=my_malloc(sizeof(struct var_decl));
		list->next=NULL;
		};
	list->var->name=Strdup(name);
	list->var->type=type;
	list->var->defvalue=defvalue;
	return list;
	}
};
void type_var_decl_list(struct vardecl_list PTR lst)
{
while(lst!=NULL)
	{
	printf("Defined variable %s of type %s:%d\n",lst->var->name,lst->var->type->name,lst->var->type->typemodf);
	lst=lst->next;
	};
};


struct typerec PTR lookup_structure_part(char PTR name, struct typerec PTR type,struct type_listoflist PTR types)
{
if((type->typekind!=STRUCT)&(type->typekind!=CLASS)&(type->typekind!=ISMODIF)&(type->typekind!=MODIFARG))
	return NULL;

if(type->typekind==STRUCT)
	{
	struct vardecl_list PTR fieldind;
	for(fieldind=type->typebody.struct_def->fields;fieldind!=NULL;fieldind=fieldind->next)
		if(!Strcmp(fieldind->var->name,name))
			return fieldind->var->type;
	return NULL; /* if none found */
	}
else 	/* class/modif */
     {
	struct vardecl_list PTR varind=NULL;
	struct type_list PTR tl;
	struct typerec PTR type1;
	   
	if(type->typekind!=MODIFARG)
	  varind=lookup_var_decl(name,type->typebody.class_def->vars);

	if(varind==NULL)
	  {
	     struct type_listoflist tlst;
	  
	     if(type->typekind!=MODIFARG)
	       {
		  tlst.tlist=type->typebody.class_def->types;
		  tlst.next=types;		
	      
		  tl=type->typebody.class_def->top_class;
	       }
	     else
	       {
		  tl=type->typebody.class_list;
	       };
	     while(tl!=NULL)
	       if((type1=lookup_structure_part(name,tl->type,&tlst))!=NULL)
		 return type1;
	     else
	       tl=tl->next;
	     
	     return NULL;
	  };
	type1=varind->var->type;
	if(type1->typekind==MODIFARG)
	  {
	     printf("# Modifier arg type %s in class - looking up ...\n",type1->name);
	     
	     if((type1=get_type_by_name(type1->name,type1->typemodf,types))==NULL)
	       {
		  printf("# Resolved modifier arg type not found !\n",type1->name);
		  return NULL;
	       };
	  };
	
	return type1;
     };
};


struct typerec PTR lookup_class_func(
listnode fn,
struct typerec PTR type,
struct vardecl_listoflist PTR vars,
struct type_listoflist PTR types,
listnode labels)
{
struct vardecl_list PTR varind;
struct type_list PTR tl;
struct typerec PTR type1=NULL;
struct type_listoflist tlst;
listnode l=NULL;

while((type->typekind==TYPEREFR)&(type->typemodf==NONE))
	type=type->typebody.pointer_to;
if((type->typekind!=CLASS)&(type->typekind!=ISMODIF)&(type->typekind!=MODIFARG))
	return NULL;
if(type->typekind!=MODIFARG)
     {
	tlst.tlist=type->typebody.class_def->types;
	tlst.next=types;		

	printf("## Checking member function of class %s ...\n",type->name);
	l=mk_set_lnd(NULL,type->typebody.class_def->funcs,FUNCDEFN);
	mk_set_lnd(l,type->typebody.class_def->constructors,FUNCDEFN);
	mk_set_lnd(l,type->typebody.class_def->destructors,FUNCDEFN);

	type1=validate_function(fn,l,vars,(type->typekind==ISMODIF)?types:&tlst,labels,1);

	rm_lnd_all(l);
     }; /* if(type->typekind!=MODIFARG) */

   if(type1==NULL)
     {
	tl=(type->typekind==MODIFARG)?type->typebody.class_list:type->typebody.class_def->top_class;
	
	while(tl!=NULL)
	  if((type1=lookup_class_func(fn,tl->type,vars,(type->typekind==CLASS)?&tlst:types,labels))!=NULL)
	    return type1;
	else
	  tl=tl->next;
	
	return NULL;
     };

   return type1;
};


struct vardecl_list PTR copy_vardecl_list(struct vardecl_list PTR vlst)
{
struct vardecl_list PTR res, PTR vl;

if(vlst==NULL)
	return NULL;

res=my_malloc(sizeof(struct vardecl_list));

if(vlst->var==NULL)
	res->var=NULL;
else
	{
	res->var=my_malloc(sizeof(struct var_decl));
	res->var->name=vlst->var->name;
	res->var->type=vlst->var->type;
	};

res->next=vlst->next;

vlst=vlst->next;
vl=res;

while(vlst!=NULL)
	{

	vl->next=my_malloc(sizeof(struct vardecl_list));
	vl=vl->next;

	if(vlst->var==NULL)
		vl->var=NULL;
	else
		{
		vl->var=my_malloc(sizeof(struct var_decl));
		vl->var->name=vlst->var->name;
		vl->var->type=vlst->var->type;
		};

	vlst=vlst->next;

	};

return res;
};

void destroy_vardecl_list(struct vardecl_list PTR vlst)
{
struct vardecl_list PTR vl;

while(vlst!=NULL)
	{
	if(vlst->var!=NULL)
		Free(vlst->var);
	vl=vlst->next;
	Free(vlst);
	vlst=vl;
	};
};


struct typerec PTR validate_function(listnode fn, listnode fnlist,struct vardecl_listoflist PTR vars,struct type_listoflist PTR types,listnode labels, int mode)
/* mode: 0-normal,1-silent,2-just verify */
{
listnode l,typeconv,lptr;
struct vardecl_list PTR vl;
struct typerec PTR part_type,PTR type1;
char local_buf[33];

if(fn==NULL)
	return NULL;

if(fn->attr!=FUNCTION)
	return NULL;

if ((*fn->data==4)&(fn->data[1]!='_'))
	{
	if(!Strcmp(fn->data,"\4objpart"))
		{
		if(fn->next!=NULL)
			{
			if(fn->next->attr==TWOLISTS)
				{
				printf("## Complex object, verifying ...\n");
				type1=validate_function((listnode)fn->next->data,fnlist,vars,types,labels,mode);
				if(type1==NULL)
					{
					if (!mode)
						printf("Problem with complex type !!!\n");
					return NULL;
					};
				}
			else if(fn->next->attr==TYPEDEFN)
				type1=(struct typerec PTR)fn->next->data;
			else
			  {
			    vl=global_find_var_decl(fn->next->data,vars);

			    if(vl==NULL)
			      {
				if (!mode)
				  fprintf(stderr,"Undefined variable %s\n",fn->next->data);
				return NULL;
			      }
			    else
			      type1=vl->var->type;
			  };
			}
		else
		  {
		    if (!mode)
		      fprintf(stderr,"Undefined variable %s\n",fn->next->data);
		    return NULL;
		  };

		type1=eval_type_refr(type1,fnlist,vars,types,labels,1);


		/* If not "typeof" - just return the same type */

		switch(type1->typekind)
			{
			case STRUCT:
/*			case UNION : */

			if(fn->next->next->attr==TWOLISTS)
				{
				if (!mode)
					fprintf(stderr,"Non-class %s doesn't have member functions\n",type1->name);
				return NULL;
				};

			case CLASS :    /* trick - no break */
			case MODIFARG:
			if(fn->next->next->attr==TWOLISTS)
				{
				struct typerec PTR type2;

				/*
				printf("## Checking member function of class %s ...\n",type1->name);

				l=mk_set_lnd(NULL,type1->typebody.class_def->funcs,FUNCDEFN);
				mk_set_lnd(l,type1->typebody.class_def->constructors,FUNCDEFN);
				mk_set_lnd(l,type1->typebody.class_def->destructors,FUNCDEFN);

				type2=validate_function((listnode)fn->next->next->data,l,vars,types,labels);

				rm_lnd_all(l);
				*/
				type2=lookup_class_func((listnode)fn->next->next->data,type1,vars,types,labels);

				if(type2==NULL)
					if (!mode)
						printf("Problem with member function %s at class %s\n",((listnode)fn->next->next->data)->data,type1->name);

				return type2;
				};

				part_type=lookup_structure_part(fn->next->next->data,type1,types);

				if(part_type==NULL)
				{
				if (!mode)
					fprintf(stderr,"%s doesn't have member %s\n",fn->next->data,fn->next->next->data);
				return NULL;
				};

				return part_type;

			default: if (!mode)
					fprintf(stderr,"Variable %s is not structured !\n",fn->next->data);
				 return NULL;
			};
		};

	if(!Strcmp(fn->data,"\4anchestor"))
		{
		if(fn->next->next->attr!=TYPEDEFN)
			printf("validate_function():in \4anchestor:\nfn->next->next->attr = %d != TYPEDEFN !!!\n",fn->next->next->attr);
		printf("#### Ok, seems that we need ancestor of type %s for var %s\n",((struct typerec PTR)fn->next->next->data)->name,fn->next->data);
		return (struct typerec PTR)fn->next->next->data;
		};
	if(!Strcmp(fn->data,"\4lambda"))
		{
		if(fn->next->next->attr!=TYPEDEFN)
			printf("validate_function():in \4lambda:\nfn->next->next->attr = %d != TYPEDEFN !!!\n",fn->next->next->attr);
		printf("#### Ok, seems that we have lambda of type %s returning %s\n",((struct typerec PTR)fn->next->next->data)->name,((struct typerec PTR)fn->next->next->data)->typebody.actionclass->res_type->name);
		return (struct typerec PTR)fn->next->next->data;
		};
	if(!Strcmp(fn->data,"\4typeadjust"))
		{
		if((fn->next==NULL)
		||(fn->next->attr!=TYPEDEFN)
		||(fn->next->next==NULL))
			{
			printf("## !!! Possibly internal problem with type adjusting !!!\n");
			return NULL;
			};

		type1=(struct typerec PTR) fn->next->data;

		if(fn->next->next->attr==TWOLISTS) /* Not variable */
 			{
			l=(listnode)fn->next->next->data;
			if(validate_function(l,fnlist,vars,types,labels,mode)==NULL)
				return NULL;

			if(mode!=2) /* if we can replace it - just replace */
				Free(fn->next->next);
			}
		else
			l=fn->next->next;

		if(mode!=2) /* if we can - free listnodes */
			{
			Free(fn->next);

			fn->attr=l->attr;
			fn->data=l->data;
			fn->next=l->next;

			Free(l);
			};

		return type1;

		};

	if(!Strcmp(fn->data,"\4sizeof_T"))
		{
		if((fn->next==NULL)||(fn->next->attr!=TYPEDEFN))
			{
			printf("## !!! Possibly internal problem with sizeof validating !!!\n");
			return NULL;
			};
		type1=eval_type_refr((struct typerec PTR) fn->next->data,fnlist,vars,types,labels,0);
		if(type1==NULL)
			return NULL;
		rm_lnd_all(fn->next);
		Free(fn->data);
		fn->next=NULL;
		fn->attr=VARIABLE;
		sprintf(local_buf,"%d",type1->size);
		fn->data=Strdup(local_buf);
		return get_type_by_name("int",NONE,types);
		};

	if(!Strcmp(fn->data,"\4sizeof_V"))
		{
		if((fn->next==NULL)||(fn->next->attr!=VARIABLE))
			{
			printf("## !!! Possibly internal problem with sizeof validating !!!\n");
			return NULL;
			};

		vl=global_find_var_decl(fn->next->data,vars);
		if(vl==NULL)
			return NULL;
		type1=eval_type_refr(vl->var->type,fnlist,vars,types,labels,0);
		if(type1==NULL)
			return NULL;
		rm_lnd_all(fn->next);
		Free(fn->data);
		fn->next=NULL;
		fn->attr=VARIABLE;
		sprintf(local_buf,"%d",type1->size);
		fn->data=Strdup(local_buf);
		return get_type_by_name("int",NONE,types);
		};

/*	printf("# Can't validate special function %s \n",fn->data); */
	return (struct typerec PTR) &validate_function;
	};

for(l=fnlist;l!=NULL;l=l->next)
	{
	struct fundef_list PTR flind;
	struct vardecl_list PTR args, PTR argscopy;
	struct vardecl_listoflist argsvarll;
	listnode l1;

	if(l->attr!=FUNCDEFN)
		{
		printf("### !!! Strange ... Might be internal problem in function list !!!\n");
		continue;
		}
	flind=(struct fundef_list PTR) l->data;
	while(flind!=NULL)
		{
		if(flind->fundef==NULL)
			break;
		if(!Strcmp(flind->fundef->name,fn->data))
			break;
		flind=flind->next;
		};
	if(flind==NULL)
		continue;

	while(flind!=NULL)
		{
		if(flind->fundef==NULL)
			break;
		if(Strcmp(flind->fundef->name,fn->data))
			{
			flind=flind->next;
			continue;
			};
		argscopy=copy_vardecl_list(flind->fundef->args);
		for(l1=fn->next,args=argscopy;(args!=NULL)&(l1!=NULL);args=args->next,l1=l1->next)
			{
			struct typerec PTR argt,PTR argstype;


			if(l1->attr!=TWOLISTS)
				{
				if(*l1->data==4)
					continue;

				if(!isnum(*l1->data))
					{
					vl=global_find_var_decl(l1->data,vars);

					if(vl==NULL)
						break;
					if(vl->var==NULL)
						break;
					argt=vl->var->type;
					}
				else
					argt=get_type_by_name("int",NONE,types);
				}
			else
				argt=validate_function((listnode)l1->data,fnlist,vars,types,labels,mode);

			if(argt==NULL)
				break;
			if(argt==(struct typerec PTR) &validate_function)
				continue;

			argstype=args->var->type;

			argt=eval_type_refr(argt,fnlist,vars,types,labels,1);  /* "binding" (?!?) */

			argsvarll.next=NULL;
			argsvarll.vlist=argscopy;

			if(argstype->typekind==MODIFARG)
				{
				printf("# Modifier arg type %s - looking up ...\n",argstype->name);
				if((argstype=get_type_by_name(argstype->name,argstype->typemodf,types))==NULL)
					{
					printf("# Resolved modifier arg type not found !\n",argstype->name);
					return NULL;
					};
				};
			if(argt->typekind==MODIFARG)
				{
				printf("# Modifier arg type %s - looking up ...\n",argstype->name);
				if((argt=get_type_by_name(argt->name,argt->typemodf,types))==NULL)
					{
					printf("# Resolved modifier arg type not found !\n",argstype->name);
					return NULL;
					};
				};
			
			argstype=eval_type_refr(argstype,fnlist,&argsvarll /*vars*/,types,labels,2);

			while((argt->typekind==TYPEREFR)&(argt->typemodf==NONE||argt->typemodf==MODIFARG))
				argt=argt->typebody.pointer_to;

			while((argstype->typekind==TYPEREFR)&(argstype->typemodf==NONE||argstype->typemodf==MODIFARG))
				argstype=argstype->typebody.pointer_to;

			if(!type_cmp(argt,argstype))
				break;
			else
				l1=convlist_to_funcall(convert_type_self_daemon(argt,convert_type_self_daemon(argstype,NULL,1),0),l1);
			};

		destroy_vardecl_list(argscopy);

		if(args==NULL)
			{
			if(l1==NULL)
				{
				if(mode!=2) /* if we allowed to substitute the name with the name in code */
					{
					if(flind->fundef->kind==is_inline)
						{
						Free(fn->data);	
						fn->data=Strdup("\4run_inline");
						fn->next=mk_head_lnd(fn->next,flind->fundef,FUNCDEFN);
						}
					else
						{
						Free(fn->data);
						fn->data=Strdup(flind->fundef->def_to_use.name_in_code);
						};
					};

				argsvarll.next=NULL;
				argsvarll.vlist=flind->fundef->args;
				return eval_type_refr(flind->fundef->res_type,fnlist,&argsvarll /*vars*/,types,labels,0);
				};
			if(flind->fundef->attr==IS_FEXPR)
				{
				while(l1!=NULL)
					{
					if(l1->attr==TWOLISTS)
						{
						if(validate_function((listnode)l1->data,fnlist,vars,types,labels,mode)==NULL)
							break;
						}
					else
						if(global_find_var_decl(l1->data,vars)==NULL)
							break;
					l1=l1->next;
					};

				if(l1==NULL)
					{
					if(mode!=2) /* if we allowed to substitute the name with the name in code */
						{
						if(flind->fundef->kind==is_inline)
							{
							Free(fn->data);	
							fn->data=Strdup("\4run_inline");
							fn->next=mk_head_lnd(fn->next,flind->fundef,FUNCDEFN);
							}
						else
							{
							Free(fn->data);
							fn->data=Strdup(flind->fundef->def_to_use.name_in_code);
							};
						};
					argsvarll.next=NULL;
					argsvarll.vlist=flind->fundef->args;
					return eval_type_refr(flind->fundef->res_type,fnlist,&argsvarll /*vars*/,types,labels,0);
					};
				};
			};

		flind=flind->next; /* arguments left, which means something wrong */
		};
	};
for(l=fnlist;l!=NULL;l=l->next)
	{
	struct fundef_list PTR flind;
	struct vardecl_list PTR args, PTR argscopy;
	struct vardecl_listoflist argsvarll;
	listnode l1;

	if(l->attr!=FUNCDEFN)
		{
		printf("### !!! Strange ... Might be internal problem in function list !!!\n");
		continue;
		}
	flind=(struct fundef_list PTR) l->data;
	while(flind!=NULL)
		{
		if(flind->fundef==NULL)
			break;
		if(!Strcmp(flind->fundef->name,fn->data))
			break;
		flind=flind->next;
		};
	if(flind==NULL)
		continue;

	while(flind!=NULL)
		{
		if(flind->fundef==NULL)
			break;
		if(Strcmp(flind->fundef->name,fn->data))
			{
			flind=flind->next;
			continue;
			};
		argscopy=copy_vardecl_list(flind->fundef->args);
		for(l1=fn->next,args=argscopy;(args!=NULL)&(l1!=NULL);args=args->next,l1=l1->next)
			{
			struct typerec PTR argt,PTR argstype;
			listnode l4;


			if(l1->attr!=TWOLISTS)
				{
				if(*l1->data==4)
					continue;

				if(!isnum(*l1->data))
					{
					vl=global_find_var_decl(l1->data,vars);

					if(vl==NULL)
						break;
					if(vl->var==NULL)
						break;
					argt=vl->var->type;
					}
				else
					argt=get_type_by_name("int",NONE,types);
				}
			else
				argt=validate_function((listnode)l1->data,fnlist,vars,types,labels,mode);

			if(argt==NULL)
				break;
			if(argt==(struct typerec PTR) &validate_function)
				continue;

			argstype=args->var->type;

			argt=eval_type_refr(argt,fnlist,vars,types,labels,1);  /* "binding" (?!?) */

			argsvarll.next=NULL;
			argsvarll.vlist=argscopy;

			if(argstype->typekind==MODIFARG)
				{
				printf("# Modifier arg type %s - looking up ...\n",argstype->name);
				if((argstype=get_type_by_name(argstype->name,argstype->typemodf,types))==NULL)
					{
					printf("# Resolved modifier arg type not found !\n",argstype->name);
					return NULL;
					};
				};
			if(argt->typekind==MODIFARG)
				{
				printf("# Modifier arg type %s - looking up ...\n",argstype->name);
				if((argt=get_type_by_name(argt->name,argt->typemodf,types))==NULL)
					{
					printf("# Resolved modifier arg type not found !\n",argstype->name);
					return NULL;
					};
				};
			
			argstype=eval_type_refr(argstype,fnlist,&argsvarll /*vars*/,types,labels,2);

			while((argt->typekind==TYPEREFR)&(argt->typemodf==NONE||argt->typemodf==MODIFARG))
				argt=argt->typebody.pointer_to;

			while((argstype->typekind==TYPEREFR)&(argstype->typemodf==NONE||argstype->typemodf==MODIFARG))
				argstype=argstype->typebody.pointer_to;

			if((typeconv=convert_type(types,argt,argstype,NULL))==NULL)
				break;

			if(mode==2) /* if its only testing */
				rm_lnd_all(typeconv);
			else	/* substitution */
				l1=(convlist_to_funcall(typeconv,l1));
			};

		destroy_vardecl_list(argscopy);

		if(args==NULL)
			{
			if(l1==NULL)
				{
				if(mode!=2) /* if we allowed to substitute the name with the name in code */
					{
					if(flind->fundef->kind==is_inline)
						{
						Free(fn->data);	
						fn->data=Strdup("\4run_inline");
						fn->next=mk_head_lnd(fn->next,flind->fundef,FUNCDEFN);
						}
					else
						{
						Free(fn->data);
						fn->data=Strdup(flind->fundef->def_to_use.name_in_code);
						};
					};

				argsvarll.next=NULL;
				argsvarll.vlist=flind->fundef->args;
				return eval_type_refr(flind->fundef->res_type,fnlist,&argsvarll /*vars*/,types,labels,0);
				};
			if(flind->fundef->attr==IS_FEXPR)
				{
				while(l1!=NULL)
					{
					if(l1->attr==TWOLISTS)
						{
						if(validate_function((listnode)l1->data,fnlist,vars,types,labels,mode)==NULL)
							break;
						}
					else
						if(global_find_var_decl(l1->data,vars)==NULL)
							break;
					l1=l1->next;
					};

				if(l1==NULL)
					{
					if(mode!=2) /* if we allowed to substitute the name with the name in code */
						{
						if(flind->fundef->kind==is_inline)
							{
							Free(fn->data);	
							fn->data=Strdup("\4run_inline");
							fn->next=mk_head_lnd(fn->next,flind->fundef,FUNCDEFN);
							}
						else
							{
							Free(fn->data);
							fn->data=Strdup(flind->fundef->def_to_use.name_in_code);
							};
						};
					argsvarll.next=NULL;
					argsvarll.vlist=flind->fundef->args;
					return eval_type_refr(flind->fundef->res_type,fnlist,&argsvarll /*vars*/,types,labels,0);
					};
				};
			};

		flind=flind->next; /* arguments left, which means something wrong */
		};
	};

if (!mode)
	printf("Problem with function %s\n",fn->data);
return NULL;
};

