/* MasC interpreter/compiler
   (Master Assembly Script Container)
   written by Jared Bruni
   
   After reading Writing Compilers and Interpreters A approach using C++ by Ronald Mak
   and the Dragon Book
   code completly re-written but using concepts teached in this book
*/
// backend implementation file (icode execution)
// a Pyschedelic String 

#include "backend.h"
#include "parser.h"

// global variables
struct symNode *loop_ptr = 0;
int (__stdcall *callback)(const char *_PROC_name, struct BackEnd *bend, struct Token *ptr_tok);
int i_p = 0;

// calculate addition , subtraction, multiplication ,divison
float calculateValue(struct BackEnd *bend, char code)
{
	float num2,num1;
	num2 = Pop(&bend->st);
	num1 = Pop(&bend->st);
	switch(code) {
	case ADD:
	case SUB:
		return (num1 + num2);
	case MUL:
		return (num1 * num2);
	case DIV:
		if(num1 != 0 && num2 != 0) {
			return (num1/num2);
		}
		else {
			printError("Division by Zero error.\n");
			return 0;
		}
	}
	return 0;
}

// free up the icode memory structure ( free (me); )
void freeIcode(struct Token *tokens, struct BackEnd *bend)
{
	if(tokens != 0)
	free(tokens);// 1
	if(bend->g_stable.root.str != 0)
		free(bend->g_stable.root.str); // 1
	if(bend->g_stable.root.next != 0)
		free(bend->g_stable.root.next);  // 1
	// = 3
	// one thing I can tell you is you got to be frEE

}
// print out tokens for debug
void printTokens(struct Token *tokens, int tlen)
{
	int i;
	for(i = 0; tokens[i].code != End; i++)
	{
		printf("token code [%d,%s (vtype) %d] string [%s] value[%f]\n", tokens[i].code,(tokens[i].code > getReservedLen() ?  "$or!&" : syntax_str[tokens[i].code]) , tokens[i].vtype, tokens[i].text == 0 ? "" : tokens[i].text,(float)tokens[i].value);
	}
}

// execute the intermediate code (Dont let me down!) this is a long function
void executeIcode(int start_pos, struct Token *tokenz,struct BackEnd *bend)
{
	
	char code = 0;
	struct symNode *node_ptr = 0, *snode_ptr = 0;
	i_p = start_pos;
	if(finished == 1)
		return;
	// for debug or to just see whats in the symbol table and tokens vector
	//printTokens(tokenz,bend->inc_len);                  
	//symNode_Print(&bend->g_stable.root);
	if(start_pos == bend->incp) {
	Push(&bend->ist,0);
	Push(&bend->ist, (float)bend->ince);
	}

	while((code = tokenz[i_p].code) != End)
	{
		int cur_ip = i_p;
		switch(code) {
	    case ADD:
	    case SUB:
	    case MUL:
	    case DIV: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root,tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not declared.");
			return;
		}
		else {
			i_p++;
			if(node_ptr->vtype == tVAR_NONE)
			{
				printError("Variable not defined. use var(#,$,&) first!\n");
				return;
			}
			Push(&bend->st, node_ptr->value);
			if(tokenz[i_p].vtype == tVAR_CINT) {
				if(tokenz[cur_ip].code == ADD || tokenz[cur_ip].code == MUL || tokenz[cur_ip].code == DIV)
					Push(&bend->st,tokenz[i_p].value);
				else if(tokenz[cur_ip].code == SUB)
					Push(&bend->st,-tokenz[i_p].value);
				node_ptr->value = calculateValue(bend,tokenz[cur_ip].code);                                  
			}
			else {

				snode_ptr = Search(&bend->g_stable.root,tokenz[i_p].text);

				if(!node_ptr) {
					printError("Variable not defined.\n");           
					i_p++;
					return;
				}
				else {
					if(snode_ptr->vtype == tVAR_NONE)
					{
						printf(tokenz[i_p].text);
						printError(" Variable not defined. use var(#,$,&) first.\n");
						i_p++;
						return;
					}
					if(tokenz[cur_ip].code == ADD || tokenz[cur_ip].code == MUL || tokenz[cur_ip].code == DIV)
						Push(&bend->st, snode_ptr->value);
					else
						Push(&bend->st, -snode_ptr->value);
					
					node_ptr->value = calculateValue(bend,tokenz[cur_ip].code);

				}  
			}
		}
	}
	break;
	// print with streams ;]
	case PRINT: {
		char tmp_buf[max_string_size];
		i_p++;

		if(tokenz[i_p].code == OSTREAM) {
			int cip = i_p+1;
			printf(stream_Data(tmp_buf,tokenz,bend,&cip));
			i_p = cip;
			continue;
		}
		else {
		if(tokenz[i_p].vtype == tVAR_CSTR)
		{
			char *str_ptr = tokenz[i_p].text;

			if(str_ptr != 0) {
				printf("%s",print_FixString(str_ptr));
				i_p++;
				continue;

			}
		}
		else if(tokenz[i_p].vtype == tVAR_CINT || tokenz[i_p].vtype == tVAR_CFLOAT )
		{
			if(strlen(tokenz[i_p].num_text) != 0)
			{
				printf("%s",tokenz[i_p].num_text);
			}
			i_p++;
			continue;

		}
		else {
			node_ptr = Search(&bend->g_stable.root,tokenz[i_p].text);
			if(!node_ptr) {
				printError("Variable undefined.");
				return;           
			}
			else {

				if(node_ptr->vtype == tVAR_NONE)
				{
					printError("Variable not defined. use var(#,$,&) first?\n");
					continue;
				}

				if(node_ptr->vtype != tVAR_INT && node_ptr->vtype != tVAR_FLOAT && strlen(node_ptr->str_value) != 0)
				{
					char *str_ptr = node_ptr->str_value;
					printf(print_FixString(str_ptr));
					i_p++;
					continue;
				}
				else {
					if(node_ptr->vtype == tVAR_INT) {
						printf("%d",(int)node_ptr->value);
					}
					else {
						printf("%f",node_ptr->value); 
					}

					i_p++;
					continue;
				} 
			} 
		}
	}
	}
	break;
	// string concatinate with streams ;]
	case SCAT: {
		char tmp_buf[max_string_size];
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("variable not declared.\n");
		}

		i_p++;
		if(tokenz[i_p].code == OSTREAM) {
			stream_Data(tmp_buf,tokenz,bend,&i_p);
			strncpy(node_ptr->str_value, tmp_buf, strlen(tmp_buf));
			node_ptr->str_value[strlen(tmp_buf)] = 0;
		}
		else {
			printError("Stream operator not found!\n");
		}
	}
	break;
	case INC:
	case DEC: {
		struct symNode *ptr_node = 0;
		i_p++;
		ptr_node = Search(&bend->g_stable.root,tokenz[i_p].text);
		if(!ptr_node) {
			printError("Variable not defined.\n");
			return;
		}

		if(ptr_node->vtype == tVAR_NONE) {
			printError("You must first declare variable before use");
			return;
		}

		if(tokenz[cur_ip].code == INC)
			ptr_node->value++;
		else
			ptr_node->value--;
	}
	break;
	case MOV: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root,tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable undefined.");
			return;
		}
		else {
			i_p++;
			if(node_ptr->vtype == tVAR_NONE)
			{
				printError("Variable not defined. use var(#,$,!) first");
				continue;
			}
			else
			{
				switch(tokenz[i_p].code)
				{
				case 100:
					snode_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
					if(!snode_ptr) {
						printError("Variable not found!");
						return;
					}
					switch(snode_ptr->vtype) {
					case tVAR_INT:
					case tVAR_FLOAT:
						node_ptr->value = snode_ptr->value;
						continue;
					break;
					}
				    break;
				}

				if(tokenz[i_p].code == 99) {
					node_ptr->value = tokenz[i_p].value;
				}

	       }
		}
	}
    break;
	case JMP: {
		char tmp_buf[255];
		i_p++;
		strncpy(tmp_buf, tokenz[i_p].text, strlen(tokenz[i_p].text));
		tmp_buf[strlen(tokenz[i_p].text)] = ':';
		tmp_buf[strlen(tokenz[i_p].text)+1] = 0;
		node_ptr = Search(&bend->g_stable.root, tmp_buf);
		if(!node_ptr) {
			printError("Label undefined.\n");
		}
		else {
			i_p = node_ptr->line;
			continue;
		}
	}
	 break;
	case JNE: 
	case JE: 
	case JL:
	case JLE:
	case JG:
	case JGE:
		{
			char tmp_buf[255];
			i_p++;
			strncpy(tmp_buf, tokenz[i_p].text, strlen(tokenz[i_p].text));
			tmp_buf[strlen(tokenz[i_p].text)] = ':';
			tmp_buf[strlen(tokenz[i_p].text)+1] = 0;
			node_ptr = Search(&bend->g_stable.root, tmp_buf);
			if(!node_ptr) {
				printError("jump command command couldnt find label.");
				return;
			}
	switch(code) {
	case JNE:
		if(bend->reg[1] == 1) {
			i_p = node_ptr->line;
			continue;
		}
		break;
	case JE: 
		if(bend->reg[0] == 1) {
			i_p = node_ptr->line;
			continue;
		}
		i_p++;
		break;
	case JL:
		if(bend->reg[2] == 1) {
			i_p = node_ptr->line;
			continue;
		}
		i_p++;
		break;
	case JG:
		if(bend->reg[3] == 1) {
			i_p = node_ptr->line;
			continue;
		}
		i_p++;
		break;
	case JLE:
		if(bend->reg[4] == 1) {
			i_p = node_ptr->line;
			continue;
		}
		i_p++;
		break;
	case JGE:
		if(bend->reg[5] == 1) {
			i_p = node_ptr->line;
		}
		break;
		}
	}
		break;

	case IN: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not defined\n");
			return;
		}
		else {
			char *p;
			p = fgets(node_ptr->str_value, max_string_size, stdin);
			if(strcmp(p,"\n") == 0) {
				node_ptr->value = 0;
				node_ptr->str_value[0] = 0;
			}
			else  {
				if(strstr(p, "\n")) {
				node_ptr->str_value[strlen(node_ptr->str_value)-1] = 0;
				}
			    node_ptr->value = (float) atof(node_ptr->str_value);
			}
			
			node_ptr->value = (float) atof(node_ptr->str_value);

		i_p++;
			 }
		}
		break;
	case CMP: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not defined.\n");
			return;
		}

		if(tokenz[i_p+1].vtype == tVAR_CINT || tokenz[i_p+1].vtype == tVAR_CFLOAT) {

			CMP_compare(&tokenz[i_p+1],bend,node_ptr);
			i_p++;
			continue;
		}
		else if(tokenz[i_p+1].vtype == tVAR_CSTR) {

			char *sptr = tokenz[i_p+1].text;
			int rt = 0;
			sptr++;
			if(tokenz[i_p+1].text[strlen(tokenz[i_p+1].text)-1] == '\"') {
				tokenz[i_p+1].text[strlen(tokenz[i_p+1].text)-1] = 0;
			}
			if(strcmp(node_ptr->str_value,sptr) == 0) {
				bend->reg[0] = 1;
				bend->reg[1] = 0;
				
			}
			else {
				bend->reg[0] = 0;
				bend->reg[1] = 1;
			}
			i_p++;
			continue;
		}
		else if(node_ptr->vtype == tVAR_STR) {
			snode_ptr = Search(&bend->g_stable.root, tokenz[i_p+1].text);
			if(!snode_ptr) {
				printError("Variable not declared...\n");
			}
			CMP_strcomparenptr(node_ptr,snode_ptr,bend);
		}
		else if(node_ptr->vtype == tVAR_INT || node_ptr->vtype == tVAR_FLOAT) {
			snode_ptr = Search(&bend->g_stable.root, tokenz[i_p+1].text);
			if(!snode_ptr) {
				printError("Variable not declared....");
				return;
			}
			CMP_comparenptr(node_ptr,snode_ptr,bend);
		}
		i_p++;

		 }
		 break;
	case EXIT:
		finished = 1;
		return;
	case CALL: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		
		if(node_ptr != 0 && node_ptr->line == 0 && tokenz[i_p].callback == 0) {
			callback(tokenz[i_p].text,bend,tokenz);
			continue;

		}
		Push(&bend->ist, (float)i_p);
		i_p = node_ptr->line;
		continue;

		}
        break;
	case CB: {
		float val;
		val = Pop(&bend->ist);
		if(val == 0)
			return;
		i_p = (int) val;
	   }
	   break;
	case RET: {
		i_p = (int) Pop(&bend->ist);
	}
	break;
	case RESET:
		i_p = bend->incp;
		break;
	case NOT: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not found!\n");
			return;
		}
		node_ptr->value = (float)!node_ptr->value;
    }
    break;
	case AND:
	case OR: 
	case XOR: {
		int val1 = 0, val2 = 0, rt = 0;
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not found!!!");
			return;
		}
		i_p++;
		switch(tokenz[i_p].code) {
		case 99:
			val1 = (int) node_ptr->value;
			val2 = (int) tokenz[i_p].value;
			switch(tokenz[cur_ip].code) {
			case AND:
			rt = val1 & val2;
			break;
			case OR:
			rt = val1 | val2;
			break;
			case XOR:
			rt = val1 ^ val2;
			break;
			}
			node_ptr->value = (float) rt;
			break;
		case 100:
			snode_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
			if(!snode_ptr) {
				printError("Variable not found!\n");
			}
			val1 = (int) node_ptr->value;
			val2 = (int) snode_ptr->value;
			switch(tokenz[cur_ip].code) {
			case AND:
			rt = val1 & val2;
			break;
			case OR:
			rt = val1 | val2;
			break;
			case XOR:
			rt = val1 ^ val2;
			break;
			}
			node_ptr->value = (float) rt;
			break;
		}

	}
	break;
	case SLOOP: {
		i_p++;
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Trying to set loop variable when label not found!");
			return;
		}
		loop_ptr = node_ptr;
		loop_ptr->line = i_p;
	}
	break;
	case LOOP:
	case LOOPN0: {
		i_p++;
		if(loop_ptr == 0) {
			printError("Loop found without sloop first.\n");
			return;
		}
		switch(code) {
		case LOOP:
		if(loop_ptr->value > 1)  {
			i_p = loop_ptr->line;
			continue;
		}
		break;
	case LOOPN0:
		if(loop_ptr->value != 0) {
			if(!node_ptr) {
				printError("Error label not found.\n");
				return;
			}

			i_p = node_ptr->line;
		}
		break;
	}
	break;
	}
	case PUSH:
	case POP: {
		i_p++;
		if(tokenz[i_p].code == 99) {
			if(tokenz[cur_ip].code == PUSH) {
				Push(&bend->the_stack, tokenz[i_p].value);
			}
			else {
				printError("Trying to pop to constant");
				return;
			}
			continue;
		}
		node_ptr = Search(&bend->g_stable.root, tokenz[i_p].text);
		if(!node_ptr) {
			printError("Variable not found.!\n");
		}

		switch(node_ptr->vtype) {
		case tVAR_INT:
		case tVAR_FLOAT:
		if(tokenz[cur_ip].code == PUSH)
			Push(&bend->the_stack,node_ptr->value);
		else 
			node_ptr->value = Pop(&bend->the_stack);
		break;
		case tVAR_STR:
			printError("Trying to push string into stack!\n");
			return;	
		break;
		}
		
	}
	break;
	default:
		i_p++;
		}

	}
}
// compare two floating points and put the results in virtual flag registers
void CMP_compare(struct Token *tokens, struct BackEnd *bend, struct symNode *node_ptr) 
{
	bend->reg[0] = node_ptr->value == tokens->value;
	bend->reg[1] = node_ptr->value != tokens->value;
	bend->reg[2] = node_ptr->value < tokens->value;
	bend->reg[3] = node_ptr->value > tokens->value;
	bend->reg[4] = node_ptr->value <= tokens->value;
	bend->reg[5] = node_ptr->value >= tokens->value;
}
// compare two floating points inside of symbol table node pointers and put results in virtual flag registers
void CMP_comparenptr(struct symNode *node_ptr, struct symNode *snode_ptr, struct BackEnd *bend)
{
	bend->reg[0] = node_ptr->value == snode_ptr->value;
	bend->reg[1] = node_ptr->value != snode_ptr->value;
	bend->reg[2] = node_ptr->value < snode_ptr->value;
	bend->reg[3] = node_ptr->value > snode_ptr->value;
	bend->reg[4] = node_ptr->value <= snode_ptr->value;
	bend->reg[5] = node_ptr->value >= snode_ptr->value;
}

// compare two strings inside of symbol table node pointers put results in virtual flag reigsters
void CMP_strcomparenptr(struct symNode *node_ptr, struct symNode *snode_ptr, struct BackEnd *bend)
{
	char *sptr = node_ptr->str_value, *ssptr = snode_ptr->str_value;

	int rt = 0;
	if(node_ptr->str_value[0] == '\"')
	sptr++;
	if(snode_ptr->str_value[0] == '\"')
	ssptr++;

	if(node_ptr->str_value[strlen(node_ptr->str_value)-1] == '\"') {
		node_ptr->str_value[strlen(node_ptr->str_value)-1] = 0;
	}
	if(snode_ptr->str_value[strlen(snode_ptr->str_value)-1] == '\"') {
		snode_ptr->str_value[strlen(snode_ptr->str_value)-1] = 0;
	}

	if(strcmp(ssptr,sptr) == 0) {
		bend->reg[0] = 1;
		bend->reg[1] = 0;

	}
	else {
		bend->reg[0] = 0;
		bend->reg[1] = 1;
	}
}


// convert a file in intermediate code to a form that can be interpreted
struct convertHolder convertIcode(const char *fname, struct Token *tokens, struct BackEnd *bend)
{
	FILE *fptr = fopen(fname, "rb");
	int symtbl_count = 0, tokens_count = 0;
	int token_index = 0;
	char token_code = 0;
	int token_len = 0;
	struct symNode *pptr_node = 0;
	struct convertHolder hold;

	if(!fptr) {
		printError("File not found!");
		Abort();
	}

	fread((char*)&token_code, sizeof(char),1, fptr);
	if(token_code != 101) {
		printf("Invalid File requires masc byte code file.\n");
		hold.bend = bend;
		hold.tokens = tokens;
		hold.rt_val = 0;
		return hold;
	}
	bend->incp = 0;
	bend->ince = 0;
	initStacks(&bend->st, &bend->str_st);
	initStacks(&bend->the_stack, &bend->str_st);
	initTable(&bend->g_stable);

	fread((char*)&symtbl_count, sizeof(int), 1, fptr);
	fread((char*)&tokens_count, sizeof(int), 1, fptr);

	tokens = (struct Token*) malloc ( sizeof(struct Token) * (tokens_count+symtbl_count+2));

	do {

		fread((char*)&token_code, sizeof(char), 1, fptr); 
		if(token_code == 100) {

			char *tmp_buf;
			tokens[token_index].code = token_code;
			fread((char*)&token_len, sizeof(int), 1, fptr);
			tmp_buf = (char*) malloc ( sizeof(char) * token_len + 1);
			fread((char*)tmp_buf, sizeof(char), token_len, fptr);
			tmp_buf[token_len] = 0;
			tokens[token_index].text = tmp_buf;
			tokens[token_index].value = 0;
			if(tokens[token_index].text[0] == '\"') {
				tokens[token_index].vtype = tVAR_CSTR;
			}
			else {
				if(tokens[token_index-1].code == CALL)
				tokens[token_index].callback = 0;

				pptr_node = Search(&bend->g_stable.root, tokens[token_index].text);
				if(!pptr_node) {
					pptr_node = Enter(&bend->g_stable, &bend->g_stable.root,tokens[token_index].text);

					switch(tokens[token_index-1].code) {
					case VAR_INT:
						pptr_node->vtype = tVAR_INT;
						tokens[token_index].vtype = tVAR_INT;
						break;
					case VAR_STR:
						pptr_node->vtype = tVAR_STR;
						tokens[token_index].vtype = tVAR_STR;
						break;
					case VAR_FLOAT:
						pptr_node->vtype = tVAR_FLOAT;
						tokens[token_index].vtype = tVAR_FLOAT;
						break;
					}

					if(tokens[token_index-1].code == _PROC) {
						pptr_node->line = token_index;
						printf("procedure %s at %d\n", tokens[token_index].text, token_index);
					}
					else
						pptr_node->line = 0;
					
					if(strstr(tokens[token_index].text, ":")) {
						pptr_node->line = token_index;
						pptr_node->vtype = tVAR_LABEL;
						pptr_node->str_value[0] = 0;
						tokens[token_index].vtype = tVAR_LABEL;
					}
					else
					{
						pptr_node->str_value[0] = 0;
					}

				}

			}
			
			token_index++;
			continue;
		}
		if(token_code == 99) {
			int ctoken_len = 0;
			tokens[token_index].code = token_code;
			fread((char*)&ctoken_len, sizeof(int),1,fptr);
			tokens[token_index].text = (char*) malloc ( sizeof(char) * ctoken_len + 1 );
			fread((char*)tokens[token_index].text, sizeof(char),ctoken_len, fptr);
			tokens[token_index].text[ctoken_len] = 0;
			tokens[token_index].value = (float)atof(tokens[token_index].text);
			strncpy(tokens[token_index].num_text,tokens[token_index].text,strlen(tokens[token_index].text));
			tokens[token_index].num_text[strlen(tokens[token_index].text) < 25 ? strlen(tokens[token_index].text) : 24] = 0;
			free(tokens[token_index].text);// as a bird
			tokens[token_index].text = 0;
			tokens[token_index].vtype = tVAR_CINT;
			token_index++;
			continue;     
		}

		if(token_code >= 0 && token_code <= getReservedLen()) {
			if(token_code ==(char) BEGIN) {
				bend->incp = token_index;
			}

			if(token_code == END) {
				bend->ince = token_index;
			}

			tokens[token_index].num_text[0] = 0;
			tokens[token_index].text = 0;
			tokens[token_index].value = 0;
			tokens[token_index].vtype = vRES;
			tokens[token_index++].code = token_code;
			continue;
		}


	} while ( token_code != End );

	tokens[token_index].code = End; 
	tokens[token_index].text = 0;
	tokens[token_index].value = 0;
	fclose(fptr); 
	bend->inc_len = tokens_count+symtbl_count;

	if(!syntaxCheck(tokens,tokens_count+symtbl_count,bend))
	{
		printf("\nSource contains syntax errors, cannot continue..\n");
		Abort();
	}

	hold.bend = bend;
	hold.tokens = tokens;
	hold.rt_val = 1;
	return hold;
}
// print the string or copy it correctly without the "
char *print_FixString(char *str)
{
	char *sptr = str;
	if(str == 0)
		return 0;
	if(sptr[0] == '\"') 
		sptr++;
	if(sptr[strlen(sptr)-1] == '\"') 
		sptr[strlen(sptr)-1] = 0;

	return sptr;
}
// convert streamed data to a char *
char *stream_Data(char *str, struct Token *tokenz, struct BackEnd *bend, int *cipi)
{
	struct symNode *node_ptr = 0;
	int cip = *cipi;
	strcpy(str, "");
	do {
		switch(tokenz[cip].code) {
			case 100:
			case 99:
				if(tokenz[cip].vtype != tVAR_CINT && tokenz[cip].vtype != tVAR_CSTR && tokenz[cip].vtype != tVAR_CFLOAT) {

				node_ptr = Search(&bend->g_stable.root, tokenz[cip].text);
				if(!node_ptr) {
					printError("Variable not found.!\n");
					return "";
				}

				switch(node_ptr->vtype) {
				case tVAR_STR:
					sprintf(str,"%s%s", str, print_FixString(node_ptr->str_value));
					cip++;
					break;
				case tVAR_FLOAT:
					sprintf(str,"%s%f", str, node_ptr->value);
					cip++;
					break;
				case tVAR_INT:
					sprintf(str,"%s%d", str, (int)node_ptr->value);
					cip++;
					break;
				}

				}
				else {

					switch(tokenz[cip].vtype) {
					case tVAR_CSTR:
					sprintf(str, "%s%s", str, print_FixString(tokenz[cip].text));
					cip++;
					break;
					case tVAR_CFLOAT:
					case tVAR_CINT:
						sprintf(str,"%s%s", str, tokenz[cip].num_text);
						cip++;
					}
					break;

				}
				break;
			case OSTREAM:
				cip++;
				break;
		}

		if(tokenz[cip].code >= ADD && tokenz[cip].code < OSTREAM) {
			break;
		}

	} while (1); // life = while(1) { change(); }

	*cipi = cip;
	return str;
}

// you gonna lose that girl ;]
// come together right now over me. frEE(software);
// how do you do what you do to me 
// we can work it out
// life is very short
// take 2
// who finds the money when you pay the rent?


