/******************************************************************************
 *      "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 of Assembler/Disassembler parser
//    contains functions and structures to be used in source generated
//  by bison (yacc) when generating translated string by the
//  knitting algorithm
//  
//  author:  Zdenek Prikryl, xprikr09@stud.fit.vutbr.cz
//  created: 10.03.2005
//  last change: 27.03.2005
//
//  changelist:
// 		20.7.2006 - Zdenek Prikryl, xprikr09@.stud.fit.vutbr.cz
// 		 + rewrite to cpp
//
//////////////////////////////////////////////////////////////////////


#ifndef _KNITTINGALG_H_INCLUDED_
#define _KNITTINGALG_H_INCLUDED_

#include "asmutils.h"

#define KSTR_INIT_SIZE 2

typedef struct tagSymbolPos {
  int nLowBit;
  int nHighBit;
  void* pSymbol;
  bool bRelative;
  SINT nDisplace;
} sympos_t;

typedef struct tagSymbols {
  int nCount;
  int nAllocated;
  sympos_t* pCont;
} symbols_t;

/* type that represents string */
typedef struct tagKnittingString {
  int nAllocated; /* amount of allocated memory for this string */
  int nLength;   /* position of terminating zero  */
  char* sCont;   /* pointer to allocated string - if this pointer is NULL, other members of this structure have no meaning */
  symbols_t sSymbols;
} kstr_t;

//Class which implements functions for CKnittingAlg
class CKnittingString{
	
	public:
		CKnittingString() {}
		~CKnittingString() {}

		//Init kstr_t string
		void ks_init(kstr_t *psStr);
		void ks_symbol_alloc(symbols_t *pSymbols, int pnCount);
		//alloc memory for kstr_t
		void ks_alloc(kstr_t *psStr, int pnCount);
		//free memory of kstr_t
		void ks_free(kstr_t *psStr);
		//concatenate 2 symbols
		void ks_symbol_cat(kstr_t *psDest, const char *psSrc, void *pSymbol, const bool bRelative, const SINT nDisplacement);
		//concatenane 2 kstr_t
		void ks_cat(kstr_t *psDest, const char *psSrc);
		//move symbol psSrc to psDest
		void ks_symbol_moveto(kstr_t *psDest, kstr_t *psSrc);
		//move psSrc to psDest
		void ks_moveto(kstr_t *psDest, kstr_t *psSrc);	
		//debug function
		#ifdef NDEBUG
		void ks_print(kstr_t psStr);
		#endif
};

class CKnittingAlg : public CKnittingString, public CUtils{

	public:
		CKnittingAlg(const UINT nFirstID, const UINT nLastID);
		~CKnittingAlg();
			
		/* tests whether is anything "hung" on destination nonterm.  */
		/*   if the according string is not NULL, then it raises some error because there should't  */
		/*   be anything */
		/*  - now only for testing purposes, but maybe in the future may be used for something useful */
		bool ka_beginaction(const UINT nID);
		
		/* and symetric function */
		bool ka_finishaction(const UINT nID);

		/* takes the string "hung" on the source nonterminal and appends it to the string that  */
		/*   is hung on destination string */
		
		/* this function does as decribed above, but if is the destination pointer to string */
		/*  NULL, it sets this pointer to the value of source string pointer and then sets the source  */
		/*  pointer to NULL */
		void ka_appendnonterm(const UINT nDestID, const UINT nSrcID);
		
		/* these functions append received string to the destination string */
		/*   if the dest. str. pointer is null, it allocates a new one and */
		/*   copies received string to it */
		void ka_appendterm(const UINT nDestID, const char* sTerm);
		
		/* same as previous, but if the last parameter is true, then this */
		/*  function also frees the received string */
		void ka_appendattr(const UINT nDestID, char* sAttr, const bool bFreeAfter);
		
		void ka_appendsymbol(const UINT nDestID, char* sAttr, const bool bFreeAfter,
		        void *pSymbol, const bool bRelative, const SINT nDisplacement);
		
		/* returns pointer to string that is hung on the nonter with id nID */
		/*   do not edit contents of this string */
		char* ka_getvalue(const UINT nID);
		
		symbols_t ka_getsymbols(const UINT nID);
		
		/* deallocates string associated with selected nonterminal */
		void ka_freevalue(const UINT nID);		
		
	private:
		/* global variables definitions */
		
		kstr_t *m_pTable; 
		
		/* constats, set by  */
		UINT m_nFirstID;
		UINT m_nLastID;
	
		bool  m_bInitialized;

		/* initializes the algorithm and nonterminals-table  */
		/*   the table is indexed from nFirstID to nLastID (including both border values) */
		void ka_init(const UINT nFirstID, const UINT nLastID);
			
		/* releases all dynamically allocated resources  */
		void ka_close();
		
};

#endif /*#ifndef _KNITTINGALG_H_INCLUDED_*/
