/*                      QBCC Project

This source file is licensed under the GNU Public Licence which should be 
included with the distribution of this source.

*/
// Info Pass

#include "qbcc.h"
#include "structures.h"
#include "error.h"
#include "info.h"
#include "scanner.h"

///////////////////
// Adds a variable to the current function
int AddVariable(char *name, int type, int size, int flags, type_t *structtype)
{	
	int vtype = 0;
	var_t *tempvar;
	func_t *tempfunc;
		
	// First make sure this variable isn't already added to the variable list for the function
	
	// First check global variable list
	tempfunc = curFUNC;	
	FindFunction("__BC_GLOBAL__",TRUE);
	tempvar = curFUNC->vars;
	while(tempvar->prev != NULL)
		tempvar = tempvar->prev;
		
	while(tempvar != NULL)
	{		
		if(strcmp(tempvar->name,name) == 0)
		{
			curFUNC = tempfunc;
			return FALSE;
		}
		tempvar = tempvar->next;
	}
	
	// Now check the current function variable list
	curFUNC = tempfunc;	
	tempvar = curFUNC->vars;
	while(tempvar->prev != NULL)
		tempvar = tempvar->prev;
		
	while(tempvar != NULL)
	{		
		if(strcmp(tempvar->name,name) == 0)
			return FALSE;
		tempvar = tempvar->next;
	}

	// All Clear!!!!!

	// Go to the end of the list	
	while(curFUNC->vars->next != NULL)	
		curFUNC->vars = curFUNC->vars->next;	
	
	curFUNC->vars->next = (var_t *)malloc(sizeof(var_t));	
	if (curFUNC->vars->next == NULL)
		SysError(__LINE__,"AddVariable", "Out of memory");	
	
	curFUNC->vars->next->prev = curFUNC->vars;
	curFUNC->vars = curFUNC->vars->next;
	curFUNC->vars->next = NULL;	
	
	strcpy(curFUNC->vars->name, name);
	curFUNC->vars->type = type;
	curFUNC->vars->size = size;
	curFUNC->vars->flags = flags;
	curFUNC->vars->structtype = structtype;
	
	return TRUE;
}

///////////////////
// Adds a function to the list
int AddFunction(char *name, int ret, type_t *structtype)
{	
	func_t *tempfunc;

	// First make sure this function doesn't already exist
	tempfunc = curFUNC;
	while(tempfunc->prev != NULL)
		tempfunc = tempfunc->prev;

	while(tempfunc != NULL)
	{
		if(strcmp(tempfunc->name,name) == 0)
			return FALSE;
		tempfunc = tempfunc->next;
	}

	// Go to the end of the functions list
	while(curFUNC->next != NULL)
		curFUNC = curFUNC->next;

	curFUNC->next = (func_t *)malloc(sizeof(func_t));
	if(curFUNC->next == NULL)
		SysError(__LINE__,"AddFunction", "Out of memory");

	curFUNC->next->prev = curFUNC;
	curFUNC = curFUNC->next;
	curFUNC->next = NULL;

	strcpy(curFUNC->name,name);
	curFUNC->ret = ret;
	curFUNC->retstruct = structtype;

	// Variables
	curFUNC->vars = (var_t *)malloc(sizeof(var_t));
	if(curFUNC->vars == NULL)
		SysError(__LINE__,"AddFunction","Out of memory");
		
	strcpy(curFUNC->vars->name,"");
	curFUNC->vars->type = DefStruct->DefaultType;

	curFUNC->vars->next = NULL;
	curFUNC->vars->prev = NULL;

	// Arguments
	curFUNC->args = (var_t *)malloc(sizeof(var_t));
	if(curFUNC->args == NULL)
		SysError(__LINE__,"AddFunction","Out of memory");
	
	strcpy(curFUNC->args->name,"");
	curFUNC->args->type = DefStruct->DefaultType;
	curFUNC->args->next = NULL;
	curFUNC->args->prev = NULL;

	return TRUE;
}

///////////////////
// Adds an arg to the current function
int AddArgument(char *name, int type, int size, int flags, char *nametype,type_t *structtype)
{
	// Go to the end of the list
	while(curFUNC->args->next != NULL)	
		curFUNC->args = curFUNC->args->next;	
	
	curFUNC->args->next = (var_t *)malloc(sizeof(var_t));	
	if (curFUNC->args->next == NULL)
		SysError(__LINE__,"AddArgument", "Out of memory");	
	
	flags |= VRF_POINTER;		// Gotta be a pointer

	curFUNC->args->next->prev = curFUNC->args;
	curFUNC->args = curFUNC->args->next;
	curFUNC->args->next = NULL;	
	
	strcpy(curFUNC->args->name, name);
	strcpy(curFUNC->args->nametype,nametype);		// Awful hack #178
	curFUNC->args->type = type;
	curFUNC->args->size = size;
	curFUNC->args->flags = flags;
	curFUNC->args->structtype = structtype;
	
	return TRUE;
}

///////////////////
// Add a Type
int AddType(char *name)
{
	// Go to the end of the type list
	while(curTYPE->next != NULL)
		curTYPE = curTYPE->next;

	curTYPE->next = (type_t *)malloc(sizeof(type_t));
	if(curTYPE->next == NULL)
		SysError(__LINE__,"AddType","Out of memory");

	curTYPE->next->prev = curTYPE;
	curTYPE = curTYPE->next;
	curTYPE->next = NULL;

	strcpy(curTYPE->name,name);
	curTYPE->nummembers = 0;

	curTYPE->vars = (var_t *)malloc(sizeof(var_t));
	if(curTYPE->vars == NULL)
		SysError(__LINE__,"AddType","Out of memory");
	
	curTYPE->vars->prev = curTYPE->vars->next = NULL;
	strcpy(curTYPE->vars->name,"");

	return TRUE;
}


///////////////////
// Add a member to the current type
int AddMember(char *name, int type, int size, int flags, type_t *structtype)
{
	// Go to the end of the members list
	while(curTYPE->vars->next != NULL)
		curTYPE->vars = curTYPE->vars->next;

	curTYPE->vars->next = (var_t *)malloc(sizeof(var_t));
	if(curTYPE->vars->next == NULL)
		SysError(__LINE__,"AddMember","Out of memory");

	curTYPE->vars->next->prev = curTYPE->vars;
	curTYPE->vars = curTYPE->vars->next;
	curTYPE->vars->next = NULL;

	strcpy(curTYPE->vars->name,name);
	curTYPE->vars->type = type;
	curTYPE->vars->size = size;
	curTYPE->vars->flags = flags;
	curTYPE->vars->structtype = structtype;
	curTYPE->nummembers++;

	return TRUE;
}

///////////////////
// Find a TYPE
int FindType(char *name,int set)
{
	type_t *poldtype;
	int found = FALSE;

	poldtype = curTYPE;
	while(poldtype->prev != NULL)
		poldtype = poldtype->prev;

	while(poldtype != NULL)
	{
		if(strcmp(poldtype->name,name) == 0)
		{
			found = TRUE;
			break;
		}
		poldtype = poldtype->next;
	}
	
	if(found && set)
		curTYPE = poldtype;

	return found;
}

///////////////////
// Find a function
int FindFunction(char *name, int set)
{
	int found = FALSE;
	func_t *poldfunc = curFUNC;
		
	while(poldfunc->prev != NULL)
		poldfunc = poldfunc->prev;	

	while(poldfunc != NULL)
	{		
		if(strcmp(name,poldfunc->name) == 0)
		{
			found = TRUE;
			break;
		}		
		poldfunc = poldfunc->next;	
	}	

	if(set && found)
		curFUNC = poldfunc;	

	return found;
}

///////////////////
// Find's a variable in the current function & Global Function
int FindVariable(char *name, var_t *varstruct)
{
	var_t *poldvar = NULL;
	func_t *poldfunc = NULL;

	// First Global Function	
	poldfunc = curFUNC;	
	if(FindFunction("__BC_GLOBAL__",TRUE) == FALSE)
		SysError(__LINE__,"FindVariable","Could not find global function");
		
	poldvar = curFUNC->vars;
	while(poldvar->prev != NULL)
		poldvar = poldvar->prev;

	while(poldvar != NULL)
	{
		if(stricmp(name,poldvar->name) == 0)
		{			
			curFUNC->vars = poldvar;
			*varstruct = *curFUNC->vars;
			curFUNC = poldfunc;
			return TRUE;
		}
		poldvar = poldvar->next;
	}


	// Now function variables
	curFUNC = poldfunc;
	poldvar = curFUNC->vars;
	while(poldvar->prev != NULL)
		poldvar = poldvar->prev;

	while(poldvar != NULL)
	{
		if(stricmp(name,poldvar->name) == 0)
		{
			curFUNC->vars = poldvar;
			*varstruct = *curFUNC->vars;
			return TRUE;
		}
		poldvar = poldvar->next;
	}

	return FALSE;
}


///////////////////
// Find's a arguement in the current function
int FindArguement(char *name, var_t *varstruct)
{	
	var_t *poldvar = curFUNC->args;

	while(poldvar->prev != NULL)
		poldvar = poldvar->prev;

	while(poldvar != NULL)
	{
		if(stricmp(name,poldvar->name) == 0)		
		{
			*varstruct = *poldvar;
			return TRUE;
		}
		poldvar = poldvar->next;
	}

	return FALSE;
}

///////////////////
// Find a Member from the current type
int FindMember(char *name,var_t *varstruct)
{
	var_t *poldvar = curTYPE->vars;

	while(poldvar->prev != NULL)
		poldvar = poldvar->prev;

	while(poldvar != NULL)
	{
		if(stricmp(name,poldvar->name) == 0)		
		{
			*varstruct = *poldvar;
			return TRUE;
		}
		poldvar = poldvar->next;
	}

	return FALSE;

}

///////////////////
// Variable & Function Pass
void VarFuncPass(void)
{
	func_t *poldfunc;
	var_t *poldvar;
	char buf[81];
	char DATA[8192];

#ifdef _DEV_
	printf("- Variable/Function Pass\n");
#endif
	FindFunction("__BC_GLOBAL__",TRUE);

	strcpy(DATA,"char *__DATA__[] = {");
	while(curToken->type != TK_EOF)
	{
		GetToken();
		
		switch(curToken->type)
		{
			case TK_KEYWORD:

				// Translate the Prototype
				if(strcmp(curToken->text,"DECLARE")==0)				
				{
					TranslateDECLARE();					
					break;
				}

				// Translate the DIM statement
				if(strcmp(curToken->text,"DIM") == 0 || strcmp(curToken->text,"REDIM") == 0)
				{					
					TranslateDIM();
					break;
				}

				// Translate the function
				if(strcmp(curToken->text,"SUB") == 0 || strcmp(curToken->text,"FUNCTION") == 0)
				{
					if(LookToken->type == TK_UNKNOWN)
					{
						if(strcmp(curToken->text,"SUB") == 0)
							AddFunction(LookToken->text,VAR_VOID,NULL);
						else
							AddFunction(LookToken->text,LookToken->VarType,NULL);

					}
					GetToken();
					if(FindFunction(curToken->text,TRUE) == FALSE)
						SysError(__LINE__,"VarFuncPass","Function not found!");

					NextLine(TK_NEWLINE);
					break;
				}

				// Get rid of these
				if(strcmp(curToken->text,"END") == 0 && 
					(strcmp(LookToken->text,"SUB") == 0 ||
					strcmp(LookToken->text,"FUNCTION") == 0))
				{
					// Don't want these
					GetToken();
					break;
				}

				// Get rid of these
				if(strcmp(curToken->text,"EXIT") == 0)
				{
					GetToken();
					break;
				}

				// Const's
				if(strcmp(curToken->text,"CONST") == 0)
				{
					TranslateCONST();
					break;
				}				
				
				// DEF's
				if(strncmp(curToken->text,"DEF",3) == 0)					
				{
					TranslateDEF(curToken->text);
					NextLine(TK_NEWLINE);
					break;
				}

				// Type's
				if(strcmp(curToken->text,"TYPE") == 0)
				{
					TranslateTYPE();
					break;
				}

				// Data Statements
				if(strcmp(curToken->text,"DATA") == 0)
				{
					TranslateDATA(DATA);
					break;
				}

				// Ignore RESTORE and GOTO keywords
				if(strcmp(curToken->text,"RESTORE") == 0 || strcmp(curToken->text,"GOTO") == 0)
				{
					NextLine(TK_NEWLINE);
					break;
				}

				break;

			case TK_DOT:
				// Ignore the next member
				GetToken();
				break;

			case TK_UNKNOWN:
				AddVariable(curToken->text,curToken->VarType,0,0,NULL);
				break;

			case TK_LABEL:
				// Labels tie in with DATA statements and RESTORE statements
				strcat(DATA,"\"__LABEL__:");
				strcat(DATA,curToken->text);
				strcat(DATA,"\",");
				break;

			case TK_FUNCTION:

				// We skip these functions coz they use keywords that could be possible 
				// variables
				// In other words, we don't declare em as keywords, so people can use them
				// as variables. These use INPUT,B,BF etc
				// Get rid of these
				if(strcmp(curToken->text,"OPEN") == 0)
				{
					NextLine(TK_SOFTLINE);
					break;
				}

				// Get rid of these
				if(strcmp(curToken->text,"LINE") == 0)
				{
					NextLine(TK_SOFTLINE);
					break;
				}
				break;
		}

		// Make sure the graphics LINE function doesn't log it's line type as a variable
		// eg (B or BF)
		if(strcmp(curToken->text,"LINE") == 0 && strcmp(LookToken->text,"INPUT") != 0)
			NextLine(TK_SOFTLINE);
	}

	// Do another function pass to give the "User Defined" functions proper pointer's
	// now that the TYPE's should have been parsed
	FindFunction("__BC_GLOBAL__",TRUE);
	poldfunc = curFUNC;
	while(poldfunc != NULL)
	{
		poldvar = poldfunc->args;
		while(poldvar->prev != NULL)
			poldvar = poldvar->prev;

		while(poldvar != NULL)
		{
			if(strcmp(poldvar->name,"") != 0)
			{
				if(poldvar->type == VAR_USER_DEFINED && !poldvar->structtype)
				{
					if(!FindType(poldvar->nametype,TRUE))
					{
						sprintf(buf,"Could not find type '%s'\n",poldvar->nametype);
						SysError(__LINE__,"VarFuncPass",buf);
					}
					poldvar->structtype = curTYPE;
				}
			}
			poldvar = poldvar->next;
		}

		poldfunc = poldfunc->next;
	}

	strcat(DATA,"\"__QBCC_ENDDATA__\"};");

	// Output the DATA string
	fprintf(outfile,"\n/* Data Statement */\n%s\n\n",DATA);
}


///////////////////
// Translate the DECLARE statements
void TranslateDECLARE(void)
{	
	int FNType = VAR_VOID;			// Default
	char argname[81];
	int argtype = DefStruct->DefaultType;
	int flags = 0;
	type_t *typestruct = NULL;
	int GotArg = FALSE;
	char NameType[81];
	int Extern = FALSE;
	
	// Function Type
	GetToken();

	if(strcmp(LookToken->text,"EXTERN") == 0)
		Extern = TRUE;

	if(strcmp(curToken->text,"SUB") == 0)
	{
		if(Extern)
			GetToken();
		FNType = VAR_VOID;
	}
	if(strcmp(curToken->text,"FUNCTION") == 0)
	{
		if(Extern)
			GetToken();
		FNType = LookToken->VarType;
	}
		
	// Function Name
	GetToken();
	AddFunction(curToken->text,FNType,NULL);
	curFUNC->flags |= VRF_EXTERN;

	// Arguement List
	Match("(");
	
	while(curToken->type != TK_NEWLINE && curToken->type != TK_EOF)
	{
		GetToken();

		if(strcmp(curToken->text,"AS") == 0)
		{
			GetToken();
			argtype = TYPEtoNumber(curToken->text);
			if(argtype == VAR_USER_DEFINED)			
				if(FindType(curToken->text,TRUE))
					typestruct = curTYPE;				
				
			strcpy(NameType,curToken->text);
				// Type's may be defined later in file (should be)
			continue;
		}

		if(strcmp(curToken->text,")") == 0 && GotArg)
		{
			AddArgument(argname,argtype,0,flags,NameType,typestruct);			
			continue;
		}

		if(strcmp(curToken->text,",") == 0)			
		{
			AddArgument(argname,argtype,0,flags,NameType,typestruct);
			strcpy(argname,"");
			argtype = DefStruct->DefaultType;
			typestruct = NULL;
			GotArg = FALSE;
			flags = 0;
			continue;
		}

		if(strcmp(curToken->text,"(") == 0)
		{
			flags |= VRF_ARRAY;			
			while(strcmp(curToken->text,")") != 0)
				GetToken();
			continue;
		}

		GotArg = TRUE;
		strcpy(argname,curToken->text);
		argtype = curToken->VarType;
	}	

	FindFunction("__BC_GLOBAL__",TRUE);		// Important
}

///////////////////
// Translate the DIM statements (Add Var's Only)
void TranslateDIM(void)
{
	char name[81];
	int Type = DefStruct->DefaultType;
	int Global = FALSE;
	int flags = 0;
	type_t *typestruct = NULL;	
	char buf[81];
	int bracket = 0;
	int Extern = FALSE;
	
	while(1)
	{
		GetToken();

		if(strcmp(curToken->text,"SHARED") == 0)
		{			
			Global = TRUE;
			continue;

		}
		if(strcmp(curToken->text,"EXTERN") == 0)
		{
			Extern = TRUE;
			continue;
		}

		if(strcmp(curToken->text,"AS") == 0)
		{
			GetToken();
			Type = TYPEtoNumber(curToken->text);
			if(Type == VAR_USER_DEFINED)			
				if(FindType(curToken->text,TRUE))
					typestruct = curTYPE;
				else
				{
					typestruct = NULL;
					sprintf(buf,"Type '%s' does not exist!\n",curToken->text);
					BASError(LineNumber,buf);
				}
			continue;
		}
		if(strcmp(curToken->text,"(") == 0)
		{			
			flags |= VRF_ARRAY;
			bracket = 0;
			GetToken();
			while(curToken->type != TK_NEWLINE)
			{
				if(strcmp(curToken->text,"(") == 0)
					bracket++;
				if(strcmp(curToken->text,")") == 0)
					bracket--;
				if(bracket == -1)
					break;
				
				GetToken();
			}
			
			continue;
		}

		// Next Definition
		if(strcmp(curToken->text,",") == 0)
		{
			AddVariable(name,Type,0,flags,typestruct);
			Type = DefStruct->DefaultType;
			flags = 0;
			typestruct = NULL;

			continue;
		}

		if(curToken->type == TK_NEWLINE)
		{
			AddVariable(name,Type,0,flags,typestruct);			
			Type = DefStruct->DefaultType;
			flags = 0;
			typestruct = NULL;

			break;
		}

		if(strcmp(curToken->text,"*") == 0)
		{
			while(1)
			{
				GetToken();
				if(strcmp(LookToken->text,",") == 0 || LookToken->type == TK_NEWLINE)
					break;
			}			
			continue;
		}
		
		// Variable Name
		strcpy(name,curToken->text);
		Type = curToken->VarType;
		flags |= VRF_DIMMED;
		if(Extern)
			flags |= VRF_EXTERN;
	}
}


///////////////////
// Convert a Type to a number
int TYPEtoNumber(char *name)
{
	if(strcmp(name,"SINGLE") == 0)
		return VAR_SINGLE;
	if(strcmp(name,"DOUBLE") == 0)
		return VAR_DOUBLE;
	if(strcmp(name,"STRING") == 0)
		return VAR_STRING;
	if(strcmp(name,"INTEGER") == 0)
		return VAR_INTEGER;
	if(strcmp(name,"LONG") == 0)
		return VAR_LONG;

	return VAR_USER_DEFINED;
}

///////////////////
// Translate a TYPE structure
void TranslateTYPE(void)
{	
	char MemberName[81];
	int MemberType = DefStruct->DefaultType;
	int flags=0;
	type_t *typestruct = NULL;
	type_t *poldtype = curTYPE;
	char buf[81];
	int bracket = 0;	
	int TYPEFlags = 0;

	GetToken();			// Type Name (or EXTERN kw)

	if(strcmp(curToken->text,"EXTERN") == 0)
	{
		TYPEFlags |= VRF_EXTERN;
		GetToken();
	}
	
	AddType(curToken->text);
	curTYPE->Flags = TYPEFlags;

	GetToken();			// Newline

	while(1)
	{
		GetToken();		
		if(strcmp(curToken->text,"AS") == 0)
		{
			GetToken();
			MemberType = TYPEtoNumber(curToken->text);
			if(MemberType == VAR_USER_DEFINED)
			{
				poldtype = curTYPE;
				if(FindType(curToken->text,TRUE))
				{
					typestruct = curTYPE;
					curTYPE = poldtype;
				}
				else
				{
					sprintf(buf,"Type '%s' does not exist!\n",curToken->text);
					BASError(LineNumber,buf);
				}
			}
			continue;
		}
		
		if(strcmp(curToken->text,"*") == 0)
		{
			while(1)
			{
				GetToken();
				if(LookToken->type == TK_NEWLINE)
					break;
			}
			continue;
		}

		if(strcmp(curToken->text,"END") == 0 && strcmp(LookToken->text,"TYPE") == 0)
		{
			GetToken();
			break;
		}

		if(strcmp(curToken->text,"(") == 0)
		{
			bracket = 0;
			flags |= VRF_ARRAY;
			GetToken();
			while(curToken->type != TK_NEWLINE)
			{
				if(strcmp(curToken->text,"(") == 0)
					bracket++;
				if(strcmp(curToken->text,")") == 0)
					bracket--;
				if(bracket == -1)
					break;
				GetToken();
			}
			
			continue;
		}
		
		if(curToken->type == TK_NEWLINE)
		{
			AddMember(MemberName,MemberType,0,flags,typestruct);
			MemberType = DefStruct->DefaultType;
			flags = 0;
			typestruct = NULL;
			continue;
		}
		
		// Member name
		strcpy(MemberName,curToken->text);
		MemberType = curToken->VarType;
	}
}

///////////////////
// Translate a 'DEF' keyword for the info pass
void TranslateDEF(char *name)
{
	char type[8];
	if(strcmp(LookToken->text,"SEG") == 0 ||
		strcmp(LookToken->text,"FN") == 0)
	{
		GetToken();
		return;										// Ignore these
	}

	strcpy(type,strdup(name+3));
	if(strcmp(type,"INT") == 0)
		DefStruct->DefaultType = VAR_INTEGER;
	if(strcmp(type,"SNG") == 0)
		DefStruct->DefaultType = VAR_SINGLE;
	if(strcmp(type,"DBL") == 0)
		DefStruct->DefaultType = VAR_DOUBLE;
	if(strcmp(type,"LNG") == 0)
		DefStruct->DefaultType = VAR_LONG;
	if(strcmp(type,"STR") == 0)
		DefStruct->DefaultType = VAR_STRING;
}

///////////////////
// Translate a 'CONST' keyword for the info pass
void TranslateCONST(void)
{
	func_t *poldfunc = curFUNC;
	int VarType = DefStruct->DefaultType;
	int ExitWhile = FALSE;


	if(!FindFunction("__BC_GLOBAL__",TRUE))
		SysError(__LINE__,"TranslateCONST","Could not find the Global function");

	GetToken();
	while(!ExitWhile)
	{
		AddVariable(curToken->text,curToken->VarType,0,0,NULL);

		while(strcmp(curToken->text,",") != 0 
			&& curToken->type != TK_NEWLINE 
			&& curToken->type != TK_EOF)
				GetToken();

		if(curToken->type == TK_NEWLINE || curToken->type == TK_EOF)
			break;

		GetToken();
	}

	curFUNC = poldfunc;
}


///////////////////
// Translates a 'DATA' keyword for the info pass
void TranslateDATA(char *DATA)
{
	int IsStringConstant = FALSE;

	
	// Loop until we get to an end-of-line or end-of-file
	GetToken();
	
	// Bit of a hack to see if the first token is a comma
	if(strcmp(curToken->text,",") == 0)
	{
		strcat(DATA,"\"");
		strcat(DATA,"\"");
		strcat(DATA,",");
		GetToken();
	}

	while(curToken->type != TK_NEWLINE && 
		curToken->type != TK_SOFTLINE && 
		curToken->type != TK_EOF)
	{
		if(curToken->type == TK_STRINGCONSTANT)	
			IsStringConstant = TRUE;
		else
			IsStringConstant = FALSE;

		if(strcmp(curToken->text,",") == 0)
		{
			GetToken();
			if(curToken->type == TK_STRINGCONSTANT)	
				IsStringConstant = TRUE;
			else
				IsStringConstant = FALSE;
		}

		if(!IsStringConstant)
			strcat(DATA,"\"");
		if(strcmp(curToken->text,",") != 0)
			strcat(DATA,curToken->text);
		if(!IsStringConstant)
			strcat(DATA,"\"");

		GetToken();
		strcat(DATA,",");
	}

	
	// For neater output
	strcat(DATA,"\n                    ");
}