#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((t1->typemodf==t2->typemodf)
      &((t1->typemodf==POINTER)
	||(t1->typemodf==REFERENCE)
	||(t1->typemodf==INDEX)))
     {
	if(t1->typemodf==INDEX)
	  {
	     if(t1->typebody.index.size!=t2->typebody.index.size)
	       printf("Warning: different array dimensions\n");
	     else if(memcmp(t1->typebody.index.dims,t2->typebody.index.dims,t1->typebody.index.size))
	       printf("Warning: different array dimensions\n");
	     return type_cmp(t1->typebody.index.pointer_to,t2->typebody.index.pointer_to);
	  }
	else
	  return type_cmp(t1->typebody.pointer_to,t2->typebody.pointer_to);
     }
   else
     {
	if(!Strcmp(t1->name,t2->name))
	  /* different modifiers -> no match */
	  return (t1->typemodf==t2->typemodf);
	else
	  /* different names -> no match */
	  return 0; 
     };
}





struct typerec * mk_type_from_arr(
char * instr,
struct typerec * type,
struct type_listoflist * tll,
int * change)
{
  char * str;
  listnode arrdims=NULL;
  char numbuff[10],local_buf[34];
  int size=0, * dims,dptr=0;
  struct type_list PTR tl;

  if((type==NULL)||(change==NULL))
    return type;

  *change=0;
  str=instr;

  while(*str==' ') str++;
  if(*str!='[')
    return type;
	
  str++;
  while(*str==' ') str++;
  *change+=str-instr;
  instr=str;
  while((*str!=']')&(*str!=0))
    {
      memset(numbuff,0,sizeof(numbuff));
      while(isnum(*str)) str++;
      if(str==instr)
	{
	  printf("# Strange, empty array: %s\n",str);
	  return NULL;
	};
      strncpy(numbuff,instr,str-instr);
      arrdims=mk_head_lnd(arrdims,(char*)atoi(numbuff),PARTOFOP);
      size++;
      while(*str==' ') str++;
      if(*str==',')
	{
	  str++;
	  while(*str==' ') str++;
	  *change+=str-instr;
	  instr=str;
	};
    };
  if(*str!=']')
    return NULL;
  str++;
  while(*str==' ') str++;
  *change+=str-instr;
  instr=str;

  dims=my_malloc(sizeof(int)*size);
  arrdims=lnd_reverse_r(arrdims);
  while(arrdims!=NULL)
    {
      dims[dptr]=(int)arrdims->data;
      arrdims=rm_cdr_next(arrdims);
      dptr++;
    };

  memset(local_buf,0,sizeof(local_buf));
  global_tmp_type++;
  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,4,Strdup(local_buf),TYPEREFR,INDEX,__void__,NULL);
      global_type_id_count++;
      tl=tll->tlist;
      tl->type->typeid=global_type_id_count;
    }
  else
    tl=install_type(tll->tlist,4,Strdup(local_buf),TYPEREFR,INDEX,__void__,NULL);
 
  tl->type->typebody.index.pointer_to=type;
  tl->type->typebody.index.size=size;
  tl->type->typebody.index.dims=dims;

  return tl->type;
}










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 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;
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,listnode valids)
{
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))
    {
      if((valids!=NULL)&(type->validate!=NULL))
	{
	  mk_set_lnd(valids,(char *)mk_head_lnd(copylist(type->validate),strdup(type->name),ASSOCVAR),TWOLISTS);
	};
      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,valids);
      
      if((valids!=NULL)&(type->typebody.pointer_to!=NULL))
	{
	  if(type->typebody.pointer_to->validate!=NULL)
	    mk_set_lnd(valids,(char *)mk_head_lnd(copylist(type->typebody.pointer_to->validate),strdup(type->typebody.pointer_to->name),ASSOCVAR),TWOLISTS);
	};
      
      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,0);
      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((valids!=NULL)&(type->validate!=NULL))
    {
      mk_set_lnd(valids,(char *)mk_head_lnd(copylist(type->validate),strdup(type->name),ASSOCVAR),TWOLISTS);
    };

  if(bind==0)
    return eval_type_refr(type,fnlist,vars,types,labels,0,valids);/* 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,"\4tmptype%lx",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,
struct type_listoflist * types
)
{
   if((type1==NULL)||(type2==NULL))
     return NULL;
   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)
      &(type_cmp(type1->typebody.pointer_to,type2->typebody.index.pointer_to)))
     {
	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((type2->typemodf==POINTER)
      &(type1->typemodf==INDEX)
      &(type_cmp(type2->typebody.pointer_to,type1->typebody.index.pointer_to)))
     {
	printf("# Converting pointer index of type %s to pointer to type %s\n",type1->name,type2->name);
	return mk_set_lnd(NULL,"\4_Bstdind2ptrconv",FUNCTION);
     };
   
   if((type1->typemodf==POINTER) & (type2->typemodf==POINTER))
     {	if(type_cmp(type1->typebody.pointer_to,get_type_by_name("void",NONE,types)))
	  {
	     printf("# Representing void * as %s * \n",type2->name);
	     return mk_set_lnd(NULL,"\4_Bstdvoidconv",FUNCTION);
	  };
	if(type_cmp(type2->typebody.pointer_to,get_type_by_name("void",NONE,types)))
	  {
	     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;
   
   if((clst=convert_type_special(type1,type2,typelist))!=NULL)
     {
	lnd_rapnde(clst,convlist);
	return clst;
     };

   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 (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,typelist))!=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,typelist))!=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,typelist))!=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,typelist))!=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",(long unsigned int)convind,(long unsigned int)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,int mode)
/* mode: 0 to find only variable declarations, 1 to find functions too */
{
   while(lst!=NULL)
     {
	if(lst->var!=NULL)
	  {
	     if (!Strcmp(lst->var->name,name))
	       {
		  if(mode==0)
		    {
		       if((lst->var->attr!=FN_VAR)&(lst->var->attr!=VFN_VAR))
			 break;
		    }
		  else
		    break;
	       };
	  };
	lst=lst->next;
     };
   return lst;
}

struct vardecl_list PTR global_find_var_decl(char PTR name, struct vardecl_listoflist PTR vars,int mode)
/* mode: 0 to find only variable declarations, 1 to find functions too */
{
   struct vardecl_list PTR l;
   if(vars==NULL)
     return NULL;
   for(l=lookup_var_decl(name,vars->vlist,mode);(l==NULL)&(vars!=NULL);vars=vars->next)
     l=lookup_var_decl(name,vars->vlist,mode);
   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)
/* replace: 0 - don't replace, 1 - replace vars,2 - add funcs without replacing,3 - replace funcs */
{
   struct vardecl_list PTR l;
   l=lookup_var_decl(name,list,replace>=2);
   if((l!=NULL)&(replace!=2))
     {
	if(replace)
	  {
	     if(((l->var->attr==FN_VAR)||(l->var->attr==VFN_VAR))&(replace!=3))
	       return NULL;
	     l->var->type=type;
	     l->var->var_data.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->var_data.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,0);

	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 %s 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 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 
 3,4,5 - "shifted" mode in case of dynamic type */
{
  listnode l,typeconv,nfn,vtargs=NULL,valids=NULL;
   struct vardecl_list PTR vl;
   struct typerec PTR part_type,PTR type1,PTR res=NULL;
   char local_buf[33];
   int l_dt_flag=0;
   listnode fn_orig=NULL; /* to keep fn's name, since we are replacing fn sometimes */
   
   nfn=fn; 
   /* nfn is used as additional index just in case of dyn type */
   
   if(fn==NULL)
     return NULL;
   
   if(fn->attr!=FUNCTION)
     return NULL;
   
   if ((*fn->data==4)&(fn->data[1]!='_'))
     {
	if(mode>2)
	  mode-=3;
	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 if(!strcmp(fn->next->data,"META"))
		    {
		      printf("# META %s %s\n",(fn->next->next->attr==TWOLISTS)?"function":"variable",fn->next->next->data);
		      return (struct typerec *) &validate_function;
		    }
		  else
		    {
		       vl=global_find_var_decl(fn->next->data,vars,0);
		       
		       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,NULL);
	     
	     
	     /* 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,NULL);
	     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,1);
	     if(vl==NULL)
	       return NULL;
	     type1=eval_type_refr(vl->var->type,fnlist,vars,types,labels,0,NULL);
	     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;
     };
   

   valids=mk_set_lnd(NULL,NULL,PARTOFOP);
   fn_orig=fn;
   

   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)
	     continue;
	   if(!Strcmp(flind->fundef->name,fn_orig->data))
	     break;
	   if(flind==NULL)
	     continue;
	   
	   while(flind!=NULL)
	     {
	       if(flind->fundef==NULL)
		 break;
	       if(Strcmp(flind->fundef->name,fn_orig->data))
		 {
		   flind=flind->next;
		   continue;
		 };
	       argscopy=copy_vardecl_list(flind->fundef->args);
	       vtargs=NULL;
	       
	       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
		 {
		   nfn=lnd_cdre(nfn);
		   nfn->next=mk_head_lnd(mk_head_lnd(NULL,copylist(fn_orig),TWOLISTS),Strdup("\4vartypetry"),FUNCTION);   
		   l1=((listnode)nfn->next->next->data)->next;
		 }
	       else
		 l1=fn->next;
	       
	       for(args=argscopy;(args!=NULL)&(l1!=NULL);args=args->next,l1=l1->next)
		 {
		   struct typerec PTR argt,PTR argstype;
		   
		   l_dt_flag=0;

		   if(l1->attr==FUNCTION)
		     /* one argument only, being a function call */
		     {
		       /* create a "branch" of a list to make it standart form of call*/
		       l1->data=(char *)mk_head_lnd(l1->next,l1->data,l1->attr);
		       l1->attr=TWOLISTS;
		       l1->next=NULL;
		     };

		   if(l1->attr!=TWOLISTS)
		     {
		       if(*l1->data==4)
			 continue;
		       
		       if(!isnum(*l1->data))
			 {
			   vl=global_find_var_decl(l1->data,vars,1);
			   
			   if(vl==NULL)
			     break;
			   if(vl->var==NULL)
			     {
			       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
				 rm_listnode(nfn); /* remove nfn->next tree */
			       l_dt_flag=2; /* special value for error */ 
			       break;
			     };
			   argt=vl->var->type;
			 }
		       else
			 argt=get_type_by_name("int",NONE,types);
		     }
		   else
		     {
		       if(!Strcmp(((listnode)l1->data)->data,"\4vartypearg"))
			 {
			   if(*((listnode)l1->data)->next->next->next->data==4)
			     continue;
			   
			   if(!isnum(*((listnode)l1->data)->next->next->next->data))
			     {
			       vl=global_find_var_decl(((listnode)l1->data)->next->next->next->data,vars,1);
			       
			       if(vl==NULL)
				 break;
			       if(vl->var==NULL)
				 {
				   if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
				     rm_listnode(nfn); /* remove nfn->next tree */
				   l_dt_flag=2; /* special value for error */ 
				   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>2)?mode-3:mode);
		     };
		   
		   if(argt==NULL)
		     {
		       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
			 rm_listnode(nfn); /* remove nfn->next tree */
		       l_dt_flag=2; /* special value for error */ 
		       break;
		     };
		   if(argt==(struct typerec PTR) &validate_function)
		     continue;
		   
		   argstype=args->var->type;
		   
		   argt=eval_type_refr(argt,fnlist,vars,types,labels,1,NULL);  /* "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 %s not found !\n",argstype->name);
			   rm_lnd_all(valids);
			   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 %s not found !\n",argstype->name);
			   rm_lnd_all(valids);
			   return NULL;
			 };
		     };
		   
		   argstype=eval_type_refr(argstype,fnlist,&argsvarll /*vars*/,types,labels,2,valids);
		   
		   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))
		     {
		       if(argstype->validate!=NULL)
			 {
			   mk_set_lnd(valids,(char *)mk_head_lnd(copylist(argstype->validate),strdup(argstype->name),ASSOCVAR),TWOLISTS);
			 };
		       argstype=argstype->typebody.pointer_to;
		     };
		   if((!type_cmp(argt,argstype))||(valids->next!=NULL)||(argt->typekind==VAR_TYPE))
		     {
		       rm_listnode(valids);
		       /*clean everything except dummy first node*/
		       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
			 rm_listnode(nfn); /* remove nfn->next tree */
		       l_dt_flag=2; /* special value for error */ 
		       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((!l_dt_flag)&(mode>2))
		 /* if l_dt_flag==0 it means that on this function there was 
		    no  dynamic types involved */
		 {
		   if(fn!=fn_orig)
		     nfn=nfn->next;
		   mode-=3;
		 };
	       
	       if((mode>2)&(l_dt_flag!=2))
		 {
		   if(Strcmp(nfn->data,"\4vartypetry"))
		     {
		       nfn=mk_head_lnd(mk_head_lnd(NULL,copylist(nfn),TWOLISTS),Strdup("\4vartypetry"),FUNCTION);
		       rm_listnode(fn);
		       free(fn->data);
		       *fn=*nfn;
		       free(nfn);
		       nfn=fn;
		     }
		   else
		     nfn=nfn->next;
		 };
	       
	       
	       if(args==NULL)
		 {
		   res=flind->fundef->res_type;
		   if(l1==NULL)
		     {
		       if((mode!=2)&(mode!=5)) /* if we allowed to substitute the name with the name in code */
			 {
			   if(flind->fundef->kind==is_inline)
			     {
			       if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				 {
				   Free(((listnode)nfn->next->data)->data);
				   ((listnode)nfn->next->data)->data=Strdup("\4run_inline");
				   ((listnode)nfn->next->data)->next=mk_head_lnd(((listnode)nfn->next->data)->next,flind->fundef,FUNCDEFN);
				 }
			       else
				 {
				   Free(nfn->data);	
				   nfn->data=Strdup("\4run_inline");
				   nfn->next=mk_head_lnd(nfn->next,flind->fundef,FUNCDEFN);
				 };
			     }
			   else
			     {
			       if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				 {
				   Free(((listnode)nfn->next->data)->data);
				   ((listnode)nfn->next->data)->data=Strdup(flind->fundef->def_to_use.name_in_code);
				 }
			       else
				 {
				   Free(nfn->data);
				   nfn->data=Strdup(flind->fundef->def_to_use.name_in_code);
				 };
			     };
			 };
		       
		       argsvarll.next=NULL;
		       argsvarll.vlist=flind->fundef->args;
		       if(mode<3)
			 {
			   if(fn_orig!=fn)
			     rm_lnd_all(fn_orig);
			   rm_lnd_all(valids);
			   return eval_type_refr(res,fnlist,&argsvarll /*vars*/,types,labels,0,NULL);
			 };
		     };
		   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,1)==NULL)
			       break;
			   l1=l1->next;
			 };
		       
		       if(l1==NULL)
			 {
			   res=flind->fundef->res_type;
			   if((mode!=2)&(mode!=5)) /* if we allowed to substitute the name with the name in code */
			     {
			       if(flind->fundef->kind==is_inline)
				 {
				   if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				     {
				       Free(((listnode)nfn->next->data)->data);
				       ((listnode)nfn->next->data)->data=Strdup("\4run_inline");
				       ((listnode)nfn->next->data)->next=mk_head_lnd(((listnode)nfn->next->data)->next,flind->fundef,FUNCDEFN);
				     }
				   else
				     {
				       Free(nfn->data);	
				       nfn->data=Strdup("\4run_inline");
				       nfn->next=mk_head_lnd(nfn->next,flind->fundef,FUNCDEFN);
				     };
				 }
			       else
				 {
				   if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				     {
				       Free(((listnode)nfn->next->data)->data);
				       ((listnode)nfn->next->data)->data=Strdup(flind->fundef->def_to_use.name_in_code);
				     }
				   else
				     {
				       Free(nfn->data);
				       nfn->data=Strdup(flind->fundef->def_to_use.name_in_code);
				     };
				 };
			     };
			   
			   argsvarll.next=NULL;
			   argsvarll.vlist=flind->fundef->args;
			   if(mode<3)
			     {
			       if(fn_orig!=fn)
				 rm_lnd_all(fn_orig); 
			       rm_lnd_all(valids);
			       return eval_type_refr(res,fnlist,&argsvarll /*vars*/,types,labels,0,NULL);
			     };
			 };
		     };
		 };
	       
	       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_orig->data))
	       break;
	     flind=flind->next;
	  };
	if(flind==NULL)
	  continue;
	
	while(flind!=NULL)
	  {
	     if(flind->fundef==NULL)
	       break;
	     if(Strcmp(flind->fundef->name,fn_orig->data))
	       {
		  flind=flind->next;
		  continue;
	       };
	     argscopy=copy_vardecl_list(flind->fundef->args);
	     vtargs=NULL;
	     
	     if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
	        {
		   nfn=lnd_cdre(nfn);
		   nfn->next=mk_head_lnd(mk_head_lnd(NULL,copylist(fn_orig),TWOLISTS),Strdup((l_dt_flag==3)?"\4tryvalid":"\4vartypetry"),FUNCTION);   
		   l1=((listnode)nfn->next->next->data)->next;
		}
	     else
	       l1=fn->next;

	     for(args=argscopy;(args!=NULL)&(l1!=NULL);args=args->next,l1=l1->next)
	       {
		  struct typerec PTR argt,PTR argstype;
		  
		  l_dt_flag=0;		  		  

		  if(l1->attr==FUNCTION)
		    /* one argument only, being a function call */
		    {
		      /* create a "branch" of a list to make it standart form of call*/
		      l1->data=(char *)mk_head_lnd(l1->next,l1->data,l1->attr);
		      l1->attr=TWOLISTS;
		      l1->next=NULL;
		    };
		  
		  if(l1->attr!=TWOLISTS)
		    {
		       if(*l1->data==4)
			 continue;
		       
		       if(!isnum(*l1->data))
			 {
			    vl=global_find_var_decl(l1->data,vars,1);
			    
			    if(vl==NULL)
			      {
				 if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
				   rm_listnode(nfn);
				 l_dt_flag=2;
				 break;
			      };
			    if(vl->var==NULL)
			      {
				 if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
				   rm_listnode(nfn);
				 l_dt_flag=2;
				 break;
			      };
			    argt=vl->var->type;
			 }
		       else
			 argt=get_type_by_name("int",NONE,types);
		    }
		  else
		    {
		       if(!Strcmp(((listnode)l1->data)->data,"\4vartypearg"))
			 {
			    if(*((listnode)l1->data)->next->next->next->data==4)
			      continue;
			    
			    if(!isnum(*((listnode)l1->data)->next->next->next->data))
			      {
				 vl=global_find_var_decl(((listnode)l1->data)->next->next->next->data,vars,1);
				 
				 if(vl==NULL)
				   break;
				 if(vl->var==NULL)
				   {
				      if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
					rm_listnode(nfn);
				      l_dt_flag=2; /* special value for error */ 
				      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>2)?mode-3:mode);
		    };
		  
		  if(argt==NULL)
		    {
		       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
			 rm_listnode(nfn);
		       l_dt_flag=2;
		       break;
		    };
		  if(argt==(struct typerec PTR) &validate_function)
		    continue;
		  
		  argstype=args->var->type;
		  
		  argt=eval_type_refr(argt,fnlist,vars,types,labels,1,NULL);  /* "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 %s not found !\n",argstype->name);
			    rm_lnd_all(valids);
			    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 %s not found !\n",argstype->name);
			    rm_lnd_all(valids);
			    return NULL;
			 };
		    };
		  
		  argstype=eval_type_refr(argstype,fnlist,&argsvarll /*vars*/,types,labels,2,valids);
		  
		  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))
		    {
		      if(argstype->validate!=NULL)
			mk_set_lnd(valids,(char *)mk_head_lnd(copylist(argstype->validate),strdup(argstype->name),ASSOCVAR),TWOLISTS);
		      argstype=argstype->typebody.pointer_to;
		    };
		  if((argstype->typekind==VAR_TYPE)||(argt->typekind==VAR_TYPE))
		    {
		       if(fn==fn_orig)
			 fn_orig=copylist(fn);
		       vtargs=mk_head_lnd(mk_head_lnd(mk_head_lnd(NULL,l1->data,l1->attr),argstype,(argstype->typekind==VAR_TYPE)?VARTYPEL:TYPEDEFN),argt,(argt->typekind==VAR_TYPE)?VARTYPEL:TYPEDEFN);
		       l1->attr=TWOLISTS;
			l1->data=(char *)mk_head_lnd(vtargs,"\4vartypearg",FUNCTION);
		       if(mode<3)
			 mode+=3;
		       l_dt_flag=1;
		    }
		  else if(valids->next!=NULL)
		    {
		       listnode lvalid,lkeep;
		       
		       if(fn==fn_orig)
			 fn_orig=copylist(fn);		       
		       lkeep=mk_head_lnd(NULL,((l1->attr==TWOLISTS)||(l1->attr==FUNCAVAR))?(char *)copylist((listnode)l1->data):strdup(l1->data),l1->attr);
		       for(lvalid=valids->next;lvalid!=NULL;lvalid=rm_cdr_next(lvalid))
			 {
			    if(lvalid->attr!=TWOLISTS)
			      (*((char *)NULL))+=printf("Strange: in validators list: %d attr != TWOLISTS\nCore dump:",lvalid->attr);
			    lnd_replace(((listnode)lvalid->data)->next,((listnode)lvalid->data)->data,ASSOCVAR,l1->data,l1->attr,3,0);
			    lnd_replace(((listnode)lvalid->data)->next,((listnode)lvalid->data)->data,VARIABLE,l1->data,l1->attr,3,0);
			   if((l1->attr==TWOLISTS)||(l1->attr==FUNCAVAR))
			     rm_lnd_all((listnode)l1->data);
			   l1->attr=TWOLISTS;
			   l1->data=(char *)rm_cdr_next((listnode)lvalid->data);
			 };
		       valids->next=NULL;
		       l1->attr=TWOLISTS;
		       l1->data=(char *)mk_head_lnd(mk_head_lnd(lkeep,(char *)l1->data,TWOLISTS),"\4vartypevalid",FUNCTION);
		       if(mode<3)
			 mode+=3;
		       l_dt_flag=3;
		       /* 3 means that it was validator */

		    }
		  else if(type_cmp(argt,argstype))
		    continue;
		  else if((typeconv=convert_type(types,argt,argstype,NULL))==NULL)
		    {
		       if(!(Strcmp(fn->data,"\4vartypetry")&Strcmp(fn->data,"\4tryvalid")))
			 rm_listnode(nfn);
		       l_dt_flag=2;
		       break;
		    };
		  
		  if(mode==2) /* if its only testing */
		    rm_lnd_all(typeconv);
		  else if((l_dt_flag!=1)&(l_dt_flag!=3))	
		    /* substitution */
		    l1=(convlist_to_funcall(typeconv,l1));
	       };
	     
	     destroy_vardecl_list(argscopy);

	     if((!l_dt_flag)&(mode>2))
	       /* if l_dt_flag==0 it means that on this function there was 
		no  dynamic types involved */
	       {
		  if(fn!=fn_orig)
		    nfn=nfn->next;
		  mode-=3;
	       };

	     if((mode>2)&(l_dt_flag!=2))
	       {
		  if((Strcmp(nfn->data,(l_dt_flag==3)?"\4tryvalid":"\4vartypetry"))&(nfn->attr==FUNCTION))
		    {
		       nfn=mk_head_lnd(mk_head_lnd(NULL,copylist(nfn),TWOLISTS),Strdup((l_dt_flag==3)?"\4tryvalid":"\4vartypetry"),FUNCTION);
		       rm_listnode(fn);
		       free(fn->data);
		       *fn=*nfn;
		       free(nfn);
		       nfn=fn;
		    }
		  else
		    nfn=nfn->next;
	       };
	     

	     if(args==NULL)
	       {
		  res=flind->fundef->res_type;
		  
		  if(l1==NULL)
		    {
		       if((mode!=2)&(mode!=5)) /* if we allowed to substitute the name with the name in code */
			 {
			    if(flind->fundef->kind==is_inline)
			      {
				 if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				   {
				      Free(((listnode)nfn->next->data)->data);
				      ((listnode)nfn->next->data)->data=Strdup("\4run_inline");
				      ((listnode)nfn->next->data)->next=mk_head_lnd(((listnode)nfn->next->data)->next,flind->fundef,FUNCDEFN);
				   }
				 else
				   {
				      Free(nfn->data);	
				      nfn->data=Strdup("\4run_inline");
				      nfn->next=mk_head_lnd(nfn->next,flind->fundef,FUNCDEFN);
				   };
			      }
			    else
			      {
				 if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
				   {
				     if((l_dt_flag==3)&(nfn->next!=NULL))
				       {
					 while(nfn->next->next!=NULL)
					   {
					     nfn=nfn->next;
					   }
				       };
				     Free(((listnode)nfn->next->data)->data);
				     ((listnode)nfn->next->data)->data=Strdup(flind->fundef->def_to_use.name_in_code);
				   }
				 else
				   {
				      Free(nfn->data);
				      nfn->data=Strdup(flind->fundef->def_to_use.name_in_code);
				   };
			      };
			 };
		       
		       argsvarll.next=NULL;
		       argsvarll.vlist=flind->fundef->args;
		       if(mode<3)
			 {
			    if(fn_orig!=fn)
			      rm_lnd_all(fn_orig); 
			    rm_lnd_all(valids);
			    return eval_type_refr(res,fnlist,&argsvarll /*vars*/,types,labels,0,NULL);
			 };
		    };
		  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,1)==NULL)
				break;
			    l1=l1->next;
			 };
		       
		       if(l1==NULL)
			 {
			    res=flind->fundef->res_type;
			    if((mode!=2)&(mode!=5)) /* if we allowed to substitute the name with the name in code */
			      {
				 if(flind->fundef->kind==is_inline)
				   {
				      if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
					{
					   Free(((listnode)nfn->next->data)->data);
					   ((listnode)nfn->next->data)->data=Strdup("\4run_inline");
					   ((listnode)nfn->next->data)->next=mk_head_lnd(((listnode)nfn->next->data)->next,flind->fundef,FUNCDEFN);
					}
				      else
					{
					   Free(nfn->data);	
					   nfn->data=Strdup("\4run_inline");
					   nfn->next=mk_head_lnd(nfn->next,flind->fundef,FUNCDEFN);
					};
				   }
				 else
				   {
				      if(!(Strcmp(nfn->data,"\4vartypetry")&Strcmp(nfn->data,"\4tryvalid")))
					{
					   Free(((listnode)nfn->next->data)->data);
					   ((listnode)nfn->next->data)->data=Strdup(flind->fundef->def_to_use.name_in_code);
					}
				      else
					{
					   Free(nfn->data);
					   nfn->data=Strdup(flind->fundef->def_to_use.name_in_code);
					};
				   };
			      };
			    argsvarll.next=NULL;
			    argsvarll.vlist=flind->fundef->args;
			    if(mode<3)
			      {
				 if(fn_orig!=fn)
				   rm_lnd_all(fn_orig); 
				 rm_lnd_all(valids);
				 return eval_type_refr(res,fnlist,&argsvarll /*vars*/,types,labels,0,NULL);
			      };
			 };
		    };
	       };
	     
	     flind=flind->next; /* arguments left, which means something wrong */
	  };
     };

   if(mode>2)
     {
	printf("### Only dynamic types matches in %s - dangerous !\n",fn_orig->data);
	if(fn_orig!=fn)
	  rm_lnd_all(fn_orig);
	rm_lnd_all(valids);
	if(strcmp(fn->data,"\4vartypetry")&strcmp(fn->data,"\4tryvalid"))
	  {
	    fn->next=mk_head_lnd(NULL,mk_head_lnd(fn->next,fn->data,fn->attr),TWOLISTS);
	    fn->data=strdup((l_dt_flag==3)?"\4tryvalid":"\4vartypetry");
	  };
	return eval_type_refr(res,fnlist,vars,types,labels,0,NULL);
     };
   if (!mode)
     printf("Problem with function %s\n",fn->data);
   rm_lnd_all(valids);
   return NULL;
}

