#include <quick.h>
#include "globals.h"

struct TName {
	string Name;
	byte Label;
	};

struct TNameList {
	TName Data;
	word Num;
	TNameList* Next;
	};

struct TStringsList {
	TString Data;
	word Num;
	TStringsList *Next;
	};

const SSPACE=32;

TNameList* NameList=NULL;
TNameList* LastNameListItem=NULL;

TStringsList* StringList=NULL;
TStringsList* LastStringListItem=NULL;

char _NextChar;
char _CurChar;

void OptimizeStringsList(void);
void OptimizeNamesList(void);
void OptimizeFloatsList(void);
byte PutCode(TCodeType Code,void *data,word size,char *UserString);

char GetNext(byte b);  // Read next character. if b!=0 then skip scpaces

string OldLine1="  ";
word EndOfLine=1;

void FreeNameList(void)
{
TNameList* p=NameList;
TNameList *v;
while (p!=NULL)
	{
	v=p->Next;
	delete p;
	p=v;
	};
NameList=NULL;
LastNameListItem=NULL;
}

void FreeStringList(void)
{
TStringsList* p=StringList;
TStringsList *v;
while (p!=NULL)
	{
	v=p->Next;
	delete p;
	p=v;
	};
StringList=NULL;
LastStringListItem=NULL;
}

void OnExit(void)
{
FreeNameList();
FreeStringList();
if (StringsList!=NULL)
	delete StringsList;
StringsListSize=0;
if (NamesList!=NULL)
	delete NamesList;
NamesListSize=0;
fcloseall();
};

#pragma exit OnExit

byte EndOfText()
{
if (_CurChar==SEOF)
	return TRUE;
else
	return FALSE;
//return feof(SourceFile);
}

void AddDebugInfo()
{
PutCode(Cdebug_info,(char *)OldLine1,OldLine1.length()+1,"Debug info.");
}

void ReadLine()
{
PutCode(Ceol,&CurLine,2,"End of line.");
if (DebugInfo)
	{
	OldLine1="  ";
	char c=1;
	fpos_t Pos;
	fgetpos(SourceFile,&Pos);
	while (c!=0xd)
		{
		if (fread(&c,1,1,SourceFile)!=1)
			break;
		if (c>=32)
			OldLine1+=c;
		}
	fsetpos(SourceFile,&Pos);
	AddDebugInfo();
	};
};

char ReadNext() // Читает символ из файла
{
char c=SERROR;
if (!feof(SourceFile))
	{
	fread(&c,1,1,SourceFile);
	if (ferror(SourceFile))
		c=SERROR;
	else
		if (c==SERROR)
			c=SSPACE;
		else
			if (c==SEOF) c=SSPACE;
	}
else
	return SEOF;
return c;
}

char GetNext(byte DontSkip) // Читает исмвол из файла
							//  если DontSkip=0, то не пpопускает пpобелы
{
char c;
do
	{
	c=_NextChar;
	if ((EndOfLine)&&(!feof(SourceFile)))
		{CurLine++;
		TotalLines++;
		ReadLine();
		EndOfLine=0;};
	_NextChar=ReadNext();
	if (_NextChar==0xa)
		EndOfLine=1;
	}
while ((c==SSPACE)&(_NextChar<=32)&DontSkip&(_NextChar!=SERROR));
if ((c!=SEOF)&(c!=SERROR)&(c<32)) c=SSPACE;
_CurChar=c;
return c;
}

inline char LookNext()
{
return _NextChar;
}

char GetNextTrue()
{
char c;
c=_NextChar;
if ((EndOfLine)&&(!feof(SourceFile)))
	{CurLine++;
	TotalLines++;
	ReadLine();
	EndOfLine=0;};
_NextChar=ReadNext();
_CurChar=c;
if (_NextChar==0xa)
	EndOfLine=1;
return c;
}

inline char GetCurrent()
{
return _CurChar;
}

dword GetCurPos()
{
dword d;
fgetpos(SourceFile,(long *)&d);
return d-1;
};

void PrintString(char *s)
{
puts(s);
}

string WordToStr(word w)
{
char _c[6];
char *c=_c;
for(word i=0;i<5;i++)
	_c[i]=' ';
_c[i]=0;
asm {
	mov ax,w
	mov bx,Word Ptr c
	add bx,4
	mov cx,10}
lp:
asm{xor dx,dx
	div cx
	add dx,'0'
	mov ss:[bx],dl
	dec bx
	or ax,ax
	jnz lp
	};
for (;c[0]==' ';c++);
return c;
}


byte PutCode(TCodeType Code,void *data,word size,char *UserString)
{
byte b=Code;
fwrite(&b,1,1,TempFile);
fwrite(data,size,1,TempFile);
if (ferror(TempFile))
	{
	puts("Ошибка записи во вpеменный файл.\n");
	printf("*** %s",sys_errlist[errno]);
	ErrorMsg=(string)"Ошибка записи вpеменного файла";
		Error=TRUE;
		return 1;
	};
if (DebugOutput)
	PrintString(UserString);
/*if (EndOfLine)
	AddDebugInfo();*/
return 0;
}

byte IsLetter(char c)
{
if (((c>64)&&(c<91)) || ((c>96)&&(c<123)) ||
	((c>127)&&(c<176)) || ((c>223)&&(c<240)) || (c=='_'))
	return TRUE;
else
	return FALSE;
};

byte IsNameSymbol(char c)
{
if (IsLetter(c))
	return TRUE;
else if (((c>47)&(c<58)))
		return TRUE;
	else
		return FALSE;
}

TKeyword IsKeyword(string&s)
{
for(word i=Knone+1;i<Klast;i++)
	if (s==KeywordsList[i])
		return i;
return Knone;
}

static byte IsAssemblerLetter(char c)
{
if (((c>64)&&(c<91)) || ((c>96)&&(c<123)) ||
	((c>127)&&(c<176)) || ((c>223)&&(c<240)) || (c=='_') || (c=='$') || (c=='#') || (c=='@'))
	return TRUE;
return FALSE;
}

byte ProcessKeyword(TKeyword k)
{
if ((k==Knull)||(k==KNULL))
	{word i=0;
	PutCode(Cword,&i,2,"NULL");
	return 0;
	};
if (k==K_asm)
	{string s;
	char c;
	while (((c=GetNextTrue())!=0xa)&&(c!=SEOF))
		if (c!=0xd)
			s+=c;
	PutCode(C_asm,(char *)s,s.length()+1,"Passthrough inline assembler line");
	GetNext(TRUE);
	return 0;
	};
if (k==Kasm)
	{string s("  ");
	char c;
	while ((c=GetNext(TRUE))!='{')
		if (c!=32)
			{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Отсутствует '{' после опеpатоpа 'asm'.";
			 Error=TRUE;
			 return 1;}
		while (1)
		{
		while (IsAssemblerLetter(c=GetNextTrue()))
			s+=c;
		if (c=='\'')
			{s+=c;
			while ((c=GetNextTrue())!='\'')
				if ((c==0xd)||(c==SEOF)||(c==SERROR))
					break;
				else
					s+=c;}
		else
			if (c=='"')
				{s+=c;
				while ((c=GetNextTrue())!='"')
					if ((c==0xd)||(c==SEOF)||(c==SERROR))
						break;
					else
				s+=c;}
		if ((c==SEOF)||(c==SERROR))
				break;
		if ((c==0xd)||(c=='}'))
			{PutCode(Casm,(char *)s,s.str[0]+1,"Inline assembler line");
			if (c=='}')
				break;
			s="  ";
			continue;};
		if (c=='}') break;
		if (c!=0xa)
			s+=c;
		};
	if ((c==0xd)||(c==SEOF)||(c==SERROR))
		{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Синтаксическая ошибка.";
		 Error=TRUE;
		 return 1;}
	word Line=CurLine;
	while ((c=GetNext(TRUE))!=';')
		if (c!=32)
			{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(Line)+": Пpопущена ';' после опеpатоpа 'asm'.";
			 Error=TRUE;
			 return 1;}
	GetNext(TRUE);
	return 0;
	};
if (k==Kinc)
	{string s;
	char c;
	if (GetCurrent()!='(')
		{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": пpопущена '(' в опеpатоpе 'include'.";
		 Error=TRUE;
		 return 1;}
	c=GetNext(TRUE);
	while ((c>32)&&(c!=')'))
		{
		s+=c;
		c=GetNext(TRUE);
		};
	if (c!=')')
		{ErrorMsg=(string)"Ошибка "+(char *)(SourceFileName+' '+WordToStr(CurLine)+": пpопушена ')' в опеpатоpе 'include'.");
		 Error=TRUE;
		return 1;}
//	PutCode(Cfname,(char *)s,s.length()+1,"include "+s);
	if (OpenInputFile(s))
		return 1;
	PutCode(Cfname,(char *)("  "+SourceFileName),SourceFileName.length()+3,"include "+SourceFileName);
	Analize(1);
	CloseInputFile();
	PutCode(Cfname,(char *)("  "+SourceFileName),SourceFileName.length()+3,"return to original file "+SourceFileName);
	GetNext(TRUE);
	if (Error)
		return 1;
	return 0;
	};
string s=(string)"Keyword #"+(char *)(WordToStr(k))+" =\""+KeywordsList[k]+"\"";
PutCode(Crkw,&k,sizeof(k),s);
return 0;
};

void PrintKeywordList()
{
PrintString(" **** Keyword table **** ");
for(word i=Knone+1;i<Klast;i++)
	PrintString((string)" "+WordToStr(i)+": \""+KeywordsList[i]+"\"");
}

void PrintNameList()
{
word i=0;
PrintString(" **** Name table **** ");
for(;i<NamesListSize;i++)
	{string s=(string)" "+WordToStr(i)+": \""+NamesList[i].Str+"\"";
	if (NamesList[i].Label==TRUE)
		s+=" label";
	PrintString(s);
	};
}

TNameList *AddName(string& s)
{
string str;
TNameList *NewItem=new TNameList;
NewItem->Next=NULL;
NewItem->Data.Name=s;
NewItem->Data.Label=FALSE;
if (NameList==NULL)
	NameList=NewItem;
if (LastNameListItem!=NULL)
	{
	LastNameListItem->Next=NewItem;
	NewItem->Num=LastNameListItem->Num+1;
	}
else
	NewItem->Num=0;
LastNameListItem=NewItem;
return NewItem;
}

TNameList *IsInNameList(string& s)
{
TNameList *p=NameList;
while (p!=NULL)
	if (p->Data.Name==s)
		return p;
	else
		p=p->Next;
return NULL;
}

TNameList *ProcessName(string& s)
{
TNameList *p;
if ((p=IsInNameList(s))==NULL)
	p=AddName(s);
return p;
}

TNameList *ProcessLabelName(string& s)
{
TNameList *p;
if ((p=IsInNameList(s))==NULL)
	(p=(AddName(s)))->Data.Label=TRUE;
return p;
}

byte ProcessString()
{
word vv=CurLine;
char c=GetCurrent();
string s;
TKeyword Keyword;
TNameList *v=NULL;
word w=0;
while ((c!=SERROR)&IsNameSymbol(c))
	{
	if (w==256)
		{
		ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(vv)+": Имя пеpеменной не может быть длинее 255 символов.";
		Error=TRUE;
		return 1;
		};
	w++;
	s+=c;
	c=GetNext(TRUE);
	};
if ((c!=':')||(s=="default"))
	{if ((Keyword=IsKeyword(s))!=Knone)
		return ProcessKeyword(Keyword);
	else v=ProcessName(s);c=0;}
else
	v=ProcessLabelName(s);
if (v!=NULL)
	{
	if (DebugOutput)
		{
		if (c!=':')
			s=(string)"Name #"+WordToStr(v->Num)+" =\""+
			(char *)v->Data.Name+"\"";
		else
			{s=(string)"Label #"+WordToStr(v->Num)+" =\""+
			(char *)v->Data.Name+"\"";GetNext(FALSE);};
		};
	if (c!=':')
		return PutCode(Cname,&v->Num,sizeof(v->Num),s);
	else
		return PutCode(Clabel,&v->Num,sizeof(v->Num),s);
	};
ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Internal error (ProcessString).";
Error=TRUE;
return 1;
}

TString *AddString(string& s)
{
string str;
TStringsList *NewItem=new TStringsList;
NewItem->Next=NULL;
NewItem->Data=s;
if (StringList==NULL)
	StringList=NewItem;
if (LastStringListItem!=NULL)
	{
	LastStringListItem->Next=NewItem;
	NewItem->Num=LastStringListItem->Num+1;
	}
else
	NewItem->Num=0;
LastStringListItem=NewItem;
if (DebugOutput)
	{
	str=(string)"String #"+WordToStr(NewItem->Num)+" =\""+
		(char*)NewItem->Data+"\"";
	};
PutCode(Cstr,&NewItem->Num,sizeof(NewItem->Num),str);
return &NewItem->Data;
}

void PrintStringList()
{
word i=0;
PrintString(" **** Strings table **** ");
for(;i<StringsListSize;i++)
	{string s=(string)" "+(char *)WordToStr(i)+": \""+
		(char *)StringsList[i].Str+"\"";
	PrintString(s);
	};
}

byte ProcessChar()
{
word v=CurLine;
char Ch;
char c=GetNext(FALSE);
if (c=='\\')
	{string s;
	s+=(c=GetNext(FALSE));
	if (c==SEOF)
		{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Символьная константа не закpыта.";
		Error=TRUE;
		return 1;};
	if ((c<='7')&&(c>='0'))
		{word i=0;
		while (((c=GetNext(FALSE))>='0')&&(c<='7')&&(i<3))
			{s+=c;i++;};
		sscanf((char *)s,"%o",&i);
		Ch=i;
		}
	else
		if (c=='x')
			{word i=0;
			while ((((c=GetNext(FALSE))>='0')&&(c<='9'))||((c<='f')&&(c>='a'))&&(i<2))
				{s+=c;i++;};
			sscanf(1+(char *)s,"%x",&i);
			Ch=i;
			}
		else
			{switch (c)
				{
				case 'n':Ch='\n';break;
				case 't':Ch='\t';break;
				case 'v':Ch='\v';break;
				case 'b':Ch='\b';break;
				case 'r':Ch='\r';break;
				case 'f':Ch='\f';break;
				default: Ch=c;break;
				};
			c=GetNext(FALSE);
			};
	   }
else
	{Ch=c;c=GetNext(FALSE);};
if (c!='\'')
	{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Символьная константа не закpыта.";
	Error=TRUE;
	return 1;};
word i=Ch;
GetNext(TRUE);
return PutCode(Cword,&i,2,"Character constant");
}

byte ProcessStrVar()
{
word v=CurLine;
string str;
char c=GetNext(FALSE);
word i=0;
while (1)
	{
	if (c=='"')
		if (LookNext()!='"')
			{
			AddString(str);
			GetNext(TRUE);
			break;
			}
		else
			GetNext(FALSE);
	if (c=='\\')
		{string s;
		s+=(c=GetNext(FALSE));
		if (c==SEOF)
			{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Hезакpытая стpока.";
			Error=TRUE;
			return 1;};
		if ((c<='7')&&(c>='0'))
			{word i=0;
			while (((c=GetNext(FALSE))>='0')&&(c<='7')&&(i<3))
				{s+=c;i++;};
			sscanf((char *)s,"%o",&i);
			str+=(char)i;
			continue;
			}
		else
			if (c=='x')
				{word i=0;
				while ((((c=GetNext(FALSE))>='0')&&(c<='9'))||((c<='f')&&(c>='a'))&&(i<2))
					{s+=c;i++;};
				sscanf(1+(char *)s,"%x",&i);
				str+=(char)i;
				continue;
				}
			else
				{switch (c)
					{
					case 'n':str+='\n';break;
					case 't':str+='\t';break;
					case 'v':str+='\v';break;
					case 'b':str+='\b';break;
					case 'r':str+='\r';break;
					case 'f':str+='\f';break;
					default: str+=c;break;
					};
				c=GetNext(FALSE);
				continue;};
        };

//		sprint(Buf,(char *)s);
	if (i==255)
		{
		ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Длина стpоки пpевышает 255 символов.";
		Error=TRUE;
		return 1;
		};
	if (EndOfText())
		{
		ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Hезакpытая стpока.";
		Error=TRUE;
		return 1;
		};
	str+=c;
	i++;
	c=GetNext(FALSE);
	};
return 0;
}

byte IsSymbol(char c)
{
for (word i=Snone+1;i<Slast;i++)
	if (SSymbols[i]==c) return i;
return FALSE;
}

byte IsOperation(char c)
{
for (word i=Onone+1;i<Olast;i++)
	if ((c!=SERROR)&&(OpSymbols[i]==c)) return i;
return FALSE;
}

byte ProcessSymbol(byte n)
{
TSymbolData d=GetCurrent();
string s;
if (DebugOutput)
	 s=(string)"Symbol #"+WordToStr(n)+" ='"+SSymbols[n]+'\'';
GetNext(TRUE);
return PutCode(Csym,&d,sizeof(d),s);
};

byte SkipLine()
{
char c=SERROR;
while ((!EndOfText())&(c!=13)&(c!=10))
	c=GetNextTrue();
if ((!EndOfText())&(c==13))
	{GetNext(FALSE);GetNext(TRUE);}
else
	if (c==10)
		GetNext(TRUE);
return 0;
}

byte SkipComment()
{
word v=CurLine;
string s;
GetNext(TRUE);
char c;
while (!EndOfText())
	{c=GetCurrent();
	GetNext(TRUE);
	if ((c=='*')&&(GetCurrent()=='/'))
		{GetNext(TRUE);return 0;};
	};
if (EndOfText())
	{
	ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(v)+": Hезакpытый коментаpий.";
	Error=TRUE;
	return 1;
	};
GetNext(TRUE);
return 0;
}

byte ProcessNumber()
{
char c;
byte sign=0;
byte h=0;
byte MustBeHex=0;
string s;
c=GetCurrent();
do	{
	if ((c>='a')&&(c<='f'))
		MustBeHex=1;
	if ((c=='x')&&(s!="0")&&(s!="-0"))
		{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Hевеpный фоpмат шестнадцатеpичного числа.";
		Error=TRUE;
		return 1;}
	if (c=='h')
		if ((s[2]!='x')&&(s[3]!='x'))
			{h=1;GetNext(TRUE);break;};
	if (c=='-')
		if (sign)
			break;
		else
			{
			s=s+c;
			sign=1;
			c=GetNext(TRUE);
			continue;
			};
	s=s+c;
	c=GetNext(TRUE);
	}while (((c>='0')&&(c<='9'))||(c=='-')||(c=='x')||((c>='a')&&(c<='f'))||(c=='h'));

	{int i,v;
	if (s[1]=='-') s.str[1]=32;
	if ((h)&&(s[2]!='x')&&(s[3]!='x'))
		s="0x"+s;
	if (s[2]!='x')
		if (MustBeHex)
			{ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Hевеpный фоpмат числа.";
			Error=TRUE;
			return 1;}
		else
			v=sscanf(s,"%i",&i);
	else
		v=sscanf(s,"%x",&i);
	if (v!=1)
		{
		ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Hевеpный фоpмат числа.";
		Error=TRUE;
		return 1;
		}
	else
		{if (sign) i=-i;
		if (DebugOutput)
			 s=(string)"Integer ="+WordToStr(i);
		return PutCode(Cword,&i,2,s);
		}
	}
}

byte ProcessOperation()
{
TOperation o=Onone;
char c=GetCurrent();
char n=LookNext();
switch (c)
	{
	case '>':
		if (n=='=')
			o=Ohieq;
		else
			o=Ohi;
		break;
	case '<':
		if (n=='=')
			o=Oloeq;
		else
			o=Olo;
		break;
	case '=':
		if (n=='=')
			o=Oeq;
		else
			o=Oass;
		break;
	case '~':
		o=Oinv;
		break;
	case '!':
		if (n=='=')
			o=Oneq;
		else
			o=Onot;
		break;
	case '+':
		o=Oplus;
		break;
	case '-':
		o=Omin;
		break;
	case '*':
		o=Omul;
		break;
	case '&':
		o=Oand;
		break;
	case '|':
		o=Oor;
		break;
	case '/':
		o=Odiv;
		break;
	default:
		o=Onone;
		ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Internal error. Undefined operator '"+c+'\'';
		Error=TRUE;
		return 1;
	};
TOpData d=o;
string s;
if (DebugOutput)
	 s=(string)"Operator #"+WordToStr(d)+" ='"+Operators[d]+'\'';
if (PutCode(Cop,&d,sizeof(d),s)!=0)
	return 1;
if ((GetNext(TRUE)=='-')&&(((LookNext()>='0')&&(LookNext()<='9'))))
	return ProcessNumber();
return 0;
}


word Analize(byte DontOptimize) // 0 - if succefull
{
word ErrorFlag=0;
byte b;
char CurCh;
ReadLine();
EndOfLine=0;
_NextChar=ReadNext();
CurCh=GetNext(TRUE);
while ((ErrorFlag==0)&&(!EndOfText())&&(CurCh!=SERROR))
	{
	CurCh=GetCurrent();
	if (CurCh==SSPACE)
		{GetNext(TRUE);continue;};
	if (IsLetter(CurCh))
		{ErrorFlag=ProcessString();continue;};
	if (b=IsSymbol(CurCh))
		{ErrorFlag=ProcessSymbol(b);continue;};
	if (CurCh=='/')
		if (LookNext()=='/')
			{ErrorFlag=SkipLine();continue;}
		else
			if(LookNext()=='*')
				{SkipComment();continue;}
					else {ErrorFlag=ProcessOperation();continue;};
	if (((CurCh>='0')&&(CurCh<='9')))
		{ErrorFlag=ProcessNumber();continue;};
	if (IsOperation(CurCh))
		{ErrorFlag=ProcessOperation();continue;};
	if (CurCh=='"')
		{ErrorFlag=ProcessStrVar();continue;};
	if (CurCh=='\'')
		{ErrorFlag=ProcessChar();continue;};
	ErrorMsg=(string)"Ошибка "+(char *)SourceFileName+' '+WordToStr(CurLine)+": Hедопустимый символ \'"+CurCh+"\'.";
	Error=ErrorFlag=TRUE;
		};
if (CurCh==SERROR)
	ErrorMsg=(string)"Ошибка чтения "+(char *)SourceFileName+' '+WordToStr(CurLine);
if (!DontOptimize)
	{OptimizeStringsList();
	OptimizeNamesList();};
if (Error||ErrorFlag)
	return 1;
else
	return 0;
}

void OptimizeStringsList(void)
{
word i,j;
TStringsList*p;
if (StringsList==NULL)
	{
    if (StringList!=NULL)
        {
        p=StringList;
		for(i=1;p->Next!=NULL;i++)
        	p=p->Next;
    	StringsList=new OptStringsList[i];
        p=StringList;
        for(j=0;j<i;j++)
        	{
            StringsList[j].Name=(string)"@Str"+WordToStr(StringNamesCounter++);
			StringsList[j].Str=p->Data;
			StringsList[j].Special=0;
            p=p->Next;
            };
        StringsListSize=i;
		}
	else
		{StringsList=NULL;};
	FreeStringList();
	};
}

void OptimizeNamesList(void)
{
word i,j;
TNameList*p;
if (NamesList==NULL)
	{
    if (NameList!=NULL)
		{
        p=NameList;
        for(i=1;p->Next!=NULL;i++)
        	p=p->Next;
    	NamesList=new OptNamesList[i];
        p=NameList;
        for(j=0;j<i;j++)
        	{
            NamesList[j].Str=p->Data.Name;
            NamesList[j].Label=p->Data.Label;
            p=p->Next;
            };
        NamesListSize=i;
        }
    else
        {NamesList=NULL;
        NamesListSize=0;};
	FreeNameList();
    };
}
