#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*/;
defined_op tmp1;
cmp_str res1;
int step1,step2,formind;
defined_op matches,smatches,uplim,downlim;
int i,j,lnd_stat,skip;
char * str;
char tok[33],mtch[33];
int op_list_dup_status=0;
/* 0-not copied,1-copied */

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)
		{
		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]!=32;step2++){};mtch[step2]=0;
		Strncpy(tok,str,strlen(mtch));
		for(step2=0;!!tok[step2]&tok[step2]!=32;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]!=32;step2++){};mtch[step2]=0;
		Strncpy(tok,str,strlen(mtch));
		for(step2=0;!!tok[step2]&tok[step2]!=32;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("## 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);
				vl=global_find_var_decl(mtch,vars);
				if(smatches->prev->attr!=NOTYPECK)
					{
					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;
				};

/*			printf("## Removing matches with wrong types (currently %d matches)\n",inline_op_list_count(matches));*/
			for(ind=matches;(type1!=NULL)&(ind!=smatches->next)&(ind!=NULL)/*NULL ???*/;)
				{
/*				printf("## looking at op %d [%s] %s ...\n",ind->attr,ind->form,ind->defn);*/

				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)
					{
/*					printf("## 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(tok,get_nth_token(formind+1,ind->defn),32);
					for(step2=0;!!tok[step2]&tok[step2]!=32;step2++){};tok[step2]=0;

					vl=lookup_var_decl(tok,ind->vars);

					if(vl==NULL)
						{
/*						printf("## op [%s] %s haven't specified\n## var %s, so leaving it\n",ind->form,ind->defn,tok);*/
						ind=ind->next;
						}
					else if(vl->var==NULL)
						{
						printf("op_recognize(): vl->var==NULL !!!\n");
						exit(1);
						}
					else if(vl->var->type==NULL)
						{
/*						printf("## op [%s] %s haven't specified\n## var %s's type, so  leaving it\n",ind->form,ind->defn,tok);*/
						ind=ind->next;
						}
					else
						{
						struct typerec PTR type2=NULL;
						listnode lconv=NULL;

						type2=eval_type_refr(vl->var->type,fnlist,vars,types,NULL,2);

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

						type1=eval_type_refr(type1,fnlist,vars,types,NULL,2);

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

						if(type1==type2)
							{
/*							printf("## 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("## op [%s] %s var %s is convertable\n",ind->form,ind->defn,mtch);*/
								rm_lnd_all(lconv);
								ind=ind->next;
								}
							else
								{
/*								printf("## op [%s] %s var %s is UNCORRECT\n",ind->form,ind->defn,mtch);*/

								if(!op_list_dup_status)
									{
/*									printf("# op_recognize(): the op matched ([%s] %s) have wrong type\n",ind->form,ind->defn);*/
									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(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==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]!=32;step2++){};mtch[step2]=0;
		Strncpy(tok,str,strlen(mtch));
		for(step2=0;!!tok[step2]&tok[step2]!=32;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]!=32;step2++){};mtch[step2]=0;
		Strncpy(tok,str,strlen(mtch));
		for(step2=0;!!tok[step2]&tok[step2]!=32;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]!=32;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]!=32;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);

				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]!=32;step2++){};mtch[step2]=0;

					vl=lookup_var_decl(mtch,ind->vars);

					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");
						(void *)vl->var->type;
						}
					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);

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

						type1=eval_type_refr(type1,fnlist,vars,types,block_lab,2);

						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]!=32;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]!=32;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]!=32;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 *********************************/
