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

/******************************************************************************/
/*       Gets string and recognizes operators, variables and expressions      */
/*    Uses get_expression(),get_variable(),lnd_asapnde(). Can skip N tokens   */
/******************************************************************************/

int op_recognize(
		 char * instr,
		 listnode dst,
		 defined_op oda,
		 listnode inl,
		 int inskip,
		 struct type_listoflist PTR types,
		 struct vardecl_listoflist PTR vars,
		 listnode fnlist)
{
  defined_op ind;
  listnode l,l1,l2/*,l3*/;
  cmp_str res1;
  int step1,step2,formind;
  defined_op matches,smatches,uplim,downlim;
  int i,j,lnd_stat,skip,type_match_flag=0;
  char * str;
  char tok[33],mtch[33];
  int op_list_dup_status=0;
  /* 0-not copied,1-copied */
  struct typerec * type_match=NULL;
  
  if (oda==NULL) return 0;
  
  skip=inskip;
  l=mk_set_lnd(NULL,NULL,VARIABLE);
  j=0;
  lnd_stat=lnd_count(dst);
  str=instr;
  formind=0;
  downlim=inline_opdef_last(oda);
  uplim=oda;
  smatches=downlim;matches=uplim;
   
  while((smatches!=((matches->next==NULL)?NULL:matches))&!!*str)
    {
      if(smatches->prev==NULL)
	break;
      else if(smatches->prev->form==NULL)
	break;
      else if(!smatches->prev->form[formind])
	break;
      
      while(*str==32)
	str++; 
      step2=1;
      step1=0;
      j=0;
	
      
      for(ind=matches;(!skip)&(ind!=smatches->next);ind=ind->next)
	{
	  type_match_flag=0;
	  if((ind->form==NULL)||(ind->attr==255))
	    break;
	  else if(*(ind->form+formind)!='f')
	    break;
	     
	  for(step1=0;step1<34;step1++) tok[step1]=mtch[step1]=0;
	  Strncpy(mtch,get_nth_token(formind+1,ind->defn),32);
	  for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
	  Strncpy(tok,str,strlen(mtch));
	  for(step2=0;(!!tok[step2])&(tok[step2]!=' ');step2++){};tok[step2]=0;
	  /*	for(step2--,step1=step2;!!tok[step2]&(tok[step2]!=mtch[step1])&isidch(tok[step2]);step2--) tok[step2]=0;*/
	  res1=str_cmp(tok,mtch);
	  if (ind->attr==255)
	    res1=right; /* buffer reached */
	  if ((res1!=left)&(res1!=llong))
	    break;
	};
      if (ind==smatches->next) ind=smatches;
      matches=ind;
      for(ind=matches;(!skip)&(ind!=smatches->next);ind=ind->next)
	{
	  if((ind->form==NULL)||(ind->attr==255))
	    break;
	  else if(ind->form[formind]!='f')
	    break;
	  
	  for(step1=0;step1<34;step1++) tok[step1]=mtch[step1]=0;
	  Strncpy(mtch,get_nth_token(formind+1,ind->defn),32);
	  for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
	  Strncpy(tok,str,strlen(mtch));
	  for(step2=0;(!!tok[step2])&(tok[step2]!=' ');step2++){};tok[step2]=0;
	  for(step2--,step1=step2;!!tok[step2]&(tok[step2]!=mtch[step1])&isidch(tok[step2]);step2--) tok[step2]=0;
	  res1=str_cmp(tok,mtch);
	  if (ind->attr==255)
	    res1=right; /* buffer reached */
	  if ((res1==right)||(res1==rlong))
	    break;
	  else
	    j=strlen(mtch);
	};
      if (matches==ind)
	j=0;
      if (ind==smatches->next)
	ind=smatches;
      smatches=ind;
      i=0;

      if(matches->form!=NULL)
	if(matches->form[formind]=='t')
	  /* If there's only one op */
	  type_match_flag=1;
      
      if (smatches==matches) /* no compare */
	{
	  smatches=downlim;	/* try match with vars */
	  
	  for (ind=downlim;(ind!=uplim->next);ind=ind->prev)
	    {
	      if((ind->form!=NULL)&(ind->attr!=255))
		{
		  if(ind->form[formind]=='t')
		    type_match_flag=1;
		  if(ind->form[formind]=='f')
		    break;
		};
	      j=j;
	    };
	  
	  if (ind==uplim->next)
	    ind=uplim;
	  else
	    ind=ind->next;
	  
	  if((ind->form!=NULL)&(ind->attr!=255))
	    if ((ind->form[formind]!='f')
		&(!!ind->form[formind]))
	      matches=ind;
	  
	  if(matches!=NULL)
	    /* if this is the only op then matches
	       can be == ind and still be wrong */
	    {
	      if((matches->attr==255)||(matches->form==NULL))
		matches=NULL;
	      else
		if(matches->form[formind]=='f')
		  matches=NULL;
	    };
	  
	  if((matches!=ind)||(matches==NULL)) /* no match */
	    {
	      /*	       	printf("## op_recognize(): no match\n");*/
	      if(op_list_dup_status) /* then we need to remove duped copy of list */
		destroy_inline_op_list(uplim); /* destroy all the list */
	      rm_lnd_all(l);
	      
	      return 0;  /* No vars */
	    };
	  
	  if (smatches==matches)
	    {
	      /*	       	printf("## op_recognize(): no match\n");*/
	      if(op_list_dup_status) /* then we need to remove duped copy of list */
		destroy_inline_op_list(uplim); /* destroy all the list */
	      rm_lnd_all(l);
	      
	      return 0;  /* No vars */
	    };
	  
	  if((matches->next!=smatches)&(!op_list_dup_status))
	    /* if there are possibilities of different ops */
	    {
	      /*printf("## op_recognize(): duplicating inline ops list (%d ops of %d)\n",inline_op_list_count_part(matches,smatches->next),inline_op_list_count(uplim));*/
		  
	      matches=copy_inline_op_list_part(matches,smatches->next);
	      smatches=inline_opdef_last(matches);
	      uplim=matches;downlim=smatches;
	      op_list_dup_status=1;
	    };
	  
	  if (!skip)  		/* don't skip */
	    {
	      struct typerec PTR type1=NULL;
	      
	      l1=mk_set_lnd(NULL,NULL,VARIABLE);
	      
	      j=get_expression(str,l1,oda,inl,1,types,vars,fnlist);
	      
	      if((!j)&(smatches->prev->prec<FUNC_PREC))
		{
		  j=get_variable(str)-str;
		  while(str[j]==32)
		    j++;
		  if(str[j]=='(')
		    j=get_function(str,l1,oda,inl,0,types,vars,fnlist);
		  else
		    j=0;
		};
	      
	      
	      if(j)
		{
		  l2=l1->next;
		  Free(l1);
		  
		  l2=op_to_function(l2);
		  
		  if(smatches->prev->attr!=NOTYPECK)
		    {
		      type1=validate_function(l2,fnlist,vars,types,NULL,2);
		      /* 2 is for "validate only" mode, when function only checks
			 for error (silently) and don't replace anything. We would use
			 validate_function() one more time, so we need "regular" function
			 names, not asmnames.*/
		      
		      if(type1==NULL)
			{					printf("## op_recognize(): function or expression given as component #%d of\n## the operator can't be validated ! (Aborting op_recognize() with 0)\n",formind);
			if(op_list_dup_status)
			  destroy_inline_op_list(uplim);
			/*						else
									printf("## op_recognize(): parsing variables now, but ops aren't duped ?!?\n");*/
			rm_lnd_all(l);
			rm_lnd_all(l2); /* parsing function, so l2 is l1 converted to function; */
			return 0;
			};
		    }
		  else
		    type1=NULL;
		}
	      else
		{
		  struct vardecl_list PTR vl=NULL;
		  
		  l2=NULL;
		  
		  if((j=get_variable(str)-str)==0)
		    {
		      if(op_list_dup_status)
			destroy_inline_op_list(uplim);
		      rm_lnd_all(l);
		      rm_lnd_all(l1);
		      return 0;
		    };
		  
		  i=ASSOCVAR;
		  
		  rm_lnd_all(l1);
		  l2=l1=NULL;
		  
		  memset(mtch,0,34);
		  strncpy(mtch,str,j);
		  
		  if(isnum(*mtch))
		    {
		      if((type1=get_type_by_name("int",NONE,types))==NULL)
			{
			  fprintf(stderr,"\"int\" type not defined at this level \n");
			  return 0;
			};
		    }
		  else
		    {
		      if(type_match_flag)
			{
			  int tmp_j=0;

			  type_match=NULL;
			  if(tmp_j=get_type_from_code(str,NULL,fnlist,types,vars,NULL,inl,oda,NULL,&type_match))
			    j=tmp_j;
			};
		      vl=global_find_var_decl(mtch,vars,0);
		      if((smatches->prev->attr!=NOTYPECK)&&(!!strcmp(mtch,"META"))&&(!type_match_flag||(type_match==NULL)))
			{
			  if(vl==NULL)
			    {
			      /*printf("## op_recognize(): variable %s given as component #%d of\n## the operator can't be found ! (Aborting op_recognize() with 0)\n",mtch,formind);*/
			      if(op_list_dup_status)
				destroy_inline_op_list(uplim);
			      /*else
				printf("## op_recognize(): parsing variables now, but ops aren't duped ?!?\n");*/
			      
			      rm_lnd_all(l);
			      return 0;
			    };
			  
			  type1=vl->var->type;
			}
		      else
			type1=NULL;
		      
		    };
		};
	      
	      for(ind=matches;(type1!=NULL)&(ind!=smatches->next)&(ind!=NULL)/*NULL ???*/;)
		{
		  
		  if((ind->attr==STOP_XOP)
		     ||(ind->attr==NOTYPECK)
		     ||(ind->fdef.opdef==NULL)
		     ||(ind->form==NULL)
		     ||(ind->defn==NULL))
		    {
		      ind=ind->next;
		      continue;
		    };
		  
		  if(ind->vars==NULL)
		    {
		      ind=ind->next;
		    }
		  else
		    {
		      struct vardecl_list PTR vl;
		      
		      Strncpy(tok,get_nth_token(formind+1,ind->defn),32);
		      for(step2=0;(!!tok[step2])&(tok[step2]!=' ');step2++){};tok[step2]=0;
		      
		      if(type_match_flag & ((ind->form[formind]!='t')==(type_match!=NULL)))
			{

			  if(!op_list_dup_status)
			    {
			      
			      if(matches->next!=smatches)
				{
				  printf("op_recognize(): matches->next!=smatches !\n");
				};
			      rm_lnd_all(l);
			      return 0;
			    };
			  
			  if(ind==matches)
			    {
			      ind=matches->next;
			      Free(matches);
			      matches=ind;
			    }
			  else
			    {
			      inline_op indtmp;
			      ind->prev->next=ind->next;
			      ind->prev->next->prev=ind->prev;
			      indtmp=ind;
			      ind=ind->next;
			      Free(indtmp);
			    };
			}
		      else if(ind->form[formind]!='t')
			{
			  vl=lookup_var_decl(tok,ind->vars,0);
		      
			  if(vl==NULL)
			    {
			      ind=ind->next;
			    }
			  else if(vl->var==NULL)
			    {
			      printf("op_recognize(): vl->var==NULL !!!\n");
			      exit(1);
			    }
			  else if(vl->var->type==NULL)
			    {
			      ind=ind->next;
			    }
			  else
			    {
			      struct typerec PTR type2=NULL;
			      listnode lconv=NULL;
			  
			      type2=eval_type_refr(vl->var->type,fnlist,vars,types,NULL,2,NULL);
			      
			      while((type2->typekind==TYPEREFR)&(type2->typemodf==NONE))
				type2=type2->typebody.pointer_to;
			      
			      type1=eval_type_refr(type1,fnlist,vars,types,NULL,2,NULL);
			      
			      while((type1->typekind==TYPEREFR)&(type1->typemodf==NONE))
				type1=type1->typebody.pointer_to;
			      
			      if(type1==type2)
				{
				  ind=ind->next;
				}
			      else
				{
				  lconv=convert_type(types,type1,type2,NULL);
				  if(lconv!=NULL)
				    {
				      rm_lnd_all(lconv);
				      ind=ind->next;
				    }
				  else
				    {
				      if(!op_list_dup_status)
					{
					  
					  if(matches->next!=smatches)
					    {
					      printf("op_recognize(): matches->next!=smatches !\n");
					    };
					  rm_lnd_all(l);
					  return 0;
					};
				      
				      if(ind==matches)
					{
					  ind=matches->next;
					  Free(matches);
					  matches=ind;
					}
				      else
					{
					  inline_op indtmp;
					  ind->prev->next=ind->next;
					  ind->prev->next->prev=ind->prev;
					  indtmp=ind;
					  ind=ind->next;
					  Free(indtmp);
					};
				    };
				};
			    };
			};
		    };
		}; /* End of the for loop, the one which checks all vars */
	      
	      
	      if(matches==NULL)
		{
		  /*				printf("## op_recognize(): no match after applying types\n");*/
		  
		  rm_lnd_all(l);
		  if(l2!=NULL)
		    rm_lnd_all(l2);
		  else
		    rm_lnd_all(l1);
		  
		  if(op_list_dup_status)
		    destroy_inline_op_list(uplim);
		  
		  return 0;
		  
		};
	      
	      mk_set_lnd(l,NULL,VARIABLE);
	      l1=lnd_cdre(l);
	      

	      if(type_match_flag && (type_match!=NULL))
		{
		  l1->attr=TYPEDEFN;
		  l1->data=(char *)type_match;
		  type_match=NULL;
		}
	      else if(l2!=NULL)
		{
		  l1->attr=FUNCAVAR;
		  l1->data=(char PTR)l2;/* dumb AIX cc */
		  
		  i=i|64; /* I have no idea where I need this value !!!!! */
		}
	      else
		{
		  l1->attr=ASSOCVAR;
		  l1->data=Strdup(mtch); /* if it was a var ... */
		  
		  i=i|64; /* I have no idea where I need this value !!!!! */
		}
	      
	    } /*else  printf("Skipping ... skip #%d\n",skip);*/
	  /* if (!skip) */
	}
      
      if ((!j)&(smatches->prev->form[formind-1]=='l'))  /* list of parameters */
	{
	  /*		printf("Seems to be a list of arguments\n");*/
	  while(*str==32) str++;
	  if (*str!=',') break;
	  str++;
	  formind--;
	  smatches=downlim;
	  matches=uplim;
	  continue;
	};
      
      if(op_list_dup_status)
	{
	  /*		printf("## op_recognize(): removing duped and not used inline op list entries\n");*/
	  if(uplim!=matches)
	    destroy_inline_op_list_part(uplim,matches);
	  if((smatches->next!=NULL)&(downlim!=smatches))
	    {
	      destroy_inline_op_list(smatches->next); /* to the end, i.e. downlim */
	      smatches->next=NULL;
	    };
	};
      
      downlim=smatches;uplim=matches;
      for(step1=0;step1<34;step1++) tok[step1]=0;
      if (!skip)
	/* we don't do all this when we skip or if it is list ! */
	{
	  if (!j) break;
	  /*		Strncpy(tok,str,j);
			printf("Next token : %s\n",tok);
			if (i!=64) lnd_asapnde(dst,tok,i);
			if (i!=64) lnd_asapnde(l,tok,PARTOFOP);  */
	  str+=j; /* cut string */
	};
      if(skip) skip--;
      formind++;
      
    };
  
  if (smatches->prev==NULL)
    {
      rm_lnd_all(l);
      
      if(op_list_dup_status)
	destroy_inline_op_list(uplim);
      
      rm_listnode(get_nth_lnd(dst,lnd_stat+1));
      return 0;
    };
  
  if(smatches->prev->form[formind])
    {
      rm_lnd_all(l);
      
      if(op_list_dup_status)
	destroy_inline_op_list(uplim);
      
      rm_listnode(get_nth_lnd(dst,lnd_stat+1));
      return 0;
    };
  
  smatches=smatches->prev;
  /*printf("The operator was %s\n",smatches->defn);*/
  i=str-instr;
  
  l=rm_cdr_next(l);
  l1=mk_set_lnd(dst,smatches,OPDEFPTR);
  /*
    l1=l1->next;
    * 
    l1->attr=OPDEFPTR;
    (defined_op) l1->data=smatches;
    l1->next=NULL;
  */
  /*printlist(l);*/
  
  instr=smatches->form;
  str=smatches->defn;
  
  for(;inskip>0;inskip--)
    {
      memset(tok,0,32);
      Strncpy(tok,str,get_variable(str)-str);
      l2=mk_set_lnd(NULL,Strdup(tok),VARIABLE);
      mk_set_lnd(dst,l2,TWOLISTS);
      str=next_token1(str);
    };
  
  /* str=get_nth_token(++inskip,str); */
  
  for(l1=l;!!*instr&(l1!=NULL);instr++)
    {
      while(*instr=='f')
	{
	  while(*str==32) str++;
	  while((*str!=' ')&(*str!=0))
	    str++;
	  instr++;
	};
      if(*str==0)
	break;
      else
	while(*str==32) str++;

      if(l1->attr==TYPEDEFN)
	{
	  memset(tok,0,32);
	  Strncpy(tok,str,get_variable(str)-str);
	  l2=mk_set_lnd(NULL,Strdup(tok),VARIABLE);
	  mk_set_lnd(dst,l2,TWOLISTS);
	  
	  mk_set_lnd(l2,l1->data,l1->attr);
	  l1->data=NULL;
	}
      else if ((l1->attr==ASSOCVAR)|(l1->attr==FUNCAVAR))
	{
	  memset(tok,0,32);
	  Strncpy(tok,str,get_variable(str)-str);
	  l2=mk_set_lnd(NULL,Strdup(tok),VARIABLE);
	  mk_set_lnd(dst,l2,TWOLISTS);
	  
	  /* l2=mk_set_lnd(dst,NULL,TWOLISTS);
	     lnd_asapnde(l2,tok,VARIABLE); */
	  
	  mk_set_lnd(l2,l1->data,l1->attr);
	  l1->data=NULL;
	  
	  if (*instr=='l')
	    while((l1->next!=NULL)&(l1->next->attr==ASSOCVAR))
	      {
		l1=l1->next;
		mk_set_lnd(l2,l1->data,l1->attr);
		l1->data=NULL;
	      };
	  
	} else lnd_asapnde(dst,l1->data,l1->attr);
      l1=l1->next;
      /*	Free(l);
		//	l=l1;*/
      /*
	if((*instr=='l')&(l1->attr&&ASSOCVAR))
	instr--;
	else    */
      str=next_token(str);
      
    };
  rm_lnd_all(l);
  return i;
}

/*************************** End op_recognize ******************************/


int inline_op_recognize(
			char * str,
			listnode dst,
			inline_op oda,
			defined_op ops,
			listnode inl_list,listnode inl_lab,listnode block_lab,
			struct vardecl_listoflist PTR vars,
			struct type_listoflist PTR types,
			listnode fnlist,
			int inskip,int do_list)
{
   inline_op ind;
   listnode l,l1,l2,l3,process_line=NULL,loc_labels=NULL;
   listnode loc_inl_list;
   /*inline_op tmp1;*/
   cmp_str res1;
   int step1,step2,formind;
   inline_op matches,smatches,uplim,downlim;
   int i,j,lnd_stat,skip;
   char * instr;/*str;*/
   char tok[33],mtch[33];
   int processing_status=0;
   /* 0-unknown,1-inserting,2-finished */
   int inline_op_list_dup_status=0;
   /* 0-not copied,1-copied */
   
   if (oda==NULL) return 0;
   
   loc_inl_list=inl_list;
   skip=inskip;
   l=mk_set_lnd(NULL,NULL,VARIABLE);
   j=0;
   lnd_stat=lnd_count(dst);
   /*str=instr;*/
   formind=0;
   downlim=inline_opdef_last(oda);
   uplim=oda;
   smatches=downlim;matches=uplim;
   
   while  ((smatches!=((matches->next==NULL)?NULL:matches))&!!*str)
     {
	if(smatches->prev==NULL)
	  break;
	else if(smatches->prev->form==NULL)
	  break;
	else if(!smatches->prev->form[formind])
	  break;
	
	instr=str;
	while(*instr==32) 
	  instr++;
	refresh_buffer(str,instr-str,64);
	step2=1;
	step1=0;
	j=0;
	
	
	if((processing_status)&(process_line!=NULL))
	  {
	     while(process_line!=NULL)
	       {
		  struct vardecl_list PTR vl;
		  if(process_line->attr==TWOLISTS)
		    {
		       for(l2=l;l2!=NULL;l2=l2->next)
			 if(l2->data != NULL)
			   if(inline_op_find_var(((listnode)l2->data)->data,(listnode)process_line->data)!=NULL)
			     break;
		       if(l2!=NULL)
			 {
			    l3=copylist((listnode)process_line->data);
			    inline_op_subst_lvar(((listnode)l2->data)->data,l3,copylist(((listnode)l2->data)->next));
			    mk_asm_output(l3,inl_lab,vars,types,fnlist);
			    rm_lnd_all(l3);
			    process_line=rm_cdr_next(process_line);
			    continue;
			 };
		       /* TEMPORARY				else
			break; */
		    };
		  /* now checking for UNRESOLVED vars */
		  for(vl=matches->vars;vl!=NULL;vl=vl->next)
		    if(vl->var != NULL)
		      if(inline_op_find_var(vl->var->name,(listnode)process_line->data)!=NULL)
			break;
		  if(vl!=NULL) /* if there are unresolved vars ... */
		    break;
		  mk_asm_output((listnode)process_line->data,inl_lab,vars,types,fnlist);
		  process_line=rm_cdr_next(process_line);
	       };
	  };
	
	
	for(ind=matches;(!skip)&(ind!=smatches->next);ind=ind->next)
	  {
	     if((ind->form==NULL)||(ind->attr==255))
	       break;
	     else if(*(ind->form+formind)!='f')
	       break;
	     
	     for(step1=0;step1<34;step1++) tok[step1]=mtch[step1]=0;
	     Strncpy(mtch,get_nth_token(formind+1,ind->defn),32);
	     for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
	     Strncpy(tok,str,strlen(mtch));
	     for(step2=0;(!!tok[step2])&(tok[step2]!=' ');step2++){};tok[step2]=0;
	     /*	for(step2--,step1=step2;!!tok[step2]&(tok[step2]!=mtch[step1])&isidch(tok[step2]);step2--) tok[step2]=0;*/
	     res1=str_cmp(tok,mtch);
	     if (ind->attr==255)
	       res1=right; /* buffer reached */
	     if ((res1!=left)&(res1!=llong))
	       break;
	  };
	if (ind==smatches->next) ind=smatches;
	matches=ind;
	for(ind=matches;(!skip)&(ind!=smatches->next);ind=ind->next)
	  {
	     if((ind->form==NULL)||(ind->attr==255))
	       break;
	     else if(ind->form[formind]!='f')
	       break;
	     
	     for(step1=0;step1<34;step1++) tok[step1]=mtch[step1]=0;
	     Strncpy(mtch,get_nth_token(formind+1,ind->defn),32);
	     for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
	     Strncpy(tok,str,strlen(mtch));
	     for(step2=0;(!!tok[step2])&(tok[step2]!=' ');step2++){};tok[step2]=0;
	     for(step2--,step1=step2;!!tok[step2]&(tok[step2]!=mtch[step1])&isidch(tok[step2]);step2--) tok[step2]=0;
	     res1=str_cmp(tok,mtch);
	     if (ind->attr==255)
	       res1=right; /* buffer reached */
	     if ((res1==right)||(res1==rlong))
	       break;
	     else
	       j=strlen(mtch);
	  };
	if (matches==ind) 
	  j=0;
	if (ind==smatches->next) 
	  ind=smatches;
	smatches=ind;
	i=0;
	
	if (smatches==matches) /* no compare */
	  {
	     smatches=downlim;	/* try match with vars */
	     
	     for (ind=downlim;(ind!=uplim->next);ind=ind->prev)
	       {
		  if((ind->form!=NULL)&(ind->attr!=255))
		    if(ind->form[formind]=='f')
		      break;
		  j=j;
	       };
	     
	     if (ind==uplim->next)
	       ind=uplim;
	     else
	       ind=ind->next;
	     
	     if((ind->form!=NULL)&(ind->attr!=255))
	       if ((ind->form[formind]!='f')
		   &(!!ind->form[formind]))
		 matches=ind;
	     
	     if(matches!=NULL) 
	       /* if this is the only op then matches 
		can be == ind and still be wrong */ 
	       {
		  if((matches->attr==255)||(matches->form==NULL))
		    matches=NULL;
		  else
		    if(matches->form[formind]=='f')
		      matches=NULL;
	       };
	     
	     if((matches!=ind)||(matches==NULL)) /* no match */
	       {
		  printf("## inline_op_recognize(): no match\n");
		  if(inline_op_list_dup_status) /* then we need to remove duped copy of list */
		    destroy_inline_op_list(uplim); /* destroy all the list */
		  rm_lnd_all(process_line);
		  rm_lnd_all(l);
		  
		  return 0;  /* No vars */
	       };
	     
	     if (smatches==matches)
	       {
		  printf("## inline_op_recognize(): no match\n");
		  if(inline_op_list_dup_status) /* then we need to remove duped copy of list */
		    destroy_inline_op_list(uplim); /* destroy all the list */
		  rm_lnd_all(process_line);
		  rm_lnd_all(l);
		  
		  return 0;  /* No vars */
	       };
	     
	     if((matches->next!=smatches)&(!inline_op_list_dup_status))
	       /* if there are possibilities of different ops */
	       {
		  printf("## inline_op_recognize(): duplicating inline ops list (%d ops of %d)\n",inline_op_list_count_part(matches,smatches->next),inline_op_list_count(uplim));
		  
		  matches=copy_inline_op_list_part(matches,smatches->next);
		  smatches=inline_opdef_last(matches);
		  uplim=matches;downlim=smatches;
		  inline_op_list_dup_status=1;
	       };
	     
	     if (!skip)  		/* don't skip */
	       {
		  struct typerec PTR type1=NULL;
		  
		  l1=mk_set_lnd(NULL,NULL,VARIABLE);
		  
		  if(smatches->prev!=NULL)
		    if(smatches->prev->form[formind]=='c')
		    {
		       int double_block_usage_flag=0; 
		       /* 0 - once, 1 - several times, 
			2 - now and not a simple construct  */
		       printf("## inline_op_recognize: Possibly code block component %c #%d from %s \n",smatches->prev->form[formind],formind,smatches->prev->defn);
		       
		       /* l2=mk_set_lnd(NULL,loc_labels,TWOLISTS);
			//l2->next=inl_lab; */
		       memset(tok,0,34);
		       
		       
		       Strncpy(mtch,get_nth_token(formind+1,matches->defn),32);
		       for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
		       
		       if(process_line->data != NULL)
			 if(!((inline_op_find_var(mtch,(listnode)process_line->data)!=NULL)
			      &(((listnode)process_line->data)->attr==FUNCTION)
			      &(!Strcmp(((listnode)process_line->data)->data,"\4runcode"))))
			   double_block_usage_flag=2;
		       
		       if((double_block_usage_flag==2)||((process_line->next!=NULL)&
							 (inline_op_find_var(mtch,process_line->next)!=NULL)))
			 {
			    if((double_block_usage_flag==2)||(inline_op_find_var(mtch,(listnode)process_line->data)==NULL))
			      {
				 sprintf(tok,"lab%lx",global_label_count++);
				 printf("jmp %s\n",tok);
			      };
			    printf("lab%s :\n",get_local_label(mtch,inl_lab,LABELDEF));
			    
			    double_block_usage_flag=1; /* we don't need 2 anymore since from now it's being treated in the same way */
			 };
		       
		       loc_labels=mk_set_lnd(NULL,mk_set_lnd(NULL,NULL,LABELDEF),TWOLISTS);
		       loc_labels->next=inl_lab;
		       
		       if(!get_code_block(str,l1,loc_inl_list,ops,loc_labels,block_lab,vars,types,fnlist,0))
			 {
			    if(l2!=NULL)
			      l2->next=NULL; /* Secure labels */
			    rm_lnd_all(dst);
			    rm_lnd_all(l1);
			    return 0;
			 };
		       
		       loc_labels->next=NULL; /* Secure labels any way */
		       
		       str=instr;
		       if(do_list)
			 {
			    l2=l1->next;
			    Free(l1);
			    mk_set_lnd(l,NULL,VARIABLE);
			    l2=op_to_function(l2);
			    l1=lnd_cdre(l);
			 }
		       else
			 l2=NULL;
		       if(!processing_status)
			 {
			    l1->attr=(l2->attr==OPDEFPTR)?TWOLISTS:FUNCAVAR;
			    l1->data=(char PTR)l2;
			 }
		       else /* processing_status */
			 {
			    if(do_list)
			      {
				 Strncpy(mtch,get_nth_token(formind+1,matches->defn),32);
				 for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
				 l1->attr=TWOLISTS;
				 l1->data=(char PTR)mk_set_lnd(NULL,my_malloc(strlen(mtch)),INLCBVAR);
				 Strcpy(((listnode)l1->data)->data,mtch);
				 /*printf("Assoced one more code var %s\n",mtch);*/
				 ((listnode)l1->data)->next=l2;
				 if(l2!=NULL)
				   lnd_rapnde(dst,l2); /*** CAN BE DANGER HERE !!!!!!!!!!!!!!!***/
			      };
			    if(double_block_usage_flag)
			      printf("retn ; double usage\n");
			    if(*tok)
			      printf("lab%s :\n",tok);
			    if(!double_block_usage_flag)
			      process_line=rm_cdr_next(process_line);
			    
			 };
		       
		       if(l2!=NULL)
			 Free(l2); /* Clear "junky" listnode at the beginning */
		       
		       l2=(listnode)loc_labels->data;
		       while(l2!=NULL)
			 if(l2->attr==LABELDEF) /* resolved label */
			 {
			    rm_lnd_all((listnode)l2->data);
			    l1=l2;
			    l2=l2->next;
			    Free(l1);
			 }
		       else
			 if(l2->attr==LABELREQ) /* unresolved label */
			 {
			    l1=l2;
			    l2=l2->next;
			    l1->next=NULL;
			    if(l1->data!=NULL)      /* Junk killer */
			      lnd_rapnde((listnode)inl_lab->data,l1);
			    else
			      rm_lnd_all(l1);
			    
			 }
		       else
			 l2=l2->next;
		       
		       
		       rm_lnd_all(loc_labels);
		       
		       formind++;
		       continue;
		    };
		  
		  j=get_expression(str,l1,ops,inl_list,0,types,vars,fnlist);
		  
		  if (!j)
		    j=get_function(str,l1,ops,inl_list,0,types,vars,fnlist);
		  
		  
		  if(j)
		    {
		       l2=l1->next;
		       Free(l1);
		       l2=op_to_function(l2);
		       mk_set_lnd(l,NULL,VARIABLE);
		       
		       type1=validate_function(l2,fnlist,vars,types,block_lab,2);
		       /* 2 is for "validate only" mode, when function only checks
			for error (silently) and don't replace anything. We would use
			validate_function() one more time, so we need "regular" function
			names, not asmnames.*/
		       
		       if(type1==NULL)
			 {
			    printf("## inline_op_recognize(): function or expression given as component #%d of\n## the operator can't be validated ! (Aborting inline_op_recognize() with 0)\n",formind);
			    if(inline_op_list_dup_status)
			      destroy_inline_op_list(uplim);
			    else
			      printf("## inline_op_recognize(): parsing variables now, but ops aren't duped ?!?\n");
			    rm_lnd_all(process_line);
			    rm_lnd_all(l);
			    rm_lnd_all(l2); /* parsing function, so l2 is l1 converted to function; */
			    return 0;
			 };
		    }
		  else
		    {
		       struct vardecl_list PTR vl=NULL;
		       
		       j=get_variable(str)-str;
		       i=ASSOCVAR;
		       
		       rm_lnd_all(l1);
		       l2=l1=NULL;
		       
		       memset(mtch,0,34);
		       strncpy(mtch,str,j);
		       vl=global_find_var_decl(mtch,vars,0);
		       
		       if(vl==NULL)
			 {
			    printf("## inline_op_recognize(): variable %s given as component #%d of\n## the operator can't be found ! (Aborting inline_op_recognize() with 0)\n",mtch,formind);
			    if(inline_op_list_dup_status)
			      destroy_inline_op_list(uplim);
			    else
			      printf("## inline_op_recognize(): parsing variables now, but ops aren't duped ?!?\n");
			    rm_lnd_all(process_line);
			    rm_lnd_all(l);
			    return 0;
			 };
		       
		       type1=vl->var->type;
		    };
		  
		  printf("## Removing matches with wrong types (currently %d matches)\n",inline_op_list_count(matches));
		  for(ind=matches;(ind!=smatches->next)&(ind!=NULL)/*NULL ???*/;)
		    {
		       printf("## looking at inline op %d [%s] %s ...\n",ind->attr,ind->form,ind->defn);
		       
		       if((ind->attr==255)
			  ||(ind->fdef.inlfun==NULL)
			  ||(ind->form==NULL)
			  ||(ind->defn==NULL))
			 {
			    ind=ind->next;
			    continue;
			 };
		       
		       if(ind->vars!=ind->fdef.inlfun->args)
			 printf("### ind->vars!=ind->fdef->args !!!\n"); 
		       
		       if(ind->vars==NULL)
			 {
			    printf("## inline op [%s] %s haven't specified\n## vars, so leaving it\n",ind->form,ind->defn);
			    ind=ind->next;
			 }
		       else
			 {
			    struct vardecl_list PTR vl;
			    
			    Strncpy(mtch,get_nth_token(formind+1,ind->defn),32);
			    for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
			    
			    vl=lookup_var_decl(mtch,ind->vars,0);
			    
			    if(vl==NULL)
			      {
				 printf("## inline op [%s] %s haven't specified\n## var %s, so leaving it\n",ind->form,ind->defn,mtch);
				 ind=ind->next;
			      }
			    else if(vl->var==NULL)
			      {
				 printf("inline_op_recognize(): vl->var==NULL !!!\n");
				 printf("vl==%8lx\nCreating SEGV to dump core ...\n",(unsigned long int)vl);
				 (*((char *)NULL))++;
			      }
			    else if(vl->var->type==NULL)
			      {
				 printf("## inline op [%s] %s haven't specified\n## var %s's type, so leaving it\n",ind->form,ind->defn,mtch);
				 ind=ind->next;
			      }
			    else
			      {
				 struct typerec PTR type2=NULL;
				 listnode lconv=NULL;
				 
				 type2=eval_type_refr(vl->var->type,fnlist,vars,types,block_lab,2,NULL);
				 
				 while((type2->typekind==TYPEREFR)&(type2->typemodf==NONE))
				   type2=type2->typebody.pointer_to;
				 
				 type1=eval_type_refr(type1,fnlist,vars,types,block_lab,2,NULL);
				 
				 while((type1->typekind==TYPEREFR)&(type1->typemodf==NONE))
				   type1=type1->typebody.pointer_to;
				 
				 if(type1==type2)
				   {
				      printf("## inline op [%s] %s var %s is correct\n",ind->form,ind->defn,mtch);
				      ind=ind->next;
				   }
				 else
				   {
				      lconv=convert_type(types,type1,type2,NULL);
				      if(lconv!=NULL)
					{
					   printf("## inline op [%s] %s var %s is convertable\n",ind->form,ind->defn,mtch);
					   rm_lnd_all(lconv);
					   ind=ind->next;
					}
				      else
					{
					   printf("## inline op [%s] %s var %s is UNCORRECT\n",ind->form,ind->defn,mtch);
					   
					   if(!inline_op_list_dup_status)
					     {
						printf("# inline_op_recognize(): the op matched ([%s] %s) have wrong type\n",ind->form,ind->defn); 
						if(matches->next!=smatches)
						  {
						     printf("inline_op_recognize(): matches->next!=smatches !\n"); 
						  };
						rm_lnd_all(process_line);
						rm_lnd_all(l);
						return 0;
					     };
					   
					   if(ind==matches)
					     {
						ind=matches->next;
						Free(matches);
						matches=ind;
					     }
					   else
					     {
						inline_op indtmp;
						ind->prev->next=ind->next;
						ind->prev->next->prev=ind->prev;
						indtmp=ind;
						ind=ind->next;
						Free(indtmp);
					     };
					};
				   };
			      };
			 };
		    }; /* End of the for loop, the one which checks all vars */
		  
		  
		  if(matches==NULL)
		    {
		       printf("## inline_op_recognize(): no match after applying types\n");
		       
		       rm_lnd_all(process_line);
		       rm_lnd_all(l);
		       if(l2!=NULL)
			 rm_lnd_all(l2);
		       else
			 rm_lnd_all(l1);
		       
		       if(inline_op_list_dup_status)
			 destroy_inline_op_list(uplim);
		       
		       return 0;
		       
		    };
		  
		  if(l2!=NULL)
		    {
		       l1=lnd_cdre(l);
		       if(!processing_status)
			 {
			    l1->attr=(l2->attr==OPDEFPTR)?TWOLISTS:FUNCAVAR;
			    l1->data=(char PTR)l2;
			 }
		       else /*processing_status*/
			 {
			    Strncpy(mtch,get_nth_token(formind+1,matches->defn),32);
			    for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
			    l1->attr=TWOLISTS;
			    l1->data=(char PTR)mk_set_lnd(NULL,my_malloc(34),INLCBVAR);
			    Strcpy(((listnode)l1->data)->data,mtch);
			    /*					printf("Assoced one more var %s\n",mtch);*/
			    ((listnode)l1->data)->next=l2;
			 };
		       
		       i=i|64; /* I have no idea where I need this value !!!!! */
		    };
		  
	       } /*else  printf("Skipping ... skip #%d\n",skip);*/
	     /* if (!skip) */
	  }
	
	if ((!j)&(smatches->prev->form[formind-1]=='l'))  /* list of parameters */
	  {
	     /*		printf("Seems to be a list of arguments\n");*/
	     while(*str==32) str++;
	     if (*str!=',') break;
	     str++;
	     formind--;
	     smatches=downlim;
	     matches=uplim;
	     continue;
	  };
	
	if(inline_op_list_dup_status)
	  {
	     printf("## inline_op_recognize(): removing duped and not used inline op list entries\n");
	     if(uplim!=matches)
	       destroy_inline_op_list_part(uplim,matches);
	     if((smatches->next!=NULL)&(downlim!=smatches))
	       {
		  destroy_inline_op_list(smatches->next); /* to the end, i.e. downlim */
		  smatches->next=NULL;
	       };
	  };
	
	downlim=smatches;uplim=matches;
	for(step1=0;step1<34;step1++) tok[step1]=0;
	if (!skip)
	  /* we don't do all this when we skip or if it is list ! */
	  {
	     if (!j) break;
	     /*		Strncpy(tok,str,j);
	      printf("Next token : %s\n",tok);
	      if (i!=64) lnd_asapnde(dst,tok,i); 
	      if (i!=64) lnd_asapnde(l,tok,PARTOFOP);  */
	     refresh_buffer(str,j,64); /* cut string */
	  };
	if(skip) skip--;
	formind++;
	
	if ((!processing_status)&(matches->next==smatches)&(smatches!=NULL))
	  {
	     printf("## On step %d I determined the op is %s\n",formind-1,matches->defn);
	     
	     l1=mk_set_lnd(NULL,NULL,VARIABLE);
	     
	     processing_status=1;
	     process_line=matches->fdef.inlfun->body;
	     /* Making l a complete list with var refs */
	     l2=l;
	     l=l1;
	     for (step1=0;step1<formind;step1++)
	       if(matches->form[step1]!='f') /* no form parts */
	       {
		  Strncpy(mtch,get_nth_token(step1+1,matches->defn),32);
		  for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
		  
		  l1=mk_set_lnd(l,NULL,TWOLISTS);
		  l1->data=(char PTR)mk_set_lnd(NULL,my_malloc(34),INLCBVAR);
		  
		  Strcpy(((listnode)l1->data)->data,mtch);
		  
		  ((listnode)l1->data)->next=l2;
		  l2=l2->next;
		  ((listnode)l1->data)->next->next=NULL;
	       };
	     l1=l->next;
	     if(l1!=NULL)
	       {
		  Free(l);
		  l=l1;
	       };
	     
	     loc_inl_list=mk_set_lnd(NULL,matches->fdef.inlfun->subfunctions,INLINSUB);
	     loc_inl_list->next=inl_list;
	     
	     lnd_rapnde((listnode)inl_lab->data,copylist(matches->fdef.inlfun->labels));
	  };
     };
   
   if (smatches->prev==NULL)
     {
	rm_lnd_all(process_line);
	rm_lnd_all(l);
	
	if(inline_op_list_dup_status)
	  destroy_inline_op_list(uplim);
	
	rm_listnode(get_nth_lnd(dst,lnd_stat+1));
	return 0;
     };
   
   if(smatches->prev->form[formind])
     {
	rm_lnd_all(process_line);
	rm_lnd_all(l);
	
	if(inline_op_list_dup_status)
	  destroy_inline_op_list(uplim);
	
	rm_listnode(get_nth_lnd(dst,lnd_stat+1));
	return 0;
     };
   
   
   
   if((smatches!=NULL)&(smatches->prev!=matches))
     {
	printf("## inline_op_recognize(): more than one inline op matches !\n");
	
	if(processing_status)
	  {
	     printf("inline_op_recognize(): more than one match and processing status is set !!!\n");
	  };
	
	if(inline_op_list_dup_status)
	  destroy_inline_op_list_part(uplim,smatches->prev);
	
	uplim=matches=smatches->prev;
	
	printf("## On step %d I guess the op is %s\n",formind-1,matches->defn);
	
	l1=mk_set_lnd(NULL,NULL,VARIABLE);
	
	processing_status=1;
	process_line=matches->fdef.inlfun->body;
	/* Making l a complete list with var refs */
	l2=l;
	l=l1;
	
	for (step1=0;step1<formind;step1++)
	  if(*(matches->form+step1)!='f') /* no form parts */
	  {
	     Strncpy(mtch,get_nth_token(step1+1,matches->defn),32);
	     for(step2=0;(!!mtch[step2])&(mtch[step2]!=' ');step2++){};mtch[step2]=0;
	     
	     l1=mk_set_lnd(l,NULL,TWOLISTS);
	     l1->data=(char PTR)mk_set_lnd(NULL,my_malloc(34),INLCBVAR);
	     
	     Strcpy(((listnode)l1->data)->data,mtch);
	     
	     ((listnode)l1->data)->next=l2;
	     l2=l2->next;
	     ((listnode)l1->data)->next->next=NULL;
	     
	  };
	
	l1=l->next;
	
	if(l1!=NULL)
	  {
	     Free(l);
	     l=l1;
	  };
	
	loc_inl_list=mk_set_lnd(NULL,matches->fdef.inlfun->subfunctions,INLINSUB);
	loc_inl_list->next=inl_list;
	
	lnd_rapnde((listnode)inl_lab->data,copylist(matches->fdef.inlfun->labels));
	
     };
   
   if((processing_status)&(process_line!=NULL))
     {
	while(process_line!=NULL)
	  {
	     struct vardecl_list PTR vl;
	     l2=NULL;
	     if(process_line->attr==TWOLISTS)
	       {
		  for(l2=l;l2!=NULL;l2=l2->next)
		    if(l2->data != NULL)
		      if(inline_op_find_var(((listnode)l2->data)->data,(listnode)process_line->data)!=NULL)
			break;
		  if(l2!=NULL)
		    {
		       l3=copylist((listnode)process_line->data);
		       inline_op_subst_lvar(((listnode)l2->data)->data,l3,copylist(((listnode)l2->data)->next));
		       mk_asm_output(l3,inl_lab,vars,types,fnlist);
		       rm_lnd_all(l3);
		       process_line=rm_cdr_next(process_line);
		       continue;
		    };
		  /* TEMPORARY			else
		   {
		      printf("## Seems to be a mistake !!!\n");
		      printlist2((listnode)process_line->data,0,1);
		      process_line=rm_cdr_next(process_line);
		   }; */
	       }
	     if(l2==NULL)
	       {
		  for(vl=matches->vars;vl!=NULL;vl=vl->next)
		    if(vl->var != NULL)
		      if(inline_op_find_var(vl->var->name,(listnode)process_line->data)!=NULL)
			break;
		  if(vl!=NULL)
		    break;
		  mk_asm_output((listnode)process_line->data,inl_lab,vars,types,fnlist);
		  process_line=rm_cdr_next(process_line);
	       };
	  };
     };
   
   Free(loc_inl_list); /* would not affect inl_list */
   
   if(inline_op_list_dup_status)
     destroy_inline_op_list(uplim);
   
   l1=lnd_cdre(dst);
   l1->next=l;
   /*rm_lnd_all(l);*/
   return 1; /* True */
}

/***************************** End inline_op_recognize *********************************/
