#include <string.h>
int convert_label(char *s,int *n,bool *err);
bool isfirstvarc(char c)
{
	if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))||(c=='_')) return(true);
	else return(false);
}
bool isnextvarc(char c)
{
	if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))||(c=='_')||((c>='0')&&(c<='9'))) return(true);
	else return(false);
}
int strvarn(char *s)
{
	int i;
	if (!isfirstvarc(s[0])) return(0);
	i=1;
	while(isnextvarc(s[i])) i++;
	return(i);
}
int strlabn(char *s)
{
	int i;
	if (!isfirstvarc(s[0])) return(0);
	i=0;
	while(isnextvarc(s[i])||(s[i]=='.')) i++;
	return(i);
}

char hex(char c)
{
	if ((c>='0')&&(c<='9')) return(c-'0');
	else if ((c>='A')&&(c<='F')) return(c-'A'+10);
	else if ((c>='a')&&(c<='f')) return(c-'a'+10);
	else if ((c>='G')&&(c<='Z')) return(-2);
	else if ((c>='g')&&(c<='z')) return(-2);
	else return(-1);
}
int atov(char *s,int *n, bool *err)
{
	int i,d,h;
	char c,neg;
	bool y,errv;
	errv=0;
	if (s[0]=='-') neg=1; else neg=0;
	i=neg;
	if ((s[i]=='0')&&((s[i+1]=='x')||(s[i+1]=='X'))) {
		i+=2; h=0;
		while((c=hex(s[i]))>=0) {
			h=(h<<4)+c;
			i++;
		}
		if (c==-2) errv=1;
	} else {
		d=0; h=0; y=0;
		while((c=hex(s[i]))>=0) {
			h=(h<<4)+c;
			d=d*10+c;
			if (c>=10) y=1;
			i++;
		}
		if ((s[i]=='h')||(s[i]=='H')) {
			i++;
		} else if (c==-2) {
			errv=1;
		} else if (y) {
			h=d;
			errv=1;
		} else {
			h=d;
		}
	}
	if (n!=NULL) *n=i;
	if (err!=NULL) *err=errv;
	if (hex(s[i])!=-1) *err=1;
	return(h);
}

short ops[]={
	'!',
	'~',
	'<<',
	'>>',
	'/',
	'*',
	'-',
	'+',
	'^',
	'&',
	'|',
	'>',
	'<',
	'>=',
	'<=',
	'==',
	'!=',
	'&&',
	'||',
	')',
	';',
	',',
	'\0',
	'('
};


char opc(char *s)
{
	int i;
	for(i=0;i<(sizeof(ops)/sizeof(short));i++) {
		if ((ops[i]&0xFF00)!=0) {
			if ((s[0]==(ops[i]>>8))&&(s[1]==(ops[i]&0xFF))) return(i);
		}
	}
	for(i=0;i<(sizeof(ops)/sizeof(short));i++) {
		if ((ops[i]&0xFF00)==0) {
			if (s[0]==ops[i]) return(i);
		}
	}
	return(-1);
}
int expression(char *s,int *errpos)
{
	int vstack[100];
	short opstack[100];
	char c0;
	short lastexp;
	int vsp;
	int opsp;
	int i,n,v;
	
	bool errv;
	i=0; vsp=0; opsp=0; 
	lastexp='(';
	if (errpos!=NULL) *errpos=-1;
	
	do {
		if ((s[i]=='/')&&(s[i+1]=='*')) {
			while(!((s[i]==0)||((s[i]=='*')&&(s[i+1]=='/')))) i++;
			c0=s[i];
			if (s[i]!=0) {i++; c0=' ';}
		} else if (((s[i]=='/')&&(s[i+1]=='/'))||(s[i]==';')) {
			while(s[i]!=0) i++;
			c0=0;
		} else c0=s[i];
		if ((c0>0)&&(c0<=' ')) i++;
		else if ((c0>='0')&&(c0<='9')) {
			v=atov(s+i,&n,&errv);	
			if (errv) {if (errpos!=NULL) *errpos=i; return(0);}
			vstack[vsp]=v;
			vsp++;
			i+=n;
			lastexp=0x7F;
		} else if (isfirstvarc(s[i])) {
			v=convert_label(s+i,&n,&errv);
			if (errv) {if (errpos!=NULL) *errpos=i; return(0);}
			vstack[vsp]=v;
			vsp++;
			i+=n;
			lastexp=0x7F;
		} else {
			v=opc(s+i);
			if (v==-1) {
				if (errpos!=NULL) *errpos=i; return(-1);
			}
			if ((c0!='(')&&(opsp>0)&&(opstack[opsp-1]<=v)) {//pop
				while((opsp>0)&&(opstack[opsp-1]<=v)) {
					opsp--;
					switch(ops[opstack[opsp]]) {
					case '(': break;
					case '!': if (vsp<1) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-1]=-vstack[vsp-1]; break;
					case '~': if (vsp<1) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-1]=~vstack[vsp-1]; break;
					case '<<': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]<<vstack[vsp-1]; vsp--; break;
					case '>>': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]>>vstack[vsp-1]; vsp--; break;
					case '/': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]/vstack[vsp-1]; vsp--; break;
					case '*': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]*vstack[vsp-1]; vsp--; break;
					case '-': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]-vstack[vsp-1]; vsp--; break;
					case '+': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]+vstack[vsp-1]; vsp--; break;
					case '^': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]^vstack[vsp-1]; vsp--; break;
					case '&': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]&vstack[vsp-1]; vsp--; break;
					case '|': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
							vstack[vsp-2]=vstack[vsp-2]|vstack[vsp-1]; vsp--; break;
					case '>': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]>vstack[vsp-1])?1:0; vsp--; break;
					case '<': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]<vstack[vsp-1])?1:0; vsp--; break;
					case '>=': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]>=vstack[vsp-1])?1:0; vsp--; break;
					case '<=': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]<=vstack[vsp-1])?1:0; vsp--; break;
					case '==': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]==vstack[vsp-1])?1:0; vsp--; break;
					case '!=': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=(vstack[vsp-2]!=vstack[vsp-1])?1:0; vsp--; break;
					case '&&': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=((vstack[vsp-2]!=0)&&(vstack[vsp-1]!=0))?1:0; vsp--; break;
					case '||': if (vsp<2) {if (errpos!=NULL) *errpos=i; return(-1);} 
						vstack[vsp-2]=((vstack[vsp-2]!=0)||(vstack[vsp-1]!=0))?1:0; vsp--; break;
					}
				}
			}
			if (c0==')') {
				if (opsp==0) {if (errpos!=NULL) *errpos=i; return(0);}
				opsp--; //'('
			} else {
				if ((c0=='-')&&(lastexp=='(')) {
					v=opc("!");
				}
				opstack[opsp]=v;
				opsp++;
			}
			i++; if (ops[v]&0xFF00) i++;
			lastexp=c0;
		}
	} while ((c0!=0)&&(c0!=',')&&(c0!=';'));

	if (opsp!=1) {if (errpos!=NULL) *errpos=i;}
	if (vsp!=1) {if (errpos!=NULL) *errpos=i;}
	return(vstack[0]);
}

