/******************************************************************************
 *      "Copyright (C) 2006, ApS s.r.o Brno, All Rights Reserved"             *
 ******************************************************************************
 *============================================================================*
 *   Version „number“    Header/source file for the project   "file name"     *
 *----------------------------------------------------------------------------*
 * VERSION   DATE    TIME  BY   CHANGE/COMMENTS                               *
 *----------------------------------------------------------------------------*
 *============================================================================*/
 
//  part assembler generator
//    contains interface of functions for generating output file
//  
//  author:  Adam Husar, xhusar01@stud.fit.vutbr.cz
//  created: 27.03.2005
//  last change: 27.03.2005
//
//  changelist:
// 		20.7.2006 - Zdenek Prikryl, xprikr09@.stud.fit.vutbr.cz
// 		 + rewrite to cpp
////////////////////////////////////////////////////////////////////


#ifndef _CODEGEN_H_INCLUDED_
#define _CODEGEN_H_INCLUDED_

#include "asmknittingalg.h"
#include "objectfile.h"
#include "exceptions.h"



/* initial size of buffer */
#define CG_BUFF_INIT_SIZE 1024

#define SECTION_TEXT        1
#define SECTION_DATA        2
#define SECTION_BSS         3

#define SYMBOL_PRIVATE      1
#define SYMBOL_PUBLIC       2
#define SYMBOL_EXTERN       3

#define GENERATE_LINE_INFO   true


using namespace ObjectFile;


class CCodeGen : public CKnittingAlg{
	public:

		//deftypes...
		typedef struct resmem{
			int endianess;
			int size;
			bool flat;
			
			resmem() : endianess(0), size(8), flat(true) {}
			resmem(int e, int s, bool f) : endianess(e), size(s), flat(f) {}
			
			bool operator!=(resmem rm){
				if ( endianess == rm.endianess &&
					 size == rm.size &&
					 flat == rm.flat)
					return false;
				else
					return true;
			}
		}resmem_t;

		typedef resmem_t (*TPFGETRESMEM)(int);

		typedef struct Symbol {
		    bool bLabel;
		    CSymbol *pLabel;
	    } symbol_t;
	    
		enum
		{
		    FIRST_PASS = 1,
		    LAST_PASS
		};	


		CCodeGen(const UINT nFirstID, const UINT nLastID, TPFGETRESMEM pf) : CKnittingAlg(nFirstID, nLastID) {
			Init();
			m_pGetResMem = (TPFGETRESMEM) pf;
		}

		~CCodeGen();
	

			
	private:
	
		/*-initialization an deinitialization of code generator*/
		void Init();
		void Close();
		
	public:
		const char * InputFileName();
		
		/*stop generating code and clear buffer*/
		void StopAndClear();
		
		/*start generating of code, does not need to be balled at begin -
		  CGInit also initializes generating */
		void Start();
		void StartPass(int pass);
		
		/* appends received string to binary output*/
		void PutToOutput(const char* str, const symbols_t symbols);
		
		/* creates section */
		void CreateSection(int nType, const char * pName, int nOrg);
		void SymbolDeclaration(const char * pSymbol, int nType);
		void LabelDefinition(symbol_t *pSymbol);
		
		symbol_t *LookUpSymbol(const char * pSymbol);
		symbol_t *SetAddress(int nConstNum);
		void FreeSymbol(symbol_t *symbol);
		
		bool   IsLabel(const symbol_t *symbol);
		void * GetLabel(const symbol_t *symbol);
		int    GetAddress(const symbol_t *symbol);

		/* returns pointer to buffer */
		CObjectFile * GetAbsObjFile();
		CObjectFile * GetRelObjFile();
	
	private:	    
		//private fce witch are used in public
		CObjectFile* CreateObjFile(bool bAbsolute);
		void SetSymbolLocation(CSymbolTable *table, const char *src_file);
		void SetSymbolExp();
		void LinkTables(CSymbolTable *src, CSymbolTable *dst);
		void LinkSections();
		void CheckSection();
		CSymbolTable* GetSymbolTable();
		bool ExistInSecondTable(CSymbol * pSymbol);
		bool ModifySymbol(CSymbol * pSymbol, CSymbol::eType type);
		CSymbol* FindSymbol(CObjectFile * obj, const char * sName);

		bool m_bGenerating;
		int  m_nPass;
		int  m_nSection;
		
		typedef vector<CSection *> TSections;
		
		CObjectFile * m_pAbsObjFile;
		CObjectFile * m_pRelObjFile;
		CSection    * m_pSection;
		TSections     m_vSections;
		
		//zde si dle startu sekce urcime, v jake pameti jsme
		bool m_bResMemIsSet;
		resmem_t m_tmem;
		TPFGETRESMEM m_pGetResMem;
		
		
		
};	
		

#endif /*#ifndef _CODEGEN_H_INCLUDED_*/
