
#include <quick.h>
#include "strings.h"
#include <stdlib.h>
#include "arrays.h"
#include <stdio.h>

// Коды спец-символов
enum TSymbol {Snone=0,  // ошибка
	Sb,		// {
	Se,		// }
	Sob,	// (
	Scb,	// )
	Scol,	// :
	Sscl,	// ;
	Sz,		// ,
	Sbl,	// [
	Sbr,	// ]
	Sptr,	// #
	Sdot,   // .
	Slast};  // Defines last symbol code
enum TOperation {  // Operations
	Onone,  // none
	Oplus,	// +
	Omin,	// -
	Omul,	// *
	Odiv,	// /
	Oand,	// &
	Oor,	// |
	Oxor,	// ^
	Onot,	// !
	Oinv,	// ~
	Oass,	// =
	Ohi,	// >
	Olo,	// <
	Oeq,	// ==
	Oneq,   // !=
	Oloeq,  // <=
	Ohieq,  // >=
	Olast   // Defines last operation code
	};	// !=

enum TCodeType {	// Codes of internal symbol types
	Cerr,	// Error
	Crkw,	// Reserved keyword
	Cop,	// Operator
	Csym,	// Symbol
	Cname,	// Name
	Cproc,	// ProcName
	Cstr,	// String
	Cword,	// Integer number
	Cfloat,	// Floating point number
	Ccb,	// Comments begins here
	Cce,	// Comments ends here
    Clabel,	// Label (Name with ':')
    Ceol,   // End of line
	Cfname,	// Change current file name
	Cdebug_info, // Debug info (line from source).
	Casm,	// Inline assembler
	C_asm,	// Passthrough inline assempler
	Clast	// Defines last code type
	};

enum TVar {	// Variables types codes
	Vnone,  // Error
	Vfunc,	// Function
	Vlabel, // Label
	Vint,	// Int
	Viptr,  // Int pointer
	Vchar,  // Byte
	Vcptr,	// Byte pointer
	Varray, // array of byte,internal type
	VRsrv1, // Reserved value 1
	VRsrv2, // Reserved value 2
	VRsrv3, // Reserved value 3
	VRsrv4, // Reserved value 4
	VRsrv5, // Reserved value 5
	VRsrv6, // Reserved value 6
	VRsrv7, // Reserved value 7
	Vlast	// Defines last variable types code
	};

enum TKeyword { //Keyword codes
	Knone,	// Error
	Kinc,   // 'include'
	Kif,	// 'if'
	Kelse,	// 'else'
	Kfor,	// 'for'
	Kcont,	// 'continue'
	Kbreak,	// 'break'
	Kwhile, // 'while'
	Kswitch,// 'switch'
	Kcase,  // 'case'
	Kdefault,//'default'
	Kstatic,// 'static'
	Kint,	// 'int'
	Kchar,	// 'char'
	Kreturn,// 'return'
	Kgoto,	// 'goto'
	Kdec,	// 'declare'
	Kext,	// 'extern'
	Kpub,	// 'public'
	K_asm,	// '_asm'
	Kasm,	// 'asm'
    Klibrary,// 'library'
    Kattach,// attach
	Knull,	// null
	KNULL,	// null
    Kconst,	// const
	Klast,	// Defines last keyword kode
};
enum TWhere {Wnone,WInStack,WInVariable,WConst,WInAX,WInBX,WInCX,WInString,WComparation};
enum TWho {WNone,WVar,WWord,WByte,WArray,WOp,WComp,WFunction};


const SERROR=0;
const SEOF=1;
extern char *KeywordsList[Klast];
extern char OpSymbols[Olast];
extern char SSymbols[Slast];
extern char *Operators[Olast];

typedef word TKeyWordData;
typedef word TNameData;
typedef word TStringData;
typedef word TSymbolData;
typedef word TOpData;

typedef string TString;


extern string ErrorMsg;
extern word  Error;
extern byte InsideSWITCH;
extern word SwitchBPState;
extern word MainFile;


struct OptStringsList {
    string Name;
	string Str;
    byte Special;
	};
struct OptNamesList {
	string Str;
    byte Label;
	};
/*struct OptFloatsList {
	string Name;
	float Value;
	};*/

extern OptStringsList *StringsList;
extern OptNamesList *NamesList;
extern word StringNamesCounter;

extern word StringsListSize;
extern word NamesListSize;

extern string SourceFileName;
extern string TempFileName;
extern string AsmFileName;
extern string SourcePath;

extern FILE* SourceFile;
extern FILE* TempFile;
extern FILE* AsmFile;
extern word DebugOutput;
extern word AddTraps;
extern word PacketMode;
extern word ShowTables;
extern word VarTabOutput;
extern word Analize(byte=0);
extern void PrintStringList();
extern void PrintNameList();
extern void PrintKeywordList();
extern string WordToStr(word w);

struct TFunction {
	byte ParamsNum; //  Кол-во паpаметpов у функции
	byte VariableParams; // = 1  если pазpешено пеpеменное кол-во паpаметpов
	TVar Params[16]; // Типы паpаметpов
	TVar Type;	// Тип возвpащяемого значения
	};

class TVariable;
class TStackItem;

class OStack {
	protected:
	TStackItem *ProcessPlus(TStackItem *p);
	TStackItem *ProcessNeg(TStackItem *p);
	TStackItem *ProcessAddr(TStackItem *p);
	TStackItem *ProcessMinus(TStackItem *p);
	TStackItem *ProcessMul(TStackItem *p);
	TStackItem *ProcessDiv(TStackItem *p);
	TStackItem *ProcessArray(TStackItem *p);
	TStackItem *ProcessPointer(TStackItem *p);
	TStackItem *ChangeItems(TStackItem *p,word NumItems);
	TStackItem *ProcessSemi(TStackItem *p,byte ResultToRegister);
	TStackItem *ProcessEq(TStackItem *p);
	TStackItem *ProcessIncDec(TStackItem *p);
	TStackItem *ProcessMulti(TStackItem *p,string &OpN);
	TStackItem *ProcessLogic(TStackItem *p);
	TStackItem *ProcessNot(TStackItem *p,byte DontCalculate=0);
	TStackItem *ProcessNotNot(TStackItem *p,byte DontCalculate);
	TStackItem *ProcessNot2(TStackItem *p);
	TStackItem *ProcessComparation(TStackItem *p,byte DontCalculate=0);
	TStackItem *ProcessFunction(TStackItem *p);
	TStackItem* ProcessTypeCast(TStackItem *p);
	void ProcessEq(byte MoveToAX=0);
	void RestoreCX(TStackItem *p);
  private:
	void CheckBX(TStackItem *p);
	void CheckAX(TStackItem *p);
	void CheckCX(TStackItem *p);
  public:
	TStackItem *First;
	TStackItem *Last;
	TStackItem *Current;
	OStack();
	~OStack();
	void InsertAfter(TStackItem *After,TStackItem* Item);
	void Insert(TStackItem *Before,TStackItem* Item);
	TStackItem* AddOperand(void);
	TStackItem* AddOperator(byte o);
	void AddStack(OStack *stk);
	void PrintStack();
	TWhere BuildCalcCode(byte MoveToAX=0,byte IFOptimized=0,byte DontOptimize=0);
	};

typedef OStack * PStack;
typedef TFILO <PStack> TParamStack;

class TStackItem
{
	public:
	TVar Type;
	TWhere Where;
	TWho Who;
	TVariable *Var;
	int Value;
	byte Op;
	word NumOps;
	TParamStack *Params;
	TStackItem *Next;
	TStackItem *Prev;
	~TStackItem() {if ((Who==WOp)&&(Op=='F')&&(Params))
			{delete Params;};
		};
	};


class TVariable {
	public:
	string Name;
	string Str;
	string Init;
	TVar type;
	word Size;
	void *EInfo;
	byte local;
	uns ext:1;
	uns pub:1;
	uns defined:1;
	uns declared:1;
	uns Static:1;
	struct TVariable *Next;
	TVariable() {EInfo=NULL;type=Vnone;};
	~TVariable() {if ((type==Vnone)&&EInfo)
		delete (TFunction *)EInfo;};
	};

//extern byte CurrentLevel;
extern TVariable *VariableList;
extern TVariable *VariableListTop;
extern word InFunction;

extern void AddLine(string& Line);


struct TLex {
	TCodeType Type;
	word Data;
	};
extern TLex CurLex;
extern word CurLine;
extern word TotalLines;

extern char _NextChar;
extern char _CurChar;


extern void AddLine(string& Line);
extern void PrintError(string Error,word Warning=0);
extern void Prolog(void);
extern void Epilog(void);

inline word End(void)
{
return feof(TempFile);
}

extern word BXUsed;
extern word CXUsed;
extern word DebugInfo;
extern word ODebugInfo;
//extern word ExtendedSyntax;
extern word SIUsed;
extern word DIUsed;
extern word OpenInputFile(string &Name);
extern void CloseInputFile(void);
extern word UsedFiles;
extern void AddLabel(word Num);
extern void AddGoto(word Num);
extern word FindLabel(word Num);
extern word FindLabelByName(string &Name);


class TBlockStack {
struct _TBlockStackItem {
	int BPOffset;
	word BPCache;
	byte Level;
	};
public:
	TFILO <_TBlockStackItem> Stack;
   _TBlockStackItem Cur;
	word CurLabelNumber;
	string FunctionName;
	TVar ResultType;
	word AutoReturn;
	TBlockStack(void);
	void StartProc(char *Name="",TVar ResultType=Vint);
	void StartBlock(void);
	void EndBlock(void);
	void GenerateEndBlock(word ToLevel);
	void CheckCache(void);
	word ReserveLabel(void)
		{return CurLabelNumber++;};
	void ReservePlace(word Size)
		{Cur.BPCache+=Size;};
	void Push(word Size)
		{Cur.BPOffset+=Size;};
	void Pop(word Size)
		{if (Cur.BPOffset<Size)
			PrintError("Internal error. (Globals.h TBlockStack::Pop) Stack is empty");
		Cur.BPOffset-=Size;};
};


extern TBlockStack Block;
extern byte ResultUsed;

struct TGotoItem{
	word Label;
	word BPOffset;
	word Line;
	};
struct TGotoLabelItem{
	word Num;
	word BPOffset;
	};


extern TGotoItem GotoList[64];
extern TGotoLabelItem GotoLabelList[64];
extern word InGotoList;
extern word InLabelList;


extern OStack *BuildEStack(char EndSym1=';',char EndSym2=0);
extern void StoreInVar(TStackItem *v,TVariable *Var);
extern void MoveToAX(TStackItem *v);
extern void MoveToBX(TStackItem *v);
extern void Move(TStackItem *To,TStackItem *From,byte IsAddress=0);
extern void AddToBX(TStackItem *Array);
extern void AddToDI(TStackItem *Array);
extern byte OperationPriority(char Op);
extern byte IsFollowedByEq(TStackItem *p,byte =1);
extern TWhere BuildExpression(OStack *st,byte SaveResult=0);
extern byte IsExpression(void);
extern void GetComparationByValue(word Value,string &OpN,byte Inverse);
extern void ProcessStatment(void);
extern void ProcessBlock(void);
extern word DecodeFilePath(string& Full,string& Path,string& Name,string& Ext);
extern string* AttachList[32];
extern void MakeAttachList(void);
extern word DATAClosed;
extern word NoTDebug;

struct TConstList {
	word Name;
	word Value;
	byte String;
};

extern TFILO <TConstList> ConstList;
extern TFILO <TConstList>::_TListItem* IsInConstList(word Name);
extern TVariable *IsInVarList(string& name,word Level);
extern void MoveToDI(TStackItem *v);




